The code extract from Ewrt Open-Source firmware, for my personal project purpose.
Project repository: http://git.lazytech.info/?p=aghttpd.git

Sample code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <signal.h>
 
#include "http.h"
 
static int caught_sigint = 0;
 
void handle_free ( GIOChannel *sock, http_request *h ) { 
    g_io_channel_unref( sock );
    http_request_free( h );
}
 
gboolean handle_write( GIOChannel *sock, GIOCondition cond, http_request *h ) { 
    gchar *response = "It Works!";
    guint r, n;
 
    n = strlen( response );
 
    http_add_header( h, "Content-Type", "text/html" );
    http_send_header( h, 200, "OK" );
 
    r = g_io_channel_write( h->sock, response, n, &n );
 
    if ( r != G_IO_ERROR_NONE ) {
        g_warning( "Serving response to %s failed: %m", h->peer_ip );
    }
 
    g_io_channel_close( sock );
    handle_free(sock, h);
 
    return FALSE;
}
 
gboolean handle_read( GIOChannel *sock, GIOCondition cond, http_request *h ) {
    ssize_t n = http_request_read( h );
 
    if ( http_request_ok( h ) ) {
        g_io_add_watch( sock, G_IO_OUT, (GIOFunc)handle_write, h );
        return FALSE;
    } else if ( 0 == n ) {
        handle_free( sock, h );
        return FALSE;
    } else {
        return TRUE;
    }
}
 
gboolean handle_accept( GIOChannel *sock, GIOCondition cond, gpointer data ) {
    struct sockaddr_in peer_addr;
    int peer_fd, n = sizeof( peer_addr );
    GIOChannel *peer;
    http_request *req;
 
    peer_fd = accept( g_io_channel_unix_get_fd(sock),
                      (struct sockaddr *)&peer_addr, &n );
    g_assert( peer_fd != -1 );
 
    peer = g_io_channel_unix_new( peer_fd );
    req  = http_request_new( peer );
    g_io_add_watch( peer, G_IO_IN, (GIOFunc)handle_read, req );
 
    return TRUE;
}
 
gboolean check_sigint ( GMainLoop *loop ) {
    if ( caught_sigint ) {
        g_message( "Caught SIGINT!" );
        g_main_quit( loop );
    }
    return TRUE;
}
 
void handle_sigint ( int sig ) {
    caught_sigint++;
}
 
int main (int argc, char **argv) {
    GMainLoop *loop;
    GIOChannel *sock;
 
    signal( SIGPIPE, SIG_IGN );
    signal( SIGINT, handle_sigint );
 
    loop = g_main_new( FALSE );
 
    sock = http_bind_socket( "0.0.0.0", 12345, 5 );
 
    g_io_add_watch( sock, G_IO_IN, (GIOFunc)handle_accept, NULL );
    g_timeout_add( 1000, (GSourceFunc)check_sigint, loop );
 
    g_message( "starting main loop" );
    g_main_run( loop );
    g_message( "exiting main loop" );
 
    return 0;
}

It take more lines number than “libevent webserver in 40 lines of c“…

And benchmarks on my virtual machine:
ab -c 1000 -n 10000 http://localhost:12345/

libevent: Requests per second: 1349.16 [#/sec] (mean)
aghttpd: Requests per second: 2255.85 [#/sec] (mean)

Tags: ,