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.");
        }
Exemple #2
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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);
        }