/* Starts listening for incoming events from the the object's clients. * This function BLOCKS until either 'ClientListener_stop()' is called * or all the clients have disconnected and there are no more clients in * the listener's client list. */ alib_error ClientListener_start(ClientListener* listener) { if(!listener)return(ALIB_BAD_ARG); int err; /* Stop the listener if it is running. */ if((listener->flag_pole & THREAD_IS_RUNNING) || listener->ep.efd > -1) ClientListener_stop(listener); /* Initialize the epoll. */ err = init_epoll_tsafe(listener); if(err) return(err); /* Add the clients to the epoll. */ err = add_clients_to_epoll_tsafe(listener); if(err)goto f_error; /* Start the listener. */ err = listen_loop(listener); /* Must close the epoll. */ close_epoll_tsafe(listener); return(err); f_error: ClientListener_stop(listener); return(err); }
/* * Creates a RAW Socket and starts the listen loop. This function will not return. * * @param interface: Interface to listen on, if NULL: all availible interfaces will be used. */ void init_raw_socket(char* interface ) { int rawsock = 0; pinfo("Try to register a RAW socket (does need root rights or CAP_NET_RAW capability)" ); rawsock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // ETH_P_802_3 would make more sense, but does not work global_signal_handler_rawsock = rawsock; if( rawsock < 0 ) { perror("ERROR: socket(AF_PACKET, SOCK_RAW...) failed"); exit(1); } if( interface != NULL && setsockopt(rawsock, SOL_SOCKET, SO_BINDTODEVICE, interface, strlen(interface)) < 0 ) { perror("ERROR: setsockopt(rawsock, SOL_SOCKET, SO_BINDTODEVICE...) failed"); if( rawsock > 0 ) close(rawsock); exit(1); } listen_loop(rawsock); // never reached, only for debug if( rawsock > 0 ) close(rawsock); }
/* Function used to start listening to client events on a separate * thread. */ static void* threaded_run(void* v_listener) { ClientListener* listener = (ClientListener*)v_listener; flag_raise(&listener->flag_pole, THREAD_IS_RUNNING); flag_lower(&listener->flag_pole, THREAD_STOP); listen_loop(listener); flag_lower(&listener->flag_pole, THREAD_IS_RUNNING); /* Epoll is no longer in use, we should close * the file descriptor. */ close_epoll_tsafe(listener); return(NULL); }
void KDA_Init_conn() { NOTE_F; // Add self to world_ranks... world_ranks = hashtable_create(mpi_size); int* heap_mpi_rank = malloc(sizeof(int)); *heap_mpi_rank = mpi_size; hashtable_add(world_ranks, xheap(id), heap_mpi_rank); MPIRPC_Comm_add(MPI_COMM_WORLD); MPIRPC_Register("get_id", handle_get_id); MPIRPC_Register("get_rank", handle_get_rank); sleep(mpi_rank * 3); if (mpi_rank > 0) { int other_rank = rand_lt(mpi_rank); MPIRPC_Node node; MPIRPC_Node_make(MPI_COMM_WORLD, other_rank, &node); SHOW_I(other_rank); char* result = MPIRPC_Block(node, "get_id", NULL); KDA_ID other_id; sscanf(result, "%X", &other_id); free(result); KDA_Neighbor neighbor; KDA_Neighbor_make_id(other_id, node, &neighbor); neighbor_add(&neighbor); MPIRPC_Node dummy = {0}; KDA_Join(dummy, &neighbor); } /* int client = cmpi_mode_first_client(mpi_rank, mpi_size, kda_nodes); SHOW_I(client); int msg = -2; // MPI_Send(&msg, 1, MPI_INT, client, 0, MPI_COMM_WORLD); */ listen_loop(); }
void listen_loop(int do_init) { struct client_struct* new_client; struct np_sock npsock = {.count = 0}; int ret; struct timespec ts; #ifdef NP_SSH ssh_bind sshbind = NULL; #endif #ifdef NP_TLS SSL_CTX* tlsctx = NULL; #endif /* Init */ if (do_init) { #ifdef NP_SSH np_ssh_init(); #endif #ifdef NP_TLS np_tls_init(); #endif if ((ret = pthread_create(&netopeer_state.data_tid, NULL, data_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } if ((ret = pthread_create(&netopeer_state.netconf_rpc_tid, NULL, netconf_rpc_thread, NULL)) != 0) { nc_verb_error("%s: failed to create a thread (%s)", __func__, strerror(ret)); return; } } /* Main accept loop */ do { new_client = NULL; /* Binds change check */ if (netopeer_options.binds_change_flag) { /* BINDS LOCK */ pthread_mutex_lock(&netopeer_options.binds_lock); sock_cleanup(&npsock); sock_listen(netopeer_options.binds, &npsock); netopeer_options.binds_change_flag = 0; /* BINDS UNLOCK */ pthread_mutex_unlock(&netopeer_options.binds_lock); if (npsock.count == 0) { nc_verb_warning("Server is not listening on any address!"); } } #ifdef NP_SSH sshbind = np_ssh_server_id_check(sshbind); #endif #ifdef NP_TLS tlsctx = np_tls_server_id_check(tlsctx); #endif #ifndef DISABLE_CALLHOME /* Callhome client check */ if (callhome_client != NULL) { /* CALLHOME LOCK */ pthread_mutex_lock(&callhome_lock); new_client = callhome_client; callhome_client = NULL; /* CALLHOME UNLOCK */ pthread_mutex_unlock(&callhome_lock); } #endif /* Listen client check */ if (new_client == NULL) { new_client = sock_accept(&npsock); } /* New client full structure creation */ if (new_client != NULL) { /* Maximum number of sessions check */ if (netopeer_options.max_sessions > 0) { ret = 0; #ifdef NP_SSH ret += np_ssh_session_count(); #endif #ifdef NP_TLS ret += np_tls_session_count(); #endif if (ret >= netopeer_options.max_sessions) { nc_verb_error("Maximum number of sessions reached, droppping the new client."); new_client->to_free = 1; switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: client_free_ssh((struct client_struct_ssh*)new_client); break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: client_free_tls((struct client_struct_tls*)new_client); break; #endif default: nc_verb_error("%s: internal error (%s:%d)", __func__, __FILE__, __LINE__); } free(new_client); /* sleep to prevent clients from immediate connection retry */ usleep(netopeer_options.response_time*1000); continue; } } switch (new_client->transport) { #ifdef NP_SSH case NC_TRANSPORT_SSH: ret = np_ssh_create_client((struct client_struct_ssh*)new_client, sshbind); if (ret != 0) { new_client->to_free = 1; client_free_ssh((struct client_struct_ssh*)new_client); } break; #endif #ifdef NP_TLS case NC_TRANSPORT_TLS: ret = np_tls_create_client((struct client_struct_tls*)new_client, tlsctx); if (ret != 0) { new_client->to_free = 1; client_free_tls((struct client_struct_tls*)new_client); } break; #endif default: nc_verb_error("Client with an unknown transport protocol, dropping it."); new_client->to_free = 1; ret = 1; } /* client is not valid, some error occured */ if (ret != 0) { free(new_client); continue; } /* add the client into the global clients structure */ /* GLOBAL WRITE LOCK */ pthread_rwlock_wrlock(&netopeer_state.global_lock); client_append(&netopeer_state.clients, new_client); /* GLOBAL WRITE UNLOCK */ pthread_rwlock_unlock(&netopeer_state.global_lock); } } while (!quit && !restart_soft); /* Cleanup */ sock_cleanup(&npsock); #ifdef NP_SSH ssh_bind_free(sshbind); #endif #ifdef NP_TLS SSL_CTX_free(tlsctx); #endif if (!restart_soft) { if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { nc_verb_warning("%s: failed to get time (%s)", strerror(errno)); } ts.tv_sec += THREAD_JOIN_QUIT_TIMEOUT; /* wait for all the clients to exit nicely themselves */ if ((ret = pthread_timedjoin_np(netopeer_state.netconf_rpc_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the netconf RPC thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.netconf_rpc_tid); } } if ((ret = pthread_timedjoin_np(netopeer_state.data_tid, NULL, &ts)) != 0) { nc_verb_warning("%s: failed to join the SSH data thread (%s)", __func__, strerror(ret)); if (ret == ETIMEDOUT) { pthread_cancel(netopeer_state.data_tid); } } #ifdef NP_SSH np_ssh_cleanup(); #endif #ifdef NP_TLS np_tls_cleanup(); #endif } } int main(int argc, char** argv) { struct sigaction action; sigset_t block_mask; char *aux_string = NULL, path[PATH_MAX]; int next_option; int daemonize = 0, len; int listen_init = 1; struct np_module* netopeer_module = NULL, *server_module = NULL; /* initialize message system and set verbose and debug variables */ if ((aux_string = getenv(ENVIRONMENT_VERBOSE)) == NULL) { netopeer_options.verbose = NC_VERB_ERROR; } else { netopeer_options.verbose = atoi(aux_string); } aux_string = NULL; /* for sure to avoid unwanted changes in environment */ /* parse given options */ while ((next_option = getopt(argc, argv, OPTSTRING)) != -1) { switch (next_option) { case 'd': daemonize = 1; break; case 'h': print_usage(argv[0]); break; case 'v': netopeer_options.verbose = atoi(optarg); break; case 'V': print_version(argv[0]); break; default: print_usage(argv[0]); break; } } /* set signal handler */ sigfillset (&block_mask); action.sa_handler = signal_handler; action.sa_mask = block_mask; action.sa_flags = 0; sigaction(SIGINT, &action, NULL); sigaction(SIGQUIT, &action, NULL); sigaction(SIGABRT, &action, NULL); sigaction(SIGTERM, &action, NULL); sigaction(SIGHUP, &action, NULL); nc_callback_print(clb_print); /* normalize value if not from the enum */ if (netopeer_options.verbose > NC_VERB_DEBUG) { netopeer_options.verbose = NC_VERB_DEBUG; } nc_verbosity(netopeer_options.verbose); /* go to the background as a daemon */ if (daemonize == 1) { if (daemon(0, 0) != 0) { nc_verb_error("Going to background failed (%s)", strerror(errno)); return EXIT_FAILURE; } openlog("netopeer-server", LOG_PID, LOG_DAEMON); } else { openlog("netopeer-server", LOG_PID|LOG_PERROR, LOG_DAEMON); } /* make sure we were executed by root */ if (geteuid() != 0) { nc_verb_error("Failed to start, must have root privileges."); return EXIT_FAILURE; } /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION /* initialize library including internal datastores and maybee something more */ if (nc_init(NC_INIT_ALL | NC_INIT_MULTILAYER) < 0) { nc_verb_error("Library initialization failed."); return EXIT_FAILURE; } server_start = 1; restart: /* start NETCONF server module */ if ((server_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary NETCONF server plugin failed!"); return EXIT_FAILURE; } server_module->name = strdup(NCSERVER_MODULE_NAME); if (module_enable(server_module, 0)) { nc_verb_error("Starting necessary NETCONF server plugin failed!"); free(server_module->name); free(server_module); return EXIT_FAILURE; } /* start netopeer device module - it will start all modules that are * in its configuration and in server configuration */ if ((netopeer_module = calloc(1, sizeof(struct np_module))) == NULL) { nc_verb_error("Creating necessary Netopeer plugin failed!"); module_disable(server_module, 1); return EXIT_FAILURE; } netopeer_module->name = strdup(NETOPEER_MODULE_NAME); if (module_enable(netopeer_module, 0)) { nc_verb_error("Starting necessary Netopeer plugin failed!"); module_disable(server_module, 1); free(netopeer_module->name); free(netopeer_module); return EXIT_FAILURE; } server_start = 0; nc_verb_verbose("Netopeer server successfully initialized."); listen_loop(listen_init); /* unload Netopeer module -> unload all modules */ module_disable(server_module, 1); module_disable(netopeer_module, 1); /* main cleanup */ if (!restart_soft) { /* close libnetconf only when shutting down or hard restarting the server */ nc_close(); } if (restart_soft) { nc_verb_verbose("Server is going to soft restart."); restart_soft = 0; listen_init = 0; goto restart; } else if (restart_hard) { nc_verb_verbose("Server is going to hard restart."); len = readlink("/proc/self/exe", path, PATH_MAX); path[len] = 0; xmlCleanupParser(); execv(path, argv); } /* *Free the global variables that may *have been allocated by the parser. */ xmlCleanupParser(); return EXIT_SUCCESS; }