public NetIO(Socket sock, Dictionary <ushort, Packet> commandTable, Client client, bool isgateway) { this.sock = sock; this.stream = new NetworkStream(sock); this.commandTable = commandTable; this.client = client; this.isGateway = isgateway; this.callbackSize = new AsyncCallback(this.ReceiveSize); this.callbackData = new AsyncCallback(this.ReceiveData); this.nlock = new ReaderWriterLock(); // Use the static key untill the keys have been exchanged this.clientKey = new byte[16]; Encryption.StaticKey.CopyTo(this.clientKey, 0); this.serverKey = new byte[16]; Encryption.StaticKey.CopyTo(this.serverKey, 0); this.isDisconnected = false; // Receive the size of the next packet and call ReceiveSize when finished if (sock.Connected) { try { stream.BeginRead(buffer, 0, 2, this.callbackSize, null); } catch (Exception ex) { Logger.ShowError(ex, null); try//this could crash the gateway somehow,so better ignore the Exception { this.Disconnect(); } catch (Exception) { } Logger.ShowWarning("Paquete invalido de:" + sock.RemoteEndPoint.ToString(), null); return; } } else { this.Disconnect(); return; } }
private void StartPacketParsing() { if (sock.Connected) { try { stream.BeginRead(buffer, 0, 4, this.callbackSize, null); } catch (Exception ex) { Logger.ShowError(ex, null); try//this could crash the gateway somehow,so better ignore the Exception { this.Disconnect(); } catch (Exception) { } Logger.ShowWarning("Invalid packet head from:" + sock.RemoteEndPoint.ToString(), null); return; } } else { this.Disconnect(); return; } }
private void ReceiveSize(IAsyncResult ar) { try { if (this.isDisconnected) { return; } if (buffer[0] == 0xFF && buffer[1] == 0xFF & buffer[2] == 0xFF && buffer[3] == 0xFF) { // if the buffer is marked as "empty", there was an error during reading // normally happens if the client disconnects // note: this is required as sock.Connected still can be true, even the client // is already disconnected ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } if (!sock.Connected) { ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } try { stream.EndRead(ar); } catch (Exception) { ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } Array.Reverse(buffer); uint size = BitConverter.ToUInt32(buffer, 0) + 4; if (size < 4) { Logger.ShowWarning(sock.RemoteEndPoint.ToString() + " error: packet size is < 4", null); return; } /*while (sock.Available+4 < size) * { * //Logger.ShowWarning(sock.RemoteEndPoint.ToString() + string.Format(" error: packet data is too short, should be {0:G}", size - 2), null); * Thread.Sleep(100); * }*/ byte[] data = new byte[size + 4]; // mark buffer as "empty" buffer[0] = 0xFF; buffer[1] = 0xFF; buffer[2] = 0xFF; buffer[3] = 0xFF; lastSize = (int)size; if (sock.Available < lastSize) { size = (uint)sock.Available; } if (size > 1024) { size = 1024; alreadyReceived = 1024; } else { alreadyReceived = (int)size; } // Receive the data from the packet and call the receivedata function // The packet is stored in AsyncState //Console.WriteLine("New packet with size " + p.size); try { stream.BeginRead(data, 4, (int)(size), this.callbackData, data); } catch (Exception ex) { ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } catch (Exception e) { Logger.ShowError(e, null); } }
private void ReceiveData(IAsyncResult ar) { try { this.nlock.AcquireWriterLock(Timeout.Infinite); if (this.isDisconnected) { this.nlock.ReleaseWriterLock(); return; } if (!sock.Connected) { this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } try { stream.EndRead(ar); } catch (Exception) { this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } byte[] raw = (byte[])ar.AsyncState; if (this.isGateway) { raw = Encryption.Decrypt(raw, 2, this.ClientKey); } if (!isGateway) { ushort messageID = (ushort)(raw[7] + (raw[6] << 8)); if (!this.commandTable.ContainsKey((messageID))) { if (!this.fullHeader) { Logger.ShowWarning(string.Format("Un paquete desconocido {0:X} {1:X} desde " + sock.RemoteEndPoint.ToString(), raw[6], raw[7]), null); } else { if (commandTable.ContainsKey((ushort)0xFFFF)) { if (this.commandTable[(ushort)0xFFFF].SizeIsOk((ushort)raw.Length)) { Packet p = this.commandTable[(ushort)0xFFFF].New(); p.data = raw; p.size = (ushort)(raw.Length); ClientManager.EnterCriticalArea(); try { p.Parse(this.client); } catch (Exception ex) { Logger.ShowError(ex); } ClientManager.LeaveCriticalArea(); } else { string error = "Paquete invalido del cliente " + sock.RemoteEndPoint.ToString(); Console.WriteLine(error); Log.WriteLog(error); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } else { Logger.ShowWarning("Paquete universal 0xFFFF no definido!", null); } } } else { if (this.commandTable[messageID].SizeIsOk((ushort)raw.Length)) { Packet p = this.commandTable[messageID].New(); p.data = raw; p.size = (ushort)(raw.Length); Client client; if (p.SessionID != 0) { client = this.currentClientManager.GetClient(p.SessionID); if (client == null) { client = this.client; } } else { client = this.client; } ClientManager.EnterCriticalArea(); try { if (client.netIO == null) { client.netIO = this; } p.Parse(client); } catch (Exception ex) { Logger.ShowError(ex); } ClientManager.LeaveCriticalArea(); } else { string error = string.Format("Tamano del paquete invalido (Paquete:{0:X4}) de cliente {1}", messageID, sock.RemoteEndPoint.ToString()); Console.WriteLine(error); Log.WriteLog(error); this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } } else { ushort messageID; if (!fullHeader) { messageID = (ushort)(raw[7] + (raw[6] << 8)); if (!this.commandTable.ContainsKey((messageID))) { Logger.ShowWarning(string.Format("Se ha obtenido un paquete desconocido {0:X} {1:X} desde " + sock.RemoteEndPoint.ToString(), raw[6], raw[7]), null); } else { if (this.commandTable[messageID].SizeIsOk((ushort)raw.Length)) { Packet p = this.commandTable[messageID].New(); p.data = raw; p.size = (ushort)(raw.Length); p.isGateway = this.isGateway; ClientManager.EnterCriticalArea(); try { p.Parse(this.client); } catch (Exception ex) { Logger.ShowError(ex); } ClientManager.LeaveCriticalArea(); } else { string error = "Invalid packet size from client " + sock.RemoteEndPoint.ToString(); Console.WriteLine(error); Log.WriteLog(error); this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } } else { if (commandTable.ContainsKey((ushort)0xFFFF)) { if (this.commandTable[(ushort)0xFFFF].SizeIsOk((ushort)raw.Length)) { Packet p = this.commandTable[(ushort)0xFFFF].New(); p.data = raw; p.size = (ushort)(raw.Length); p.isGateway = this.isGateway; ClientManager.EnterCriticalArea(); try { p.Parse(this.client); } catch (Exception ex) { Logger.ShowError(ex); } ClientManager.LeaveCriticalArea(); } else { string error = "Invalid packet size from client " + sock.RemoteEndPoint.ToString(); Console.WriteLine(error); Log.WriteLog(error); this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } else { Logger.ShowWarning("Universal Packet 0xFFFF not defined!", null); } } } try { this.nlock.ReleaseWriterLock(); stream.BeginRead(buffer, 0, 2, this.callbackSize, null); } catch (Exception) { ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } catch (Exception e) { Logger.ShowError(e, null); } }
private void ReceiveSize(IAsyncResult ar) { this.nlock.AcquireWriterLock(Timeout.Infinite); try { if (this.isDisconnected) { this.nlock.ReleaseWriterLock(); return; } if (buffer[0] == 0xFF && buffer[1] == 0xFF) { // if the buffer is marked as "empty", there was an error during reading // normally happens if the client disconnects // note: this is required as sock.Connected still can be true, even the client // is already disconnected this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } if (!sock.Connected) { this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } try { stream.EndRead(ar); } catch (Exception) { this.nlock.ReleaseWriterLock(); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } ushort size = BitConverter.ToUInt16(buffer, 0); if (size < 4) { Logger.ShowWarning(sock.RemoteEndPoint.ToString() + " error: el tamano del paquete es < 4", null); /*try//this could crash the gateway somehow,so better ignore the Exception * { * ClientManager.EnterCriticalArea(); * this.Disconnect(); * ClientManager.LeaveCriticalArea(); * } * catch (Exception ex) * { * Logger.ShowError(ex, null); * //sock.Disconnect(true); * sock.Close(); * ClientManager.LeaveCriticalArea(); * }*/ this.nlock.ReleaseWriterLock(); return; } if (sock.Available < (size - 2)) { Logger.ShowWarning(sock.RemoteEndPoint.ToString() + string.Format(" error: los datos del paquete son demaciados cortos, debe ser {0:G}", size - 2), null); /*try//this could crash the gateway somehow,so better ignore the Exception * { * ClientManager.EnterCriticalArea(); * this.Disconnect(); * ClientManager.LeaveCriticalArea(); * } * catch (Exception) * { * //sock.Disconnect(true); * sock.Close(); * ClientManager.LeaveCriticalArea(); * }*/ //this.nlock.ReleaseWriterLock(); //return; } byte[] data = new byte[size]; data[0] = buffer[0]; data[1] = buffer[1]; // mark buffer as "empty" buffer[0] = 0xFF; buffer[1] = 0xFF; // Receive the data from the packet and call the receivedata function // The packet is stored in AsyncState //Console.WriteLine("New packet with size " + p.size); try { this.nlock.ReleaseWriterLock(); stream.BeginRead(data, 2, size - 2, this.callbackData, data); } catch (Exception) { //Logger.ShowError(ex, null); ClientManager.EnterCriticalArea(); this.Disconnect(); ClientManager.LeaveCriticalArea(); return; } } catch (Exception e) { Logger.ShowError(e, null); } }