UCMA Conference call stuck at first participant establishing - timeout

I'm trying to start a conference by using UCMA 4.0 basic conferencing sample and first user endpoint stuck at establishing the call (it's lync is not ringing). Timeout exception is triggered after a while. What's the main problem ?
BTW, platform is being started already with discovering 3 application endpoints as established.
sip:kl.dev.local#dev.local;gruu;opaque=srvr:yyapp:EHghH8UXNVqIedXU3YgJyQAAYYApp
sip:kl.cdev.local#dev.local;gruu;opaque=srvr:yyapp:EHghH8UXNVqIedXU3YgJyQAAMachine1
sip:kl.dev.local#dev.local;gruu;opaque=srvr:yyapp:EHghH8UXNVqIedXU3YgJyQAAMachine2
sip:kl.dev.local#dev.local;gruu;opaque=srvr:yyapp:EHghH8UXNVqIedXU3YgJyQAAMachine3
'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Data.SqlXml\v4.0_4.0.0.0__b77a5c561934e089\System.Data.SqlXml.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): Loaded 'System.Xml.Xsl.CompiledQuery.1'.
The thread 0x6e8 has exited with code 259 (0x103).
The thread 0x3dd4 has exited with code 259 (0x103).
The thread 0x2138 has exited with code 259 (0x103).
'LyncGame.Gateway.TestConnection.vshost.exe' (CLR v4.0.30319: LyncGame.Gateway.TestConnection.vshost.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Security\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Security.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
The thread 0x3180 has exited with code 259 (0x103).
The thread 0x350c has exited with code 259 (0x103).
The thread 0x1698 has exited with code 0 (0x0).
The thread 0x3ef4 has exited with code 0 (0x0).
The thread 0x3f00 has exited with code 259 (0x103).
The thread 0x2a24 has exited with code 259 (0x103).
The thread 0x3fc0 has exited with code 259 (0x103).
The thread 0x3750 has exited with code 259 (0x103).
The thread 0x27b8 has exited with code 259 (0x103).
The thread 0x11e0 has exited with code 259 (0x103).
The thread 0x2214 has exited with code 259 (0x103).
The thread 0x1564 has exited with code 259 (0x103).
The thread 0x3740 has exited with code 259 (0x103).
The thread 0x28a8 has exited with code 259 (0x103).
The thread 0x1da8 has exited with code 259 (0x103).
A first chance exception of type 'Microsoft.Rtc.Signaling.OperationTimeoutException' occurred in Microsoft.Rtc.Collaboration.dll
class UCMAConference
{
#region Locals
// The IM to send upon joining the MCU.
private static String _messageToSend = "Hello, World!";
private Conference _conference;
private ApplicationEndpoint _callerEndpoint, _calleeEndpoint;
//Wait handles are only present to keep things synchronous and easy to read.
private AutoResetEvent _waitForCallEstablish = new AutoResetEvent(false);
private AutoResetEvent _waitForConferenceScheduling = new AutoResetEvent(false);
private AutoResetEvent _waitForConferenceJoin = new AutoResetEvent(false);
private AutoResetEvent _waitForMessageReceived = new AutoResetEvent(false);
private AutoResetEvent _waitForMessage2Received = new AutoResetEvent(false);
private AutoResetEvent waitForUserEndpointEstablish = new AutoResetEvent(false);
private AutoResetEvent _waitForShutdown = new AutoResetEvent(false);
private AutoResetEvent _waitForConversationInviteRemoteParticipants = new AutoResetEvent(false);
private InstantMessagingFlow _IMFlow;
private InstantMessagingFlow _IMFlow2;
#endregion
public Conference StartConference()
{
try
{
foreach (var item in PlatformDataProvider.DataProvider.AppEndpoints)
{
WriteLog.AddLine(item.EndpointUri + item.OwnerDisplayName);
Console.WriteLine(item.EndpointUri + item.OwnerDisplayName);
}
// to create end point(s)
UCMACoach ucmaCoach = new UCMACoach();
UserEndpointSettings settings = new UserEndpointSettings("sip:user8#dev.local");
UserEndpoint _userEndpoint = new UserEndpoint(PlatformDataProvider.DataProvider.CollabPlatform, settings);
_userEndpoint.BeginEstablish(ar =>
{
try
{
_userEndpoint.EndEstablish(ar);
waitForUserEndpointEstablish.Set();
}
catch (Exception ex)
{
WriteLog.AddLine("Error on establish: " + ex.Message);
waitForUserEndpointEstablish.Set();
}
}, null);
waitForUserEndpointEstablish.WaitOne();
WriteLog.AddLine("User endpoint has been established ");
_userEndpoint.LocalOwnerPresence.BeginSubscribe(r =>
{
}, null);
//IAsyncResult result = _userEndpoint.LocalOwnerPresence.BeginPublishPresence(Microsoft.Rtc.Collaboration.Presence.PresenceAvailability.Busy);
// Create a user endpoint, using the network credential object
// defined above.
_callerEndpoint = PlatformDataProvider.DataProvider.AppEndpoints[1];
/* friendly name for conference leader endpoint */
// Create a second user endpoint, using the network credential object
// defined above.
_calleeEndpoint = PlatformDataProvider.DataProvider.AppEndpoints[2];
/* friendly name for conference attendee endpoint */
// Get the URI for the user logged onto Microsoft Lync
String _ocUserURI = "sip:user9#dev.local";
// One of the endpoints schedules the conference in advance. At
// schedule time, all the conference settings are set.
// The base conference settings object, used to set the policies for the conference.
ConferenceScheduleInformation conferenceScheduleInformation = new ConferenceScheduleInformation();
// An open meeting (participants can join who are not on the list),
// but requiring authentication (no anonymous users allowed.)
conferenceScheduleInformation.AccessLevel = ConferenceAccessLevel.SameEnterprise;
// The below flag determines whether or not the passcode is optional
// for users joining the conference.
conferenceScheduleInformation.IsPasscodeOptional = true;
conferenceScheduleInformation.Passcode = "1357924680";
// The verbose description of the conference
conferenceScheduleInformation.Description = "StartReady | Conference Testing";
// The below field indicates the date and time after which the conference can be deleted.
conferenceScheduleInformation.ExpiryTime = System.DateTime.Now.AddHours(5);
// These two lines assign a set of modalities (here, only
// InstantMessage) from the available MCUs to the conference. Custom
// modalities (and their corresponding MCUs) may be added at this
// time as part of the extensibility model.
ConferenceMcuInformation instantMessageMCU = new ConferenceMcuInformation(McuType.InstantMessaging);
conferenceScheduleInformation.Mcus.Add(instantMessageMCU);
// Now that the setup object is complete, schedule the conference
// using the conference services off of Endpoint. Note: the conference
// organizer is considered a leader of the conference by default.
_callerEndpoint.ConferenceServices.BeginScheduleConference(conferenceScheduleInformation,
EndScheduleConference, _callerEndpoint.ConferenceServices);
// Wait for the scheduling to complete.
_waitForConferenceScheduling.WaitOne();
// Now that the conference is scheduled, it's time to join it. As we
// already have a reference to the conference object populated from
// the EndScheduleConference call, we do not need to get the
// conference first. Initialize a conversation off of the endpoint,
// and join the conference from the uri provided above.
Conversation callerConversation = new Conversation(_callerEndpoint);
callerConversation.ConferenceSession.StateChanged += new
EventHandler<StateChangedEventArgs<ConferenceSessionState>>(ConferenceSession_StateChanged);
// Join and wait, again forcing synchronization.
callerConversation.ConferenceSession.BeginJoin(_conference.ConferenceUri, null /*joinOptions*/,
EndJoinConference, callerConversation.ConferenceSession);
_waitForConferenceJoin.WaitOne();
// Placing the calls on the conference-connected conversation
// connects to the respective MCUs. These calls may then be used to
// communicate with the conference/MCUs.
InstantMessagingCall instantMessagingCall = new InstantMessagingCall(callerConversation);
// Hooking up event handlers and then placing the call.
instantMessagingCall.InstantMessagingFlowConfigurationRequested +=
this.instantMessagingCall_InstantMessagingFlowConfigurationRequested;
instantMessagingCall.StateChanged += this._call_StateChanged;
instantMessagingCall.BeginEstablish(EndCallEstablish, instantMessagingCall);
//Synchronize to ensure that call has completed.
_waitForCallEstablish.WaitOne();
//send conf invite
ConferenceInvitationDeliverOptions deliverOptions = new ConferenceInvitationDeliverOptions();
deliverOptions.ToastMessage = new ToastMessage("Welcome to conference of StartReady Demo");
ConferenceInvitation invitation = new ConferenceInvitation(callerConversation);
invitation.BeginDeliver(_ocUserURI, deliverOptions, EndDeliverInvitation, invitation);
// Synchronize to ensure that invitation is complete
_waitForConversationInviteRemoteParticipants.WaitOne();
//And from the other endpoint's perspective:
//Initialize a conversation off of the endpoint, and join the
//conference from the uri provided above.
Conversation calleeConversation = new Conversation(_calleeEndpoint);
calleeConversation.ConferenceSession.StateChanged += new
EventHandler<StateChangedEventArgs<ConferenceSessionState>>(ConferenceSession_StateChanged);
// Join and wait, again forcing synchronization.
calleeConversation.ConferenceSession.BeginJoin(_conference.ConferenceUri, null /*joinOptions*/,
EndJoinConference, calleeConversation.ConferenceSession);
_waitForConferenceJoin.WaitOne();
// Placing the calls on the conference-connected conversation
// connects to the respective MCUs. These calls may then be used to
//communicate with the conference/MCUs.
InstantMessagingCall instantMessagingCall2 = new InstantMessagingCall(calleeConversation);
//Hooking up event handlers and then placing the call.
instantMessagingCall2.InstantMessagingFlowConfigurationRequested +=
this.instantMessagingCall2_InstantMessagingFlowConfigurationRequested;
instantMessagingCall2.StateChanged += this._call_StateChanged;
instantMessagingCall2.BeginEstablish(EndCallEstablish, instantMessagingCall2);
//Synchronize to ensure that call has completed.
_waitForCallEstablish.WaitOne();
//Synchronize to ensure that all messages are sent and received
_waitForMessageReceived.WaitOne();
//Wait for shutdown initiated by user
//_waitForShutdown.WaitOne();
//UCMASampleHelper.PauseBeforeContinuing("Press ENTER to shutdown and exit.");
return _conference;
}
catch (Exception ex)
{
WriteLog.AddLine("Cannot start conference: " + ex.Message);
return null;
}
}
#region side methods
void ConferenceSession_StateChanged(object sender, StateChangedEventArgs<ConferenceSessionState> e)
{
ConferenceSession confSession = sender as ConferenceSession;
//Session participants allow for disambiguation.
WriteLog.AddLine("The conference session with Local Participant: " +
confSession.Conversation.LocalParticipant + " has changed state. " +
"The previous conference state was: " + e.PreviousState +
" and the current state is: " + e.State);
}
// Flow created indicates that there is a flow present to begin media
// operations with, and that it is no longer null.
public void instantMessagingCall_InstantMessagingFlowConfigurationRequested
(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
WriteLog.AddLine("Caller's Flow Created.");
instantMessagingFlow = e.Flow;
_IMFlow = instantMessagingFlow;
// Now that the flow is non-null, bind the event handlers for State
// Changed and Message Received. When the flow goes active, (as
// indicated by the state changed event) the program will send the
// IM in the event handler.
instantMessagingFlow.StateChanged += this.instantMessagingFlow_StateChanged;
// Message Received is the event used to indicate that a message has
// been received from the far end.
instantMessagingFlow.MessageReceived += this.instantMessagingFlow_MessageReceived;
}
// Flow created indicates that there is a flow present to begin media
// operations with, and that it is no longer null.
public void instantMessagingCall2_InstantMessagingFlowConfigurationRequested(
object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
WriteLog.AddLine("Callee's Flow Created.");
instantMessagingFlow = e.Flow;
_IMFlow2 = instantMessagingFlow;
// Now that the flow is non-null, bind the event handlers for State
// Changed and Message Received. When the flow goes active, the
// program will send the IM in the event handler.
instantMessagingFlow.StateChanged += this.instantMessagingFlow2_StateChanged;
// Message Received is the event used to indicate that a message
// from the far end has been received.
instantMessagingFlow.MessageReceived += this.instantMessagingFlow2_MessageReceived;
}
private void instantMessagingFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
WriteLog.AddLine("Flow state changed from " + e.PreviousState + " to " + e.State);
//When flow is active, media operations (here, sending an IM) may begin.
if (e.State == MediaFlowState.Active)
{
_IMFlow = instantMessagingFlow;
WriteLog.AddLine("Please type the message to send...");
string msg = Console.ReadLine();
//Send the message on the InstantMessagingFlow.
instantMessagingFlow.BeginSendInstantMessage(msg, EndSendMessage, instantMessagingFlow);
}
}
private void instantMessagingFlow2_StateChanged(object sender, MediaFlowStateChangedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
WriteLog.AddLine("Flow state changed from " + e.PreviousState + " to " + e.State);
//When flow is active, media operations (here, sending an IM) may begin.
if (e.State == MediaFlowState.Active)
{
_IMFlow2 = instantMessagingFlow;
}
}
private void EndSendMessage(IAsyncResult ar)
{
InstantMessagingFlow instantMessagingFlow = ar.AsyncState as InstantMessagingFlow;
try
{
instantMessagingFlow.EndSendInstantMessage(ar);
WriteLog.AddLine("The message has been sent.");
}
catch (OperationTimeoutException opTimeEx)
{
// OperationFailureException: Indicates failure to connect the
// IM to the remote party due to timeout (called party failed
// to respond within the expected time).
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(opTimeEx.ToString());
}
}
private void instantMessagingFlow_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
//On an incoming Instant Message, print the contents to the console.
WriteLog.AddLine("In caller's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody);
_waitForMessageReceived.Set();
}
private void instantMessagingFlow2_MessageReceived(object sender, InstantMessageReceivedEventArgs e)
{
InstantMessagingFlow instantMessagingFlow = sender as InstantMessagingFlow;
//On an incoming Instant Message, print the contents to the console.
WriteLog.AddLine("In callee's message handler: " + e.Sender.DisplayName + " said: " + e.TextBody);
WriteLog.AddLine("Message received will be echoed");
_messageToSend = "echo: " + e.TextBody;
//Send the message on the InstantMessagingFlow.
if (_IMFlow2 != null && _IMFlow2.State == MediaFlowState.Active)
{
_IMFlow2.BeginSendInstantMessage(_messageToSend, EndSendMessage, instantMessagingFlow);
}
else
WriteLog.AddLine("Could not echo message because flow was either null or inactive");
_waitForMessage2Received.Set();
}
private void EndCallEstablish(IAsyncResult ar)
{
Call call = ar.AsyncState as Call;
try
{
call.EndEstablish(ar);
WriteLog.AddLine("The call with Local Participant: " + call.Conversation.LocalParticipant +
" and Remote Participant: " + call.RemoteEndpoint.Participant +
" is now in the established state.");
}
catch (OperationFailureException opFailEx)
{
// OperationFailureException: Indicates failure to connect the
// call to the remote party.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(opFailEx.ToString());
}
catch (RealTimeException exception)
{
// RealTimeException may be thrown on media or link-layer
//failures.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(exception.ToString());
}
finally
{
//Again, just to sync the completion of the code.
_waitForCallEstablish.Set();
}
}
private void EndDeliverInvitation(IAsyncResult ar)
{
ConferenceInvitation invitation = ar.AsyncState as ConferenceInvitation;
try
{
invitation.EndDeliver(ar);
}
catch (OperationFailureException opFailEx)
{
// OperationFailureException: Indicates failure to connect the
// call to the remote party.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(opFailEx.ToString());
}
catch (RealTimeException exception)
{
// RealTimeException may be thrown on media or link-layer failures.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(exception.ToString());
}
finally
{
//Again, just to sync the completion of the code.
_waitForConversationInviteRemoteParticipants.Set();
}
}
private void EndScheduleConference(IAsyncResult ar)
{
ConferenceServices confSession = ar.AsyncState as ConferenceServices;
try
{
//End schedule conference returns the conference object, which
// contains the vast majority of the data relevant to that
// conference.
_conference = confSession.EndScheduleConference(ar);
WriteLog.AddLine("");
WriteLog.AddLine(" The conference is now scheduled.");
WriteLog.AddLine("");
}
catch (ConferenceFailureException confFailEx)
{
// ConferenceFailureException may be thrown on failures to
// schedule due to MCUs being absent or unsupported, or due to
// malformed parameters.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(confFailEx.ToString());
}
//Again, for sync. reasons.
_waitForConferenceScheduling.Set();
}
private void EndJoinConference(IAsyncResult ar)
{
ConferenceSession confSession = ar.AsyncState as ConferenceSession;
try
{
confSession.EndJoin(ar);
}
catch (ConferenceFailureException confFailEx)
{
// ConferenceFailureException may be thrown on failures due to
// MCUs being absent or unsupported, or due to malformed parameters.
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(confFailEx.ToString());
}
catch (RealTimeException rTEx)
{
// TODO (Left to the reader): Add error handling code
WriteLog.AddLine(rTEx.ToString());
}
finally
{
//Again, for sync. reasons.
_waitForConferenceJoin.Set();
}
}
//Just to record the state transitions in the console.
void _call_StateChanged(object sender, CallStateChangedEventArgs e)
{
Call call = sender as Call;
//Call participants allow for disambiguation.
WriteLog.AddLine("The call with Local Participant: " + call.Conversation.LocalParticipant +
" has changed state. The previous call state was: " + e.PreviousState +
" and the current state is: " + e.State);
}
#endregion
}
}

The other thing that's really useful here is to run OCSLogger on the application server and see what comes back. You can run S4 to get SIP traces. Might just be something simple like you're not able to receive messages on 5061 (or whichever callback port you specified in your provisioning). If it's only failing on A/V, look at what addresses are being used in the SDP offer/answer and see if those are reachable as well. Again, OCSLogger (or the Lync CLS) and Snooper are your friends here.

Related

netmq TryReceiveMultipartMessage() works abnormal

I used the netmq (VisualStudio 2022, by Nuget install netmq) as https://www.nuget.org/packages/NetMQ/ described.
One SubscriberSocket one thread to connect and receive message from one publisher. source code like below:
public void ZMQReceiveThread(string serverIP, int port)
{
//Create SubscriberSocket
SubscriberSocket subSocket = new SubscriberSocket();
//Connect to Publisher
subSocket.Connect("tcp://" + serverIP + ":" + port.ToString());
//Subscribe all topics
subSocket.Subscribe("");
//set timeout value
int timeout = 10000 * 300; //300ms
TimeSpan ts = new TimeSpan(timeout);
while (!_isStopEnabled)
{
NetMQMessage recvMessage = null;
bool bSuccess = subSocket.TryReceiveMultipartMessage(ts, ref recvMessage, 1);
if(bSuccess == true) //Recieve data successfully
{
//Handle the recvMessage
}
else //Timeout
{
//output log message
Loger.Error($"TryReceiveMultipartMessage({ts.TotalMilliseconds} ms) timeout...");
continue;
}
}
}
sometimes the subSocket.TryReceiveMultipartMessage() timeout although the publisher sent message continuously (we used another test app written in C language linked libzmq(https://github.com/zeromq/libzmq) which can receive the continuous message).
Any comments about this topic?
thanks a lot in advance.
I looked through the netmq source code(https://github.com/zeromq/netmq) but cannot find any clues about TryReceiveMultipartMessage()

Having trouble decrypting HTTPS traffic from IOS using FiddlerCore

I was able to run the FiddlerCore demo (that comes with the package) without issue. I see both http and https traffic being logged on my PC.
My goal now is to do the same for my iOS traffic but I can't figure out what I am missing. I can see my https traffic fine when I use the desktop Fiddler app, by following the instructions at ConfigureForiOS.
I run the console FiddlerCore demo, hit 't' to trust the root certificate and then try to follow the same steps on my iPhone as I did for the Fidder app, namely setting my proxy to the Fiddler instance (my machine's IP and port 7777 as that is what it looks like the demo is using) and trusting the Fiddler cert that I had already installed on my phone when setting it up to work with the desktop Fiddler app. Then when I try to start an app on my phone that goes over https (for example a game) it just hangs. I don't see any errors being logged in the console app. It works ok when just running the desktop Fiddler app.
My SSL/cert/Fiddler knowledge is weak so I am hoping I am just missing a simple step or two.
Questions:
How can I capture iOS HTTPS traffic using the FiddlerCore demo app?
Do I need to trust the root certificate each time I start the demo
app (hitting 't')?
Thanks.
P.S. I added the demo app here, which can be found in the FiddlerCore package, for reference.
using Fiddler;
using System;
using System.Collections.Generic;
using System.Threading;
namespace FiddlerCoreDemo
{
class Program
{
static Proxy oSecureEndpoint;
static string sSecureEndpointHostname = "localhost";
static int iSecureEndpointPort = 7777;
public static void WriteCommandResponse(string s)
{
ConsoleColor oldColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(s);
Console.ForegroundColor = oldColor;
}
public static void DoQuit()
{
WriteCommandResponse("Shutting down...");
if (null != oSecureEndpoint) oSecureEndpoint.Dispose();
Fiddler.FiddlerApplication.Shutdown();
Thread.Sleep(500);
}
private static string Ellipsize(string s, int iLen)
{
if (s.Length <= iLen) return s;
return s.Substring(0, iLen - 3) + "...";
}
#if SAZ_SUPPORT
private static void ReadSessions(List<Fiddler.Session> oAllSessions)
{
Session[] oLoaded = Utilities.ReadSessionArchive(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
+ Path.DirectorySeparatorChar + "ToLoad.saz", false);
if ((oLoaded != null) && (oLoaded.Length > 0))
{
oAllSessions.AddRange(oLoaded);
WriteCommandResponse("Loaded: " + oLoaded.Length + " sessions.");
}
}
private static void SaveSessionsToDesktop(List<Fiddler.Session> oAllSessions)
{
bool bSuccess = false;
string sFilename = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
+ Path.DirectorySeparatorChar + DateTime.Now.ToString("hh-mm-ss") + ".saz";
try
{
try
{
Monitor.Enter(oAllSessions);
string sPassword = null;
Console.WriteLine("Password Protect this Archive (Y/N)?");
ConsoleKeyInfo oCKI = Console.ReadKey();
if ((oCKI.KeyChar == 'y') || (oCKI.KeyChar == 'Y'))
{
Console.WriteLine("\nEnter the password:");
sPassword = Console.ReadLine();
Console.WriteLine(String.Format("\nEncrypting with Password: '{0}'", sPassword));
}
Console.WriteLine();
bSuccess = Utilities.WriteSessionArchive(sFilename, oAllSessions.ToArray(), sPassword, false);
}
finally
{
Monitor.Exit(oAllSessions);
}
WriteCommandResponse( bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename) );
}
catch (Exception eX)
{
Console.WriteLine("Save failed: " + eX.Message);
}
}
#endif
private static void WriteSessionList(List<Fiddler.Session> oAllSessions)
{
ConsoleColor oldColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("Session list contains...");
try
{
Monitor.Enter(oAllSessions);
foreach (Session oS in oAllSessions)
{
Console.Write(String.Format("{0} {1} {2}\n{3} {4}\n\n", oS.id, oS.oRequest.headers.HTTPMethod, Ellipsize(oS.fullUrl, 60), oS.responseCode, oS.oResponse.MIMEType));
}
}
finally
{
Monitor.Exit(oAllSessions);
}
Console.WriteLine();
Console.ForegroundColor = oldColor;
}
static void Main(string[] args)
{
List<Fiddler.Session> oAllSessions = new List<Fiddler.Session>();
// <-- Personalize for your Application, 64 chars or fewer
Fiddler.FiddlerApplication.SetAppDisplayName("FiddlerCoreDemoApp");
#region AttachEventListeners
//
// It is important to understand that FiddlerCore calls event handlers on session-handling
// background threads. If you need to properly synchronize to the UI-thread (say, because
// you're adding the sessions to a list view) you must call .Invoke on a delegate on the
// window handle.
//
// If you are writing to a non-threadsafe data structure (e.g. List<t>) you must
// use a Monitor or other mechanism to ensure safety.
//
// Simply echo notifications to the console. Because Fiddler.CONFIG.QuietMode=true
// by default, we must handle notifying the user ourselves.
Fiddler.FiddlerApplication.OnNotification += delegate (object sender, NotificationEventArgs oNEA) { Console.WriteLine("** NotifyUser: " + oNEA.NotifyString); };
Fiddler.FiddlerApplication.Log.OnLogString += delegate (object sender, LogEventArgs oLEA) { Console.WriteLine("** LogString: " + oLEA.LogString); };
Fiddler.FiddlerApplication.BeforeRequest += delegate (Fiddler.Session oS)
{
// Console.WriteLine("Before request for:\t" + oS.fullUrl);
// In order to enable response tampering, buffering mode MUST
// be enabled; this allows FiddlerCore to permit modification of
// the response in the BeforeResponse handler rather than streaming
// the response to the client as the response comes in.
oS.bBufferResponse = false;
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);
// Set this property if you want FiddlerCore to automatically authenticate by
// answering Digest/Negotiate/NTLM/Kerberos challenges itself
// oS["X-AutoAuth"] = "(default)";
/* If the request is going to our secure endpoint, we'll echo back the response.
Note: This BeforeRequest is getting called for both our main proxy tunnel AND our secure endpoint,
so we have to look at which Fiddler port the client connected to (pipeClient.LocalPort) to determine whether this request
was sent to secure endpoint, or was merely sent to the main proxy tunnel (e.g. a CONNECT) in order to *reach* the secure endpoint.
As a result of this, if you run the demo and visit https://localhost:7777 in your browser, you'll see
Session list contains...
1 CONNECT http://localhost:7777
200 <-- CONNECT tunnel sent to the main proxy tunnel, port 8877
2 GET https://localhost:7777/
200 text/html <-- GET request decrypted on the main proxy tunnel, port 8877
3 GET https://localhost:7777/
200 text/html <-- GET request received by the secure endpoint, port 7777
*/
if ((oS.oRequest.pipeClient.LocalPort == iSecureEndpointPort) && (oS.hostname == sSecureEndpointHostname))
{
oS.utilCreateResponseAndBypassServer();
oS.oResponse.headers.SetStatus(200, "Ok");
oS.oResponse["Content-Type"] = "text/html; charset=UTF-8";
oS.oResponse["Cache-Control"] = "private, max-age=0";
oS.utilSetResponseBody("<html><body>Request for httpS://" + sSecureEndpointHostname + ":" + iSecureEndpointPort.ToString() + " received. Your request was:<br /><plaintext>" + oS.oRequest.headers.ToString());
}
};
/*
// The following event allows you to examine every response buffer read by Fiddler. Note that this isn't useful for the vast majority of
// applications because the raw buffer is nearly useless; it's not decompressed, it includes both headers and body bytes, etc.
//
// This event is only useful for a handful of applications which need access to a raw, unprocessed byte-stream
Fiddler.FiddlerApplication.OnReadResponseBuffer += new EventHandler<RawReadEventArgs>(FiddlerApplication_OnReadResponseBuffer);
*/
/*
Fiddler.FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oS) {
// Console.WriteLine("{0}:HTTP {1} for {2}", oS.id, oS.responseCode, oS.fullUrl);
// Uncomment the following two statements to decompress/unchunk the
// HTTP response and subsequently modify any HTTP responses to replace
// instances of the word "Microsoft" with "Bayden". You MUST also
// set bBufferResponse = true inside the beforeREQUEST method above.
//
//oS.utilDecodeResponse(); oS.utilReplaceInResponse("Microsoft", "Bayden");
};*/
Fiddler.FiddlerApplication.AfterSessionComplete += delegate (Fiddler.Session oS)
{
//Console.WriteLine("Finished session:\t" + oS.fullUrl);
Console.Title = ("Session list contains: " + oAllSessions.Count.ToString() + " sessions");
};
// Tell the system console to handle CTRL+C by calling our method that
// gracefully shuts down the FiddlerCore.
//
// Note, this doesn't handle the case where the user closes the window with the close button.
// See http://geekswithblogs.net/mrnat/archive/2004/09/23/11594.aspx for info on that...
//
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
#endregion AttachEventListeners
string sSAZInfo = "NoSAZ";
#if SAZ_SUPPORT
sSAZInfo = Assembly.GetAssembly(typeof(Ionic.Zip.ZipFile)).FullName;
// You can load Transcoders from any different assembly if you'd like, using the ImportTranscoders(string AssemblyPath)
// overload.
//
//if (!FiddlerApplication.oTranscoders.ImportTranscoders(Assembly.GetExecutingAssembly()))
//{
// Console.WriteLine("This assembly was not compiled with a SAZ-exporter");
//}
DNZSAZProvider.fnObtainPwd = () =>
{
Console.WriteLine("Enter the password (or just hit Enter to cancel):");
string sResult = Console.ReadLine();
Console.WriteLine();
return sResult;
};
FiddlerApplication.oSAZProvider = new DNZSAZProvider();
#endif
Console.WriteLine(String.Format("Starting {0} ({1})...", Fiddler.FiddlerApplication.GetVersionString(), sSAZInfo));
// For the purposes of this demo, we'll forbid connections to HTTPS
// sites that use invalid certificates. Change this from the default only
// if you know EXACTLY what that implies.
Fiddler.CONFIG.IgnoreServerCertErrors = false;
// ... but you can allow a specific (even invalid) certificate by implementing and assigning a callback...
// FiddlerApplication.OnValidateServerCertificate += new System.EventHandler<ValidateServerCertificateEventArgs>(CheckCert);
FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.abortifclientaborts", true);
// For forward-compatibility with updated FiddlerCore libraries, it is strongly recommended that you
// start with the DEFAULT options and manually disable specific unwanted options.
FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
// E.g. If you want to add a flag, start with the .Default and "OR" the new flag on:
// oFCSF = (oFCSF | FiddlerCoreStartupFlags.CaptureFTP);
// ... or if you don't want a flag in the defaults, "and not" it out:
// Uncomment the next line if you don't want FiddlerCore to act as the system proxy
// oFCSF = (oFCSF & ~FiddlerCoreStartupFlags.RegisterAsSystemProxy);
// *******************************
// Important HTTPS Decryption Info
// *******************************
// When FiddlerCoreStartupFlags.DecryptSSL is enabled, you must include either
//
// MakeCert.exe
//
// *or*
//
// CertMaker.dll
// BCMakeCert.dll
//
// ... in the folder where your executable and FiddlerCore.dll live. These files
// are needed to generate the self-signed certificates used to man-in-the-middle
// secure traffic. MakeCert.exe uses Windows APIs to generate certificates which
// are stored in the user's \Personal\ Certificates store. These certificates are
// NOT compatible with iOS devices which require specific fields in the certificate
// which are not set by MakeCert.exe.
//
// In contrast, CertMaker.dll uses the BouncyCastle C# library (BCMakeCert.dll) to
// generate new certificates from scratch. These certificates are stored in memory
// only, and are compatible with iOS devices.
// Uncomment the next line if you don't want to decrypt SSL traffic.
// oFCSF = (oFCSF & ~FiddlerCoreStartupFlags.DecryptSSL);
// NOTE: In the next line, you can pass 0 for the port (instead of 8877) to have FiddlerCore auto-select an available port
int iPort = 8877;
Fiddler.FiddlerApplication.Startup(iPort, oFCSF);
FiddlerApplication.Log.LogFormat("Created endpoint listening on port {0}", iPort);
FiddlerApplication.Log.LogFormat("Starting with settings: [{0}]", oFCSF);
FiddlerApplication.Log.LogFormat("Gateway: {0}", CONFIG.UpstreamGateway.ToString());
Console.WriteLine("Hit CTRL+C to end session.");
// We'll also create a HTTPS listener, useful for when FiddlerCore is masquerading as a HTTPS server
// instead of acting as a normal CERN-style proxy server.
oSecureEndpoint = FiddlerApplication.CreateProxyEndpoint(iSecureEndpointPort, true, sSecureEndpointHostname);
if (null != oSecureEndpoint)
{
FiddlerApplication.Log.LogFormat("Created secure endpoint listening on port {0}, using a HTTPS certificate for '{1}'", iSecureEndpointPort, sSecureEndpointHostname);
}
bool bDone = false;
do
{
Console.WriteLine("\nEnter a command [C=Clear; L=List; G=Collect Garbage; W=write SAZ; R=read SAZ;\n\tS=Toggle Forgetful Streaming; T=Trust Root Certificate; Q=Quit]:");
Console.Write(">");
ConsoleKeyInfo cki = Console.ReadKey();
Console.WriteLine();
switch (Char.ToLower(cki.KeyChar))
{
case 'c':
Monitor.Enter(oAllSessions);
oAllSessions.Clear();
Monitor.Exit(oAllSessions);
WriteCommandResponse("Clear...");
FiddlerApplication.Log.LogString("Cleared session list.");
break;
case 'd':
FiddlerApplication.Log.LogString("FiddlerApplication::Shutdown.");
FiddlerApplication.Shutdown();
break;
case 'l':
WriteSessionList(oAllSessions);
break;
case 'g':
Console.WriteLine("Working Set:\t" + Environment.WorkingSet.ToString("n0"));
Console.WriteLine("Begin GC...");
GC.Collect();
Console.WriteLine("GC Done.\nWorking Set:\t" + Environment.WorkingSet.ToString("n0"));
break;
case 'q':
bDone = true;
DoQuit();
break;
case 'r':
#if SAZ_SUPPORT
ReadSessions(oAllSessions);
#else
WriteCommandResponse("This demo was compiled without SAZ_SUPPORT defined");
#endif
break;
case 'w':
#if SAZ_SUPPORT
if (oAllSessions.Count > 0)
{
SaveSessionsToDesktop(oAllSessions);
}
else
{
WriteCommandResponse("No sessions have been captured");
}
#else
WriteCommandResponse("This demo was compiled without SAZ_SUPPORT defined");
#endif
break;
case 't':
try
{
WriteCommandResponse("Result: " + Fiddler.CertMaker.trustRootCert().ToString());
}
catch (Exception eX)
{
WriteCommandResponse("Failed: " + eX.ToString());
}
break;
// Forgetful streaming
case 's':
bool bForgetful = !FiddlerApplication.Prefs.GetBoolPref("fiddler.network.streaming.ForgetStreamedData", false);
FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.ForgetStreamedData", bForgetful);
Console.WriteLine(bForgetful ? "FiddlerCore will immediately dump streaming response data." : "FiddlerCore will keep a copy of streamed response data.");
break;
}
} while (!bDone);
}
/*
/// <summary>
/// This callback allows your code to evaluate the certificate for a site and optionally override default validation behavior for that certificate.
/// You should not implement this method unless you understand why it is a security risk.
/// </summary>
static void CheckCert(object sender, ValidateServerCertificateEventArgs e)
{
if (null != e.ServerCertificate)
{
Console.WriteLine("Certificate for " + e.ExpectedCN + " was for site " + e.ServerCertificate.Subject + " and errors were " + e.CertificatePolicyErrors.ToString());
if (e.ServerCertificate.Subject.Contains("fiddler2.com"))
{
Console.WriteLine("Got a certificate for fiddler2.com. We'll say this is also good for any other site, like https://fiddlertool.com.");
e.ValidityState = CertificateValidity.ForceValid;
}
}
}
*/
/*
// This event handler is called on every socket read for the HTTP Response. You almost certainly don't want
// to add a handler for this event, but the code below shows how you can use it to mess up your HTTP traffic.
static void FiddlerApplication_OnReadResponseBuffer(object sender, RawReadEventArgs e)
{
// NOTE: arrDataBuffer is a fixed-size array. Only bytes 0 to iCountOfBytes should be read/manipulated.
//
// Just for kicks, lowercase every byte. Note that this will obviously break any binary content.
for (int i = 0; i < e.iCountOfBytes; i++)
{
if ((e.arrDataBuffer[i] > 0x40) && (e.arrDataBuffer[i] < 0x5b))
{
e.arrDataBuffer[i] = (byte)(e.arrDataBuffer[i] + (byte)0x20);
}
}
Console.WriteLine(String.Format("Read {0} response bytes for session {1}", e.iCountOfBytes, e.sessionOwner.id));
}
*/
/// <summary>
/// When the user hits CTRL+C, this event fires. We use this to shut down and unregister our FiddlerCore.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
DoQuit();
}
}
}
You can grant the certificate full trust at:
Settings > General > About > Trust Cert

FlumeRpcClient multithreading

I'm trying to understand the correct way to use the Flume RpcClient in a multithreaded application. Information I have found so far indicates that the components are thread safe, but the example in the Flume documentation clouds the issue when it comes to error handling. This code:
public void sendDataToFlume(String data) {
// Create a Flume Event object that encapsulates the sample data
Event event = EventBuilder.withBody(data, Charset.forName("UTF-8"));
// Send the event
try {
client.append(event);
} catch (EventDeliveryException e) {
// clean up and recreate the client
client.close();
client = null;
client = RpcClientFactory.getDefaultInstance(hostname, port);
// Use the following method to create a thrift client (instead of the above line):
// this.client = RpcClientFactory.getThriftInstance(hostname, port);
}
}
If more then one thread calls this method, and the exception is thrown, then there will be a problem as multiple threads try and recreate the client in the exception handler.
Is the intent of the SDK that it should only be used by a single thread? Should this method be synchronized, as it appears to be in the log4jappender that is part of the Flume source? Should I put this code in its own worker and pass it events via a queue?
Does anyone have an example of RpcClient being used by more then one thread (included the error condition)?
Would I be better off using the "embedded agent"? Is that multithread friendly?
With the embedded agent, you get the same case except you don't know what to do:
try {
agent.put(event);
} catch (EventDeliveryException e) {
// ???
}
You could stop the agent, and restart it - but you would need a synchronized block (or a ReentrantReadWriteLock, to not block thread while "reading" the client field). But since I'm not a Flume expert, I can't tell you which one is better.
Example:
class MyClass {
private final ReentrantReadWriteLocklock;
private final Lock readLock;
private final Lock writeLock;
private RpcClient client;
private final String hostname;
private final Integer port;
// Constructor
MyClass(String hostname, Integer port) {
this.hostname = Objects.requireNonNull(hostname, "hostname");
this.port = Objects.requireNonNull(port, "port");
this.lock = new ReentrantReadWriteLock();
this.readLock = this.lock.readLock();
this.writeLock = this.lock.writeLock();
this.client = buildClient();
}
private RpcClient buildClient() {
return RpcClientFactory.getDefaultInstance(hostname, port);
}
public void sendDataToFlume(String data) {
// Create a Flume Event object that encapsulates the sample data
Event event = EventBuilder.withBody(data, Charset.forName("UTF-8"));
// Send the event
readLock.lock(); // lock for reading 'client'
try {
try {
client.append(event);
} catch (EventDeliveryException e) {
writeLock.lock(); // lock for reading/writing client
try {
// clean up and recreate the client
client.close();
client = null;
client = buildClient();
} finally {
writeLock.unlock();
}
}
} finally {
readLock.unlock();
}
}
}
Beside, the example will lose the event because it is not sent back. Some kind of loop + a max retry would probably do the trick:
int i = 0;
for (; i < maxRetry; ++i) {
try {
client.append(event);
break;
} catch (EventDeliveryException e) {
// clean up and recreate the client
client.close();
client = null;
client = RpcClientFactory.getDefaultInstance(hostname, port);
// Use the following method to create a thrift client (instead of the above line):
// this.client = RpcClientFactory.getThriftInstance(hostname, port);
}
}
if (i == maxRetry) {
logger.error("flume client is offline, loosing events {}", event);
}
That's the idea, but I don't think that should be the task of the user (eg: us), but an option in the client or the agent to store event that could not be processed due to such errors.

SMSLib example for interactive USSD session

I have a USSD application that provides an interactive session for users, for example:
User> Dial USSD Shortcode
Serv> Return Main Menu
User> Select Option 1, e.g. "View Movie Times"
Serv> Return List of Cities
User> Select Option 3, e.g. Mumbai
Serv> Return List of Cinemas
User> etc ...
I would like to test the USSD Server by using SMSLib to simulate the user.
Are there any example SMSLib code snippets that show how to perform an interactive USSD session with a USSD server?
The code at this link gives an example of sending and receiving USSD data using smslib:
// SendUSSD.java - Sample application.
//
// This application shows you the basic procedure for sending messages.
// You will find how to send synchronous and asynchronous messages.
//
// For asynchronous dispatch, the example application sets a callback
// notification, to see what's happened with messages.
package examples.modem;
import org.smslib.AGateway;
import org.smslib.AGateway.Protocols;
import org.smslib.IUSSDNotification;
import org.smslib.Library;
import org.smslib.Service;
import org.smslib.USSDResponse;
import org.smslib.modem.SerialModemGateway;
public class SendUSSD
{
public void doIt() throws Exception
{
Service srv;
USSDNotification ussdNotification = new USSDNotification();
System.out.println("Example: Send USSD Command from a serial gsm modem.");
System.out.println(Library.getLibraryDescription());
System.out.println("Version: " + Library.getLibraryVersion());
srv = new Service();
SerialModemGateway gateway = new SerialModemGateway("modem.com1", "COM4", 19200, "Huawei", "E220");
gateway.setProtocol(Protocols.PDU);
gateway.setInbound(true);
gateway.setOutbound(true);
gateway.setSimPin("0000");
srv.setUSSDNotification(ussdNotification);
srv.addGateway(gateway);
srv.startService();
System.out.println();
System.out.println("Modem Information:");
System.out.println(" Manufacturer: " + gateway.getManufacturer());
System.out.println(" Model: " + gateway.getModel());
System.out.println(" Serial No: " + gateway.getSerialNo());
System.out.println(" SIM IMSI: " + gateway.getImsi());
System.out.println(" Signal Level: " + gateway.getSignalLevel() + "%");
System.out.println(" Battery Level: " + gateway.getBatteryLevel() + "%");
System.out.println();
String resp = gateway.sendUSSDCommand("*888#"); // not working
// String resp = gateway.sendCustomATCommand("AT+CUSD=1,\"*888#\",15\r"); // working
System.out.println(resp);
System.out.println("Now Sleeping - Hit <enter> to terminate.");
System.in.read();
srv.stopService();
}
public class USSDNotification implements IUSSDNotification
{
public void process(AGateway gateway, USSDResponse response) {
System.out.println("USSD handler called from Gateway: " + gateway.getGatewayId());
System.out.println(response);
}
}
public static void main(String args[])
{
SendUSSD app = new SendUSSD();
try
{
app.doIt();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}

tfs addWorkItemSaveListener is not getting events

I am adding a TFS WorkItemSaveListener but not getting any Event on saving workitem.
public static void main(String[] args) {
// Connecting to Project
final TFSTeamProjectCollection collection = ConsoleSettings.connectToTFS();
// Creating an object of listener
WorkItemSaveListenerImpl listener = new WorkItemSaveListenerImpl();
//Adding the listener
collection.getWorkItemClient().getEventEngine().addWorkItemSaveListener(listener);
for(;;) {
// keeping the program alive
try {
Thread.sleep(10000);
}
catch (InterruptedException exception) {
// TODO Auto-generated catch block
exception.printStackTrace();
}
}
}
Only really guessing here as I don't know the java sdk. But is it possible that the addWorkItemSaveListener event is only triggered for work items changed by that particular work item client?
You may need to setup a soap subscription, or write a server plugin instead.
C# to setup a soap subscription
Sorry it's for the wrong event, but it may be enough to give you an idea.
TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(txtServerUrl.Text));
tpc.EnsureAuthenticated();
IEventService eventSrv = tpc.GetService(typeof(IEventService)) as IEventService;
DeliveryPreference delPref = new DeliveryPreference();
delPref.Address = "http://" + System.Environment.MachineName + ":8001/CheckInNotify";
delPref.Schedule = DeliverySchedule.Immediate;
delPref.Type = DeliveryType.Soap;
subscriptionId = eventSrv.SubscribeEvent(System.Environment.UserDomainName + "\\" + System.Environment.UserName, "CheckInNotify", "", delPref);

Resources