in linux/src/async_socket_linux.c [855:927]
int async_socket_notify_io_async(ASYNC_SOCKET_HANDLE async_socket, ASYNC_SOCKET_NOTIFY_IO_TYPE io_type, ON_ASYNC_SOCKET_NOTIFY_IO_COMPLETE on_notify_io_complete, void* on_notify_io_complete_context)
{
int result;
// Codes_SRS_ASYNC_SOCKET_LINUX_04_012: [ If async_socket is NULL, async_socket_notify_io_async shall fail and return a non-zero value. ]
// Codes_SRS_ASYNC_SOCKET_LINUX_04_013: [ If on_notify_io_complete is NULL, async_socket_notify_io_async shall fail and return a non-zero value. ]
// Codes_SRS_ASYNC_SOCKET_LINUX_04_014: [ If io_type has an invalid value, then async_socket_notify_io_async shall fail and return a non-zero value. ]
// Codes_SRS_ASYNC_SOCKET_LINUX_04_016: [ on_notify_io_complete_context is allowed to be NULL. ]
if (async_socket == NULL || on_notify_io_complete == NULL || (io_type != ASYNC_SOCKET_NOTIFY_IO_TYPE_IN && io_type != ASYNC_SOCKET_NOTIFY_IO_TYPE_OUT))
{
LogError(
"Invalid arguments: ASYNC_SOCKET_HANDLE async_socket=%p, ASYNC_SOCKET_NOTIFY_IO_TYPE io_type=%" PRI_MU_ENUM
", ON_ASYNC_SOCKET_NOTIFY_IO_COMPLETE on_io_complete=%p, void* on_io_complete_context=%p",
async_socket, MU_ENUM_VALUE(ASYNC_SOCKET_NOTIFY_IO_TYPE, io_type), on_notify_io_complete, on_notify_io_complete_context);
result = MU_FAILURE;
}
else
{
(void)interlocked_increment(&async_socket->pending_api_calls);
// Codes_SRS_ASYNC_SOCKET_LINUX_04_015: [ If the async socket's current state is not ASYNC_SOCKET_LINUX_STATE_OPEN then async_socket_notify_io_async shall fail and return a non-zero value. ]
ASYNC_SOCKET_LINUX_STATE current_state;
if ((current_state = interlocked_add(&async_socket->state, 0)) != ASYNC_SOCKET_LINUX_STATE_OPEN)
{
LogWarning("Not open, current state is %" PRI_MU_ENUM "", MU_ENUM_VALUE(ASYNC_SOCKET_LINUX_STATE, current_state));
result = MU_FAILURE;
}
else
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_017: [ Otherwise async_socket_notify_io_async shall create a context for the notify where the on_notify_io_complete and on_notify_io_complete_context shall be stored. ]
ASYNC_SOCKET_IO_CONTEXT* io_context = malloc(sizeof(ASYNC_SOCKET_IO_CONTEXT));
if (io_context == NULL)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_020: [ If any error occurs, async_socket_notify_io_async shall fail and return a non-zero value. ]
LogError("failure in malloc(sizeof(ASYNC_SOCKET_IO_CONTEXT)=%zu) failed", sizeof(ASYNC_SOCKET_IO_CONTEXT));
result = MU_FAILURE;
}
else
{
io_context->io_type = ASYNC_SOCKET_IO_TYPE_NOTIFY;
io_context->on_notify_io_complete = on_notify_io_complete;
io_context->callback_context = on_notify_io_complete_context;
io_context->async_socket = async_socket;
int epoll_op = (io_type == ASYNC_SOCKET_NOTIFY_IO_TYPE_IN) ? EPOLLIN : EPOLLOUT;
// Codes_SRS_ASYNC_SOCKET_LINUX_04_018: [ Then the context shall then be added to the completion port system by calling completion_port_add with EPOLLIN if io_type is ASYNC_SOCKET_NOTIFY_IO_TYPE_IN and EPOLLOUT otherwise and event_complete_callback as the callback. ]
if (completion_port_add(async_socket->completion_port, epoll_op, async_socket->socket_handle, event_complete_callback, io_context) != 0)
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_020: [ If any error occurs, async_socket_notify_io_async shall fail and return a non-zero value. ]
LogWarning("failure with completion_port_add");
result = MU_FAILURE;
}
else
{
// Codes_SRS_ASYNC_SOCKET_LINUX_04_019: [ On success, async_socket_notify_io_async shall return 0. ]
result = 0;
(void)interlocked_increment(&async_socket->added_to_completion_port);
goto all_ok;
}
free(io_context);
}
}
all_ok:
if (interlocked_decrement(&async_socket->pending_api_calls) == 0)
{
wake_by_address_single(&async_socket->pending_api_calls);
}
}
return result;
}