public void SendTracked(TrackPacket tracked) { if (AddressMap.Count == 0) { return; } RudpAddress target = tracked.SpecialTarget ? tracked.Target : PrimaryAddress; LastSend = Core.TimeNow; tracked.TimeSent = Core.TimeNow.Ticks; tracked.Target = target; tracked.Packet.SenderID = Network.Local.UserID; tracked.Packet.SenderClient = Network.Local.ClientID; if (tracked.Packet.PacketType != RudpPacketType.Syn) { SendPacket(tracked.Packet, target); } else { PrimaryAddress.Reset = true; foreach (RudpAddress address in AddressMap.Values) { tracked.Packet.Ident = address.Ident; tracked.Target = address; SendPacket(tracked.Packet, address); } } }
void SendPing(RudpAddress address) { RudpPacket ping = new RudpPacket(); ping.TargetID = Session.UserID; ping.TargetClient = Session.ClientID; ping.PeerID = RemotePeerID; ping.PacketType = RudpPacketType.Ping; ping.Sequence = 0; ping.Payload = BitConverter.GetBytes(address.Ident); //Session.Log("Keep Alive Sent, Seq " + alive.Sequence.ToString() + ", ID " + alive.PeerID.ToString()); TrackPacket tracked = new TrackPacket(ping); tracked.Target = address; tracked.SpecialTarget = true; SendTracked(tracked); }
void ManageSendWindow() { ArrayList retransmit = new ArrayList(); int rtt = AvgLatency.GetAverage(); int outstanding = 0; lock (SendSection) { // iter through send window foreach (TrackPacket packet in SendPacketMap) { if (packet.Acked) { continue; } else if (packet.TimeSent == 0) { retransmit.Add(packet); } // connecting so must be a syn packet else if (State == RudpState.Connecting) { if (packet.TimeEllapsed(Core) > 1000 * 2) // dont combine with above cause then next else if would always run { retransmit.Add(packet); } } // send packets that havent been sent yet, and ones that need to be retransmitted else if (packet.TimeEllapsed(Core) > rtt * 2) { retransmit.Add(packet); } // mark as outstanding else { outstanding++; } } } // re-transmit packets foreach (TrackPacket track in retransmit) { if (outstanding < SendWindowSize) { //Session.Log("Re-Send ID " + track.Packet.PeerID.ToString() + // ", Type " + track.Packet.Type.ToString() + // ", Seq " + track.Packet.Sequence.ToString() + ", Retries " + track.Retries.ToString() + // ", Passed " + track.TimeEllapsed().ToString() + " ms"); track.Retries++; ReTransmits++; SendTracked(track); outstanding++; } else { break; } } lock (SendSection) { // send number of packets so that outstanding equals window size while (outstanding < SendWindowSize && SendBuffLength > 0 && SendPacketMap.Count < MAX_WINDOW_SIZE) { int buffLen = (SendBuffLength > CHUNK_SIZE) ? CHUNK_SIZE : SendBuffLength; RudpPacket data = new RudpPacket(); data.TargetID = Session.UserID; data.TargetClient = Session.ClientID; data.PeerID = RemotePeerID; data.PacketType = RudpPacketType.Data; data.Sequence = CurrentSeq++; data.Payload = Utilities.ExtractBytes(SendBuff, 0, buffLen); // move next data on deck for next send if (SendBuffLength > buffLen) { Buffer.BlockCopy(SendBuff, buffLen, SendBuff, 0, SendBuffLength - buffLen); } SendBuffLength -= buffLen; TrackPacket track = new TrackPacket(data); SendPacketMap.Enqueue(track); //Session.Log("Data Sent, Seq " + data.Sequence.ToString() + ", ID " + data.PeerID.ToString() + ", Size " + buffLen.ToString()); SendTracked(track); outstanding++; } } // if we can take more data call onsend if (SendBuffLength == 0 && RudpSendBlock) { //Session.Log("OnSend Called"); RudpSendBlock = false; Session.OnSend(); } }
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(); }
void ManageSendWindow() { ArrayList retransmit = new ArrayList(); int rtt = AvgLatency.GetAverage(); int outstanding = 0; lock (SendSection) { // iter through send window foreach (TrackPacket packet in SendPacketMap) { if (packet.Acked) continue; else if (packet.TimeSent == 0) retransmit.Add(packet); // connecting so must be a syn packet else if (State == RudpState.Connecting) { if (packet.TimeEllapsed(Core) > 1000 * 2) // dont combine with above cause then next else if would always run retransmit.Add(packet); } // send packets that havent been sent yet, and ones that need to be retransmitted else if (packet.TimeEllapsed(Core) > rtt * 2) retransmit.Add(packet); // mark as outstanding else outstanding++; } } // re-transmit packets foreach (TrackPacket track in retransmit) if (outstanding < SendWindowSize) { //Session.Log("Re-Send ID " + track.Packet.PeerID.ToString() + // ", Type " + track.Packet.Type.ToString() + // ", Seq " + track.Packet.Sequence.ToString() + ", Retries " + track.Retries.ToString() + // ", Passed " + track.TimeEllapsed().ToString() + " ms"); track.Retries++; ReTransmits++; SendTracked(track); outstanding++; } else break; lock (SendSection) { // send number of packets so that outstanding equals window size while (outstanding < SendWindowSize && SendBuffLength > 0 && SendPacketMap.Count < MAX_WINDOW_SIZE) { int buffLen = (SendBuffLength > CHUNK_SIZE) ? CHUNK_SIZE : SendBuffLength; RudpPacket data = new RudpPacket(); data.TargetID = Session.UserID; data.TargetClient = Session.ClientID; data.PeerID = RemotePeerID; data.PacketType = RudpPacketType.Data; data.Sequence = CurrentSeq++; data.Payload = Utilities.ExtractBytes(SendBuff, 0, buffLen); // move next data on deck for next send if (SendBuffLength > buffLen) Buffer.BlockCopy(SendBuff, buffLen, SendBuff, 0, SendBuffLength - buffLen); SendBuffLength -= buffLen; TrackPacket track = new TrackPacket(data); SendPacketMap.Enqueue(track); //Session.Log("Data Sent, Seq " + data.Sequence.ToString() + ", ID " + data.PeerID.ToString() + ", Size " + buffLen.ToString()); SendTracked(track); outstanding++; } } // if we can take more data call onsend if(SendBuffLength == 0 && RudpSendBlock) { //Session.Log("OnSend Called"); RudpSendBlock = false; Session.OnSend(); } }
public void SendTracked(TrackPacket tracked) { if (AddressMap.Count == 0) return; RudpAddress target = tracked.SpecialTarget ? tracked.Target : PrimaryAddress; LastSend = Core.TimeNow; tracked.TimeSent = Core.TimeNow.Ticks; tracked.Target = target; tracked.Packet.SenderID = Network.Local.UserID; tracked.Packet.SenderClient = Network.Local.ClientID; if (tracked.Packet.PacketType != RudpPacketType.Syn) SendPacket(tracked.Packet, target); else { PrimaryAddress.Reset = true; foreach (RudpAddress address in AddressMap.Values) { tracked.Packet.Ident = address.Ident; tracked.Target = address; SendPacket(tracked.Packet, address); } } }