Ejemplo n.º 1
0
DWORD
LwSmReleaseServiceHandle(
    LW_SERVICE_HANDLE hHandle
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    in.tag = SM_IPC_RELEASE_SERVICE_HANDLE_REQ;
    in.data = (PVOID) hHandle;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_RELEASE_SERVICE_HANDLE_RES:
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        /* Destroying the in parameters will free the handle */
        lwmsg_call_destroy_params(pCall, &in);
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 2
0
DWORD
LwSmSetServiceLogTarget(
    LW_SERVICE_HANDLE hHandle,
    LW_PCSTR pszFacility,
    LW_SM_LOGGER_TYPE type,
    PCSTR pszTarget
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    SM_SET_LOG_INFO_REQ info = {0};

    info.hHandle = (LWMsgHandle*) hHandle;
    info.pFacility = (PSTR) pszFacility;
    info.type = type;
    info.pszTarget = (PSTR) pszTarget;
    in.tag = SM_IPC_SET_LOG_INFO_REQ;
    in.data = &info;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_SET_LOG_INFO_RES:
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 3
0
DWORD
LwSmWaitService(
    LW_SERVICE_HANDLE hHandle,
    LW_SERVICE_STATE currentState,
    PLW_SERVICE_STATE pNewState
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    SM_IPC_WAIT_STATE_CHANGE_REQ req = {0};

    req.hHandle = (LWMsgHandle*) hHandle;
    req.state = currentState;

    in.tag = SM_IPC_WAIT_SERVICE_REQ;
    in.data = &req;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_WAIT_SERVICE_RES:
        *pNewState = *(PLW_SERVICE_STATE) out.data;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 4
0
DWORD
LwmEvtGetRecordCount(
    PLW_EVT_CLIENT_CONNECTION_CONTEXT pConn,
    IN PCWSTR pSqlFilter,
    OUT PDWORD pNumMatched
    )
{
    DWORD dwError = 0;
    PEVT_IPC_GENERIC_ERROR pError = NULL;

    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    LWMsgCall* pCall = NULL;

    dwError = LwmEvtAcquireCall(pConn, &pCall);
    BAIL_ON_EVT_ERROR(dwError);

    in.tag = EVT_Q_GET_RECORD_COUNT;
    in.data = (PVOID)pSqlFilter;

    dwError = MAP_LWMSG_ERROR(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_EVT_ERROR(dwError);
    
    switch (out.tag)
    {
    case EVT_R_GET_RECORD_COUNT:
        *pNumMatched = *(PDWORD)out.data;
        break;
    case EVT_R_GENERIC_ERROR:
        pError = (PEVT_IPC_GENERIC_ERROR) out.data;
        dwError = pError->Error;
        BAIL_ON_EVT_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_EVT_ERROR(dwError);
    }

cleanup:
    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }
    return dwError;

error:
    if (pNumMatched)
    {
        *pNumMatched = 0;
    }
    goto cleanup;
}
Ejemplo n.º 5
0
DWORD
LwSmAcquireServiceHandle(
    LW_PCWSTR pwszServiceName,
    PLW_SERVICE_HANDLE phHandle
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    in.tag = SM_IPC_ACQUIRE_SERVICE_HANDLE_REQ;
    in.data = (PVOID) pwszServiceName;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_ACQUIRE_SERVICE_HANDLE_RES:
        *phHandle = out.data;
        out.data = NULL;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    *phHandle = NULL;

    goto cleanup;
}
Ejemplo n.º 6
0
DWORD
LwmEvtWriteRecords(
    PLW_EVT_CLIENT_CONNECTION_CONTEXT pConn,
    IN DWORD Count,
    IN PLW_EVENTLOG_RECORD pRecords 
    )
{
    DWORD dwError = 0;
    PEVT_IPC_GENERIC_ERROR pError = NULL;
    EVT_IPC_RECORD_ARRAY req = { 0 };

    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    LWMsgCall* pCall = NULL;

    dwError = LwmEvtAcquireCall(pConn, &pCall);
    BAIL_ON_EVT_ERROR(dwError);

    req.Count = Count;
    req.pRecords = pRecords;

    in.tag = EVT_Q_WRITE_RECORDS;
    in.data = &req;

    dwError = MAP_LWMSG_ERROR(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_EVT_ERROR(dwError);
    
    switch (out.tag)
    {
    case EVT_R_GENERIC_SUCCESS:
        break;
    case EVT_R_GENERIC_ERROR:
        pError = (PEVT_IPC_GENERIC_ERROR) out.data;
        dwError = pError->Error;
        BAIL_ON_EVT_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_EVT_ERROR(dwError);
    }

cleanup:
    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }
    return dwError;

error:
    goto cleanup;
}
Ejemplo n.º 7
0
DWORD
LwSmQueryServiceInfo(
    LW_SERVICE_HANDLE hHandle,
    PLW_SERVICE_INFO* ppInfo
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    in.tag = SM_IPC_QUERY_SERVICE_INFO_REQ;
    in.data = hHandle;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_QUERY_SERVICE_INFO_RES:
        *ppInfo = out.data;
        out.data = NULL;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    *ppInfo = NULL;

    goto cleanup;
}
Ejemplo n.º 8
0
DWORD
LwSmEnumerateServices(
    PWSTR** pppwszServiceNames
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    in.tag = SM_IPC_ENUMERATE_SERVICES_REQ;
    in.data = NULL;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_ENUMERATE_SERVICES_RES:
        *pppwszServiceNames = (PWSTR*) out.data;
        out.data = NULL;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    *pppwszServiceNames = NULL;

    goto cleanup;
}
Ejemplo n.º 9
0
LW_NTSTATUS
LwIoQueryStateDriver(
    LW_PWSTR pwszDriverName,
    PLWIO_DRIVER_STATE pState
    )
{
    NTSTATUS status = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    status = LwIoConnectionAcquireCall(&pCall);
    BAIL_ON_NT_STATUS(status);

    in.tag = LWIO_QUERY_STATE_DRIVER;
    in.data = pwszDriverName;

    status = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_NT_STATUS(status);

    switch (out.tag)
    {
    case LWIO_QUERY_STATE_DRIVER_SUCCESS:
        *pState = *((PLWIO_DRIVER_STATE) out.data);
        break;
    case LWIO_QUERY_STATE_DRIVER_FAILED:
        status = ((PLWIO_STATUS_REPLY) out.data)->dwError;
        BAIL_ON_LWIO_ERROR(status);
        break;
    default:
        status = STATUS_INTERNAL_ERROR;
        BAIL_ON_LWIO_ERROR(status);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return status;

error:

    goto cleanup;
}
Ejemplo n.º 10
0
DWORD
LwSmShutdown(
    VOID
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;

    in.tag = SM_IPC_SHUTDOWN_REQ;
    in.data = NULL;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_SHUTDOWN_RES:
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 11
0
static
VOID
NtpFreeClientAsyncContext(
    PIO_CLIENT_ASYNC_CONTEXT pContext
    )
{
    if (pContext)
    {
        if (pContext->pCall)
        {
            lwmsg_call_destroy_params(pContext->pCall, &pContext->out);
            lwmsg_call_release(pContext->pCall);
        }

        RTL_FREE(&pContext);
    }
}
Ejemplo n.º 12
0
static
VOID
NtpCtxFreeResponse(
    IN LWMsgCall* pCall,
    IN LWMsgTag ResponseType,
    IN PVOID pResponse
    )
{
    LWMsgStatus status = LWMSG_STATUS_SUCCESS;
    LWMsgParams params = LWMSG_PARAMS_INITIALIZER;

    params.tag = ResponseType;
    params.data = pResponse;

    status = lwmsg_call_destroy_params(pCall, &params);
    LW_ASSERT(status == LWMSG_STATUS_SUCCESS);
}
Ejemplo n.º 13
0
static void*
add_thread(void* _data)
{
    Data *data = _data;
    int i;
    LWMsgCall* call = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    CounterAdd add;
    CounterReply* reply = NULL;

    pthread_mutex_lock(&data->lock);
    while (!data->go)
    {
        pthread_cond_wait(&data->event, &data->lock);
    }
    pthread_mutex_unlock(&data->lock);

    add.handle = data->handle;
    add.delta = 1;

    for (i = 0; i < data->iters; i++)
    {
        MU_TRY(lwmsg_peer_acquire_call(data->client, &call));

        in.tag = COUNTER_ADD;
        in.data = &add;
        
        MU_TRY(lwmsg_call_dispatch(call, &in, &out, NULL, NULL));

        MU_ASSERT_EQUAL(MU_TYPE_INTEGER, out.tag, COUNTER_ADD_SUCCESS);
        reply = (CounterReply*) out.data;
        
        MU_VERBOSE("(0x%lx) counter: %i -> %i",
                   (unsigned long) (pthread_self()), 
                   reply->counter,
                   reply->counter+1);
        
        lwmsg_call_destroy_params(call, &out);
        lwmsg_call_release(call);
    }

    return NULL;
}
Ejemplo n.º 14
0
DWORD
LwmEvtReadRecords(
    PLW_EVT_CLIENT_CONNECTION_CONTEXT pConn,
    IN DWORD MaxResults,
    IN PCWSTR pSqlFilter,
    OUT PDWORD pCount,
    OUT PLW_EVENTLOG_RECORD* ppRecords
    )
{
    DWORD dwError = 0;
    PEVT_IPC_GENERIC_ERROR pError = NULL;
    EVT_IPC_READ_RECORDS_REQ req = { 0 };
    PEVT_IPC_RECORD_ARRAY pRes = NULL;

    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    LWMsgCall* pCall = NULL;

    dwError = LwmEvtAcquireCall(pConn, &pCall);
    BAIL_ON_EVT_ERROR(dwError);

    req.MaxResults = MaxResults;
    req.pFilter = pSqlFilter;

    in.tag = EVT_Q_READ_RECORDS;
    in.data = &req;

    dwError = MAP_LWMSG_ERROR(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_EVT_ERROR(dwError);
    
    switch (out.tag)
    {
    case EVT_R_READ_RECORDS:
        pRes = (PEVT_IPC_RECORD_ARRAY)out.data;
        *pCount = pRes->Count;
        *ppRecords = pRes->pRecords;
        pRes->Count = 0;
        pRes->pRecords = NULL;
        break;
    case EVT_R_GENERIC_ERROR:
        pError = (PEVT_IPC_GENERIC_ERROR) out.data;
        dwError = pError->Error;
        BAIL_ON_EVT_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_EVT_ERROR(dwError);
    }

cleanup:
    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }
    return dwError;

error:
    *pCount = 0;
    *ppRecords = NULL;
    goto cleanup;
}
Ejemplo n.º 15
0
DWORD
LwSmGetServiceLogState(
    LW_SERVICE_HANDLE hHandle,
    LW_PCSTR pFacility,
    PLW_SM_LOGGER_TYPE pType,
    LW_PSTR* ppTarget,
    PLW_SM_LOG_LEVEL pLevel
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    SM_GET_LOG_STATE_REQ req = {0};
    PSM_GET_LOG_STATE_RES pRes = NULL;

    req.hHandle = (LWMsgHandle*) hHandle;
    req.pFacility = (PSTR) pFacility;

    in.tag = SM_IPC_GET_LOG_STATE_REQ;
    in.data = &req;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_GET_LOG_STATE_RES:
        pRes = out.data;
        *pType = pRes->type;
        *ppTarget = pRes->pszTarget;
        *pLevel = pRes->Level;
        pRes->pszTarget = NULL;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 16
0
DWORD
LwSmGetGlobal(
    LW_IN LW_SM_GLOBAL_SETTING Setting,
    ...
    )
{
    DWORD dwError = 0;
    LWMsgCall* pCall = NULL;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    SM_GET_GLOBAL_REQ req = {0};
    PSM_GLOBAL_VALUE pValue = NULL;
    va_list ap;

    req.Setting = Setting;

    in.tag = SM_IPC_GET_GLOBAL_REQ;
    in.data = &req;

    dwError = LwSmIpcAcquireCall(&pCall);
    BAIL_ON_ERROR(dwError);

    dwError = MAP_LWMSG_STATUS(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL));
    BAIL_ON_ERROR(dwError);

    switch (out.tag)
    {
    case SM_IPC_GET_GLOBAL_RES:
        pValue = out.data;
        break;
    case SM_IPC_ERROR:
        dwError = *(PDWORD) out.data;
        BAIL_ON_ERROR(dwError);
        break;
    default:
        dwError = LW_ERROR_INTERNAL;
        BAIL_ON_ERROR(dwError);
        break;
    }

    va_start(ap, Setting);
    switch (Setting)
    {
    case LW_SM_GLOBAL_SETTING_WATCHDOG:
        if (pValue->Type != SM_GLOBAL_TYPE_BOOLEAN)
        {
            dwError = LW_ERROR_INTERNAL;
        }
        else
        {
            *(va_arg(ap, PBOOLEAN)) = pValue->Value.Boolean;
        }
        break;
    default:
        dwError = ERROR_INVALID_PARAMETER;
        break;
    }
    va_end(ap);
    BAIL_ON_ERROR(dwError);

cleanup:

    if (pCall)
    {
        lwmsg_call_destroy_params(pCall, &out);
        lwmsg_call_release(pCall);
    }

    return dwError;

error:

    goto cleanup;
}
Ejemplo n.º 17
0
MU_TEST(stress, parallel)
{
    Data data;
    pthread_t threads[NUM_THREADS];
    int i;
    LWMsgContext* context = NULL;
    LWMsgProtocol* protocol = NULL;
    LWMsgPeer* client = NULL;
    LWMsgPeer* server = NULL;
    CounterRequest request;
    CounterReply* reply;
    LWMsgCall* call;
    LWMsgParams in = LWMSG_PARAMS_INITIALIZER;
    LWMsgParams out = LWMSG_PARAMS_INITIALIZER;
    LWMsgTime timeout = {1, 0};

    MU_TRY(lwmsg_context_new(NULL, &context));
    lwmsg_context_set_log_function(context, lwmsg_test_log_function, NULL);

    MU_TRY(lwmsg_protocol_new(context, &protocol));
    MU_TRY(lwmsg_protocol_add_protocol_spec(protocol, counterprotocol_spec));

    MU_TRY(lwmsg_peer_new(context, protocol, &server));
    MU_TRY(lwmsg_peer_add_dispatch_spec(server, counter_dispatch));
    MU_TRY(lwmsg_peer_add_listen_endpoint(server, LWMSG_CONNECTION_MODE_LOCAL, TEST_ENDPOINT, 0600));
    MU_TRY(lwmsg_peer_set_max_listen_clients(server, MAX_CLIENTS));
    MU_TRY(lwmsg_peer_set_timeout(server, LWMSG_TIMEOUT_IDLE, &timeout));
    MU_TRY(lwmsg_peer_start_listen(server));

    MU_TRY(lwmsg_peer_new(context, protocol, &client));
    MU_TRY(lwmsg_peer_add_connect_endpoint(client, LWMSG_CONNECTION_MODE_LOCAL, TEST_ENDPOINT));

    request.counter = 0;

    MU_TRY(lwmsg_peer_acquire_call(client, &call));
    in.tag = COUNTER_OPEN;
    in.data = &request;

    MU_TRY(lwmsg_call_dispatch(call, &in, &out, NULL, NULL));
    
    MU_ASSERT_EQUAL(MU_TYPE_INTEGER, out.tag, COUNTER_OPEN_SUCCESS);
    lwmsg_call_release(call);

    data.client = client;
    data.handle = out.data;
    data.iters = NUM_ITERS;
    data.go = 0;
    
    pthread_mutex_init(&data.lock, NULL);
    pthread_cond_init(&data.event, NULL);

    pthread_mutex_lock(&data.lock);
    for (i = 0; i < NUM_THREADS; i++)
    {
        pthread_create(&threads[i], NULL, add_thread, &data);
    }
    data.go = 1;
    pthread_cond_broadcast(&data.event);
    pthread_mutex_unlock(&data.lock);

    for (i = 0; i < NUM_THREADS; i++)
    {
        pthread_join(threads[i], NULL);
    }

    MU_TRY(lwmsg_peer_acquire_call(client, &call));
    in.tag = COUNTER_READ;
    in.data = data.handle;

    MU_TRY(lwmsg_call_dispatch(call, &in, &out, NULL, NULL));
    
    MU_ASSERT_EQUAL(MU_TYPE_INTEGER, out.tag, COUNTER_READ_SUCCESS);
    reply = out.data;

    MU_ASSERT_EQUAL(MU_TYPE_INTEGER, reply->counter, NUM_THREADS * NUM_ITERS);

    lwmsg_call_destroy_params(call, &out);
    lwmsg_call_release(call);
    
    MU_TRY(lwmsg_peer_acquire_call(client, &call));
    in.tag = COUNTER_CLOSE;
    in.data = data.handle;

    MU_TRY(lwmsg_call_dispatch(call, &in, &out, NULL, NULL));
    
    MU_ASSERT_EQUAL(MU_TYPE_INTEGER, out.tag, COUNTER_CLOSE_SUCCESS);

    lwmsg_call_destroy_params(call, &out);
    lwmsg_call_release(call);

    MU_TRY(lwmsg_peer_disconnect(client));
    lwmsg_peer_delete(client);

    MU_TRY(lwmsg_peer_stop_listen(server));
    lwmsg_peer_delete(server);

    pthread_mutex_destroy(&data.lock);
    pthread_cond_destroy(&data.event);
}