Esempio n. 1
0
        internal void SendConnect(TimeSpan now)
        {
            Peer.AssertIsOnLibraryThread();

            int preAllocate = 13 + _peerConfiguration.AppIdentifier.Length;

            preAllocate += LocalHailMessage == null ? 0 : LocalHailMessage.ByteLength;

            NetOutgoingMessage om = Peer.CreateMessage(preAllocate);

            om._messageType = NetMessageType.Connect;
            om.Write(_peerConfiguration.AppIdentifier);
            om.Write(Peer.UniqueIdentifier);
            om.Write(now);

            WriteLocalHail(om);

            Peer.SendLibraryMessage(om, RemoteEndPoint);

            _connectRequested      = false;
            _lastHandshakeSendTime = now;
            _handshakeAttempts++;

            if (_handshakeAttempts > 1)
            {
                Peer.LogDebug(new NetLogMessage(NetLogCode.ResendingConnect));
            }
            SetStatus(NetConnectionStatus.InitiatedConnect);
        }
Esempio n. 2
0
        internal void SendDisconnect(NetOutgoingMessage?message, bool onLibraryThread)
        {
            if (onLibraryThread)
            {
                Peer.AssertIsOnLibraryThread();
            }

            if (message == null)
            {
                message = Peer.CreateMessage();
                message._messageType = NetMessageType.Disconnect;
            }

            if (onLibraryThread)
            {
                Peer.SendLibraryMessage(message, RemoteEndPoint);
            }
            else
            {
                Peer.UnsentUnconnectedMessages.Enqueue((RemoteEndPoint, message));
            }
        }
Esempio n. 3
0
        internal void ExecuteDisconnect(NetOutgoingMessage?reason, bool sendByeMessage)
        {
            Peer.AssertIsOnLibraryThread();

            // clear send queues
            for (int i = 0; i < _sendChannels.Length; i++)
            {
                NetSenderChannel?channel = _sendChannels[i];
                if (channel != null)
                {
                    channel.Reset();
                }
            }

            if (sendByeMessage)
            {
                SendDisconnect(reason, true);
            }

            if (Status == NetConnectionStatus.ReceivedInitiation)
            {
                // nothing much has happened yet; no need to send disconnected status message
                Status = NetConnectionStatus.Disconnected;
            }
            else
            {
                SetStatus(NetConnectionStatus.Disconnected, reason);
            }

            // in case we're still in handshake
            Peer.Handshakes.TryRemove(RemoteEndPoint, out _);

            _disconnectRequested = false;
            _connectRequested    = false;
            _handshakeAttempts   = 0;
        }
Esempio n. 4
0
        internal void SendConnectResponse(TimeSpan now, bool onLibraryThread)
        {
            if (onLibraryThread)
            {
                Peer.AssertIsOnLibraryThread();
            }

            NetOutgoingMessage om = Peer.CreateMessage(
                _peerConfiguration.AppIdentifier.Length + 13 +
                (LocalHailMessage == null ? 0 : LocalHailMessage.ByteLength));

            om._messageType = NetMessageType.ConnectResponse;
            om.Write(_peerConfiguration.AppIdentifier);
            om.Write(Peer.UniqueIdentifier);
            om.Write(now);

            WriteLocalHail(om);

            if (onLibraryThread)
            {
                Peer.SendLibraryMessage(om, RemoteEndPoint);
            }
            else
            {
                Peer.UnsentUnconnectedMessages.Enqueue((RemoteEndPoint, om));
            }

            _lastHandshakeSendTime = now;
            _handshakeAttempts++;

            if (_handshakeAttempts > 1)
            {
                Peer.LogDebug(new NetLogMessage(NetLogCode.ResendingRespondedConnect));
            }
            SetStatus(NetConnectionStatus.RespondedConnect);
        }
Esempio n. 5
0
        internal void ReceivedHandshake(TimeSpan now, NetMessageType type, int offset, int payloadLength)
        {
            Peer.AssertIsOnLibraryThread();

            switch (type)
            {
            case NetMessageType.Connect:
                if (Status == NetConnectionStatus.ReceivedInitiation)
                {
                    // Whee! Server full has already been checked
                    var(success, hail, hailLength) = ValidateHandshakeData(offset, payloadLength);
                    if (success)
                    {
                        if (hail != null)
                        {
                            RemoteHailMessage = Peer.CreateIncomingMessage(NetIncomingMessageType.Data);
                            RemoteHailMessage.SetBuffer(hail, true);
                            RemoteHailMessage.ByteLength = hailLength;
                        }
                        else
                        {
                            RemoteHailMessage = null;
                        }

                        if (_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionApproval))
                        {
                            // ok, let's not add connection just yet
                            var appMsg = Peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval);

                            appMsg.ReceiveTime      = now;
                            appMsg.SenderConnection = this;
                            appMsg.SenderEndPoint   = RemoteEndPoint;

                            if (RemoteHailMessage != null)
                            {
                                appMsg.Write(RemoteHailMessage.GetBuffer().AsSpan(0, RemoteHailMessage.ByteLength));
                            }

                            SetStatus(NetConnectionStatus.RespondedAwaitingApproval);
                            Peer.ReleaseMessage(appMsg);
                            return;
                        }

                        SendConnectResponse(now, true);
                    }
                    return;
                }
                if (Status == NetConnectionStatus.RespondedAwaitingApproval)
                {
                    Peer.LogWarning(new NetLogMessage(NetLogCode.IgnoringMultipleConnects, endPoint: this));
                    return;
                }
                if (Status == NetConnectionStatus.RespondedConnect)
                {
                    // our ConnectResponse must have been lost
                    SendConnectResponse(now, true);
                    return;
                }
                Peer.LogDebug(NetLogMessage.FromValues(NetLogCode.UnhandledConnect, endPoint: this, value: (int)Status));
                break;

            case NetMessageType.ConnectResponse:
                HandleConnectResponse(offset, payloadLength);
                break;

            case NetMessageType.ConnectionEstablished:
                switch (Status)
                {
                case NetConnectionStatus.Connected:
                    // ok...
                    break;

                case NetConnectionStatus.Disconnected:
                case NetConnectionStatus.Disconnecting:
                case NetConnectionStatus.None:
                    // too bad, almost made it
                    break;

                case NetConnectionStatus.ReceivedInitiation:
                    // uh, a little premature... ignore
                    break;

                case NetConnectionStatus.InitiatedConnect:
                    // weird, should have been RespondedConnect...
                    break;

                case NetConnectionStatus.RespondedConnect:
                    // awesome
                    NetIncomingMessage msg = Peer.SetupReadHelperMessage(offset, payloadLength);
                    InitializeRemoteTimeOffset(msg.ReadTimeSpan());

                    Peer.AcceptConnection(this);
                    InitializePing();
                    SetStatus(NetConnectionStatus.Connected);
                    return;
                }
                break;

            case NetMessageType.InvalidHandshake:
            case NetMessageType.WrongAppIdentifier:
            case NetMessageType.ConnectTimedOut:
            case NetMessageType.TimedOut:
            case NetMessageType.Disconnect:
                NetOutgoingMessage?reason = null;
                try
                {
                    reason = Peer.CreateReadHelperOutMessage(offset, payloadLength);
                }
                catch
                {
                }
                ExecuteDisconnect(reason, false);
                break;

            case NetMessageType.Discovery:
                Peer.HandleIncomingDiscoveryRequest(now, RemoteEndPoint, offset, payloadLength);
                return;

            case NetMessageType.DiscoveryResponse:
                Peer.HandleIncomingDiscoveryResponse(now, RemoteEndPoint, offset, payloadLength);
                return;

            case NetMessageType.Ping:
                // silently ignore
                return;

            default:
                Peer.LogDebug(NetLogMessage.FromValues(NetLogCode.UnhandledHandshakeMessage, value: (int)Status));
                break;
            }
        }
Esempio n. 6
0
        // heartbeat called when connection still is in m_handshakes of NetPeer
        internal void UnconnectedHeartbeat(TimeSpan now)
        {
            Peer.AssertIsOnLibraryThread();

            if (_disconnectRequested)
            {
                ExecuteDisconnect(_disconnectMessage, true);
            }

            if (_connectRequested)
            {
                switch (Status)
                {
                case NetConnectionStatus.Connected:
                case NetConnectionStatus.RespondedConnect:
                    // reconnect
                    ExecuteDisconnect(NetMessageType.ConnectTimedOut);
                    break;

                case NetConnectionStatus.InitiatedConnect:
                    // send another connect attempt
                    SendConnect(now);
                    break;

                case NetConnectionStatus.Disconnected:
                    Peer.LogError(NetLogMessage.FromValues(NetLogCode.DisconnectedPeer));
                    break;

                case NetConnectionStatus.Disconnecting:
                    // let disconnect finish first
                    break;

                case NetConnectionStatus.None:
                default:
                    SendConnect(now);
                    break;
                }
                return;
            }

            if (now - _lastHandshakeSendTime > _peerConfiguration._resendHandshakeInterval)
            {
                if (_handshakeAttempts >= _peerConfiguration._maximumHandshakeAttempts)
                {
                    // failed to connect
                    ExecuteDisconnect(NetMessageType.ConnectTimedOut);
                    return;
                }

                // resend handshake
                switch (Status)
                {
                case NetConnectionStatus.InitiatedConnect:
                    SendConnect(now);
                    break;

                case NetConnectionStatus.RespondedConnect:
                    SendConnectResponse(now, true);
                    break;

                case NetConnectionStatus.RespondedAwaitingApproval:
                    // awaiting approval
                    _lastHandshakeSendTime = now;     // postpone handshake resend
                    break;

                case NetConnectionStatus.None:
                case NetConnectionStatus.ReceivedInitiation:
                default:
                    Peer.LogWarning(NetLogMessage.FromValues(NetLogCode.UnexpectedHandshakeStatus, value: (int)Status));
                    break;
                }
            }
        }