Exemple #1
0
        /// <summary>
        /// Handles a solution packet
        /// </summary>
        /// <param name="solution">Solution.</param>
        private void HandleSolution(UdpSolution solution, EndPoint endpoint)
        {
            var ipEndpoint = (IPEndPoint)endpoint;
            var address    = ipEndpoint.Address;

            if (connections.TryGetValue(ipEndpoint, out var oldcon))
            {
                if (oldcon.salt != solution.salt)
                {
                    Log.Write("New connection failed: already an existing connection");
                    return;
                }

                Send(new UdpConnected(oldcon.salt, (ushort)oldcon.LocalPort), endpoint);
                return;
            }

            if (!requestStates.TryGetValue(ipEndpoint, out var state))
            {
                Log.Write("New connection failed: no request state found");
                return;
            }

            var saltSolution = Udp.CreateSalt(state.clientSalt, state.serverSalt);

            if (solution.salt != saltSolution)
            {
                Log.Write("New connection failed: salt solution invalid");
                return;
            }

            if (!requestStates.TryRemove(ipEndpoint, out state))
            {
                Log.Write("New connection failed: no request state to remove");
                return;
            }

            if (!availablePorts.TryDequeue(out int port))
            {
                Log.Write("New connection failed: failed to assign port");
                return;
            }

            var connection = (TCon)Activator.CreateInstance(typeof(TCon));

            if (!connections.TryAdd(ipEndpoint, connection))
            {
                availablePorts.Enqueue(port); // return port
                connection.Disconnect(UdpDisconnectReason.Custom, true, "Failed to add connection");
                Log.Write("New connection failed: failed to add connection");
                return;
            }

            connection.SetConnectedTo(endpoint, saltSolution, port);
            connection.OnDisconnect += ClientDisconnected;
            HandleConnection(connection);
            connection.StartRead();

            Send(new UdpConnected(saltSolution, (ushort)port), endpoint);
        }
Exemple #2
0
        /// <summary>
        /// Read callback for the receiving socket
        /// </summary>
        /// <param name="ar">Ar.</param>
        private void OnRead(IAsyncResult ar)
        {
            EndPoint fromEndpoint = new IPEndPoint(IPAddress.Any, 0);
            int      length       = 0;

            try
            {
                length = socket.EndReceiveFrom(ar, ref fromEndpoint);
            }
            catch (ObjectDisposedException)
            {
                return;
            }

            byte[] data = new byte[length];
            System.Buffer.BlockCopy(buffer.data, 0, data, 0, length);
            BeginRead(); // start reading for more packets

            BitReader r     = new BitReader(data, length);
            bool      isUdp = r.ReadBool();

            if (!isUdp)
            {
                return;         // only accept udp packets
            }
            byte id     = r.ReadUInt8();
            var  packet = Udp.CreateUdpPacket(id);

            if (packet == null)
            {
                return;                 // failed to create a packet from the given id value
            }
            packet.ReadPacket(r);
            HandlePacket(packet, fromEndpoint);
        }
Exemple #3
0
        /// <summary>
        /// Handles a connect packet
        /// </summary>
        /// <param name="connect">Connect.</param>
        private void HandleConnect(UdpConnect connect, EndPoint endpoint)
        {
            var ipEndpoint = (IPEndPoint)endpoint;

            //var address = ipEndpoint.Address;

            if (availablePorts.Count == 0) // no available ports
            {
                Send(new UdpDisconnect(connect.clientSalt, UdpDisconnectReason.ServerFull), endpoint);
                return;
            }

            if (connections.TryGetValue(ipEndpoint, out var connection))
            {
                Send(new UdpDisconnect(connect.clientSalt, UdpDisconnectReason.ExistingConnection), endpoint);
                return;
            }

            var state = CreateConnectionRequest(connect.clientSalt, ipEndpoint);

            requestStates[ipEndpoint] = state;

            var saltSolution = Udp.CreateSalt(state.clientSalt, state.serverSalt);

            Send(new UdpChallenge(state.clientSalt, state.serverSalt), endpoint);
        }
Exemple #4
0
 /// <summary>
 /// Connects to a given EndPoint
 /// </summary>
 /// <param name="endpoint"></param>
 public void Connect(EndPoint endpoint)
 {
     // return if already started connection process
     if (!SetConnectionState(ConnectionState.AwaitingChallenge, ConnectionState.ReadyToConnect))
     {
         return;
     }
     remoteEndPoint = endpoint;
     socket.Bind(new IPEndPoint(IPAddress.Any, 0));
     localSalt = Udp.GenerateLocalSalt();
     timer.Start();
     StartRead();
     SendConnect();
 }
Exemple #5
0
 /// <summary>
 /// Responds to a challenge packet received from the remote server
 /// </summary>
 /// <param name="challenge">Challenge.</param>
 private void HandleChallenge(UdpChallenge challenge)
 {
     if (challenge.clientSalt != localSalt)
     {
         return;                                    // salt mismatch, could be spoofed sender
     }
     if (!SetConnectionState(ConnectionState.AwaitingConnected, ConnectionState.AwaitingChallenge))
     {
         return;
     }
     remoteSalt = challenge.serverSalt;
     salt       = Udp.CreateSalt(localSalt, remoteSalt);
     retryCount = 0;
     SendSolution();
 }
Exemple #6
0
        /// <summary>
        /// Packet data received
        /// </summary>
        /// <param name="length"></param>
        protected void ReceivedData(byte[] data, int length)
        {
            BitReader r     = new BitReader(data, length);
            bool      isUdp = r.ReadBool();
            byte      id;

            if (isUdp)
            {
                id = r.ReadUInt8();
                var udpPacket = Udp.CreateUdpPacket(id);
                if (udpPacket == null)
                {
                    return;
                }
                udpPacket.ReadPacket(r);
                HandleUdpPacket(udpPacket);
                return;
            }

            ulong receivedSalt = r.ReadUInt64();

            if (receivedSalt != salt)
            {
                return;                       // salt mismatch, TODO disconnect
            }
#if DEBUG
            if (Rand.Next(10000) / 100.0 < Simulate_Packet_Loss_Percent)
            {
                Log.Error("Stopped packet: " + r.ReadUInt16());
                return;
            }
#endif
            lastReceived = DateTime.Now;

            id = r.ReadUInt8();         // read packet type
            var channel = channels[id]; // get channel for packet type

            channel.ReceivePacket(r, id);
        }
Exemple #7
0
        private ConnectRequestState CreateConnectionRequest(ulong clientSalt, IPEndPoint ipEndpoint)
        {
            ulong serverSalt = Udp.GenerateLocalSalt();

            return(new ConnectRequestState(clientSalt, serverSalt, ipEndpoint));
        }