/// <summary>
        ///   Adds a new connection.
        /// </summary>
        /// <param name="connection">
        ///   The <see cref="PeerConnection"/> to add.
        /// </param>
        /// <returns>
        ///   The connection that should be used.
        /// </returns>
        /// <remarks>
        ///   If a connection already exists to the peer, the specified
        ///   <paramref name="connection"/> is closed and existing connection
        ///   is returned.
        /// </remarks>
        public PeerConnection Add(PeerConnection connection)
        {
            if (connection == null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            if (connection.RemotePeer == null)
            {
                throw new ArgumentNullException(nameof(connection.RemotePeer));
            }

            if (connection.RemotePeer.Id == null)
            {
                throw new ArgumentNullException(nameof(connection.RemotePeer.Id));
            }

            _connections.AddOrUpdate(
                Key(connection.RemotePeer),
                key => new List <PeerConnection> {
                connection
            },
                (key, conns) =>
            {
                if (!conns.Contains(connection))
                {
                    conns.Add(connection);
                }

                return(conns);
            }
                );

            if (connection.RemotePeer.ConnectedAddress == null)
            {
                connection.RemotePeer.ConnectedAddress = connection.RemoteAddress;
            }

            connection.Closed += (s, e) => Remove(e);
            return(connection);
        }
        /// <summary>
        ///   Remove a connection.
        /// </summary>
        /// <param name="connection">
        ///   The <see cref="PeerConnection"/> to remove.
        /// </param>
        /// <returns>
        ///   <b>true</b> if the connection was removed; otherwise, <b>false</b>.
        /// </returns>
        /// <remarks>
        ///    The <paramref name="connection"/> is removed from the list of
        ///    connections and is closed.
        /// </remarks>
        public bool Remove(PeerConnection connection)
        {
            if (connection == null)
            {
                return(false);
            }

            if (!_connections.TryGetValue(Key(connection.RemotePeer), out var originalConns))
            {
                connection.Dispose();
                return(false);
            }

            if (!originalConns.Contains(connection))
            {
                connection.Dispose();
                return(false);
            }

            var newConns = new List <PeerConnection>();

            newConns.AddRange(originalConns.Where(c => c != connection));
            _connections.TryUpdate(Key(connection.RemotePeer), newConns, originalConns);

            connection.Dispose();
            if (newConns.Count > 0)
            {
                var last = newConns.Last();
                last.RemotePeer.ConnectedAddress = last.RemoteAddress;
            }
            else
            {
                connection.RemotePeer.ConnectedAddress = null;
                PeerDisconnected?.Invoke(this, connection.RemotePeer.Id);
            }

            return(true);
        }
Exemple #3
0
 /// <summary>
 ///   Is invoked by the <see cref="SwarmService"/> when a peer is connected to.
 /// </summary>
 private void Swarm_ConnectionEstablished(object sender, PeerConnection connection)
 {
     SetReachable(connection.RemotePeer);
 }