1

I'm working on a server implementation on a Chromebook, using tcp connectivity between the windows client and the ChromeOS server. When a connection is being made, the server (Chromebook) side is sending out 5 packets; first one is the header, the next 3 ones are the information sent and the last one is the footer of the message.

We're using send and recv for sending and receiving the information, and after the header is being sent, the rest of the packets are never received, because the client is receiving error code 10054, "connection reset by peer", before the rest are received, though those are sent.

The sizes of the packets are as follows: Header is 4 bytes, the second packet sent is 2 bytes, the next one is 1 byte and the next one is 8 bytes, and the footer is 4 bytes. Our suspicion was that perhaps the 2 bytes are too small for the OS to send, and it perhaps waits for more data before sending, unlike in Windows where it currently does send those immediately. So we tried using SO_LINGER on the socket, but it didn't help. We also tried using TCP_NODELAY, but it didn't help as well. When attempting not to write to the socket's fd with the timeout (using select) the connection is being broken after the first header is sent.

We know all the packets are sent, because logging the sent packets from the machine shows all packets as sent, and only the first one arrives.

Socket flag used is this only:

setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n));

Sending a message:

ret = write_timeout(fd, timeout);
if (ret != OK) {
Logger::LogError(PROTOCOL_ERROR, "Write data to socket failed with error %d, while waiting timeout of %u\n", get_last_comm_error(), timeout);
return PROTOCOL_ERROR;
}

while (size) {
    ret = send(fd, ptr, size, 0);
    ptr += ret;
    size -= ret;
    if (ret < 0) {
        Logger::LogError(PROTOCOL_ERROR, "Transport write failed: %d\n", get_last_comm_error());
        return PROTOCOL_ERROR;
    }
}

Write_timeout:

int write_timeout(int fd, unsigned int wait_useconds)
{
    Logger::LogInfo(__FUNCTION__);
    int ret = OK;
    if (wait_useconds > 0) {
        fd_set write_fdset;
        struct timeval timeout;

        FD_ZERO(&write_fdset);
        FD_SET(fd, &write_fdset);
        timeout.tv_sec = 0;
        timeout.tv_usec = wait_useconds;

        do {
            ret = select(fd + 1, NULL, &write_fdset, NULL, &timeout);
        } while (ret < 0 && errno == EINTR);
        if (ret == OK) {
            ret = -1;
            errno = ETIMEDOUT;
        } else if (ret == 1)
            return OK;
 }

The receiving end is similar:

    ret = read_timeout(fd, timeout);
    if (ret != OK) {
        Logger::LogError(PROTOCOL_ERROR, "Error while trying to receive data from the host - timeout\n");
        return TIMED_OUT;
    }
    while (size) {
        ret = recv(fd, ptr, size, 0);
        ptr+=ret;
        size-=ret; 
        if (ret == 0) {
            return FAILED_TRANSACTION;
        }

        if (ret < 0) {
            Logger::LogError(PROTOCOL_ERROR, "Transport read failed: %d\n", get_last_comm_error());
            return UNKNOWN_ERROR;
        }
    }

   return OK;

And timeout:

int read_timeout(int fd, unsigned int wait_useconds)
{
    Logger::LogInfo(__FUNCTION__);
    int ret = OK;
    if (wait_useconds > 0) {
        fd_set read_fdset;
        struct timeval timeout;

        FD_ZERO(&read_fdset);
        FD_SET(fd, &read_fdset);
        timeout.tv_sec = 0;
        timeout.tv_usec = wait_useconds;

        do {
            ret = select(fd + 1, &read_fdset, NULL, NULL, &timeout);
        } while (ret < 0 && errno == EINTR);

        if (ret == OK) {
            ret = -1;
            errno = ETIMEDOUT;
        } else if (ret == 1)
            return OK;
    }

Our code does work on Windows, but (after modifying it accordingly and) using it on ChromeOS does not seem to work unfortunately. We're running the server on a Chromebook with version 93 and building the code with that code base as well.

I did try making the second packet 4 bytes as well, but it still does not work and connection is being reset by peer after the first one is received correctly.

Does anyone know if maybe the chrome OS system waits for bigger packets before sending? Or if something else works a little bit different when working with TCP on that OS that needs to be done differently then in Windows?

0 Answers0