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); }
public async void SendMessage(string message) { if (socket == null) { Diag.DebugPrint("Please setup connection with the server first."); return; } try { if (writePacket == null) { writePacket = new DataWriter(socket.OutputStream); } Diag.DebugPrint("Sending message to server: " + message); // Buffer any data we want to send. writePacket.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8; writePacket.WriteString(message); // Send the data as one complete message. await writePacket.StoreAsync(); } catch (Exception exp) { Diag.DebugPrint("failed to write into the streamwebsocket: " + exp.Message); } }
public bool SetupTransport(string socketUri) { bool result = false; lock (this) { this.socketUri = socketUri; result = RegisterWithControlChannelTrigger(socketUri); if (result == false) { Diag.DebugPrint("Failed to sign on and connect"); if (socket != null) { socket.Close(1001, "Failed to sign on and connect"); socket.Dispose(); socket = null; reader = null; } if (channel != null) { channel.Dispose(); channel = null; } } } return(result); }
public bool SetupTransport(Uri serverUriIn) { bool result = false; lock (this) { try { // Save these to help reconnect later. serverUri = serverUriIn; // Set up the CCT channel with the stream socket. result = RegisterWithCCT(); if (result == false) { Diag.DebugPrint("Failed to sign on and connect"); DisposeProperties(); } } catch (Exception ex) { Diag.DebugPrint("Failed to sign on and connect. Exception: " + ex.ToString()); DisposeProperties(); } } return(result); }
private void OnReadAsInputStreamCompleted(IAsyncOperationWithProgress <IInputStream, ulong> asyncInfo, AsyncStatus asyncStatus) { try { if (asyncStatus == AsyncStatus.Canceled) { Diag.DebugPrint("IHttpContent.ReadAsInputStreamAsync was canceled."); return; } if (asyncStatus == AsyncStatus.Error) { Diag.DebugPrint("IHttpContent.ReadAsInputStreamAsync failed: " + asyncInfo.ErrorCode); return; } Diag.DebugPrint("IHttpContent.ReadAsInputStreamAsync succeeded."); inputStream = asyncInfo.GetResults(); ReadMore(); } catch (Exception ex) { Diag.DebugPrint("Error in OnReadAsInputStreamCompleted: " + ex.ToString()); } }
public string ReadResponse(Task <HttpResponseMessage> httpResponseTask) { string message = null; try { if (httpResponseTask.IsCanceled || httpResponseTask.IsFaulted) { Diag.DebugPrint("Task is cancelled or has failed"); return(message); } // We'll wait until we got the whole response. This is the only supported // scenario for HttpClient for ControlChannelTrigger. HttpResponseMessage httpResponse = httpResponseTask.Result; Diag.DebugPrint("Reading from httpresponse"); if (httpResponse == null || httpResponse.Content == null) { Diag.DebugPrint("Cant read from httpresponse, as either httpResponse or its content is null. try to reset connection."); } else { // This is likely being processed in the context of a background task and so // synchronously read the Content's results inline so that the Toast can be shown. // before we exit the Run method. message = httpResponse.Content.ReadAsStringAsync().Result; } } catch (Exception exp) { Diag.DebugPrint("Failed to read from httpresponse with error: " + exp.ToString()); } return(message); }
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."); }
async void ClientInit() { commModule = new CommModule(); if (lockScreenAdded == false) { BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync(); Diag.DebugPrint("Lock screen status " + status); switch (status) { case BackgroundAccessStatus.AlwaysAllowed: case BackgroundAccessStatus.AllowedSubjectToSystemPolicy: lockScreenAdded = true; break; case BackgroundAccessStatus.DeniedBySystemPolicy: case BackgroundAccessStatus.DeniedByUser: Diag.DebugPrint("As lockscreen status was Denied, app should switch to polling mode such as email based on time triggers"); break; } } btnConnection.Visibility = Visibility.Visible; return; }
public void OnDataReadCompletion(uint bytesRead, DataReader readPacket) { Diag.DebugPrint("OnDataReadCompletion Entry"); if (readPacket == null) { Diag.DebugPrint("DataReader is null"); return; } uint buffLen = readPacket.UnconsumedBufferLength; Diag.DebugPrint($"bytesRead: {bytesRead}, unconsumedBufferLength: {buffLen}"); if (buffLen == 0) { Diag.DebugPrint("Received zero bytes from the socket. Server must have closed the connection."); Diag.DebugPrint("Try disconnecting and reconnecting to the server"); return; } string serializedMessage = readPacket.ReadString(buffLen); var message = JsonConvert.DeserializeObject <Message>(serializedMessage); Diag.DebugPrint("Received Buffer: " + serializedMessage); actions.ReceiveMessage(message); AppContext.Enqueue(message); PostSocketRead(MAX_BUFFER_LENGTH); Diag.DebugPrint("OnDataReadCompletion Exit"); }
public static async Task AcceptConnection(string serviceName, CommModule myCommModule) { // Create and store a streamsocketlistener in the class. This way, new connections // can be automatically accepted. if (myCommModule.serverListener == null) { myCommModule.serverListener = new StreamSocketListener(); } myCommModule.serverListener.ConnectionReceived += (op, evt) => { // For simplicity, the server can talk to only one client at a time. myCommModule.serverSocket = evt.Socket; if (myCommModule.writePacket != null) { myCommModule.writePacket.DetachStream(); myCommModule.writePacket = null; } Diag.DebugPrint("Connection Received!"); }; await myCommModule.serverListener.BindServiceNameAsync(serviceName); return; }
// Registers a background task with an network change system trigger. private void RegisterNetworkChangeTask() { try { if (NetworkTaskRegistrationGuid != Guid.Empty) { IReadOnlyDictionary <Guid, IBackgroundTaskRegistration> allTasks = BackgroundTaskRegistration.AllTasks; if (allTasks.ContainsKey(NetworkTaskRegistrationGuid)) { Diag.DebugPrint("Network task is already registered."); return; } } BackgroundTaskBuilder myTaskBuilder = new BackgroundTaskBuilder(); SystemTrigger myTrigger = new SystemTrigger(SystemTriggerType.NetworkStateChange, false); myTaskBuilder.SetTrigger(myTrigger); myTaskBuilder.TaskEntryPoint = "Background.NetworkChangeTask"; myTaskBuilder.Name = "Network change task"; BackgroundTaskRegistration myTask = myTaskBuilder.Register(); NetworkTaskRegistrationGuid = myTask.TaskId; } catch (Exception exp) { Diag.DebugPrint("Exception caught while setting up system event" + exp.ToString()); } }
private void SetUpHttpRequestAndSendToHttpServer() { try { AppendOriginToUri(); Diag.DebugPrint("SetUpHttpRequestAndSendToHttpServer started with URI: " + serverUri); // IMPORTANT: // For HTTP based transports that use ControlChannelTrigger, whenever we send the next request, // we will abort the earlier outstanding HTTP request and start a new one. // For example, when the HTTP server is taking longer to reply, and the keep alive trigger is fired // in-between then the keep alive task will abort the outstanding HTTP request and start a new request // which should be finished before the next keep alive task is triggered. ResetRequest(); httpRequest = new HttpRequestMessage(HttpMethod.Get, serverUri); SendHttpRequest(); } catch (Exception ex) { Diag.DebugPrint("Connect failed with: " + ex.ToString()); throw; } }
private async void ListenButton_Click(object sender, RoutedEventArgs e) { if (listenState == listeningStates.notListening) { string serverPort = GetServerPort(); bool result = await Task <bool> .Factory.StartNew(() => { return(commModule.SetupTransport(null, serverPort)); }); Diag.DebugPrint("CommModule setup result: " + result); if (result == true) { ListenButton.Content = "Stop Listening"; listenState = listeningStates.listening; } else { ListenButton.Content = "failed to listen. click to retry"; listenState = listeningStates.notListening; } } else { await ResetTransportTaskAsync(); listenState = listeningStates.notListening; ListenButton.Content = "Listen"; } }
// Registers a background task with a network change system trigger. private void RegisterNetworkChangeTask() { try { // Delete previously registered network status change tasks as // the background triggers are persistent by nature across process // lifetimes. foreach (var cur in BackgroundTaskRegistration.AllTasks) { Diag.DebugPrint("Deleting Background Taks " + cur.Value.Name); cur.Value.Unregister(true); } var myTaskBuilder = new BackgroundTaskBuilder(); var myTrigger = new SystemTrigger(SystemTriggerType.NetworkStateChange, false); myTaskBuilder.SetTrigger(myTrigger); myTaskBuilder.TaskEntryPoint = "Background.NetworkChangeTask"; myTaskBuilder.Name = "Network change task"; var myTask = myTaskBuilder.Register(); } catch (Exception exp) { Diag.DebugPrint("Exception caught while setting up system event" + exp.ToString()); } }
private void ClientRole_Click(object sender, RoutedEventArgs e) { // To keep things simple, this button is disabled once clicked. Diag.DebugPrint("Client role selected"); ClientRoleButton.IsEnabled = false; ClientInit(); }
private void OnSendRequestCompleted(IAsyncOperationWithProgress <HttpResponseMessage, HttpProgress> asyncInfo, AsyncStatus asyncStatus) { try { if (asyncStatus == AsyncStatus.Canceled) { Diag.DebugPrint("HttpRequestMessage.SendRequestAsync was canceled."); return; } if (asyncStatus == AsyncStatus.Error) { Diag.DebugPrint("HttpRequestMessage.SendRequestAsync failed: " + asyncInfo.ErrorCode); return; } Diag.DebugPrint("HttpRequestMessage.SendRequestAsync succeeded."); HttpResponseMessage response = asyncInfo.GetResults(); readAsInputStreamOperation = response.Content.ReadAsInputStreamAsync(); readAsInputStreamOperation.Completed = OnReadAsInputStreamCompleted; } catch (Exception ex) { Diag.DebugPrint("Error in OnSendRequestCompleted: " + ex.ToString()); } }
private void SetupHttpRequestAndSendToHttpServer() { try { Diag.DebugPrint("SetupHttpRequestAndSendToHttpServer started with uri: " + serverUri); // IMPORTANT: // For HTTP based transports that use the RTC broker, whenever we send next request, we will abort the earlier // outstanding http request and start new one. // For example in case when http server is taking longer to reply, and keep alive trigger is fired in-between // then keep alive task will abort outstanding http request and start a new request which should be finished // before next keep alive task is triggered. if (httpRequest != null) { httpRequest.Dispose(); } httpRequest = RtcRequestFactory.Create(HttpMethod.Get, serverUri); SendHttpRequest(); } catch (Exception e) { Diag.DebugPrint("Connect failed with: " + e.ToString()); throw; } }
private void ShowBackgroundTasks(object sender, RoutedEventArgs e) { Diag.DebugPrint("Background Tasks: "); foreach (var cur in BackgroundTaskRegistration.AllTasks) { Diag.DebugPrint($" {cur.Value.Name}"); } }
private void TestSocket(object sender, RoutedEventArgs e) { if (!(string.IsNullOrEmpty(txtMessage.Text))) { Diag.DebugPrint("TestSocket: Posting message to Web API and returning a notification"); SendMessage(txtMessage.Text); } }
void UnregisterBackgroundTasks() { foreach (var cur in BackgroundTaskRegistration.AllTasks) { Diag.DebugPrint("Deleting Background Task " + cur.Value.Name); cur.Value.Unregister(true); } }
public void Run(Windows.ApplicationModel.Background.IBackgroundTaskInstance taskInstance) { if (taskInstance == null) { Diag.DebugPrint("PushNotifyTask: taskInstance was null"); return; } Diag.DebugPrint("PushNotifyTask " + taskInstance.Task.Name + " Starting..."); // Use the ControlChannelTriggerEventDetails object to derive the context for this background task. // The context happens to be the channelId that apps can use to differentiate between // various instances of the channel.. var channelEventArgs = taskInstance.TriggerDetails as IControlChannelTriggerEventDetails; ControlChannelTrigger channel = channelEventArgs.ControlChannelTrigger; if (channel == null) { Diag.DebugPrint("Channel object may have been deleted."); return; } string channelId = channel.ControlChannelTriggerId; if (((IDictionary <string, object>)CoreApplication.Properties).ContainsKey(channelId)) { try { string messageReceived = "PushNotification Received"; var appContext = ((IDictionary <string, object>)CoreApplication.Properties)[channelId] as AppContext; // Process any messages that have been enqueued by the receive completion handler. bool result = AppContext.messageQueue.TryDequeue(out messageReceived); if (result) { Diag.DebugPrint("Message: " + messageReceived); InvokeSimpleToast(messageReceived); } else { Diag.DebugPrint("There was no message for this push notification: "); } } catch (Exception exp) { Diag.DebugPrint("PushNotifyTask failed with: " + exp.Message); } } else { Diag.DebugPrint("Cannot find AppContext key " + channelId); } Diag.DebugPrint("PushNotifyTask " + taskInstance.Task.Name + " finished."); }
private void ClientRole_Click(object sender, RoutedEventArgs e) { Diag.DebugPrint("Client role selected"); // In order to simplify the sample and focus on the core controlchanneltrigger // related concepts, once a role is selected, the app has // to be restarted to change the role. ClientRoleButton.IsEnabled = false; ClientInit(); }
public void Run(IBackgroundTaskInstance taskInstance) { if (taskInstance == null) { Diag.DebugPrint("NetworkChangeTask: taskInstance was null"); return; } NetworkStateChangeEventDetails details = taskInstance.TriggerDetails as NetworkStateChangeEventDetails; // Only restart CCT connection if network connectivity level changes. if (details.HasNewNetworkConnectivityLevel == false) { return; } Diag.DebugPrint("System task - " + taskInstance.Task.Name + " starting ..."); // In this example, the channel name has been hardcoded to lookup the property bag // for any previous contexts. The channel name may be used in more sophisticated ways // in case an app has multiple ControlChannelTrigger objects. string channelId = "channelOne"; if (((IDictionary <string, object>)CoreApplication.Properties).ContainsKey(channelId)) { try { AppContext appContext = null; lock (CoreApplication.Properties) { appContext = ((IDictionary <string, object>)CoreApplication.Properties)[channelId] as AppContext; } if (appContext != null && appContext.CommunicationInstance != null) { CommunicationModule communicationInstance = appContext.CommunicationInstance; // Clear any existing channels, sockets etc. communicationInstance.Reset(); // Create CCT enabled transport. communicationInstance.SetUpTransport(communicationInstance.serverUri, GetType().Name); } } catch (Exception ex) { Diag.DebugPrint("Registering with CCT failed with: " + ex.ToString()); } } else { Diag.DebugPrint("Cannot find AppContext key channelOne"); } Diag.DebugPrint("System task - " + taskInstance.Task.Name + " finished."); }
private void CheckEnter(object sender, KeyRoutedEventArgs e) { if (e.Key == Windows.System.VirtualKey.Enter) { if (!(string.IsNullOrEmpty(txtMessage.Text))) { Diag.DebugPrint("TestSocket: Posting message to Web API and returning a notification"); SendMessage(txtMessage.Text); } } }
void PostSocketRead(int length) { Diag.DebugPrint("Entering PostSocketRead"); // IMPORTANT: When using winRT based transports such as StreamSocket with the ControlChannelTrigger, // we have to use the raw async pattern for handling reads instead of the await model. // Using the raw async pattern allows Windows to synchronize the PushNotification task's // IBackgroundTask::Run method with the return of the receive completion callback. // The Run method is invoked after the completion callback returns. This ensures that the app has // received the data/errors before the Run method is invoked. // It is important to note that the app has to post another read before it returns control from the completion callback. // It is also important to note that the DataReader is not directly used with the // StreamSocket transport since that breaks the synchronization described above. // It is not supported to use DataReader's LoadAsync method directly on top of the transport. Instead, // the IBuffer returned by the transport's ReadAsync method can be later passed to DataReader::FromBuffer() // for further processing. try { var readBuf = new Windows.Storage.Streams.Buffer((uint)length); var readOp = socket.InputStream.ReadAsync(readBuf, (uint)length, InputStreamOptions.Partial); readOp.Completed = (IAsyncOperationWithProgress <IBuffer, uint> asyncAction, AsyncStatus asyncStatus) => { switch (asyncStatus) { case AsyncStatus.Completed: case AsyncStatus.Error: try { // GetResults in AsyncStatus::Error is called as it throws a user friendly error string. IBuffer localBuf = asyncAction.GetResults(); uint bytesRead = localBuf.Length; readPacket = DataReader.FromBuffer(localBuf); OnDataReadCompletion(bytesRead, readPacket); } catch (Exception exp) { Diag.DebugPrint("Read operation failed: " + exp.Message); } break; case AsyncStatus.Canceled: // Read is not cancelled in this sample. break; } }; } catch (Exception exp) { Diag.DebugPrint("failed to post a read failed with error: " + exp.Message); } Diag.DebugPrint("Leaving PostSocketRead"); }
public bool SendMessageToHttpServer() { try { SetupHttpRequestAndSendToHttpServer(); return(true); } catch (Exception ex) { Diag.DebugPrint("httpClient write failed with error: " + ex.ToString()); return(false); } }
async Task SendNotification(Notification notification) { using (var client = new HttpClient()) { var message = new HttpRequestMessage(HttpMethod.Post, new Uri(sendUri)); message.Headers.Accept.Add(new HttpMediaTypeWithQualityHeaderValue("application/json")); var content = new HttpStringContent(JsonConvert.SerializeObject(notification), UnicodeEncoding.Utf8, "application/json"); message.Content = content; var result = await client.SendRequestAsync(message); Diag.DebugPrint($"SendNotification: Completed with status code {result.StatusCode}: {result.ReasonPhrase}"); } }
public static Uri CreateSocketServerUri(this string socketUri) { try { var serverSocket = new Uri(socketUri); return(serverSocket); } catch (Exception ex) { Diag.DebugPrint("Error creating URI: " + ex.Message); return(null); } }
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."); } }
protected override async void OnBackgroundActivated(BackgroundActivatedEventArgs e) { base.OnBackgroundActivated(e); var deferral = e.TaskInstance.GetDeferral(); switch (e.TaskInstance.Task.Name) { case "ToastTask": try { Diag.DebugPrint("ToastTask Starting..."); e.TaskInstance.Canceled += new BackgroundTaskCanceledEventHandler((sender, reason) => { deferral.Complete(); }); var details = e.TaskInstance.TriggerDetails as ToastNotificationActionTriggerDetail; if (details != null) { var args = QueryString.Parse(details.Argument); if (args["uri"] != null) { Diag.DebugPrint("ToastTask: Launching URI - " + args["uri"]); await Windows.System.Launcher.LaunchUriAsync(new Uri(args["uri"])); } else { Diag.DebugPrint("ToastTask: No launch URI found for this toast"); } } else { Diag.DebugPrint("ToastTask: No Trigger Details found for this task"); } } catch (Exception ex) { Diag.DebugPrint("ToastTask failed with: " + ex.Message); } break; default: break; } deferral.Complete(); }