// Queue an item for immediate sending on the wire // This method is called from the ISenderChannels internal void QueueSendMessage(NetOutgoingMessage om, int seqNr) { m_peer.VerifyNetworkThread(); int sz = om.GetEncodedSize(); //if (sz > m_currentMTU) // m_peer.LogWarning("Message larger than MTU! Fragmentation must have failed!"); bool connReset; // TODO: handle connection reset // can fit this message together with previously written to buffer? if (m_sendBufferWritePtr + sz > m_currentMTU) { if (m_sendBufferWritePtr > 0 && m_sendBufferNumMessages > 0) { // previous message in buffer; send these first m_peer.SendPacket(m_sendBufferWritePtr, m_remoteEndPoint, m_sendBufferNumMessages, out connReset); m_statistics.PacketSent(m_sendBufferWritePtr, m_sendBufferNumMessages); m_sendBufferWritePtr = 0; m_sendBufferNumMessages = 0; } } // encode it into buffer regardless if it (now) fits within MTU or not m_sendBufferWritePtr = om.Encode(m_peer.m_sendBuffer, m_sendBufferWritePtr, seqNr); m_sendBufferNumMessages++; if (m_sendBufferWritePtr > m_currentMTU) { // send immediately; we're already over MTU m_peer.SendPacket(m_sendBufferWritePtr, m_remoteEndPoint, m_sendBufferNumMessages, out connReset); m_statistics.PacketSent(m_sendBufferWritePtr, m_sendBufferNumMessages); m_sendBufferWritePtr = 0; m_sendBufferNumMessages = 0; } if (m_sendBufferWritePtr > 0) m_peer.m_needFlushSendQueue = true; // flush in heartbeat Interlocked.Decrement(ref om.m_recyclingCount); }
// send message immediately and recycle it internal void SendLibrary(NetOutgoingMessage msg, NetEndPoint recipient) { VerifyNetworkThread(); NetException.Assert(msg.m_isSent == false); bool connReset; int len = msg.Encode(m_sendBuffer, 0, 0); SendPacket(len, recipient, 1, out connReset); // no reliability, no multiple recipients - we can just recycle this message immediately msg.m_recyclingCount = 0; Recycle(msg); }