示例#1
0
        /// <summary>
        /// Recycles a NetIncomingMessage instance for reuse; taking pressure off the garbage collector
        /// </summary>
        public void Recycle(NetIncomingMessage msg)
        {
            if (m_incomingMessagesPool == null)
            {
                return;
            }

            NetException.Assert(m_incomingMessagesPool.Contains(msg) == false, "Recyling already recycled message! Thread race?");

            byte[] storage = msg.m_data;
            msg.m_data = null;
            Recycle(storage);
            msg.Reset();
            m_incomingMessagesPool.Enqueue(msg);
        }
示例#2
0
        /// <summary>
        /// Emit receipt event
        /// </summary>
        internal void FireReceipt(NetConnection connection, NetBuffer receiptData)
        {
            if ((m_enabledMessageTypes & NetMessageType.Receipt) != NetMessageType.Receipt)
            {
                return;                 // disabled
            }
            IncomingNetMessage msg = CreateIncomingMessage();

            msg.m_sender  = connection;
            msg.m_msgType = NetMessageType.Receipt;
            msg.m_data    = receiptData;

            lock (m_receivedMessages)
                m_receivedMessages.Enqueue(msg);
        }
示例#3
0
        /// <summary>
        /// Recycle the message to the library for reuse
        /// </summary>
        public void Recycle(NetIncomingMessage msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }

            if (msg.m_status != NetIncomingMessageReleaseStatus.ReleasedToApplication)
            {
                throw new NetException("Message not under application control; recycled more than once?");
            }

            msg.m_status = NetIncomingMessageReleaseStatus.RecycledByApplication;
            if (msg.m_data != null)
            {
                lock (m_storagePool)
                {
#if DEBUG
                    if (m_storagePool.Contains(msg.m_data))
                    {
                        throw new NetException("Storage pool object recycled twice!");
                    }
#endif
                    m_storedBytes += msg.m_data.Length;
                    m_storagePool.Add(msg.m_data);
                }
                msg.m_data = null;
            }
            m_incomingMessagesPool.Enqueue(msg);
        }
        internal void Recycle(NetOutgoingMessage msg)
        {
            if (m_outgoingMessagesPool == null)
            {
                return;
            }

            NetException.Assert(msg.m_recyclingCount == 0, "Wrong recycling count! Should be zero");

            NetException.Assert(m_outgoingMessagesPool.Contains(msg) == false, "Recyling already recycled message! Thread race?");

            byte[] storage = msg.m_data;
            msg.m_data = null;

            // message fragments cannot be recycled
            // TODO: find a way to recycle large message after all fragments has been acknowledged; or? possibly better just to garbage collect them
            if (msg.m_fragmentGroup == 0)
            {
                Recycle(storage);
            }

            msg.Reset();
            if (m_outgoingMessagesPool.Count < m_maxCacheCount)
            {
                m_outgoingMessagesPool.Enqueue(msg);
            }
        }
示例#5
0
        internal void Recycle(NetOutgoingMessage msg)
        {
            if (m_outgoingMessagesPool == null)
            {
                return;
            }
#if DEBUG
            NetException.Assert(m_outgoingMessagesPool.Contains(msg) == false, "Recyling already recycled outgoing message! Thread race?");
            if (msg.m_recyclingCount != 0)
            {
                LogWarning("Wrong recycling count! should be zero; found " + msg.m_recyclingCount);
            }
#endif
            // setting m_recyclingCount to zero SHOULD be an unnecessary maneuver, if it's not zero something is wrong
            // however, in RELEASE, we'll just have to accept this and move on with life
            msg.m_recyclingCount = 0;

            byte[] storage = msg.m_data;
            msg.m_data = null;

            // message fragments cannot be recycled
            // TODO: find a way to recycle large message after all fragments has been acknowledged; or? possibly better just to garbage collect them
            if (msg.m_fragmentGroup == 0)
            {
                Recycle(storage);
            }

            msg.Reset();
            if (m_outgoingMessagesPool.Count < m_maxCacheCount)
            {
                m_outgoingMessagesPool.Enqueue(msg);
            }
        }
示例#6
0
        internal void ReleaseMessage(NetIncomingMessage msg)
        {
            NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);

            if (msg.m_isFragment)
            {
                HandleReleasedFragment(msg);
                return;
            }

            m_releasedIncomingMessages.Enqueue(msg);

            if (m_messageReceivedEvent != null)
            {
                m_messageReceivedEvent.Set();
            }

            if (m_receiveCallbacks != null)
            {
                foreach (var tuple in m_receiveCallbacks)
                {
                    tuple.Item1.Post(tuple.Item2, this);
                }
            }
        }
        internal void ReleaseMessage(NetIncomingMessage msg)
        {
            NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);

            if (msg.m_isFragment)
            {
                HandleReleasedFragment(msg);
                return;
            }

            m_releasedIncomingMessages.Enqueue(msg);

            if (m_messageReceivedEvent != null)
            {
                m_messageReceivedEvent.Set();
            }

            if (m_receiveCallbacks != null)
            {
                int ct = m_receiveCallbacks.Count;
                for (int i = 0; i < ct; ++i)
                {
                    var tuple = m_receiveCallbacks[i];
                    tuple.Item1.Post(tuple.Item2, this);
                }
            }
        }
示例#8
0
        internal void Recycle(NetOutgoingMessage msg)
        {
            if (m_outgoingMessagesPool == null)
            {
                return;
            }
#if DEBUG
            if (m_outgoingMessagesPool.Contains(msg))
            {
                throw new NetException("Recyling already recycled message! Thread race?");
            }
#endif

            byte[] storage = msg.m_data;
            msg.m_data = null;

            // message fragments cannot be recycled
            // TODO: find a way to recycle large message after all fragments has been acknowledged; or? possibly better just to garbage collect them
            if (msg.m_fragmentGroup == 0)
            {
                Recycle(storage);
            }

            msg.Reset();
            m_outgoingMessagesPool.Enqueue(msg);
        }
示例#9
0
 /// <summary>
 /// Send a single, out-of-band unreliable message
 /// </summary>
 public void SendOutOfBandMessage(NetBuffer data, IPEndPoint recipient)
 {
     lock (m_unsentOutOfBandMessages)
     {
         m_unsentOutOfBandMessages.Enqueue(data);
         m_unsentOutOfBandRecipients.Enqueue(recipient);
     }
 }
示例#10
0
 internal void EnqueueReceivedMessage(IncomingNetMessage msg)
 {
     lock (m_receivedMessages)
     {
         m_receivedMessages.Enqueue(msg);
     }
     m_dataReceivedEvent.Set();
 }
示例#11
0
        /// <summary>
        /// Recycles a NetIncomingMessage instance for reuse; taking pressure off the garbage collector
        /// </summary>
        public void Recycle(NetIncomingMessage msg)
        {
            if (m_incomingMessagesPool == null)
            {
                return;
            }
#if DEBUG
            if (m_incomingMessagesPool.Contains(msg))
            {
                throw new NetException("Recyling already recycled message! Thread race?");
            }
#endif
            byte[] storage = msg.m_data;
            msg.m_data = null;
            Recycle(storage);
            msg.Reset();
            m_incomingMessagesPool.Enqueue(msg);
        }
示例#12
0
        // received a library message while Connected
        internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength)
        {
            m_peer.VerifyNetworkThread();

            float now = (float)NetTime.Now;

            switch (tp)
            {
            case NetMessageType.Disconnect:
                NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                ExecuteDisconnect(msg.ReadString(), false);
                break;

            case NetMessageType.Acknowledge:
                for (int i = 0; i < payloadLength; i += 3)
                {
                    NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++];                             // netmessagetype
                    int            seqNr = m_peer.m_receiveBuffer[ptr++];
                    seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8);

                    // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends
                    m_queuedIncomingAcks.Enqueue(new NetTuple <NetMessageType, int>(acktp, seqNr));
                }
                break;

            case NetMessageType.Ping:
                int pingNr = m_peer.m_receiveBuffer[ptr++];
                SendPong(pingNr);
                break;

            case NetMessageType.Pong:
                NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int   pongNr            = pmsg.ReadByte();
                float remoteSendTime    = pmsg.ReadSingle();
                ReceivedPong(now, pongNr, remoteSendTime);
                break;

            case NetMessageType.ExpandMTURequest:
                SendMTUSuccess(payloadLength);
                break;

            case NetMessageType.ExpandMTUSuccess:
                NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int size = emsg.ReadInt32();
                HandleExpandMTUSuccess(now, size);
                break;

            case NetMessageType.NatIntroduction:
                // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual
                m_peer.HandleNatIntroduction(ptr);
                break;

            default:
                m_peer.LogWarning("Connection received unhandled library message: " + tp);
                break;
            }
        }
示例#13
0
        internal void ReleaseMessage(NetIncomingMessage msg)
        {
            NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);

            if (msg.m_isFragment)
            {
                HandleReleasedFragment(msg);
                return;
            }

            m_releasedIncomingMessages.Enqueue(msg);
            if (m_messageReceivedEvent != null)
            {
                m_messageReceivedEvent.Set();
            }
        }
示例#14
0
        /// <summary>
        /// Recycle the message to the library for reuse
        /// </summary>
        internal void Recycle(NetOutgoingMessage msg)
        {
            VerifyNetworkThread();

#if DEBUG
            lock (m_connections)
            {
                foreach (NetConnection conn in m_connections)
                {
                    for (int i = 0; i < conn.m_unsentMessages.Count; i++)
                    {
                        NetSending send = conn.m_unsentMessages.TryPeek(i);
                        if (send != null && send.Message == msg)
                        {
                            throw new NetException("Ouch! Recycling unsent message!");
                        }

                        foreach (NetSending asend in conn.m_unackedSends)
                        {
                            if (asend.Message == msg)
                            {
                                throw new NetException("Ouch! Recycling stored message!");
                            }
                        }
                    }
                }
            }
#endif
            NetException.Assert(msg.m_numUnfinishedSendings == 0, "Recycling m_numUnfinishedSendings is " + msg.m_numUnfinishedSendings + " (expected 0)");

            if (msg.m_data != null)
            {
                lock (m_storagePool)
                {
                    if (!m_storagePool.Contains(msg.m_data))
                    {
                        m_storedBytes += msg.m_data.Length;
                        m_storagePool.Add(msg.m_data);
                    }
                }
                msg.m_data = null;
            }
            m_outgoingMessagesPool.Enqueue(msg);
        }
        /// <summary>
        /// Recycles a NetIncomingMessage instance for reuse; taking pressure off the garbage collector
        /// </summary>
        public void Recycle(NetIncomingMessage msg)
        {
            if (m_incomingMessagesPool == null || msg == null)
            {
                return;
            }

            NetException.Assert(m_incomingMessagesPool.Contains(msg) == false, "Recyling already recycled incoming message! Thread race?");

            byte[] storage = msg.m_buf;
            msg.m_buf = null;
            Recycle(storage);
            msg.Reset();

            if (m_incomingMessagesPool.Count < m_maxCacheCount)
            {
                m_incomingMessagesPool.Enqueue(msg);
            }
        }
示例#16
0
        internal void ReleaseMessage(NetIncomingMessage msg)
        {
            NetException.Assert(msg.m_incomingMessageType != NetIncomingMessageType.Error);

            if (msg.m_isFragment)
            {
                HandleReleasedFragment(msg);
                return;
            }

            if (msg.SenderConnection != null && msg.SenderConnection.MessageHandler != null)
            {
                var handled = msg.SenderConnection.MessageHandler(msg);
                if (handled)
                {
                    return;
                }
            }

            m_releasedIncomingMessages.Enqueue(msg);

            if (m_messageReceivedEvent != null)
            {
                m_messageReceivedEvent.Set();
            }

            if (m_receiveCallbacks != null)
            {
                foreach (var tuple in m_receiveCallbacks)
                {
                    try
                    {
                        tuple.Item1.Post(tuple.Item2, this);
                    }
                    catch (Exception ex)
                    {
                        LogWarning("Receive callback exception:" + ex);
                    }
                }
            }
        }
示例#17
0
        // TODO: Use this with TRUE isLibraryThread for internal sendings (acks etc)

        internal void SendMessage(NetBuffer data, NetChannel channel, NetBuffer receiptData, bool isLibraryThread)
        {
            if (m_status != NetConnectionStatus.Connected)
            {
                throw new NetException("Status must be Connected to send messages");
            }

            if (data.LengthBytes > m_owner.m_config.m_maximumTransmissionUnit)
            {
                //
                // Fragmented message
                //

                int dataLen      = data.LengthBytes;
                int chunkSize    = m_owner.m_config.m_maximumTransmissionUnit - 10;              // header
                int numFragments = dataLen / chunkSize;
                if (chunkSize * numFragments < dataLen)
                {
                    numFragments++;
                }

                ushort fragId = m_nextSendFragmentId++;

                for (int i = 0; i < numFragments; i++)
                {
                    OutgoingNetMessage fmsg = m_owner.CreateOutgoingMessage();
                    fmsg.m_type    = NetMessageLibraryType.UserFragmented;
                    fmsg.m_msgType = NetMessageType.Data;

                    NetBuffer fragBuf = m_owner.CreateBuffer();
                    fragBuf.Write(fragId);
                    fragBuf.WriteVariableUInt32((uint)i);
                    fragBuf.WriteVariableUInt32((uint)numFragments);

                    if (i < numFragments - 1)
                    {
                        // normal fragment
                        fragBuf.Write(data.Data, i * chunkSize, chunkSize);
                    }
                    else
                    {
                        // last fragment
                        int bitsInLast  = data.LengthBits - (chunkSize * (numFragments - 1) * 8);
                        int bytesInLast = dataLen - (chunkSize * (numFragments - 1));
                        fragBuf.Write(data.Data, i * chunkSize, bytesInLast);

                        // add receipt only to last message
                        fmsg.m_receiptData = receiptData;
                    }
                    fmsg.m_data            = fragBuf;
                    fmsg.m_data.m_refCount = 1;                     // since it's just been created

                    fmsg.m_numSent         = 0;
                    fmsg.m_nextResend      = double.MaxValue;
                    fmsg.m_sequenceChannel = channel;
                    fmsg.m_sequenceNumber  = -1;

                    if (isLibraryThread)
                    {
                        m_unsentMessages.Enqueue(fmsg);
                    }
                    else
                    {
                        lock (m_lockedUnsentMessages)
                            m_lockedUnsentMessages.Enqueue(fmsg);
                    }
                }

                // TODO: recycle the original, unfragmented data

                return;
            }

            //
            // Normal, unfragmented, message
            //

            OutgoingNetMessage msg = m_owner.CreateOutgoingMessage();

            msg.m_msgType = NetMessageType.Data;
            msg.m_type    = NetMessageLibraryType.User;
            msg.m_data    = data;
            msg.m_data.m_refCount++;             // it could have been sent earlier also
            msg.m_numSent         = 0;
            msg.m_nextResend      = double.MaxValue;
            msg.m_sequenceChannel = channel;
            msg.m_sequenceNumber  = -1;
            msg.m_receiptData     = receiptData;

            if (isLibraryThread)
            {
                m_unsentMessages.Enqueue(msg);
            }
            else
            {
                lock (m_lockedUnsentMessages)
                    m_lockedUnsentMessages.Enqueue(msg);
            }
        }
 internal void QueueAck(NetMessageType tp, int sequenceNumber)
 {
     m_queuedOutgoingAcks.Enqueue(new NetTuple <NetMessageType, int>(tp, sequenceNumber));
 }
        // received a library message while Connected
        internal void ReceivedLibraryMessage(NetMessageType tp, int ptr, int payloadLength)
        {
            m_peer.VerifyNetworkThread();

            float now = (float)NetTime.Now;

            switch (tp)
            {
            case NetMessageType.Connect:
                m_peer.LogDebug("Received handshake message (" + tp + ") despite connection being in place");
                break;

            case NetMessageType.ConnectResponse:
                // handshake message must have been lost
                HandleConnectResponse(now, tp, ptr, payloadLength);
                break;

            case NetMessageType.ConnectionEstablished:
                // do nothing, all's well
                break;

            case NetMessageType.LibraryError:
                m_peer.ThrowOrLog("LibraryError received by ReceivedLibraryMessage; this usually indicates a malformed message");
                break;

            case NetMessageType.Disconnect:
                NetIncomingMessage msg = m_peer.SetupReadHelperMessage(ptr, payloadLength);

                m_disconnectRequested  = true;
                m_disconnectMessage    = msg.ReadString();
                m_disconnectReqSendBye = false;
                //ExecuteDisconnect(msg.ReadString(), false);
                break;

            case NetMessageType.Acknowledge:
                for (int i = 0; i < payloadLength; i += 3)
                {
                    NetMessageType acktp = (NetMessageType)m_peer.m_receiveBuffer[ptr++];                             // netmessagetype
                    int            seqNr = m_peer.m_receiveBuffer[ptr++];
                    seqNr |= (m_peer.m_receiveBuffer[ptr++] << 8);

                    // need to enqueue this and handle it in the netconnection heartbeat; so be able to send resends together with normal sends
                    m_queuedIncomingAcks.Enqueue(new NetTuple <NetMessageType, int>(acktp, seqNr));
                }
                break;

            case NetMessageType.Ping:
                int pingNr = m_peer.m_receiveBuffer[ptr++];
                SendPong(pingNr);
                break;

            case NetMessageType.Pong:
                NetIncomingMessage pmsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int   pongNr            = pmsg.ReadByte();
                float remoteSendTime    = pmsg.ReadSingle();
                ReceivedPong(now, pongNr, remoteSendTime);
                break;

            case NetMessageType.ExpandMTURequest:
                SendMTUSuccess(payloadLength);
                break;

            case NetMessageType.ExpandMTUSuccess:
                if (m_peer.Configuration.AutoExpandMTU == false)
                {
                    m_peer.LogDebug("Received ExpandMTURequest altho AutoExpandMTU is turned off!");
                    break;
                }
                NetIncomingMessage emsg = m_peer.SetupReadHelperMessage(ptr, payloadLength);
                int size = emsg.ReadInt32();
                HandleExpandMTUSuccess(now, size);
                break;

            case NetMessageType.NatIntroduction:
                // Unusual situation where server is actually already known, but got a nat introduction - oh well, lets handle it as usual
                m_peer.HandleNatIntroduction(ptr);
                break;

            default:
                m_peer.LogWarning("Connection received unhandled library message: " + tp);
                break;
            }
        }
 internal void EnqueueReceivedMessage(IncomingNetMessage msg)
 {
     m_receivedMessages.Enqueue(msg);
 }