Jump to content
Returning Members: Password Reset Required ×

Recommended Posts

Posted

So, I may have had this working before, honestly ive been staying up so late these days I cant remember if I dreamed that this worked at one point or if I actually had it working. 
Either way, into the issue, I believe I am completing the login handshake just fine. the code runs properly as expected when i step through manually and we send the AuthResponsePacket 

heres my console messages:
 

Quote

info: OpenConquer.AccountServer.LoginHandshakeService[0]
      LoginHandshakeService listening on port 9959
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\repos\OpenConquer\OpenConquer.AccountServer
info: OpenConquer.AccountServer.LoginHandshakeService[0]
      Accepted login connection from redacted:50747
info: OpenConquer.AccountServer.LoginHandshakeService[0]
      Beginning handshake for redacted:50747
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      Starting handshake for redacted:50747
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      SeedResponsePacket sent (Seed=81136454)
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      Received login request (Len=276 Id=1060)
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      Parsed LoginRequest for storm
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (23ms) [Parameters=[@__username_0='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
      SELECT `a`.`uid`, `a`.`answer`, `a`.`Email`, `a`.`hash`, `a`.`password`, `a`.`permission`, `a`.`question`, `a`.`timestamp`, `a`.`username`
      FROM `accounts` AS `a`
      WHERE `a`.`username` = @__username_0
      LIMIT 1
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (3ms) [Parameters=[@__p_0='?' (DbType = UInt32)], CommandType='Text', CommandTimeout='30']
      SELECT `a`.`uid`, `a`.`answer`, `a`.`Email`, `a`.`hash`, `a`.`password`, `a`.`permission`, `a`.`question`, `a`.`timestamp`, `a`.`username`
      FROM `accounts` AS `a`
      WHERE `a`.`uid` = @__p_0
      LIMIT 1
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[@p2='?' (DbType = UInt32), @p0='?' (DbType = UInt32), @p1='?' (DbType = UInt32)], CommandType='Text', CommandTimeout='30']
      SET AUTOCOMMIT = 1;
      UPDATE `accounts` SET `hash` = @p0, `timestamp` = @p1
      WHERE `uid` = @p2;
      SELECT ROW_COUNT();
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      AuthResponse ␦ Port=5816, ExternalIp='redacted'
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      ␦ AuthResponsePacket bytes: 36-00-1F-04-01-00-00-00-09-00-00-00-B8-16-00-00-00-00-00-00-31-39-32-2E-31-36-38-2E-31-2E-35-38-00-00-00-00
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      Sent AuthResponse (Key=9) for storm
info: OpenConquer.AccountServer.Session.LoginClientSession[0]
      Handshake complete, closed login session for redacted:50747
info: OpenConquer.AccountServer.LoginHandshakeService[0]
      Completed handshake for redacted:50747


ignore the closed login session message I commented out my Disconnect call to  see if I was just disconnecting early but no. I even tried awaiting another packet from the client to see if I was missing a step or something but nothing ever came from the client after I sent the AuthResponsePacket. After the following code it just never connects to the gameserver 
 

        private async Task<AuthResponsePacket> BuildResponseAsync(string user, string pass, CancellationToken ct)
        {
            uint loginSessionKey = _keyProvider.NextKey();
            uint accountSessionHash = (uint)Random.Shared.Next(1, 1000000);

            Account? acct = await _accounts.GetByUsernameAsync(user).ConfigureAwait(false);

            if (acct is null)
            {
                acct = new Account
                {
                    Username = user,
                    Password = pass,
                    Permission = PlayerPermission.Player,
                    Hash = accountSessionHash,
                    Timestamp = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
                };

                acct = await _accounts.CreateAsync(acct, ct).ConfigureAwait(false);

                if (acct is null || acct.UID == 0)
                {
                    return AuthResponsePacket.CreateInvalid();
                }
            }
            else if (acct.Password != pass || acct.Permission == PlayerPermission.Error)
            {
                return AuthResponsePacket.CreateInvalid();
            }
            else if (acct.Permission == PlayerPermission.Banned)
            {
                return new AuthResponsePacket
                {
                    Key = AuthResponsePacket.RESPONSE_BANNED
                };
            }
            else
            {
                acct.Hash = accountSessionHash;
                await _accounts.UpdateHashAsync(acct.UID, accountSessionHash, ct).ConfigureAwait(false);
            }

            return new AuthResponsePacket
            {
                UID = loginSessionKey,
                Key = acct.UID,
                Port = (uint)_gamePort,
                ExternalIp = _externalIp
            };
        }
        private async Task RespondAsync(LoginRequestPacket req, uint seed, CancellationToken ct)
        {
            string password = DecryptPassword(req, seed);
            var resp = await BuildResponseAsync(req.Username, password, ct).ConfigureAwait(false);

            _logger.LogInformation("AuthResponse: Port={Port}, ExternalIp='{IP}'", resp.Port, resp.ExternalIp);
            var outBuf = PacketWriter.Serialize(resp);
            _logger.LogInformation("AuthResponsePacket bytes: {Hex}", BitConverter.ToString(outBuf));
            await SendToClientAsync(outBuf, ct).ConfigureAwait(false);
            _logger.LogInformation("Sent AuthResponse (Key={Key}) for {User}", resp.Key, req.Username);
        }
        public async Task HandleHandshakeAsync(CancellationToken ct)
        {
            var endpoint = _tcpClient.Client.RemoteEndPoint;
            _logger.LogInformation("Starting handshake for {Endpoint}", endpoint);

            try
            {
                uint seed = await SendSeedAsync(ct);
                var (pktLen, pktId, fullPacket) = await ReadAndDecryptRequestAsync(ct);

                _logger.LogInformation("Received login request (Len={Len} Id={Id})", pktLen, pktId);
                var req = LoginRequestPacket.Parse(fullPacket);
                _logger.LogInformation("Parsed LoginRequest for {User}", req.Username);

                await RespondAsync(req, seed, ct).ConfigureAwait(false);

                await Task.Delay(100, ct);

                //Disconnect();
                _logger.LogInformation("Handshake complete, closed login session for {Endpoint}", endpoint);
            }
            catch (OperationCanceledException)
            {
                _logger.LogInformation("Handshake canceled for {Endpoint}", endpoint);
                Disconnect();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Handshake failed for {Endpoint}", endpoint);
                Disconnect();
            }
        }


I dont think its the Gameserver code as an issue or a firewall issue because I can ping the gameserver from powershell and it will get the connection and try to parse the ping. but the client just wont connect. 

using conquerloader to launch the client
with these settings 
[Loader]
IPAddress=redacted <--- port forwarded address yes I have checked that on both ports for login and gameport are port forwarded
LoginPort=9959
GamePort=5816
Website=http://www.elitepvpers.de
Force=TRUE


Wondering if anyone sees a blatant flaw in my implementation that im not seeing, or could just give me a few ideas of where or what to check, I would greatly appreciate it, been racking my brain on this one since yesterday. 

Posted

Heres an example of me pinging the gameserver so I know its listening and receiving the client is just never reaching out to it properly for some reason.

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT `l`.`profession`, `l`.`level`, `l`.`Agility`, `l`.`Health`, `l`.`Mana`, `l`.`Spirit`, `l`.`Strength`, `l`.`Vitality`
      FROM `LevelStats` AS `l`
      ORDER BY `l`.`profession`, `l`.`level`
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (3ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT `e`.`curve_type`, `e`.`level`, `e`.`experience`
      FROM `ExperienceCurves` AS `e`
      ORDER BY `e`.`curve_type`, `e`.`level`
info: OpenConquer.GameServer.Calculations.Implementation.ExperienceService[0]
      ExperienceService initialized: loaded 720 level-stat entries across 6 professions, 141 curve entries
info: OpenConquer.GameServer.GameHandshakeService[0]
      GameHandshakeService listening on port 5816
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\repos\OpenConquer\OpenConquer.GameServer
info: OpenConquer.GameServer.GameHandshakeService[0]
      Accepted game connection from redacted:53377
fail: OpenConquer.GameServer.GameHandshakeService[0]
      Error during game handshake for redacted:53377
      System.InvalidOperationException: Unable to resolve service for type 'OpenConquer.Protocol.Packets.Parsers.PacketParserRegistry' while attempting to activate 'OpenConquer.GameServer.Session.GameClientSession'.
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
         at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance[T](IServiceProvider provider, Object[] parameters)
         at OpenConquer.GameServer.GameHandshakeService.HandleClientAsync(TcpClient client, CancellationToken ct) in D:\repos\OpenConquer\OpenConquer.GameServer\GameHandshakeService.cs:line 65
info: OpenConquer.GameServer.GameHandshakeService[0]
      Closed game connection for redacted:53377

it would expect to error out as I am building it out to expect specific packets only (i'll flesh that out to swallow invalid packets or something properly later) but this shows that the code on the gameserver is working as I expect it to, if the darn client would just send it a packet. 

Posted

I figured it out in case any one was wondering or stumbles into this in the future, despite albetros saying that the auth response packet length should be 54 bytes on the wire they actually only write 36, changed my length from 54 to 36 and now were cooking again boys! So note to anyone in the future working on a 5517 server the auth response packet length should be 36 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...