private void SendHttpRequest() { // 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 again. Diag.DebugPrint("Calling UsingTransport() ..."); channel.UsingTransport(httpRequest); // Call the SendRequestAsync function to kick start the TCP connection establishment // process for this HTTP request. Diag.DebugPrint("Calling SendRequestAsync() ..."); sendRequestOperation = httpClient.SendRequestAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead); sendRequestOperation.Completed += OnSendRequestCompleted; // Call WaitForPushEnabled API to make sure the TCP connection has been established, // which will mean that the OS will have allocated any hardware or software slot for this TCP connection. ControlChannelTriggerStatus status = channel.WaitForPushEnabled(); Diag.DebugPrint("WaitForPushEnabled() completed with status: " + status); if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated) { throw new Exception("Hardware/Software slot not allocated"); } Diag.DebugPrint("Transport is ready to read response from server."); }
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); } }
private void SendHttpRequest() { if (httpRequest == null) { throw new Exception("HttpRequest object is null"); } // 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 plugin a new transport by // calling UsingTransport API again. Diag.DebugPrint("Calling UsingTransport() ..."); channel.UsingTransport(httpRequest); // Call the SendAsync function to kick start the TCP connection establishment // process for this http request. Task <HttpResponseMessage> httpResponseTask = httpClient.SendAsync(httpRequest); // 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. ControlChannelTriggerStatus status = channel.WaitForPushEnabled(); Diag.DebugPrint("WaitForPushEnabled() completed with status: " + status); if (status != ControlChannelTriggerStatus.HardwareSlotAllocated && status != ControlChannelTriggerStatus.SoftwareSlotAllocated) { throw new Exception("Hardware/Software slot not allocated"); } Diag.DebugPrint("In SetupHttpRequestAndSendToHttpServer httpResponse is prepared to read response from server."); // IMPORTANT: This sample is noticably different from other transports based on ControlChannelTrigger // The HttpClient receive callback is delivered via a Task to the app since the HttpClient code is purely // managed code based. This means push notification task will fire as soon as the data or error is dispatched // to the application. Hence, in this sample we Enqueue the responseTask returned by httpClient.sendAsync // into a queue that the push notify task will pick up and process inline. AppContext.messageQueue.Enqueue(httpResponseTask); }
async Task <bool> RegisterWithControlChannelTriggerHelper(string serverHostName, string serverPort) { bool result = false; socket = new StreamSocket(); // 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"; // 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 lockscreen. " + exp.Message); return(result); } // Register the apps background task with the trigger for keepalive. var keepAliveBuilder = new BackgroundTaskBuilder(); keepAliveBuilder.Name = "KeepaliveTaskForChannelOne"; keepAliveBuilder.TaskEntryPoint = "Background.KATask"; 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 = "Background.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 plugin a new transport by // calling UsingTransport API again. try { Diag.DebugPrint("Calling UsingTransport() ..."); channel.UsingTransport(socket); // Connect the socket HostName hostName = new HostName(serverHostName); // If connect fails or times out it will throw exception. await socket.ConnectAsync(hostName, serverPort); 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. if (((IDictionary <string, object>)CoreApplication.Properties).ContainsKey(channel.ControlChannelTriggerId)) { CoreApplication.Properties.Remove(channel.ControlChannelTriggerId); } var appContext = new AppContext(this, socket, channel, channel.ControlChannelTriggerId); ((IDictionary <string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); Diag.DebugPrint("RegisterWithCCTHelper Completed."); result = true; // We are all set. Post a read to ensure push notificiation fires. PostSocketRead(MAX_BUFFER_LENGTH); } catch (Exception exp) { Diag.DebugPrint("RegisterWithCCTHelper 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); }
async Task <bool> RegisterWithCCTHelper(string serverUri) { bool result = false; socket = new MessageWebSocket(); socket.MessageReceived += Socket_MessageReceived; // 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 = "ControlChannelWebSocketUWP"; // 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("About to 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. OutputDebugString("edetocCCTSample_Tracing: Entering RegisterWithCCTHelper"); try { channel = new ControlChannelTrigger(channelId, serverKeepAliveInterval, ControlChannelTriggerResourceType.RequestHardwareSlot); } catch (UnauthorizedAccessException exp) { //Diag.DebugPrint("Please add the app to the lock screen." + exp.Message); OutputDebugString("edetocCCTSample_Tracing: Failed to create ControlChannelTrigger" + exp.Message); return(result); } OutputDebugString("edetocCCTSample_Tracing: ControlChannelTrigger created with success"); //Diag.DebugPrint("ControlChannelTrigger creation OK"); Uri serverUriInstance; try { serverUriInstance = new Uri(serverUri); OutputDebugString("edetocCCTSample_Tracing: Uri is " + serverUriInstance.ToString()); } catch (Exception exp) { OutputDebugString("edetocCCTSample_Tracing: error create URI: " + exp.Message); //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 = "KeepaliveTaskFor" + channelId; keepAliveBuilder.TaskEntryPoint = WebSocketKeepAliveTask; keepAliveBuilder.SetTrigger(channel.KeepAliveTrigger); keepAliveBuilder.Register(); OutputDebugString("edetocCCTSample_Tracing: WebSocketKeepAliveTask registered"); //Diag.DebugPrint("edetoc - BG keepAliveBuilder register OK"); // Register the apps background task with the trigger for push notification task. var pushNotifyBuilder = new BackgroundTaskBuilder(); pushNotifyBuilder.Name = "PushNotificationTaskFor" + channelId; pushNotifyBuilder.TaskEntryPoint = "BackgroundTaskHelper.PushNotifyTask"; pushNotifyBuilder.SetTrigger(channel.PushNotificationTrigger); pushNotifyBuilder.Register(); //Diag.DebugPrint("edetoc - BG pushNotifyBuilder register OK"); OutputDebugString("edetocCCTSample_Tracing: PushNotifyTask registered"); // 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 { OutputDebugString("edetocCCTSample_Tracing: Before UsingTransport"); channel.UsingTransport(socket); OutputDebugString("edetocCCTSample_Tracing: After UsingTransport"); // Connect the socket // // If connect fails or times out it will throw exception. OutputDebugString(string.Format("edetocCCTSample_Tracing: {0} Before ConnectAsync", DateTime.Now.ToString())); await socket.ConnectAsync(serverUriInstance); OutputDebugString("edetocCCTSample_Tracing: After ConnectASync"); //Diag.DebugPrint("Socket 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) { OutputDebugString("edetocCCTSample_Tracing: Neither hardware nor software slot could be allocated"); throw new Exception(string.Format("Neither hardware nor software slot could be allocated. ChannelStatus is {0}", status.ToString())); } OutputDebugString("edetocCCTSample_Tracing: WaitForPushEnabled OK"); // 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 ApplicationContext(this, socket, channel, channel.ControlChannelTriggerId); ((IDictionary <string, object>)CoreApplication.Properties).Add(channel.ControlChannelTriggerId, appContext); result = true; //Diag.DebugPrint("RegisterWithCCTHelper Completed."); } catch (Exception exp) { //Diag.DebugPrint("RegisterWithCCTHelper Task failed with: " + exp.Message); OutputDebugString("edetocCCTSample_Tracing: RegisterWithCCTHelper 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); }