void connection_accept_loop(void) { connection_t *con; _build_pool(); while (global.running == ICE_RUNNING) { if (global . schedule_config_reread) { /* reread config file */ INFO0("Scheduling config reread ..."); connection_inject_event(EVENT_CONFIG_READ, NULL); global . schedule_config_reread = 0; } con = _accept_connection(); if (con) { _add_connection(con); } } /* Give all the other threads notification to shut down */ thread_cond_broadcast(&global.shutdown_cond); _destroy_pool(); /* wait for all the sources to shutdown */ thread_rwlock_wlock(&_source_shutdown_rwlock); thread_rwlock_unlock(&_source_shutdown_rwlock); }
void connection_inject_event(int eventnum, void *event_data) { connection_t *con = calloc(1, sizeof(connection_t)); con->event_number = eventnum; con->event = event_data; _add_connection(con); }
static void *_connection_thread (void *arg) { connection_queue_t *node; int err; WARN("Launched connection thread"); while (_connection_running) { /* XXX(xaiki): this needs to wait on a fd, so we don't kill polar bears */ node = _get_connection(); INFO("got node"); if (!node) { continue; } err = _connection_process (node); if (err > 0) { free(node); continue; } switch (-err) { case EAGAIN: /* put it again at the end of the queue */ _add_connection (node); break; case EINPROGRESS: /* already handled */ free(node); break; default: ERROR ("droping node (%p, client => %p), error = %d", node, node->client, err); _connection_node_destroy (node); break; } } while (_con_queue) { node = _get_connection(); _connection_node_destroy (node); } INFO0 ("Connection thread shutdown complete"); return NULL; }
void connection_accept_loop (void) { connection_queue_t *node; connection_t *con; ice_config_t *config; int duration = 3000; int timeout = 0; config = config_get_config (); get_ssl_certificate (config); timeout = config->header_timeout; config_release_config (); while (global.running == ICE_RUNNING) { con = _accept_connection (duration); if (!con) { duration = 30000; /* use longer timeouts when nothing waiting */ continue; } con->con_timeout = time(NULL) + timeout; /* add connection async to the connection queue, then the * connection loop will do all the dirty work */ node =_connection_node_new (con); _add_connection (node); duration = 3000; } /* Give all the other threads notification to shut down */ thread_cond_broadcast(&global.shutdown_cond); /* wait for all the sources to shutdown */ thread_rwlock_wlock(&_source_shutdown_rwlock); thread_rwlock_unlock(&_source_shutdown_rwlock); }
/* run along queue checking for any data that has come in or a timeout */ static void process_request_queue (void) { client_queue_t **node_ref = (client_queue_t **)&_req_queue; ice_config_t *config = config_get_config (); int timeout = config->header_timeout; config_release_config(); while (*node_ref) { client_queue_t *node = *node_ref; client_t *client = node->client; int len = PER_CLIENT_REFBUF_SIZE - 1 - node->offset; char *buf = client->refbuf->data + node->offset; if (len > 0) { if (client->con->con_time + timeout <= time(NULL)) len = 0; else len = client_read_bytes (client, buf, len); } if (len > 0) { int pass_it = 1; char *ptr; /* handle \n, \r\n and nsvcap which for some strange reason has * EOL as \r\r\n */ node->offset += len; client->refbuf->data [node->offset] = '\000'; do { if (node->shoutcast == 1) { /* password line */ if (strstr (client->refbuf->data, "\r\r\n") != NULL) break; if (strstr (client->refbuf->data, "\r\n") != NULL) break; if (strstr (client->refbuf->data, "\n") != NULL) break; } /* stream_offset refers to the start of any data sent after the * http style headers, we don't want to lose those */ ptr = strstr (client->refbuf->data, "\r\r\n\r\r\n"); if (ptr) { node->stream_offset = (ptr+6) - client->refbuf->data; break; } ptr = strstr (client->refbuf->data, "\r\n\r\n"); if (ptr) { node->stream_offset = (ptr+4) - client->refbuf->data; break; } ptr = strstr (client->refbuf->data, "\n\n"); if (ptr) { node->stream_offset = (ptr+2) - client->refbuf->data; break; } pass_it = 0; } while (0); if (pass_it) { if ((client_queue_t **)_req_queue_tail == &(node->next)) _req_queue_tail = (volatile client_queue_t **)node_ref; *node_ref = node->next; node->next = NULL; _add_connection (node); continue; } } else { if (len == 0 || client->con->error) { if ((client_queue_t **)_req_queue_tail == &node->next) _req_queue_tail = (volatile client_queue_t **)node_ref; *node_ref = node->next; client_destroy (client); free (node); continue; } } node_ref = &node->next; } _handle_connection(); }