Exemplo n.º 1
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public ITrackingConnection AddOrUpdateConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            bool isNewConnection = true;
            ITrackingConnection oldConnection = null;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                Logger.LogVerbose(String.Format("Connection {0} exists. Closing previous connection.", old.Connection.ConnectionId));
                // Kick out the older connection. This should only happen when 
                // a previous connection attempt fails on the client side (e.g. transport fallback).

                old.Connection.ApplyState(TransportConnectionStates.Replaced);

                // Don't bother disposing the registration here since the token source
                // gets disposed after the request has ended
                old.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
                oldConnection = old.Connection;

                return newMetadata;
            });

            if (isNewConnection)
            {
                Logger.LogInformation(String.Format("Connection {0} is New.", connection.ConnectionId));
                connection.IncrementConnectionsCount();
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            newMetadata.Connection.ApplyState(TransportConnectionStates.Added);

            return oldConnection;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection exists. Closing previous connection. Old=({0}, {1}) New=({2})", oldMetadata.Connection.IsAlive, oldMetadata.Connection.Url, connection.Url);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection is New=({0}).", connection.Url);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
Exemplo n.º 4
0
        private void CheckDisconnect(ConnectionMetadata metadata)
        {
            try
            {
                if (RaiseDisconnect(metadata))
                {
                    // Remove the connection from the list
                    RemoveConnection(metadata.Connection);

                    // Fire disconnect on the connection
                    metadata.Connection.Disconnect();

                    // End the connection
                    metadata.Connection.End();
                }
            }
            catch (Exception ex)
            {
                // Swallow exceptions that might happen during disconnect
                Trace.TraceInformation("Raising Disconnect failed: {0}", ex);
            }
        }
Exemplo n.º 5
0
        private bool RaiseTimeout(ConnectionMetadata metadata)
        {
            // The connection already timed out so do nothing
            if (metadata.Connection.IsTimedOut)
            {
                return(false);
            }

            var keepAlive = _configurationManager.KeepAlive;

            // If keep alive is configured and the connection supports keep alive
            // don't ever time out
            if (keepAlive != null && metadata.Connection.SupportsKeepAlive)
            {
                return(false);
            }

            TimeSpan elapsed = DateTime.UtcNow - metadata.Initial;

            // Only raise timeout if we're past the configured connection timeout.
            return(elapsed >= _configurationManager.ConnectionTimeout);
        }
Exemplo n.º 6
0
        private bool RaiseTimeout(ConnectionMetadata metadata)
        {
            // The connection already timed out so do nothing
            if (metadata.Connection.IsTimedOut)
            {
                return(false);
            }

            // If keep alives are enabled and the transport doesn't require timeouts,
            // i.e. anything but long-polling, don't ever timeout.
            var keepAlive = _transportOptions.KeepAlive;

            if (keepAlive != null && !metadata.Connection.RequiresTimeout)
            {
                return(false);
            }

            TimeSpan elapsed = DateTime.UtcNow - metadata.Initial;

            // Only raise timeout if we're past the configured connection timeout.
            return(elapsed >= _transportOptions.LongPolling.PollTimeout);
        }
Exemplo n.º 7
0
        async Task <Try <ICloudConnection> > TryCreateCloudConnectionFromServiceIdentity(IIdentity identity, Action <string, CloudConnectionStatus> connectionStatusChangedHandler, bool refreshOutOfDateCache, CloudListener cloudListener, string authChain)
        {
            Events.CreatingCloudConnectionOnBehalfOf(identity);
            ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(identity.Id);

            string          productInfo = connectionMetadata.EdgeProductInfo;
            Option <string> modelId     = connectionMetadata.ModelId;

            ITransportSettings[] transportSettings = GetTransportSettings(
                this.upstreamProtocol,
                this.connectionPoolSize,
                this.proxy,
                this.useServerHeartbeat,
                authChain);

            try
            {
                ICloudConnection cc = await CloudConnection.Create(
                    identity,
                    connectionStatusChangedHandler,
                    transportSettings,
                    this.messageConverterProvider,
                    this.clientProvider,
                    cloudListener,
                    this.edgeHubTokenProvider,
                    this.idleTimeout,
                    this.closeOnIdleTimeout,
                    this.operationTimeout,
                    productInfo,
                    modelId);

                Events.SuccessCreatingCloudConnection(identity);
                return(Try.Success(cc));
            }
            catch (UnauthorizedException ex) when(this.trackDeviceState)
            {
                return(await this.TryRecoverCloudConnection(identity, connectionStatusChangedHandler, refreshOutOfDateCache, ex));
            }
        }
Exemplo n.º 8
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                RemoveConnection(metadata.Connection);

                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();

                // End the connection
                metadata.Connection.End();
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networking hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    Trace.TraceInformation("KeepAlive(" + metadata.Connection.ConnectionId + ")");

                    // If the keep alive send fails then kill the connection
                    metadata.Connection.KeepAlive()
                    .Catch(ex =>
                    {
                        Trace.TraceInformation("Failed to send keep alive: " + ex.GetBaseException());

                        RemoveConnection(metadata.Connection);

                        metadata.Connection.End();
                    });

                    metadata.UpdateKeepAlive(_configurationManager.KeepAlive);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            _trace.Source.TraceInformation("TransportHeartBeat: Adding connection {0}", connection.ConnectionId);

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                _trace.Source.TraceInformation("TransportHeartBeat: Connection {0} already exists and alive={1}. Closing previous connection id.", oldMetadata.Connection.ConnectionId, oldMetadata.Connection.IsAlive);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                _trace.Source.TraceInformation("TransportHeartBeat: Connection {0} is new.", connection.ConnectionId);
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return isNewConnection;
        }
Exemplo n.º 10
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();

                RemoveConnection(metadata.Connection);
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networing hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    metadata.Connection.KeepAlive().Catch();
                    metadata.UpdateKeepAlive(_configurationManager.KeepAlive);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 11
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networking hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    Trace.TraceEvent(TraceEventType.Verbose, 0, "KeepAlive(" + metadata.Connection.ConnectionId + ")");

                    // Ensure delegate continues to use the C# Compiler static delegate caching optimization.
                    metadata.Connection.KeepAlive().Catch((ex, state) => OnKeepAliveError(ex, state), state: Trace, traceSource: Trace);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection           = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return(newMetadata);
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection exists. Closing previous connection. Old=({0}, {1}) New=({2})", oldMetadata.Connection.IsAlive, oldMetadata.Connection.Url, connection.Url);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                oldMetadata.Connection.End();

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection is New=({0}).", connection.Url);
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Set the keep alive time
            newMetadata.UpdateKeepAlive(_configurationManager.KeepAlive);

            return(isNewConnection);
        }
Exemplo n.º 13
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();

                EndConnection(metadata);
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networking hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    Trace.TraceEvent(TraceEventType.Verbose, 0, "KeepAlive(" + metadata.Connection.ConnectionId + ")");

                    metadata.Connection.KeepAlive()
                                       .Catch(ex =>
                                       {
                                           Trace.TraceEvent(TraceEventType.Error, 0, "Failed to send keep alive: " + ex.GetBaseException());
                                       });
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 14
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection {0} exists. Closing previous connection.", oldMetadata.Connection.ConnectionId);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).

                // Don't bother disposing the registration here since the token source
                // gets disposed after the request has ended
                EndConnection(oldMetadata, disposeRegistration: false);

                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection {0} is New.", connection.ConnectionId);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Register for disconnect cancellation
            newMetadata.Registration = connection.CancellationToken.SafeRegister(OnConnectionEnded, newMetadata);

            return isNewConnection;
        }
Exemplo n.º 15
0
        private bool RaiseTimeout(ConnectionMetadata metadata)
        {
            // The connection already timed out so do nothing
            if (metadata.Connection.IsTimedOut)
            {
                return false;
            }

            TimeSpan? keepAlive = _configurationManager.KeepAlive;
            // If keep alive is configured and the connection supports keep alive
            // don't ever time out
            if (keepAlive != null && metadata.Connection.SupportsKeepAlive)
            {
                return false;
            }

            TimeSpan elapsed = DateTime.UtcNow - metadata.Initial;

            // Only raise timeout if we're past the configured connection timeout.
            return elapsed >= _configurationManager.ConnectionTimeout;
        }
Exemplo n.º 16
0
        public async Task SmokeTest()
        {
            // Arrange
            string edgeProductInfo = "IoTEdge 1.0.7";
            var    storeProvider   = new StoreProvider(new InMemoryDbStoreProvider());
            IEntityStore <string, string> store = storeProvider.GetEntityStore <string, string>("connectionMetadata");
            var metadataStore = new MetadataStore(store, edgeProductInfo);

            var deviceProductInfos = new Dictionary <string, string>
            {
                ["d1"]    = Guid.NewGuid().ToString(),
                ["d2"]    = Guid.NewGuid().ToString(),
                ["d3"]    = Guid.NewGuid().ToString(),
                ["d3/m1"] = Guid.NewGuid().ToString(),
                ["d3/m2"] = Guid.NewGuid().ToString()
            };

            var deviceToModelIds = new Dictionary <string, string>
            {
                ["d1"]    = "dtmi:example:capabailityModels:MXChip;1",
                ["d2"]    = "dtmi:example2:capabailityModels:MXChip;1",
                ["d3"]    = "dtmi:example3:capabailityModels:MXChip;1",
                ["d3/m1"] = "dtmi:example4:capabailityModels:MXChip;1",
                ["d3/m2"] = "dtmi:example5:capabailityModels:MXChip;1"
            };

            // Act
            foreach (KeyValuePair <string, string> kvp in deviceProductInfos)
            {
                await metadataStore.SetProductInfo(kvp.Key, kvp.Value);
            }

            foreach (KeyValuePair <string, string> kvp in deviceToModelIds)
            {
                await metadataStore.SetModelId(kvp.Key, kvp.Value);
            }

            var receivedDeviceInfos     = new Dictionary <string, string>();
            var receivedEdgeDeviceInfos = new Dictionary <string, string>();
            var receivedDeviceModelIds  = new Dictionary <string, string>();

            foreach (string id in deviceProductInfos.Keys)
            {
                ConnectionMetadata connectionMetadata = await metadataStore.GetMetadata(id);

                string productInfo           = connectionMetadata.ProductInfo;
                string deviceEdgeProductInfo = connectionMetadata.EdgeProductInfo;

                receivedDeviceInfos.Add(id, productInfo);
                receivedEdgeDeviceInfos.Add(id, deviceEdgeProductInfo);
            }

            foreach (string id in deviceToModelIds.Keys)
            {
                ConnectionMetadata connectionMetadata = await metadataStore.GetMetadata(id);

                Option <string> modelId = connectionMetadata.ModelId;
                modelId.ForEach(m => receivedDeviceModelIds.Add(id, m));
            }

            // Assert
            Assert.Equal(deviceProductInfos.Count, receivedDeviceInfos.Count);
            Assert.Equal(deviceProductInfos.Count, receivedEdgeDeviceInfos.Count);
            Assert.Equal(deviceToModelIds.Count, receivedDeviceModelIds.Count);

            foreach (KeyValuePair <string, string> kvp in deviceProductInfos)
            {
                Assert.Equal(kvp.Value, receivedDeviceInfos[kvp.Key]);
                Assert.Equal($"{kvp.Value} {edgeProductInfo}", receivedEdgeDeviceInfos[kvp.Key]);
            }

            foreach (KeyValuePair <string, string> kvp in deviceToModelIds)
            {
                Assert.Equal(kvp.Value, receivedDeviceModelIds[kvp.Key]);
            }
        }
Exemplo n.º 17
0
        public async Task TestSendMessages()
        {
            // Arrange
            const string Id                             = "id1";
            var          identity                       = Mock.Of <IIdentity>(i => i.Id == Id);
            var          twinMessageConverter           = new TwinMessageConverter();
            var          twinCollectionMessageConverter = new TwinCollectionMessageConverter();
            var          messageConverterProvider       = new MessageConverterProvider(
                new Dictionary <Type, IMessageConverter>()
            {
                { typeof(Message), new DeviceClientMessageConverter() },
                { typeof(Shared.Twin), twinMessageConverter },
                { typeof(TwinCollection), twinCollectionMessageConverter }
            });

            var edgeHubTokenProvider = new Mock <ITokenProvider>();

            var clientWatcher = new ClientWatcher();

            var clientProvider = new Mock <IClientProvider>();

            clientProvider.Setup(c => c.Create(identity, edgeHubTokenProvider.Object, It.IsAny <ITransportSettings[]>(), Option.None <string>()))
            .Returns(() => new ThrowingClient(clientWatcher, 3));

            var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>();

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(Id))
            .ReturnsAsync(
                Option.Some(
                    new ServiceIdentity(
                        Id,
                        "dummy",
                        new List <string>(),
                        new ServiceAuthentication(new SymmetricKeyAuthentication("foo", "bar")),
                        ServiceIdentityStatus.Enabled)));
            deviceScopeIdentitiesCache.Setup(d => d.GetAuthChain(It.Is <string>(i => i == Id)))
            .ReturnsAsync(Option.Some(Id));

            var edgeHubIdentity = Mock.Of <IIdentity>();

            ConnectionMetadata connectionMetadata = new ConnectionMetadata("edgeProdInfo");
            var metadataStore = new Mock <IMetadataStore>();

            metadataStore.Setup(p => p.GetMetadata(Id))
            .ReturnsAsync(connectionMetadata);

            var identityProvider = new Mock <IIdentityProvider>();

            identityProvider.Setup(i => i.Create(Id)).Returns(identity);

            var credentialsCache = new Mock <ICredentialsCache>();
            var edgeHub          = new Mock <IEdgeHub>();

            var connectionProvider = new CloudConnectionProvider(
                messageConverterProvider,
                1,
                clientProvider.Object,
                Option.None <UpstreamProtocol>(),
                edgeHubTokenProvider.Object,
                deviceScopeIdentitiesCache.Object,
                credentialsCache.Object,
                edgeHubIdentity,
                TimeSpan.FromMinutes(10),
                false,
                TimeSpan.FromMinutes(10),
                false,
                Option.None <IWebProxy>(),
                metadataStore.Object,
                scopeAuthenticationOnly: true,
                trackDeviceState: true,
                true);

            connectionProvider.BindEdgeHub(edgeHub.Object);

            var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>();
            var connectionManager         = new ConnectionManager(connectionProvider, credentialsCache.Object, identityProvider.Object, deviceConnectivityManager);
            var messagesToSend            = new List <IMessage>();

            for (int i = 0; i < 10; i++)
            {
                var message = new EdgeMessage.Builder(new byte[i])
                              .SetSystemProperties(
                    new Dictionary <string, string>()
                {
                    [SystemProperties.MessageId] = i.ToString()
                })
                              .Build();
                messagesToSend.Add(message);
            }

            // Act
            Option <ICloudProxy> cloudProxyOption = await connectionManager.GetCloudConnection(Id);

            // Assert
            Assert.True(cloudProxyOption.HasValue);
            ICloudProxy cloudProxy = cloudProxyOption.OrDefault();

            Assert.True(cloudProxy.IsActive);

            // Act
            await RunSendMessages(cloudProxy, messagesToSend);

            // Assert
            Assert.Equal(messagesToSend.Count, clientWatcher.ReceivedMessages.Count());
            Assert.Equal(5, clientWatcher.OpenAsyncCount);
            Assert.True(cloudProxy.IsActive);

            IEnumerable <string> expectedMessageIds = messagesToSend.Select(m => m.SystemProperties[SystemProperties.MessageId]);
            IEnumerable <string> receivedMessageIds = clientWatcher.ReceivedMessages.Select(m => m.MessageId);

            Assert.Equal(expectedMessageIds, receivedMessageIds);
        }
Exemplo n.º 18
0
        private bool RaiseTimeout(ConnectionMetadata metadata)
        {
            // The connection already timed out so do nothing
            if (metadata.Connection.IsTimedOut)
            {
                return false;
            }

            // If keep alives are enabled and the transport doesn't require timeouts,
            // i.e. anything but long-polling, don't ever timeout.
            var keepAlive = _configurationManager.KeepAlive;
            if (keepAlive != null && !metadata.Connection.RequiresTimeout)
            {
                return false;
            }

            TimeSpan elapsed = DateTime.UtcNow - metadata.Initial;

            // Only raise timeout if we're past the configured connection timeout.
            return elapsed >= _configurationManager.ConnectionTimeout;
        }
Exemplo n.º 19
0
        private bool RaiseDisconnect(ConnectionMetadata metadata)
        {
            // The transport is currently dead but it could just be reconnecting 
            // so we to check it's last active time to see if it's over the disconnect
            // threshold
            TimeSpan elapsed = DateTime.UtcNow - metadata.LastMarked;

            // The threshold for disconnect is the transport threshold + (potential network issues)
            var threshold = metadata.Connection.DisconnectThreshold + _configurationManager.DisconnectTimeout;

            return elapsed >= threshold;
        }
Exemplo n.º 20
0
        private void CheckDisconnect(ConnectionMetadata metadata)
        {
            try
            {
                if (RaiseDisconnect(metadata))
                {
                    // Remove the connection from the list
                    RemoveConnection(metadata.Connection);

                    // Fire disconnect on the connection
                    metadata.Connection.Disconnect();
                }
            }
            catch (Exception ex)
            {
                // Swallow exceptions that might happen during disconnect
                _trace.Source.TraceInformation("TransportHeartBeat: Raising Disconnect failed: {0}", ex);
            }
        }
Exemplo n.º 21
0
        public static void RunClient(string hostName = "localhost", int port = 11111)
        {
            if (hostName == null)
            {
                throw new ArgumentNullException("Error: StandaloneClient.hostName null string");
            }
            if (hostName.Length == 0)
            {
                throw new ArgumentNullException("Error: StandaloneClient.hostName empty string");
            }
            if (port <= 0 || port > 65535)
            {
                throw new ArgumentOutOfRangeException("Error: StandaloneClient.port must be between 1 and 65535 (inclusive).");
            }

            bool      done     = false;
            TcpClient myClient = null;

            while (!done)
            {
                // ESTABLISH CONNECTION -------------------------------------------------------------------------------------
                hostName = GetIpAddress(hostName);
                if (hostName == "")
                {
                    Console.WriteLine("Unable to determine server IP address, try again?  (y,[n])");
                    if (Console.ReadLine().ToLower().Contains("y"))
                    {
                        continue;
                    }
                    else
                    {
                        done = true;
                    }
                    break;
                }
                port     = GetPort(port);
                myClient = GetClientConnection(hostName, port);
                if (myClient == null)
                {
                    Console.WriteLine("Unable to connect to server, try again?  (y,[n])");
                    if (Console.ReadLine().ToLower().Contains("y"))
                    {
                        continue;
                    }
                    else
                    {
                        done = true;
                    }
                    break;
                }
                Console.WriteLine("Connected to the Server!\n");
                Console.WriteLine("==================================================================\n");

                // SET UP ASYNC LISTENER FOR INPUT -------------------------------------------------------------------------------------

                ConnectionMetadata connection = new ConnectionMetadata(myClient.Client);
                myClient.Client.BeginReceive(connection.Buffer, 0, ConnectionMetadata.BufferSize, 0, new AsyncCallback(OnReceiveData), connection);

                // ESTABLISH STREAM -------------------------------------------------------------------------------------

                using NetworkStream SteamToServer = myClient.GetStream();
                {
                    byte[] data = new byte[ConnectionMetadata.BufferSize];
                    string userInput;

                    // MAIN OUTPUT LOOP -------------------------------------------------------------------------------------

                    while (!done)
                    {
                        userInput = Console.ReadLine();
                        try
                        {
                            switch (userInput)
                            {
                            case "disconnect":
                            case "dcon":
                            case "exit":
                            case "quit":
                                userInput = "/disconnect";
                                SteamToServer.Write(Encoding.ASCII.GetBytes(userInput), 0, userInput.Length);
                                Console.WriteLine("Disconnecting from server...");
                                done = true;
                                break;

                            default:
                                if (userInput == "")
                                {
                                    userInput = " ";
                                }
                                SteamToServer.Write(Encoding.ASCII.GetBytes(userInput), 0, userInput.Length);
                                break;
                            }
                        }
                        catch (IOException)
                        {
                            Console.Write("\n\nLost connection to server!\n\nReconnect? (y,[n])");
                            if (Console.ReadLine().ToLower().Contains("y"))
                            {
                                done = false;
                                break;
                            }
                            else
                            {
                                done = true;
                                break;
                            }
                        }
                        SteamToServer.Flush();
                    }
                }
            }
            if (myClient != null)
            {
                myClient.Close();
            }

            System.Console.WriteLine("Program gracefully terminated.");
        }
Exemplo n.º 22
0
        /// <summary>
        /// Adds a new connection to the list of tracked connections.
        /// </summary>
        /// <param name="connection">The connection to be added.</param>
        public bool AddConnection(ITrackingConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            var newMetadata = new ConnectionMetadata(connection);
            ConnectionMetadata oldMetadata = null;
            bool isNewConnection = true;

            _connections.AddOrUpdate(connection.ConnectionId, newMetadata, (key, old) =>
            {
                oldMetadata = old;
                return newMetadata;
            });

            if (oldMetadata != null)
            {
                Trace.TraceInformation("Connection exists. Closing previous connection. Old=({0}, {1}) New=({2})", oldMetadata.Connection.IsAlive, oldMetadata.Connection.Url, connection.Url);

                // Kick out the older connection. This should only happen when
                // a previous connection attempt fails on the client side (e.g. transport fallback).
                EndConnection(oldMetadata);
                // If we have old metadata this isn't a new connection
                isNewConnection = false;
            }
            else
            {
                Trace.TraceInformation("Connection is New=({0}).", connection.Url);
            }

            lock (_counterLock)
            {
                _counters.ConnectionsCurrent.RawValue = _connections.Count;
            }

            // Set the initial connection time
            newMetadata.Initial = DateTime.UtcNow;

            // Register for disconnect cancellation
            newMetadata.Registration = connection.CancellationToken.SafeRegister(OnConnectionEnded, newMetadata);

            return isNewConnection;
        }
Exemplo n.º 23
0
        private void OnConnectionEnded(ConnectionMetadata metadata)
        {
            Trace.TraceInformation("OnConnectionEnded({0})", metadata.Connection.ConnectionId);

            // Release the request
            metadata.Connection.ReleaseRequest();

            if (metadata.Registration != null)
            {
                metadata.Registration.Dispose();
            }
        }
Exemplo n.º 24
0
        private static void EndConnection(ConnectionMetadata metadata)
        {
            // End the connection
            metadata.Connection.End();

            // Dispose of the registration
            if (metadata.Registration != null)
            {
                metadata.Registration.Dispose();
            }
        }
Exemplo n.º 25
0
 public EmailService(ConnectionMetadata connectionMetadata, ILogger <EmailService> logger)
 {
     _connectionMetadata = connectionMetadata;
     _logger             = logger;
 }
Exemplo n.º 26
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networking hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    Trace.TraceEvent(TraceEventType.Verbose, 0, "KeepAlive(" + metadata.Connection.ConnectionId + ")");

                    // Ensure delegate continues to use the C# Compiler static delegate caching optimization.
                    metadata.Connection.KeepAlive().Catch((ex, state) => OnKeepAliveError(ex, state), Trace);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 27
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                RemoveConnection(metadata.Connection);

                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();

                // End the connection
                metadata.Connection.End();
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networking hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    Trace.TraceInformation("KeepAlive(" + metadata.Connection.ConnectionId + ")");

                    // If the keep alive send fails then kill the connection
                    metadata.Connection.KeepAlive()
                                       .Catch(ex =>
                                       {
                                           Trace.TraceInformation("Failed to send keep alive: " + ex.GetBaseException());

                                           RemoveConnection(metadata.Connection);

                                           metadata.Connection.End();
                                       });

                    metadata.UpdateKeepAlive(_configurationManager.KeepAlive);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 28
0
        private void CheckDisconnect(ConnectionMetadata metadata)
        {
            try
            {
                if (RaiseDisconnect(metadata))
                {
                    // Remove the connection from the list
                    RemoveConnection(metadata.Connection);

                    // Fire disconnect on the connection
                    metadata.Connection.Disconnect();
                }
            }
            catch (Exception ex)
            {
                // Swallow exceptions that might happen during disconnect
                Trace.TraceEvent(TraceEventType.Error, 0, "Raising Disconnect failed: {0}", ex);
            }
        }
Exemplo n.º 29
0
        public async Task TestGetTwin()
        {
            // Arrange
            const string Id                             = "id1";
            var          identity                       = Mock.Of <IIdentity>(i => i.Id == Id);
            var          twinMessageConverter           = new TwinMessageConverter();
            var          twinCollectionMessageConverter = new TwinCollectionMessageConverter();
            var          messageConverterProvider       = new MessageConverterProvider(
                new Dictionary <Type, IMessageConverter>()
            {
                { typeof(Message), new DeviceClientMessageConverter() },
                { typeof(Shared.Twin), twinMessageConverter },
                { typeof(TwinCollection), twinCollectionMessageConverter }
            });

            var edgeHubTokenProvider = new Mock <ITokenProvider>();

            var clientWatcher = new ClientWatcher();

            var clientProvider = new Mock <IClientProvider>();

            clientProvider.Setup(c => c.Create(identity, edgeHubTokenProvider.Object, It.IsAny <ITransportSettings[]>(), Option.None <string>()))
            .Returns(() => new ThrowingClient(clientWatcher, 3));

            var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>();

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(Id))
            .ReturnsAsync(
                Option.Some(
                    new ServiceIdentity(
                        Id,
                        "dummy",
                        new List <string>(),
                        new ServiceAuthentication(new SymmetricKeyAuthentication("foo", "bar")),
                        ServiceIdentityStatus.Enabled)));
            deviceScopeIdentitiesCache.Setup(d => d.GetAuthChain(It.Is <string>(i => i == Id)))
            .ReturnsAsync(Option.Some(Id));

            var edgeHubIdentity = Mock.Of <IIdentity>();

            ConnectionMetadata connectionMetadata = new ConnectionMetadata("edgeProdInfo");
            var metadataStore = new Mock <IMetadataStore>();

            metadataStore.Setup(p => p.GetMetadata(Id))
            .ReturnsAsync(connectionMetadata);

            var identityProvider = new Mock <IIdentityProvider>();

            identityProvider.Setup(i => i.Create(Id)).Returns(identity);

            var credentialsCache = new Mock <ICredentialsCache>();
            var edgeHub          = new Mock <IEdgeHub>();

            var connectionProvider = new CloudConnectionProvider(
                messageConverterProvider,
                1,
                clientProvider.Object,
                Option.None <UpstreamProtocol>(),
                edgeHubTokenProvider.Object,
                deviceScopeIdentitiesCache.Object,
                credentialsCache.Object,
                edgeHubIdentity,
                TimeSpan.FromMinutes(10),
                false,
                TimeSpan.FromMinutes(10),
                false,
                Option.None <IWebProxy>(),
                metadataStore.Object,
                true);

            connectionProvider.BindEdgeHub(edgeHub.Object);

            var deviceConnectivityManager = Mock.Of <IDeviceConnectivityManager>();
            var connectionManager         = new ConnectionManager(connectionProvider, credentialsCache.Object, identityProvider.Object, deviceConnectivityManager);

            // Act
            Option <ICloudProxy> cloudProxyOption = await connectionManager.GetCloudConnection(Id);

            // Assert
            Assert.True(cloudProxyOption.HasValue);
            ICloudProxy cloudProxy = cloudProxyOption.OrDefault();

            Assert.True(cloudProxy.IsActive);

            // Act
            await RunGetTwin(cloudProxy, 10);

            // Assert
            Assert.Equal(5, clientWatcher.OpenAsyncCount);
            Assert.True(cloudProxy.IsActive);
            Assert.Equal(10, clientWatcher.GetTwinCount);
        }
Exemplo n.º 30
0
        private bool RaiseKeepAlive(ConnectionMetadata metadata)
        {
            var keepAlive = _configurationManager.KeepAlive;

            // Don't raise keep alive if it's set to 0 or the transport doesn't support
            // keep alive
            if (keepAlive == null || !metadata.Connection.SupportsKeepAlive)
            {
                return false;
            }

            // Raise keep alive if the keep alive value has passed
            return _heartbeatCount % (ulong)ConfigurationExtensions.HeartBeatsPerKeepAlive == 0;
        }
Exemplo n.º 31
0
        private void CheckTimeoutAndKeepAlive(ConnectionMetadata metadata)
        {
            if (RaiseTimeout(metadata))
            {
                // If we're past the expiration time then just timeout the connection
                metadata.Connection.Timeout();

                RemoveConnection(metadata.Connection);
            }
            else
            {
                // The connection is still alive so we need to keep it alive with a server side "ping".
                // This is for scenarios where networing hardware (proxies, loadbalancers) get in the way
                // of us handling timeout's or disconnects gracefully
                if (RaiseKeepAlive(metadata))
                {
                    metadata.Connection.KeepAlive().Catch();
                    metadata.UpdateKeepAlive(_configurationManager.KeepAlive);
                }

                MarkConnection(metadata.Connection);
            }
        }
Exemplo n.º 32
0
        private static void EndConnection(ConnectionMetadata metadata, bool disposeRegistration = true)
        {
            if (disposeRegistration)
            {
                // Dispose of the registration
                if (metadata.Registration != null)
                {
                    metadata.Registration.Dispose();
                }
            }

            // End the connection
            metadata.Connection.End();
        }
Exemplo n.º 33
0
        private bool RaiseKeepAlive(ConnectionMetadata metadata)
        {
            TimeSpan? keepAlive = _configurationManager.KeepAlive;

            if (keepAlive == null)
            {
                return false;
            }

            // Raise keep alive if the keep alive value has passed
            return DateTime.UtcNow >= metadata.KeepAliveTime;
        }
Exemplo n.º 34
0
        public async Task <Try <ICloudConnection> > Connect(IIdentity identity, Action <string, CloudConnectionStatus> connectionStatusChangedHandler)
        {
            Preconditions.CheckNotNull(identity, nameof(identity));

            try
            {
                var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), identity.Id);
                Option <ServiceIdentity> serviceIdentity = (await this.deviceScopeIdentitiesCache.GetServiceIdentity(identity.Id))
                                                           .Filter(s => s.Status == ServiceIdentityStatus.Enabled);

                string authChain = string.Empty;
                if (this.nestedEdgeEnabled)
                {
                    Option <string> authChainMaybe = await this.deviceScopeIdentitiesCache.GetAuthChain(identity.Id);

                    authChain = authChainMaybe.Expect(() => new InvalidOperationException($"No auth chain for the client identity: {identity.Id}"));
                }

                ITransportSettings[] transportSettings = GetTransportSettings(
                    this.upstreamProtocol,
                    this.connectionPoolSize,
                    this.proxy,
                    this.useServerHeartbeat,
                    authChain);

                return(await serviceIdentity
                       .Map(
                           async si =>
                {
                    Events.CreatingCloudConnectionOnBehalfOf(identity);
                    ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(identity.Id);
                    string productInfo = connectionMetadata.EdgeProductInfo;
                    Option <string> modelId = connectionMetadata.ModelId;
                    ICloudConnection cc = await CloudConnection.Create(
                        identity,
                        connectionStatusChangedHandler,
                        transportSettings,
                        this.messageConverterProvider,
                        this.clientProvider,
                        cloudListener,
                        this.edgeHubTokenProvider,
                        this.idleTimeout,
                        this.closeOnIdleTimeout,
                        this.operationTimeout,
                        productInfo,
                        modelId);
                    Events.SuccessCreatingCloudConnection(identity);
                    return Try.Success(cc);
                })
                       .GetOrElse(
                           async() =>
                {
                    Events.ServiceIdentityNotFound(identity);
                    Option <IClientCredentials> clientCredentials = await this.credentialsCache.Get(identity);
                    return await clientCredentials
                    .Map(cc => this.Connect(cc, connectionStatusChangedHandler))
                    .GetOrElse(() => throw new InvalidOperationException($"Unable to find identity {identity.Id} in device scopes cache or credentials cache"));
                }));
            }
            catch (Exception ex)
            {
                Events.ErrorCreatingCloudConnection(identity, ex);
                return(Try <ICloudConnection> .Failure(ex));
            }
        }
Exemplo n.º 35
0
        private void CheckDisconnect(ConnectionMetadata metadata)
        {
            try
            {
                if (RaiseDisconnect(metadata))
                {
                    // Remove the connection from the list
                    RemoveConnection(metadata.Connection);

                    // Fire disconnect on the connection
                    metadata.Connection.Disconnect();
                }
            }
            catch (Exception ex)
            {
                // Swallow exceptions that might happen during disconnect
                Logger.LogError(String.Format("Raising Disconnect failed: {0}", ex));
            }
        }
Exemplo n.º 36
0
        public async Task <Try <ICloudConnection> > Connect(IClientCredentials clientCredentials, Action <string, CloudConnectionStatus> connectionStatusChangedHandler)
        {
            Preconditions.CheckNotNull(clientCredentials, nameof(clientCredentials));

            try
            {
                Events.CreatingCloudConnectionUsingClientCredentials(clientCredentials);
                var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), clientCredentials.Identity.Id);
                ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(clientCredentials.Identity.Id);

                string          productInfo = connectionMetadata.EdgeProductInfo;
                Option <string> modelId     = clientCredentials.ModelId.HasValue ? clientCredentials.ModelId : connectionMetadata.ModelId;
                string          authChain   = string.Empty;
                if (this.nestedEdgeEnabled)
                {
                    Option <string> authChainMaybe = await this.deviceScopeIdentitiesCache.GetAuthChain(clientCredentials.Identity.Id);

                    // It's possible to have no auth-chain for out-of-scope leaf devices connecting through
                    // us as a gateway. In this case we let the upstream connection happen anyways, as any
                    // unauthorized attempt here would be denied by IoTHub.
                    authChain = authChainMaybe.OrDefault();
                }

                // Get the transport settings
                ITransportSettings[] transportSettings = GetTransportSettings(
                    this.upstreamProtocol,
                    this.connectionPoolSize,
                    this.proxy,
                    this.useServerHeartbeat,
                    authChain);

                if (this.edgeHubIdentity.Id.Equals(clientCredentials.Identity.Id))
                {
                    ICloudConnection cc = await CloudConnection.Create(
                        clientCredentials.Identity,
                        connectionStatusChangedHandler,
                        transportSettings,
                        this.messageConverterProvider,
                        this.clientProvider,
                        cloudListener,
                        this.edgeHubTokenProvider,
                        this.idleTimeout,
                        this.closeOnIdleTimeout,
                        this.operationTimeout,
                        productInfo,
                        modelId);

                    Events.SuccessCreatingCloudConnection(clientCredentials.Identity);
                    return(Try.Success(cc));
                }
                else if (clientCredentials is ITokenCredentials clientTokenCredentails)
                {
                    ICloudConnection cc = await ClientTokenCloudConnection.Create(
                        clientTokenCredentails,
                        connectionStatusChangedHandler,
                        transportSettings,
                        this.messageConverterProvider,
                        this.clientProvider,
                        cloudListener,
                        this.idleTimeout,
                        this.closeOnIdleTimeout,
                        this.operationTimeout,
                        productInfo,
                        modelId);

                    Events.SuccessCreatingCloudConnection(clientCredentials.Identity);
                    return(Try.Success(cc));
                }
                else
                {
                    throw new InvalidOperationException($"Cannot connect using client credentials of type {clientCredentials.AuthenticationType} for identity {clientCredentials.Identity.Id}");
                }
            }
            catch (Exception ex)
            {
                Events.ErrorCreatingCloudConnection(clientCredentials.Identity, ex);
                return(Try <ICloudConnection> .Failure(ex));
            }
        }
Exemplo n.º 37
0
        private void CheckDisconnect(ConnectionMetadata metadata)
        {
            try
            {
                if (RaiseDisconnect(metadata))
                {
                    // Remove the connection from the list
                    RemoveConnection(metadata.Connection);

                    // Fire disconnect on the connection
                    metadata.Connection.Disconnect();
                }
            }
            catch
            {
                // Swallow exceptions that might happen during disconnect
            }
        }