Inheritance: IControlChannelTrigger, IClosable
示例#1
0
 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;
        }
示例#6
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;
            }
        }
示例#7
0
        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));
            }
        }
示例#8
0
 public void CheckKeepAlive(string id, ControlChannelTrigger trigger)
 {
     Connection connection = _connectionList[id];
     if (connection != null)
         connection.CheckKeepAlive(trigger);
 }
示例#9
0
        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;
        }
示例#10
0
        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;
        }