void ProxyGateway_DoWork ( REMOTE_MODULE_HANDLE remote_module ) { if (NULL == remote_module) { /* Codes_SRS_PROXY_GATEWAY_027_026: [Prerequisite Check - If the `remote_module` parameter is `NULL`, then `ProxyGateway_DoWork` shall do nothing] */ LogError("%s: NULL parameter - remote_module!", __FUNCTION__); } else { int32_t bytes_received; void * control_message = NULL; /* Codes_SRS_PROXY_GATEWAY_027_027: [Control Channel - `ProxyGateway_DoWork` shall poll the gateway control channel by calling `int nn_recv(int s, void * buf, size_t len, int flags)` with the control socket for `s`, `NULL` for `buf`, `NN_MSG` for `len` and NN_DONTWAIT for `flags`] */ if (0 > (bytes_received = nn_recv(remote_module->control_socket, &control_message, NN_MSG, NN_DONTWAIT))) { if (EAGAIN == nn_errno()) { /* Codes_SRS_PROXY_GATEWAY_027_028: [Control Channel - If no message is available, then `ProxyGateway_DoWork` shall abandon the control channel request] */ } else { /* Codes_SRS_PROXY_GATEWAY_027_066: [Control Channel - If an error occurred when polling the gateway, then `ProxyGateway_DoWork` shall signal the gateway abandon the control channel request] */ LogError("%s: Unexpected error received from the control channel!", __FUNCTION__); (void)send_control_reply(remote_module, (uint8_t)REMOTE_MODULE_GATEWAY_CONNECTION_ERROR); } } else { CONTROL_MESSAGE * structured_control_message; /* Codes_SRS_PROXY_GATEWAY_027_029: [Control Channel - If a control message was received, then `ProxyGateway_DoWork` will parse that message by calling `CONTROL_MESSAGE * ControlMessage_CreateFromByteArray(const unsigned char * source, size_t size)` with the buffer received from `nn_recv` as `source` and return value from `nn_recv` as `size`] */ if (NULL == (structured_control_message = ControlMessage_CreateFromByteArray((const unsigned char *)control_message, bytes_received))) { /* Codes_SRS_PROXY_GATEWAY_027_030: [Control Channel - If unable to parse the control message, then `ProxyGateway_DoWork` shall signal the gateway, free any previously allocated memory and abandon the control channel request] */ LogError("%s: Unable to parse control message!", __FUNCTION__); (void)send_control_reply(remote_module, (uint8_t)REMOTE_MODULE_GATEWAY_CONNECTION_ERROR); } else { // Route control channel messages to appropriate functions switch (structured_control_message->type) { case CONTROL_MESSAGE_TYPE_MODULE_CREATE: /* Codes_SRS_PROXY_GATEWAY_027_031: [Control Channel - If the message type is CONTROL_MESSAGE_TYPE_MODULE_CREATE, then `ProxyGateway_DoWork` shall process the create message] */ if (0 != process_module_create_message(remote_module, (const CONTROL_MESSAGE_MODULE_CREATE *)structured_control_message)) { LogError("%s: Unable to process create message!", __FUNCTION__); } break; case CONTROL_MESSAGE_TYPE_MODULE_START: /* Codes_SRS_PROXY_GATEWAY_027_032: [Control Channel - If the message type is CONTROL_MESSAGE_TYPE_MODULE_START and `Module_Start` was provided, then `ProxyGateway_DoWork` shall call `void Module_Start(MODULE_HANDLE moduleHandle)`] */ if (((MODULE_API_1 *)remote_module->module.module_apis)->Module_Start) { ((MODULE_API_1 *)remote_module->module.module_apis)->Module_Start(remote_module->module.module_handle); } break; case CONTROL_MESSAGE_TYPE_MODULE_DESTROY: /* Codes_SRS_PROXY_GATEWAY_027_033: [Control Channel - If the message type is CONTROL_MESSAGE_TYPE_MODULE_DESTROY, then `ProxyGateway_DoWork` shall call `void Module_Destroy(MODULE_HANDLE moduleHandle)`] */ ((MODULE_API_1 *)remote_module->module.module_apis)->Module_Destroy(remote_module->module.module_handle); remote_module->module.module_handle = NULL; /* Codes_SRS_PROXY_GATEWAY_027_034: [Control Channel - If the message type is CONTROL_MESSAGE_TYPE_MODULE_DESTROY, then `ProxyGateway_DoWork` shall disconnect from the message channel] */ disconnect_from_message_channel(remote_module); break; default: LogError("ERROR: REMOTE_MODULE - Received unsupported message type! [%d]\n", structured_control_message->type); break; } /* Codes_SRS_PROXY_GATEWAY_027_035: [Control Channel - `ProxyGateway_DoWork` shall free the resources held by the parsed control message by calling `void ControlMessage_Destroy(CONTROL_MESSAGE * message)` using the parsed control message as `message`] */ ControlMessage_Destroy(structured_control_message); } /* Codes_SRS_PROXY_GATEWAY_027_036: [Control Channel - `ProxyGateway_DoWork` shall free the resources held by the gateway message by calling `int nn_freemsg(void * msg)` with the resulting buffer from the previous call to `nn_recv`] */ (void)nn_freemsg(control_message); } /* Codes_SRS_PROXY_GATEWAY_027_037: [Message Channel - `ProxyGateway_DoWork` shall not check for messages, if the message socket is not available] */ if ( 0 > remote_module->message_socket ) { // not connected to message channel } else { void * module_message = NULL; /* Codes_SRS_PROXY_GATEWAY_027_038: [Message Channel - `ProxyGateway_DoWork` shall poll the gateway message channel by calling `int nn_recv(int s, void * buf, size_t len, int flags)` with each message socket for `s`, `NULL` for `buf`, `NN_MSG` for `len` and NN_DONTWAIT for `flags`] */ if (0 > (bytes_received = nn_recv(remote_module->message_socket, &module_message, NN_MSG, NN_DONTWAIT))) { /* Codes_SRS_PROXY_GATEWAY_027_039: [Message Channel - If no message is available or an error occurred, then `ProxyGateway_DoWork` shall abandon the message channel request] */ if (EAGAIN == nn_errno()) { // no messages available at this time } else { LogError("%s: Unexpected error received from the message channel!", __FUNCTION__); } } else { MESSAGE_HANDLE structured_module_message; /* Codes_SRS_PROXY_GATEWAY_027_040: [Message Channel - If a module message was received, then `ProxyGateway_DoWork` will parse that message by calling `MESSAGE_HANDLE Message_CreateFromByteArray(const unsigned char * source, int32_t size)` with the buffer received from `nn_recv` as `source` and return value from `nn_recv` as `size`] */ if (NULL == (structured_module_message = Message_CreateFromByteArray((const unsigned char *)module_message, bytes_received))) { /* Codes_SRS_PROXY_GATEWAY_027_041: [Message Channel - If unable to parse the module message, then `ProxyGateway_DoWork` shall free any previously allocated memory and abandon the message channel request] */ LogError("%s: Unable to parse control message!", __FUNCTION__); } else { /* Codes_SRS_PROXY_GATEWAY_027_042: [Message Channel - `ProxyGateway_DoWork` shall pass the structured message to the module by calling `void Module_Receive(MODULE_HANDLE moduleHandle)` using the parsed message as `moduleHandle`] */ ((MODULE_API_1 *)remote_module->module.module_apis)->Module_Receive(remote_module->module.module_handle, structured_module_message); /* Codes_SRS_PROXY_GATEWAY_027_043: [Message Channel - `ProxyGateway_DoWork` shall free the resources held by the parsed module message by calling `void Message_Destroy(MESSAGE_HANDLE * message)` using the parsed module message as `message`] */ Message_Destroy(structured_module_message); } /* Codes_SRS_PROXY_GATEWAY_027_044: [Message Channel - `ProxyGateway_DoWork` shall free the resources held by the gateway message by calling `int nn_freemsg(void * msg)` with the resulting buffer from the previous call to `nn_recv`] */ (void)nn_freemsg(module_message); } } } return; }
/** * This function runs for each module. It receives a pointer to a MODULE_INFO * object that describes the module. Its job is to call the Receive function on * the associated module whenever it receives a message. */ static int module_worker(void * user_data) { /*Codes_SRS_BROKER_13_026: [This function shall assign `user_data` to a local variable called `module_info` of type `BROKER_MODULEINFO*`.]*/ BROKER_MODULEINFO* module_info = (BROKER_MODULEINFO*)user_data; int should_continue = 1; while (should_continue) { /*Codes_SRS_BROKER_13_089: [ This function shall acquire the lock on module_info->socket_lock. ]*/ if (Lock(module_info->socket_lock)) { /*Codes_SRS_BROKER_02_004: [ If acquiring the lock fails, then module_worker shall return. ]*/ LogError("unable to Lock"); should_continue = 0; break; } int nn_fd = module_info->receive_socket; int nbytes; unsigned char *buf = NULL; /*Codes_SRS_BROKER_17_005: [ For every iteration of the loop, the function shall wait on the receive_socket for messages. ]*/ nbytes = nn_recv(nn_fd, (void *)&buf, NN_MSG, 0); /*Codes_SRS_BROKER_13_091: [ The function shall unlock module_info->socket_lock. ]*/ if (Unlock(module_info->socket_lock) != LOCK_OK) { /*Codes_SRS_BROKER_17_016: [ If releasing the lock fails, then module_worker shall return. ]*/ should_continue = 0; if (nbytes > 0) { /*Codes_SRS_BROKER_17_019: [ The function shall free the buffer received on the receive_socket. ]*/ nn_freemsg(buf); } break; } if (nbytes < 0) { /*Codes_SRS_BROKER_17_006: [ An error on receiving a message shall terminate the loop. ]*/ should_continue = 0; } else { if (nbytes == BROKER_GUID_SIZE && (strncmp(STRING_c_str(module_info->quit_message_guid), (const char *)buf, BROKER_GUID_SIZE-1)==0)) { /*Codes_SRS_BROKER_13_068: [ This function shall run a loop that keeps running until module_info->quit_message_guid is sent to the thread. ]*/ /* received special quit message for this module */ should_continue = 0; } else { /*Codes_SRS_BROKER_17_024: [ The function shall strip off the topic from the message. ]*/ const unsigned char*buf_bytes = (const unsigned char*)buf; buf_bytes += sizeof(MODULE_HANDLE); /*Codes_SRS_BROKER_17_017: [ The function shall deserialize the message received. ]*/ MESSAGE_HANDLE msg = Message_CreateFromByteArray(buf_bytes, nbytes - sizeof(MODULE_HANDLE)); /*Codes_SRS_BROKER_17_018: [ If the deserialization is not successful, the message loop shall continue. ]*/ if (msg != NULL) { /*Codes_SRS_BROKER_13_092: [The function shall deliver the message to the module's callback function via module_info->module_apis. ]*/ MODULE_RECEIVE(module_info->module->module_apis)(module_info->module->module_handle, msg); /*Codes_SRS_BROKER_13_093: [ The function shall destroy the message that was dequeued by calling Message_Destroy. ]*/ Message_Destroy(msg); } } /*Codes_SRS_BROKER_17_019: [ The function shall free the buffer received on the receive_socket. ]*/ nn_freemsg(buf); } } return 0; }
int outprocessIncomingMessageThread(void *param) { /*Codes_SRS_OUTPROCESS_MODULE_17_037: [ This function shall receive the module handle data as the thread parameter. ]*/ OUTPROCESS_HANDLE_DATA * handleData = (OUTPROCESS_HANDLE_DATA*)param; if (handleData == NULL) { LogError("outprocess thread: parameter is NULL"); } else { int should_continue = 1; while (should_continue) { /*Codes_SRS_OUTPROCESS_MODULE_17_036: [ This function shall ensure thread safety on execution. ]*/ if (Lock(handleData->handle_lock) != LOCK_OK) { LogError("unable to Lock handle data"); should_continue = 0; break; } int nn_fd = handleData->message_socket; if (Unlock(handleData->handle_lock) != LOCK_OK) { should_continue = 0; break; } /*Codes_SRS_OUTPROCESS_MODULE_17_036: [ This function shall ensure thread safety on execution. ]*/ if (Lock(handleData->message_receive_thread.thread_lock) != LOCK_OK) { LogError("unable to Lock"); should_continue = 0; break; } if (handleData->message_receive_thread.thread_flag == THREAD_FLAG_STOP) { should_continue = 0; (void)Unlock(handleData->message_receive_thread.thread_lock); break; } if (Unlock(handleData->message_receive_thread.thread_lock) != LOCK_OK) { should_continue = 0; break; } int nbytes; unsigned char *buf = NULL; errno = 0; /*Codes_SRS_OUTPROCESS_MODULE_17_038: [ This function shall read from the message channel for gateway messages from the module host. ]*/ nbytes = nn_recv(nn_fd, (void *)&buf, NN_MSG, 0); if (nbytes < 0) { int receive_error = nn_errno(); if (receive_error != ETIMEDOUT && receive_error != EINTR) should_continue = 0; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_039: [ Upon successful receiving a gateway message, this function shall deserialize the message. ]*/ const unsigned char*buf_bytes = (const unsigned char*)buf; MESSAGE_HANDLE msg = Message_CreateFromByteArray(buf_bytes, nbytes); if (msg != NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_040: [ This function shall publish any successfully created gateway message to the broker. ]*/ Broker_Publish(handleData->broker, (MODULE_HANDLE)handleData, msg); Message_Destroy(msg); } nn_freemsg(buf); } ThreadAPI_Sleep(1); } } return 0; }