summaryrefslogtreecommitdiff
path: root/src/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network.c')
-rw-r--r--src/network.c891
1 files changed, 0 insertions, 891 deletions
diff --git a/src/network.c b/src/network.c
deleted file mode 100644
index 988dc940..00000000
--- a/src/network.c
+++ /dev/null
@@ -1,891 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <stdio.h>
-
-#include "network.h"
-#include "fdevent.h"
-#include "log.h"
-#include "connections.h"
-#include "plugin.h"
-#include "joblist.h"
-
-#include "network_backends.h"
-#include "sys-mmap.h"
-#include "sys-socket.h"
-#include "sys-files.h"
-
-#ifdef USE_OPENSSL
-# include <openssl/ssl.h>
-# include <openssl/err.h>
-# include <openssl/rand.h>
-#endif
-
-#define BACKEND_HANDLERS(read, write) network_read_chunkqueue_##read, network_write_chunkqueue_##write
-static network_backend_info_t network_backends[] = {
- /* lowest id wins */
- {
- NETWORK_BACKEND_LINUX_SENDFILE,
- "linux-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_LINUX_SENDFILE
- BACKEND_HANDLERS(read, linuxsendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_LINUX_AIO_SENDFILE,
- "linux-aio-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_LINUX_AIO_SENDFILE
- BACKEND_HANDLERS(read, linuxaiosendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_FREEBSD_SENDFILE,
- "freebsd-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_FREEBSD_SENDFILE
- BACKEND_HANDLERS(read, freebsdsendfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_SOLARIS_SENDFILEV,
- "solaris-sendfilev",
- NULL,
-#if defined USE_WRITE && defined USE_SOLARIS_SENDFILEV
- BACKEND_HANDLERS(read, solarissendfilev)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_POSIX_AIO,
- "posix-aio",
- NULL,
-#if defined USE_WRITE && defined USE_POSIX_AIO
- BACKEND_HANDLERS(read, posixaio)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_GTHREAD_AIO,
- "gthread-aio",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO
- BACKEND_HANDLERS(read, gthreadaio)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_GTHREAD_SENDFILE,
- "gthread-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO && defined USE_GTHREAD_SENDFILE
- BACKEND_HANDLERS(read, gthreadsendfile)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_GTHREAD_FREEBSD_SENDFILE,
- "gthread-freebsd-sendfile",
- NULL,
-#if defined USE_WRITE && defined USE_GTHREAD_AIO && defined USE_GTHREAD_FREEBSD_SENDFILE
- BACKEND_HANDLERS(read, gthreadfreebsdsendfile)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_WRITEV,
- "writev",
- NULL,
-#if defined USE_WRITE && defined USE_WRITEV
- BACKEND_HANDLERS(read, writev)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WRITE,
- "write",
- NULL,
-#if defined USE_WRITE
- BACKEND_HANDLERS(read, write)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WIN32_TRANSMITFILE,
- "win32-transmitfile",
- NULL,
-#if defined USE_WIN32_TRANSMITFILE
- BACKEND_HANDLERS(win32recv, win32transmitfile)
-#else
- NULL, NULL
-#endif
- },
- {
- NETWORK_BACKEND_WIN32_SEND,
- "win32-send",
- NULL,
-#if defined USE_WIN32_SEND && defined USE_WIN32_SEND
- BACKEND_HANDLERS(win32recv, win32send)
-#else
- NULL, NULL
-#endif
- },
-
- {
- NETWORK_BACKEND_UNSET,
- NULL,
- NULL,
- NULL, NULL
- }
-};
-
-const network_backend_info_t *network_get_backends() {
- return network_backends;
-}
-
-const network_backend_info_t *network_get_defaultbackend() {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (backend->write_handler) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-const network_backend_info_t *network_get_backend_info_by_type(network_backend_t type) {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (type == backend->type) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-const network_backend_info_t *network_get_backend_info_by_name(const char *name) {
- const network_backend_info_t *backend = network_get_backends();
-
- while (backend->name) {
- if (strcmp(name, backend->name) == 0) {
- return backend;
- }
- backend ++;
- }
-
- return NULL;
-}
-
-handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
- server *srv = (server *)s;
- server_socket *srv_socket = (server_socket *)context;
- connection *con;
- int loops = 0;
-
- UNUSED(context);
-
- if (revents != FDEVENT_IN) {
- log_error_write(srv, __FILE__, __LINE__, "sdd",
- "strange event for server socket",
- srv_socket->sock->fd,
- revents);
- return HANDLER_ERROR;
- }
-
- /* accept()s at most 100 connections directly
- *
- * we jump out after 100 to give the waiting connections a chance */
- for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
- joblist_append(srv, con);
- }
- return HANDLER_GO_ON;
-}
-
-#if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
-static int network_ssl_servername_callback(SSL *ssl, int *al, server *srv) {
- const char *servername;
- connection *con = (connection *) SSL_get_app_data(ssl);
-
- UNUSED(al);
-
- buffer_copy_string(con->uri.scheme, "https");
-
- if (NULL == (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
-#if 0
- /* this "error" just means the client didn't support it */
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "failed to get TLS server name");
-#endif
- return SSL_TLSEXT_ERR_NOACK;
- }
- buffer_copy_string(con->sock->tlsext_server_name, servername);
- buffer_to_lower(con->sock->tlsext_server_name);
-
- config_patch_connection(srv, con, COMP_SERVER_SOCKET);
- config_patch_connection(srv, con, COMP_HTTP_SCHEME);
- config_patch_connection(srv, con, COMP_HTTP_HOST);
-
- if (NULL == con->conf.ssl_ctx) {
- /* ssl_ctx <=> pemfile was set <=> ssl_ctx got patched: so this should never happen */
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- "null SSL_CTX for TLS server name", con->sock->tlsext_server_name);
- return SSL_TLSEXT_ERR_ALERT_FATAL;
- }
-
- /* switch to new SSL_CTX in reaction to a client's server_name extension */
- if (con->conf.ssl_ctx != SSL_set_SSL_CTX(ssl, con->conf.ssl_ctx)) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- "failed to set SSL_CTX for TLS server name", con->sock->tlsext_server_name);
- return SSL_TLSEXT_ERR_ALERT_FATAL;
- }
-
- return SSL_TLSEXT_ERR_OK;
-}
-#endif
-
-static int network_server_init(server *srv, buffer *host_token, specific_config *s) {
- int val;
- socklen_t addr_len;
- server_socket *srv_socket;
- char *sp;
- unsigned int port = 0;
- const char *host;
- buffer *b;
- int is_unix_domain_socket = 0;
- int fd;
-
-#ifdef SO_ACCEPTFILTER
- struct accept_filter_arg afa;
-#endif
-
-#ifdef _WIN32
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-
- wVersionRequested = MAKEWORD( 2, 2 );
-
- err = WSAStartup( wVersionRequested, &wsaData );
- if ( err != 0 ) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- return -1;
- }
-#endif
-
- srv_socket = calloc(1, sizeof(*srv_socket));
- srv_socket->sock = iosocket_init();
-
- srv_socket->srv_token = buffer_init();
- buffer_copy_string_buffer(srv_socket->srv_token, host_token);
-
- b = buffer_init();
- buffer_copy_string_buffer(b, host_token);
-
- /* ipv4:port
- * [ipv6]:port
- */
- if (NULL == (sp = strrchr(b->ptr, ':'))) {
- log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
-
- goto error_free_socket;
- }
-
- host = b->ptr;
-
- /* check for [ and ] */
- if (b->ptr[0] == '[' && *(sp-1) == ']') {
- *(sp-1) = '\0';
- host++;
-
- s->use_ipv6 = 1;
- }
-
- *(sp++) = '\0';
-
- port = strtol(sp, NULL, 10);
-
- if (host[0] == '/') {
- /* host is a unix-domain-socket */
- is_unix_domain_socket = 1;
- } else if (port == 0 || port > 65535) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
-
- goto error_free_socket;
- }
-
- if (*host == '\0') host = NULL;
-
- if (is_unix_domain_socket) {
-#ifdef HAVE_SYS_UN_H
-
- srv_socket->addr.plain.sa_family = AF_UNIX;
-
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
-#else
- log_error_write(srv, __FILE__, __LINE__, "s",
- "ERROR: Unix Domain sockets are not supported.");
- goto error_free_socket;
-#endif
- }
-
-#ifdef HAVE_IPV6
- if (s->use_ipv6) {
- srv_socket->addr.plain.sa_family = AF_INET6;
-
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
- srv_socket->use_ipv6 = 1;
- }
-#endif
-
- if (srv_socket->sock->fd == -1) {
- srv_socket->addr.plain.sa_family = AF_INET;
- if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
- goto error_free_socket;
- }
- }
-
- val = 1;
- if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
- goto error_free_socket;
- }
-
- switch(srv_socket->addr.plain.sa_family) {
-#ifdef HAVE_IPV6
- case AF_INET6:
- memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in6));
- srv_socket->addr.ipv6.sin6_family = AF_INET6;
- if (host == NULL) {
- srv_socket->addr.ipv6.sin6_addr = in6addr_any;
- } else {
- struct addrinfo hints, *res;
- int r;
-
- memset(&hints, 0, sizeof(hints));
-
- hints.ai_family = AF_INET6;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
- log_error_write(srv, __FILE__, __LINE__,
- "sssss", "getaddrinfo failed: ",
- gai_strerror(r), "'", host, "'");
-
- goto error_free_socket;
- }
-
- memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
-
- freeaddrinfo(res);
- }
- srv_socket->addr.ipv6.sin6_port = htons(port);
- addr_len = sizeof(struct sockaddr_in6);
- break;
-#endif
- case AF_INET:
- memset(&srv_socket->addr, 0, sizeof(struct sockaddr_in));
- srv_socket->addr.ipv4.sin_family = AF_INET;
- if (host == NULL) {
- srv_socket->addr.ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
- } else {
- struct hostent *he;
- if (NULL == (he = gethostbyname(host))) {
- log_error_write(srv, __FILE__, __LINE__,
- "sds", "gethostbyname failed: ",
- h_errno, host);
- goto error_free_socket;
- }
-
- if (he->h_addrtype != AF_INET) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
- goto error_free_socket;
- }
-
- if (he->h_length != sizeof(struct in_addr)) {
- log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
- goto error_free_socket;
- }
-
- memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
- }
- srv_socket->addr.ipv4.sin_port = htons(port);
-
- addr_len = sizeof(struct sockaddr_in);
-
- break;
-#ifndef _WIN32
- case AF_UNIX:
- srv_socket->addr.un.sun_family = AF_UNIX;
- strcpy(srv_socket->addr.un.sun_path, host);
-
-#ifdef SUN_LEN
- addr_len = SUN_LEN(&srv_socket->addr.un);
-#else
- /* stevens says: */
- addr_len = strlen(host) + 1 + sizeof(srv_socket->addr.un.sun_family);
-#endif
-
- /* check if the socket exists and try to connect to it. */
- if (-1 != (fd = connect(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
- close(fd);
-
- log_error_write(srv, __FILE__, __LINE__, "ss",
- "server socket is still in use:",
- host);
-
-
- goto error_free_socket;
- }
-
- /* connect failed */
- switch(errno) {
- case ECONNREFUSED:
- unlink(host);
- break;
- case ENOENT:
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "testing socket failed:",
- host, strerror(errno));
-
- goto error_free_socket;
- }
-
- break;
-#endif
- default:
- addr_len = 0;
-
- goto error_free_socket;
- }
-
- if (0 != bind(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
- switch(srv_socket->addr.plain.sa_family) {
- case AF_UNIX:
- log_error_write(srv, __FILE__, __LINE__, "sds",
- "can't bind to socket:",
- host, strerror(errno));
- break;
- default:
- log_error_write(srv, __FILE__, __LINE__, "ssds",
- "can't bind to port:",
- host, port, strerror(errno));
- break;
- }
- goto error_free_socket;
- }
-
- if (-1 == listen(srv_socket->sock->fd, 128 * 8)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
- goto error_free_socket;
- }
-
- if (s->is_ssl) {
-#ifdef USE_OPENSSL
- if (NULL == (srv_socket->ssl_ctx = s->ssl_ctx)) {
- log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
- goto error_free_socket;
- }
-#else
-
- buffer_free(srv_socket->srv_token);
- free(srv_socket);
-
- buffer_free(b);
-
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "ssl requested but openssl support is not compiled in");
-
- goto error_free_socket;
-#endif
- } else {
-#ifdef SO_ACCEPTFILTER
- /*
- * FreeBSD accf_http filter
- *
- */
- memset(&afa, 0, sizeof(afa));
- strcpy(afa.af_name, "httpready");
- if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
- if (errno != ENOENT) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno));
- }
- }
-#endif
- }
-
-#ifdef FD_CLOEXEC
- /* set FD_CLOEXEC now, fdevent_fcntl_set is called later; needed for pipe-logger forks */
- fcntl(srv_socket->sock->fd, F_SETFD, FD_CLOEXEC);
-#endif
-
- srv_socket->is_ssl = s->is_ssl;
-
- if (srv->srv_sockets.size == 0) {
- srv->srv_sockets.size = 4;
- srv->srv_sockets.used = 0;
- srv->srv_sockets.ptr = malloc(srv->srv_sockets.size * sizeof(server_socket));
- } else if (srv->srv_sockets.used == srv->srv_sockets.size) {
- srv->srv_sockets.size += 4;
- srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
- }
-
- srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
- buffer_free(b);
-
- return 0;
-
-error_free_socket:
- iosocket_free(srv_socket->sock);
- buffer_free(srv_socket->srv_token);
- free(srv_socket);
-
- return -1;
-}
-
-int network_close(server *srv) {
- size_t i;
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
-
- if (srv_socket->sock->fd != -1) {
- /* check if server fd are already registered */
- if (srv_socket->sock->fde_ndx != -1) {
- fdevent_event_del(srv->ev, srv_socket->sock);
- fdevent_unregister(srv->ev, srv_socket->sock);
- }
- }
-
- iosocket_free(srv_socket->sock);
-
- buffer_free(srv_socket->srv_token);
-
- free(srv_socket);
- }
-
-#ifdef USE_OPENSSL
- ERR_free_strings();
-#endif
- free(srv->srv_sockets.ptr);
-
- return 0;
-}
-
-int network_init(server *srv) {
- buffer *b;
- size_t i;
- const network_backend_info_t *backend;
-
-#ifdef USE_OPENSSL
- /* load SSL certificates */
- for (i = 0; i < srv->config_context->used; i++) {
- specific_config *s = srv->config_storage[i];
-
- if (buffer_is_empty(s->ssl_pemfile)) continue;
-
-#ifdef OPENSSL_NO_TLSEXT
- {
- data_config *dc = (data_config *)srv->config_context->data[i];
- if (COMP_HTTP_HOST == dc->comp) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
- return -1;
- }
- }
-#endif
-
- if (srv->ssl_is_init == 0) {
- SSL_load_error_strings();
- SSL_library_init();
- srv->ssl_is_init = 1;
-
- if (0 == RAND_status()) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "not enough entropy in the pool");
- return -1;
- }
- }
-
- if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
-
- if (!s->ssl_use_sslv2) {
- /* disable SSLv2 */
- if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- }
-
- if (!buffer_is_empty(s->ssl_cipher_list)) {
- if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- }
-
- if (!buffer_is_empty(s->ssl_ca_file)) {
- if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
- return -1;
- }
- if (s->ssl_verifyclient) {
- STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
- if (!certs) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
- }
- if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- ERR_error_string(ERR_get_error(), NULL));
- return -1;
- }
- SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
- SSL_CTX_set_verify(
- s->ssl_ctx,
- SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
- NULL
- );
- SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
- }
- } else if (s->ssl_verifyclient) {
- log_error_write(
- srv, __FILE__, __LINE__, "s",
- "SSL: You specified ssl.verifyclient.activate but no ca_file"
- );
- }
-
- if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
- return -1;
- }
-
- if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
- log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
- ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
- return -1;
- }
-
- if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
- "Private key does not match the certificate public key, reason:",
- ERR_error_string(ERR_get_error(), NULL),
- s->ssl_pemfile);
- return -1;
- }
-
-#ifndef OPENSSL_NO_TLSEXT
- if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
- !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
- log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
- "failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
- return -1;
- }
-#endif
- }
-#endif
-
- b = buffer_init();
-
- buffer_copy_string_buffer(b, srv->srvconf.bindhost);
- buffer_append_string_len(b, CONST_STR_LEN(":"));
- buffer_append_long(b, srv->srvconf.port);
-
- if (0 != network_server_init(srv, b, srv->config_storage[0])) {
- return -1;
- }
- buffer_free(b);
-
-#ifdef USE_OPENSSL
- srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
-#endif
-
- backend = network_get_backend_info_by_type(srv->network_backend);
- assert(backend && backend->read_handler);
- srv->network_backend_read = backend->read_handler;
- srv->network_backend_write = backend->write_handler;
-
-#ifdef USE_OPENSSL
- srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
- srv->network_ssl_backend_read = network_read_chunkqueue_openssl;
-#endif
-
- /* check for $SERVER["socket"] */
- for (i = 1; i < srv->config_context->used; i++) {
- data_config *dc = (data_config *)srv->config_context->data[i];
- specific_config *s = srv->config_storage[i];
- size_t j;
-
- /* not our stage */
- if (COMP_SERVER_SOCKET != dc->comp) continue;
-
- if (dc->cond != CONFIG_COND_EQ) continue;
-
- /* check if we already know this socket,
- * if yes, don't init it */
- for (j = 0; j < srv->srv_sockets.used; j++) {
- if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
- break;
- }
- }
-
- if (j == srv->srv_sockets.used) {
- if (0 != network_server_init(srv, dc->string, s)) return -1;
- }
- }
-
- return 0;
-}
-
-int network_register_fdevents(server *srv) {
- size_t i;
- if (-1 == fdevent_reset(srv->ev)) {
- return -1;
- }
- /* register fdevents after reset */
- for (i = 0; i < srv->srv_sockets.used; i++) {
- server_socket *srv_socket = srv->srv_sockets.ptr[i];
- fdevent_register(srv->ev, srv_socket->sock, network_server_handle_fdevent, srv_socket);
- fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN);
- }
- return 0;
-}
-
-network_status_t network_read(server *srv, connection *con, iosocket *sock, chunkqueue *cq) {
- server_socket *srv_socket = con->srv_socket;
- network_status_t ret = NETWORK_STATUS_UNSET;
- off_t start_bytes_in = cq->bytes_in;
-
- if (srv_socket->is_ssl) {
-#ifdef USE_OPENSSL
- ret = srv->network_ssl_backend_read(srv, con, sock, cq);
-#else
- ret = NETWORK_STATUS_FATAL_ERROR;
-#endif
- } else {
- ret = srv->network_backend_read(srv, con, sock, cq);
- }
-
- con->bytes_read += cq->bytes_in - start_bytes_in;
-
- return ret;
-}
-
-network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
- network_status_t ret = NETWORK_STATUS_UNSET;
- off_t written = 0;
-#ifdef TCP_CORK
- int corked = 0;
-#endif
- server_socket *srv_socket = con->srv_socket;
-
- if (con->conf.global_kbytes_per_second &&
- *(con->conf.global_bytes_per_second_cnt_ptr) > con->conf.global_kbytes_per_second * 1024) {
- /* we reached the global traffic limit */
-
- con->traffic_limit_reached = 1;
- joblist_append(srv, con);
-
- return NETWORK_STATUS_WAIT_FOR_AIO_EVENT;
- }
-
- written = cq->bytes_out;
-
-#ifdef TCP_CORK
- /* Linux: put a cork into the socket as we want to combine the write() calls
- * but only if we really have multiple chunks
- */
- if (cq->first && cq->first->next) {
- corked = 1;
- setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
- }
-#endif
-
- if (srv_socket->is_ssl) {
-#ifdef USE_OPENSSL
- ret = srv->network_ssl_backend_write(srv, con, con->sock, cq);
-#endif
- } else {
- ret = srv->network_backend_write(srv, con, con->sock, cq);
- }
-
- switch (ret) {
- case NETWORK_STATUS_WAIT_FOR_FD:
- case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
- case NETWORK_STATUS_WAIT_FOR_EVENT:
- case NETWORK_STATUS_SUCCESS:
- chunkqueue_remove_finished_chunks(cq);
-
- break;
- default:
- break;
- }
-
-#ifdef TCP_CORK
- if (corked) {
- corked = 0;
- setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
- }
-#endif
-
- written = cq->bytes_out - written;
- con->bytes_written += written;
- con->bytes_written_cur_second += written;
-
- *(con->conf.global_bytes_per_second_cnt_ptr) += written;
-
- if (con->conf.kbytes_per_second &&
- (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
- /* we reached the traffic limit */
-
- con->traffic_limit_reached = 1;
- joblist_append(srv, con);
- }
- return ret;
-}