private void SendPacket(RUDPPacket p) { DateTime dtNow = DateTime.Now; InitSequence(p.Dst); RUDPConnectionData sq = _sequences[p.Dst.ToString()]; if (!p.Retransmit) { p.Seq = sq.Local; sq.Local++; p.Snt_TS = dtNow; lock (sq.Pending) foreach (RUDPPacket unconfirmed in sq.Pending.Where(x => (dtNow - p.Snt_TS).Seconds >= 1)) { RetransmitPacket(unconfirmed); } Debug($"SEND -> { p.Dst}: {p}"); } else { Debug($"RETRANSMIT -> {p.Dst}: {p}"); } lock (sq.Pending) { sq.Pending.RemoveAll(x => x.Dst.ToString() == p.Dst.ToString() && x.Seq == p.Seq); sq.Pending.Add(p); } Send(p.Dst, p.ToByteArray(_packetHeader)); }
public override void PacketReceive(IPEndPoint ep, byte[] data, int length) { base.PacketReceive(ep, data, length); if (length > _packetHeader.Length && data.Take(_packetHeader.Length).SequenceEqual(_packetHeader)) { RUDPPacket p = RUDPPacket.Deserialize(_packetHeader, data); p.Src = IsServer ? ep : RemoteEndPoint; p.Rcv_TS = DateTime.Now; InitSequence(p.Src); RUDPConnectionData sq = _sequences[p.Src.ToString()]; Send(p.Src, new RUDPInternalPacket.ACKPacket() { header = _internalHeader, sequence = p.Seq }.Serialize()); Debug($"ACK SEND -> {p.Src}: {p.Seq}"); lock (sq.ReceivedPackets) sq.ReceivedPackets.Add(p); } else if (length > _internalHeader.Length && data.Take(_internalHeader.Length).SequenceEqual(_internalHeader)) { IPEndPoint src = IsServer ? ep : RemoteEndPoint; InitSequence(src); RUDPConnectionData sq = _sequences[src.ToString()]; RUDPInternalPacket.ACKPacket ack = RUDPInternalPacket.ACKPacket.Deserialize(data); Debug($"ACK RECV <- {src}: {ack.sequence}"); lock (sq.Pending) sq.Pending.RemoveAll(x => x.Seq == ack.sequence); } else { Console.WriteLine($"[{GetType()}] RAW RECV: [{Encoding.ASCII.GetString(data, 0, length)}]"); } }
public void Send(IPEndPoint destination, RUDPPacketType type = RUDPPacketType.DAT, RUDPPacketFlags flags = RUDPPacketFlags.NUL, byte[] data = null, int[] intData = null) { InitSequence(destination); RUDPConnectionData sq = _sequences[destination.ToString()]; if ((data != null && data.Length < _maxMTU) || data == null) { SendPacket(new RUDPPacket() { Dst = destination, Id = sq.PacketId, Type = type, Flags = flags, Data = data }); sq.PacketId++; } else if (data != null && data.Length >= _maxMTU) { int i = 0; List <RUDPPacket> PacketsToSend = new List <RUDPPacket>(); while (i < data.Length) { int min = i; int max = _maxMTU; if ((min + max) > data.Length) { max = data.Length - min; } byte[] buf = data.Skip(i).Take(max).ToArray(); PacketsToSend.Add(new RUDPPacket() { Dst = destination, Id = sq.PacketId, Type = type, Flags = flags, Data = buf }); i += _maxMTU; } foreach (RUDPPacket p in PacketsToSend) { p.Qty = PacketsToSend.Count; SendPacket(p); } sq.PacketId++; } else { throw new Exception("This should not happen"); } if (sq.PacketId > PacketIdLimit) { sq.PacketId = 0; } }
public void ProcessRecvQueue() { foreach (var cdata in _sequences) { RUDPConnectionData sq = cdata.Value; List <RUDPPacket> PacketsToRecv = new List <RUDPPacket>(); lock (sq.ReceivedPackets) PacketsToRecv.AddRange(sq.ReceivedPackets.OrderBy(x => x.Seq)); PacketsToRecv = PacketsToRecv.GroupBy(x => x.Seq).Select(g => g.First()).ToList(); for (int i = 0; i < PacketsToRecv.Count; i++) { RUDPPacket p = PacketsToRecv[i]; lock (sq.ReceivedPackets) sq.ReceivedPackets.Remove(p); if (p.Seq < sq.Remote) { continue; } if (p.Seq > sq.Remote) { sq.ReceivedPackets.Add(p); break; } Debug($"RECV <- {p.Src}: {p}"); if (p.Qty == 0) { sq.Remote++; if (p.Type == RUDPPacketType.SYN) { if (IsServer) { Send(p.Src, RUDPPacketType.SYN, RUDPPacketFlags.ACK); OnClientConnect?.Invoke(p.Src); } else if (p.Flags == RUDPPacketFlags.ACK) { State = ConnectionState.OPEN; OnConnected?.Invoke(p.Src); } continue; } OnPacketReceived?.Invoke(p); } else { // Multipacket! List <RUDPPacket> multiPackets = PacketsToRecv.Skip(i).Take(p.Qty).ToList(); if (multiPackets.Count == p.Qty) { Debug($"MULTIPACKET {p.Id}"); byte[] buf; using (MemoryStream ms = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(ms)) foreach (RUDPPacket mp in multiPackets) { bw.Write(mp.Data); Debug($"RECV MP <- {p.Src}: {mp}"); } buf = ms.ToArray(); } Debug($"MULTIPACKET ID {p.Id} DATA: {Encoding.ASCII.GetString(buf)}"); OnPacketReceived?.Invoke(new RUDPPacket() { //ACK = p.ACK, Retransmit = p.Retransmit, Snt_TS = p.Snt_TS, Data = buf, Dst = p.Dst, Flags = p.Flags, Id = p.Id, Qty = p.Qty, Rcv_TS = p.Rcv_TS, Seq = p.Seq, Src = p.Src, Type = p.Type }); sq.Remote += p.Qty; i += p.Qty; } else { if (multiPackets.Count < p.Qty) { sq.ReceivedPackets.Add(p); break; } else { Debug($"P.QTY > MULTIPACKETS.COUNT ({p.Qty} > {multiPackets.Count})"); throw new Exception(); } } } } } }