Exemple #1
0
        async Task <PeerConnection> DialAsync(Peer remote, MultiAddress addr, CancellationToken cancel)
        {
            // TODO: HACK: Currenty only the ipfs/p2p is supported.
            // short circuit to make life faster.
            if (addr.Protocols.Count != 3 ||
                !(addr.Protocols[2].Name == "ipfs" || addr.Protocols[2].Name == "p2p"))
            {
                throw new Exception($"Cannnot dial; unknown protocol in '{addr}'.");
            }

            // Establish the transport stream.
            Stream stream = null;

            foreach (var protocol in addr.Protocols)
            {
                cancel.ThrowIfCancellationRequested();
                if (TransportRegistry.Transports.TryGetValue(protocol.Name, out Func <IPeerTransport> transport))
                {
                    stream = await transport().ConnectAsync(addr, cancel).ConfigureAwait(false);

                    if (cancel.IsCancellationRequested)
                    {
                        stream?.Dispose();
                        continue;
                    }
                    break;
                }
            }
            if (stream == null)
            {
                throw new Exception("Missing a known transport protocol name.");
            }

            // Build the connection.
            var connection = new PeerConnection
            {
                IsIncoming = false,
                LocalPeer  = LocalPeer,
                // TODO: LocalAddress
                LocalPeerKey  = LocalPeerKey,
                RemotePeer    = remote,
                RemoteAddress = addr,
                Stream        = stream
            };

            // Are we communicating to a private network?
            if (NetworkProtector != null)
            {
                connection.Stream = await NetworkProtector.ProtectAsync(connection).ConfigureAwait(false);
            }


            return(connection);
        }
Exemple #2
0
        /// <summary>
        ///   Called when a remote peer is connecting to the local peer.
        /// </summary>
        /// <param name="stream">
        ///   The stream to the remote peer.
        /// </param>
        /// <param name="local">
        ///   The local peer's address.
        /// </param>
        /// <param name="remote">
        ///   The remote peer's address.
        /// </param>
        /// <remarks>
        ///   Establishes the protocols of the connection.  Any exception is simply
        ///   logged as warning.
        /// </remarks>
        async void OnRemoteConnect(Stream stream, MultiAddress local, MultiAddress remote)
        {
            // If the remote is already trying to establish a connection, then we
            // can just refuse this one.
            if (!pendingRemoteConnections.TryAdd(remote, null))
            {
                log.Debug($"Duplicate remote connection from {remote}");
                stream.Dispose();
                return;
            }

            try
            {
                log.Debug($"{LocalPeer.Id} got remote connection");
                log.Debug("local " + local);
                log.Debug("remote " + remote);

                // TODO: Check the policies

                var connection = new PeerConnection
                {
                    IsIncoming    = true,
                    LocalPeer     = LocalPeer,
                    LocalAddress  = local,
                    LocalPeerKey  = LocalPeerKey,
                    RemoteAddress = remote,
                    Stream        = stream
                };

                // Are we communicating to a private network?
                if (NetworkProtector != null)
                {
                    connection.Stream = await NetworkProtector.ProtectAsync(connection).ConfigureAwait(false);
                }

                // Mount the protocols.
                MountProtocols(connection);

                // Start the handshake
                // TODO: Isn't connection cancel token required.
                connection.ReadMessages(default(CancellationToken));

                // Wait for security to be established.
                await connection.SecurityEstablished.Task.ConfigureAwait(false);

                // TODO: Maybe connection.LocalPeerKey = null;

                // Wait for the handshake to complete.
                var muxer = await connection.MuxerEstablished.Task;

                // Need details on the remote peer.
                Identify1 identify = null;
                lock (protocols)
                {
                    identify = protocols.OfType <Identify1>().First();
                }
                connection.RemotePeer = await identify.GetRemotePeer(connection, default(CancellationToken)).ConfigureAwait(false);

                connection.RemotePeer    = RegisterPeer(connection.RemotePeer);
                connection.RemoteAddress = new MultiAddress($"{remote}/ipfs/{connection.RemotePeer.Id}");
                var actual = Manager.Add(connection);
                if (actual == connection)
                {
                    ConnectionEstablished?.Invoke(this, connection);
                }
            }
            catch (Exception e)
            {
                log.Warn("Remote connect failed", e);
                try
                {
                    stream.Dispose();
                }
                catch (Exception)
                {
                    // eat it.
                }
            }
            finally
            {
                pendingRemoteConnections.TryRemove(remote, out object _);
            }
        }