Example #1
0
        /// <inheritdoc/>
        public async Task RespondToHandShakeAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            this.logger.LogTrace("()");

            using (var listener = new NetworkPeerListener(this))
            {
                this.logger.LogTrace("Responding to handshake with my version.");
                await this.SendMessageAsync(this.MyVersion, cancellationToken).ConfigureAwait(false);

                this.logger.LogTrace("Waiting for version acknowledgement or rejection message.");

                while (this.State != NetworkPeerState.HandShaked)
                {
                    Payload payload = await listener.ReceivePayloadAsync <Payload>(cancellationToken).ConfigureAwait(false);

                    switch (payload)
                    {
                    case RejectPayload rejectPayload:
                        this.logger.LogTrace("Version rejected: code {0}, reason '{1}'.", rejectPayload.Code, rejectPayload.Reason);
                        this.logger.LogTrace("(-)[VERSION_REJECTED]");
                        throw new ProtocolException("Version rejected " + rejectPayload.Code + ": " + rejectPayload.Reason);

                    case VerAckPayload verAckPayload:
                        this.logger.LogTrace("Sending version acknowledgement.");
                        await this.SendMessageAsync(new VerAckPayload(), cancellationToken).ConfigureAwait(false);

                        await this.SetStateAsync(NetworkPeerState.HandShaked).ConfigureAwait(false);

                        break;
                    }
                }
            }

            this.logger.LogTrace("(-)");
        }
Example #2
0
        /// <inheritdoc/>
        public async Task VersionHandshakeAsync(NetworkPeerRequirement requirements, CancellationToken cancellationToken)
        {
            this.logger.LogTrace("({0}.{1}:{2})", nameof(requirements), nameof(requirements.RequiredServices), requirements?.RequiredServices);

            requirements = requirements ?? new NetworkPeerRequirement();
            using (var listener = new NetworkPeerListener(this))
            {
                this.logger.LogTrace("Sending my version.");
                await this.SendMessageAsync(this.MyVersion, cancellationToken).ConfigureAwait(false);

                this.logger.LogTrace("Waiting for version or rejection message.");
                bool versionReceived = false;
                bool verAckReceived  = false;
                while (!versionReceived || !verAckReceived)
                {
                    Payload payload = await listener.ReceivePayloadAsync <Payload>(cancellationToken).ConfigureAwait(false);

                    switch (payload)
                    {
                    case RejectPayload rejectPayload:
                        this.logger.LogTrace("(-)[HANDSHAKE_REJECTED]");
                        throw new ProtocolException("Handshake rejected: " + rejectPayload.Reason);

                    case VersionPayload versionPayload:
                        versionReceived = true;

                        this.PeerVersion = versionPayload;
                        if (!versionPayload.AddressReceiver.Address.Equals(this.MyVersion.AddressFrom.Address))
                        {
                            this.logger.LogDebug("Different external address detected by the node '{0}' instead of '{1}'.", versionPayload.AddressReceiver.Address, this.MyVersion.AddressFrom.Address);
                        }

                        if (versionPayload.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                        {
                            this.logger.LogDebug("Outdated version {0} received, disconnecting peer.", versionPayload.Version);

                            this.Disconnect("Outdated version");
                            this.logger.LogTrace("(-)[OUTDATED]");
                            return;
                        }

                        if (!requirements.Check(versionPayload))
                        {
                            this.logger.LogTrace("(-)[UNSUPPORTED_REQUIREMENTS]");
                            this.Disconnect("The peer does not support the required services requirement");
                            return;
                        }

                        this.logger.LogTrace("Sending version acknowledgement.");
                        await this.SendMessageAsync(new VerAckPayload(), cancellationToken).ConfigureAwait(false);

                        break;

                    case VerAckPayload verAckPayload:
                        verAckReceived = true;
                        break;
                    }
                }

                await this.SetStateAsync(NetworkPeerState.HandShaked).ConfigureAwait(false);

                if (this.advertize && this.MyVersion.AddressFrom.Address.IsRoutable(true))
                {
                    var addrPayload = new AddrPayload
                                      (
                        new NetworkAddress(this.MyVersion.AddressFrom)
                    {
                        Time = this.dateTimeProvider.GetTimeOffset()
                    }
                                      );

                    await this.SendMessageAsync(addrPayload, cancellationToken).ConfigureAwait(false);
                }
            }

            this.logger.LogTrace("(-)");
        }