libasyncd
ad_server.c
Go to the documentation of this file.
1 /******************************************************************************
2  * libasyncd
3  *
4  * Copyright (c) 2014 Seungyoung Kim.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *****************************************************************************/
28 
29 /**
30  * Main core logic of the server implementation.
31  *
32  * @file ad_server.c
33  */
34 
35 #include <stdbool.h>
36 #include <stdlib.h>
37 #include <strings.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <errno.h>
41 #include <assert.h>
42 #include <sys/un.h>
43 #include <sys/socket.h>
44 #include <sys/eventfd.h>
45 #include <event2/event.h>
46 #include <event2/bufferevent.h>
47 #include <event2/bufferevent_ssl.h>
48 #include <event2/thread.h>
49 #include <event2/listener.h>
50 #include <openssl/ssl.h>
51 #include <openssl/rand.h>
52 #include <openssl/conf.h>
53 #include <openssl/engine.h>
54 #include <openssl/err.h>
55 #include "macro.h"
56 #include "qlibc/qlibc.h"
57 #include "ad_server.h"
58 
59 #ifndef _DOXYGEN_SKIP
60 /*
61  * User callback hook container.
62  */
63 typedef struct ad_hook_s ad_hook_t;
64 struct ad_hook_s {
65  char *method;
66  ad_callback cb;
67  void *userdata;
68 };
69 
70 /*
71  * Local functions.
72  */
73 static int notify_loopexit(ad_server_t *server);
74 static void notify_cb(struct bufferevent *buffer, void *userdata);
75 static void *server_loop(void *instance);
76 static void close_server(ad_server_t *server);
77 static void libevent_log_cb(int severity, const char *msg);
78 static int set_undefined_options(ad_server_t *server);
79 static SSL_CTX *init_ssl(const char *cert_path, const char *pkey_path);
80 static void listener_cb(struct evconnlistener *listener,
81  evutil_socket_t evsocket, struct sockaddr *sockaddr,
82  int socklen, void *userdata);
83 static ad_conn_t *conn_new(ad_server_t *server, struct bufferevent *buffer);
84 static void conn_reset(ad_conn_t *conn);
85 static void conn_free(ad_conn_t *conn);
86 static void conn_read_cb(struct bufferevent *buffer, void *userdata) ;
87 static void conn_write_cb(struct bufferevent *buffer, void *userdata);
88 static void conn_event_cb(struct bufferevent *buffer, short what, void *userdata);
89 static void conn_cb(ad_conn_t *conn, int event);
90 static int call_hooks(short event, ad_conn_t *conn);
91 static void *set_userdata(ad_conn_t *conn, int index, const void *userdata, ad_userdata_free_cb free_cb);
92 static void *get_userdata(ad_conn_t *conn, int index);
93 
94 /*
95  * Local variables.
96  */
97 static bool initialized = false;
98 #endif
99 
100 /*
101  * Global variables.
102  */
104 
105 /**
106  * Set debug output level.
107  *
108  * @param debug_level debug output level. 0 to disable.
109  *
110  * @return previous debug level.
111  *
112  * @note
113  * debug_level:
114  * AD_LOG_DISABLE
115  * AD_LOG_ERROR
116  * AD_LOG_WARN (default)
117  * AD_LOG_INFO
118  * AD_LOG_DEBUG
119  * AD_LOG_DEBUG2
120  */
121 enum ad_log_e ad_log_level(enum ad_log_e log_level) {
122  int prev = _ad_log_level;
123  _ad_log_level = log_level;
124  return prev;
125 }
126 
127 /**
128  * Create a server object.
129  */
131  if (initialized) {
132  initialized = true;
133  //evthread_use_pthreads();
134  }
135 
136  ad_server_t *server = NEW_OBJECT(ad_server_t);
137  if (server == NULL) {
138  return NULL;
139  }
140 
141  // Initialize instance.
142  server->options = qhashtbl(0, 0);
143  server->stats = qhashtbl(100, QHASHTBL_THREADSAFE);
144  server->hooks = qlist(0);
145  if (server->options == NULL || server->stats == NULL || server->hooks == NULL) {
146  ad_server_free(server);
147  return NULL;
148  }
149 
150  DEBUG("Created a server object.");
151  return server;
152 }
153 
154 /**
155  * Start server.
156  *
157  * @return 0 if successful, otherwise -1.
158  */
160  DEBUG("Starting a server.");
161 
162  // Set default options that were not set by user..
163  set_undefined_options(server);
164 
165  // Hookup libevent's log message.
166  if (_ad_log_level >= AD_LOG_DEBUG) {
167  event_set_log_callback(libevent_log_cb);
168  if (_ad_log_level >= AD_LOG_DEBUG2) {
169  event_enable_debug_mode();
170  }
171  }
172 
173  // Parse addr
174  int port = ad_server_get_option_int(server, "server.port");
175  char *addr = ad_server_get_option(server, "server.addr");
176  struct sockaddr *sockaddr = NULL;
177  size_t sockaddr_len = 0;
178  if (addr[0] == '/') { // Unix socket.
179  struct sockaddr_un unixaddr;
180  bzero((void *) &unixaddr, sizeof(struct sockaddr_un));
181  if (strlen(addr) >= sizeof(unixaddr.sun_path)) {
182  errno = EINVAL;
183  DEBUG("Too long unix socket name. '%s'", addr);
184  return -1;
185  }
186  unixaddr.sun_family = AF_UNIX;
187  strcpy(unixaddr.sun_path, addr); // no need of strncpy()
188  sockaddr = (struct sockaddr *) &unixaddr;
189  sockaddr_len = sizeof(unixaddr);
190  } else if (strstr(addr, ":")) { // IPv6
191  struct sockaddr_in6 ipv6addr;
192  bzero((void *) &ipv6addr, sizeof(struct sockaddr_in6));
193  ipv6addr.sin6_family = AF_INET6;
194  ipv6addr.sin6_port = htons(port);
195  evutil_inet_pton(AF_INET6, addr, &ipv6addr.sin6_addr);
196  sockaddr = (struct sockaddr *) &ipv6addr;
197  sockaddr_len = sizeof(ipv6addr);
198  } else { // IPv4
199  struct sockaddr_in ipv4addr;
200  bzero((void *) &ipv4addr, sizeof(struct sockaddr_in));
201  ipv4addr.sin_family = AF_INET;
202  ipv4addr.sin_port = htons(port);
203  ipv4addr.sin_addr.s_addr =
204  (IS_EMPTY_STR(addr)) ? INADDR_ANY : inet_addr(addr);
205  sockaddr = (struct sockaddr *) &ipv4addr;
206  sockaddr_len = sizeof(ipv4addr);
207  }
208 
209  // SSL
210  if (!server->sslctx && ad_server_get_option_int(server, "server.enable_ssl")) {
211  char *cert_path = ad_server_get_option(server, "server.ssl_cert");
212  char *pkey_path = ad_server_get_option(server, "server.ssl_pkey");
213  server->sslctx = init_ssl(cert_path, pkey_path);
214  if (server->sslctx == NULL) {
215  ERROR("Couldn't load certificate file(%s) or private key file(%s).",
216  cert_path, pkey_path);
217  return -1;
218  }
219  DEBUG("SSL Initialized.");
220  }
221 
222  // Bind
223  if (! server->evbase) {
224  server->evbase = event_base_new();
225  if (! server->evbase) {
226  ERROR("Failed to create a new event base.");
227  return -1;
228  }
229  }
230 
231  // Create a eventfd for notification channel.
232  int notifyfd = eventfd(0, 0);
233  server->notify_buffer = bufferevent_socket_new(server->evbase, notifyfd, BEV_OPT_CLOSE_ON_FREE);
234  bufferevent_setcb(server->notify_buffer, NULL, notify_cb, NULL, server);
235 
236  if (! server->listener) {
237  server->listener = evconnlistener_new_bind(
238  server->evbase, listener_cb, (void *)server,
239  LEV_OPT_THREADSAFE | LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
240  ad_server_get_option_int(server, "server.backlog"),
241  sockaddr, sockaddr_len);
242  if (! server->listener) {
243  ERROR("Failed to bind on %s:%d", addr, port);
244  return -1;
245  }
246  }
247 
248  // Listen
249  INFO("Listening on %s:%d%s", addr, port, ((server->sslctx) ? " (SSL)" : ""));
250 
251  int exitstatus = 0;
252  if (ad_server_get_option_int(server, "server.thread")) {
253  DEBUG("Launching server as a thread.")
254  server->thread = NEW_OBJECT(pthread_t);
255  pthread_create(server->thread, NULL, &server_loop, (void *)server);
256  //pthread_detach(server->thread);
257  } else {
258  int *retval = server_loop(server);
259  exitstatus = *retval;
260  free(retval);
261 
262  close_server(server);
263  if (ad_server_get_option_int(server, "server.free_on_stop")) {
264  ad_server_free(server);
265  }
266  }
267 
268  return exitstatus;
269 }
270 
271 /**
272  * Stop server.
273  *
274  * This call is be used to stop a server from different thread.
275  *
276  * @return 0 if successful, otherwise -1.
277  */
279  DEBUG("Send loopexit notification.");
280  notify_loopexit(server);
281  sleep(1);
282 
283  if (ad_server_get_option_int(server, "server.thread")) {
284  close_server(server);
285  if (ad_server_get_option_int(server, "server.free_on_stop")) {
286  ad_server_free(server);
287  }
288  }
289 }
290 
291 /**
292  * Release server object and all the resources.
293  */
295  if (server == NULL) return;
296 
297  int thread = ad_server_get_option_int(server, "server.thread");
298  if (thread && server->thread) {
299  notify_loopexit(server);
300  sleep(1);
301  close_server(server);
302  }
303 
304  if (server->evbase) {
305  event_base_free(server->evbase);
306  }
307 
308  if (server->sslctx) {
309  SSL_CTX_free(server->sslctx);
310  ERR_clear_error();
311  ERR_remove_state(0);
312  }
313 
314  if (server->options) {
315  server->options->free(server->options);
316  }
317  if (server->stats) {
318  server->stats->free(server->stats);
319  }
320  if (server->hooks) {
321  qlist_t *tbl = server->hooks;
322  ad_hook_t *hook;
323  while ((hook = tbl->popfirst(tbl, NULL))) {
324  if (hook->method) free(hook->method);
325  free(hook);
326  }
327  server->hooks->free(server->hooks);
328  }
329  free(server);
330  DEBUG("Server terminated.");
331 }
332 
333 /**
334  * Clean up all the global objects.
335  *
336  * This will make memory-leak checkers happy.
337  * There are globally shared resources in libevent and openssl and
338  * it's usually not a problem since they don't grow but having these
339  * can confuse some debugging tools into thinking as memory leak.
340  * If you need to make sure that libasyncd has released all internal
341  * library-global data structures, call this.
342  */
344  // Libevent related.
345  //libevent_global_shutdown(); // From libevent v2.1
346 
347  // OpenSSL related.
348  ENGINE_cleanup();
349  CONF_modules_free();
350  ERR_free_strings();
351  EVP_cleanup();
352  CRYPTO_cleanup_all_ex_data();
353  sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
354 }
355 
356 /**
357  * Set server option.
358  *
359  * @see AD_SERVER_OPTIONS
360  */
361 void ad_server_set_option(ad_server_t *server, const char *key, const char *value) {
362  server->options->putstr(server->options, key, value);
363 }
364 
365 /**
366  * Retrieve server option.
367  */
368 char *ad_server_get_option(ad_server_t *server, const char *key) {
369  return server->options->getstr(server->options, key, false);
370 }
371 
372 /**
373  * Retrieve server option in integer format.
374  */
375 int ad_server_get_option_int(ad_server_t *server, const char *key) {
376  char *value = ad_server_get_option(server, key);
377  return (value) ? atoi(value) : 0;
378 }
379 
380 /**
381  * Helper method for creating minimal OpenSSL SSL_CTX object.
382  *
383  * @param cert_path path to a PEM encoded certificate file
384  * @param pkey_path path to a PEM encoded private key file
385  *
386  * @return newly allocated SSL_CTX object or NULL on failure
387  *
388  * @note
389  * This function initializes SSL_CTX with minimum default with
390  * "SSLv23_server_method" which will make the server understand
391  * SSLv2, SSLv3, and TLSv1 protocol.
392  *
393  * @see ad_server_set_ssl_ctx()
394  */
395 SSL_CTX *ad_server_ssl_ctx_create_simple(const char *cert_path,
396  const char *pkey_path) {
397 
398  SSL_CTX *sslctx = SSL_CTX_new(SSLv23_server_method());
399  if (! SSL_CTX_use_certificate_file(sslctx, cert_path, SSL_FILETYPE_PEM) ||
400  ! SSL_CTX_use_PrivateKey_file(sslctx, pkey_path, SSL_FILETYPE_PEM)) {
401 
402  ERROR("Couldn't load certificate file(%s) or private key file(%s).",
403  cert_path, pkey_path);
404 
405  return NULL;
406  }
407 
408  return sslctx;
409 }
410 
411 /**
412  * Attach OpenSSL SSL_CTX to the server.
413  *
414  * @param server a valid server instance
415  * @param sslctx allocated and configured SSL_CTX object
416  *
417  * @note
418  * This function attached SSL_CTX object to the server causing it to
419  * communicate over SSL. Use ad_server_ssl_ctx_create_simple() to
420  * quickly create a simple SSL_CTX object or make your own with OpenSSL
421  * directly. This function must never be called when ad_server is running.
422  *
423  * @see ad_server_ssl_ctx_create_simple()
424  */
425 void ad_server_set_ssl_ctx(ad_server_t *server, SSL_CTX *sslctx) {
426 
427  if (server->sslctx) {
428  SSL_CTX_free(server->sslctx);
429  }
430 
431  server->sslctx = sslctx;
432 }
433 
434 /**
435  * Get OpenSSL SSL_CTX object.
436  *
437  * @param server a valid server instance
438  * @return SSL_CTX object, NULL if not enabled.
439  *
440  * @note
441  * As a general rule the returned SSL_CTX object must not be modified
442  * while server is running as it may cause unpredictable results.
443  * However, it is safe to use it for reading SSL statistics.
444  */
446  return server->sslctx;
447 }
448 
449 /**
450  * Return internal statistic counter map.
451  */
452 qhashtbl_t *ad_server_get_stats(ad_server_t *server, const char *key) {
453  return server->stats;
454 }
455 
456 /**
457  * Register user hook.
458  */
459 void ad_server_register_hook(ad_server_t *server, ad_callback cb, void *userdata) {
460  ad_server_register_hook_on_method(server, NULL, cb, userdata);
461 }
462 
463 /**
464  * Register user hook on method name.
465  */
466 void ad_server_register_hook_on_method(ad_server_t *server, const char *method, ad_callback cb, void *userdata) {
467  ad_hook_t hook;
468  bzero((void *)&hook, sizeof(ad_hook_t));
469  hook.method = (method) ? strdup(method) : NULL;
470  hook.cb = cb;
471  hook.userdata = userdata;
472 
473  server->hooks->addlast(server->hooks, (void *)&hook, sizeof(ad_hook_t));
474 }
475 
476 /**
477  * Attach userdata into the connection.
478  *
479  * @return previous userdata;
480  */
481 void *ad_conn_set_userdata(ad_conn_t *conn, const void *userdata, ad_userdata_free_cb free_cb) {
482  return set_userdata(conn, 0, userdata, free_cb);
483 }
484 
485 /**
486  * Get userdata attached in the connection.
487  *
488  * @return previous userdata;
489  */
491  return get_userdata(conn, 0);
492 }
493 
494 /**
495  * Set extra userdata into the connection.
496  *
497  * @return previous userdata;
498  *
499  * @note
500  * Extra userdata is for default protocol handler such as ad_http_handler to
501  * provide higher abstraction. End users should always use only ad_conn_set_userdata()
502  * to avoid any conflict with default handlers.
503  */
504 void *ad_conn_set_extra(ad_conn_t *conn, const void *extra, ad_userdata_free_cb free_cb) {
505  return set_userdata(conn, 1, extra, free_cb);
506 }
507 
508 /**
509  * Get extra userdata attached in this connection.
510  */
512  return get_userdata(conn, 1);
513 }
514 
515 /**
516  * Set method name on this connection.
517  *
518  * Once the method name is set, hooks registered by ad_server_register_hook_on_method()
519  * will be called if method name is matching as registered.
520  *
521  * @see ad_server_register_hook_on_method()
522  */
523 char *ad_conn_set_method(ad_conn_t *conn, char *method) {
524  char *prev = conn->method;
525  if (conn->method) {
526  free(conn->method);
527  }
528  conn->method = strdup(method);
529  return prev;
530 }
531 
532 /******************************************************************************
533  * Private internal functions.
534  *****************************************************************************/
535 #ifndef _DOXYGEN_SKIP
536 
537 /**
538  * If there's no event, loopbreak or loopexit call won't work until one more
539  * event arrived. So we use eventfd as a internal notification channel to let
540  * server get out of the loop without waiting for an event.
541  */
542 static int notify_loopexit(ad_server_t *server) {
543  uint64_t x = 0;
544  return bufferevent_write(server->notify_buffer, &x, sizeof(uint64_t));
545 }
546 
547 static void notify_cb(struct bufferevent *buffer, void *userdata) {
548  ad_server_t *server = (ad_server_t *)userdata;
549  event_base_loopexit(server->evbase, NULL);
550  DEBUG("Existing loop.");
551 }
552 
553 static void *server_loop(void *instance) {
554  ad_server_t *server = (ad_server_t *)instance;
555 
556  int *retval = NEW_OBJECT(int);
557  DEBUG("Loop start");
558  event_base_loop(server->evbase, 0);
559  DEBUG("Loop finished");
560  *retval = (event_base_got_break(server->evbase)) ? -1 : 0;
561 
562  return retval;
563 }
564 
565 static void close_server(ad_server_t *server) {
566  DEBUG("Closing server.");
567 
568  if (server->notify_buffer) {
569  bufferevent_free(server->notify_buffer);
570  server->notify_buffer = NULL;
571  }
572 
573  if (server->listener) {
574  evconnlistener_free(server->listener);
575  server->listener = NULL;
576  }
577 
578  if (server->thread) {
579  void *retval = NULL;
580  DEBUG("Waiting server's last loop to finish.");
581  pthread_join(*(server->thread), &retval);
582  free(retval);
583  free(server->thread);
584  server->thread = NULL;
585  }
586  INFO("Server closed.");
587 }
588 
589 static void libevent_log_cb(int severity, const char *msg) {
590  switch(severity) {
591  case _EVENT_LOG_MSG : {
592  INFO("%s", msg);
593  break;
594  }
595  case _EVENT_LOG_WARN : {
596  WARN("%s", msg);
597  break;
598  }
599  case _EVENT_LOG_ERR : {
600  ERROR("%s", msg);
601  break;
602  }
603  default : {
604  DEBUG("%s", msg);
605  break;
606  }
607  }
608 }
609 
610 // Set default options that were not set by user..
611 static int set_undefined_options(ad_server_t *server) {
612  int newentries = 0;
613  char *default_options[][2] = AD_SERVER_OPTIONS;
614  for (int i = 0; ! IS_EMPTY_STR(default_options[i][0]); i++) {
615  if (! ad_server_get_option(server, default_options[i][0])) {
616  ad_server_set_option(server, default_options[i][0], default_options[i][1]);
617  newentries++;
618  }
619  DEBUG("%s=%s", default_options[i][0], ad_server_get_option(server, default_options[i][0]));
620  }
621  return newentries;
622 }
623 
624 static SSL_CTX *init_ssl(const char *cert_path, const char *pkey_path) {
625  SSL_CTX *sslctx = SSL_CTX_new(SSLv23_server_method());
626  if (! SSL_CTX_use_certificate_file(sslctx, cert_path, SSL_FILETYPE_PEM) ||
627  ! SSL_CTX_use_PrivateKey_file(sslctx, pkey_path, SSL_FILETYPE_PEM)) {
628  return NULL;
629  }
630  return sslctx;
631 }
632 
633 static void listener_cb(struct evconnlistener *listener, evutil_socket_t socket,
634  struct sockaddr *sockaddr, int socklen, void *userdata) {
635  DEBUG("New connection.");
636  ad_server_t *server = (ad_server_t *)userdata;
637 
638  // Create a new buffer.
639  struct bufferevent *buffer = NULL;
640  if (server->sslctx) {
641  buffer = bufferevent_openssl_socket_new(server->evbase, socket,
642  SSL_new(server->sslctx),
643  BUFFEREVENT_SSL_ACCEPTING,
644  BEV_OPT_CLOSE_ON_FREE);
645  } else {
646  buffer = bufferevent_socket_new(server->evbase, socket, BEV_OPT_CLOSE_ON_FREE);
647  }
648  if (buffer == NULL) goto error;
649 
650  // Set read timeout.
651  int timeout = ad_server_get_option_int(server, "server.timeout");
652  if (timeout > 0) {
653  struct timeval tm;
654  bzero((void *)&tm, sizeof(struct timeval));
655  tm.tv_sec = timeout;
656  bufferevent_set_timeouts(buffer, &tm, NULL);
657  }
658 
659  // Create a connection.
660  void *conn = conn_new(server, buffer);
661  if (! conn) goto error;
662 
663  return;
664 
665  error:
666  if (buffer) bufferevent_free(buffer);
667  ERROR("Failed to create a connection handler.");
668  event_base_loopbreak(server->evbase);
669  server->errcode = ENOMEM;
670 }
671 
672 static ad_conn_t *conn_new(ad_server_t *server, struct bufferevent *buffer) {
673  if (server == NULL || buffer == NULL) {
674  return NULL;
675  }
676 
677  // Create a new connection container.
678  ad_conn_t *conn = NEW_OBJECT(ad_conn_t);
679  if (conn == NULL) return NULL;
680 
681  // Initialize with default values.
682  conn->server = server;
683  conn->buffer = buffer;
684  conn->in = bufferevent_get_input(buffer);
685  conn->out = bufferevent_get_output(buffer);
686  conn_reset(conn);
687 
688  // Bind callback
689  bufferevent_setcb(buffer, conn_read_cb, conn_write_cb, conn_event_cb, (void *)conn);
690  bufferevent_setwatermark(buffer, EV_WRITE, 0, 0);
691  bufferevent_enable(buffer, EV_WRITE);
692  bufferevent_enable(buffer, EV_READ);
693 
694  // Run callbacks with AD_EVENT_INIT event.
695  conn->status = call_hooks(AD_EVENT_INIT | AD_EVENT_WRITE, conn);
696 
697  return conn;
698 }
699 
700 static void conn_reset(ad_conn_t *conn) {
701  conn->status = AD_OK;
702 
703  for(int i = 0; i < AD_NUM_USERDATA; i++) {
704  if (conn->userdata[i]) {
705  if (conn->userdata_free_cb[i] != NULL) {
706  conn->userdata_free_cb[i](conn, conn->userdata[i]);
707  } else {
708  WARN("Found unreleased userdata.");
709  }
710  conn->userdata[i] = NULL;
711  }
712  }
713 
714  if (conn->method) {
715  free(conn->method);
716  conn->method = NULL;
717  }
718 }
719 
720 static void conn_free(ad_conn_t *conn) {
721  if (conn) {
722  if (conn->status != AD_CLOSE) {
723  call_hooks(AD_EVENT_CLOSE | AD_EVENT_SHUTDOWN , conn);
724  }
725  conn_reset(conn);
726  if (conn->buffer) {
727  if (conn->server->sslctx) {
728  int sslerr = bufferevent_get_openssl_error(conn->buffer);
729  if (sslerr) {
730  char errmsg[256];
731  ERR_error_string_n(sslerr, errmsg, sizeof(errmsg));
732  ERROR("SSL %s (err:%d)", errmsg, sslerr);
733  }
734  }
735  bufferevent_free(conn->buffer);
736  }
737  free(conn);
738  }
739 }
740 
741 #define DRAIN_EVBUFFER(b) evbuffer_drain(b, evbuffer_get_length(b))
742 static void conn_read_cb(struct bufferevent *buffer, void *userdata) {
743  DEBUG("read_cb");
744  ad_conn_t *conn = userdata;
745  conn_cb(conn, AD_EVENT_READ);
746 }
747 
748 static void conn_write_cb(struct bufferevent *buffer, void *userdata) {
749  DEBUG("write_cb");
750  ad_conn_t *conn = userdata;
751  conn_cb(conn, AD_EVENT_WRITE);
752 }
753 
754 static void conn_event_cb(struct bufferevent *buffer, short what, void *userdata) {
755  DEBUG("event_cb 0x%x", what);
756  ad_conn_t *conn = userdata;
757 
758  if (what & BEV_EVENT_EOF || what & BEV_EVENT_ERROR || what & BEV_EVENT_TIMEOUT) {
759  conn->status = AD_CLOSE;
760  conn_cb(conn, AD_EVENT_CLOSE | ((what & BEV_EVENT_TIMEOUT) ? AD_EVENT_TIMEOUT : 0));
761  }
762 }
763 
764 static void conn_cb(ad_conn_t *conn, int event) {
765  DEBUG("conn_cb: status:0x%x, event:0x%x", conn->status, event)
766  if(conn->status == AD_OK || conn->status == AD_TAKEOVER) {
767  int status = call_hooks(event, conn);
768  // Update status only when it's higher then before.
769  if (! (conn->status == AD_CLOSE || (conn->status == AD_DONE && conn->status >= status))) {
770  conn->status = status;
771  }
772  }
773 
774  if(conn->status == AD_DONE) {
775  if (ad_server_get_option_int(conn->server, "server.request_pipelining")) {
776  call_hooks(AD_EVENT_CLOSE , conn);
777  conn_reset(conn);
778  call_hooks(AD_EVENT_INIT , conn);
779  } else {
780  // Do nothing but drain input buffer.
781  if (event == AD_EVENT_READ) {
782  DEBUG("Draining in-buffer. %d", conn->status);
783  DRAIN_EVBUFFER(conn->in);
784  }
785  }
786  return;
787  } else if(conn->status == AD_CLOSE) {
788  if (evbuffer_get_length(conn->out) <= 0) {
789  int newevent = (event & AD_EVENT_CLOSE) ? event : AD_EVENT_CLOSE;
790  call_hooks(newevent, conn);
791  conn_free(conn);
792  DEBUG("Connection closed.");
793  return;
794  }
795  }
796 }
797 
798 static int call_hooks(short event, ad_conn_t *conn) {
799  DEBUG("call_hooks: event 0x%x", event);
800  qlist_t *hooks = conn->server->hooks;
801 
802  qdlobj_t obj;
803  bzero((void *)&obj, sizeof(qdlobj_t));
804  while (hooks->getnext(hooks, &obj, false) == true) {
805  ad_hook_t *hook = (ad_hook_t *)obj.data;
806  if (hook->cb) {
807  if (hook->method && conn->method && strcmp(hook->method, conn->method)) {
808  continue;
809  }
810  int status = hook->cb(event, conn, hook->userdata);
811  if (status != AD_OK) {
812  return status;
813  }
814  }
815  }
816  return AD_OK;
817 }
818 
819 static void *set_userdata(ad_conn_t *conn, int index, const void *userdata, ad_userdata_free_cb free_cb) {
820  void *prev = conn->userdata;
821  conn->userdata[index] = (void *)userdata;
822  conn->userdata_free_cb[index] = free_cb;
823  return prev;
824 }
825 
826 static void *get_userdata(ad_conn_t *conn, int index) {
827  return conn->userdata[index];
828 }
829 
830 #endif // _DOXYGEN_SKIP
void ad_server_register_hook(ad_server_t *server, ad_callback cb, void *userdata)
Register user hook.
Definition: ad_server.c:459
struct bufferevent * notify_buffer
Definition: ad_server.h:153
int ad_server_start(ad_server_t *server)
Start server.
Definition: ad_server.c:159
SSL_CTX * ad_server_get_ssl_ctx(ad_server_t *server)
Get OpenSSL SSL_CTX object.
Definition: ad_server.c:445
SSL_CTX * ad_server_ssl_ctx_create_simple(const char *cert_path, const char *pkey_path)
Helper method for creating minimal OpenSSL SSL_CTX object.
Definition: ad_server.c:395
int status
Definition: ad_server.h:164
void ad_server_free(ad_server_t *server)
Release server object and all the resources.
Definition: ad_server.c:294
qhashtbl_t * stats
Definition: ad_server.h:147
struct bufferevent * buffer
Definition: ad_server.h:161
#define AD_EVENT_WRITE
Definition: ad_server.h:125
SSL_CTX * sslctx
Definition: ad_server.h:151
#define AD_EVENT_TIMEOUT
Definition: ad_server.h:127
#define AD_NUM_USERDATA
Defaults.
Definition: ad_server.h:133
#define AD_EVENT_SHUTDOWN
Definition: ad_server.h:128
char * ad_server_get_option(ad_server_t *server, const char *key)
Retrieve server option.
Definition: ad_server.c:368
#define AD_CLOSE
Definition: ad_server.h:60
struct evbuffer * out
Definition: ad_server.h:163
#define AD_EVENT_CLOSE
Definition: ad_server.h:126
#define AD_SERVER_OPTIONS
Server option names and default values.
Definition: ad_server.h:81
struct evbuffer * in
Definition: ad_server.h:162
ad_log_e
Definition: ad_server.h:65
void ad_server_set_option(ad_server_t *server, const char *key, const char *value)
Set server option.
Definition: ad_server.c:361
ad_server_t * server
Definition: ad_server.h:160
struct evconnlistener * listener
Definition: ad_server.h:149
int ad_server_get_option_int(ad_server_t *server, const char *key)
Retrieve server option in integer format.
Definition: ad_server.c:375
char * method
Definition: ad_server.h:168
ad_userdata_free_cb userdata_free_cb[2]
Definition: ad_server.h:167
qhashtbl_t * options
Definition: ad_server.h:146
ad_server_t * ad_server_new(void)
Create a server object.
Definition: ad_server.c:130
void(* ad_userdata_free_cb)(ad_conn_t *conn, void *userdata)
Definition: ad_server.h:118
Connection structure.
Definition: ad_server.h:159
char * ad_conn_set_method(ad_conn_t *conn, char *method)
Set method name on this connection.
Definition: ad_server.c:523
#define AD_EVENT_INIT
Event types.
Definition: ad_server.h:123
#define AD_EVENT_READ
Definition: ad_server.h:124
int _ad_log_level
Definition: ad_server.c:103
void * ad_conn_set_userdata(ad_conn_t *conn, const void *userdata, ad_userdata_free_cb free_cb)
Attach userdata into the connection.
Definition: ad_server.c:481
void * userdata[2]
Definition: ad_server.h:166
#define AD_TAKEOVER
Definition: ad_server.h:58
ad_server header file
void * ad_conn_set_extra(ad_conn_t *conn, const void *extra, ad_userdata_free_cb free_cb)
Set extra userdata into the connection.
Definition: ad_server.c:504
void ad_server_register_hook_on_method(ad_server_t *server, const char *method, ad_callback cb, void *userdata)
Register user hook on method name.
Definition: ad_server.c:466
void ad_server_set_ssl_ctx(ad_server_t *server, SSL_CTX *sslctx)
Attach OpenSSL SSL_CTX to the server.
Definition: ad_server.c:425
qhashtbl_t * ad_server_get_stats(ad_server_t *server, const char *key)
Return internal statistic counter map.
Definition: ad_server.c:452
enum ad_log_e ad_log_level(enum ad_log_e log_level)
Set debug output level.
Definition: ad_server.c:121
int(* ad_callback)(short event, ad_conn_t *conn, void *userdata)
User callback(hook) prototype.
Definition: ad_server.h:117
qlist_t * hooks
Definition: ad_server.h:148
#define AD_OK
Definition: ad_server.h:57
void * ad_conn_get_extra(ad_conn_t *conn)
Get extra userdata attached in this connection.
Definition: ad_server.c:511
pthread_t * thread
Definition: ad_server.h:144
Server info container.
Definition: ad_server.h:142
#define AD_DONE
Definition: ad_server.h:59
struct event_base * evbase
Definition: ad_server.h:150
void ad_server_global_free(void)
Clean up all the global objects.
Definition: ad_server.c:343
void ad_server_stop(ad_server_t *server)
Stop server.
Definition: ad_server.c:278
void * ad_conn_get_userdata(ad_conn_t *conn)
Get userdata attached in the connection.
Definition: ad_server.c:490