/* 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; }
/// <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); } }
/// <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."); } } }
/// <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; } }
/// <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."); } } }
/// <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(); } }
/// <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; }
/// <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; }
/// <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); } }