int async_socket_open_async()

in win32/src/async_socket_win32.c [337:411]


int async_socket_open_async(ASYNC_SOCKET_HANDLE async_socket, SOCKET_HANDLE socket_handle, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete, void* on_open_complete_context)
{
    int result;

    /* Codes_SRS_ASYNC_SOCKET_WIN32_01_009: [ on_open_complete_context shall be allowed to be NULL. ]*/

    if (
        /* Codes_SRS_ASYNC_SOCKET_WIN32_01_007: [ If async_socket is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
        (async_socket == NULL) ||
        /* Codes_SRS_ASYNC_SOCKET_WIN32_01_008: [ If on_open_complete is NULL, async_socket_open_async shall fail and return a non-zero value. ]*/
        (on_open_complete == NULL) ||
        /* Codes_SRS_ASYNC_SOCKET_WIN32_01_034: [ If socket_handle is INVALID_SOCKET, async_socket_create shall fail and return NULL. ]*/
        (SOCKET)socket_handle == INVALID_SOCKET
        )
    {
        /* Codes_SRS_ASYNC_SOCKET_WIN32_01_039: [ If any error occurs, async_socket_open_async shall fail and return a non-zero value. ]*/
        LogError("ASYNC_SOCKET_HANDLE async_socket=%p, ON_ASYNC_SOCKET_OPEN_COMPLETE on_open_complete=%p, void* on_open_complete_context=%p",
            async_socket, on_open_complete, on_open_complete_context);
        result = MU_FAILURE;
    }
    else
    {
        /* Codes_SRS_ASYNC_SOCKET_WIN32_01_023: [ Otherwise, async_socket_open_async shall switch the state to OPENING. ]*/
        LONG current_state = InterlockedCompareExchange(&async_socket->state, (LONG)ASYNC_SOCKET_WIN32_STATE_OPENING, (LONG)ASYNC_SOCKET_WIN32_STATE_CLOSED);
        if (current_state != (LONG)ASYNC_SOCKET_WIN32_STATE_CLOSED)
        {
            /* Codes_SRS_ASYNC_SOCKET_WIN32_01_015: [ If async_socket is already OPEN or OPENING, async_socket_open_async shall fail and return a non-zero value. ]*/
            LogError("Open called in state %" PRI_MU_ENUM "", MU_ENUM_VALUE(ASYNC_SOCKET_WIN32_STATE, current_state));
            result = MU_FAILURE;
        }
        else
        {
            async_socket->socket_handle = socket_handle;

            /* Codes_SRS_ASYNC_SOCKET_WIN32_01_016: [ Otherwise async_socket_open_async shall initialize a thread pool environment by calling InitializeThreadpoolEnvironment. ]*/
            InitializeThreadpoolEnvironment(&async_socket->tp_environment);

            /* Codes_SRS_ASYNC_SOCKET_WIN32_01_036: [ async_socket_open_async shall set the thread pool for the environment to the pool obtained from the execution engine by calling SetThreadpoolCallbackPool. ]*/
            SetThreadpoolCallbackPool(&async_socket->tp_environment, async_socket->pool);

            /* Codes_SRS_ASYNC_SOCKET_WIN32_01_058: [ async_socket_open_async shall create a threadpool IO by calling CreateThreadpoolIo and passing socket_handle, the callback environment to it and on_io_complete as callback. ]*/
            async_socket->tp_io = CreateThreadpoolIo(async_socket->socket_handle, on_io_complete, NULL, &async_socket->tp_environment);
            if (async_socket->tp_io == NULL)
            {
                /* Codes_SRS_ASYNC_SOCKET_WIN32_01_039: [ If any error occurs, async_socket_open_async shall fail and return a non-zero value. ]*/
                LogLastError("CreateThreadpoolIo failed");
                result = MU_FAILURE;
            }
            else
            {
                /* Codes_SRS_ASYNC_SOCKET_WIN32_01_094: [ async_socket_open_async shall set the state to OPEN. ]*/
                (void)InterlockedExchange(&async_socket->state, (LONG)ASYNC_SOCKET_WIN32_STATE_OPEN);
                WakeByAddressSingle((PVOID)&async_socket->state);

                /* Codes_SRS_ASYNC_SOCKET_WIN32_01_017: [ On success async_socket_open_async shall call on_open_complete_context with ASYNC_SOCKET_OPEN_OK. ]*/
                on_open_complete(on_open_complete_context, ASYNC_SOCKET_OPEN_OK);

                /* Codes_SRS_ASYNC_SOCKET_WIN32_01_014: [ On success, async_socket_open_async shall return 0. ]*/
                result = 0;

                goto all_ok;
            }

            async_socket->socket_handle = (SOCKET_HANDLE)INVALID_SOCKET;

            DestroyThreadpoolEnvironment(&async_socket->tp_environment);

            (void)InterlockedExchange(&async_socket->state, (LONG)ASYNC_SOCKET_WIN32_STATE_CLOSED);
            WakeByAddressSingle((PVOID)&async_socket->state);
        }
    }

all_ok:
    return result;
}