MU_TEST(client_server, handle_invalidation) { LWMsgContext* context = NULL; LWMsgProtocol* protocol = NULL; LWMsgPeer* client = NULL; LWMsgPeer* server = NULL; CounterHandle* handle = NULL; CounterRequest request; LWMsgCall* call; LWMsgSession* session = NULL; LWMsgParams in = LWMSG_PARAMS_INITIALIZER; LWMsgParams out = LWMSG_PARAMS_INITIALIZER; LWMsgHandleType locality = 0; struct timespec ts = {0, 50000000}; MU_TRY(lwmsg_context_new(NULL, &context)); 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_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)); session = lwmsg_call_get_session(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); handle = out.data; MU_TRY(lwmsg_peer_stop_listen(server)); nanosleep(&ts, NULL); MU_TRY(lwmsg_peer_start_listen(server)); MU_TRY(lwmsg_peer_acquire_call(client, &call)); MU_ASSERT_EQUAL(MU_TYPE_INTEGER, lwmsg_session_get_handle_location(session, handle, &locality), LWMSG_STATUS_INVALID_HANDLE); MU_TRY(lwmsg_session_release_handle(session, handle)); MU_TRY(lwmsg_peer_disconnect(client)); lwmsg_peer_delete(client); MU_TRY(lwmsg_peer_stop_listen(server)); lwmsg_peer_delete(server); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
static NTSTATUS NtpCtxCall( IN LWMsgCall* pCall, IN LWMsgTag RequestType, IN PVOID pRequest, IN LWMsgTag ResponseType, OUT PVOID* ppResponse ) { NTSTATUS status = 0; LWMsgParams in = LWMSG_PARAMS_INITIALIZER; LWMsgParams out = LWMSG_PARAMS_INITIALIZER; in.tag = RequestType; in.data = pRequest; status = NtIpcLWMsgStatusToNtStatus(lwmsg_call_dispatch(pCall, &in, &out, NULL, NULL)); BAIL_ON_NT_STATUS(status); if (out.tag != ResponseType) { status = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(status); } *ppResponse = out.data; cleanup: return status; error: *ppResponse = NULL; NtpCtxFreeResponse(pCall, out.tag, out.data); goto cleanup; }
static NTSTATUS NtpCtxCallAsync( IN PIO_CLIENT_ASYNC_CONTEXT pContext, IN LWMsgTag RequestType, IN PVOID pRequest, IN LWMsgTag ResponseType, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK pControl, IN IO_CLIENT_ASYNC_COMPLETE_FUNCTION pfnComplete ) { NTSTATUS status = STATUS_SUCCESS; pContext->in.tag = RequestType; pContext->in.data = pRequest; status = LwIoConnectionAcquireCall(&pContext->pCall); BAIL_ON_NT_STATUS(status); if (pControl) { pContext->lRefcount = 2; pContext->pfnComplete = pfnComplete; pContext->pControl = pControl; pContext->responseType = ResponseType; status = NtIpcLWMsgStatusToNtStatus(lwmsg_call_dispatch( pContext->pCall, &pContext->in, &pContext->out, NtpCtxCallComplete, pContext)); } else { status = NtIpcLWMsgStatusToNtStatus(lwmsg_call_dispatch( pContext->pCall, &pContext->in, &pContext->out, NULL, NULL)); } switch (status) { case STATUS_PENDING: /* We should only get STATUS_PENDING from async calls */ assert(pControl); pControl->AsyncCancelContext = pContext; BAIL_ON_NT_STATUS(status); case STATUS_SUCCESS: if (pContext->out.tag != ResponseType) { status = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(status); } break; default: BAIL_ON_NT_STATUS(status); } cleanup: return status; error: goto cleanup; }
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; }
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; }
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; }
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); }