SOCKET_SEND_RESULT socket_transport_send()

in linux/src/socket_transport_linux.c [362:441]


SOCKET_SEND_RESULT socket_transport_send(SOCKET_TRANSPORT_HANDLE socket_transport, const SOCKET_BUFFER* payload, uint32_t buffer_count, uint32_t* bytes_sent, uint32_t flags, void* data)
{
    SOCKET_SEND_RESULT result;
    // Codes_SOCKET_TRANSPORT_LINUX_11_027: [ If socket_transport is NULL, socket_transport_send shall fail and return SOCKET_SEND_INVALID_ARG. ]
    if (socket_transport == NULL ||
        // Codes_SOCKET_TRANSPORT_LINUX_11_028: [ If payload is NULL, socket_transport_send shall fail and return SOCKET_SEND_INVALID_ARG. ]
        payload == NULL ||
        // Codes_SOCKET_TRANSPORT_LINUX_11_029: [ If buffer_count is 0, socket_transport_send shall fail and return SOCKET_SEND_INVALID_ARG. ]
        buffer_count == 0)
    {
        LogError("Invalid arguments: SOCKET_TRANSPORT_HANDLE socket_transport: %p, const SOCKET_BUFFER* payload: %p, uint32_T buffer_count: %" PRIu32 ", void* data: %p",
            socket_transport, payload, buffer_count, data);
        result = SOCKET_SEND_INVALID_ARG;
    }
    else
    {
        // Codes_SOCKET_TRANSPORT_LINUX_11_030: [ socket_transport_send shall call sm_exec_begin. ]
        SM_RESULT sm_result = sm_exec_begin(socket_transport->sm);
        if (sm_result != SM_EXEC_GRANTED)
        {
            // Codes_SOCKET_TRANSPORT_LINUX_11_031: [ If sm_exec_begin does not return SM_EXEC_GRANTED, socket_transport_send shall fail and return SOCKET_SEND_ERROR. ]
            LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result));
            result = SOCKET_SEND_ERROR;
        }
        else
        {
            uint32_t total_send_size = 0;
            for (uint32_t index = 0; index < buffer_count; index++)
            {
                // Codes_SOCKET_TRANSPORT_LINUX_11_032: [ For each buffer count in payload socket_transport_send shall call send to send data with flags as a parameter. ]
                ssize_t data_sent = 0;
                do
                {
                    ssize_t send_size = send(socket_transport->socket, payload[index].buffer, payload[index].length, flags);
                    if (send_size < 0)
                    {
                        // Codes_SOCKET_TRANSPORT_LINUX_11_033: [ If send returns a value less then 0, socket_transport_send shall stop sending and return SOCKET_SEND_FAILED. ]
                        LogErrorNo("Failure sending data index: %" PRIu32 ", payload.buffer: %p, payload.length: %" PRIu32 "", index, payload[index].buffer, payload[index].length);
                        result = SOCKET_SEND_FAILED;
                        break;
                    }
                    else
                    {
                        result = SOCKET_SEND_OK;
                        data_sent += send_size;
                    }
                    // Codes_SOCKET_TRANSPORT_LINUX_11_035: [ Otherwise socket_transport_send shall continue calling send until the SOCKET_BUFFER length is reached. ]
                } while (data_sent < payload[index].length);

                if (result == SOCKET_SEND_OK)
                {
    #ifdef ENABLE_SOCKET_LOGGING
                    LogVerbose("Send completed synchronously at %lf", timer_global_get_elapsed_us());
    #endif
                    total_send_size += data_sent;
                }
                else
                {
                    if (errno == ECONNRESET)
                    {
                        // Codes_SOCKET_TRANSPORT_LINUX_11_034: [ If the errno is equal to ECONNRESET, socket_transport_send shall return SOCKET_SEND_SHUTDOWN. ]
                        result = SOCKET_SEND_SHUTDOWN;
                        LogError("A reset on the send socket has been encountered");
                    }
                    else
                    {
                        // Send the result unchanged
                        LogErrorNo("Failure sending socket data: buffer: %p, length: %" PRIu32 "", payload->buffer, payload->length);
                    }
                }
            }
            if (bytes_sent != NULL)
            {
                *bytes_sent = total_send_size;
            }
            sm_exec_end(socket_transport->sm);
        }
    }
    return result;
}