in win32/src/socket_transport_win32.c [476:553]
SOCKET_RECEIVE_RESULT socket_transport_receive(SOCKET_TRANSPORT_HANDLE socket_transport, SOCKET_BUFFER* payload, uint32_t buffer_count, uint32_t* bytes_recv, uint32_t flags, void* data)
{
SOCKET_RECEIVE_RESULT result;
// Codes_SOCKET_TRANSPORT_WIN32_09_041: [ If socket_transport is NULL, socket_transport_receive shall fail and return SOCKET_RECEIVE_ERROR. ]
if (socket_transport == NULL ||
// Codes_SOCKET_TRANSPORT_WIN32_09_042: [ If payload is NULL, socket_transport_receive shall fail and return SOCKET_RECEIVE_ERROR. ]
payload == NULL ||
// Codes_SOCKET_TRANSPORT_WIN32_09_043: [ If buffer_count is 0, socket_transport_receive shall fail and return SOCKET_RECEIVE_ERROR. ]
buffer_count == 0)
{
LogError("Invalid arguments: SOCKET_TRANSPORT_HANDLE socket_transport=%p, const SOCKET_BUFFER* payload=%p, uint32_t flags=%" PRIu32 ", void*, data=%p",
socket_transport, payload, flags, data);
result = SOCKET_RECEIVE_INVALID_ARG;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_044: [ socket_transport_receive shall call sm_exec_begin. ]
SM_RESULT sm_result = sm_exec_begin(socket_transport->sm);
// Codes_SOCKET_TRANSPORT_WIN32_09_045: [ If sm_exec_begin does not return SM_EXEC_GRANTED, socket_transport_receive shall fail and return SOCKET_RECEIVE_ERROR. ]
if (sm_result != SM_EXEC_GRANTED)
{
LogError("sm_exec_begin failed : %" PRI_MU_ENUM, MU_ENUM_VALUE(SM_RESULT, sm_result));
result = SOCKET_RECEIVE_ERROR;
}
else
{
DWORD num_bytes = 0;
LPDWORD num_bytes_param = NULL;
if (data == NULL)
{
num_bytes_param = &num_bytes;
}
// Codes_SOCKET_TRANSPORT_WIN32_09_046: [ socket_transport_receive shall call WSARecv with the payload, flags and the data which is used as overlapped object. ]
int recv_result = WSARecv(socket_transport->socket, (LPWSABUF)payload, buffer_count, num_bytes_param, (LPDWORD)&flags, (LPWSAOVERLAPPED)data, NULL);
// Codes_SOCKET_TRANSPORT_WIN32_09_047: [ If WSARecv return 0, socket_transport_receive shall do the following: ]
if (recv_result == 0)
{
// Codes_SOCKET_TRANSPORT_WIN32_09_048: [ If bytes_recv is not NULL, socket_transport_receive shall copy the number of bytes into bytes_recv. ]
// Success
if (bytes_recv != NULL)
{
*bytes_recv = num_bytes;
}
// Codes_SOCKET_TRANSPORT_WIN32_09_049: [ socket_transport_receive shall return SOCKET_RECEIVE_OK. ]
result = SOCKET_RECEIVE_OK;
}
// Codes_SOCKET_TRANSPORT_WIN32_09_050: [ If WSARecv returns an non-zero value, socket_transport_receive shall do the following: ]
else
{
int wsa_last_error = WSAGetLastError();
// Codes_SOCKET_TRANSPORT_WIN32_09_051: [ If WSAGetLastError returns WSA_IO_PENDING, and bytes_recv is not NULL, socket_transport_receive shall set bytes_recv to 0. ]
if (WSA_IO_PENDING == wsa_last_error)
{
if (bytes_recv != NULL)
{
*bytes_recv = 0;
}
// Codes_SOCKET_TRANSPORT_WIN32_09_052: [ socket_transport_receive shall return SOCKET_RECEIVE_WOULD_BLOCK. ]
result = SOCKET_RECEIVE_WOULD_BLOCK;
}
else
{
// Codes_SOCKET_TRANSPORT_WIN32_09_053: [ If WSAGetLastError does not returns WSA_IO_PENDING socket_transport_receive shall return SOCKET_RECEIVE_ERROR. ]
LogLastError("WSARecv failed with %d, WSAGetLastError returned %lu", recv_result, wsa_last_error);
result = SOCKET_RECEIVE_ERROR;
}
}
// Codes_SOCKET_TRANSPORT_WIN32_09_054: [ socket_transport_receive shall call sm_exec_end. ]
sm_exec_end(socket_transport->sm);
}
}
return result;
}