Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authenticating users on a Qt Server

Tags:

c++

qt

I am trying to implement an authentication system using C++/QtTcpSocket for a personal project (A Multiplayer Chess Game).

My friend suggested a method for verifying a user but I wanted to ask if there was an easier or better way. Coming from a Python background and mostly doing this project to develop a deeper understanding of C++.

I will post the method my friend suggested and ask for maybe a better solution.

He built it in a kind of pseudo code fashion. The server is mostly built, I am now hoping to implement Authentication

*cheers

void process_packet(PACKET *pkt)
{
    switch(pkt->PacketID)
    {
        case 0: // let's say packet id 0 is the logon packet; packet contents are username and password
        {
            //let's say packet size is 101 bytes; packet id was already received, so get the other 100 bytes
            unsigned char BUFFER[101] = {0}; // i always add an extra byte to the end of the buffer to allow for off-by-one errors ^_^

            int result = recv_packet(pkt->cSocket, 100, BUFFER);

            if(result <= 0)
                return; // connection error; no packet data was received

            unsigned char *UserName = BUFFER+0; //+0 is not neccessary, but the username starts at the beginning. just getting the point across.
            unsigned char *PassWord = BUFFER+50;

            //side note: if we did "unsigned long *blah = BUFFER+4" or something, we would have to make sure the byte order is right. network byte order is BIG ENDIAN
            //  WINDOWS byte order is LITTLE ENDIAN

            result = QueryDatabase("SELECT username, password FROM chess_players WHERE username = '%s'", FILTER_INVALID_CHARS(UserName));

            // check result

            unsigned char ServerResponse[2] = {0};

            if(result['password'] == PassWord)
            {
                ServerResponse[0] = 1; // packet id will be 1. the next byte can be 1 or 0 to indicate logon success or failure.
                ServerResponse[1] = true; // so packet 0x0101 mean logon success, packet 0x0100 means logon failure
                send_packet(pkt->cSocket, ServerResponse, 2);
            } else {

                ServerResponse[0] = 1;
                ServerResponse[1] = false;
                send_packet(pkt->cSocket, ServerResponse, 2);
            }
        }
        break;

        default:
        {
            // received an unknown packet id; send a packet to the client that indicates an error_status_t

            unsigned char *ServerResponse[2] = {0};
            ServerResponse[0] = 2; // packet id 2 means server error
            ServerResponse[1] = 0; // error code 0 means 'unknown packet id'

            send_packet(pkt_cSocket, ServerResponse, 2);
        }
        break;
    }

    delete pkt; // must delete pkt, was created with 'new' in get_client_packets()
}
like image 671
townlong Avatar asked Feb 17 '26 03:02

townlong


1 Answers

This seems rather C-stylish and not like the Qt way of doing things. There is no general answer to your question but my suggestions are the following:

Listen to the newConnection() signal of the QTcpServer. Your handler has to call the nextPendingConnection() to get the next client waiting in the queue. The first thing you will do is probably your user authentication. Once authenticated, you keep the QTcpSocket in your list of active connections.

Take a look at e.g. the fortune client/server examples how to actually write/read packets. You might also want to look into the stream operators << to serialize your objects. This is much easier and less error prone than the low-level method you posted. ALso, QDataStream will take care of host and network byte orders automatically.

like image 157
pokey909 Avatar answered Feb 19 '26 16:02

pokey909