According to the Client/server protocol this convention is used to describe all traffic on the socket:
{...}: utf8 strings or raw data, suffixed with a \00 byte. To avoid confusion with this end-of-string byte, all transferred \00 and \FF bytes are prefixed by an additional \FF byte. |
And this is the sequence that has to be sent to the server for succesfull authentication
{username} {md5(md5(username:realm:password) + nonce)} |
In one of the C-examples this is written as
BaseX Server expects an authentification sequence:
{username}\0{md5(md5(user:realm:password) + timestamp)}\0 |
This means that all the time I have to deal with terminating zero's. To make things worse, after successfull authentication, sequences that are sent to or received from the server can contain embedded \00's and \FF bytes,
From my experiences in R, I learned that Unix and Windows handle these zero's in different ways. The constant attention I had to pay to the zeros eventually led me to the decision to convert all strings to byte arrays first and then only send byte arrays over the socket. When I see how many problems the zeros cause me during the authentication process alone, I'm seriously considering using this approach in the C++ version of the client as well.
So far I am very happy with everyone else's comments. I have already learned a lot about C++
Ben
PS. Through the R-developers mailing list I heard that when using non-blocking sockets my approach was doomed to fail from the start. With a non-blocking socket you have to build in a function between sending the authentication data and requesting the status byte that waits until the server prepares the status byte in the socket.
It turned out that this function was already present in the readSocket function.
1 2 3 4 5 6 7 8 9 10 11 12 13
|
bool wait(int s) {
bool done{};
while (!done ) {
fd_set read_set;
FD_ZERO(&read_set);
FD_SET(s, &read_set);
struct timeval timeout {};
memset(&timeout, 0, sizeof(timeout));
int rc = select(s + 1, &read_set, NULL, NULL, &timeout);
done = (rc == 1) && FD_ISSET(s, &read_set);
};
return done;
};
|