private static void EndReceive(IAsyncResult ar) { var client = (Client)ar.AsyncState; var socket = client.Socket; try { int count = socket.EndReceive(ar); for (int i = 0; i < count; ++i) { client.fullRecvBuffer.Add(client.recvBuffer[i]); } if (count == 0 || client.fullRecvBuffer[0] != 0xAA) { Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received", client.ConnectionId); client.Connected = false; return; } while (client.fullRecvBuffer.Count > 3) { Logger.Debug("in fullRecvBuffer loop"); int length = client.fullRecvBuffer[1]*256 + client.fullRecvBuffer[2] + 3; if (length > client.fullRecvBuffer.Count) break; var range = client.fullRecvBuffer.GetRange(0, length); var buffer = range.ToArray(); client.fullRecvBuffer.RemoveRange(0, length); var packet = new ClientPacket(buffer); if (packet.ShouldEncrypt) packet.Decrypt(client); if (packet.Opcode == 0x39 || packet.Opcode == 0x3A) packet.DecryptDialog(); if (client.Connected) { if (Constants.PACKET_THROTTLES.ContainsKey(packet.Opcode)) { ThrottleInfo tinfo; if (client.Throttle.TryGetValue(packet.Opcode, out tinfo)) { tinfo.Received(); if (tinfo.IsThrottled) { Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttled", client.ConnectionId, packet.Opcode); if (tinfo.TotalThrottled > tinfo.Throttle.DisconnectAfter) { Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttle limit reached: disconnected", client.ConnectionId, packet.Opcode); client.Connected = false; break; } client.recving = false; continue; } } else { // We've never seen this packet before on this client. And obviously, as a result, // we can be neither squelched nor throttled. Logger.DebugFormat("cid {0}: creating throttle for opcode 0x{0:X2}", client.ConnectionId, packet.Opcode); client.Throttle[packet.Opcode] = new ThrottleInfo(packet.Opcode); } } Logger.Debug("Proceeding to packet processing"); // For Lobby and Login, we simply process the packet as we can do so in a // thread safe manner. // For World, which involves game logic, we queue the packet for processing by // the world consumer thread. try { if (client.Server is Lobby) { Logger.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode); var handler = (client.Server as Lobby).PacketHandlers[packet.Opcode]; handler.Invoke(client, packet); client.UpdateLastReceived(); } else if (client.Server is Login) { var handler = (client.Server as Login).PacketHandlers[packet.Opcode]; handler.Invoke(client, packet); Logger.DebugFormat("Login: 0x{0:X2}", packet.Opcode); client.UpdateLastReceived(); } else { if (packet.Opcode != 0x45 && packet.Opcode != 0x75) { // Heartbeats don't effect our idle calcuations client.UpdateLastReceived((packet.Opcode != 0x45 && packet.Opcode != 0x75)); } Logger.DebugFormat("Queuing: 0x{0:X2}", packet.Opcode); World.MessageQueue.Add(new HybrasylClientMessage(packet, client.ConnectionId)); } } catch (Exception e) { Logger.ErrorFormat("EXCEPTION IN HANDLING: {0}: {1}", packet.Opcode, e); } client.recving = false; } } } catch (Exception e) { client.Connected = false; Logger.ErrorFormat(e.ToString()); } }
private static void EndReceive(IAsyncResult ar) { var client = (Client)ar.AsyncState; var socket = client.Socket; try { int count = socket.EndReceive(ar); for (int i = 0; i < count; ++i) { client.fullRecvBuffer.Add(client.recvBuffer[i]); } if (count == 0 || client.fullRecvBuffer[0] != 0xAA) { Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received", client.ConnectionId); client.Connected = false; return; } while (client.fullRecvBuffer.Count > 3) { Logger.Debug("in fullRecvBuffer loop"); int length = client.fullRecvBuffer[1] * 256 + client.fullRecvBuffer[2] + 3; if (length > client.fullRecvBuffer.Count) { break; } var range = client.fullRecvBuffer.GetRange(0, length); var buffer = range.ToArray(); client.fullRecvBuffer.RemoveRange(0, length); var packet = new ClientPacket(buffer); if (packet.ShouldEncrypt) { packet.Decrypt(client); } if (packet.Opcode == 0x39 || packet.Opcode == 0x3A) { packet.DecryptDialog(); } if (client.Connected) { if (Constants.PACKET_THROTTLES.ContainsKey(packet.Opcode)) { ThrottleInfo tinfo; if (client.Throttle.TryGetValue(packet.Opcode, out tinfo)) { tinfo.Received(); if (tinfo.IsThrottled) { Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttled", client.ConnectionId, packet.Opcode); if (tinfo.TotalThrottled > tinfo.Throttle.DisconnectAfter) { Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttle limit reached: disconnected", client.ConnectionId, packet.Opcode); client.Connected = false; break; } client.recving = false; continue; } } else { // We've never seen this packet before on this client. And obviously, as a result, // we can be neither squelched nor throttled. Logger.DebugFormat("cid {0}: creating throttle for opcode 0x{0:X2}", client.ConnectionId, packet.Opcode); client.Throttle[packet.Opcode] = new ThrottleInfo(packet.Opcode); } } Logger.Debug("Proceeding to packet processing"); // For Lobby and Login, we simply process the packet as we can do so in a // thread safe manner. // For World, which involves game logic, we queue the packet for processing by // the world consumer thread. try { if (client.Server is Lobby) { Logger.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode); var handler = (client.Server as Lobby).PacketHandlers[packet.Opcode]; handler.Invoke(client, packet); client.UpdateLastReceived(); } else if (client.Server is Login) { var handler = (client.Server as Login).PacketHandlers[packet.Opcode]; handler.Invoke(client, packet); Logger.DebugFormat("Login: 0x{0:X2}", packet.Opcode); client.UpdateLastReceived(); } else { if (packet.Opcode != 0x45 && packet.Opcode != 0x75) { // Heartbeats don't effect our idle calcuations client.UpdateLastReceived((packet.Opcode != 0x45 && packet.Opcode != 0x75)); } Logger.DebugFormat("Queuing: 0x{0:X2}", packet.Opcode); World.MessageQueue.Add(new HybrasylClientMessage(packet, client.ConnectionId)); } } catch (Exception e) { Logger.ErrorFormat("EXCEPTION IN HANDLING: {0}: {1}", packet.Opcode, e); } client.recving = false; } } } catch (Exception e) { client.Connected = false; Logger.ErrorFormat(e.ToString()); } }
public void ReadCallback(IAsyncResult ar) { ClientState state = (ClientState)ar.AsyncState; Client client; SocketError errorCode; int bytesRead = 0; if (this is Login) { Logger.InfoFormat("This is a login ReadCallback"); } try { bytesRead = state.WorkSocket.EndReceive(ar, out errorCode); if (errorCode != SocketError.Success) { bytesRead = 0; } } catch (SocketException) { state.WorkSocket.Close(); } catch (ObjectDisposedException) { state.WorkSocket.Close(); } if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client)) { // Is this a redirect? Redirect redirect; if (!GlobalConnectionManifest.TryGetRedirect(state.Id, out redirect)) { Logger.ErrorFormat("Receive: data from unknown client (id {0}, closing connection", state.Id); state.WorkSocket.Close(); state.WorkSocket.Dispose(); return; } client = redirect.Client; client.ClientState = state; GlobalConnectionManifest.RegisterClient(client); } if (bytesRead > 0) { if (this is Login) { Logger.InfoFormat("Dafuq bro"); } var inboundBytes = state.ReceiveBufferTake(bytesRead).ToArray(); if (inboundBytes[0] != 0xAA) { Logger.DebugFormat("cid {0}: client is wat", client.ConnectionId); state.ResetReceive(); } else { while (inboundBytes.Length > 3) { Logger.InfoFormat("Inside while loop"); var packetLength = ((int)inboundBytes[1] << 8) + (int)inboundBytes[2] + 3; if (packetLength > inboundBytes.Length) { // We haven't received the entire packet yet; read more bytes break; } else { // We've received an intact packet, pop it off ClientPacket receivedPacket = new ClientPacket(state.ReceiveBufferPop(packetLength).ToArray()); // Also remove it from our local buffer...this seems kinda gross to me inboundBytes = new List <byte>(inboundBytes).GetRange(packetLength, inboundBytes.Length - packetLength) .ToArray(); if (receivedPacket.ShouldEncrypt) { receivedPacket.Decrypt(client); } if (receivedPacket.Opcode == 0x39 || receivedPacket.Opcode == 0x3A) { receivedPacket.DecryptDialog(); } try { if (this is Lobby) { Logger.InfoFormat("Lobby: 0x{0:X2}", receivedPacket.Opcode); var handler = (this as Lobby).PacketHandlers[receivedPacket.Opcode]; handler.Invoke(client, receivedPacket); Logger.InfoFormat("Lobby packet done"); client.UpdateLastReceived(); } else if (this is Login) { Logger.InfoFormat("Login: 0x{0:X2}", receivedPacket.Opcode); var handler = (this as Login).PacketHandlers[receivedPacket.Opcode]; handler.Invoke(client, receivedPacket); Logger.InfoFormat("Login packet done"); client.UpdateLastReceived(); } else { client.UpdateLastReceived(receivedPacket.Opcode != 0x45 && receivedPacket.Opcode != 0x75); Logger.InfoFormat("Queuing: 0x{0:X2}", receivedPacket.Opcode); World.MessageQueue.Add(new HybrasylClientMessage(receivedPacket, client.ConnectionId)); Logger.InfoFormat("World packet done"); } } catch (Exception e) { Logger.ErrorFormat("EXCEPTION IN HANDLING: 0x{0:X2}: {1}", receivedPacket.Opcode, e); } } } } } else { Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received", client.ConnectionId); client.Disconnect(); return; } // Continue getting dem bytes try { state.WorkSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0, new AsyncCallback(this.ReadCallback), state); Logger.InfoFormat("Triggering receive callback"); } catch (ObjectDisposedException) { //client.Disconnect(); state.WorkSocket.Close(); } catch (SocketException) { client.Disconnect(); } }