Example #1
0
        public static RudpPacket Decode(G2Header root)
        {
            RudpPacket gc = new RudpPacket();

            if (G2Protocol.ReadPayload(root))
            {
                gc.Payload = Utilities.ExtractBytes(root.Data, root.PayloadPos, root.PayloadSize);
            }

            G2Protocol.ResetPacket(root);


            G2Header child = new G2Header(root.Data);

            while (G2Protocol.ReadNextChild(root, child) == G2ReadResult.PACKET_GOOD)
            {
                if (!G2Protocol.ReadPayload(child))
                {
                    continue;
                }

                switch (child.Name)
                {
                case Packet_SenderDht:
                    gc.SenderID = BitConverter.ToUInt64(child.Data, child.PayloadPos);
                    break;

                case Packet_SenderClient:
                    gc.SenderClient = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                    break;

                case Packet_TargetDht:
                    gc.TargetID = BitConverter.ToUInt64(child.Data, child.PayloadPos);
                    break;

                case Packet_TargetClient:
                    gc.TargetClient = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                    break;

                case Packet_Type:
                    gc.PacketType = child.Data[child.PayloadPos];
                    break;

                case Packet_ID:
                    gc.PeerID = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                    break;

                case Packet_Seq:
                    gc.Sequence = (byte)child.Data[child.PayloadPos];
                    break;

                case Packet_Ident:
                    gc.Ident = BitConverter.ToUInt32(child.Data, child.PayloadPos);
                    break;

                case Packet_To:
                    gc.ToAddress = DhtAddress.ReadPacket(child);
                    break;

                case Packet_Proxy:
                    gc.RemoteProxy = DhtAddress.ReadPacket(child);
                    break;
                }
            }

            return(gc);
        }
Example #2
0
        public void ReceiveCommPacket(G2ReceivedPacket raw, RudpPacket packet)
        {
            try
            {
                if (packet.PacketType == RudpPacketType.Light ||
                    packet.PacketType == RudpPacketType.LightAck)
                {
                    LightComm.ReceivePacket(raw, packet);
                    return;
                }

                // if a socket already set up
                lock (RudpControl.SocketMap)
                    if (RudpControl.SocketMap.ContainsKey(packet.PeerID))
                    {
                        RudpControl.SocketMap[packet.PeerID].RudpReceive(raw, packet, IsLookup);
                        return;
                    }

                // if starting new session
                if (packet.PacketType != RudpPacketType.Syn)
                    return;

                RudpSyn syn = new RudpSyn(packet.Payload);

                // prevent connection from self
                if (syn.SenderID == Local.UserID && syn.ClientID == Local.ClientID)
                    return;

                // find connecting session with same or unknown client id
                ulong id = syn.SenderID ^ syn.ClientID;

                if (RudpControl.SessionMap.ContainsKey(id))
                {
                    RudpSession session = RudpControl.SessionMap[id];

                    // if session id zero or matches forward
                    if ((session.Comm.State == RudpState.Connecting && session.Comm.RemotePeerID == 0) ||
                        (session.Comm.State != RudpState.Closed && session.Comm.RemotePeerID == syn.ConnID)) // duplicate syn
                    {
                        session.Comm.RudpReceive(raw, packet, IsLookup);
                        return;
                    }

                    else if (session.Comm.State == RudpState.Finishing)
                    {
                        RudpControl.RemoveSession(session);
                        // remove session, allow new one to be created
                    }
                    else
                        return;
                }

                // if clientid not in session, create new session
                RudpSession newSession = new RudpSession(RudpControl, syn.SenderID, syn.ClientID, true);

                RudpControl.SessionMap[id] = newSession;

                // send ack before sending our own syn (connect)
                // ack tells remote which address is good so that our syn's ack comes back quickly
                newSession.Comm.RudpReceive(raw, packet, IsLookup);

                newSession.Connect();

                UpdateLog("RUDP", "Inbound session accepted to ClientID " + syn.ClientID.ToString());
            }
            catch (Exception ex)
            {
                UpdateLog("Exception", "DhtNetwork::ReceiveCommPacket: " + ex.Message);
            }
        }
Example #3
0
        public static RudpPacket Decode(G2Header root)
        {
            RudpPacket gc = new RudpPacket();

            if( G2Protocol.ReadPayload(root) )
                gc.Payload = Utilities.ExtractBytes(root.Data, root.PayloadPos, root.PayloadSize);

            G2Protocol.ResetPacket(root);

            G2Header child = new G2Header(root.Data);

            while( G2Protocol.ReadNextChild(root, child) == G2ReadResult.PACKET_GOOD )
            {
                if (!G2Protocol.ReadPayload(child))
                    continue;

                switch (child.Name)
                {
                    case Packet_SenderDht:
                        gc.SenderID = BitConverter.ToUInt64(child.Data, child.PayloadPos);
                        break;

                    case Packet_SenderClient:
                        gc.SenderClient = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                        break;

                    case Packet_TargetDht:
                        gc.TargetID = BitConverter.ToUInt64(child.Data, child.PayloadPos);
                        break;

                    case Packet_TargetClient:
                        gc.TargetClient = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                        break;

                    case Packet_Type:
                        gc.PacketType = child.Data[child.PayloadPos];
                        break;

                    case Packet_ID:
                        gc.PeerID = BitConverter.ToUInt16(child.Data, child.PayloadPos);
                        break;

                    case Packet_Seq:
                        gc.Sequence = (byte)child.Data[child.PayloadPos];
                        break;

                    case Packet_Ident:
                        gc.Ident = BitConverter.ToUInt32(child.Data, child.PayloadPos);
                        break;

                    case Packet_To:
                        gc.ToAddress = DhtAddress.ReadPacket(child);
                        break;

                    case Packet_Proxy:
                        gc.RemoteProxy = DhtAddress.ReadPacket(child);
                        break;
                }
            }

            return gc;
        }
Example #4
0
        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);
        }
Example #5
0
        void SendSyn()
        {
            RudpPacket syn = new RudpPacket();

            lock (SendSection) // ensure queued in right order with right current seq
            {
                syn.TargetID = Session.UserID;
                syn.TargetClient = Session.ClientID;
                syn.PeerID = 0;
                syn.PacketType = RudpPacketType.Syn;
                syn.Sequence = CurrentSeq++;
                syn.Payload = RudpSyn.Encode(1, Network.Local.UserID, Network.Local.ClientID, PeerID);

                SendPacketMap.Enqueue(new TrackPacket(syn));
            }

            ManageSendWindow();
        }
Example #6
0
        void ReceiveSyn(RudpPacket packet)
        {
            RudpSyn syn = new RudpSyn(packet.Payload);

            if(RemotePeerID == 0)
                RemotePeerID = syn.ConnID;

            //Session.Log("Syn Recv, Seq " + packet.Sequence.ToString() + ", ID " + syn.ConnID.ToString());

            SendAck(packet); // send ack here also because peerID now set

            SynAckSent = true;

            if(SynAckSent && SynAckReceieved)
            {
                Session.Log("Connected (recv syn)");
                ChangeState(RudpState.Connected);
                SetConnected();
            }
        }
Example #7
0
        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) );
        }
Example #8
0
        void ReceivePing(RudpPacket ping)
        {
            RudpPacket pong = new RudpPacket();

            pong.TargetID = Session.UserID;
            pong.TargetClient = Session.ClientID;
            pong.PeerID = RemotePeerID;
            pong.PacketType = RudpPacketType.Pong;
            pong.Sequence = 0;
            pong.Payload = ping.Payload;

            SendTracked(new TrackPacket(pong));
        }
Example #9
0
        void ReceivePong(RudpPacket pong)
        {
            if (pong.Payload != null)
            {
                uint ident = BitConverter.ToUInt32(pong.Payload, 0);

                SetPrimaryAddress(ident);
            }
        }
Example #10
0
        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();
        }
Example #11
0
        void ReceiveFin(RudpPacket packet)
        {
            //Session.Log("Fin Recv, Seq " + packet.Sequence.ToString() + ", ID " + packet.PeerID.ToString() + ", Reason " + packet.Payload[0].ToString());

            FinReceived = true;

            SendAck(packet);

            if(!FinSent)
                RudpClose(CloseReason.YOU_CLOSED);
        }
Example #12
0
        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();
            }
        }
Example #13
0
        public void SendPacket(RudpPacket packet, RudpAddress target)
        {
            Debug.Assert(packet.Payload != null);

            // sending syn  to (tracked target) through (address target) udp / tcp

            /*string log = "Sending " + tracked.Packet.PacketType.ToString();
            if (tracked.Packet.Ident != 0) log  += ", ID " + tracked.Packet.Ident.ToString();
            log +=  " to " + Utilities.IDtoBin(tracked.Packet.TargetID).Substring(0, 10);
            log += " target address " + target.Address.ToString();*/

            int sentBytes = 0;

            // same code used in lightComm
            if (Core.Firewall != FirewallType.Blocked && target.LocalProxy == null)
            {
                sentBytes = Network.SendPacket(target.Address, packet);
            }

            else if (target.Address.TunnelClient != null)
                sentBytes = Network.SendTunnelPacket(target.Address, packet);

            else
            {
                packet.ToAddress = target.Address;

                TcpConnect proxy = Network.TcpControl.GetProxy(target.LocalProxy);

                if (proxy != null)
                    sentBytes = proxy.SendPacket(packet);
                else
                    sentBytes = Network.TcpControl.SendRandomProxy(packet);

                //log += " proxied by local tcp";
            }

            Bandwidth.OutPerSec += sentBytes;

            //Session.Log(log);
        }
Example #14
0
        public void RudpReceive(G2ReceivedPacket raw, RudpPacket packet, bool global)
        {
            // check if packet meant for another socket
            if(packet.PeerID != 0 && packet.PeerID != PeerID)
                return;

            // check for errors
            string error = null;

            if(packet.Sequence > HighestSeqRecvd && State == RudpState.Closed) // accept only packets that came before the fin
                error = "Packet Received while in Close State ID " + packet.PeerID.ToString() + ", Type " + packet.PacketType.ToString();

            else if (packet.Payload.Length > 4096)
            {
                error = "Too Large Packet Received Size " + packet.Payload.Length.ToString() + ", Type " + packet.PacketType.ToString();
                RudpClose(CloseReason.LARGE_PACKET);
            }

            if( error != null )
            {
                Session.Log(error);
                return;
            }

            Bandwidth.InPerSec += raw.Root.Data.Length;

            // add proxied and direct addresses
            // proxied first because that packet has highest chance of being received, no need for retry
            // also allows quick udp hole punching
            if (raw.ReceivedTcp)
                AddAddress(new RudpAddress(raw.Source, raw.Tcp));

            AddAddress( new RudpAddress(raw.Source) ); // either direct node, or node's proxy

            // received syn, ident 5, from 1001 over tcp
            /*string log = "Received " + packet.PacketType.ToString();
            if (packet.Ident != 0) log += " ID:" + packet.Ident.ToString();
            log += " from " + raw.Source.ToString();

            if (raw.Tcp != null)
                log += " tcp";
            else
                log += " udp";
            Session.Log(log);*/

            if (packet.PacketType == RudpPacketType.Unreliable)
            {
                Session.UnreliableReceive(packet.Payload);
                return;
            }

            // try to clear up bufffer, helps if full, better than calling this on each return statement
            ManageRecvWindow();

            // if ACK, PING, or PONG
            if (packet.PacketType == RudpPacketType.Ack || packet.PacketType == RudpPacketType.Ping || packet.PacketType == RudpPacketType.Pong)
            {
                if (packet.PacketType == RudpPacketType.Ack)
                    ReceiveAck(packet);

                if (packet.PacketType == RudpPacketType.Ping)
                    ReceivePing(packet);

                if (packet.PacketType == RudpPacketType.Pong)
                    ReceivePong(packet);

                return;
            }

            // if SYN, DATA or FIN packet

            // stop acking so remote host catches up
            if (packet.Sequence > HighestSeqRecvd + MAX_WINDOW_SIZE || RecvPacketMap.Count > MAX_WINDOW_SIZE)
            {
                //Session.Log("Error Packet Overflow");
                return;
            }

            // Send Ack - cant combine if statements doesnt work
            if( AckMap.Contains(packet.Sequence) )
            {
                //Session.Log("Error Packet Seq " + packet.Sequence.ToString() + " Already Received");
                SendAck(packet);
                return;
            }

            // insert into recv map
            lock (RecvPacketMap)
            {
                RecvPacketMap[packet.Sequence] = packet;
            }

            ManageRecvWindow();

            // ack down here so highest received is iterated, syns send own acks
            if (packet.PacketType != RudpPacketType.Syn)
                SendAck(packet);
        }
Example #15
0
 public TrackPacket(RudpPacket packet)
 {
     Packet = packet;
 }
Example #16
0
        void StartFin(CloseReason reason)
        {
            FinPacket = new RudpPacket();

            lock (SendSection) // ensure queued in right order with right current seq
            {
                FinPacket.TargetID = Session.UserID;
                FinPacket.TargetClient = Session.ClientID;
                FinPacket.PeerID = RemotePeerID;
                FinPacket.PacketType = RudpPacketType.Fin;
                FinPacket.Payload = new byte[1] { (byte)reason };
            }

            ChangeState(RudpState.Finishing);
            FinTimeout = 15;

            TrySendFin();

            //Session.Log("Fin Sent, Seq " + fin.Sequence.ToString() + ", ID " + fin.PeerID.ToString() + ", Reason " + reason.ToString());

            ManageSendWindow(); // immediately try to send the fin
        }