Add custom server socket callbacks (for ssl modules)

personal/stbuehler/wip
Stefan Bühler 14 years ago
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…
Cancel
Save