Пример #1
0
        public bool Use(User target)
        {
            GameLog.DebugFormat("warp: {0} from {1} ({2},{3}) to {4} ({5}, {6}", target.Name, SourceMap.Name, X, Y,
                                DestinationMapName, DestinationX, DestinationY);
            switch (WarpType)
            {
            case WarpType.Map:
                Map map;
                if (SourceMap.World.WorldData.TryGetValueByIndex(DestinationMapName, out map))
                {
                    target.Teleport(map.Id, DestinationX, DestinationY);
                    return(true);
                }
                GameLog.ErrorFormat("User {0} tried to warp to nonexistent map {1} from {2}: {3},{4}", target.Name,
                                    DestinationMapName, SourceMap.Name, X, Y);
                break;

            case WarpType.WorldMap:
                WorldMap wmap;
                if (SourceMap.World.WorldData.TryGetValue(DestinationMapName, out wmap))
                {
                    SourceMap.Remove(target);
                    target.SendWorldMap(wmap);
                    SourceMap.World.WorldData.Get <Map>(Hybrasyl.Constants.LAG_MAP).Insert(target, 5, 5, false);
                    return(true);
                }
                GameLog.ErrorFormat("User {0} tried to warp to nonexistent worldmap {1} from {2}: {3},{4}",
                                    target.Name,
                                    DestinationMapName, SourceMap.Name, X, Y);
                break;
            }
            return(false);
        }
Пример #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 static void DeregisterClient(Client client)
 {
     ConnectedClients.TryRemove(client.ConnectionId, out Client _);
     GameLog.InfoFormat("Deregistering {0}", client.ConnectionId);
     // Send a control message to clean up after World users; Lobby and Login handle themselves
     if (client.ServerType == ServerTypes.World)
     {
         if (!WorldClients.TryRemove(client.ConnectionId, out Client _))
         {
             GameLog.Error("Couldn't deregister cid {id}", client.ConnectionId);
         }
         try
         {
             if (!World.ControlMessageQueue.IsCompleted)
             {
                 World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser,
                                                                          CleanupType.ByConnectionId, client.ConnectionId));
             }
         }
         catch (InvalidOperationException e)
         {
             Game.ReportException(e);
             if (!World.ControlMessageQueue.IsCompleted)
             {
                 GameLog.ErrorFormat("Connection {id}: DeregisterClient failed", client.ConnectionId);
             }
         }
     }
 }
Пример #4
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);
        }
Пример #5
0
        // Chart for all error password-related error codes were provided by kojasou@ on
        // https://github.com/hybrasyl/server/pull/11.
        private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet)
        {
            var name        = packet.ReadString8();
            var currentPass = packet.ReadString8();
            // Clientside validation ensures that the same string is typed twice for the new
            // password, and the new password is only sent to the server once. We can assume
            // that they matched if 0x26 request is sent from the client.
            var newPass = packet.ReadString8();

            // TODO: REDIS

            User player;

            if (!World.TryGetUser(name, out player))
            {
                client.LoginMessage(GetPasswordError(0x0E), 0x0E);
                GameLog.InfoFormat("cid {0}: Password change attempt on nonexistent player {1}", client.ConnectionId, name);
                return;
            }

            if (player.VerifyPassword(currentPass))
            {
                // Check if the password is valid.
                byte err = 0x00;
                if (ValidPassword(newPass, out err))
                {
                    player.Password.Hash            = HashPassword(newPass);
                    player.Password.LastChanged     = DateTime.Now;
                    player.Password.LastChangedFrom = ((IPEndPoint)client.Socket.RemoteEndPoint).Address.ToString();
                    player.Save();
                    // Let the user know the good news.
                    client.LoginMessage("Your password has been changed successfully.", 0x0);
                    GameLog.InfoFormat("Password successfully changed for `{0}`", name);
                }
                else
                {
                    client.LoginMessage(GetPasswordError(err), err);
                    GameLog.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name);
                }
            }
            // The current password is incorrect. Don't allow any changes to happen.
            else
            {
                client.LoginMessage(GetPasswordError(0x0F), 0x0F);
                GameLog.ErrorFormat("Invalid current password during password change attempt for `{0}`", name);
            }
        }
Пример #6
0
        public void SendCallback(IAsyncResult ar)
        {
            ClientState state = (ClientState)ar.AsyncState;
            Client      client;

            GameLog.DebugFormat($"EndSend: SocketConnected: {state.WorkSocket.Connected}, IAsyncResult: Completed: {ar.IsCompleted}, CompletedSynchronously: {ar.CompletedSynchronously}");

            try
            {
                SocketError errorCode;
                var         bytesSent = state.WorkSocket.EndSend(ar, out errorCode);
                if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client))
                {
                    GameLog.ErrorFormat("Send: socket should not exist: cid {0}", state.Id);
                    state.WorkSocket.Close();
                    state.WorkSocket.Dispose();
                    return;
                }

                if (bytesSent == 0 || errorCode != SocketError.Success)
                {
                    GameLog.ErrorFormat("cid {0}: disconnected");
                    client.Disconnect();
                    throw new SocketException((int)errorCode);
                }
            }
            catch (SocketException e)
            {
                Game.ReportException(e);
                GameLog.Error($"Error Code: {e.ErrorCode}, {e.Message}");
                state.WorkSocket.Close();
            }
            catch (ObjectDisposedException)
            {
                //client.Disconnect();
                GameLog.Error($"ObjectDisposedException");
                state.WorkSocket.Close();
            }
            state.SendComplete.Set();
        }
Пример #7
0
 public static void DeregisterClient(Client client)
 {
     ((IDictionary)ConnectedClients).Remove(client.ConnectionId);
     GameLog.InfoFormat("Deregistering {0}", client.ConnectionId);
     // Send a control message to clean up after World users; Lobby and Login handle themselves
     if (client.ServerType == ServerTypes.World)
     {
         ((IDictionary)WorldClients).Remove(client.ConnectionId);
         // This will also handle removing the user from WorldClients if necessary
         try
         {
             World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, client.ConnectionId));
         }
         catch (InvalidOperationException)
         {
             if (!World.ControlMessageQueue.IsCompleted)
             {
                 GameLog.ErrorFormat("Connection {id}: DeregisterClient failed", client.ConnectionId);
             }
         }
     }
 }
Пример #8
0
        public void FlushReceiveBuffer()
        {
            lock (ClientState.ReceiveLock)
            {
                try
                {
                    ClientPacket packet;
                    while (ClientState.ReceiveBufferTake(out packet))
                    {
                        if (packet.ShouldEncrypt)
                        {
                            packet.Decrypt(this);
                        }

                        if (packet.Opcode == 0x39 || packet.Opcode == 0x3A)
                        {
                            packet.DecryptDialog();
                        }
                        try
                        {
                            if (Server is Lobby)
                            {
                                GameLog.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode);
                                var handler = (Server as Lobby).PacketHandlers[packet.Opcode];
                                handler.Invoke(this, packet);
                                GameLog.DebugFormat("Lobby packet done");
                                UpdateLastReceived();
                            }
                            else if (Server is Login)
                            {
                                GameLog.Debug($"Login: 0x{packet.Opcode:X2}");
                                var handler = (Server as Login).PacketHandlers[packet.Opcode];
                                handler.Invoke(this, packet);
                                GameLog.DebugFormat("Login packet done");
                                UpdateLastReceived();
                            }
                            else
                            {
                                UpdateLastReceived(packet.Opcode != 0x45 &&
                                                   packet.Opcode != 0x75);
                                GameLog.Debug($"Queuing: 0x{packet.Opcode:X2}");
                                //packet.DumpPacket();
                                // Check for throttling
                                var throttleResult = Server.PacketThrottleCheck(this, packet);
                                if (throttleResult == ThrottleResult.OK || throttleResult == ThrottleResult.ThrottleEnd || throttleResult == ThrottleResult.SquelchEnd)
                                {
                                    World.MessageQueue.Add(new HybrasylClientMessage(packet, ConnectionId));
                                }
                                else
                                if (packet.Opcode == 0x06)
                                {
                                    World.ControlMessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.TriggerRefresh, ConnectionId));
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Game.ReportException(e);
                            GameLog.ErrorFormat("EXCEPTION IN HANDLING: 0x{0:X2}: {1}", packet.Opcode, e);
                        }
                    }
                }
                catch (Exception e)
                {
                    Game.ReportException(e);
                    Console.WriteLine(e);
                    throw;
                }
            }
        }