SMSLib example for interactive USSD session - ussd

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();
}
}
}

Related

Not able to get scanner device name via bluetooth on iOS device

Currently working on xamarin and trying to connect a scanner device(Zebra scanner) via bluetooth. CoreBluetooth.CBPeripheral is used to get information of device like id, name etc…
To scan device used following code :
protected override async Task StartScanningForDevicesNativeAsync(Guid[] serviceUuids, bool allowDuplicatesKey, CancellationToken scanCancellationToken)
{
// Wait for the PoweredOn state
await WaitForState(CBCentralManagerState.PoweredOn, scanCancellationToken).ConfigureAwait(false);
if (scanCancellationToken.IsCancellationRequested)
throw new TaskCanceledException("StartScanningForDevicesNativeAsync cancelled");
Trace.Message("Adapter: Starting a scan for devices.");
CBUUID[] serviceCbuuids = null;
if (serviceUuids != null && serviceUuids.Any())
{
serviceCbuuids = serviceUuids.Select(u => CBUUID.FromString(u.ToString())).ToArray();
Trace.Message("Adapter: Scanning for " + serviceCbuuids.First());
}
DiscoveredDevices.Clear();
_centralManager.ScanForPeripherals(serviceCbuuids, new PeripheralScanningOptions { AllowDuplicatesKey = allowDuplicatesKey });
}
And getting Response in Event by following code :
_centralManager.DiscoveredPeripheral += (sender, e) =>
{
Trace.Message("DiscoveredPeripheral: {0}, Id: {1}", e.Peripheral.Name, e.Peripheral.Identifier);
System.Diagnostics.Debug.WriteLine("DiscoveredPeripheral: {0}, Id: {1}", e.Peripheral.Name, e.Peripheral.Identifier);;
var name = e.Peripheral.Name;
foreach (var oData in e.AdvertisementData)
{
System.Diagnostics.Debug.WriteLine("AdvertisementData : key : " + oData.Key + " , Value : " + oData.Value);
}
if (e.AdvertisementData.ContainsKey(CBAdvertisement.DataLocalNameKey))
{
// iOS caches the peripheral name, so it can become stale (if changing)
// keep track of the local name key manually
name = ((NSString)e.AdvertisementData.ValueForKey(CBAdvertisement.DataLocalNameKey)).ToString();
}
var device = new Device(this, e.Peripheral, name, e.RSSI.Int32Value,
ParseAdvertismentData(e.AdvertisementData));
HandleDiscoveredDevice(device);
};
Now, in this AdvertisementData doesn’t contains CBAdvertisement.DataLocalNameKey so not able to get device name…?


Pushsharp 4.0.10 "Connection Error" for IOS device tokens

I developed windows service for sending push notifications to both iOS and Android apps using pushsharp library. Recently I updated the library from 2.x.x to 4.0.10 and GCM notifications are sending fine but Ios notifications are not sending, always getting "Connection Error" And I need to send notifications to thousands of tokens, So I am looping through all the tokens and queuing. Even for 10 tokens also getting same error.
Please suggest me what's wrong with my code. Here is my code snippet
public static void SendNotifications(List currentBrandNotications, long brandId)
{
byte[] appleCert = null;
string p12File = #"aps_production_brand" + brandId.ToString().Trim() + ".p12";
try
{
appleCert = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "P12\\" + p12File));
}
catch (Exception ex)
{
logger.Debug("P12 certificate is not avilable for BrandId: " + brandId);
}
try
{
logger.Debug(" Send PushNotifications To Apple :- ");
if (appleCert != null)
{
// Configuration
var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, appleCert, currentBrandNotications[0].P12Password);
// Create a new broker
var apnsBroker = new ApnsServiceBroker(config);
var fbs = new FeedbackService(config);
// Wire up events
apnsBroker.OnNotificationFailed += (Notification, aggregateEx) =>
{
//ScheduledNotification ScheduledNotification = new InstantPNScheduler.ScheduledNotification();
aggregateEx.Handle(ex =>
{
// See what kind of exception it was to further diagnose
if (ex is ApnsNotificationException)
{
var notificationException = (ApnsNotificationException)ex;
// Deal with the failed notification
var apnsNotification = notificationException.Notification;
var statusCode = notificationException.ErrorStatusCode;
logger.Debug("Apple Notification Failed: ID=" + apnsNotification.Identifier + " Code=" + statusCode);
}
else
{
// Inner exception might hold more useful information like an ApnsConnectionException
logger.Debug(ex.InnerException.ToString());
}
// Mark it as handled
return true;
});
};
apnsBroker.OnNotificationSucceeded += (Notification) =>
{
logger.Debug("Apple Notification Sent!");
};
// Start the broker
apnsBroker.Start();
foreach (ScheduledNotification notification in currentBrandNotications)
{
try
{
//logger.Debug("iOS Device token=" + notification.DeviceToken); apnsBroker.QueueNotification(new ApnsNotification
{
DeviceToken = notification.DeviceToken,
Payload = JObject.Parse("{\"aps\":{\"alert\":\"" + notification.Message + "\",\"badge\":1,\"sound\":\"sound.caf\",\"BrandId\":\"" + brandId.ToString() + "\",\"notificationType\":\"Basic\",\"DeviceType\":\"" + notification.DeviceType + "\",\"DeviceToken\":\"" + notification.DeviceToken + "\",\"NotificationId\":\"" + notification.NotificationId + "\"}}")
});
}
Thread.Sleep(800);
}
catch (Exception ex)
{
logger.Debug(" SendPushNotificationToApple :- " + ex.Message);
}
}
// Stop the broker, wait for it to finish
// This isn't done after every message, but after you're
// done with the broker
apnsBroker.Stop();
}
}
catch (Exception ex)
{
logger.Debug("Error" + ex.Message);
}
finally
{
//apnsBroker = null;
}
}
Note : If I put thread.sleep(800) in for loop, then notifications will be sent but it's getting too late in case of thousands of tokens. I need it without thread.sleep(800), even If I reduce below 800ms, getting same exception.
Please help me what's wrong with my code.
Any help would be appreciated.

Get view count using Google Youtube API

I want to get the view count of set of videos. Following is the relevant part of my code.
SearchResult singleVideo = iteratorSearchResults.next();
ResourceId rId = singleVideo.getId();
// Double checks the kind is video.
if (rId.getKind().equals("youtube#video")) {
Thumbnail thumbnail = singleVideo.getSnippet().getThumbnails().get("default");
System.out.println(" Video Id" + rId.getVideoId());
System.out.println(" Title: " + singleVideo.getSnippet().getTitle());
System.out.println(" Thumbnail: " + thumbnail.getUrl());
YouTube.Videos.List list = youtube.videos().list("statistics");
list.setId(rId.getVideoId());
list.setKey("youtube.apikey");
Video v = list.execute().getItems().get(0);
System.out.println("The view count is: "+v.getStatistics().getViewCount());
System.out.println("\n-------------------------------------------------------------\n");
}
This gives the following error in the line "YouTube.Videos.Lists list = youtube.videos().list("statistics");".
error: method list in class YouTube.Videos cannot be applied to given types;
If this is a compilation error then there might be some issue with the library version that you have included. I tried sample code from youtube API docs and it worked for me.
I have removed some extra code from the sample to show how view counts can be retrieved for a single video:
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.services.samples.youtube.cmdline.Auth;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoListResponse;
import java.io.IOException;
import java.math.BigInteger;
public class GeolocationSearch {
public static void main(String[] args) {
try {
YouTube youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest request) throws IOException {
}
}).setApplicationName("APP_ID").build();
String apiKey = "API_KEY";
YouTube.Videos.List listVideosRequest = youtube.videos().list("statistics");
listVideosRequest.setId("lf_wVfwpfp8"); // add list of video IDs here
listVideosRequest.setKey(apiKey);
VideoListResponse listResponse = listVideosRequest.execute();
Video video = listResponse.getItems().get(0);
BigInteger viewCount = video.getStatistics().getViewCount();
System.out.println(" ViewCount: " + viewCount);
System.out.println("\n-------------------------------------------------------------\n");
} catch (GoogleJsonResponseException e) {
System.err.println("There was a service error: " + e.getDetails().getCode() + " : "
+ e.getDetails().getMessage());
} catch (IOException e) {
System.err.println("There was an IO error: " + e.getCause() + " : " + e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
}
}

UCMA Conference call stuck at first participant establishing

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.

commons.net FTPSClient.storeFile doesn't throw IOException if connection with server is lost

Background:
I'm attempting to add some level fault tolerance to an application that uses Apache Commons.net FTPSClient to transfer files. If the connection between the client and server fails, I'd like to capture the produced exception/return code, log the details, and attempt to reconnect/retry the transfer.
What works:
The retrieveFile() method. If the connection fails, (i.e. I disable the server's public interface), I receive a CopyStreamException caused by a SocketTimeoutException after the amount of time I specified as the timeout.
What doesn't work:
The storeFile() method. If I initiate a transfer via storeFile() and disable the server's public interface, the storeFile() method blocks/hangs indefinitely with out throwing any exceptions.
Here is a simple app that hangs if the connection is terminated:
public class SmallTest {
private static Logger log = Logger.getLogger(SmallTest.class);
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
FTPSClient client = new FTPSClient(true);
FTPSCredentials creds = new FTPSCredentials("host", "usr", "pass",
"/keystore/ftpclient.jks", "pass",
"/keystore/rootca.jks");
String file = "/file/jdk-7u21-linux-x64.rpm";
String destinationFile = "/jdk-7u21-linux-x64.rpm";
client.setTrustManager(TrustManagerUtils.getValidateServerCertificateTrustManager());
client.setKeyManager(creds.getKeystoreManager());
client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
client.setCopyStreamListener(createListener());
client.setConnectTimeout(5000);
client.setDefaultTimeout(5000);
client.connect(creds.getHost(), 990);
client.setSoTimeout(5000);
client.setDataTimeout(5000);
if (!FTPReply.isPositiveCompletion(client.getReplyCode())) {
client.disconnect();
log.error("ERROR: " + creds.getHost() + " refused the connection");
} else {
if (client.login(creds.getUser(), creds.getPass())) {
log.debug("Logged in as " + creds.getUser());
client.enterLocalPassiveMode();
client.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
client.setFileType(FTP.BINARY_FILE_TYPE);
InputStream inputStream = new FileInputStream(file);
log.debug("Invoking storeFile()");
if (!client.storeFile(destinationFile, inputStream)) {
log.error("ERROR: Failed to store " + file
+ " on remote host. Last reply code: "
+ client.getReplyCode());
} else {
log.debug("Stored the file...");
}
inputStream.close();
client.logout();
client.disconnect();
} else {
log.error("Could not log into " + creds.getHost());
}
}
}
private static CopyStreamListener createListener(){
return new CopyStreamListener(){
private long megsTotal = 0;
#Override
public void bytesTransferred(CopyStreamEvent event) {
bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize());
}
#Override
public void bytesTransferred(long totalBytesTransferred,
int bytesTransferred, long streamSize) {
long megs = totalBytesTransferred / 1000000;
for (long l = megsTotal; l < megs; l++) {
System.out.print("#");
}
megsTotal = megs;
}
};
}
Is there any way to make the connection ACTUALLY timeout?
SW Versions:
Commons.net v3.3
Java 7
CentOS 6.3
Thanks in advance,
Joe
I ran into this same problem, and I think that I was able to get something that seems to work with the desired timeout behavior when I unplug the ethernet cable on my laptop.
I use 'storeFileStream' instead of 'storeFile', and then use 'completePendingCommand' to finish the transfer. You can check the Apache commons docs for 'completePendingCommand' to see an example of this kind of transfer. It took about 15 mins for it to timeout for me. One other thing: the aforementioned docs include calling 'isPositiveIntermediate' to check for an error, but this wasn't working. I replaced it with 'isPositivePreliminary' and now it seems to work. I'm not sure if that's actually correct, but it's the best I've found so far.

Resources