Exemple #1
0
        async Task HandleFailedConnectedPeerAsync(Exception e, MessageRelayConnection connection)
        {
            if (connection == null)  // there was no connection available
            {
                return;
            }

            if (e == null) // explicit disconnect
            {
                Debug.Assert(connection.ConnectionState.HasFlag(ConnectedPeer.State.Disconnecting));
                Debug.Assert(connection.ConnectionState.HasFlag(ConnectedPeer.State.Disposed));
            }
            else
            {
                Debug.Assert(connection.ConnectionState.HasFlag(ConnectedPeer.State.Failed));
                Debug.Assert(connection.ConnectionState.HasFlag(ConnectedPeer.State.Disposed));
            }


            if (PeerManager.ShouldRecordError(e, !this.cancellation.Token.IsCancellationRequested, connection.ToString(), this.logger))
            {
                // set these properties on the loaded connection instance and not only in the repository, so that we can
                // use the cached collection of Peer objects
                connection.MessageRelayRecord.LastErrorUtc = DateTime.UtcNow;
                await this.messageRelayRecords.UpdatePeerLastError(connection.MessageRelayRecord.Id,
                                                                   connection.MessageRelayRecord.LastErrorUtc);
            }

            this.connections.TryRemove(connection.MessageRelayRecord.Id, out _);
        }
Exemple #2
0
        public async Task <MessageRelayConnection> SelectNextConnectionAsync()
        {
            IReadOnlyList <MessageRelayRecord> allRecords = await this.messageRelayRecords.GetAllMessageRelayRecordsAsync();


            if (allRecords.Count == 0)
            {
                this.logger.LogWarning("No relay addresses in the store - can't select a connection candidate!");
                return(null);
            }

            // peers, shortest success ago first
            var hottestRecords = allRecords
                                 .Where(x => !IsExcluded(x))                                    // e.g. if we are already connected, or the last error is less than a certain time ago
                                 .OrderBy(x => DateTimeOffset.UtcNow - x.LastSeenUtc)           // then, try the best candidates first
                                 .ThenByDescending(x => DateTimeOffset.UtcNow - x.LastErrorUtc) // then, try the candidates where the last error is longest ago
                                 .ToList();

            if (hottestRecords.Count == 0)
            {
                this.logger.LogDebug("After applying the filtering rules, no connection candidates remain for selection.");
                return(null);
            }

            MessageRelayRecord messageRelayRecord = hottestRecords[0];

            this.logger.LogDebug($"Selected connection candidate {messageRelayRecord}, last seen {DateTimeOffset.UtcNow - messageRelayRecord.LastSeenUtc} ago, last error {DateTimeOffset.UtcNow - messageRelayRecord.LastErrorUtc} ago.");
            var  messageRelayConnection = new MessageRelayConnection(messageRelayRecord, this.cancellation.Token);
            bool addSuccess             = this.connections.TryAdd(messageRelayRecord.Id, messageRelayConnection);

            Debug.Assert(addSuccess, $"Bug: Peer {messageRelayRecord} was already in the ConnectedPeers dictionary - that should not happen.");
            return(messageRelayConnection);
        }
Exemple #3
0
        async Task ConnectAndRunAsync(MessageRelayConnection createdInstance)
        {
            var connectedInstance = await CreateConnectedPeerBlockingOrThrowAsync(createdInstance);

            if (connectedInstance != null)
            {
                this.logger.LogInformation($"Successfully created connected peer {createdInstance}, loading off to new thread.");
                //await RunNetworkPeer(createdInstance);
            }
        }
Exemple #4
0
        async Task <MessageRelayConnection> CreateConnectedPeerBlockingOrThrowAsync(MessageRelayConnection connection)
        {
            try
            {
                connection.ConnectionState |= ConnectedPeer.State.Connecting;
                await connection.ConnectAsync();

                connection.ConnectionState &= ~ConnectedPeer.State.Connecting;
                connection.ConnectionState |= ConnectedPeer.State.Connected;

                return(connection);
            }
            catch (Exception e)
            {
                await HandleFailedConnectedPeerAsync(e, connection);

                return(null);
            }
        }
Exemple #5
0
        public async Task <List <IEnvelope> > SendRequestAsync(byte[] request)
        {
            var response = new List <IEnvelope>();

            MessageRelayConnection currentConnection = null;

            try
            {
                await this.semaphore.WaitAsync(); // this definitely deadlocks sometimes

                currentConnection = GetRandomConnection();

                if (currentConnection == null)
                {
                    throw new MessageRelayConnectionException("No connection(s) available, please retry later.", null)
                          {
                              NoConnectionAvailable = true
                          }
                }
                ;

                await currentConnection.SendAsync(request);

                response.AddRange(await currentConnection.ReceiveAsync());
            }
            catch (Exception e)
            {
                await HandleFailedConnectedPeerAsync(e, currentConnection);

                throw;
            }
            finally
            {
                this.semaphore.Release();
            }
            return(response);
        }