protected override void AckChunks(int ack) { do { if (ResendQueue.Count == 0) { return; } if (ResendQueue.TryPeek(out var chunk)) { if (NetworkCore.IsSeqInBackroom(chunk.Sequence, ack)) { ResendQueue.Dequeue(); BufferSize -= SIZEOF_NETWORK_CHUNK_RESEND + chunk.DataSize; } else { return; } } else { return; } } while (true); }
public override void Update() { if (State == ConnectionState.OFFLINE || State == ConnectionState.ERROR) { return; } if (State != ConnectionState.OFFLINE && State != ConnectionState.CONNECT && (Time.Get() - LastReceiveTime) > Time.Freq() * Config["ConnTimeout"]) { State = ConnectionState.ERROR; Error = "Timeout"; return; } if (ResendQueue.Count > 0) { var resend = ResendQueue.Peek(); if (Time.Get() - resend.FirstSendTime > Time.Freq() * Config["ConnTimeout"]) { State = ConnectionState.ERROR; Error = $"Too weak connection (not acked for {Config["ConnTimeout"]} seconds)"; } else if (Time.Get() - resend.LastSendTime > Time.Freq()) { ResendChunk(resend); } } if (State == ConnectionState.ONLINE) { if (Time.Get() - LastSendTime > Time.Freq() / 2) { var flushedChunks = Flush(); if (flushedChunks != 0) { Debug.Log("connection", $"flushed connection due to timeout. {flushedChunks} chunks."); } } if (Time.Get() - LastSendTime > Time.Freq()) { SendControlMsg(ConnectionMessages.KEEPALIVE, ""); } } else if (State == ConnectionState.CONNECT) { if (Time.Get() - LastSendTime > Time.Freq() / 2) { SendControlMsg(ConnectionMessages.CONNECT, ""); } } }
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); }
public override void Reset() { Sequence = 0; UnknownAck = false; Ack = 0; PeerAck = 0; RemoteClosed = false; State = ConnectionState.OFFLINE; ConnectedAt = 0; LastReceiveTime = 0; LastSendTime = 0; UseToken = true; Token = 0; EndPoint = null; ResendQueue.Clear(); BufferSize = 0; Error = string.Empty; ResetQueueConstruct(); }