internal void DoSendDiscoveryRequest(
            NetworkEndPoint endPoint,
            bool useBroadcast,
            NetDiscoveryRequest request,
            float interval,
            float timeout)
        {
            if (!m_netBase.m_isBound)
            {
                m_netBase.Start();
            }

            m_netBase.LogWrite("Discovery request to " + endPoint);

            if (request == null)
            {
                m_netBase.LogVerbose("Creating discovery request " + m_nextRequestNumber);
                request = new NetDiscoveryRequest(endPoint, m_nextRequestNumber++, useBroadcast, interval, timeout);
                if (m_requests == null)
                {
                    m_requests = new List <NetDiscoveryRequest>();
                }
                m_requests.Add(request);
            }

            string    appIdent = m_netBase.m_config.ApplicationIdentifier;
            NetBuffer data     = new NetBuffer(appIdent.Length + 8);

            // write app identifier
            data.Write(appIdent);

            // write netbase identifier to avoid self-discovery
            data.Write(m_netBase.m_localRndSignature);

            // write request number
            data.Write((ushort)request.Number);

            m_netBase.LogWrite("Discovering " + endPoint.ToString() + "...");
            m_netBase.QueueSingleUnreliableSystemMessage(NetSystemType.Discovery, data, endPoint, useBroadcast);
        }
        private void CheckHandshake(double now)
        {
            if (now - m_handshakeInitiated > m_owner.Configuration.HandshakeAttemptRepeatDelay)
            {
                if (m_handshakeAttempts >= m_owner.Configuration.HandshakeAttemptsMaxCount)
                {
                    Disconnect("No answer from remote host", 0, false, true);
                    return;
                }
                m_handshakeAttempts++;
                if (m_isInitiator)
                {
                    m_owner.LogWrite("Re-sending Connect", this);
                    Connect();
                }
                else
                {
                    m_owner.LogWrite("Re-sending ConnectResponse", this);

                    var responseBuffer = m_owner.GetTempBuffer();
                    responseBuffer.Write(m_owner.m_localRndSignature);
                    responseBuffer.Write(m_localRndSeqNr);
                    responseBuffer.Write(m_remoteRndSignature);
                    responseBuffer.Write(m_remoteRndSeqNr);

                    double localTimeSent = m_connectLocalSentTime;
                    responseBuffer.Write(localTimeSent);
                    double remoteTimeRecv = m_connectRemoteRecvTime;
                    responseBuffer.Write(remoteTimeRecv);
                    double remoteTimeSent = NetTime.Now + m_owner.m_localTimeOffset;
                    responseBuffer.Write(remoteTimeSent);

                    if (m_localHailData != null)
                    {
                        responseBuffer.Write(m_localHailData);
                    }

                    m_handshakeInitiated = remoteTimeSent;
                    SendSingleUnreliableSystemMessage(NetSystemType.ConnectResponse, responseBuffer);
                }
            }
        }
        internal void Heartbeat(double now)
        {
            if (m_status == NetConnectionStatus.Disconnected)
            {
                return;
            }

            //CongestionHeartbeat(now);

            // drain messages from application into main unsent list
            lock (m_lockedUnsentMessages)
            {
                OutgoingNetMessage lm;
                while ((lm = m_lockedUnsentMessages.Dequeue()) != null)
                {
                    m_unsentMessages.Enqueue(lm);
                }
            }

            if (m_status == NetConnectionStatus.Connecting)
            {
                if (now - m_handshakeInitiated > m_owner.Configuration.HandshakeAttemptRepeatDelay)
                {
                    if (m_handshakeAttempts >= m_owner.Configuration.HandshakeAttemptsMaxCount)
                    {
                        Disconnect("No answer from remote host", 0, false, true);
                        return;
                    }
                    m_handshakeAttempts++;
                    if (m_isInitiator)
                    {
                        m_owner.LogWrite("Re-sending Connect", this);
                        Connect();
                    }
                    else
                    {
                        m_owner.LogWrite("Re-sending ConnectResponse", this);
                        m_handshakeInitiated = now;

                        OutgoingNetMessage response = m_owner.CreateSystemMessage(NetSystemType.ConnectResponse);
                        if (m_localHailData != null)
                        {
                            response.m_data.Write(m_localHailData);
                        }
                        m_unsentMessages.Enqueue(response);
                    }
                }
            }
            else if (m_status == NetConnectionStatus.Connected)
            {
                // send ping?
                CheckPing(now);
            }

            if (m_requestDisconnect)
            {
                InitiateDisconnect();
            }

            if (now > m_futureClose)
            {
                FinalizeDisconnect();
            }

            // Resend all packets that has reached a mature age
            ResendMessages(now);

            // send all unsent messages
            SendUnsentMessages(now);
        }