예제 #1
0
파일: Client.cs 프로젝트: wren11/server
        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);
        }
예제 #2
0
        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;
        }
예제 #3
0
        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);
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
파일: Client.cs 프로젝트: wren11/server
 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;
 }
예제 #6
0
        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);
        }
예제 #7
0
파일: Client.cs 프로젝트: wren11/server
 public ClientState(Socket incoming)
 {
     this.WorkSocket = incoming;
     this.Id         = GlobalConnectionManifest.GetNewConnectionId();
     this.Connected  = true;
 }
예제 #8
0
파일: Client.cs 프로젝트: wren11/server
 public void Disconnect()
 {
     GlobalConnectionManifest.DeregisterClient(this);
     World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, ConnectionId));
     ClientState.Dispose();
 }
예제 #9
0
파일: Client.cs 프로젝트: saroque/server
        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();
        }
예제 #10
0
 public void Disconnect()
 {
     ClientState.Dispose();
     GlobalConnectionManifest.DeregisterClient(this);
 }
예제 #11
0
        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();
            }
        }