예제 #1
0
        /*
        static double _noneTime = 0.0f;
        static int _noneSize = 0;

        static int _encodeSize = 0;
        static double _encodeTime = 0.0f;
        static int  _encodeCompressSize = 0;
        static double _encodeCompressTime = 0.0f;
        static int  _encodeCompressEncryptSize = 0;
        static double _encodeCompressEncryptTime = 0.0f;
          static int   _compressSize = 0;
        static double _compressTime = 0.0f;
           static int  _compressEncryptSize = 0;
        static double _compressEncryptTime = 0.0f;
          static int   _encryptSize = 0;
        static double _encryptTime = 0.0f;
        static int _encryptEncodeSize = 0;
        static double _encryptEncodeTime = 0.0f;

        static int _packetCounter = 0;
        */
        /// <summary>
        ///     Serializes this packet to a byte buffer than can be recreated by calling FromBuffer.
        /// </summary>
        /// <param name="inReplyTo">If not null this packet is marked as a reply to another packet.</param>
        /// <param name="cryptor">The encryption class to encrypt the buffer with.</param>
        /// <param name="compressor">Compressor used to compress the packet.</param>
        /// <param name="encoder">Encoder used for delta-encoding of packets.</param>
        /// <returns>Byte buffer conversion of packet.</returns>
        public byte[] ToBuffer(Packet inReplyTo, StreamEncryptor cryptor, StreamCompressor compressor, StreamDeltaEncoder encoder)
        {
            byte[] data = CreatePayload();

            // Data cannot be larger than a ushort.
            if (data.Length >= ushort.MaxValue)
            {
                throw new InvalidDataException("Packets cannot be larger than a ushort's max value.");
            }

            // Work out checksum of unmodified payload.
            PearsonHash hash = new PearsonHash();
            hash.AddBuffer(data, 0, data.Length);
            byte dataChecksum = hash.Calculate();

            // Mangle our data based ready for transport.
            data = MangleData(data, encoder, compressor, cryptor);

            // DEBUG TIMING
            /*
            HighPerformanceTimer timer = new HighPerformanceTimer();

            StreamEncryptor tmp_cryptor = cryptor == null ? null : cryptor.Clone();
            StreamCompressor tmp_compressor = new StreamCompressor();
            StreamDeltaEncoder tmp_encoder = encoder == null ? null : encoder.Clone();

            byte[] tmp = CreatePayload();
            timer.Start();
            _noneSize += MangleData(tmp, null, null, null).Length;
            _noneTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeSize += MangleData(tmp, tmp_encoder, null, null).Length;
            _encodeTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeCompressSize += MangleData(tmp, tmp_encoder, tmp_compressor, null).Length;
            _encodeCompressTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encodeCompressEncryptSize += MangleData(tmp, tmp_encoder, tmp_compressor, tmp_cryptor).Length;
            _encodeCompressEncryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _compressSize += MangleData(tmp, null, tmp_compressor, null).Length;
            _compressTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _compressEncryptSize += MangleData(tmp, null, tmp_compressor, tmp_cryptor).Length;
            _compressEncryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encryptSize += MangleData(tmp, null, null, tmp_cryptor).Length;
            _encryptTime += timer.Stop();

            tmp = CreatePayload();
            timer.Start();
            _encryptEncodeSize += MangleData(tmp, tmp_encoder, null, tmp_cryptor).Length;
            _encryptEncodeTime += timer.Stop();

            _packetCounter++;
            if (_packetCounter >= 100000)
            {
                System.Console.WriteLine("DONE!");
            }
             * */
            // DEBUG TIMING

            // Write in data checksum.
            byte[] buffer = new byte[HEADER_SIZE + data.Length];
            buffer[0] = dataChecksum;

            // Write in payload size.
            byte[] bytes = BitConverter.GetBytes((ushort)data.Length);
            buffer[1] = bytes[0];
            buffer[2] = bytes[1];

            // Write in class hash.
            bytes = BitConverter.GetBytes(this.GetType().FullName.GetHashCode());
            buffer[3] = bytes[0];
            buffer[4] = bytes[1];
            buffer[5] = bytes[2];
            buffer[6] = bytes[3];

            // Write in a reply-to-packet-id.
            bytes = BitConverter.GetBytes(inReplyTo == null ? 0 : inReplyTo.PacketID);
            buffer[7] = bytes[0];
            buffer[8] = bytes[1];

            // Write in payload.
            for (int i = 0; i < data.Length; i++)
            {
                buffer[HEADER_SIZE + i] = data[i];
            }

            return buffer;
        }
예제 #2
0
        /// <summary>
        ///     Processes a packet that has been recieved from a client.
        /// </summary>
        /// <param name="packet">Packet that we recieved.</param>
        private void ProcessIncomingPacket(Packet packet)
        {
            // -----------------------------------------------------------------
            // Client is attempting to login.
            // -----------------------------------------------------------------
            if (packet is LoginPacket)
            {
                LoginPacket specificPacket = packet as LoginPacket;
                LoginResultPacket reply = new LoginResultPacket();

                reply.Result = LoginResult.Success;

                // Already logged into an account?
                if (m_account != null)
                {
                    reply.Result = LoginResult.AlreadyLoggedIn;
                }

                else
                {
                    UserAccount account = UserAccount.LoadByUsername(m_arbitrator.DatabaseConnection, specificPacket.Username);

                    // Account not found?
                    if (account == null)
                    {
                        reply.Result = LoginResult.AccountNotFound;
                    }

                    // Password invalid?
                    else if (account.Password != specificPacket.Password)
                    {
                        reply.Result = LoginResult.PasswordInvalid;
                    }

                    // Account already in us?
                    else
                    {
                        DBResults results = m_arbitrator.DatabaseConnection.Query(@"SELECT id FROM {0} WHERE account_id={1}",
                                                                                   Settings.DB_TABLE_ACTIVE_CLIENTS,
                                                                                   account.ID);

                        // Account already in us?
                        if (results.RowsAffected > 0)
                        {
                            reply.Result = LoginResult.AccountInUse;
                        }

                        // Success! Mark client as logged in.
                        else
                        {
                            m_arbitrator.DatabaseConnection.Query(@"UPDATE {0} SET account_id={1} WHERE id={2}",
                                                                    Settings.DB_TABLE_ACTIVE_CLIENTS,
                                                                    account.ID,
                                                                    m_clientDatabaseID);
                            m_account = account;
                        }
                    }
                }

                m_connection.SendPacket(reply, specificPacket);
            }

            // -----------------------------------------------------------------
            // Client is attempting to create an account.
            // -----------------------------------------------------------------
            else if (packet is CreateAccountPacket)
            {
                CreateAccountPacket specificPacket = packet as CreateAccountPacket;
                CreateAccountResultPacket reply = new CreateAccountResultPacket();

                reply.Result = CreateAccountResult.Success;

                // Email already exists :(
                if (UserAccount.LoadByEmail(m_arbitrator.DatabaseConnection, specificPacket.Email) != null)
                {
                    reply.Result = CreateAccountResult.EmailAlreadyExists;
                }
                else
                {
                    // Username already exists :(.
                    if (UserAccount.LoadByUsername(m_arbitrator.DatabaseConnection, specificPacket.Username) != null)
                    {
                        reply.Result = CreateAccountResult.UsernameAlreadyExists;
                    }

                    // Create account!
                    else
                    {
                        UserAccount.CreateAccount(m_arbitrator.Settings, m_arbitrator.DatabaseConnection,
                                                  specificPacket.Username,
                                                  specificPacket.Password,
                                                  specificPacket.Email);
                    }
                }

                m_connection.SendPacket(reply, specificPacket);
            }

            // -----------------------------------------------------------------
            // Client is attempting to register as listening and ready to be
            // a superpeer.
            // -----------------------------------------------------------------
            else if (packet is RegisterAsListeningPacket)
            {
                RegisterAsListeningPacket specificPacket = packet as RegisterAsListeningPacket;
                RegisterAsListeningResultPacket reply = new RegisterAsListeningResultPacket();

                if (m_listening == true)
                {
                    reply.Result = RegisterAsListeningResult.AlreadyListening;
                }
                else if (m_account == null)
                {
                    reply.Result = RegisterAsListeningResult.NotLoggedIn;
                }
                else
                {
                    m_listenPort = specificPacket.Port;
                    m_listening = true;

                    reply.Result = RegisterAsListeningResult.Success;

                    // Update the client registration to include listening information.
                    RegisterClient();

                    // Send the peer a world grid.
                    SendUpdatedWorldGrid();

                    // Send account information to them.
                    UserAccountStatePacket p = new UserAccountStatePacket();
                    p.Account                = m_account.Clone();
                    p.Account.Email          = "";
                    p.Account.Password       = "";
                    p.ClientID               = (int)m_clientDatabaseID;
                    m_connection.SendPacket(p);
                }

                m_connection.SendPacket(reply, specificPacket);
            }

            // -----------------------------------------------------------------
            // Client has changed zone.
            // -----------------------------------------------------------------
            else if (packet is ChangeZonePacket)
            {
                ChangeZonePacket specificPacket = packet as ChangeZonePacket;

                Logger.Info("Client moved into zone #{0} from zone #{1}.", LoggerVerboseLevel.High, specificPacket.ZoneID, m_zoneID);

                // Update and save zone information to database.
                m_zoneID = specificPacket.ZoneID;
                RegisterClient();
            }

            // -----------------------------------------------------------------
            // SuperPeer wants account information for a given client.
            // -----------------------------------------------------------------
            else if (packet is SuperPeerRetrieveAccountPacket)
            {
                SuperPeerRetrieveAccountPacket specificPacket = packet as SuperPeerRetrieveAccountPacket;

                // TODO: Check client has authority to retrieve account information for given player.
                //       (eg. its a superpeer in an area the client is). Flag as cheating if not.

                Logger.Info("Client #{0} wants to retrieve account information for player #{1}.", LoggerVerboseLevel.High, m_clientDatabaseID, specificPacket.ClientID);

                // Load clients information from the database.
                DBResults client_info = m_arbitrator.DatabaseConnection.Query(@"SELECT `account_id` FROM {0} WHERE id={1}",
                                                                               Settings.DB_TABLE_ACTIVE_CLIENTS,
                                                                               specificPacket.ClientID);

                // TODO: Add error checking for when client-id is not valid.

                SuperPeerRetrieveAccountReplyPacket reply = new SuperPeerRetrieveAccountReplyPacket();
                reply.SuperPeerID       = specificPacket.SuperPeerID;
                reply.ClientID          = specificPacket.ClientID;
                if (client_info.RowsAffected > 0)
                {
                    reply.Account = UserAccount.LoadByID(m_arbitrator.DatabaseConnection, (int)client_info[0]["account_id"]);
                }
                else
                {
                    reply.Account = new UserAccount();
                    reply.Account.Username = "******";
                }
                reply.Account.Email     = "";
                reply.Account.Password  = "";
                m_connection.SendPacket(reply);
            }

            // -----------------------------------------------------------------
            // SuperPeer wants to store account information for a given client.
            // -----------------------------------------------------------------
            else if (packet is SuperPeerStoreAccountPacket)
            {
                SuperPeerStoreAccountPacket specificPacket = packet as SuperPeerStoreAccountPacket;

                // TODO: Check client has authority to store account information for given player.
                //       (eg. its a superpeer in an area the client is). Flag as cheating if not.

                Logger.Info("Client #{0} wants to store account information for player #{1} in zone #{2}.", LoggerVerboseLevel.High, m_clientDatabaseID, specificPacket.ClientID, specificPacket.ZoneID);

                StoreAccountRequest request = new StoreAccountRequest();
                request.SuperPeerID         = specificPacket.SuperPeerID;
                request.ClientID            = specificPacket.ClientID;
                request.ZoneID              = specificPacket.ZoneID;
                request.RecievedFrom        = this;
                request.Account             = specificPacket.Account;
                request.RecieveTime         = Environment.TickCount;
                request.Reason              = specificPacket.Reason;

                m_arbitrator.StoreAccountRequestRecieved(request);
            }

            // -----------------------------------------------------------------
            // Client wants to gracefully disconnect.
            // -----------------------------------------------------------------
            else if (packet is GracefulDisconnectPacket)
            {
                UnRegisterClient();

                GracefulDisconnectReplyPacket reply = new GracefulDisconnectReplyPacket();
                m_connection.SendPacket(reply, packet);
            }
        }
예제 #3
0
        /// <summary>
        ///     Processes a packet that has been recieved from the arbitrator.
        /// </summary>
        /// <param name="peer">The client or peer we recieved the packet from.</param>
        /// <param name="packet">Packet that we recieved.</param>
        private void ProcessArbitratorIncomingPacket(Connection peer, Packet packet)
        {
            // -----------------------------------------------------------------
            // We've been sent an updated version of the zone grid.
            // -----------------------------------------------------------------           
            if (packet is ZoneGridPacket)
            {
                ZoneGridPacket specificPacket = packet as ZoneGridPacket;
                m_zoneGrid.FromPacket(specificPacket);

                // Invoke events for all super peers who have gained control of zones.
                foreach (ZoneSuperPeer p in m_zoneGrid.GainedSuperPeers)
                {
                    Zone zone = m_zoneGrid.GetZoneByID(p.ZoneID);
                    SuperPeerGainedControl(zone, p);
                }
                
                // Invoke events for all super peers who have lost control of zones.
                foreach (ZoneSuperPeer p in m_zoneGrid.LostSuperPeers)
                {
                    Zone zone = m_zoneGrid.GetZoneByID(p.ZoneID);
                    SuperPeerLostControl(zone, p);
                }

                Logger.Info("Recieved updated zone grid from arbitrator.", LoggerVerboseLevel.High);
            }

            // -----------------------------------------------------------------
            // We've been sent our persistent state information.
            // -----------------------------------------------------------------
            else if (packet is UserAccountStatePacket)
            {
                UserAccountStatePacket specificPacket = packet as UserAccountStatePacket;

                m_account  = specificPacket.Account;
                m_clientID = specificPacket.ClientID;

                if (m_threadNameSet == false)
                {
                    System.Threading.Thread.CurrentThread.Name = "Client #" + m_clientID;
                    m_threadNameSet = true;
                }

                Logger.Info("Recieved updated account information from arbitrator.", LoggerVerboseLevel.High);
            }

            // -----------------------------------------------------------------
            // Information sent to one of our super peers about a client?
            // -----------------------------------------------------------------
            else if ((packet as SuperPeerClientPacket) != null)
            {
                SuperPeerClientPacket specificPacket = packet as SuperPeerClientPacket;
                bool found = false;

                foreach (Connection connection in m_listenConnection.Peers)
                {
                    if (connection.MetaData != null)
                    {
                        GameClientPeer p = ((GameClientPeer)connection.MetaData);
                        foreach (SuperPeerToClientConnection conn in p.SuperPeerConnections)    // ERROR IS HERE: SuperPeerConnections is filled with inactive ones that are recieving the packets too :(
                        {
                            if (conn.SuperPeer.ID == specificPacket.SuperPeerID &&
                                conn.ClientID     == specificPacket.ClientID)
                            {
                                conn.RecievedArbitratorPacket(specificPacket);
                                found = true;
                            }
                        }
                    }
                }

                if (found == false)
                {
                    throw new InvalidOperationException("Failed to find super peer to direct arbitrator packet to.");
                }
            }

            // -----------------------------------------------------------------
            // Information sent to one of our super peers?
            // -----------------------------------------------------------------
            else if ((packet as SuperPeerPacket) != null)
            {
                SuperPeerPacket specificPacket = packet as SuperPeerPacket;
                SuperPeer superpeer = FindSuperPeerByID(specificPacket.SuperPeerID);

                if (superpeer != null)
                {
                    superpeer.ArbitratorRecievedPacket(m_arbitratorConnection, specificPacket);
                }
                else
                {
                    throw new InvalidOperationException("Failed to find super peer to direct arbitrator packet to.");
                }
            }
        }
예제 #4
0
        /// <summary>
        ///     Invoked when a socket send has completed.
        /// </summary>
        /// <param name="sender">Object that invoked this event.</param>
        /// <param name="e">Arguments describing why this event was invoked.</param>
        void SocketIO_Completed(object sender, SocketAsyncEventArgs e)
        {
            // Did we error out? If so, bail out.
            if (e.SocketError != SocketError.Success)
            {
                Logger.Error("Recieved socket error ({0}) during IO, closing socket.", LoggerVerboseLevel.High, e.SocketError.ToString());

                e.Completed -= SocketIO_Completed;
                //g_socketAsyncEventArgsPool.FreeObject(e);
                e.Dispose();                
                
                DisposeSocket(true);
                return;
            }

            // Client has almost certainly disconnected in this situation.
            if (e.BytesTransferred <= 0 || m_socket == null || m_socket.Connected == false)
            {
                if (m_socket != null)// && m_socket.Connected == false)
                {
                    Logger.Error("Socket appears to have closed during IO.", LoggerVerboseLevel.High);
                }

                e.Completed -= SocketIO_Completed;
                //g_socketAsyncEventArgsPool.FreeObject(e);
                e.Dispose();

                DisposeSocket(true);
                return;
            }

            // Track bandwidth stats.
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Send:
                    m_sentBytes += e.BytesTransferred;
                    m_queuedSendBytes -= e.BytesTransferred;
                    
                    e.Completed -= SocketIO_Completed;
                    e.Dispose();    
                    //g_socketAsyncEventArgsPool.FreeObject(e);

                    break;

                case SocketAsyncOperation.Receive:
                    m_recievedBytes += e.BytesTransferred;

                    // What part of the message are we recieving?
                    if (m_readingMessagePayload == true)
                    {
                        if (m_recievePacket.RecievePayload(m_recieveBuffer, m_encryptor, m_compressor, m_deltaEncoder) == true)
                        {
                            Logger.Info("Recieved pack et of type '{0}' of size '{1}' from '{2}'.", LoggerVerboseLevel.Highest, m_recievePacket.GetType().Name, Packet.HEADER_SIZE + m_recieveBuffer.Length, m_endPoint.Serialize().ToString());
                            ProcessPacket(m_recievePacket);
                        }
                        else
                        {
                            Logger.Error("Recieved invalid payload for packet of type '{0}' of size '{1}', dropping packet.", LoggerVerboseLevel.Normal, m_recievePacket.GetType().Name, m_recieveBuffer.Length);
                        }
                        m_readingMessagePayload = false;
                    }
                    else
                    {
                        m_recievePacket = Packet.FromHeader(m_recieveBuffer, m_encryptor, m_compressor, m_deltaEncoder);
                        if (m_recievePacket == null)
                        {
                            Logger.Error("Recieved invalid header for packet of size '{0}', dropping packet.", LoggerVerboseLevel.Normal, m_recieveBuffer.Length);
                        }
                        else
                        {
                            if (m_recievePacket.PayloadSize > 0)
                            {
                                m_readingMessagePayload = true;
                            }
                            else
                            {
                               Logger.Info("Recieved packet of type '{0}' of size '{1}' from '{2}'.", LoggerVerboseLevel.Highest, m_recievePacket.GetType().Name, m_recieveBuffer.Length, m_endPoint.Serialize().ToString());
                                ProcessPacket(m_recievePacket);
                            }
                        }
                    }

                    e.Completed -= SocketIO_Completed;
                    //g_socketAsyncEventArgsPool.FreeObject(e);
                    e.Dispose();

                    // Continue reading.
                    StartRead();

                    break;
            }
        }
예제 #5
0
        /// <summary>
        ///     Processes a packet that has been recieved from a peer.
        /// </summary>
        /// <param name="packet">Packet that we recieved.</param>
        private void ProcessIncomingPacket(Packet packet)
        {
            // Peer is registering for events from a superpeer.
            if (packet is SuperPeerRegisterPacket)
            {
                SuperPeerRegisterPacket specificPacket = packet as SuperPeerRegisterPacket;

                SuperPeer peer = m_gameClient.FindSuperPeerByID(specificPacket.SuperPeerID);

                // Wait on arbitrator until we get information about the super-peer.
                while (peer == null)
                {
                    if (m_gameClient.ConnectedToArbitrator == false)
                    {
                        return;
                    }
                    m_gameClient.PollArbitrator();
                    peer = m_gameClient.FindSuperPeerByID(specificPacket.SuperPeerID);
                }

                if (peer != null)
                {
                    /*
                    foreach (SuperPeerToClientConnection p in m_superPeerConnections)
                    {
                        if (p.SuperPeer.ID == peer.ID &&
                            p.ClientID == specificPacket.ClientID)
                        {
                            p.BeginRegister();
                            return;
                        }
                    }*/

                    SuperPeerToClientConnection conn = new SuperPeerToClientConnection(m_gameClient, peer, m_connection);
                    conn.ClientID = specificPacket.ClientID;
                    m_superPeerConnections.Add(conn);

                    conn.BeginRegister();

                    return;
                }

                throw new Exception("Attempt to register to non-existing superpeer.");
            }

            // Peer is unregistering for events from a superpeer.
            else if (packet is SuperPeerUnregisterPacket)
            {
                SuperPeerUnregisterPacket specificPacket = packet as SuperPeerUnregisterPacket;

                bool found = false;
                foreach (SuperPeerToClientConnection conn in m_superPeerConnections)
                {
                    if (conn.SuperPeer.ID == specificPacket.SuperPeerID)
                    {
                        conn.BeginUnregister(specificPacket.ChangeZoneSuperPeerCount);
                        found = true;

                        // Do not break out of this loop, we may need to send packet to lingering connections as well!
                    }
                }

                if (found == false)
                {
                    throw new Exception("Attempt to unregister from non-existing superpeer.");
                }
            }

            // Peer is sending a super peer a message.
            else if ((packet as SuperPeerPacket) != null)
            {
                SuperPeerPacket specificPacket = packet as SuperPeerPacket;

                bool found = false;
                foreach (SuperPeerToClientConnection peer in m_superPeerConnections)
                {
                    if (peer.SuperPeer.ID == specificPacket.SuperPeerID)
                    {
                        peer.RecievedPacket(specificPacket);
                        found = true;

                        // Do not break out of this loop, we may need to send packet to lingering connections as well!
                    }
                }

                if (found == false)
                {
                    throw new Exception("Attempt to send-packet to non-existing superpeer.");
                }
            }
        }
예제 #6
0
        /// <summary>
        ///     Processes a packet that has just been recieved, if its internal it will do as required, if not it
        ///     will queue it and wait for the host application to deal with it.
        /// </summary>
        /// <param name="packet">Packet to process.</param>
        private void ProcessPacket(Packet packet)
        {
            lock (m_socket_lock)
            {
                // Increment the recieve packet ID.
                m_recvPacketIDCounter++;
                if (m_recvPacketIDCounter >= ushort.MaxValue)
                {
                    m_recvPacketIDCounter = 0;
                }

                // Work out ID of this packet.
                packet.PacketID = m_recvPacketIDCounter;
            }

            // Is someone waiting for this reply?
            ConnectionReplyWaitContext replyContext = null;
            lock (m_replyWaitContexts_lock)
            {
                foreach (ConnectionReplyWaitContext context in m_replyWaitContexts)
                {
                    if (context.SendPacket.PacketID == packet.ReplyToPacketID)
                    {
                        replyContext = context;
                        break;
                    }
                }
            }

            // Process system packet.
            if (ProcessInternalPacket(packet) == false)
            {
                if (m_connectionEstablished == true)
                {
                    // Not internal, leave it to host to deal with.
                    if (replyContext == null)
                    {
                        lock (m_messageQueue_lock)
                        {
                            m_messageQueue.Enqueue(packet);
                        }
                    }
                }
                else
                {
                    // TODO: Store packets till connection is established!
                    Logger.Error("Recieved non-connection based packet before connection was established.", LoggerVerboseLevel.Normal);
                }
            }

            if (replyContext != null)
            {
                replyContext.ReplyPacket = packet;
                replyContext.Event.Set();
            }
        }
예제 #7
0
        /// <summary>
        ///     Processes a packet if its an internal packet.
        /// </summary>
        /// <param name="packet">Packet to process.</param>
        /// <returns>True if the packet was processes, otherwise false.</returns>
        private bool ProcessInternalPacket(Packet packet)
        {
            // Responds to a ping request from a client.
            if (packet is PingPacket)
            {
                PongPacket pong = new PongPacket();
                SendPacket(pong, packet);

                return true;
            }

            // Registers the response from a ping packet we have sent.
            else if (packet is PongPacket)
            {
                m_ping              = Environment.TickCount - m_timeSinceLastPing;
                m_timeSinceLastPong = Environment.TickCount;
                m_waitingForPong    = false;

                return true;
            }

            // Provides connections details regarding their connection.
            else if (packet is ConnectPacket)
            {
                if (m_listenConnection == null)
                {
                    throw new InvalidOperationException("Remote host sent a connect packet to a non-listening connection.");
                }

                ConnectPacket p = (ConnectPacket)packet;

                m_hardwareFingerprint = p.HardwareFingerprint;
                m_guid                = p.ConnectionGUID;
                m_computerUserName    = p.ComputerUserName;
                m_computerName        = p.ComputerName;

                Logger.Info("Connection from {0} established connection.", LoggerVerboseLevel.High, m_endPoint.Serialize().ToString());
                Logger.Info("\tHardware Fingerprint: {0}", LoggerVerboseLevel.High, StringHelper.ByteArrayToHexString(m_hardwareFingerprint));
                Logger.Info("\tGUID: {0}", LoggerVerboseLevel.High, StringHelper.ByteArrayToHexString(m_guid));
                Logger.Info("\tComputer Name: {0}", LoggerVerboseLevel.High, m_computerName);
                Logger.Info("\tComputer User Name: {0}", LoggerVerboseLevel.High, m_computerUserName);

                // Send an AOK message :3.
                ConnectReplyPacket reply = new ConnectReplyPacket();
                SendPacket(reply, packet);

                lock (m_socket_lock)
                {
                    m_connectionEstablished = true;
                    lock (m_listenConnection.m_peers_lock)
                    {
                        m_listenConnection.m_connected_peers.Add(this);
                    }
                    m_encryptor = new StreamEncryptor(GenerateEncryptionKey());
                }

                return true;
            }

            // Finishes establishing a connection.
            else if (packet is ConnectReplyPacket)
            {
                // Generate new encryption keys.
                lock (m_socket_lock)
                {
                    m_encryptor = new StreamEncryptor(GenerateEncryptionKey());
                }

                m_connectionEstablished = true;
            }

            // Disconnects the user from the server gracefully.
            else if (packet is DisconnectPacket)
            {
                DisconnectAsync(true).Wait();
                return true;
            }

            return false;
        }
예제 #8
0
        /// <summary>
        ///     Sends a packet to the host on the other end of the connection and waits asynchronously for a reply.
        /// </summary>
        /// <returns>The packet recieved in reply, or null if we failed to recieve a reply.</returns>
        /// <param name="packet">Packet ot send.</param>
        /// <param name="inReplyTo">Packet that the packet being sent is in reply to.</param>
        /// <param name="timeout">If a packet is not recieved within this time (in milliseconds), the function will return null.</param>
        public async Task<Packet> SendPacketAndWaitAsync(Packet packet, Packet inReplyTo = null, int timeout = 60000)
        {
            // Log that we are currently waiting for a reply to this packet.
            ConnectionReplyWaitContext context = new ConnectionReplyWaitContext();
            context.SendPacket  = packet;
            context.ReplyPacket = null;

            lock (m_replyWaitContexts_lock)
            {
                m_replyWaitContexts.Add(context);
            }

            // Wait for a reply.
            Packet reply = await Task<Packet>.Run(() => 
            {
                // Send the packet.
                SendPacket(packet, inReplyTo);
                
                // Await the reply.
                Packet replyPacket = null;
                if (context.Event.WaitOne(timeout) == true)
                {
                    replyPacket = context.ReplyPacket;
                }

                // Remove the context.
                lock (m_replyWaitContexts_lock)
                {
                    if (m_replyWaitContexts.Contains(context))
                    {
                        m_replyWaitContexts.Remove(context);
                    }
                }

                // Return the reply!
                return context.ReplyPacket;
            });

            return reply;
        }
예제 #9
0
        /// <summary>
        ///     Sends a packet to the host on the other end of the connection.
        /// </summary>
        /// <param name="packet">Packet ot send.</param>
        /// <param name="inReplyTo">Packet that the packet being sent is in reply to.</param>
        public void SendPacket(Packet packet, Packet inReplyTo = null)
        {
            // If we are a listen-server then send messages to all child peers.
            if (m_listening == true)
            {
                lock (m_peers_lock)
                {
                    foreach (Connection connection in m_peers)
                    {
                        connection.SendPacket(packet, inReplyTo);
                    }
                }
            }

            // Send as a peer.
            else
            {
                if (m_socket == null || m_connected == false || (m_connectionEstablished == false && (packet as ConnectPacket) == null && (packet as ConnectReplyPacket) == null))
                {
                   // throw new InvalidOperationException("Attempt to send packet to unconnected socket!");
                }

                lock (m_socket_lock)
                {
                    if (m_socket != null && m_connected == true)
                    {
                        // Increment the send packet counter.
                        m_sendPacketIDCounter++;
                        if (m_sendPacketIDCounter >= ushort.MaxValue)
                        {
                            m_sendPacketIDCounter = 0;
                        }

                        // Give the packet a new unique ID.
                        packet.PacketID = m_sendPacketIDCounter;

                        // Convert packet to a buffer!
                        byte[] buffer = packet.ToBuffer(inReplyTo, m_encryptor, m_compressor, m_deltaEncoder);

                        //Logger.Info("Sending packet of type '{0}' of size '{1}' to '{2}'.", LoggerVerboseLevel.Highest, packet.GetType().Name, buffer.Length, m_endPoint.Serialize().ToString());

                        try
                        {
                            SocketAsyncEventArgs e = new SocketAsyncEventArgs();//g_socketAsyncEventArgsPool.NewObject();//new SocketAsyncEventArgs();
                            e.Completed += SocketIO_Completed;
                            e.UserToken = this;
                            e.SetBuffer(buffer, 0, buffer.Length);

                            m_queuedSendBytes += buffer.Length;

                            if (!m_socket.SendAsync(e))
                            {
                                SocketIO_Completed(this, e);
                            }
                        }
                        catch (SocketException)
                        {
                            // Most likely we've been disconnect, we can ignore this as the disconnect code will deal with reconnections.
                        }
                    }
                }
            }
        }
        /// <summary>
        ///     Processes an incoming packet from the super peer.
        /// </summary>
        /// <param name="packet">Packet to process.</param>
        public void ProcessIncomingPacket(Packet packet)
        {
            // Has superpeer aknowledged our registering of them.
            if (packet is SuperPeerRegisterReplyPacket)
            {
                SuperPeerRegisterReplyPacket specificPacket = packet as SuperPeerRegisterReplyPacket;

                m_service.SuperPeerRegistered(specificPacket.SuperPeerID);
            }

            // Has superpeer aknowledged our unregistering of them.
            else if (packet is SuperPeerUnregisterReplyPacket)
            {
                SuperPeerUnregisterReplyPacket specificPacket = packet as SuperPeerUnregisterReplyPacket;
                m_service.SuperPeerUnregistered(specificPacket.SuperPeerID);
            }

            // Has superpeer sent us a world state?
            else if (packet is SuperPeerWorldStatePacket)
            {
                SuperPeerWorldStatePacket specificPacket = packet as SuperPeerWorldStatePacket;
                m_service.RecievedWorldState(specificPacket);
            }
        }