public void Redirect(Redirect redirect) { Logger.InfoFormat("Processing redirect"); GlobalConnectionManifest.RegisterRedirect(this, redirect); Logger.InfoFormat("Redirect: cid {0}", this.ConnectionId); //GlobalConnectionManifest.DeregisterClient(this); redirect.Destination.ExpectedConnections.TryAdd(redirect.Id, redirect); var endPoint = Socket.RemoteEndPoint as IPEndPoint; byte[] addressBytes = IPAddress.IsLoopback(endPoint.Address) ? IPAddress.Loopback.GetAddressBytes() : Game.IpAddress.GetAddressBytes(); Array.Reverse(addressBytes); var x03 = new ServerPacket(0x03); x03.Write(addressBytes); x03.WriteUInt16((ushort)redirect.Destination.Port); x03.WriteByte((byte)(redirect.EncryptionKey.Length + Encoding.GetEncoding(949).GetBytes(redirect.Name).Length + 7)); x03.WriteByte(redirect.EncryptionSeed); x03.WriteByte((byte)redirect.EncryptionKey.Length); x03.Write(redirect.EncryptionKey); x03.WriteString8(redirect.Name); x03.WriteUInt32(redirect.Id); Thread.Sleep(100); Enqueue(x03); }
public Client(Socket socket, Server server) { ClientState = new ClientState(socket); Server = server; GameLog.InfoFormat("Connection {0} from {1}:{2}", ConnectionId, ((IPEndPoint)Socket.RemoteEndPoint).Address.ToString(), ((IPEndPoint)Socket.RemoteEndPoint).Port); if (server is Lobby) { EncryptionKey = Game.Config.ApiEndpoints.EncryptionEndpoint != null?GlobalConnectionManifest.RequestEncryptionKey(Game.Config.ApiEndpoints.EncryptionEndpoint.Url, ((IPEndPoint)socket.RemoteEndPoint).Address) : Encoding.ASCII.GetBytes("UrkcnItnI"); GameLog.InfoFormat($"EncryptionKey is {Encoding.ASCII.GetString(EncryptionKey)}"); var valid = Game.Config.ApiEndpoints.ValidationEndpoint != null?GlobalConnectionManifest.ValidateEncryptionKey(Game.Config.ApiEndpoints.ValidationEndpoint.Url, new ServerToken { Ip = ((IPEndPoint)socket.RemoteEndPoint).Address.ToString(), Seed = EncryptionKey }) : true; if (!valid) { GameLog.ErrorFormat("Invalid key from {IP}", ((IPEndPoint)Socket.RemoteEndPoint).Address.ToString()); socket.Disconnect(true); } } EncryptionKeyTable = new byte[1024]; _lastReceived = DateTime.Now.Ticks; GlobalConnectionManifest.RegisterClient(this); ConnectedSince = DateTime.Now.Ticks; }
public void ReadCallback(IAsyncResult ar) { ClientState state = (ClientState)ar.AsyncState; Client client; SocketError errorCode = SocketError.SocketError; int bytesRead = 0; ClientPacket receivedPacket; GameLog.Debug($"SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}, queue size: {state.Buffer.Length}"); GameLog.Debug("Running read callback"); if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client)) { // Is this a redirect? Redirect redirect; if (!GlobalConnectionManifest.TryGetRedirect(state.Id, out redirect)) { GameLog.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; if (client.EncryptionKey == null) { client.EncryptionKey = redirect.EncryptionKey; } GlobalConnectionManifest.RegisterClient(client); } try { bytesRead = state.WorkSocket.EndReceive(ar, out errorCode); if (bytesRead == 0 || errorCode != SocketError.Success) { GameLog.Error($"bytesRead: {bytesRead}, errorCode: {errorCode}"); client.Disconnect(); } } catch (Exception e) { GameLog.Fatal($"EndReceive Error: {e.Message}"); client.Disconnect(); } try { // TODO: improve / refactor while (client.ClientState.TryGetPacket(out receivedPacket)) { client.Enqueue(receivedPacket); } } catch (Exception e) { GameLog.Error($"ReadCallback error: {e.Message}"); } ContinueReceiving(state, client); }
public virtual void AcceptConnection(IAsyncResult ar) { // TODO: @norrismiv async callbacks+inheritance? and/or can these callbacks suck less? AllDone.Set(); if (!Active) { return; } Socket handler; Socket clientSocket; try { clientSocket = (Socket)ar.AsyncState; handler = clientSocket.EndAccept(ar); } catch (ObjectDisposedException e) { GameLog.Error($"Disposed socket {e.Message}"); return; } Client client = new Client(handler, this); Clients.TryAdd(handler.Handle, client); GlobalConnectionManifest.RegisterClient(client); if (this is Lobby) { var x7E = new ServerPacket(0x7E); x7E.WriteByte(0x1B); x7E.WriteString("CONNECTED SERVER\n"); client.Enqueue(x7E); GameLog.DebugFormat("Lobby: AcceptConnection occuring"); GameLog.DebugFormat("Lobby: cid is {0}", client.ConnectionId); } else if (this is Login) { GameLog.DebugFormat("Login: AcceptConnection occuring"); GameLog.DebugFormat("Login: cid is {0}", client.ConnectionId); } else if (this is World) { GameLog.DebugFormat("World: AcceptConnection occuring"); GameLog.DebugFormat("World: cid is {0}", client.ConnectionId); } try { handler.BeginReceive(client.ClientState.Buffer, 0, client.ClientState.Buffer.Length, 0, new AsyncCallback(ReadCallback), client.ClientState); GameLog.DebugFormat("AcceptConnection returning"); clientSocket.BeginAccept(new AsyncCallback(AcceptConnection), clientSocket); } catch (SocketException e) { Game.ReportException(e); handler.Close(); } }
public Client(Socket socket, Server server) { ClientState = new ClientState(socket); Server = server; Logger.InfoFormat("Connection {0} from {1}:{2}", ConnectionId, ((IPEndPoint)Socket.RemoteEndPoint).Address.ToString(), ((IPEndPoint)Socket.RemoteEndPoint).Port); EncryptionKey = Encoding.ASCII.GetBytes("UrkcnItnI"); EncryptionKeyTable = new byte[1024]; _lastReceived = DateTime.Now.Ticks; GlobalConnectionManifest.RegisterClient(this); ConnectedSince = DateTime.Now.Ticks; }
public void Redirect(Redirect redirect, bool isLogoff = false, int transmitDelay = 0) { GameLog.InfoFormat("Processing redirect"); GlobalConnectionManifest.RegisterRedirect(this, redirect); GameLog.InfoFormat("Redirect: cid {0}", this.ConnectionId); GameLog.Info($"Redirect EncryptionKey is {Encoding.ASCII.GetString(redirect.EncryptionKey)}"); if (isLogoff) { GlobalConnectionManifest.DeregisterClient(this); } redirect.Destination.ExpectedConnections.TryAdd(redirect.Id, redirect); var endPoint = Socket.RemoteEndPoint as IPEndPoint; byte[] addressBytes; if (Game.RedirectTarget != null) { addressBytes = Game.RedirectTarget.GetAddressBytes(); } else { addressBytes = IPAddress.IsLoopback(endPoint.Address) ? IPAddress.Loopback.GetAddressBytes() : Game.IpAddress.GetAddressBytes(); } Array.Reverse(addressBytes); var x03 = new ServerPacket(0x03); x03.Write(addressBytes); x03.WriteUInt16((ushort)redirect.Destination.Port); x03.WriteByte((byte)(redirect.EncryptionKey.Length + Encoding.ASCII.GetBytes(redirect.Name).Length + 7)); x03.WriteByte(redirect.EncryptionSeed); x03.WriteByte((byte)redirect.EncryptionKey.Length); x03.Write(redirect.EncryptionKey); x03.WriteString8(redirect.Name); x03.WriteUInt32(redirect.Id); x03.TransmitDelay = transmitDelay == 0 ? 250 : transmitDelay; Enqueue(x03); }
public ClientState(Socket incoming) { this.WorkSocket = incoming; this.Id = GlobalConnectionManifest.GetNewConnectionId(); this.Connected = true; }
public void Disconnect() { GlobalConnectionManifest.DeregisterClient(this); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, ConnectionId)); ClientState.Dispose(); }
public void ClientLoop() { while (Connected) { if (recving == false) { recving = true; try { Socket.BeginReceive(recvBuffer, 0, recvBuffer.Length, SocketFlags.None, EndReceive, this); } catch (Exception e) { Logger.ErrorFormat(e.ToString()); } } while (!SendQueue.IsEmpty) { Logger.DebugFormat("Dequeuing packet"); ServerPacket packet; if (!SendQueue.TryDequeue(out packet)) { Logger.ErrorFormat("SendQueue TryDequeue failed?"); continue; } if (packet.ShouldEncrypt) { ++serverOrdinal; packet.Ordinal = serverOrdinal; packet.GenerateFooter(); packet.Encrypt(this); } if (packet.TransmitDelay != 0) { Thread.Sleep(packet.TransmitDelay); } fullSendBuffer.AddRange((byte[])packet); } if (sending == false && fullSendBuffer.Count > 0) { sending = true; Logger.DebugFormat("Sending"); sendBuffer = fullSendBuffer.ToArray(); fullSendBuffer.Clear(); try { Socket.BeginSend(sendBuffer, 0, sendBuffer.Length, SocketFlags.None, EndSend, this); } catch (Exception e) { Logger.ErrorFormat(e.ToString()); } } Thread.Sleep(10); } GlobalConnectionManifest.DeregisterClient(this); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, ConnectionId)); Socket.Close(); }
public void Disconnect() { ClientState.Dispose(); GlobalConnectionManifest.DeregisterClient(this); }
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(); } }