void SendAck(RudpPacket packet) { RudpPacket ack = new RudpPacket(); ack.TargetID = Session.UserID; ack.TargetClient = Session.ClientID; ack.PeerID = RemotePeerID; ack.PacketType = RudpPacketType.Ack; ack.Sequence = packet.Sequence; ack.Payload = RudpAck.Encode(HighestSeqRecvd, (byte)(MAX_WINDOW_SIZE - RecvPacketMap.Count)); ack.Ident = packet.Ident; //Session.Log("Ack Sent, Seq " + ack.Sequence.ToString() + ", ID " + ack.PeerID.ToString() + ", highest " + HighestSeqRecvd.ToString()); if (!AckMap.Contains(ack.Sequence)) { AckMap[ack.Sequence] = true; AckOrder.Enqueue(ack.Sequence); } while (AckMap.Count > MAX_WINDOW_SIZE * 2) { AckMap.Remove(AckOrder.Dequeue()); } SendTracked(new TrackPacket(ack)); }
void ReceiveAck(RudpPacket packet) { int latency = 0; int retries = -1; // find original packet that was sent TrackPacket sent = null; lock (SendSection) { foreach (TrackPacket tracked in SendPacketMap) { if (tracked.Packet.Sequence == packet.Sequence) { sent = tracked; break; } } } // mark packet as acked if (sent != null) { sent.Target.LastAck = Core.TimeNow; // connect handshake if (State == RudpState.Connecting && sent.Packet.PacketType == RudpPacketType.Syn) { SynAckReceieved = true; SetPrimaryAddress(packet.Ident); if (SynAckSent && SynAckReceieved) { Session.Log("Connected (recv ack)"); ChangeState(RudpState.Connected); SetConnected(); // if data packets received before final connection ack, process them now ManageRecvWindow(); } } if (!sent.Acked) { InOrderAcks++; if (sent.Retries == 0) { latency = (int)sent.TimeEllapsed(Core); latency = latency < 5 ? 5 : latency; AvgLatency.Input(latency); AvgLatency.Next(); } } retries = sent.Retries; sent.Acked = true; } RudpAck ack = new RudpAck(packet.Payload); //Session.Log("Ack Recv, Seq " + packet.Sequence.ToString() + ", ID " + packet.PeerID.ToString() + ", highest " + ack.Start.ToString() + ", retries " + retries.ToString() + ", latency " + latency.ToString()); lock (SendSection) { // ack possibly un-acked packets foreach (TrackPacket tracked in SendPacketMap) { // ack if start past the zero boundry with sequences behind if (tracked.Packet.Sequence > 0xFF - 25 && ack.Start < 25) { tracked.Acked = true; } // break start before boundry and sequences ahead are not recvd/acked yet if (ack.Start > 0xFF - 25 && tracked.Packet.Sequence < 25) { break; } // normal acking procedure else if (ack.Start >= tracked.Packet.Sequence) { tracked.Acked = true; } else { break; } } // remove acked, only remove packets from front while (SendPacketMap.Count > 0 && SendPacketMap.Peek().Acked) { // calculate receive speed of remote host by rate they ack AvgBytesSent.Input(SendPacketMap.Peek().Packet.Payload.Length); SendPacketMap.Dequeue(); PacketsCompleted++; } } // increase window if packets removed from beginning of buffer //if(packetsRemoved && SendWindowSize < 25) // SendWindowSize++; ManageSendWindow(); }