Embeddable Event-based Asynchronous Message/HTTP Server library for C/C++

Overview

libasyncd

Embeddable Event-based Asynchronous Message/HTTP Server library for C/C++.

What is libasyncd?

Libasyncd is an embeddable event-driven asynchronous message server for C/C++. It supports HTTP protocol by default and you can add your own protocol handler(hook) to build your own high performance server.

Asynchronous way of programming can easily go quite complicated since you need to handle every thing in non-blocking way. So the goal of Libasyncd project is to make a flexible and fast asynchronous server framework with nice abstraction that can cut down the complexity.

Why libasyncd?

libasyncd is a light-weight single-threaded asynchronous RPC server. It is efficient especially when server needs to handle a large number of concurrent connections where connection-per-thread or connection-per-process model is not appropriate to consider.

  • Stands as a generic event-based server library. (single-thread)
  • Embeddable library module - you write main().
  • Pluggable protocol handlers.
  • Complete HTTP protocol handler. (support chunked transfer-encoding)
  • Support request pipelining.
  • Support multiple hooks.
  • Support SSL - Just flip the switch on.
  • Support IPv4, IPv6 and Unix Socket.
  • Simple to use - Check out examples.

Compile & Install.

$ git clone https://github.com/wolkykim/libasyncd
$ cd libasyncd
$ ./configure
# If using system wide install of qlibc, add QLIBC=system to make install command
$ make install

API Reference

"Hello World", Asynchronous Socket Server example.

int my_conn_handler(short event, ad_conn_t *conn, void *userdata) {
    if (event & AD_EVENT_WRITE) {
        evbuffer_add_printf(conn->out, "Hello World.");
        return AD_CLOSE;
    }
    return AD_OK;
}

int main(int argc, char **argv) {
    ad_log_level(AD_LOG_DEBUG);
    ad_server_t *server = ad_server_new();
    ad_server_set_option(server, "server.port", "2222");
    ad_server_register_hook(server, my_conn_handler, NULL);
    return ad_server_start(server);
}

"Hello World", Asynchronous HTTPS Server example.

int my_http_get_handler(short event, ad_conn_t *conn, void *userdata) {
    if (event & AD_EVENT_READ) {
        if (ad_http_get_status(conn) == AD_HTTP_REQ_DONE) {
            ad_http_response(conn, 200, "text/html", "Hello World", 11);
            return ad_http_is_keepalive_request(conn) ? AD_DONE : AD_CLOSE;
        }
    }
    return AD_OK;
}

int my_http_default_handler(short event, ad_conn_t *conn, void *userdata) {
    if (event & AD_EVENT_READ) {
        if (ad_http_get_status(conn) == AD_HTTP_REQ_DONE) {
            ad_http_response(conn, 501, "text/html", "Not implemented", 15);
            return AD_CLOSE; // Close connection.
        }
    }
    return AD_OK;
}

int main(int argc, char **argv) {

    SSL_load_error_strings();
    SSL_library_init();

    ad_log_level(AD_LOG_DEBUG);
    ad_server_t *server = ad_server_new();
    ad_server_set_option(server, "server.port", "8888");
    ad_server_set_ssl_ctx(server, ad_server_ssl_ctx_create_simple("ssl.cert", "ssl.pkey"));
    ad_server_register_hook(server, ad_http_handler, NULL); // HTTP Parser is also a hook.
    ad_server_register_hook_on_method(server, "GET", my_http_get_handler, NULL);
    ad_server_register_hook(server, my_http_default_handler, NULL);

    return ad_server_start(server);
}

Please refer sample codes such as echo example in examples directory for more details.

References

Contributors

The following people have helped with suggestions, ideas, code or fixing bugs: (in alphabetical order by first name)

Please send a PR for adding your name here, so we know whom to appreciate. Thanks to all the contributors.

Issues
  • Access to SSL_CTX

    Access to SSL_CTX

    Hi,

    I'm trying to write SSL server using your library and I intend to heavily customize SSL context. The issue I'm having is that SSL_CTX is only available when server is started. This poses two issues for me:

    • SSL server starts with some default configuration and will run with configuration for a brief moment meaning it in theory will be able to accept SSL connections before all security settings are applied. This is miniscule but still security flaw in the design.
    • OpenSSL documentation is explicitly suggest against modifying SSL_CTX after it had been used to create SSL sessions, which is always a possibility with the current API.

    Here are some suggestions you may consider:

    • leave it to the API user to create an SSL_CTX of their liking.
    • pass the SSL_CTX to ad_server_start() or as an option of ad_server (or NULL if no SSL support is needed).
    • remove server.enable_ssl, server.ssl_cert, server.ssl_pkey server options
    • optionally, provide an utility method to create simple SSL_CTX as a starting point for simple applications, something along these lines SSL_CTX *ad_create_ssl_context (const char *cert_path, const char *priv_key_path).
    opened by dtoubelis 5
  • segfault on ad_server_free()

    segfault on ad_server_free()

    Hello, to make a simple testcase, modify helloworld_http_server.c:

    int my_http_get_handler(short event, ad_conn_t *conn, void *userdata) {
        struct ad_http_s *http;
        if (ad_http_get_status(conn) == AD_HTTP_REQ_DONE) {
            // get the http struct pointer
            http = ad_conn_get_extra(conn);
            // check if the request matches our shutdown command
            if (strcmp("/SHUTDOWN",http->request.path) == 0) {
              ad_http_set_response_header(conn,"Content-Length","13");
              ad_http_response(conn, 200, "text/plain", "Shutting down", 13);
              ad_server_stop(conn->server);
            } else {
              ad_http_response(conn, 200, "text/html", "Hello World", 11);
            }
            return ad_http_is_keepalive_request(conn) ? AD_DONE : AD_CLOSE;
        }
        return AD_OK;
    }
    

    and in main:

    int main(int argc, char **argv) {
        int rc;
        ad_log_level(AD_LOG_DEBUG);
        ad_server_t *server = ad_server_new();
        ad_server_set_option(server, "server.port", "8888");
        // set a timeout, so the client actually renders the content
        ad_server_set_option(server, "server.timeout", "2");
        ad_server_register_hook(server, ad_http_handler, NULL); // HTTP Parser is also a hook.
        ad_server_register_hook_on_method(server, "GET", my_http_get_handler, NULL);
        ad_server_register_hook(server, my_http_default_handler, NULL);
        rc = ad_server_start(server);
        ad_server_free(server);
        return rc;
    }
    

    Start the server. Issue a test request for '/'. Get 'Hello World'. Issue a request for '/SHUTDOWN'. Get 'Shutting down'. Here's the last few lines of the log output:

    [DEBUG] Connection closed. [conn_cb(),ad_server.c:751]
    [DEBUG] Existing loop. [notify_cb(),ad_server.c:503]
    [DEBUG] Loop finished [server_loop(),ad_server.c:512]
    [DEBUG] Closing server. [close_server(),ad_server.c:519]
    [INFO] Server closed.
    [DEBUG] Server terminated. [ad_server_free(),ad_server.c:330]
    Segmentation fault
    

    uname -a: Linux sgmtech 3.2.0-4-686-pae #1 SMP Debian 3.2.65-1+deb7u2 i686 GNU/Linux distro : Debian 7, stock kernel. Libevent version: 2.0.19-stable

    opened by tarkin000 4
  • libasyncd + Free Pascal, is it possible?

    libasyncd + Free Pascal, is it possible?

    Hello,

    Firstly, thanks for share this nice library, I did some tests (using helloworld_http_server demo) with JMeter and I'm impressed with libasyncd performance, it's so fast like Civetweb HTTP server and NodeJS! =)

    However, I don't know C, so I can't understand libasyncd sources to check about this possibility: to use the libasyncd.so/dll to create a HTTP/HTTPS server with Free Pascal [¹].

    [¹] Creating bindings for C libraries.

    opened by silvioprog 4
  • Install does not install transitively-required headers

    Install does not install transitively-required headers

    When including asyncd/ad_server.h it complains about qlibc's headers. Can you also install qlibc if it is not already there, when you do make install? Otherwise you get an unusable install.

    opened by dascandy 4
  • Refactore of BSD/Mac OS X support for cleaner integration.

    Refactore of BSD/Mac OS X support for cleaner integration.

    This was just some cleanup on the work I did the other day.

    opened by spbruner 4
  • possible memory leak in ad_http_get_content

    possible memory leak in ad_http_get_content

    I am occasionally getting extra characters when using ad_http_get_content.

    post = ad_http_get_content(conn, http->request.contentlength, 0);

    Below is a screenshot. Also, that is not a real API key.

    image

    Most of the time it is just gibberish. I have seen the domain name appended to post. See screenshot below:

    image

    I'm afraid there is a memory leak in my code or the ad_http_get_content function.

    I am using SSL. If you need to see my code, it's currently in a private repo, but I can add you to it.

    Thanks!

    opened by levidurfee 3
  • Contributor

    Contributor

    This one just adds myself as a contributor.

    opened by spbruner 3
  • Segfault when using OpenSSL with HTTP handler

    Segfault when using OpenSSL with HTTP handler

    I'm getting a segfault when using SSL mode. Here is a trace from gdb:

    ...
    [DEBUG] conn_cb: status:0x0, event:0x4 [conn_cb(),ad_server.c:724]
    [DEBUG] call_hooks: event 0x4 [call_hooks(),ad_server.c:758]
    [DEBUG] ==> HTTP WRITE [ad_http_handler(),ad_http_handler.c:101]
    [DEBUG] call_hooks: event 0x8 [call_hooks(),ad_server.c:758]
    [DEBUG] ==> HTTP CLOSE=8 (TIMEOUT=0, SHUTDOWN=0) [ad_http_handler(),ad_http_handler.c:105]
    [DEBUG] Connection closed. [conn_cb(),ad_server.c:751]
    
    Program received signal SIGSEGV, Segmentation fault.
    [Switching to Thread 0x7fffb3fff700 (LWP 21411)]
    0x00007ffff672e9e6 in evbuffer_get_length () from /usr/lib/libevent-2.0.so.5
    (gdb) bt
    #0  0x00007ffff672e9e6 in evbuffer_get_length () from /usr/lib/libevent-2.0.so.5
    #1  0x0000000000421dbc in ad_http_send_header (conn=<optimized out>) at ad_http_handler.c:345
    #2  0x0000000000422078 in ad_http_send_data (conn=0x7fffac006160, data=0x42b17a, size=11) at ad_http_handler.c:367
    #3  0x000000000040d51f in _http_get_handler (event=2, conn=0x7fffac006160, userdata=0x0) at ak-http-connector.c:80
    #4  0x000000000041f6f6 in call_hooks (event=2, conn=0x7fffac006160) at ad_server.c:769
    #5  0x00000000004204ec in conn_cb (conn=0x7fffac006160, event=2) at ad_server.c:726
    #6  0x00007ffff6963369 in ?? () from /usr/lib/libevent_openssl-2.0.so.5
    #7  0x00007ffff696397a in ?? () from /usr/lib/libevent_openssl-2.0.so.5
    #8  0x00007ffff6963a08 in ?? () from /usr/lib/libevent_openssl-2.0.so.5
    #9  0x00007ffff67299cc in event_base_loop () from /usr/lib/libevent-2.0.so.5
    #10 0x000000000041f5b1 in server_loop (instance=0x650700) at ad_server.c:511
    #11 0x00007ffff6145e9a in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
    #12 0x00007ffff644e8bd in clone () from /lib/x86_64-linux-gnu/libc.so.6
    #13 0x0000000000000000 in ?? ()
    

    The test program is the one from README.md with minor tweaks to SSL_CTX_*. The code is executed on Ubuntu 12.04. And requests are generated from https://www.ssllabs.com/ssltest/index.html.

    Any ideas?

    opened by dtoubelis 2
  • Update ad_server_ssl_ctx_create_simple()

    Update ad_server_ssl_ctx_create_simple()

    SSL_CTX_use_certificate_chain_file() should be used instead of the SSL_CTX_use_certificate_file() function in order to allow the use of complete certificate chains even when no trusted CA storage is used or when the CA issuing the certificate shall not be added to the trusted CA storage.

    According to OpenSSL docs.

    opened by levidurfee 2
  • get visitor ip address

    get visitor ip address

    Is there a way I can access the IP address of the visitor? I've looked and looked, but don't see a way.

    Thanks!

    opened by levidurfee 2
  • Use Libasyncd in more then one thread

    Use Libasyncd in more then one thread

    Hello there! I'm currently trying to write multithreaded servers in C++ and decided to use Libasyncd, as it seemed simple and straightforward to work with. I already managed to write a simple http server following the examples, but it looks like your library only allows it to work in one thread. I also tried changing the "server.thread" setting to "1", but this just caused the server to stop working without any errors. Apparently, it is not sent to a separate thread, as well as it is not launched in several threads, since when sending a request into the url of my server, I get "Connection refused". So, my question is:

    1. (most importantly) is it possible to use this library to start the server in several(let's say in 4) threads, without running the code 4 times in 4 different sessions?
    2. what is the "server.thread" parameter responsible for, how should it work, and when should it be used? This was not clear from the documentation.
    3. if you can't use multithreading using the library, can you suggest different ways to solve this problem?

    I would be very grateful if I get answers to these questions! Thank you!

    opened by Roma004 0
  • crash while calling ad_server_stop

    crash while calling ad_server_stop

    Hi, i have started 6 server threads which are running independantly, and there is a need for me to stop them at some instance of execution. while i was invoking the function ad_server_stop(server*) the code was getting stuck at : pthread_join function. "Waiting server's last loop to finish"

    But after modifying the code like below it started working. if (server->thread) { void *retval = NULL; DEBUG("Waiting server's last loop to finish."); pthread_join((server->thread), &retval); //// earlier the argument to this function was (*pthread_t) which is wrong , it should be just pthread_t. free(retval); free(server->thread); server->thread = NULL; }

    opened by manjunathkokhle 1
  • Can you add a https file server example?

    Can you add a https file server example?

    Hey.

    I've been looking for a c/c++ library that can be used to make a https web server.

    How do I combine the SSL and http server examples so that I can make an https server?

    Best,

    Rick

    opened by ClemsonCoder 2
  • Vulnerability: Define a maximum length for requests

    Vulnerability: Define a maximum length for requests

    I was starting to implement a simple HTTP application using libsyncd when I noticed currently there seems to be no mechanism to limit the size of requests. This can be exploited by an attacker by sending an arbitrary amount of data to a server. While the user may provide code to impose a limit for simple TCP it seems to me that is not the case for HTTP requests using ad_http_handler().

    Explanation

    To process a HTTP request ad_http_handler() can be used. This function calls http_parser(), which returns AD_TAKEOVER except when the request is complete (both header and body have been received). Therefore, the user's callbacks are not called while the request is not complete, which means

    • the user cannot verify how much data has been received;
    • all the received data will stay in the RAM while the request is not complete (since the user's callbacks aren't called to process the data).

    This leads to a simple attack vector enabling to exhaust the memory of a server.

    Mitigation

    The best way I could think of to mitigate this vulnerability (of course you might have a better one) is to define a maximum request length per server. A default value should be provided (for example 10 MB) which the user could override with ad_server_set_option(). This would "protect" both raw TCP and HTTP(S) applications.

    At first I thought of rejecting requests based on the Content-Length header, but

    • raw TCP would be left unprotected (unless the user implemented a limit, which he might not do because he did not thing about this type of attack)
    • Content-Length refers only to the body of the request, meaning the headers would still be vulnerable
    • Content-Length is not absolutely required by HTTP/1.1

    However, using the content length header might still be useful for early rejections: for example if Content-Length states the body will contain 1 GB but our server only accepts 10 MB then the request could be rejected right away.

    As a last note: when refusing a HTTP request for being too long, a response with a HTTP 413 status code could be sent before closing the connection (so that the client is not left in the dark as to why it was closed).


    I hope this can help improving the security of libasyncd :)

    opened by goncalor 0
  • Are more than one protocol without threads possible?

    Are more than one protocol without threads possible?

    Is it (somewhat easily) possible to have different callbacks registered on different ports (e.g.because the implement different protocols) without threads? And for this, one needs to (also) hook some buffer transfer logic as the daemon mustn't block.

    So the basic idea is:

    • register various callbacks to various (different) ports
    • the callbacks are called if data is available. the callback functions buffer the data and handle it, if enough data is here (e.a. a complete request).
    • the response is constructed (non-blocking) and stored in some buffer (and is gradually transmitted).

    Using threads just adds the complexity for internal explicit synchronization ....

    opened by berndpetrovitsch 1
  • How to close a connection in a seperate thread

    How to close a connection in a seperate thread

    Hello,

    I'm using this library in a multithreaded environment. When a new request arrives I add a new thread in a Thread pool. I managed to write from here using evbuffer_add.

    I managed to do something by setting userdata. and at every event I check the content to know if I should return AD_CLOSE.

    Is there a better way to do this ?

    Thanks a lot

    opened by GuillaumeLeclerc 2
  • ad_http_send_header write

    ad_http_send_header write "(null)" as HTTPVER

    Hello,

    In all request the version sent by the server is (null).

    The output looks like this:

    (null) 200 OK
    
    Body
    

    The only way I found to solve this is to set http->request.httver to HTTP/1.1 in the INIT event.

    Is it the correct way to do ?

    opened by GuillaumeLeclerc 1
  • How to add get/post/put handlers without having to modify the lib source code and how to get the parameters in the handlers?

    How to add get/post/put handlers without having to modify the lib source code and how to get the parameters in the handlers?

    I am trying to see if I can use libasyncd as a library and write a high speed HTTPS server module allowing faster get/post/put operations.

    I am trying to see if I write the app then someway hook into internal http handler and add the get/post/put connector. I was looking at the code and wanted to not added/modify the code of the library put in hooks to get the parameters being passed into the get/post handlers.

    I can't find the good way to do that without having to modify the existing source code. Can you please let me know if that is doable (perhaps you have a sample example for the same that you can share, couldn't find anything on github).

    If not and I have to modify the existing HTTP protocol handler then please let me know

    If there are ways to add handlers to routes do I have to parse url and the post parameters or are there helpers for that?

    Please let me know Thx

    opened by sukantag 5
  • Asynchronous background processing?

    Asynchronous background processing?

    While looking through the examples I cannot find how to not immediately send back a reply, but instead to have some form of handle stored so that it will be returned later, after the background task returned a reply. This would block the connection on HTTP.

    opened by dascandy 3
  • Uses Linux-specific APIs

    Uses Linux-specific APIs

    Looking at the source, it unconditionally includes <sys/eventfd.h> and uses the (really nice) eventfd API. This means libasyncd will only run on Linux (and possibly some BSDs if they can emulate it). I'm not very familiar with libevent, but it might provide some portable replacement for the use of eventfd.

    opened by codebrainz 15
Releases(v1.0.2)
  • v1.0.2(Jan 23, 2017)

    v1.0.2 is a maintenance release with following updates.

    • support of ssl cert chain file
    • support of bsd system

    Thanks a lot!

    Seungyoung "Steve" Kim

    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Dec 16, 2015)

    Hi,

    I'm pleased to announce v1.0.1 of libasyncd. Thank you all the contributors who helped improving libasyncd.

    Changes

    • fix memory leak
    • improve with sample codes.
    • improve SSL_CTX handling
    • improve makefile
    • add sub-library installation support

    Merry Christmas & Happy New Year 2016. Thank you.

    Seungyoung "Steve" Kim

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Apr 18, 2014)

  • v0.9.0(Apr 6, 2014)

The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design

Microsoft 6.6k Dec 4, 2021
cserv is an event-driven and non-blocking web server

cserv is an event-driven and non-blocking web server. It ideally has one worker process per cpu or processor core, and each one is capable of handling thousands of incoming network connections per worker. There is no need to create new threads or processes for each connection.

null 35 Sep 10, 2021
Experimental, scalable, high performance HTTP server

Lwan Web Server Lwan is a high-performance & scalable web server. The project web site contains more details. Build status OS Arch Release Debug Stati

Leandro A. F. Pereira 5.5k Dec 2, 2021
A http/websocket server framework on linux.

The framework is a Web-Server on unix based system. Without using any third-party libraries, the framework writes from unix system calls and standard C library functions.

xingyuuchen 12 Dec 7, 2021
Drogon: A C++14/17 based HTTP web application framework running on Linux/macOS/Unix/Windows

English | 简体中文 | 繁體中文 Overview Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web applicat

An Tao 6.5k Dec 6, 2021
Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications.

Restbed Restbed is a comprehensive and consistent programming model for building applications that require seamless and secure communication over HTTP

Corvusoft 1.6k Nov 29, 2021
C++ Parallel Computing and Asynchronous Networking Engine

中文版入口 Sogou C++ Workflow As Sogou`s C++ server engine, Sogou C++ Workflow supports almost all back-end C++ online services of Sogou, including all sea

Sogou-inc 6.4k Nov 30, 2021
C library to create simple HTTP servers and Web Applications.

Onion http server library Travis status Coverity status Onion is a C library to create simple HTTP servers and Web Applications. master the developmen

David Moreno Montero 1.8k Dec 2, 2021
bittyhttp - A threaded HTTP library for building REST services in C.

bittyhttp - A threaded HTTP library for building REST services in C.

Colin Luoma 12 Nov 29, 2021
A C++11 RESTful web server library

Served Overview Served is a C++ library for building high performance RESTful web servers. Served builds upon Boost.ASIO to provide a simple API for d

Meltwater 675 Nov 23, 2021
Embedded C/C++ web server

CivetWeb The official home of CivetWeb is https://github.com/civetweb/civetweb Continuous integration for Linux and macOS (Travis CI): Continuous inte

null 1.9k Nov 30, 2021
A lightweight Bedorck Dedicated Server Plugin Loader

LiteLoader 简体中文 A lightweight Bedorck Dedicated Server Plugin Loader Based on BedrockX Install Download LiteLoader from Releases or Actions, unzip it

null 130 Dec 5, 2021
QDjango, a Qt-based C++ web framework

QDjango - a Qt-based C++ web framework Copyright (c) 2010-2015 Jeremy Lainé About QDjango is a web framework written in C++ and built on top of the Qt

Jeremy Lainé 231 Nov 26, 2021
a very based, minimal, and flexible static site generator written in pure C89 with no external deps.

based-ssg is a very based, minimal, and flexible static site generator written in pure C89 with no external deps.

null 11 Oct 10, 2021
Support for multiple RPC protocols in a single library

AnyRPC A multiprotocol remote procedure call system for C++ Overview AnyRPC provides a common system to work with a number of different remote procedu

Steve Gieseking 53 Nov 9, 2021
Pion Network Library (Boost licensed open source)

Pion Network Library C++ framework for building lightweight HTTP interfaces Project Home: https://github.com/splunk/pion Retrieving the code git clone

Splunk GitHub 290 Dec 2, 2021
An Sqlite3 Elixir library

Exqlite An SQLite3 library with an Ecto adapter implementation. Caveats When using the Ecto adapter, all prepared statements are cached using an LRU c

Matthew Johnston 84 Dec 6, 2021
A Zig binding to the webview library. Make Zig applications with a nice HTML5 frontend a reality!

A Zig binding to the webview library. Make Zig applications with a nice HTML5 frontend a reality!

ZigLibs 21 Nov 15, 2021