示例#1
0
        /// <summary>
        /// Called when receiving a NatPunchMessage from a remote endpoint
        /// </summary>
        private void HandleNatPunch(int ptr, IPEndPoint senderEndpoint)
        {
            NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000);             // never mind length

            byte fromHostByte = tmp.ReadByte();

            if (fromHostByte == 0)
            {
                // it's from client
                LogDebug("NAT punch received from " + senderEndpoint + " we're host, so we ignore this");
                return;                 // don't alert hosts about nat punch successes; only clients
            }
            string token = tmp.ReadString();

            LogDebug("NAT punch received from " + senderEndpoint + " we're client, so we've succeeded - token is " + token);

            //
            // Release punch success to client; enabling him to Connect() to msg.SenderIPEndPoint if token is ok
            //
            NetIncomingMessage punchSuccess = CreateIncomingMessage(NetIncomingMessageType.NatIntroductionSuccess, 10);

            punchSuccess.m_senderEndpoint = senderEndpoint;
            punchSuccess.Write(token);
            ReleaseMessage(punchSuccess);
        }
示例#2
0
        internal void ReceivedPong(float now, int pongNumber, float remoteSendTime)
        {
            if ((byte)pongNumber != (byte)m_sentPingNumber)
            {
                m_peer.LogVerbose("Ping/Pong mismatch; dropped message?");
                return;
            }

            m_timeoutDeadline = now + m_peerConfiguration.m_connectionTimeout;

            float rtt = now - m_sentPingTime;

            NetException.Assert(rtt >= 0);

            double diff = (remoteSendTime + (rtt / 2.0)) - now;

            if (m_averageRoundtripTime < 0)
            {
                m_remoteTimeOffset     = diff;
                m_averageRoundtripTime = rtt;
                m_peer.LogDebug("Initiated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + " Remote time is: " + (now + diff));
            }
            else
            {
                m_averageRoundtripTime = (m_averageRoundtripTime * 0.7f) + (float)(rtt * 0.3f);

                m_remoteTimeOffset = ((m_remoteTimeOffset * (double)(m_sentPingNumber - 1)) + diff) / (double)m_sentPingNumber;
                m_peer.LogVerbose("Updated average roundtrip time to " + NetTime.ToReadable(m_averageRoundtripTime) + ", remote time to " + (now + m_remoteTimeOffset) + " (ie. diff " + m_remoteTimeOffset + ")");
            }

            // update resend delay for all channels
            float resendDelay = GetResendDelay();

            foreach (var chan in m_sendChannels)
            {
                var rchan = chan as NetReliableSenderChannel;
                if (rchan != null)
                {
                    rchan.m_resendDelay = resendDelay;
                }
            }

            // m_peer.LogVerbose("Timeout deadline pushed to  " + m_timeoutDeadline);

            // notify the application that average rtt changed
            if (m_peer.m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionLatencyUpdated))
            {
                NetIncomingMessage update = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionLatencyUpdated, 4);
                update.m_senderConnection = this;
                update.m_senderEndpoint   = this.m_remoteEndpoint;
                update.Write(rtt);
                m_peer.ReleaseMessage(update);
            }
        }
        internal void SetStatus(NetConnectionStatus status, string reason)
        {
            // user or library thread

            if (status == m_status)
            {
                return;
            }

            m_status = status;
            if (reason == null)
            {
                reason = string.Empty;
            }

            if (m_status == NetConnectionStatus.Connected)
            {
                m_timeoutDeadline = (float)NetTime.Now + m_peerConfiguration.m_connectionTimeout;
                m_peer.LogVerbose("Timeout deadline initialized to  " + m_timeoutDeadline);
            }

            if (m_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.StatusChanged))
            {
                NetIncomingMessage info = m_peer.CreateIncomingMessage(NetIncomingMessageType.StatusChanged, 4 + reason.Length + (reason.Length > 126 ? 2 : 1));
                info.m_senderConnection = this;
                info.m_senderEndpoint   = m_remoteEndpoint;
                info.Write((byte)m_status);
                info.Write(reason);
                m_peer.ReleaseMessage(info);
            }
            else
            {
                // app dont want those messages, update visible status immediately
                m_visibleStatus = m_status;
            }
        }
示例#4
0
        internal void ReceivedHandshake(double now, NetMessageType tp, int ptr, int payloadLength)
        {
            m_peer.VerifyNetworkThread();

            byte[] hail;
            switch (tp)
            {
            case NetMessageType.Connect:
                if (m_status == NetConnectionStatus.None)
                {
                    // Whee! Server full has already been checked
                    bool ok = ValidateHandshakeData(ptr, payloadLength, out hail);
                    if (ok)
                    {
                        if (hail != null)
                        {
                            m_remoteHailMessage            = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail);
                            m_remoteHailMessage.LengthBits = (hail.Length * 8);
                        }
                        else
                        {
                            m_remoteHailMessage = null;
                        }

                        if (m_peerConfiguration.IsMessageTypeEnabled(NetIncomingMessageType.ConnectionApproval))
                        {
                            // ok, let's not add connection just yet
                            NetIncomingMessage appMsg = m_peer.CreateIncomingMessage(NetIncomingMessageType.ConnectionApproval, (m_remoteHailMessage == null ? 0 : m_remoteHailMessage.LengthBytes));
                            appMsg.m_receiveTime      = now;
                            appMsg.m_senderConnection = this;
                            appMsg.m_senderEndpoint   = this.m_remoteEndpoint;
                            if (m_remoteHailMessage != null)
                            {
                                appMsg.Write(m_remoteHailMessage.m_data, 0, m_remoteHailMessage.LengthBytes);
                            }
                            m_peer.ReleaseMessage(appMsg);
                            return;
                        }

                        SendConnectResponse((float)now, true);
                    }
                    return;
                }
                if (m_status == NetConnectionStatus.RespondedConnect)
                {
                    // our ConnectResponse must have been lost
                    SendConnectResponse((float)now, true);
                    return;
                }
                m_peer.LogDebug("Unhandled Connect: " + tp + ", status is " + m_status + " length: " + payloadLength);
                break;

            case NetMessageType.ConnectResponse:
                switch (m_status)
                {
                case NetConnectionStatus.InitiatedConnect:
                    // awesome
                    bool ok = ValidateHandshakeData(ptr, payloadLength, out hail);
                    if (ok)
                    {
                        if (hail != null)
                        {
                            m_remoteHailMessage            = m_peer.CreateIncomingMessage(NetIncomingMessageType.Data, hail);
                            m_remoteHailMessage.LengthBits = (hail.Length * 8);
                        }
                        else
                        {
                            m_remoteHailMessage = null;
                        }

                        m_peer.AcceptConnection(this);
                        SendConnectionEstablished();
                        return;
                    }
                    break;

                case NetConnectionStatus.RespondedConnect:
                    // hello, wtf?
                    break;

                case NetConnectionStatus.Disconnecting:
                case NetConnectionStatus.Disconnected:
                case NetConnectionStatus.None:
                    // wtf? anyway, bye!
                    break;

                case NetConnectionStatus.Connected:
                    // my ConnectionEstablished must have been lost, send another one
                    SendConnectionEstablished();
                    return;
                }
                break;

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

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

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

                case NetConnectionStatus.RespondedConnect:
                    // awesome

                    NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                    InitializeRemoteTimeOffset(msg.ReadSingle());

                    m_peer.AcceptConnection(this);
                    InitializePing();
                    SetStatus(NetConnectionStatus.Connected, "Connected to " + NetUtility.ToHexString(m_remoteUniqueIdentifier));
                    return;
                }
                break;

            case NetMessageType.Disconnect:
                // ouch
                string reason = "Ouch";
                try
                {
                    NetIncomingMessage inc = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                    reason = inc.ReadString();
                }
                catch
                {
                }
                ExecuteDisconnect(reason, false);
                break;

            case NetMessageType.Discovery:
                m_peer.HandleIncomingDiscoveryRequest(now, m_remoteEndpoint, ptr, payloadLength);
                return;

            case NetMessageType.DiscoveryResponse:
                m_peer.HandleIncomingDiscoveryResponse(now, m_remoteEndpoint, ptr, payloadLength);
                return;

            case NetMessageType.Ping:
                // silently ignore
                return;

            default:
                m_peer.LogDebug("Unhandled type during handshake: " + tp + " length: " + payloadLength);
                break;
            }
        }