/// <summary> Handles a stream based on its header/size. Determines if it should be buffered if out-of-order, /// acked and released if size is equal to header size (ack only), or delivered immediately. </summary> internal void RouteIncomingStream(NetStream strm) { var header = NetHeader.FromStream(strm); int seqDist = NetMath.SeqDistance(header.ObjSequence, LastAcceptedRemoteSequence); // If the stream is only the size of a header, it's likely a forced ack: if (strm.Length <= 120) { AckDelivered(header); strm.Release(); } else if (!RemoteSequenceValid(seqDist)) { strm.Release(); } else if (seqDist != 1) { BufferOutOfOrder(seqDist, strm, header); } else { AckReceived(header); AckDelivered(header); DeliverStream(strm); } }
/// <summary> Adds an out-of-order datagram to the buffer to await future delivery. </summary> private void BufferOutOfOrder(int seqDist, NetStream strm, NetHeader header) { if (recvBuffer.Count >= 512) { Connection.Disconnect(); return; } if (recvBufferSeqDist.Contains(seqDist)) { strm.Release(); return; } // Ack history window is only 64 bits, so only ack if within window: if (seqDist < 64) { AckReceived(header); AckDelivered(header); } else { strm.Pos = 1; // Reset to 1 so header can be reprocessed when seqDist < 64 } recvBuffer.Add(strm); recvBufferSeqDist.Add(seqDist); }
internal void TriggerReadInstantiateData(NetStream stream) { if (OnReadInstantiateData != null) { OnReadInstantiateData(stream); } stream.Release(); }
internal void TriggerReadSync(NetStream stream) { if (OnReadSync != null) { OnReadSync(stream); } stream.Release(); }
/// <summary> Removes acked messages from the send window, releases the stream, updates connection ping, and /// increments the Delivered stat. </summary> private void MessageDelivered(int index, NetHeader header) { Delivered++; NetStream strm = reliableWindow[sendWindow[index]]; if (header.AckTime > 0) { Connection.UpdatePing(NetTime.Milliseconds(), sendWindowTime[index], header.AckTime); } reliableWindow.Remove(sendWindow[index]); sendWindow.RemoveAt(index); sendWindowTime.RemoveAt(index); strm.Release(); }
/// <summary> Deserializes incoming reliable stream into NetMessages, forwards them to the NetSocket, releases the stream, /// increments the remote sequence, and retries the out-of-order buffer when needed. </summary> private void DeliverStream(NetStream strm) { // Deserialize stream into individual messages and pass them to the socket: while (NetSerializer.CanReadMessage(strm)) { var message = NetSerializer.ReadNetMessage(strm); if (message == null) { NetLog.Error("Failed to parse reliable message from: " + Connection.Endpoint + " Pos: " + strm.Pos + " Size: " + strm.Size); break; } Connection.Socket.ReceiveMessage(message, Connection); } // Return stream to pool and update receive buffer distances: strm.Release(); LastAcceptedRemoteSequence++; if (recvBuffer.Count > 0) { DecrementReceiveBuffer(); } }
/// <summary> Adds an out-of-order datagram to the buffer to await future delivery. </summary> private void BufferOutOfOrder(int seqDist, NetStream strm, NetHeader header) { if (recvBuffer.Count >= 512) { Connection.Disconnect(); return; } if (recvBufferSeqDist.Contains(seqDist)) { strm.Release(); return; } // Ack history window is only 64 bits, so only ack if within window: if (seqDist < 64) { AckReceived(header); AckDelivered(header); } else strm.Pos = 1; // Reset to 1 so header can be reprocessed when seqDist < 64 recvBuffer.Add(strm); recvBufferSeqDist.Add(seqDist); }
/// <summary> Deserializes incoming reliable stream into NetMessages, forwards them to the NetSocket, releases the stream, /// increments the remote sequence, and retries the out-of-order buffer when needed. </summary> private void DeliverStream(NetStream strm) { // Deserialize stream into individual messages and pass them to the socket: while (NetSerializer.CanReadMessage(strm)) { var message = NetSerializer.ReadNetMessage(strm); if (message == null) { NetLog.Error("Failed to parse reliable message from: " + Connection.Endpoint + " Pos: " + strm.Pos + " Size: " + strm.Size); break; } Connection.Socket.ReceiveMessage(message, Connection); } // Return stream to pool and update receive buffer distances: strm.Release(); LastAcceptedRemoteSequence++; if (recvBuffer.Count > 0) DecrementReceiveBuffer(); }
/// <summary> Handles a stream based on its header/size. Determines if it should be buffered if out-of-order, /// acked and released if size is equal to header size (ack only), or delivered immediately. </summary> internal void RouteIncomingStream(NetStream strm) { var header = NetHeader.FromStream(strm); int seqDist = NetMath.SeqDistance(header.ObjSequence, LastAcceptedRemoteSequence); // If the stream is only the size of a header, it's likely a forced ack: if (strm.Length <= 120) { AckDelivered(header); strm.Release(); } else if (!RemoteSequenceValid(seqDist)) strm.Release(); else if (seqDist != 1) BufferOutOfOrder(seqDist, strm, header); else { AckReceived(header); AckDelivered(header); DeliverStream(strm); } }