/**@internal * Main execution loop */ static void main_loop(void) { int result; pthread_t tid; s_config *config = config_get_config(); struct timespec wait_time; int msec; request *r; void **params; int* thread_serial_num_p; /* Set the time when nodogsplash started */ if (!started_time) { debug(LOG_INFO, "Setting started_time"); started_time = time(NULL); } else if (started_time < MINIMUM_STARTED_TIME) { debug(LOG_WARNING, "Detected possible clock skew - re-setting started_time"); started_time = time(NULL); } /* If we don't have the Gateway IP address, get it. Exit on failure. */ if (!config->gw_address) { debug(LOG_DEBUG, "Finding IP address of %s", config->gw_interface); if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface); exit(1); } if ((config->gw_mac = get_iface_mac(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get MAC address information of %s, exiting...", config->gw_interface); exit(1); } debug(LOG_NOTICE, "Detected gateway %s at %s (%s)", config->gw_interface, config->gw_address, config->gw_mac); } /* Initializes the web server */ if ((webserver = httpdCreate(config->gw_address, config->gw_port)) == NULL) { debug(LOG_ERR, "Could not create web server: %s", strerror(errno)); exit(1); } debug(LOG_NOTICE, "Created web server on %s:%d", config->gw_address, config->gw_port); /* Set web root for server */ debug(LOG_DEBUG, "Setting web root: %s",config->webroot); httpdSetFileBase(webserver,config->webroot); /* Add images files to server: any file in config->imagesdir can be served */ debug(LOG_DEBUG, "Setting images subdir: %s",config->imagesdir); httpdAddWildcardContent(webserver,config->imagesdir,NULL,config->imagesdir); /* Add pages files to server: any file in config->pagesdir can be served */ debug(LOG_DEBUG, "Setting pages subdir: %s",config->pagesdir); httpdAddWildcardContent(webserver,config->pagesdir,NULL,config->pagesdir); debug(LOG_DEBUG, "Registering callbacks to web server"); httpdAddCContent(webserver, "/", "", 0, NULL, http_nodogsplash_callback_index); httpdAddCWildcardContent(webserver, config->authdir, NULL, http_nodogsplash_callback_auth); httpdAddCWildcardContent(webserver, config->denydir, NULL, http_nodogsplash_callback_deny); httpdAddC404Content(webserver, http_nodogsplash_callback_404); /* Reset the firewall (cleans it, in case we are restarting after nodogsplash crash) */ fw_destroy(); /* Then initialize it */ debug(LOG_NOTICE, "Initializing firewall rules"); if( fw_init() != 0 ) { debug(LOG_ERR, "Error initializing firewall rules! Cleaning up"); fw_destroy(); debug(LOG_ERR, "Exiting because of error initializing firewall rules"); exit(1); } /* Start client statistics and timeout clean-up thread */ result = pthread_create(&tid_client_check, NULL, (void *)thread_client_timeout_check, NULL); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_client_timeout_check - exiting"); termination_handler(0); } pthread_detach(tid_client_check); /* Start control thread */ result = pthread_create(&tid, NULL, (void *)thread_ndsctl, (void *)safe_strdup(config->ndsctl_sock)); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_ndsctl - exiting"); termination_handler(0); } pthread_detach(tid); /* * Enter the httpd request handling loop */ debug(LOG_NOTICE, "Waiting for connections"); while(1) { r = httpdGetConnection(webserver, NULL); /* We can't convert this to a switch because there might be * values that are not -1, 0 or 1. */ if (webserver->lastError == -1) { /* Interrupted system call */ continue; /* continue loop from the top */ } else if (webserver->lastError < -1) { /* * FIXME * An error occurred - should we abort? * reboot the device ? */ debug(LOG_ERR, "FATAL: httpdGetConnection returned unexpected value %d, exiting.", webserver->lastError); termination_handler(0); } else if (r != NULL) { /* We got a connection */ handle_http_request(webserver, r); } else { /* webserver->lastError should be 2 */ /* XXX We failed an ACL.... No handling because * we don't set any... */ } } /* never reached */ }
/**@internal * Main execution loop */ static void main_loop(void) { int result; pthread_t tid; s_config *config = config_get_config(); struct timespec wait_time; int msec; request *r; void **params; FILE *fh; int* thread_serial_num_p; /* Set the time when nodogsplash started */ if (!started_time) { debug(LOG_INFO, "Setting started_time"); started_time = time(NULL); } else if (started_time < MINIMUM_STARTED_TIME) { debug(LOG_WARNING, "Detected possible clock skew - re-setting started_time"); started_time = time(NULL); } /* If we don't have the Gateway IP address, get it. Exit on failure. */ if (!config->gw_address) { debug(LOG_DEBUG, "Finding IP address of %s", config->gw_interface); if ((config->gw_address = get_iface_ip(config->gw_interface)) == NULL) { debug(LOG_ERR, "Could not get IP address information of %s, exiting...", config->gw_interface); exit(1); } debug(LOG_NOTICE, "Detected gateway %s at %s", config->gw_interface, config->gw_address); } /* Initializes the web server */ if ((webserver = httpdCreate(config->gw_address, config->gw_port)) == NULL) { debug(LOG_ERR, "Could not create web server: %s", strerror(errno)); exit(1); } debug(LOG_NOTICE, "Created web server on %s:%d", config->gw_address, config->gw_port); /* Set web root for server */ debug(LOG_DEBUG, "Setting web root: %s",config->webroot); httpdSetFileBase(webserver,config->webroot); /* Add images files to server: any file in config->imagesdir can be served */ debug(LOG_DEBUG, "Setting images subdir: %s",config->imagesdir); httpdAddWildcardContent(webserver,config->imagesdir,NULL,config->imagesdir); /* Add pages files to server: any file in config->pagesdir can be served */ debug(LOG_DEBUG, "Setting pages subdir: %s",config->pagesdir); httpdAddWildcardContent(webserver,config->pagesdir,NULL,config->pagesdir); debug(LOG_DEBUG, "Registering callbacks to web server"); httpdAddCContent(webserver, "/", "", 0, NULL, http_nodogsplash_callback_index); httpdAddCWildcardContent(webserver, config->authdir, NULL, http_nodogsplash_callback_auth); httpdAddCWildcardContent(webserver, config->denydir, NULL, http_nodogsplash_callback_deny); httpdAddC404Content(webserver, http_nodogsplash_callback_404); /* Reset the firewall (cleans it, in case we are restarting after nodogsplash crash) */ fw_destroy(); /* Then initialize it */ debug(LOG_NOTICE, "Initializing firewall rules"); if( fw_init() != 0 ) { debug(LOG_ERR, "Error initializing firewall rules! Cleaning up"); fw_destroy(); debug(LOG_ERR, "Exiting because of error initializing firewall rules"); exit(1); } /* Start client statistics and timeout clean-up thread */ result = pthread_create(&tid_client_check, NULL, (void *)thread_client_timeout_check, NULL); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_client_timeout_check - exiting"); termination_handler(0); } pthread_detach(tid_client_check); /* Start control thread */ result = pthread_create(&tid, NULL, (void *)thread_ndsctl, (void *)safe_strdup(config->ndsctl_sock)); if (result != 0) { debug(LOG_ERR, "FATAL: Failed to create thread_ndsctl - exiting"); termination_handler(0); } pthread_detach(tid); /* * Enter the httpd request handling loop */ debug(LOG_NOTICE, "Waiting for connections"); created_httpd_threads = 0; current_httpd_threads = 0; while(1) { r = httpdGetConnection(webserver, NULL); /* We can't convert this to a switch because there might be * values that are not -1, 0 or 1. */ if (webserver->lastError == -1) { /* Interrupted system call */ continue; /* continue loop from the top */ } else if (webserver->lastError < -1) { /* * FIXME * An error occurred - should we abort? * reboot the device ? */ debug(LOG_ERR, "FATAL: httpdGetConnection returned unexpected value %d, exiting.", webserver->lastError); termination_handler(0); } else if (r != NULL) { /* * We got a connection * * We create another thread to handle the request, * possibly sleeping first if there are too many already */ debug(LOG_DEBUG,"%d current httpd threads.", current_httpd_threads); if(config->decongest_httpd_threads && current_httpd_threads >= config->httpd_thread_threshold) { msec = current_httpd_threads * config->httpd_thread_delay_ms; wait_time.tv_sec = msec / 1000; wait_time.tv_nsec = (msec % 1000) * 1000000; debug(LOG_INFO, "Httpd thread creation delayed %ld sec %ld nanosec for congestion.", wait_time.tv_sec, wait_time.tv_nsec); nanosleep(&wait_time,NULL); } thread_serial_num_p = (int*) malloc(sizeof(int)); /* thread_httpd() must free */ *thread_serial_num_p = created_httpd_threads; debug(LOG_INFO, "Creating httpd request thread %d for %s", *thread_serial_num_p, r->clientAddr); /* The void**'s are a simulation of the normal C * function calling sequence. */ params = safe_malloc(3 * sizeof(void *)); /* thread_httpd() must free */ *params = webserver; *(params + 1) = r; *(params + 2) = thread_serial_num_p; created_httpd_threads++; result = pthread_create(&tid, NULL, (void *)thread_httpd, (void *)params); if (result != 0) { debug(LOG_ERR, "FATAL: pthread_create failed to create httpd request thread - exiting..."); termination_handler(0); } pthread_detach(tid); } else { /* webserver->lastError should be 2 */ /* XXX We failed an ACL.... No handling because * we don't set any... */ } } /* never reached */ }