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;
}