/* Tear down a connection, can be phase 1 or 2. */ static void ui_teardown(char *cmd) { struct sockaddr_in addr; struct sockaddr_in6 addr6; struct sa *sa; int phase; char name[201]; /* If no phase is given, we default to phase 2. */ phase = 2; if (sscanf(cmd, "t main %200s", name) == 1) phase = 1; else if (sscanf(cmd, "t quick %200s", name) == 1) phase = 2; else if (sscanf(cmd, "t %200s", name) != 1) { log_print("ui_teardown: command \"%s\" malformed", cmd); return; } LOG_DBG((LOG_UI, 10, "ui_teardown: teardown connection \"%s\", " "phase %d", name, phase)); bzero(&addr, sizeof(addr)); bzero(&addr6, sizeof(addr6)); if (inet_pton(AF_INET, name, &addr.sin_addr) == 1) { addr.sin_len = sizeof(addr); addr.sin_family = AF_INET; while ((sa = sa_lookup_by_peer((struct sockaddr *)&addr, SA_LEN((struct sockaddr *)&addr), phase)) != 0) { if (sa->name) connection_teardown(sa->name); sa_delete(sa, 1); } } else if (inet_pton(AF_INET6, name, &addr6.sin6_addr) == 1) { addr6.sin6_len = sizeof(addr6); addr6.sin6_family = AF_INET6; while ((sa = sa_lookup_by_peer((struct sockaddr *)&addr6, SA_LEN((struct sockaddr *)&addr6), phase)) != 0) { if (sa->name) connection_teardown(sa->name); sa_delete(sa, 1); } } else { if (phase == 2) connection_teardown(name); while ((sa = sa_lookup_by_name(name, phase)) != 0) sa_delete(sa, 1); } }
/* Teardown all SAs. */ void sa_teardown_all(void) { int i; struct sa *sa, *next = 0; LOG_DBG((LOG_SA, 70, "sa_teardown_all:")); /* Get Phase 2 SAs. */ for (i = 0; i <= bucket_mask; i++) for (sa = LIST_FIRST(&sa_tab[i]); sa; sa = next) { next = LIST_NEXT(sa, link); if (sa->phase == 2) { /* * Teardown the phase 2 SAs by name, similar * to ui_teardown. */ LOG_DBG((LOG_SA, 70, "sa_teardown_all: tearing down SA %s", sa->name ? sa->name : "<unnamed>")); if (sa->name) connection_teardown(sa->name); sa_delete(sa, 1); } } }
static void Outprocess_Destroy(MODULE_HANDLE moduleHandle) { OUTPROCESS_HANDLE_DATA* handleData = moduleHandle; /*Codes_SRS_OUTPROCESS_MODULE_17_026: [ If module is NULL, this function shall do nothing. ]*/ if (handleData != NULL) { /*tell remote module to stop*/ int32_t messageSize = 0; /*Codes_SRS_OUTPROCESS_MODULE_17_028: [ This function shall construct a Destroy Message. ]*/ void * destroyMessage = construct_destroy_message(handleData, &messageSize); if (destroyMessage != NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_029: [ This function shall send the Destroy Message on the control channel. ]*/ int sendBytes; int retry_count = 0; do { sendBytes = nn_send(handleData->control_socket, &destroyMessage, NN_MSG, NN_DONTWAIT); if (sendBytes != messageSize) { // best effort - it's mostly likely our remote module isn't attached. retry_count++; if (retry_count > 10) { break; } } } while (sendBytes != messageSize); if (sendBytes != messageSize) { /*Codes_SRS_OUTPROCESS_MODULE_17_048: [ There is a possibility the module host process is no longer operational, therefore sending the destroy the Destroy Message shall be a best effort attempt. ]*/ LogError("unable to send destroy control message [%p], continuing with module destroy", destroyMessage); nn_freemsg(destroyMessage); } } else { LogError("unable to create destroy control message, continuing with module destroy"); } /*Codes_SRS_OUTPROCESS_MODULE_17_030: [ This function shall close the message channel socket. ]*/ /*Codes_SRS_OUTPROCESS_MODULE_17_031: [ This function shall close the control channel socket. ]*/ connection_teardown(handleData); /* then stop the threads */ /*Codes_SRS_OUTPROCESS_MODULE_17_032: [ This function shall signal the messaging thread to close. ]*/ shutdown_a_thread(&(handleData->message_receive_thread)); /*Codes_SRS_OUTPROCESS_MODULE_17_049: [ This function shall signal the outgoing gateway message thread to close. ]*/ shutdown_a_thread(&(handleData->message_send_thread)); /*Codes_SRS_OUTPROCESS_MODULE_17_050: [ This function shall signal the control thread to close. ]*/ shutdown_a_thread(&(handleData->control_thread)); shutdown_a_thread(&(handleData->async_create_thread)); /* Free remaining resources */ /*Codes_SRS_OUTPROCESS_MODULE_17_034: [ This function shall release all resources created by this module. ]*/ delete_strings(handleData); (void)Lock_Deinit(handleData->handle_lock); free(handleData); } }
static MODULE_HANDLE Outprocess_Create(BROKER_HANDLE broker, const void* configuration) { OUTPROCESS_HANDLE_DATA * module; if ( (broker == NULL) || (configuration == NULL) ) { /*Codes_SRS_OUTPROCESS_MODULE_17_005: [ If broker or configuration are NULL, this function shall return NULL. ]*/ LogError("invalid arguments for outprcess module. broker=[%p], configuration = [%p]", broker, configuration); module = NULL; } else { OUTPROCESS_MODULE_CONFIG * config = (OUTPROCESS_MODULE_CONFIG*)configuration; /*Codes_SRS_OUTPROCESS_MODULE_17_006: [ This function shall allocate memory for the MODULE_HANDLE. ]*/ module = (OUTPROCESS_HANDLE_DATA*)malloc(sizeof(OUTPROCESS_HANDLE_DATA)); if (module == NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("allocation for module failed."); } else { /*Codes_SRS_OUTPROCESS_MODULE_17_007: [ This function shall intialize a lock for exclusive access to handle data. ]*/ module->handle_lock = Lock_Init(); if (module->handle_lock == NULL) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("unable to intialize module lock"); free(module); module = NULL; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_042: [ This function shall initialize a queue for outgoing gateway messages. ]*/ module->outgoing_messages = MESSAGE_QUEUE_create(); if (module->outgoing_messages == NULL) { LogError("unable to create outgoing message queue"); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { if (connection_setup(module, config) < 0) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("unable to set up connections"); connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { THREAD_CONTROL default_thread = { NULL, NULL, 0 }; module->broker = broker; module->remote_message_wait = config->remote_message_wait; module->message_receive_thread = default_thread; module->message_send_thread = default_thread; module->control_thread = default_thread; module->async_create_thread = default_thread; module->lifecyle_model = config->lifecycle_model; /*Codes_SRS_OUTPROCESS_MODULE_17_041: [ This function shall intitialize a lock for each thread for thread management. ]*/ if ((module->message_receive_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->control_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->async_create_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if ((module->message_send_thread.thread_lock = Lock_Init()) == NULL) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else if (save_strings(module, config) != 0) { connection_teardown(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_014: [ This function shall wait for a Create Response on the control channel. ]*/ if (ThreadAPI_Create(&(module->async_create_thread.thread_handle), outprocessCreate, module) != THREADAPI_OK) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("failed to spawn a thread"); module->async_create_thread.thread_handle = NULL; connection_teardown(module); delete_strings(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } else { int thread_result = -1; if (module->lifecyle_model == OUTPROCESS_LIFECYCLE_SYNC) { if (ThreadAPI_Join(module->async_create_thread.thread_handle, &thread_result) != THREADAPI_OK) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ LogError("Async create thread failed result=[%d]", thread_result); thread_result = -1; } else { /*Codes_SRS_OUTPROCESS_MODULE_17_015: [ This function shall expect a successful result from the Create Response to consider the module creation a success. ]*/ // async thread is done. } module->async_create_thread.thread_handle = NULL; } else { thread_result = 1; } if (thread_result < 0) { /*Codes_SRS_OUTPROCESS_MODULE_17_016: [ If any step in the creation fails, this function shall deallocate all resources and return NULL. ]*/ connection_teardown(module); delete_strings(module); MESSAGE_QUEUE_destroy(module->outgoing_messages); Lock_Deinit(module->async_create_thread.thread_lock); Lock_Deinit(module->control_thread.thread_lock); Lock_Deinit(module->message_receive_thread.thread_lock); Lock_Deinit(module->message_send_thread.thread_lock); Lock_Deinit(module->handle_lock); free(module); module = NULL; } } } } } } } } return module; }