int http_client_pool_init(struct http_client_pool *http_client_pool, size_t initial, size_t grow) { LOGGER_INFO("http client pool: initial=%zu, grow=%zu", initial, grow); if (0 > ctx_pool_init(&http_client_pool->ctx_pool, initial, grow, CLIENT_STACK_SIZE, sizeof(struct http_client_context))) return -1; /* Global to all clients */ if (!client_chains) { struct rlimit rlim; if (0 > getrlimit(RLIMIT_NOFILE, &rlim)) return LOGGER_PERROR("getrlimit(RLIMIT_NOFILE)"), -1; client_chains = calloc(rlim.rlim_cur, sizeof(struct list)); if (!client_chains) return LOGGER_PERROR("calloc client_chains"), -1; /* storage for multiple client chains */ client_heads = calloc(rlim.rlim_cur, sizeof(struct list)); struct list *tmp = client_heads, *tmp_end = tmp + rlim.rlim_cur; if (!client_heads) return LOGGER_PERROR("calloc client_heads"), -1; for (; tmp != tmp_end; ++tmp) list_insert_tail(&free_list, tmp); idle_ctx = ribs_context_create(SMALL_STACK_SIZE, http_client_idle_handler); hashtable_init(&ht_persistent_clients, rlim.rlim_cur); } return timeout_handler_init(&http_client_pool->timeout_handler); }
int http_server_init(struct http_server *server) { /* * one time global initializers */ if (0 > mime_types_init()) return LOGGER_ERROR("failed to initialize mime types"), -1; if (0 > http_headers_init()) return LOGGER_ERROR("failed to initialize http headers"), -1; /* * idle connection handler */ server->idle_ctx = ribs_context_create(SMALL_STACK_SIZE, http_server_idle_handler); server->idle_ctx->data.ptr = server; /* * context pool */ if (0 == server->stack_size || 0 == server->num_stacks) { struct rlimit rlim; if (0 > getrlimit(RLIMIT_STACK, &rlim)) return LOGGER_PERROR("getrlimit(RLIMIT_STACK)"), -1; long total_mem = sysconf(_SC_PHYS_PAGES); if (total_mem < 0) return LOGGER_PERROR("sysconf"), -1; total_mem *= getpagesize(); size_t num_ctx_in_one_map = total_mem / rlim.rlim_cur; /* half of total mem to start with so we don't need to enable overcommit */ num_ctx_in_one_map >>= 1; LOGGER_INFO("http server pool: initial=%zu, grow=%zu", num_ctx_in_one_map, num_ctx_in_one_map); ctx_pool_init(&server->ctx_pool, num_ctx_in_one_map, num_ctx_in_one_map, rlim.rlim_cur, sizeof(struct http_server_context) + server->context_size); } else {
int http_server_init(struct http_server *server) { /* * one time global initializers */ if (0 > mime_types_init()) return LOGGER_ERROR("failed to initialize mime types"), -1; if (0 > http_headers_init()) return LOGGER_ERROR("failed to initialize http headers"), -1; /* * idle connection handler */ server->idle_ctx = ribs_context_create(SMALL_STACK_SIZE, sizeof(struct http_server *), http_server_idle_handler); struct http_server **server_ref = (struct http_server **)server->idle_ctx->reserved; *server_ref = server; /* * context pool */ if (0 == server->num_stacks) server->num_stacks = DEFAULT_NUM_STACKS; if (0 == server->stack_size) { struct rlimit rlim; if (0 > getrlimit(RLIMIT_STACK, &rlim)) return LOGGER_PERROR("getrlimit(RLIMIT_STACK)"), -1; server->stack_size = rlim.rlim_cur; } LOGGER_INFO("http server pool: initial=%zu, grow=%zu, stack_size=%zu", server->num_stacks, server->num_stacks, server->stack_size); ctx_pool_init(&server->ctx_pool, server->num_stacks, server->num_stacks, server->stack_size, sizeof(struct http_server_context) + server->context_size); /* * listen socket */ const int LISTEN_BACKLOG = 32768; LOGGER_INFO("listening on port: %d, backlog: %d", server->port, LISTEN_BACKLOG); int lfd = socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP); if (0 > lfd) return -1; int rc; const int option = 1; rc = setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); if (0 > rc) return LOGGER_PERROR("setsockopt, SO_REUSEADDR"), rc; rc = setsockopt(lfd, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)); if (0 > rc) return LOGGER_PERROR("setsockopt, TCP_NODELAY"), rc; struct linger ls; ls.l_onoff = 0; ls.l_linger = 0; rc = setsockopt(lfd, SOL_SOCKET, SO_LINGER, (void *)&ls, sizeof(ls)); if (0 > rc) return LOGGER_PERROR("setsockopt, SO_LINGER"), rc; struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(server->port); addr.sin_addr.s_addr = INADDR_ANY; if (0 > bind(lfd, (struct sockaddr *)&addr, sizeof(addr))) return LOGGER_PERROR("bind"), -1; if (0 > listen(lfd, LISTEN_BACKLOG)) return LOGGER_PERROR("listen"), -1; server->accept_ctx = ribs_context_create(ACCEPTOR_STACK_SIZE, sizeof(struct http_server *), http_server_accept_connections); server->fd = lfd; server_ref = (struct http_server **)server->accept_ctx->reserved; *server_ref = server; if (server->max_req_size == 0) server->max_req_size = DEFAULT_MAX_REQ_SIZE; return 0; }