/* * Copy contents of new_listener into existing listener */ static void listener_update(struct Listener *existing_listener, struct Listener *new_listener, const struct Table_head *tables) { assert(existing_listener != NULL); assert(new_listener != NULL); assert(address_compare(existing_listener->address, new_listener->address) == 0); free(existing_listener->fallback_address); existing_listener->fallback_address = new_listener->fallback_address; new_listener->fallback_address = NULL; free(existing_listener->source_address); existing_listener->source_address = new_listener->source_address; new_listener->source_address = NULL; existing_listener->protocol = new_listener->protocol; free(existing_listener->table_name); existing_listener->table_name = new_listener->table_name; new_listener->table_name = NULL; logger_ref_put(existing_listener->access_log); existing_listener->access_log = logger_ref_get(new_listener->access_log); existing_listener->log_bad_requests = new_listener->log_bad_requests; struct Table *new_table = table_lookup(tables, existing_listener->table_name); if (new_table != NULL) { init_table(new_table); table_ref_put(existing_listener->table); existing_listener->table = table_ref_get(new_table); table_ref_put(new_listener->table); new_listener->table = NULL; } }
void add_table(struct Table_head *tables, struct Table *table) { table_ref_get(table); SLIST_INSERT_HEAD(tables, table, entries); }
static int init_listener(struct Listener *listener, const struct Table_head *tables, struct ev_loop *loop) { struct Table *table = table_lookup(tables, listener->table_name); if (table == NULL) { err("Table \"%s\" not defined", listener->table_name); return -1; } init_table(table); listener->table = table_ref_get(table); /* If no port was specified on the fallback address, inherit the address * from the listening address */ if (listener->fallback_address && address_port(listener->fallback_address) == 0) address_set_port(listener->fallback_address, address_port(listener->address)); int sockfd = socket(address_sa(listener->address)->sa_family, SOCK_STREAM, 0); if (sockfd < 0) { err("socket failed: %s", strerror(errno)); return -2; } /* set SO_REUSEADDR on server socket to facilitate restart */ int on = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); int result = bind(sockfd, address_sa(listener->address), address_sa_len(listener->address)); if (result < 0 && errno == EACCES) { /* Retry using binder module */ close(sockfd); sockfd = bind_socket(address_sa(listener->address), address_sa_len(listener->address)); if (sockfd < 0) { char address[128]; err("binder failed to bind to %s", display_address(listener->address, address, sizeof(address))); close(sockfd); return -3; } } else if (result < 0) { char address[128]; err("bind %s failed: %s", display_address(listener->address, address, sizeof(address)), strerror(errno)); close(sockfd); return -3; } if (listen(sockfd, SOMAXCONN) < 0) { err("listen failed: %s", strerror(errno)); close(sockfd); return -4; } int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); listener_ref_get(listener); ev_io_init(&listener->watcher, accept_cb, sockfd, EV_READ); listener->watcher.data = listener; listener->backoff_timer.data = listener; ev_io_start(loop, &listener->watcher); return sockfd; }