private void DisposeProperties() { Diag.DebugPrint("Entering cleanup"); if (httpClient != null) { httpClient.Dispose(); httpClient = null; } if (channel != null) { channel.Dispose(); channel = null; } Diag.DebugPrint("Exiting cleanup"); }
public void Reset() { lock (this) { if (readPacket != null) { try { readPacket.DetachStream(); readPacket = null; } catch (Exception exp) { Diag.DebugPrint("Could not detach DataReader: " + exp.Message); } } if (writePacket != null) { try { writePacket.DetachStream(); writePacket = null; } catch (Exception exp) { Diag.DebugPrint("Could not detach DataWriter: " + exp.Message); } } if (socket != null) { socket.Dispose(); socket = null; } if (channel != null) { if (((IDictionary<string, object>)CoreApplication.Properties).ContainsKey(channel.ControlChannelTriggerId)) { CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); } // Call the Dispose() method on the controlchanneltrigger object to release any // OS maintained resources for this channel object. channel.Dispose(); channel = null; } Diag.DebugPrint("CommModule has been reset."); } }
public AppContext(CommModule commInstance, StreamWebSocket webSocket, ControlChannelTrigger channel, string id) { WebSocketHandle = webSocket; Channel = channel; ChannelId = id; CommInstance = commInstance; messageQueue = new ConcurrentQueue<string>(); }
public bool SetupTransport(string serviceUri) { bool result = false; lock (this) { // Save these to help reconnect later. serverUri = serviceUri; // Set up the ControlChannelTrigger with the stream socket. result = RegisterWithControlChannelTrigger(serverUri); if (result == false) { Diag.DebugPrint("Failed to sign on and connect"); if (socket != null) { socket.Dispose(); socket = null; readPacket = null; } if (channel != null) { channel.Dispose(); channel = null; } } } return result; }
async Task<bool> RegisterWithCCTHelper(string serverUri) { bool result = false; socket = new StreamWebSocket(); // Specify the keepalive interval expected by the server for this app // in order of minutes. const int serverKeepAliveInterval = 30; // Specify the channelId string to differentiate this // channel instance from any other channel instance. // When background task fires, the channel object is provided // as context and the channel id can be used to adapt the behavior // of the app as required. const string channelId = "channelOne"; // IMPORTANT: Note that this is a websocket sample, therefore the // keepalive task class is provided by Windows for websockets. // For websockets, the system does the keepalive on behalf of the // app but the app still needs to specify this well known keepalive task. // This should be done here in the background registration as well // as in the package manifest. const string WebSocketKeepAliveTask = "Windows.Networking.Sockets.WebSocketKeepAlive"; // Try creating the controlchanneltrigger if this has not been already // created and stored in the property bag. Diag.DebugPrint("RegisterWithCCTHelper Starting..."); ControlChannelTriggerStatus status; Diag.DebugPrint("Create ControlChannelTrigger ..."); // Create the ControlChannelTrigger object and request a hardware slot for this app. // If the app is not on LockScreen, then the ControlChannelTrigger constructor will // fail right away. try { channel = new ControlChannelTrigger(channelId, serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot); } catch (UnauthorizedAccessException exp) { Diag.DebugPrint("Please add the app to the lock screen." + exp.Message); return result; } Uri serverUriInstance; try { serverUriInstance = new Uri(serverUri); } catch (Exception exp) { Diag.DebugPrint("Error creating URI: " + exp.Message); return result; } // Register the apps background task with the trigger for keepalive. var keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = "KeepaliveTaskForChannelOne"; keepAliveBuilder.TaskEntryPoint = WebSocketKeepAliveTask; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); keepAliveBuilder.Register(); // Register the apps background task with the trigger for push notification task. var pushNotifyBuilder = new BackgroundTaskBuilder(); pushNotifyBuilder.Name = "PushNotificationTaskForChannelOne"; pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskHelper.PushNotifyTask"; pushNotifyBuilder.SetTrigger(channel.PushNotificationTrigger); pushNotifyBuilder.Register(); // Tie the transport method to the ControlChannelTrigger object to push enable it. // Note that if the transport's TCP connection is broken at a later point of time, // the ControlChannelTrigger object can be reused to plug in a new transport by // calling UsingTransport API again. Diag.DebugPrint("Calling UsingTransport() ..."); try { channel.UsingTransport(socket); // Connect the socket // // If connect fails or times out it will throw exception. await socket.ConnectAsync(serverUriInstance); Diag.DebugPrint("Connected"); // Call WaitForPushEnabled API to make sure the TCP connection has // been established, which will mean that the OS will have allocated // any hardware slot for this TCP connection. // // In this sample, the ControlChannelTrigger object was created by // explicitly requesting a hardware slot. // // On Non-AOAC systems, if app requests hardware slot as above, // the system will fallback to a software slot automatically. // // On AOAC systems, if no hardware slot is available, then app // can request a software slot [by re-creating the ControlChannelTrigger object]. status = channel.WaitForPushEnabled(); Diag.DebugPrint("WaitForPushEnabled() completed with status: " + status); if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated) { throw new Exception(string.Format("Neither hardware nor software slot could be allocated. ChannelStatus is {0}", status.ToString())); } // Store the objects created in the property bag for later use. // NOTE: make sure these objects are free threaded. STA/Both objects can // cause deadlocks when foreground threads are suspended. CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); var appContext = new AppContext(this, socket, channel, channel.ControlChannelTriggerId); ((IDictionary<string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); result = true; Diag.DebugPrint("RegisterWithCCTHelper Completed."); // Almost done. Post a read since we are using streamwebsocket // to allow push notifications to be received. PostSocketRead(MAX_BUFFER_LENGTH); } catch (Exception exp) { Diag.DebugPrint("RegisterWithCCTHelper Task failed with: " + exp.Message); // Exceptions may be thrown for example if the application has not // registered the background task class id for using real time communications // broker in the package appx manifest. } return result; }
private bool RegisterControlChannel() { if (!UnregisterControlChannel()) return false; if (IsInternetAvailable) { _XMPP.Socket = new StreamSocket(); try { // Create controlchannel var slotType = _currentParameters.RequestConnectedStandby ? ControlChannelTriggerResourceType.RequestHardwareSlot : ControlChannelTriggerResourceType.RequestSoftwareSlot; _controlChannel = new ControlChannelTrigger("CT" + Id, 15, slotType); _controlChannel.UsingTransport(_XMPP.Socket); // Register package received event BackgroundTaskBuilder pushNotificationTrigger = new BackgroundTaskBuilder(); pushNotificationTrigger.Name = "PN" + Id; pushNotificationTrigger.TaskEntryPoint = "BackgroundTasks.PushNotificationTrigger"; pushNotificationTrigger.SetTrigger(_controlChannel.PushNotificationTrigger); pushNotificationTrigger.Register(); // Register keepalive event BackgroundTaskBuilder keepAliveTrigger = new BackgroundTaskBuilder(); keepAliveTrigger.Name = "KA" + Id; keepAliveTrigger.TaskEntryPoint = "BackgroundTasks.KeepAliveTrigger"; keepAliveTrigger.SetTrigger(_controlChannel.KeepAliveTrigger); keepAliveTrigger.Register(); } catch { PushEvent(ErrorType.RegisterControlChannel, ErrorPolicyType.Reconnect); return false; } #if DEBUG PushEvent(LogType.Info, "ControlChanel registered"); #endif return true; } else { return false; } }
public void CheckKeepAlive(ControlChannelTrigger trigger) { // Send keepalive for the next check var pingIq = new XMPP.tags.jabber.client.iq(); pingIq.type = Tags.jabber.client.iq.typeEnum.get; pingIq.from = Id; pingIq.Add(new XMPP.tags.xmpp.ping.ping()); Send(pingIq); // Check how long since the last packet var diffTime = DateTime.Now - _lastReceiveTime; var diffTimeMinutes = (uint)diffTime.TotalMinutes; var keepAliveMinutes = (trigger != null) ? trigger.CurrentKeepAliveIntervalInMinutes : 15; // 15 is default if (diffTimeMinutes > keepAliveMinutes) { trigger.DecreaseNetworkKeepAliveInterval(); OnError(this, new ErrorEventArgs("Connection to server lost", ErrorType.NotConnected, ErrorPolicyType.Reconnect)); } }
public void CheckKeepAlive(string id, ControlChannelTrigger trigger) { Connection connection = _connectionList[id]; if (connection != null) connection.CheckKeepAlive(trigger); }
private bool RegisterWithCCTHelper() { bool result = false; // Specify the keepalive interval expected by the server for this app // in order of minutes. const int serverKeepAliveInterval = 15; // Specify the channelId string to differentiate this // channel instance from any other channel instance. // When the background task runs, the channel object is provided // as context and the channel id can be used to adapt the behavior // of the app as required. const string channelId = "channelOne"; // Try creating the ControlChannelTrigger if this has not been already created and stored // in the property bag. Diag.DebugPrint("RegisterWithCCTHelper Starting..."); Diag.DebugPrint("Create ControlChannelTrigger ..."); // Create the ControlChannelTrigger object and request a hardware slot for this app. try { channel = new ControlChannelTrigger(channelId, serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot); } catch (Exception ex) { Diag.DebugPrint("Error while creating ControlChannelTrigger: " + ex.Message + " Please add the app to the lock screen."); return result; } bool registerKA = true, registerPushNotify = true; if (kaTaskId != Guid.Empty || pushNotifyTaskId != Guid.Empty) { IReadOnlyDictionary<Guid, IBackgroundTaskRegistration> allTasks = BackgroundTaskRegistration.AllTasks; if (kaTaskId != Guid.Empty && allTasks.ContainsKey(kaTaskId)) { registerKA = false; } if (pushNotifyTaskId != Guid.Empty && allTasks.ContainsKey(pushNotifyTaskId)) { registerPushNotify = false; } } if (registerKA) { // Register the apps background task with the trigger for keepalive. BackgroundTaskBuilder keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = "KeepaliveTaskForChannelOne"; keepAliveBuilder.TaskEntryPoint = "BackgroundTaskHelper.KATask"; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); BackgroundTaskRegistration KATask = keepAliveBuilder.Register(); kaTaskId = KATask.TaskId; } if (registerPushNotify) { // Register the apps background task with the trigger for push notification. BackgroundTaskBuilder pushNotifyBuilder = new BackgroundTaskBuilder(); pushNotifyBuilder.Name = "PushNotificationTaskForChannelOne"; pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskHelper.PushNotifyTask"; pushNotifyBuilder.SetTrigger(channel.PushNotificationTrigger); BackgroundTaskRegistration pushNotifyTask = pushNotifyBuilder.Register(); pushNotifyTaskId = pushNotifyTask.TaskId; } // Store the objects created in the property bag for later use. // NOTE: make sure these objects are free threaded. STA/Both objects can // cause deadlocks when foreground threads are suspended. if (((IDictionary<string, object>)CoreApplication.Properties).ContainsKey(channel.ControlChannelTriggerId)) { CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); } AppContext appContext = new AppContext(this); lock (CoreApplication.Properties) { ((IDictionary<string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); } try { // Send HTTP request SetUpHttpRequestAndSendToHttpServer(); result = true; Diag.DebugPrint("RegisterWithCCTHelper Completed."); } catch (Exception ex) { Diag.DebugPrint("RegisterWithCCTHelper Task failed with: " + ex.ToString()); // Exceptions may be thrown for example if the application has not // registered the background task class id for using real time communications // in the package appx manifest. result = false; } return result; }
public bool SetupTransport(string serverHostName, string servicePort) { bool result = false; lock (this) { if (appRole == AppRole.ClientRole) { // Save these to help reconnect later. serverName = serverHostName; serverPort = servicePort; // Set up the ControlChannelTrigger with the stream socket. result = RegisterWithControlChannelTrigger(serverHostName, serverPort); if (result == false) { Diag.DebugPrint("Failed to sign on and connect"); if (socket != null) { socket.Dispose(); socket = null; readPacket = null; } if (channel != null) { channel.Dispose(); channel = null; } } } else { // // start listening on the port. // serverSocket = null; result = StartListening(servicePort); if (result == false) { Diag.DebugPrint("Failed to listen"); } } } return result; }