void Server_queue_cleanup() { if(darray_end(SERVER_QUEUE) < SERVER_ACTIVE) { // skip it, not enough to care about return; } // pop the last one off to make sure it's never deleted Server *cur_srv = darray_pop(SERVER_QUEUE); uint32_t too_old = time(NULL) - SERVER_TTL; int i = 0; // TODO: kind of a dumb way to do this since it reorders the list // go through all but the max we want to keep for(i = 0; i < darray_end(SERVER_QUEUE) - SERVER_ACTIVE; i++) { Server *srv = darray_get(SERVER_QUEUE, i); if(srv->created_on < too_old) { Server *replace = darray_pop(SERVER_QUEUE); darray_set(SERVER_QUEUE, i, replace); srv->listen_fd = -1; // don't close it Server_destroy(srv); } } // put the sacred server back on the end darray_push(SERVER_QUEUE, cur_srv); return; }
static inline int Server_copy_active_handlers(Server *srv, Server *copy_from) { int i = 0; for(i = 0; i < darray_end(copy_from->handlers); i++) { Handler *from = darray_get(copy_from->handlers, i); int j = 0; for(j = 0; j < darray_end(srv->handlers); j++) { Handler *to = darray_get(srv->handlers, j); if(same_handler(from, to)) { debug("Swapping %p original for %p replacement", to, from); RouteUpdater update = {.original = to, .replacement = from}; tst_traverse(srv->hosts->routes, update_host_routes, &update); darray_set(srv->handlers, j, from); // swap them around so that the darrays stay full darray_set(copy_from->handlers, i, to); to->running = 0; break; } } } return 0; }
int DB_valid_schema(tns_value_t *res, int row, int ncols, ...) { va_list argp; va_start(argp, ncols); int i = 0; check(tns_get_type(res) == tns_tag_list, "Invalid result set, must be a list."); int rows = darray_end(res->value.list); check(rows != -1, "Result isn't in a table format."); check(row < rows, "Row is past end of result set: %d > %d", row, rows); // get the row they ask for tns_value_t *row_data = darray_get(res->value.list, row); // make sure it's got the right number of columns check(tns_get_type(row_data) == tns_tag_list, "Invalid row %d, must be a list.", row); int cols = darray_end(row_data->value.list); check(cols == ncols, "Expected %d columns, but result set has %d.", cols, ncols); for(i = 0; i < ncols; i++) { tns_type_tag expecting = va_arg(argp, tns_type_tag); tns_value_t *cell = DB_get(res, row, i); check(tns_get_type(cell) == expecting, "Row %d, Column %d has wrong type.", row, i); } va_end(argp); return 1; error: va_end(argp); return 0; }
void *darray_pop(darray_t *array) { check(array->end - 1 > 0, "Attempt to pop from empty array."); void *el = darray_remove(array, array->end - 1); array->end--; if(darray_end(array) > (int)array->expand_rate && darray_end(array) % array->expand_rate) { darray_contract(array); } return el; error: return NULL; }
static inline void handler_process_extended_request(int fd, Connection *conn, bstring payload) { char *x; tns_value_t *data = NULL; darray_t *l = NULL; data = tns_parse(bdata(payload),blength(payload),&x); check((x-bdata(payload))==blength(payload), "Invalid extended response: extra data after tnetstring."); check(data->type==tns_tag_list, "Invalid extended response: not a list."); l = data->value.list; check(darray_end(l)==2, "Invalid extended response: odd number of elements in list."); tns_value_t *key=darray_get(l,0); check(key->type==tns_tag_string, "Invalid extended response: key is not a string"); check(key->value.string != NULL,, "Invalid extended response: key is NULL"); if(!bstrcmp(key->value.string, &XREQ_CTL)) { check (0 == handler_process_control_request(conn, data), "Control request processing returned non-zero: %s", bdata(key->value.string)); } else { check (0 == dispatch_extended_request(conn, key->value.string, data), "Extended request dispatch returned non-zero: %s",bdata(key->value.string)); } return; error: tns_value_destroy(data); Register_disconnect(fd); // return ignored return; }
static int simple_set_session( ssl_context *ssl ) { time_t t = THE_CURRENT_TIME_IS; int i = 0; ssl_session *cur = NULL; int make_new = 1; check(setup_ssl_session_cache() == 0, "Failed to initialize SSL session cache."); for(i = 0; i < darray_end(SSL_SESSION_CACHE); i++) { cur = darray_get(SSL_SESSION_CACHE, i); if( ssl->timeout != 0 && t - cur->start > ssl->timeout ) { make_new = 0; break; /* expired, reuse this slot */ } if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 ) { make_new = 0; break; /* client reconnected */ } } if(make_new) { cur = (ssl_session *) darray_new(SSL_SESSION_CACHE); check_mem(cur); darray_push(SSL_SESSION_CACHE, cur); } *cur = *ssl->session; return 0; error: return 1; }
static int simple_get_session( ssl_context *ssl ) { time_t t = THE_CURRENT_TIME_IS; int i = 0; check(setup_ssl_session_cache() == 0, "Failed to initialize SSL session cache."); if( ssl->resume == 0 ) return 1; ssl_session *cur = NULL; for(i = 0; i < darray_end(SSL_SESSION_CACHE); i++) { cur = darray_get(SSL_SESSION_CACHE, i); if( ssl->timeout != 0 && t - cur->start > ssl->timeout ) { continue; } if( ssl->session->ciphersuite != cur->ciphersuite || ssl->session->length != cur->length ) { continue; } if( memcmp( ssl->session->id, cur->id, cur->length ) != 0 ) { continue; } // TODO: odd, why 48? this is from polarssl memcpy( ssl->session->master, cur->master, 48 ); return 0; } error: // fallthrough return 1; }
int Server_start_handlers(Server *srv, Server *copy_from) { int i = 0; int rc = 0; if(copy_from != NULL) { rc = Server_copy_active_handlers(srv, copy_from); check(rc != -1, "Failed to copy old handlers to new server config."); } for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); check(handler != NULL, "Invalid handler, can't be NULL."); if(!handler->running) { log_info("LOADING Handler %s", bdata(handler->send_spec)); rc = taskcreate(Handler_task, handler, HANDLER_STACK); check(rc != -1, "Failed to start handler task."); handler->running = 1; } } return 0; error: return -1; }
int Server_stop_handlers(Server *srv) { int i = 0; for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); check(handler != NULL, "Invalid handler, can't be NULL."); if(handler->running) { log_info("STOPPING HANDLER %s", bdata(handler->send_spec)); if(handler->task != NULL) { tasksignal(handler->task, SIGINT); handler->running = 0; taskdelay(1); } } if(handler->recv_socket) zmq_close(handler->recv_socket); if(handler->send_socket) zmq_close(handler->send_socket); handler->recv_socket = NULL; handler->send_socket = NULL; } return 0; error: return -1; }
/** * Gets the tns_value_t at this result's row/col point, * or NULL (which will be tns_get_type == tns_tag_invalid) * if that row isn't possible. */ tns_value_t *DB_get(tns_value_t *res, int row, int col) { check(tns_get_type(res) == tns_tag_list, "Result should be a list."); check(row < darray_end(res->value.list), "Row %d past end of result set length: %d", row, darray_end(res->value.list)); tns_value_t *r = darray_get(res->value.list, row); check(tns_get_type(r) == tns_tag_list, "Row %d should be a list.", row); check(col < darray_end(r->value.list), "Column %d past end of result set length: %d", col, darray_end(r->value.list)); return darray_get(r->value.list, col); error: return NULL; }
int Command_access_logs(Command *cmd) { bstring log_filename = option(cmd, "log", "logs/access.log"); check(log_filename, "Invalid log file given."); FILE *log_file = fopen(bdata(log_filename), "r"); check(log_file != NULL, "Failed to open log file: %s", bdata(log_filename)); int line_number = 0; bstring line; while ((line = bgets((bNgetc) fgetc, log_file, '\n')) != NULL) { line_number++; tns_value_t *log_item = tns_parse(bdata(line), blength(line), NULL); if (log_item == NULL || tns_get_type(log_item) != tns_tag_list || darray_end(log_item->value.list) < 9 ) { log_warn("Malformed log line: %d.", line_number); continue; } darray_t *entries = log_item->value.list; bstring hostname = darray_get_as(entries, 0, string); bstring remote_addr = darray_get_as(entries, 1, string); long remote_port = darray_get_as(entries, 2, number); long timestamp = darray_get_as(entries, 3, number); bstring request_method = darray_get_as(entries, 4, string); bstring request_path = darray_get_as(entries, 5, string); bstring version = darray_get_as(entries, 6, string); long status = darray_get_as(entries, 7, number); long size = darray_get_as(entries, 8, number); printf("[%ld] %s:%ld %s \"%s %s %s\" %ld %ld\n", timestamp, bdata(remote_addr), remote_port, bdata(hostname), bdata(request_method), bdata(request_path), bdata(version), status, size); tns_value_destroy(log_item); } return 0; error: return -1; }
static inline void Server_destroy_handlers(Server *srv) { int i = 0; for(i = 0; i < darray_end(srv->handlers); i++) { Handler *handler = darray_get(srv->handlers, i); Handler_destroy(handler); } darray_destroy(srv->handlers); }
int darray_push(darray_t *array, void *el) { array->contents[array->end] = el; array->end++; if(darray_end(array) >= darray_max(array)) { return darray_expand(array); } else { return 0; } }
static inline int hashmap_get_node(Hashmap *map, uint32_t hash, DArray *bucket, void *key) { int i = 0; for (i = 0; i < darray_end(bucket); i += 1) { debug("TRY: %d", i); HashmapNode *node = darray_get(bucket, i); if (node->hash == hash && map->compare(node->key, key) == 0) { return i; } } return -1; }
/** * Used to iterate through a result set using rows by columns. * It returns the number of rows, or -1 if this result set isn't * valid (like it's not a table form). It sets the *cols as an * out parameter for the number of cols that each row should have. */ int DB_counts(tns_value_t *res, int *cols) { int rows = 0; if(tns_get_type(res) == tns_tag_null) { *cols = 0; } else { check(tns_get_type(res) == tns_tag_list, "Result should get a list."); rows = darray_end(res->value.list); if(rows) { tns_value_t *first_row = darray_get(res->value.list, 0); check(tns_get_type(first_row) == tns_tag_list, "Wrong column type, should be list."); *cols = darray_end(first_row->value.list); } else { *cols = 0; } } return rows; error: return -1; }
int Server_queue_destroy() { int i = 0; Server *srv = NULL; for(i = 0; i < darray_end(SERVER_QUEUE); i++) { srv = darray_get(SERVER_QUEUE, i); check(srv != NULL, "Got a NULL value from the server queue."); Server_destroy(srv); } darray_destroy(SERVER_QUEUE); return 0; error: return -1; }
int Filter_run(StateEvent next, Connection *conn) { int i = 0; StateEvent res = next; check(REGISTERED_FILTERS != NULL, "No filters loaded yet, don't call this."); darray_t *filters = Filter_lookup(next); if(filters != NULL) { for(i = 0; i < darray_end(filters) && res == next; i++) { Filter *filter = darray_get(filters, i); check(filter != NULL, "Expected to get a filter record but got NULL."); res = filter->cb(next, conn, filter->config); check(res >= CLOSE && res < EVENT_END, "Filter %s returned invalid event: %d", bdata(filter->load_path), res); } } return res; error: return -1; }