Add custom server socket callbacks (for ssl modules)
This commit is contained in:
parent
c77ba3eb20
commit
a663088a77
|
@ -1,11 +1,13 @@
|
|||
#ifndef _LIGHTTPD_ANGEL_H_
|
||||
#define _LIGHTTPD_ANGEL_H_
|
||||
|
||||
typedef void (*liAngelListenCB)(liServer *srv, int fd, gpointer data);
|
||||
|
||||
/* interface to the angel; implementation needs to work without angel too */
|
||||
LI_API void li_angel_setup(liServer *srv);
|
||||
|
||||
/* listen to a socket */
|
||||
LI_API void li_angel_listen(liServer *srv, GString *str);
|
||||
LI_API void li_angel_listen(liServer *srv, GString *str, liAngelListenCB cb, gpointer data);
|
||||
|
||||
/* send log messages during startup to angel, frees the string */
|
||||
LI_API void li_angel_log(liServer *srv, GString *str);
|
||||
|
|
|
@ -30,6 +30,7 @@ struct liConnection {
|
|||
liServer *srv;
|
||||
liWorker *wrk;
|
||||
liServerSocket *srv_sock;
|
||||
gpointer srv_sock_data; /** private data for custom sockets (ssl) */
|
||||
|
||||
liConnectionState state;
|
||||
gboolean response_headers_sent, expect_100_cont;
|
||||
|
@ -95,7 +96,9 @@ struct liConnection {
|
|||
|
||||
/* Internal functions */
|
||||
LI_API liConnection* li_connection_new(liWorker *wrk);
|
||||
/** Free dead connections */
|
||||
LI_API void li_connection_free(liConnection *con);
|
||||
/** close connection */
|
||||
LI_API void li_connection_reset(liConnection *con);
|
||||
|
||||
/** aborts an active connection, calls all plugin cleanup handlers */
|
||||
|
|
|
@ -9,15 +9,6 @@
|
|||
# define USE_SENDFILE
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LI_NETWORK_STATUS_SUCCESS, /**< some IO was actually done (read/write) or cq was empty for write */
|
||||
LI_NETWORK_STATUS_FATAL_ERROR,
|
||||
LI_NETWORK_STATUS_CONNECTION_CLOSE,
|
||||
LI_NETWORK_STATUS_WAIT_FOR_EVENT, /**< read/write returned -1 with errno=EAGAIN/EWOULDBLOCK; no real IO was done
|
||||
internal: some io may be done */
|
||||
LI_NETWORK_STATUS_WAIT_FOR_AIO_EVENT /**< nothing done yet, read/write will be done somewhere else */
|
||||
} liNetworkStatus;
|
||||
|
||||
/** repeats write after EINTR */
|
||||
LI_API ssize_t li_net_write(int fd, void *buf, ssize_t nbyte);
|
||||
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
#define LIGHTTPD_SERVER_MAGIC ((guint)0x12AB34CD)
|
||||
#endif
|
||||
|
||||
typedef gboolean (*liConnectionNewCB)(liConnection *con);
|
||||
typedef void (*liConnectionCloseCB)(liConnection *con);
|
||||
typedef liNetworkStatus (*liConnectionWriteCB)(liConnection *con, goffset write_max);
|
||||
typedef liNetworkStatus (*liConnectionReadCB)(liConnection *con);
|
||||
typedef void (*liServerSocketReleaseCB)(liServerSocket *srv_sock);
|
||||
|
||||
typedef enum {
|
||||
LI_SERVER_INIT, /** start state */
|
||||
LI_SERVER_LOADING, /** config loaded, prepare listeing sockets/open log files */
|
||||
|
@ -22,6 +28,14 @@ struct liServerSocket {
|
|||
ev_io watcher;
|
||||
liSocketAddress local_addr;
|
||||
GString *local_addr_str;
|
||||
|
||||
/* Custom sockets (ssl) */
|
||||
gpointer data;
|
||||
liConnectionWriteCB write_cb;
|
||||
liConnectionReadCB read_cb;
|
||||
liConnectionNewCB new_cb;
|
||||
liConnectionCloseCB close_cb;
|
||||
liServerSocketReleaseCB release_cb;
|
||||
};
|
||||
|
||||
struct liServer {
|
||||
|
@ -94,7 +108,7 @@ LI_API void li_server_free(liServer* srv);
|
|||
LI_API gboolean li_server_loop_init(liServer *srv);
|
||||
LI_API gboolean li_server_worker_init(liServer *srv);
|
||||
|
||||
LI_API void li_server_listen(liServer *srv, int fd);
|
||||
LI_API liServerSocket* li_server_listen(liServer *srv, int fd);
|
||||
|
||||
/* exit asap with cleanup */
|
||||
LI_API void li_server_exit(liServer *srv);
|
||||
|
|
|
@ -113,6 +113,17 @@ typedef enum {
|
|||
LI_LOG_TYPE_NONE
|
||||
} liLogType;
|
||||
|
||||
/* network.h */
|
||||
|
||||
typedef enum {
|
||||
LI_NETWORK_STATUS_SUCCESS, /**< some IO was actually done (read/write) or cq was empty for write */
|
||||
LI_NETWORK_STATUS_FATAL_ERROR,
|
||||
LI_NETWORK_STATUS_CONNECTION_CLOSE,
|
||||
LI_NETWORK_STATUS_WAIT_FOR_EVENT, /**< read/write returned -1 with errno=EAGAIN/EWOULDBLOCK; no real IO was done
|
||||
internal: some io may be done */
|
||||
LI_NETWORK_STATUS_WAIT_FOR_AIO_EVENT /**< nothing done yet, read/write will be done somewhere else */
|
||||
} liNetworkStatus;
|
||||
|
||||
/* options.h */
|
||||
|
||||
typedef struct liOptionSet liOptionSet;
|
||||
|
|
|
@ -40,12 +40,21 @@ void li_angel_setup(liServer *srv) {
|
|||
srv->dest_state = LI_SERVER_SUSPENDED;
|
||||
}
|
||||
|
||||
static void li_angel_listen_cb(liAngelCall *acall, gpointer ctx, gboolean timeout, GString *error, GString *data, GArray *fds) {
|
||||
liServer *srv = ctx;
|
||||
typedef struct angel_listen_cb_ctx angel_listen_cb_ctx;
|
||||
struct angel_listen_cb_ctx {
|
||||
liServer *srv;
|
||||
liAngelListenCB cb;
|
||||
gpointer data;
|
||||
};
|
||||
|
||||
static void li_angel_listen_cb(liAngelCall *acall, gpointer pctx, gboolean timeout, GString *error, GString *data, GArray *fds) {
|
||||
angel_listen_cb_ctx ctx = * (angel_listen_cb_ctx*) pctx;
|
||||
liServer *srv = ctx.srv;
|
||||
guint i;
|
||||
UNUSED(data);
|
||||
|
||||
li_angel_call_free(acall);
|
||||
g_slice_free(angel_listen_cb_ctx, pctx);
|
||||
|
||||
ERROR(srv, "%s", "listen_cb");
|
||||
|
||||
|
@ -62,8 +71,13 @@ static void li_angel_listen_cb(liAngelCall *acall, gpointer ctx, gboolean timeou
|
|||
|
||||
if (fds && fds->len > 0) {
|
||||
for (i = 0; i < fds->len; i++) {
|
||||
INFO(srv, "listening on fd %i", g_array_index(fds, int, i));
|
||||
li_server_listen(srv, g_array_index(fds, int, i));
|
||||
int fd = g_array_index(fds, int, i);
|
||||
DEBUG(srv, "listening on fd %i", fd);
|
||||
if (ctx.cb) {
|
||||
ctx.cb(srv, fd, ctx.data);
|
||||
} else {
|
||||
li_server_listen(srv, fd);
|
||||
}
|
||||
}
|
||||
g_array_set_size(fds, 0);
|
||||
} else {
|
||||
|
@ -72,12 +86,16 @@ static void li_angel_listen_cb(liAngelCall *acall, gpointer ctx, gboolean timeou
|
|||
}
|
||||
|
||||
/* listen to a socket */
|
||||
void li_angel_listen(liServer *srv, GString *str) {
|
||||
void li_angel_listen(liServer *srv, GString *str, liAngelListenCB cb, gpointer data) {
|
||||
if (srv->acon) {
|
||||
liAngelCall *acall = li_angel_call_new(li_angel_listen_cb, 3.0);
|
||||
angel_listen_cb_ctx *ctx = g_slice_new0(angel_listen_cb_ctx);
|
||||
GError *err = NULL;
|
||||
|
||||
acall->context = srv;
|
||||
ctx->srv = srv;
|
||||
ctx->cb = cb;
|
||||
ctx->data = data;
|
||||
acall->context = ctx;
|
||||
if (!li_angel_send_call(srv->acon, CONST_STR_LEN("core"), CONST_STR_LEN("listen"), acall, g_string_new_len(GSTR_LEN(str)), &err)) {
|
||||
ERROR(srv, "couldn't send call: %s", err->message);
|
||||
g_error_free(err);
|
||||
|
@ -88,7 +106,11 @@ void li_angel_listen(liServer *srv, GString *str) {
|
|||
ERROR(srv, "listen('%s') failed", str->str);
|
||||
/* TODO: exit? */
|
||||
} else {
|
||||
li_server_listen(srv, fd);
|
||||
if (cb) {
|
||||
cb(srv, fd, data);
|
||||
} else {
|
||||
li_server_listen(srv, fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,7 +271,11 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
|||
} else {
|
||||
transferred = con->raw_in->length;
|
||||
|
||||
res = li_network_read(con->mainvr, w->fd, con->raw_in);
|
||||
if (con->srv_sock->read_cb) {
|
||||
res = con->srv_sock->read_cb(con);
|
||||
} else {
|
||||
res = li_network_read(con->mainvr, w->fd, con->raw_in);
|
||||
}
|
||||
|
||||
transferred = con->raw_in->length - transferred;
|
||||
con->wrk->stats.bytes_in += transferred;
|
||||
|
@ -319,7 +323,11 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
|||
if (write_max > 0) {
|
||||
transferred = con->raw_out->length;
|
||||
|
||||
res = li_network_write(con->mainvr, w->fd, con->raw_out, write_max);
|
||||
if (con->srv_sock->write_cb) {
|
||||
res = con->srv_sock->write_cb(con, write_max);
|
||||
} else {
|
||||
res = li_network_write(con->mainvr, w->fd, con->raw_out, write_max);
|
||||
}
|
||||
|
||||
transferred = transferred - con->raw_out->length;
|
||||
con->wrk->stats.bytes_out += transferred;
|
||||
|
@ -483,8 +491,12 @@ void li_connection_reset(liConnection *con) {
|
|||
con->response_headers_sent = FALSE;
|
||||
con->expect_100_cont = FALSE;
|
||||
|
||||
if (con->srv_sock->close_cb)
|
||||
con->srv_sock->close_cb(con);
|
||||
|
||||
li_server_socket_release(con->srv_sock);
|
||||
con->srv_sock = NULL;
|
||||
con->srv_sock_data = NULL;
|
||||
|
||||
ev_io_stop(con->wrk->loop, &con->sock_watcher);
|
||||
if (con->sock_watcher.fd != -1) {
|
||||
|
|
|
@ -511,7 +511,7 @@ static gboolean core_listen(liServer *srv, liPlugin* p, liValue *val) {
|
|||
}
|
||||
|
||||
ipstr = val->data.string;
|
||||
li_angel_listen(srv, ipstr);
|
||||
li_angel_listen(srv, ipstr, NULL, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ void li_server_socket_release(liServerSocket* sock) {
|
|||
if (!sock) return;
|
||||
assert(g_atomic_int_get(&sock->refcount) > 0);
|
||||
if (g_atomic_int_dec_and_test(&sock->refcount)) {
|
||||
if (sock->release_cb) sock->release_cb(sock);
|
||||
|
||||
li_sockaddr_clear(&sock->local_addr);
|
||||
g_string_free(sock->local_addr_str, TRUE);
|
||||
g_slice_free(liServerSocket, sock);
|
||||
|
@ -165,13 +167,6 @@ void li_server_free(liServer* srv) {
|
|||
g_array_free(srv->workers, TRUE);
|
||||
}
|
||||
|
||||
/* release modules */
|
||||
li_modules_free(srv->modules);
|
||||
|
||||
li_plugin_free(srv, srv->core_plugin);
|
||||
|
||||
log_cleanup(srv);
|
||||
|
||||
{
|
||||
guint i; for (i = 0; i < srv->sockets->len; i++) {
|
||||
liServerSocket *sock = g_ptr_array_index(srv->sockets, i);
|
||||
|
@ -181,6 +176,13 @@ void li_server_free(liServer* srv) {
|
|||
g_ptr_array_free(srv->sockets, TRUE);
|
||||
}
|
||||
|
||||
/* release modules */
|
||||
li_modules_free(srv->modules);
|
||||
|
||||
li_plugin_free(srv, srv->core_plugin);
|
||||
|
||||
log_cleanup(srv);
|
||||
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < srv->ts_formats->len; i++)
|
||||
|
@ -311,13 +313,15 @@ static void li_server_listen_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
|||
}
|
||||
|
||||
/* main worker only */
|
||||
void li_server_listen(liServer *srv, int fd) {
|
||||
liServerSocket* li_server_listen(liServer *srv, int fd) {
|
||||
liServerSocket *sock = server_socket_new(fd);
|
||||
|
||||
sock->srv = srv;
|
||||
g_ptr_array_add(srv->sockets, sock);
|
||||
|
||||
if (LI_SERVER_RUNNING == srv->state || LI_SERVER_WARMUP == srv->state) ev_io_start(srv->main_worker->loop, &sock->watcher);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
static void li_server_start_listen(liServer *srv) {
|
||||
|
|
|
@ -275,6 +275,12 @@ void li_worker_new_con(liWorker *ctx, liWorker *wrk, liSocketAddress remote_addr
|
|||
con->ts = CUR_TS(con->wrk);
|
||||
li_sockaddr_to_string(remote_addr, con->remote_addr_str, FALSE);
|
||||
li_waitqueue_push(&wrk->io_timeout_queue, &con->io_timeout_elem);
|
||||
|
||||
if (srv_sock->new_cb) {
|
||||
if (!srv_sock->new_cb(con)) {
|
||||
li_connection_error(con);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
li_worker_new_con_data *d = g_slice_new(li_worker_new_con_data);
|
||||
d->remote_addr = remote_addr;
|
||||
|
@ -610,6 +616,8 @@ void worker_con_put(liConnection *con) {
|
|||
g_array_index(wrk->connections, liConnection*, tmp->idx) = tmp;
|
||||
}
|
||||
|
||||
li_connection_reset(con);
|
||||
|
||||
/* realloc wrk->connections if it makes sense (too many allocated, only every 60sec) */
|
||||
/* if (active < allocated*0.70) { allocated *= 0.85 } */
|
||||
threshold = (wrk->connections->len * 7) / 10;
|
||||
|
@ -622,8 +630,5 @@ void worker_con_put(liConnection *con) {
|
|||
}
|
||||
wrk->connections->len = threshold;
|
||||
wrk->connections_gc_ts = now;
|
||||
} else {
|
||||
/* no realloc */
|
||||
li_connection_reset(con);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue