Beispiel #1
0
        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));
        }
Beispiel #2
0
 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)}]");
     }
 }
Beispiel #3
0
        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;
            }
        }
Beispiel #4
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();
                            }
                        }
                    }
                }
            }
        }