How to send a "Username/pwd invalid" ?

lazalong
edited July 2011 in Photon Server
Hey

I am using an operation to validate username/pwd. When valid it will return an ok response and if not a ko and then call peer.DisconnectByOtherPeer.

However I would like to print that the username/pwd was invalid and I don't know how to do it.
The problem is that because I send a DisconnectByOtherPeer() in the same method the client is usually disconnected before it can receive the published response! Note that if I don't disconnect I can see the message on my client.

Of course I can't use the workaround of letting the client take responsibility of disconnecting after getting the "invalid" message.

Any idea?
[Operation(OperationCode = (byte)OperationCode.Login)]
        public OperationResponse OperationLogin(Peer peer,
            OperationRequest request)
        {
            var operation = new LoginOperation(request);

            ... connection to db...
            ... validate the username/pwd...

            if (passwordMatch)
            {
                return operation.GetOperationResponse((int)ErrorCode.Ok, "OK");
            }

            peer.PublishOperationResponse(new OperationResponse(
                request, (int)ErrorCode.InvalidUserPass,
                "The username or password is incorrect."));
            
            peer.DisconnectByOtherPeer(this, request);
            return null;
      }

Comments

  • "Of course I can't use the workaround of letting the client take responsibility of disconnecting after getting the "invalid" message."

    I think it's kind of harsh to disconnect the player directly. It could be a typo in the password entry, so why should you not be able to re-try (without re-connect)?
    As alternative you could keep the state "unauthorized" of the peer but don't disconnect it. Make sure to only accept the authorize operation in this state.

    I don't have the proper code right now but you could also schedule a message to each connecting peer. When it triggers after a few seconds, you can check the authorization state and disconnect if the login failed until then.
  • Tobias wrote:
    I think it's kind of harsh to disconnect the player directly.
    Not really. The player don't see that he is disconnected :)
    As alternative you could keep the state "unauthorized" of the peer but don't disconnect it. Make sure to only accept the authorize operation in this state.
    Mh... which means converting the Peer into a state manager.
    That could be the solution as I see other uses of it.

    Can the Peer detect that the client is disconnected without destroying the peer immediately?
    So that I can set the peer in a "zombie" state where the avatar is controlled by an ai?

    I don't have the proper code right now but you could also schedule a message to each connecting peer. When it triggers after a few seconds, you can check the authorization state and disconnect if the login failed until then.
    Oh... You mean the peer could send a msg to itself to disconnect.
    I could send a msg to the client then just after a disconnect to the peer.

    This could work. I just need to find a code sample how a peer can send a message to itself :P
  • try to use some sort of state system - lets say you have states like "preconnect" and "connected" when you send your operation you check if the password is valid, if so you keep sending the "OK" and proceed with the login as you do now.
    If not you gonna send a failure message back.

    A little Code example how my login works:

    Server:
     [Operation(OperationCode = (byte)OperationCode.Login)]
            public OperationResponse OperationLogin(Peer peer, OperationRequest request)
            {
                var operation = new Login(request);
                if (!operation.IsValid)
                {
                    return new OperationResponse(request, (int)ErrorCode.InvalidOperationParameter, operation.GetErrorMessage());
                }
    
                User user = new User();
                // check if user exists
                if (!user.read(operation.Username, operation.Password))
                {
                    return operation.GetOperationResponse((int)ErrorCode.InvalidUserPass, "FAIL");
                }
    
                // do login
                if (user.login)
                {
                    // create session
                    World world = new World();
                    world.enter(user.Id, peer.PhotonPeer);
                    this.userId = user.Id;
                    return operation.GetOperationResponse((int)OperationCode.Login, "OK");
                }
    
    

    and on the client:
    public override void OnHandleMessage(BaseController gameLogic, OperationCode operationCode, int returnCode, Hashtable returnValues)
        {
    		// username or password wrong
            if (returnCode == (int)ErrorCode.InvalidUserPass)
            {
                iGUICode_login login = iGUICode_login.getInstance();
                login.denyLogin("Username or Password wrong", true);
            }
    		// load server selection screen
            else if(returnCode == (int)OperationCode.Login)
            {
                gameLogic.SetState(ServerSelect.Instance);
                Application.LoadLevel(1);
            }
        }
    
    

    please note that this is only an example. The denyLogin method call you see there will basically disable the loginbutton and display the error
    until the user changes the value of either the username or the password field. I do only change the clients state if the login is successful, otherwise the client will stay in the preconnect state. As Tobias already said, there is absolutely no need to disconnect the peer, it hurts more than it helps. Also you don't even need to send "Username or Password wrong" from the server to the client, just added on the client if you recieve ErrorCode.InvalidUserPass
    You don't need to care about this string beeing modified by the client, if he wants to modify it just let him do. I don't think anyone will modify an error message anyway. :)