SOCKET_RECEIVE_RESULT socket_transport_receive()

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