public override bool QueueChunkEx(ChunkFlags flags, int dataSize, byte[] data, int sequence) { if (ResendQueueConstruct.DataSize + dataSize + NetworkCore.PACKET_HEADER_SIZE > NetworkCore.MAX_PAYLOAD) { Flush(); } var header = new NetworkChunkHeader { Flags = flags, Size = dataSize, Sequence = sequence }; var chunkDataOffset = ResendQueueConstruct.DataSize; chunkDataOffset = header.Pack(ResendQueueConstruct.Data, chunkDataOffset); Buffer.BlockCopy(data, 0, ResendQueueConstruct.Data, chunkDataOffset, dataSize); chunkDataOffset += dataSize; ResendQueueConstruct.NumChunks++; ResendQueueConstruct.DataSize = chunkDataOffset; if (flags.HasFlag(ChunkFlags.VITAL) && !flags.HasFlag(ChunkFlags.RESEND)) { BufferSize += SIZEOF_NETWORK_CHUNK_RESEND + dataSize; if (BufferSize >= BUFFERSIZE) { Disconnect("too weak connection (out of buffer)"); return(false); } var resend = new NetworkChunkResend { Sequence = sequence, Flags = flags, DataSize = dataSize, Data = new byte[dataSize], FirstSendTime = Time.Get(), LastSendTime = Time.Get() }; Buffer.BlockCopy(data, 0, resend.Data, 0, dataSize); ResendQueue.Enqueue(resend); } return(true); }
private void AddChunk(NetworkChunkConstruct packet, int sequence, byte[] data, int dataSize) { Debug.Assert(packet.DataSize + NetworkCore.MAX_CHUNK_HEADER_SIZE + dataSize <= packet.Data.Length, "too much data"); var header = new NetworkChunkHeader { Flags = sequence >= 0 ? ChunkFlags.VITAL : ChunkFlags.NONE, Size = dataSize, Sequence = sequence >= 0 ? sequence : 0 }; var packetDataOffset = packet.DataSize; var chunkStartOffset = packetDataOffset; packetDataOffset = header.Pack(packet.Data, packetDataOffset); packet.DataSize += packetDataOffset - chunkStartOffset; Buffer.BlockCopy(data, 0, packet.Data, packetDataOffset, dataSize); packet.DataSize += dataSize; packet.NumChunks++; }
public override bool FetchChunk(out NetworkChunk packet) { var header = new NetworkChunkHeader(); var end = ChunkConstruct.DataSize; while (true) { if (!Valid || CurrentChunk >= ChunkConstruct.NumChunks) { Clear(); packet = null; return(false); } var dataOffset = 0; for (var i = 0; i < CurrentChunk; i++) { dataOffset = header.Unpack(ChunkConstruct.Data, dataOffset); dataOffset += header.Size; } dataOffset = header.Unpack(ChunkConstruct.Data, dataOffset); CurrentChunk++; if (dataOffset + header.Size > end) { Clear(); packet = null; return(false); } if (Connection != null && header.Flags.HasFlag(ChunkFlags.VITAL)) { if (Connection.UnknownAck || header.Sequence == (Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE) { Connection.UnknownAck = false; Connection.Ack = (Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE; } else { if (NetworkCore.IsSeqInBackroom(header.Sequence, Connection.Ack)) { continue; } Debug.Log("connection", $"asking for resend {header.Sequence} {(Connection.Ack + 1) % NetworkCore.MAX_SEQUENCE}"); Connection.SignalResend(); continue; } } packet = new NetworkChunk { ClientId = ClientId, EndPoint = EndPoint, Flags = (SendFlags)header.Flags, DataSize = header.Size, Data = new byte[header.Size] }; Buffer.BlockCopy(ChunkConstruct.Data, dataOffset, packet.Data, 0, header.Size); return(true); } }