private void SendPacket(UDPPacket p) { DateTime dtNow = DateTime.Now; InitSequence(p.Dst); UDPConnectionData sq = _sequences[p.Dst.ToString()]; if (!p.Retransmit) { p.Seq = sq.Local; sq.Local++; p.Sent = dtNow; lock (sq.Pending) foreach (UDPPacket unconfirmed in sq.Pending.Where(x => (dtNow - p.Sent).Seconds >= 1)) { RetransmitPacket(unconfirmed); } Debug("SEND -> {0}: {1}", p.Dst, p); } else { Debug("RETRANSMIT -> {0}: {1}", p.Dst, p); } lock (sq.Pending) { sq.Pending.RemoveAll(x => x.Dst.ToString() == p.Dst.ToString() && x.Seq == p.Seq); sq.Pending.Add(p); } SendToAsync(p.Dst, p.ToByteArray(_packetHeader)); }
public void Send(EndPoint destination, UDPPacketType type = UDPPacketType.DAT, UDPPacketFlags flags = UDPPacketFlags.NUL, byte[] data = null, int[] intData = null) { InitSequence(destination); UDPConnectionData sq = _sequences[destination.ToString()]; if ((data != null && data.Length < _maxMTU) || data == null) { SendPacket(new UDPPacket() { Dst = destination, Id = sq.PacketId, Type = type, Flags = flags, Data = data }); sq.PacketId++; } else if (data != null && data.Length >= _maxMTU) { int i = 0; List <UDPPacket> PacketsToSend = new List <UDPPacket>(); 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 UDPPacket() { Dst = destination, Id = sq.PacketId, Type = type, Flags = flags, Data = buf }); i += _maxMTU; } foreach (UDPPacket 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 ProcessSendQueue() { foreach (var connectionPair in _sequences) { UDPConnectionData connectionData = connectionPair.Value; foreach (var item in connectionData.Pending) { if (null != item.Data) { //NetDebug.Log(Encoding.ASCII.GetString(item.Data)); } } } }
protected override bool DecodeReceive(byte[] buffer, int offset, int count, EndPoint ep, out int error) { error = 0; byte[] data = new byte[count]; Buffer.BlockCopy(buffer, offset, data, 0, count); if (count > _packetHeader.Length && data.Take(_packetHeader.Length).SequenceEqual(_packetHeader)) { UDPPacket p = UDPPacket.Deserialize(_packetHeader, data); p.Src = IsServer ? ep : remoterPoint; p.Received = DateTime.Now; InitSequence(p.Src); UDPConnectionData sq = _sequences[p.Src.ToString()]; SendToAsync(p.Src, new UDPInternalPacket.ACKPacket() { header = _internalHeader, sequence = p.Seq }.Serialize()); Debug("ACK SEND -> {0}: {1}", p.Src, p.Seq); lock (sq.ReceivedPackets) sq.ReceivedPackets.Add(p); } else if (count > _internalHeader.Length && data.Take(_internalHeader.Length).SequenceEqual(_internalHeader)) { EndPoint src = IsServer ? ep : remoterPoint; InitSequence(src); UDPConnectionData sq = _sequences[src.ToString()]; UDPInternalPacket.ACKPacket ack = UDPInternalPacket.ACKPacket.Deserialize(data); Debug("ACK RECV <- {0}: {1}", src, ack.sequence); lock (sq.Pending) sq.Pending.RemoveAll(x => x.Seq == ack.sequence); } else { Console.WriteLine("[{0}] RAW RECV: [{1}]", GetType().ToString(), Encoding.ASCII.GetString(data, 0, count)); } return(true); }
public void ProcessRecvQueue() { foreach (var cdata in _sequences) { UDPConnectionData sq = cdata.Value; List <UDPPacket> PacketsToRecv = new List <UDPPacket>(); 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++) { UDPPacket 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 <- {0}: {1}", p.Src, p); if (p.Qty == 0) { sq.Remote++; if (p.Type == UDPPacketType.SYN) { if (IsServer) { Send(p.Src, UDPPacketType.SYN, UDPPacketFlags.ACK); OnClientConnect?.Invoke(p.Src); } else if (p.Flags == UDPPacketFlags.ACK) { State = UDPConnectionState.OPEN; OnConnected?.Invoke(p.Src); } continue; } OnPacketReceived?.Invoke(p); } else { // Multipacket! List <UDPPacket> multiPackets = PacketsToRecv.Skip(i).Take(p.Qty).ToList(); if (multiPackets.Count == p.Qty) { Debug("MULTIPACKET {0}", p.Id); byte[] buf; using (MemoryStream ms = new MemoryStream()) { using (BinaryWriter bw = new BinaryWriter(ms)) foreach (UDPPacket mp in multiPackets) { bw.Write(mp.Data); Debug("RECV MP <- {0}: {1}", p.Src, mp); } buf = ms.ToArray(); } Debug("MULTIPACKET ID {0} DATA: {1}", p.Id, Encoding.ASCII.GetString(buf)); OnPacketReceived?.Invoke(new UDPPacket() { ACK = p.ACK, Retransmit = p.Retransmit, Sent = p.Sent, Data = buf, Dst = p.Dst, Flags = p.Flags, Id = p.Id, Qty = p.Qty, Received = p.Received, 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 ({0} > {1})", p.Qty, multiPackets.Count); throw new Exception(); } } } } } }