Next: microhttpd-const, Previous: Top, Up: Top [Contents][Index]
All symbols defined in the public API start with MHD_
. MHD
is a small HTTP daemon library. As such, it does not have any API
for logging errors (you can only enable or disable logging to stderr).
Also, it may not support all of the HTTP features directly, where
applicable, portions of HTTP may have to be handled by clients of the
library.
The library is supposed to handle everything that it must handle
(because the API would not allow clients to do this), such as basic
connection management. However, detailed interpretations of headers,
such as range requests, are left to the main application. In
particular, if an application developer wants to support range
requests, he needs to explicitly indicate support in responses and
also explicitly parse the range header and generate a response (for
example, using the MHD_create_response_from_fd_at_offset
call
to serve ranges from a file). MHD does understands headers that
control connection management (specifically, Connection: close
and Expect: 100 continue
are understood and handled
automatically). Connection: upgrade
is supported by passing
control over the socket (or something that behaves like the real
socket in the case of TLS) to the application (after sending the
desired HTTP response header).
MHD largely ignores the semantics of the different HTTP methods,
so clients are left to handle those. One exception is that MHD does
understand HEAD
and will only send the headers of the response
and not the body, even if the client supplied a body. (In fact,
clients do need to construct a response with the correct length, even
for HEAD
request.)
MHD understands POST
data and is able to decode certain
formats (at the moment only application/x-www-form-urlencoded
and multipart/form-data
) using the post processor API. The
data stream of a POST is also provided directly to the main
application, so unsupported encodings could still be processed, just
not conveniently by MHD.
The header file defines various constants used by the HTTP protocol. This does not mean that MHD actually interprets all of these values. The provided constants are exported as a convenience for users of the library. MHD does not verify that transmitted HTTP headers are part of the standard specification; users of the library are free to define their own extensions of the HTTP standard and use those with MHD.
All functions are guaranteed to be completely reentrant and thread-safe. MHD checks for allocation failures and tries to recover gracefully (for example, by closing the connection). Additionally, clients can specify resource limits on the overall number of connections, number of connections per IP address and memory used per connection to avoid resource exhaustion.
MHD is currently used in a wide range of implementations. Examples based on reports we’ve received from developers include:
MHD supports four basic thread modes and up to three event loop styles.
The four basic thread modes are external sockets polling (MHD creates no threads, event loop is fully managed by the application), internal polling (MHD creates one thread for all connections), polling in thread pool (MHD creates a thread pool which is used to process all connections) and thread-per-connection (MHD creates one thread for listen sockets and then one thread per accepted connection).
These thread modes are then combined with the evet loop styles (polling function type). MHD support select, poll and epoll. select is available on all platforms, epoll and poll may not be available on some platforms. Note that it is possible to combine MHD using epoll with an external select-based event loop.
The default (if no other option is passed) is “external select”.
The highest performance can typically be obtained with a thread pool
using epoll
. Apache Benchmark (ab) was used to compare the
performance of select
and epoll
when using a thread pool
and a large number of connections. Figure 1.1 shows the
resulting plot from the benchmark.c
example, which measures the
latency between an incoming request and the completion of the
transmission of the response. In this setting, the epoll
thread pool with four threads was able to handle more than 45,000
connections per second on loopback (with Apache Benchmark running
three processes on the same machine).
Not all combinations of thread modes and event loop styles are
supported. This is partially to keep the API simple, and partially
because some combinations simply make no sense as others are strictly
superior. Note that the choice of style depends first of all on the
application logic, and then on the performance requirements.
Applications that perform a blocking operation while handling a
request within the callbacks from MHD must use a thread per
connection. This is typically rather costly. Applications that do
not support threads or that must run on embedded devices without
thread-support must use the external mode. Using epoll
is only
supported on some platform, thus portable applications must at least
have a fallback option available. Table 1.1 lists the sane
combinations.
select | poll | epoll | |
external | yes | no | yes |
internal | yes | yes | yes |
thread pool | yes | yes | yes |
thread-per-connection | yes | yes | no |
MHD uses the standard GNU system where the usual build process involves running
$ ./configure $ make $ make install
MHD supports various options to be given to configure to tailor the binary to a specific situation. Note that some of these options will remove portions of the MHD code that are required for binary-compatibility. They should only be used on embedded systems with tight resource constraints and no concerns about library versioning. Standard distributions including MHD are expected to always ship with all features enabled, otherwise unexpected incompatibilities can arise!
Here is a list of MHD-specific options that can be given to configure (canonical configure options such as “–prefix” are also supported, for a full list of options run “./configure –help”):
``--disable-curl''
disable running testcases using libcurl
``--disable-largefile''
disable support for 64-bit files
``--disable-messages''
disable logging of error messages (smaller binary size, not so much fun for debugging)
``--disable-https''
disable HTTPS support, even if GNUtls is found; this option must be used if eCOS license is desired as an option (in all cases the resulting binary falls under a GNU LGPL-only license)
``--disable-postprocessor''
do not include the post processor API (results in binary incompatibility)
``--disable-dauth''
do not include the authentication APIs (results in binary incompatibility)
``--disable-httpupgrade''
do not build code for HTTP “Upgrade” (smaller binary size, binary incompatible library)
``--disable-epoll''
do not include epoll support, even if it supported (minimally smaller binary size, good for portability testing)
``--enable-coverage''
set flags for analysis of code-coverage with gcc/gcov (results in slow, large binaries)
``--with-threads=posix,w32,none,auto''
sets threading library to use. With use “none” to not support threads. In this case, MHD will only support the “external” threading modes and not perform any locking of data structures! Use MHD_is_feature_supported(MHD_FEATURE_THREADS)
to test if threads are available. Default is “auto”.
``--with-gcrypt=PATH''
specifies path to libgcrypt installation
``--with-gnutls=PATH''
specifies path to libgnutls installation
MHD will give applications access to its internal data structures via pointers via arguments and return values from its API. This creates the question as to how long those pointers are assured to stay valid.
Most MHD data structures are associated with the connection of an
HTTP client. Thus, pointers associated with a connection are
typically valid until the connection is finished, at which point
MHD will call the MHD_RequestCompletedCallback
if one is
registered. Applications that have such a callback registered
may assume that keys and values from the
MHD_KeyValueIterator
, return values from
MHD_lookup_connection_value
and the url
,
method
and version
arguments to the
MHD_AccessHandlerCallback
will remain valid until the
respective MHD_RequestCompletedCallback
is invoked.
In contrast, the upload_data
argument of
MHD_RequestCompletedCallback
as well as all pointers
from the MHD_PostDataIterator
are only valid for the
duration of the callback.
Pointers returned from MHD_get_response_header
are
valid as long as the response itself is valid.
Ideally, before including "microhttpd.h" you should add the necessary
includes to define the uint64_t
, size_t
, fd_set
,
socklen_t
and struct sockaddr
data types. Which
specific headers are needed may depend on your platform and your build
system might include some tests to provide you with the necessary
conditional operations. For possible suggestions consult
platform.h
and configure.ac
in the MHD distribution.
Once you have ensured that you manually (!) included the right headers
for your platform before "microhttpd.h", you should also add a line
with #define MHD_PLATFORM_H
which will prevent the
"microhttpd.h" header from trying (and, depending on your platform,
failing) to include the right headers.
If you do not define MHD_PLATFORM_H, the "microhttpd.h" header will automatically include headers needed on GNU/Linux systems (possibly causing problems when porting to other platforms).
MHD does not install a signal handler for SIGPIPE. On platforms where this is possible (such as GNU/Linux), it disables SIGPIPE for its I/O operations (by passing MSG_NOSIGNAL or similar). On other platforms, SIGPIPE signals may be generated from network operations by MHD and will cause the process to die unless the developer explicitly installs a signal handler for SIGPIPE.
Hence portable code using MHD must install a SIGPIPE handler or
explicitly block the SIGPIPE signal. MHD does not do so in order to
avoid messing with other parts of the application that may need to
handle SIGPIPE in a particular way. You can make your application
handle SIGPIPE by calling the following function in main
:
static void catcher (int sig) { } static void ignore_sigpipe () { struct sigaction oldsig; struct sigaction sig; sig.sa_handler = &catcher; sigemptyset (&sig.sa_mask); #ifdef SA_INTERRUPT sig.sa_flags = SA_INTERRUPT; /* SunOS */ #else sig.sa_flags = SA_RESTART; #endif if (0 != sigaction (SIGPIPE, &sig, &oldsig)) fprintf (stderr, "Failed to install SIGPIPE handler: %s\n", strerror (errno)); }
Some platforms do not support long long
. Hence MHD defines a
macro MHD_UNSIGNED LONG_LONG
which will default to
unsigned long long
. For standard desktop operating systems,
this is all you need to know.
However, if your platform does not support unsigned long long
,
you should change "platform.h" to define MHD_LONG_LONG
and
MHD_UNSIGNED_LONG_LONG
to an appropriate alternative type and
also define MHD_LONG_LONG_PRINTF
and
MHD_UNSIGNED_LONG_LONG_PRINTF
to the corresponding format
string for printing such a data type. Note that the “signed”
versions are deprecated. Also, for historical reasons,
MHD_LONG_LONG_PRINTF
is without the percent sign, whereas
MHD_UNSIGNED_LONG_LONG_PRINTF
is with the percent sign. Newly
written code should only use the unsigned versions. However, you need
to define both in "platform.h" if you need to change the definition
for the specific platform.
libmicrohttpd in general ported well to W32. Most libmicrohttpd features are supported. W32 do not support some functions, like epoll and corresponding MHD features are not available on W32.
To compile MHD on z/OS, extract the archive and run
iconv -f UTF-8 -t IBM-1047 contrib/ascebc > /tmp/ascebc.sh chmod +x /tmp/ascebc.sh for n in `find * -type f` do /tmp/ascebc.sh $n done
to convert all source files to EBCDIC. Note that you must run
configure
from the directory where the configure script is
located. Otherwise, configure will fail to find the
contrib/xcc
script (which is a wrapper around the z/OS c89
compiler).
Next: microhttpd-const, Previous: Top, Up: Top [Contents][Index]