5 #include <netinet/in.h>
9 #include <sys/socket.h>
10 #include <sys/eventfd.h>
11 #include <event2/event.h>
12 #include <event2/bufferevent.h>
13 #include <event2/bufferevent_ssl.h>
14 #include <event2/thread.h>
15 #include <event2/listener.h>
16 #include <openssl/ssl.h>
17 #include <openssl/rand.h>
18 #include <openssl/conf.h>
19 #include <openssl/engine.h>
20 #include <openssl/err.h>
22 #include "qlibc/qlibc.h"
46 static void notify_cb(
struct bufferevent *buffer,
void *userdata);
47 static void *server_loop(
void *instance);
49 static void libevent_log_cb(
int severity,
const char *msg);
50 static int set_undefined_options(
ad_server_t *server);
51 static SSL_CTX *init_ssl(
const char *cert_path,
const char *pkey_path);
52 static void listener_cb(
struct evconnlistener *listener,
53 evutil_socket_t evsocket,
struct sockaddr *sockaddr,
54 int socklen,
void *userdata);
58 static void conn_read_cb(
struct bufferevent *buffer,
void *userdata) ;
59 static void conn_write_cb(
struct bufferevent *buffer,
void *userdata);
60 static void conn_event_cb(
struct bufferevent *buffer,
short what,
void *userdata);
61 static void conn_cb(
ad_conn_t *conn,
int event);
62 static int call_hooks(
short event,
ad_conn_t *conn);
64 static void *get_userdata(
ad_conn_t *conn,
int index);
69 static bool initialized =
false;
109 if (server == NULL) {
114 server->
options = qhashtbl(0, 0);
115 server->
stats = qhashtbl(100, QHASHTBL_THREADSAFE);
116 server->
hooks = qlist(0);
122 DEBUG(
"Created a server object.");
132 DEBUG(
"Starting a server.");
135 set_undefined_options(server);
139 event_set_log_callback(libevent_log_cb);
141 event_enable_debug_mode();
148 struct sockaddr *sockaddr = NULL;
149 size_t sockaddr_len = 0;
150 if (addr[0] ==
'/') {
151 struct sockaddr_un unixaddr;
152 bzero((
void *) &unixaddr,
sizeof(
struct sockaddr_un));
153 if (strlen(addr) >=
sizeof(unixaddr.sun_path)) {
155 DEBUG(
"Too long unix socket name. '%s'", addr);
158 unixaddr.sun_family = AF_UNIX;
159 strcpy(unixaddr.sun_path, addr);
160 sockaddr = (
struct sockaddr *) &unixaddr;
161 sockaddr_len =
sizeof(unixaddr);
162 }
else if (strstr(addr,
":")) {
163 struct sockaddr_in6 ipv6addr;
164 bzero((
void *) &ipv6addr,
sizeof(
struct sockaddr_in6));
165 ipv6addr.sin6_family = AF_INET6;
166 ipv6addr.sin6_port = htons(port);
167 evutil_inet_pton(AF_INET6, addr, &ipv6addr.sin6_addr);
168 sockaddr = (
struct sockaddr *) &ipv6addr;
169 sockaddr_len =
sizeof(ipv6addr);
171 struct sockaddr_in ipv4addr;
172 bzero((
void *) &ipv4addr,
sizeof(
struct sockaddr_in));
173 ipv4addr.sin_family = AF_INET;
174 ipv4addr.sin_port = htons(port);
175 ipv4addr.sin_addr.s_addr =
176 (IS_EMPTY_STR(addr)) ? INADDR_ANY : inet_addr(addr);
177 sockaddr = (
struct sockaddr *) &ipv4addr;
178 sockaddr_len =
sizeof(ipv4addr);
185 server->
sslctx = init_ssl(cert_path, pkey_path);
186 if (server->
sslctx == NULL) {
187 ERROR(
"Couldn't load certificate file(%s) or private key file(%s).",
188 cert_path, pkey_path);
191 DEBUG(
"SSL Initialized.");
196 server->
evbase = event_base_new();
198 ERROR(
"Failed to create a new event base.");
204 int notifyfd = eventfd(0, 0);
205 server->
notify_buffer = bufferevent_socket_new(server->
evbase, notifyfd, BEV_OPT_CLOSE_ON_FREE);
206 bufferevent_setcb(server->
notify_buffer, NULL, notify_cb, NULL, server);
209 server->
listener = evconnlistener_new_bind(
210 server->
evbase, listener_cb, (
void *)server,
211 LEV_OPT_THREADSAFE | LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
213 sockaddr, sockaddr_len);
215 ERROR(
"Failed to bind on %s:%d", addr, port);
221 INFO(
"Listening on %s:%d%s", addr, port, ((server->
sslctx) ?
" (SSL)" :
""));
225 DEBUG(
"Launching server as a thread.")
226 server->
thread = NEW_OBJECT(pthread_t);
227 pthread_create(server->
thread, NULL, &server_loop, (
void *)server);
230 int *retval = server_loop(server);
231 exitstatus = *retval;
234 close_server(server);
251 DEBUG(
"Send loopexit notification.");
252 notify_loopexit(server);
256 close_server(server);
267 if (server == NULL)
return;
270 if (daemon && server->
thread) {
271 notify_loopexit(server);
273 close_server(server);
277 event_base_free(server->
evbase);
281 SSL_CTX_free(server->
sslctx);
293 qlist_t *tbl = server->
hooks;
295 while ((hook = tbl->popfirst(tbl, NULL))) {
296 if (hook->method) free(hook->method);
302 DEBUG(
"Server terminated.");
324 CRYPTO_cleanup_all_ex_data();
325 sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
349 return (value) ? atoi(value) : 0;
378 return server->
stats;
394 hook.method = (method) ? strdup(method) : NULL;
396 hook.userdata = userdata;
407 return set_userdata(conn, 0, userdata, free_cb);
416 return get_userdata(conn, 0);
430 return set_userdata(conn, 1, extra, free_cb);
437 return get_userdata(conn, 1);
449 char *prev = conn->
method;
453 conn->
method = strdup(method);
460 #ifndef _DOXYGEN_SKIP
469 return bufferevent_write(server->
notify_buffer, &x,
sizeof(uint64_t));
472 static void notify_cb(
struct bufferevent *buffer,
void *userdata) {
474 event_base_loopexit(server->
evbase, NULL);
475 DEBUG(
"Existing loop.");
478 static void *server_loop(
void *instance) {
481 int *retval = NEW_OBJECT(
int);
483 event_base_loop(server->
evbase, 0);
484 DEBUG(
"Loop finished");
485 *retval = (event_base_got_break(server->
evbase)) ? -1 : 0;
491 DEBUG(
"Closing server.");
499 evconnlistener_free(server->
listener);
505 DEBUG(
"Waiting server's last loop to finish.");
506 pthread_join(*(server->
thread), &retval);
511 INFO(
"Server closed.");
514 static void libevent_log_cb(
int severity,
const char *msg) {
516 case _EVENT_LOG_MSG : {
520 case _EVENT_LOG_WARN : {
524 case _EVENT_LOG_ERR : {
536 static int set_undefined_options(
ad_server_t *server) {
539 for (
int i = 0; ! IS_EMPTY_STR(default_options[i][0]); i++) {
549 static SSL_CTX *init_ssl(
const char *cert_path,
const char *pkey_path) {
551 SSL_load_error_strings();
555 SSL_CTX *sslctx = SSL_CTX_new(SSLv23_server_method());
556 if (! SSL_CTX_use_certificate_file(sslctx, cert_path, SSL_FILETYPE_PEM) ||
557 ! SSL_CTX_use_PrivateKey_file(sslctx, pkey_path, SSL_FILETYPE_PEM)) {
564 static void listener_cb(
struct evconnlistener *listener, evutil_socket_t socket,
565 struct sockaddr *sockaddr,
int socklen,
void *userdata) {
566 DEBUG(
"New connection.");
570 struct bufferevent *buffer = NULL;
572 buffer = bufferevent_openssl_socket_new(server->
evbase, socket,
574 BUFFEREVENT_SSL_ACCEPTING,
575 BEV_OPT_CLOSE_ON_FREE);
577 buffer = bufferevent_socket_new(server->
evbase, socket, BEV_OPT_CLOSE_ON_FREE);
579 if (buffer == NULL)
goto error;
585 bzero((
void *)&tm,
sizeof(
struct timeval));
587 bufferevent_set_timeouts(buffer, &tm, NULL);
591 void *conn = conn_new(server, buffer);
592 if (! conn)
goto error;
597 if (buffer) bufferevent_free(buffer);
598 ERROR(
"Failed to create a connection handler.");
599 event_base_loopbreak(server->
evbase);
604 if (server == NULL || buffer == NULL) {
610 if (conn == NULL)
return NULL;
615 conn->
in = bufferevent_get_input(buffer);
616 conn->
out = bufferevent_get_output(buffer);
620 bufferevent_setcb(buffer, conn_read_cb, conn_write_cb, conn_event_cb, (
void *)conn);
621 bufferevent_setwatermark(buffer, EV_WRITE, 0, 0);
622 bufferevent_enable(buffer, EV_WRITE);
623 bufferevent_enable(buffer, EV_READ);
631 static void conn_reset(
ad_conn_t *conn) {
639 WARN(
"Found unreleased userdata.");
659 int sslerr = bufferevent_get_openssl_error(conn->
buffer);
662 ERR_error_string_n(sslerr, errmsg,
sizeof(errmsg));
663 ERROR(
"SSL %s (err:%d)", errmsg, sslerr);
666 bufferevent_free(conn->
buffer);
672 #define DRAIN_EVBUFFER(b) evbuffer_drain(b, evbuffer_get_length(b))
673 static void conn_read_cb(
struct bufferevent *buffer,
void *userdata) {
679 static void conn_write_cb(
struct bufferevent *buffer,
void *userdata) {
685 static void conn_event_cb(
struct bufferevent *buffer,
short what,
void *userdata) {
686 DEBUG(
"event_cb 0x%x", what);
689 if (what & BEV_EVENT_EOF || what & BEV_EVENT_ERROR || what & BEV_EVENT_TIMEOUT) {
695 static void conn_cb(
ad_conn_t *conn,
int event) {
696 DEBUG(
"conn_cb: status:0x%x, event:0x%x", conn->
status, event)
698 int status = call_hooks(event, conn);
713 DEBUG(
"Draining in-buffer. %d", conn->
status);
714 DRAIN_EVBUFFER(conn->
in);
719 if (evbuffer_get_length(conn->
out) <= 0) {
721 call_hooks(newevent, conn);
723 DEBUG(
"Connection closed.");
729 static int call_hooks(
short event,
ad_conn_t *conn) {
730 DEBUG(
"call_hooks: event 0x%x", event);
734 bzero((
void *)&obj,
sizeof(qdlobj_t));
735 while (hooks->getnext(hooks, &obj,
false) ==
true) {
738 if (hook->method && conn->
method && strcmp(hook->method, conn->
method)) {
741 int status = hook->cb(event, conn, hook->
userdata);
742 if (status !=
AD_OK) {
752 conn->
userdata[index] = (
void *)userdata;
757 static void *get_userdata(
ad_conn_t *conn,
int index) {