Home Announcements Schedule Assignments Project Reading Reviews Resources

libmicrohttpd Checkpoint 2: Using libmicrohttpd to build a web server

Due: Feb 25th, 2008

Now that you have learned basic socket programming using TCP and HTTP, you will use libmicrohttpd to build a web server. To do this, you must build the library and link against it. You then will need to write the web server, using microhttpd.h as the interface to the library.

Documentation for libmicrohttpd is minimal, but can be found in the header file, microhttpd.h in the src/include directory. There are also simple examples in the src directory.

Getting Started

To get started, do the following:

External select()

In this type of Web Server, you provide the fd_set for reading, writing and exceptions. You pass these into libmicrohttpd which sets its sockets correctly in your fd_sets. You then can use select() in your own code for reading and writing.

Internal select()

In this type of Web Server, libmicrohttpd provides the select to you so that you simply call MHD_run once each iteration through your main loop and it handles the processing of connections for you.

Thread per connection

In this type of Web Server, libmicrohttpd will spawn a thread to handle each connection. Note that your Web Server must be thread safe so that when the individual threads call your handlers, you code won't enter race conditions. For a threading example, look at pthread_example.c.bz2 as an example on how to create, stop and start threads.

Understanding libmicrohttpd

The image to the right is what I call a (B)roken UML (BUML) diagram to illustrate the sequence of events that occur between the daemon and the client (in this case, your web server). Note that the dark arrow heads indicate the direction of a function call (i.e., who made the function call) and time increases from the top of the figure down towards the bottom of the figure.

Initially the Web Server calls MHD_start_daemon followed by MHD_run. At some point, a TCP connection is established with the daemon, which calls the AcceptPolicyCallback function suplied by the daemon. Assuming this returns MHD_YES, the connection is established and an HTTP request is received over the TCP connection. For the purposes of this project, your AcceptPolicyCallback function should always return MHD_YES.

When a request is received by libmicrohttpd, it determines the type of request and calls the AccessHandlerCallback, which passes the session to the Web Server. The Web Server will not return from this function until it has optionally called the functions listed in the figure, including MHD_queue_response. In essence, a single request will cause a single response to be created. After MHD_queue_response is called, the daemon will send the response to the network. Note that if the Web Server created the response object by using MHD_create_response_from_callback, the daemon will begin writing the response object to the network and continually call the MHD_ContentReaderCallback function until the Web Server has given it all of its data.

In order to handle requests, the Web Server registers Handlers. When a request is received, it will specify a URI on the first line. URIs on this line always begin with '/'. The Web Server registers prefixes which determine which handler is called. To register a prefix, the server calls MHD_register_handler (and to unregister a prefix, it calls MHD_unregister_handler).

For example, a Web Server might register "/" and "/images" as the first and second handlers respectively. Anything beginning with "/images" would call the second handler while anything begining with just "/" would call the first handler.

Grading

You will be graded on the following: