コード例 #1
0
        public void Disposing()
        {
            var closeCount = 0;
            var stream     = new MemoryStream();
            var connection = new PeerConnection {
                Stream = stream
            };

            connection.Closed += (s, e) =>
            {
                ++closeCount;
            };
            Assert.IsTrue(connection.IsActive);
            Assert.IsNotNull(connection.Stream);

            connection.Dispose();
            Assert.IsFalse(connection.IsActive);
            Assert.IsNull(connection.Stream);

            // Can be disposed multiple times.
            connection.Dispose();

            Assert.IsFalse(connection.IsActive);
            Assert.AreEqual(1, closeCount);
        }
コード例 #2
0
        /// <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 List <PeerConnection> 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;
            }
            return(true);
        }
コード例 #3
0
        public void PeerDisconnectedEvent_ConnectionClose()
        {
            int gotEvent = 0;
            var manager  = new ConnectionManager();

            manager.PeerDisconnected += (s, e) => gotEvent += 1;
            var peerA = new Peer {
                Id = aId
            };
            var a = new PeerConnection {
                RemotePeer = peerA, Stream = Stream.Null
            };

            manager.Add(a);
            a.Dispose();
            Assert.AreEqual(1, gotEvent);
        }
コード例 #4
0
ファイル: Swarm.cs プロジェクト: hanabi1224/peer-talk
        /// <summary>
        ///   Establish a duplex stream between the local and remote peer.
        /// </summary>
        /// <param name="remote"></param>
        /// <param name="addrs"></param>
        /// <param name="cancel"></param>
        /// <returns></returns>
        async Task <PeerConnection> Dial(Peer remote, IEnumerable <MultiAddress> addrs, CancellationToken cancel)
        {
            log.Debug($"Dialing {remote}");

            if (remote == LocalPeer)
            {
                throw new Exception("Cannot dial self.");
            }

            // If no addresses, then ask peer routing.
            if (Router != null && addrs.Count() == 0)
            {
                var found = await Router.FindPeerAsync(remote.Id, cancel).ConfigureAwait(false);

                addrs            = found.Addresses;
                remote.Addresses = addrs;
            }

            // Get the addresses we can use to dial the remote.
            var possibleAddresses = (await Task.WhenAll(addrs.Select(a => a.ResolveAsync(cancel))).ConfigureAwait(false))
                                    .SelectMany(a => a)
                                    .Select(a => a.WithPeerId(remote.Id))
                                    .Distinct()
                                    .ToArray();

            // TODO: filter out self addresses and others.
            if (possibleAddresses.Length == 0)
            {
                throw new Exception($"{remote} has no known address.");
            }

            // Try the various addresses in parallel.  The first one to complete wins.
            PeerConnection connection = null;

            try
            {
                using (var timeout = new CancellationTokenSource(TransportConnectionTimeout))
                    using (var cts = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancel))
                    {
                        var attempts = possibleAddresses
                                       .Select(a => DialAsync(remote, a, cts.Token));
                        connection = await TaskHelper.WhenAnyResult(attempts, cts.Token).ConfigureAwait(false);

                        cts.Cancel(); // stop other dialing tasks.
                    }
            }
            catch (Exception e)
            {
                var attemped = string.Join(", ", possibleAddresses.Select(a => a.ToString()));
                log.Trace($"Cannot dial {attemped}");
                throw new Exception($"Cannot dial {remote}.", e);
            }

            // Do the connection handshake.
            try
            {
                MountProtocols(connection);
                IEncryptionProtocol[] security = null;
                lock (protocols)
                {
                    security = protocols.OfType <IEncryptionProtocol>().ToArray();
                }
                await connection.InitiateAsync(security, cancel).ConfigureAwait(false);

                await connection.MuxerEstablished.Task.ConfigureAwait(false);

                Identify1 identify = null;
                lock (protocols)
                {
                    identify = protocols.OfType <Identify1>().First();
                }
                await identify.GetRemotePeer(connection, cancel).ConfigureAwait(false);
            }
            catch (Exception)
            {
                connection.Dispose();
                throw;
            }

            var actual = Manager.Add(connection);

            if (actual == connection)
            {
                ConnectionEstablished?.Invoke(this, connection);
            }

            return(actual);
        }