static void Outprocess_Receive(MODULE_HANDLE moduleHandle, MESSAGE_HANDLE messageHandle) { OUTPROCESS_HANDLE_DATA* handleData = moduleHandle; /*Codes_SRS_OUTPROCESS_MODULE_17_022: [ If module or message_handle is NULL, this function shall do nothing. ]*/ if (handleData != NULL && messageHandle != NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_046: [ This function shall clone the message to ensure the message is kept allocated until forwarded to module host. ]*/ MESSAGE_HANDLE queued_message = Message_Clone(messageHandle); if (queued_message == NULL) { LogError("unable to clone message"); } else { /*Codes_SRS_OUTPROCESS_MODULE_17_045: [ This function shall ensure thread safety for the module data. ]*/ if (Lock(handleData->handle_lock) != LOCK_OK) { LogError("unable to Lock handle data"); Message_Destroy(queued_message); } else { /*Codes_SRS_OUTPROCESS_MODULE_17_047: [ This function shall push the message onto the end of the outgoing gateway message queue. ]*/ if (MESSAGE_QUEUE_push(handleData->outgoing_messages, queued_message) != 0) { LogError("unable to queue the message"); Message_Destroy(queued_message); } (void)Unlock(handleData->handle_lock); } } } }
int Dht_AddNode(void *client_, uint32_t addr, uint16_t port) { Message *qping = NULL; Client *client = (Client *)client_; check(client != NULL, "NULL client pointer"); Node node = { .addr.s_addr = addr, .port = port, .is_new = 1 }; qping = Message_CreateQPing(client, &node); check(qping != NULL, "Message_CreateQPing failed"); int rc = MessageQueue_Push(client->queries, qping); check(rc == 0, "Messagequeue_Push failed"); return 0; error: Message_Destroy(qping); return -1; } int Dht_Start(void *client_) { Client *client = (Client *)client_; check(client != NULL, "NULL client pointer"); Search *search = Client_AddSearch(client, &client->table->id); check(search != NULL, "Client_AddSearch failed"); int rc = NetworkUp(client); check(rc == 0, "NetworkUp failed"); return 0; error: return -1; }
char *test_junk_response(char **junk, void **gettype) { int i = 0; while (junk[i]) { int j = 0, len = strlen(junk[i]); while (gettype[j]) { Message *result = Message_Decode(junk[i], len, gettype[j]); mu_assert(result != NULL, "Message_Decode failed"); mu_assert(result->errors, "Decoded junk without error"); Message_DestroyNodes(result); Message_Destroy(result); j++; } i++; } i = 0; while (gettype[i]) free(gettype[i++]); return NULL; }
char *test_Decode_QPing() { char *data = "d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe"; Message *message = Message_Decode(data, strlen(data), NULL); mu_assert(check_Message(message, QPing) == NULL, "Bad decoded message"); Message_Destroy(message); return NULL; }
char *test_Roundtrip() { char *input[] = { "d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:rd2:id20:abcdefghij0123456789e1:t2:pi1:y1:re", "d1:rd2:id20:abcdefghij01234567895:nodes52:01234567890123456789ABCDEF????????????????????xxxxyye1:t2:fn1:y1:re", "d1:rd2:id20:abcdefghij01234567895:nodes208:012345678901234567890xxxy0112345678901234567891xxxy1212345678901234567892xxxy2312345678901234567893xxxy3412345678901234567894xxxy4512345678901234567895xxxy5612345678901234567896xxxy6712345678901234567897xxxy75:token8:aoeusnthe1:t2:gp1:y1:re", "d1:rd2:id20:abcdefghij01234567895:token8:aoeusnth6:valuesl6:0xxxy06:1xxxy16:2xxxy2ee1:t2:gp1:y1:re", "d1:rd2:id20:abcdefghij0123456789e1:t2:ap1:y1:re", "d1:eli201e23:A Generic Error Ocurrede1:t2:ee1:y1:ee", NULL }; struct PendingResponses responses = { .getPendingResponse = GetRoundtripResponseMessageType }; int i = 0; while (input[i]) { int len = strlen(input[i]); Message *message = Message_Decode(input[i], len, &responses); mu_assert(message != NULL, "Decode failed"); char *dest = calloc(1, len); mu_assert(dest != NULL, "malloc failed"); int rc = Message_Encode(message, dest, len - 1); mu_assert(rc == -1, "Encoded to too small dest"); rc = Message_Encode(message, dest, len); mu_assert(rc >= 0, "Encode failed"); mu_assert(rc == len, "Encoded too little"); mu_assert(same_bytes_len(input[i], dest, len), "Roundtrip failed"); Message_DestroyNodes(message); Message_Destroy(message); free(dest); i++; } return NULL; }
char *test_Decode_RAnnouncePeer() { char *data = "d1:rd2:id20:mnopqrstuvwxyz123456e1:t2:aa1:y1:re"; void *responses = GetMockResponses("aa", RAnnouncePeer, ID(data), 1); Message *message = Message_Decode(data, strlen(data), responses); mu_assert(check_Message(message, RAnnouncePeer) == NULL, "Bad decoded message"); Message_Destroy(message); free(responses); return NULL; }
char *test_Decode_RGetPeers_nodes() { char *input = "d1:rd2:id20:mnopqrstuvwxyz1234565:nodes208:" "012345678901234567890xxxy0" "112345678901234567891xxxy1" "212345678901234567892xxxy2" "312345678901234567893xxxy3" "412345678901234567894xxxy4" "512345678901234567895xxxy5" "612345678901234567896xxxy6" "712345678901234567897xxxy7" "5:token8:aoeusnthe1:t2:aa1:y1:re"; void *responses = GetMockResponses("aa", RGetPeers, ID(input), 1); Message *message = Message_Decode(input, strlen(input), responses); mu_assert(check_Message(message, RGetPeers) == NULL, "Bad decoded message"); RGetPeersData *data = &message->data.rgetpeers; mu_assert(same_bytes_len("aoeusnth", data->token.data, data->token.len), "Bad token"); mu_assert(data->values == NULL, "Bad values"); mu_assert(data->count == BUCKET_K, "Wrong nodes count"); char id[] = "_1234567890123456789", addr[] = "_xxx", port[] = "y_"; int i = 0; for (i = 0; i < BUCKET_K; i++) { id[0] = '0' + i; addr[0] = '0' + i; port[1] = '0' + i; mu_assert(same_bytes(id, data->nodes[i]->id.value), "Bad id"); mu_assert(data->nodes[i]->addr.s_addr == chntohl(addr), "Bad addr"); mu_assert(data->nodes[i]->port == chntohs(port), "Bad port"); } Message_DestroyNodes(message); Message_Destroy(message); free(responses); return NULL; }
char *test_Decode_QGetPeers() { char *data = "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe"; char *info_hash = "mnopqrstuvwxyz123456"; Message *message = Message_Decode(data, strlen(data), NULL); mu_assert(check_Message(message, QGetPeers) == NULL, "Bad decoded message"); mu_assert(message->data.qgetpeers.info_hash != NULL, "Missing info_hash"); mu_assert(same_bytes(info_hash, message->data.qgetpeers.info_hash->value), "Wrong info_hash"); Message_Destroy(message); return NULL; }
char *test_Decode_QFindNode() { char *data = "d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe"; Message *message = Message_Decode(data, strlen(data), NULL); mu_assert(check_Message(message, QFindNode) == NULL, "Bad decoded message"); mu_assert(message->data.qfindnode.target != NULL, "No target"); mu_assert(same_bytes("mnopqrstuvwxyz123456", message->data.qfindnode.target->value), "Wrong target"); Message_Destroy(message); return NULL; }
void MESSAGE_QUEUE_destroy(MESSAGE_QUEUE_HANDLE handle) { if (handle == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_004: [ MESSAGE_QUEUE_destroy shall not perform any actions on a NULL message queue. ]*/ LogError("invalid argument handle(NULL)."); } else { MESSAGE_QUEUE_HANDLE_DATA * mq = (MESSAGE_QUEUE_HANDLE_DATA*)handle; MESSAGE_HANDLE message; while((message = message_pop(mq)) != NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_005: [ If the message queue is not empty, MESSAGE_QUEUE_destroy shall destroy all messages in the queue. ]*/ Message_Destroy(message); } /*Codes_SRS_MESSAGE_QUEUE_17_006: [ MESSAGE_QUEUE_destroy shall free all allocated resources. ]*/ free(handle); } }
char *test_Decode_RError() { char *data[] = { "d1:eli201e7:Generice1:t2:aa1:y1:ee", "d1:eli202e6:Servere1:t2:aa1:y1:ee", "d1:eli203e8:Protocole1:t2:aa1:y1:ee", "d1:eli204e6:Methode1:t2:aa1:y1:ee", NULL }; int expected_code[] = { 201, 202, 203, 204 }; struct tagbstring expected_msg[] = { bsStatic("Generic"), bsStatic("Server"), bsStatic("Protocol"), bsStatic("Method") }; int i = 0; while (data[i]) { Message *message = Message_Decode(data[i], strlen(data[i]), NULL); mu_assert(message->type == RError, "Wrong message type"); mu_assert(same_bytes_len("aa", message->t, message->t_len), "Wrong transaction id"); RErrorData *data = &message->data.rerror; mu_assert(data->code == expected_code[i], "Wrong error code"); mu_assert(bstrcmp(&expected_msg[i], data->message) == 0, "Wrong message"); Message_Destroy(message); i++; } return NULL; }
static void publish_with_new_properties(MAP_HANDLE newProperties, MESSAGE_HANDLE messageHandle, IDENTITY_MAP_DATA * idModule) { /*Codes_SRS_IDMAP_17_034: [IdentityMap_Receive shall clone message content.] */ CONSTBUFFER_HANDLE content = Message_GetContentHandle(messageHandle); if (content == NULL) { /*Codes_SRS_IDMAP_17_035: [If cloning message content fails, IdentityMap_Receive shall deallocate all resources and return.]*/ LogError("Could not extract message content"); } else { MESSAGE_BUFFER_CONFIG newMessageConfig = { content, newProperties }; /*Codes_SRS_IDMAP_17_036: [IdentityMap_Receive shall create a new message by calling Message_CreateFromBuffer with new map and cloned content.]*/ MESSAGE_HANDLE newMessage = Message_CreateFromBuffer(&newMessageConfig); if (newMessage == NULL) { /*Codes_SRS_IDMAP_17_037: [If creating new message fails, IdentityMap_Receive shall deallocate all resources and return.]*/ LogError("Could not create new message to publish"); } else { MESSAGE_BUS_RESULT busStatus; /*Codes_SRS_IDMAP_17_038: [IdentityMap_Receive shall call MessageBus_Publish with busHandle and new message.]*/ busStatus = MessageBus_Publish(idModule->busHandle, newMessage); if (busStatus != MESSAGE_BUS_OK) { LogError("Message bus publish failure: %s", ENUM_TO_STRING(MESSAGE_BUS_RESULT, busStatus)); } Message_Destroy(newMessage); } /*Codes_SRS_IDMAP_17_039: [IdentityMap_Receive will destroy all resources it created.]*/ CONSTBUFFER_Destroy(content); } }
char *test_Decode_RGetPeers_values() { char *input = "d1:rd2:id20:mnopqrstuvwxyz1234565:token8:aoeusnth6:valuesl" "6:" "0xxxy0" "6:" "1xxxy1" "6:" "2xxxy2" "ee1:t2:aa1:y1:re"; void *responses = GetMockResponses("aa", RGetPeers, ID(input), 1); Message *message = Message_Decode(input, strlen(input), responses); mu_assert(check_Message(message, RGetPeers) == NULL, "Bad decoded message"); RGetPeersData *data = &message->data.rgetpeers; mu_assert(same_bytes_len("aoeusnth", data->token.data, data->token.len), "Bad token"); mu_assert(data->nodes == NULL, "Bad nodes"); mu_assert(data->count == 3, "Wrong values count"); char addr[] = "_xxx", port[] = "y_"; int i = 0; for (i = 0; i < 3; i++) { addr[0] = '0' + i; port[1] = '0' + i; mu_assert(data->values[i].addr == chntohl(addr), "Bad addr"); mu_assert(data->values[i].port == chntohs(port), "Bad port"); } Message_Destroy(message); free(responses); return NULL; }
char *test_Decode_RFindNode() { char *data = "d1:rd2:id20:mnopqrstuvwxyz1234565:nodes52:" "01234567890123456789ABCDEF" "????????????????????xxxxyy" "e1:t2:aa1:y1:re"; void *responses = GetMockResponses("aa", RFindNode, ID(data), 1); Message *message = Message_Decode(data, strlen(data), responses); mu_assert(check_Message(message, RFindNode) == NULL, "Bad decoded message"); mu_assert(message->data.rfindnode.nodes != NULL, "NULL nodes"); mu_assert(message->data.rfindnode.count == 2, "Wrong node count"); mu_assert(same_bytes("01234567890123456789", message->data.rfindnode.nodes[0]->id.value), "Wrong nodes[0] id"); mu_assert(message->data.rfindnode.nodes[0]->addr.s_addr == chntohl("ABCD"), "Wrong nodes[0] addr"); mu_assert(message->data.rfindnode.nodes[0]->port == chntohs("EF"), "Wrong nodes[0] port"); mu_assert(same_bytes("????????????????????", message->data.rfindnode.nodes[1]->id.value), "Wrong nodes[1] id"); mu_assert(message->data.rfindnode.nodes[1]->addr.s_addr == chntohl("xxxx"), "Wrong nodes[1] addr"); mu_assert(message->data.rfindnode.nodes[1]->port == chntohs("yy"), "Wrong nodes[1] port"); Message_DestroyNodes(message); Message_Destroy(message); free(responses); return NULL; }
char *test_Decode_QAnnouncePeer() { char *data = "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe"; char *info_hash = "mnopqrstuvwxyz123456", *token = "aoeusnth"; const int port = 6881; Message *message = Message_Decode(data, strlen(data), NULL); mu_assert(check_Message(message, QAnnouncePeer) == NULL, "Bad decoded message"); mu_assert(message->data.qannouncepeer.info_hash != NULL, "Missing info_hash"); mu_assert(same_bytes(info_hash, message->data.qannouncepeer.info_hash->value), "Wrong info_hash"); mu_assert(message->data.qannouncepeer.token.data != NULL, "No token"); mu_assert(message->data.qannouncepeer.token.len == strlen(token), "Wrong token length"); mu_assert(same_bytes(token, message->data.qannouncepeer.token.data), "Wrong token"); mu_assert(message->data.qannouncepeer.port == port, "Wrong port"); Message_Destroy(message); return NULL; }
BROKER_RESULT Broker_Publish(BROKER_HANDLE broker, MODULE_HANDLE source, MESSAGE_HANDLE message) { BROKER_RESULT result; /*Codes_SRS_BROKER_13_030: [If broker or message is NULL the function shall return BROKER_INVALIDARG.]*/ if (broker == NULL || source == NULL || message == NULL) { result = BROKER_INVALIDARG; LogError("Broker handle, source, and/or message handle is NULL"); } else { BROKER_HANDLE_DATA* broker_data = (BROKER_HANDLE_DATA*)broker; /*Codes_SRS_BROKER_17_022: [ Broker_Publish shall Lock the modules lock. ]*/ if (Lock(broker_data->modules_lock) != LOCK_OK) { /*Codes_SRS_BROKER_13_053: [This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise.]*/ LogError("Lock on broker_data->modules_lock failed"); result = BROKER_ERROR; } else { int32_t msg_size; int32_t buf_size; /*Codes_SRS_BROKER_17_007: [ Broker_Publish shall clone the message. ]*/ MESSAGE_HANDLE msg = Message_Clone(message); /*Codes_SRS_BROKER_17_008: [ Broker_Publish shall serialize the message. ]*/ msg_size = Message_ToByteArray(message, NULL, 0); if (msg_size < 0) { /*Codes_SRS_BROKER_13_053: [This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise.]*/ LogError("unable to serialize a message [%p]", msg); Message_Destroy(msg); result = BROKER_ERROR; } else { /*Codes_SRS_BROKER_17_025: [ Broker_Publish shall allocate a nanomsg buffer the size of the serialized message + sizeof(MODULE_HANDLE). ]*/ buf_size = msg_size + sizeof(MODULE_HANDLE); void* nn_msg = nn_allocmsg(buf_size, 0); if (nn_msg == NULL) { /*Codes_SRS_BROKER_13_053: [This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise.]*/ LogError("unable to serialize a message [%p]", msg); result = BROKER_ERROR; } else { /*Codes_SRS_BROKER_17_026: [ Broker_Publish shall copy source into the beginning of the nanomsg buffer. ]*/ unsigned char *nn_msg_bytes = (unsigned char *)nn_msg; memcpy(nn_msg_bytes, &source, sizeof(MODULE_HANDLE)); /*Codes_SRS_BROKER_17_027: [ Broker_Publish shall serialize the message into the remainder of the nanomsg buffer. ]*/ nn_msg_bytes += sizeof(MODULE_HANDLE); Message_ToByteArray(message, nn_msg_bytes, msg_size); /*Codes_SRS_BROKER_17_010: [ Broker_Publish shall send a message on the publish_socket. ]*/ int nbytes = nn_send(broker_data->publish_socket, &nn_msg, NN_MSG, 0); if (nbytes != buf_size) { /*Codes_SRS_BROKER_13_053: [This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise.]*/ LogError("unable to send a message [%p]", msg); /*Codes_SRS_BROKER_17_012: [ Broker_Publish shall free the message. ]*/ nn_freemsg(nn_msg); result = BROKER_ERROR; } else { result = BROKER_OK; } } /*Codes_SRS_BROKER_17_012: [ Broker_Publish shall free the message. ]*/ Message_Destroy(msg); /*Codes_SRS_BROKER_17_011: [ Broker_Publish shall free the serialized message data. ]*/ } /*Codes_SRS_BROKER_17_023: [ Broker_Publish shall Unlock the modules lock. ]*/ Unlock(broker_data->modules_lock); } } /*Codes_SRS_BROKER_13_037: [ This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise. ]*/ return result; }
static int SimulatorModule_thread(void * context) { int thread_result; SIMULATOR_MODULE_HANDLE * module = (SIMULATOR_MODULE_HANDLE *)context; MESSAGE_CONFIG message_to_send; thread_result = SimulatorModule_create_message(module, &message_to_send); if (thread_result != 0) { LogError("unable to continue with simulation"); if (message_to_send.sourceProperties != NULL) { Map_Destroy(message_to_send.sourceProperties); } if (message_to_send.source != NULL) { free( (void*)message_to_send.source); } } else { using HrClock = std::chrono::high_resolution_clock; using MicroSeconds = std::chrono::microseconds; long long time_to_wait = module->message_delay * 1000; size_t messages_produced = 0; thread_result = 0; while (module->thread_flag) { std::chrono::time_point<HrClock, MicroSeconds> t1 = std::chrono::time_point_cast<MicroSeconds>(HrClock::now()); auto t1_as_int = t1.time_since_epoch().count(); std::string t1_as_string = std::to_string(t1_as_int); messages_produced++; std::string messages_produced_as_string = std::to_string(messages_produced); if (Map_AddOrUpdate(message_to_send.sourceProperties, "timestamp", t1_as_string.c_str()) != MAP_OK) { LogError("Unable to update timestamp in message"); module->thread_flag = false; thread_result = -__LINE__; break; } else if (Map_AddOrUpdate(message_to_send.sourceProperties, "sequence number", messages_produced_as_string.c_str()) != MAP_OK) { LogError("Unable to update sequence number in message"); module->thread_flag = false; thread_result = -__LINE__; break; } else { MESSAGE_HANDLE next_message = Message_Create(&message_to_send); if (next_message == NULL) { LogError("Unable to create next message"); module->thread_flag = false; thread_result = -__LINE__; break; } else { if (Broker_Publish(module->broker, module, next_message) != BROKER_OK) { LogError("Unable to publish message"); module->thread_flag = false; thread_result = -__LINE__; break; } else { Message_Destroy(next_message); std::chrono::time_point<HrClock, MicroSeconds> t2 = std::chrono::time_point_cast<MicroSeconds>(HrClock::now()); auto time_to_publish = t2.time_since_epoch().count() - t1_as_int; if (time_to_publish < time_to_wait) { unsigned int remaining_time = static_cast<unsigned int>((time_to_wait - time_to_publish)/1000); ThreadAPI_Sleep(remaining_time); } } } } } if (message_to_send.sourceProperties != NULL) { Map_Destroy(message_to_send.sourceProperties); } if (message_to_send.source != NULL) { free((void*)message_to_send.source); } } return thread_result; }
/** * 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; }
/* Codes_SRS_BROKER_17_026: [ N/A - Broker_Publish shall copy source into the beginning of the nanomsg buffer. ] */ BROKER_RESULT Broker_Publish ( BROKER_HANDLE broker, MODULE_HANDLE source, MESSAGE_HANDLE message ) { (void)source; REMOTE_MODULE_HANDLE remote_module = (REMOTE_MODULE_HANDLE)broker; BROKER_RESULT result; /* Codes_SRS_BROKER_13_030: [If broker or message is NULL the function shall return BROKER_INVALIDARG.] */ if (broker == NULL || message == NULL) { result = BROKER_INVALIDARG; LogError("Broker handle and/or message handle is NULL"); } else { // Send message_ to nanomsg int32_t msg_size; int32_t buf_size; /* Codes_SRS_BROKER_17_007: [ Broker_Publish shall clone the message. ] */ MESSAGE_HANDLE msg = Message_Clone(message); /* Codes_SRS_BROKER_17_008: [ Broker_Publish shall serialize the message. ] */ msg_size = Message_ToByteArray(message, NULL, 0); if (msg_size < 0) { /* Codes_SRS_BROKER_13_037: [ This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise. ] */ LogError("unable to serialize a message [%p]", msg); Message_Destroy(msg); result = BROKER_ERROR; } else { /* Codes_SRS_BROKER_17_025: [ Broker_Publish shall allocate a nanomsg buffer the size of the serialized message + sizeof(MODULE_HANDLE). ] */ buf_size = msg_size; void* nn_msg = nn_allocmsg(buf_size, 0); if (nn_msg == NULL) { /* Codes_SRS_BROKER_13_037: [ This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise. ] */ LogError("unable to serialize a message [%p]", msg); result = BROKER_ERROR; } else { unsigned char *nn_msg_bytes = (unsigned char *)nn_msg; /* Codes_SRS_BROKER_17_027: [ Broker_Publish shall serialize the message into the remainder of the nanomsg buffer. ] */ Message_ToByteArray(message, nn_msg_bytes, msg_size); /* Codes_SRS_BROKER_17_010: [ Broker_Publish shall send a message on the publish_socket. ] */ int nbytes = nn_really_send(remote_module->message_socket, &nn_msg, NN_MSG, 0); if (nbytes != buf_size) { /* Codes_SRS_BROKER_13_037: [ This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise. ] */ LogError("unable to send a message [%p]", msg); /* Codes_SRS_BROKER_17_012: [ Broker_Publish shall free the message. ] */ nn_freemsg(nn_msg); result = BROKER_ERROR; } else { result = BROKER_OK; } } /* Codes_SRS_BROKER_17_012: [ Broker_Publish shall free the message. ] */ Message_Destroy(msg); /* Codes_SRS_BROKER_17_011: [ Broker_Publish shall free the serialized message data. ] */ } } /* Codes_SRS_BROKER_13_037: [ This function shall return BROKER_ERROR if an underlying API call to the platform causes an error or BROKER_OK otherwise. ] */ return result; }
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; }
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; }
static int outprocessOutgoingMessagesThread(void * param) { OUTPROCESS_HANDLE_DATA * handleData = (OUTPROCESS_HANDLE_DATA*)param; if (handleData == NULL) { LogError("outprocess send message thread: parameter is NULL"); } else { int should_continue = 1; while (should_continue) { /*Codes_SRS_OUTPROCESS_MODULE_17_053: [ This thread shall ensure thread safety on the module data. ]*/ if (Lock(handleData->message_send_thread.thread_lock) != LOCK_OK) { LogError("unable to Lock"); should_continue = 0; break; } if (handleData->message_send_thread.thread_flag == THREAD_FLAG_STOP) { should_continue = 0; (void)Unlock(handleData->message_send_thread.thread_lock); break; } if (Unlock(handleData->message_send_thread.thread_lock) != LOCK_OK) { should_continue = 0; break; } MESSAGE_HANDLE messageHandle; /*Codes_SRS_OUTPROCESS_MODULE_17_053: [ This thread shall ensure thread safety on the module data. ]*/ if (Lock(handleData->handle_lock) != LOCK_OK) { LogError("unable to Lock"); should_continue = 0; break; } if (MESSAGE_QUEUE_is_empty(handleData->outgoing_messages)) { messageHandle = NULL; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_054: [ This function shall remove the oldest message from the outgoing gateway message queue. ]*/ messageHandle = MESSAGE_QUEUE_pop(handleData->outgoing_messages); if (messageHandle == NULL) { LogError("bad condition: message handle in queue is NULL"); (void)Unlock(handleData->handle_lock); should_continue = 0; break; } } if (Unlock(handleData->handle_lock) != LOCK_OK) { should_continue = 0; break; } /* forward message to remote */ if (messageHandle != NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_023: [ This function shall serialize the message for transmission on the message channel. ]*/ int32_t msg_size = Message_ToByteArray(messageHandle, NULL, 0); if (msg_size < 0) { LogError("unable to serialize outgoing message [%p]", messageHandle); } else { void* result = nn_allocmsg(msg_size, 0); if (result == NULL) { LogError("unable to allocate buffer for outgoing message [%p]", messageHandle); } else { unsigned char *nn_msg_bytes = (unsigned char *)result; Message_ToByteArray(messageHandle, nn_msg_bytes, msg_size); /*Codes_SRS_OUTPROCESS_MODULE_17_024: [ This function shall send the message on the message channel. ]*/ int nbytes = nn_really_send(handleData->message_socket, &result, NN_MSG, 0); if (nbytes != msg_size) { LogError("unable to send buffer to remote for message [%p]", messageHandle); /*Codes_SRS_OUTPROCESS_MODULE_17_025: [ This function shall free any resources created. ]*/ nn_freemsg(result); } } } // We are finally finished with this message /*Codes_SRS_OUTPROCESS_MODULE_17_055: [ This function shall Destroy the message once successfully transmitted. ]*/ Message_Destroy(messageHandle); } ThreadAPI_Sleep(1); } } return 0; }
char *test_Decode_JunkQuery() { char *ok[] = { "d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", }; ok[1]=ok[1]; char *junk[] = { /* Wrong bencode */ "foo", "i0e", "le", "1:x", /* No 'y' */ "d1:ad2:id20:abcdefghij0123456789e1:q4:ping1:t2:aae" /* No 'q' */ "d1:ad2:id20:abcdefghij0123456789e1:t2:aa1:y1:qe", /* Unknown 'q' value */ "d1:ad2:id20:abcdefghij0123456789e1:q3:foo:t2:aa1:y1:qe", /* No 't' */ "d1:ad2:id20:abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:y1:qe", /* No arguments */ "d1:q4:ping1:t2:aa1:y1:qe", "d1:q9:find_node1:t2:aa1:y1:qe", "d1:q9:get_peers1:t2:aa1:y1:qe", "d1:q13:announce_peer1:t2:aa1:y1:qe", /* Bad id */ "d1:ad2:id19:bcdefghij0123456789e1:q4:ping1:t2:aa1:y1:qe", "d1:ad2:id21:+abcdefghij01234567896:target20:mnopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe", "d1:ad2:id0:9:info_hash20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe", "d1:ad2:idi0e9:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", /* find_node target */ "d1:ad2:id20:abcdefghij0123456789e1:q9:find_node1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567896:target19:nopqrstuvwxyz123456e1:q9:find_node1:t2:aa1:y1:qe", /* get_peers info_hash */ "d1:ad2:id20:abcdefghij01234567899:info_h___20:mnopqrstuvwxyz123456e1:q9:get_peers1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash0:e1:q9:get_peers1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hashi0ee1:q9:get_peers1:t2:aa1:y1:qe", /* announce_peer info_hash */ "d1:ad2:id20:abcdefghij01234567899:info_h___0:mnopqrstuvwxyz1234564:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash1:x4:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hashi0e4:porti6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", /* announce_peer port */ "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:po__i6881e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:port4:68815:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti65536e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti18446744073709551616e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti-1e5:token8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", /* announce_peer token */ "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:to___8:aoeusnthe1:q13:announce_peer1:t2:aa1:y1:qe", "d1:ad2:id20:abcdefghij01234567899:info_hash20:mnopqrstuvwxyz1234564:porti6881e5:tokeni0ee1:q13:announce_peer1:t2:aa1:y1:qe", NULL }; int i = 0; while (junk[i]) { Message *result = Message_Decode(junk[i], strlen(junk[i]), NULL); mu_assert(result != NULL, "Message_Decode failed"); mu_assert(result->errors, "Junk decoded without errors"); Message_Destroy(result); i++; } return NULL; }