[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r12349 - libmicrohttpd-docs/WWW
From: |
gnunet |
Subject: |
[GNUnet-SVN] r12349 - libmicrohttpd-docs/WWW |
Date: |
Mon, 26 Jul 2010 22:03:34 +0200 |
Author: grothoff
Date: 2010-07-26 22:03:34 +0200 (Mon, 26 Jul 2010)
New Revision: 12349
Modified:
libmicrohttpd-docs/WWW/microhttpd.html
libmicrohttpd-docs/WWW/microhttpd.pdf
libmicrohttpd-docs/WWW/tutorial.html
libmicrohttpd-docs/WWW/tutorial.pdf
Log:
tut
Modified: libmicrohttpd-docs/WWW/microhttpd.html
===================================================================
--- libmicrohttpd-docs/WWW/microhttpd.html 2010-07-26 20:03:04 UTC (rev
12348)
+++ libmicrohttpd-docs/WWW/microhttpd.html 2010-07-26 20:03:34 UTC (rev
12349)
@@ -1,11 +1,11 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html401/loose.dtd">
<html>
-<!-- This manual documents GNU libmicrohttpd version 0.4.4, last
-updated 4 December 2009. It is built upon the documentation in the
+<!-- This manual documents GNU libmicrohttpd version 0.9.0, last
+updated 26 July 2010. It is built upon the documentation in the
header file microhttpd.h.
-Copyright C 2007, 2008, 2009 Christian Grothoff
+Copyright C 2007, 2008, 2009, 2010 Christian Grothoff
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
@@ -14,8 +14,9 @@
Texts. A copy of the license is included in the section entitled "GNU
Free Documentation License".
+GNU libmicrohttpd is a GNU package.
-->
-<!-- Created on January 8, 2010 by texi2html 1.82
+<!-- Created on July 26, 2010 by texi2html 1.82
texi2html was written by:
Lionel Cons <address@hidden> (original author)
Karl Berry <address@hidden>
@@ -65,12 +66,12 @@
</tr></table>
<a name="The-GNU-libmicrohttpd-Library"></a>
<h1 class="settitle">The GNU libmicrohttpd Library</h1>
-<p>This manual documents GNU libmicrohttpd version 0.4.4, last
-updated 4 December 2009. It is built upon the documentation in the
+<p>This manual documents GNU libmicrohttpd version 0.9.0, last
+updated 26 July 2010. It is built upon the documentation in the
header file ‘<tt>microhttpd.h</tt>’.
</p>
-<p>Copyright © 2007, 2008, 2009 Christian Grothoff
+<p>Copyright © 2007, 2008, 2009, 2010 Christian Grothoff
</p>
<blockquote><p>Permission is granted to copy, distribute and/or modify this
document
under the terms of the GNU Free Documentation License, Version 1.3
@@ -79,7 +80,6 @@
Texts. A copy of the license is included in the section entitled "GNU
Free Documentation License".
</p></blockquote>
-
<p>GNU libmicrohttpd is a GNU package.
</p>
<table class="menu" border="0" cellspacing="0">
@@ -122,7 +122,7 @@
<a name="microhttpd_002dintro"></a>
<table cellpadding="1" cellspacing="1" border="0">
<tr><td valign="middle" align="left">[<a href="#Top" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#microhttpd_002dconst" title="Next
section in reading order"> > </a>]</td>
+<td valign="middle" align="left">[<a href="#SIGPIPE" title="Next section in
reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left">[<a href="#Top" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
@@ -179,13 +179,67 @@
number of connections, number of connections per IP address and memory
used per connection to avoid resource exhaustion.
</p>
+<hr size="6">
+<a name="SIGPIPE"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#microhttpd_002dintro"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#microhttpd_002dconst" title="Next
section in reading order"> > </a>]</td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left">[<a href="#microhttpd_002dintro"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#microhttpd_002dintro" title="Up
section"> Up </a>]</td>
+<td valign="middle" align="left">[<a href="#microhttpd_002dconst" title="Next
chapter"> >> </a>]</td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
+<td valign="middle" align="left">[<a href="#Concept-Index"
title="Index">Index</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
+</tr></table>
+<h2 class="section">1.1 SIGPIPE</h2>
+<a name="index-signals"></a>
+<p><acronym>MHD</acronym> 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). On other platforms,
+SIGPIPE signals may be generated from network operations by
+<acronym>MHD</acronym> and will cause the process to die unless the developer
+explicitly installs a signal handler for SIGPIPE.
+</p>
+<p>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 <code>main</code>:
+</p>
+<pre class="verbatim">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));
+}
+</pre>
+
<hr size="6">
<a name="microhttpd_002dconst"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#microhttpd_002dintro"
title="Previous section in reading order"> < </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#SIGPIPE" title="Previous
section in reading order"> < </a>]</td>
<td valign="middle" align="left">[<a href="#microhttpd_002dstruct" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left">[<a href="#microhttpd_002dintro"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
@@ -359,45 +413,56 @@
value of NULL has no special significance; (however,
note that if you return non-NULL, you can no longer
rely on the first call to the access handler having
-<code>NULL == *con_cls on entry</code> on entry)
+<code>NULL == *con_cls</code> on entry)
<code>cls</code> will be set to the second argument following
MHD_OPTION_URI_LOG_CALLBACK. Finally, <code>uri</code> will
be the 0-terminated URI of the request.
</p>
</dd>
<dt> <code>MHD_OPTION_HTTPS_MEM_KEY</code></dt>
-<dd><p>Memory pointer to the private key to be used by the
+<dd><a name="index-SSL"></a>
+<a name="index-TLS"></a>
+<p>Memory pointer to the private key to be used by the
HTTPS daemon. This option should be followed by an
"const char*" argument.
This should be used in conjunction with
’MHD_OPTION_HTTPS_MEM_CERT’.
</p>
</dd>
<dt> <code>MHD_OPTION_HTTPS_MEM_CERT</code></dt>
-<dd><p>Memory pointer to the certificate to be used by the
+<dd><a name="index-SSL-1"></a>
+<a name="index-TLS-1"></a>
+<p>Memory pointer to the certificate to be used by the
HTTPS daemon. This option should be followed by an
"const char*" argument.
This should be used in conjunction with ’MHD_OPTION_HTTPS_MEM_KEY’.
</p>
</dd>
-<dt> <code>MHD_OPTION_CRED_TYPE</code></dt>
-<dd><p>Daemon credentials type. Either certificate or anonymous,
+<dt> <code>MHD_OPTION_HTTPS_CRED_TYPE</code></dt>
+<dd><a name="index-SSL-2"></a>
+<a name="index-TLS-2"></a>
+<p>Daemon credentials type. Either certificate or anonymous,
this option should be followed by one of the values listed in
-"enum MHD_GNUTLS_CredentialsType".
+"enum gnutls_credentials_type_t".
</p>
</dd>
-<dt> <code>MHD_OPTION_PROTOCOL_VERSION</code></dt>
-<dd><p>SSL/TLS protocol version.
-Memory pointer to a zero (MHD_GNUTLS_PROTOCOL_END) terminated
-(const) array of ’enum MHD_GNUTLS_Protocol’ values representing the
-protocol versions to this server should support. Unsupported
-requests will be dropped by the server.
-</p>
+<dt> <code>MHD_OPTION_HTTPS_PRIORITIES</code></dt>
+<dd><a name="index-SSL-3"></a>
+<a name="index-TLS-3"></a>
+<a name="index-cipher"></a>
+<p>SSL/TLS protocol version and ciphers.
+This option must be followwed by an "const char *" argument
+specifying the SSL/TLS protocol versions and ciphers that
+are acceptable for the application. The string is passed
+unchanged to gnutls_priority_init. If this option is not
+specified, “NORMAL” is used.
+</p>
</dd>
-<dt> <code>MHD_OPTION_CIPHER_ALGORITHM</code></dt>
-<dd><p>Memory pointer to a zero (MHD_GNUTLS_CIPHER_UNKNOWN)
-terminated (const) array of ’enum MHD_GNUTLS_CipherAlgorithm’
-representing the cipher priority order to which the HTTPS
-daemon should adhere.
+<dt> <code>MHD_OPTION_LISTEN_SOCKET</code></dt>
+<dd><a name="index-systemd"></a>
+<p>Listen socket to use. Pass a listen socket for MHD to use
+(systemd-style). If this option is used, MHD will not open its own
+listen socket(s). The argument passed must be of type "int" and refer
+to an existing socket that has been bound to a port and is listening.
</p>
</dd>
<dt> <code>MHD_OPTION_EXTERNAL_LOGGER</code></dt>
@@ -415,6 +480,16 @@
even if this argument is used.
</p>
</dd>
+<dt> <code>MHD_OPTION_THREAD_POOL_SIZE</code></dt>
+<dd><a name="index-performance"></a>
+<p>Number (unsigned int) of threads in thread pool. Enable
+thread pooling by setting this value to to something
+greater than 1. Currently, thread model must be
+MHD_USE_SELECT_INTERNALLY if thread pooling is enabled
+(MHD_start_daemon returns NULL for an unsupported thread
+model).
+</p>
+</dd>
<dt> <code>MHD_OPTION_ARRAY</code></dt>
<dd><a name="index-options"></a>
<p>This option can be used for initializing MHD using options from an
@@ -492,7 +567,7 @@
<dd><p><code>GET</code> (<acronym>URI</acronym>) arguments.
</p>
</dd>
-<dt> <code>MHD_HEADER_KIND</code></dt>
+<dt> <code>MHD_FOOTER_KIND</code></dt>
<dd><p><acronym>HTTP</acronym> footer (only for http 1.1 chunked encodings).
</p>
</dd>
@@ -526,41 +601,9 @@
</dl>
</dd></dl>
-<dl>
-<dt><a name="index-MHD_005fGNUTLS_005fProtocol"></a><u>Enumeration:</u>
<b>MHD_GNUTLS_Protocol</b></dt>
-<dd><p>SSL/TLS Protocol types. Note that not all listed algorithms are
-necessarily supported by all builds of MHD.
-</p>
-<dl compact="compact">
-<dt> <code>MHD_GNUTLS_PROTOCOL_END</code></dt>
-<dt> <code>MHD_GNUTLS_PROTOCOL_SSL3</code></dt>
-<dt> <code>MHD_GNUTLS_PROTOCOL_TLS1_0</code></dt>
-<dt> <code>MHD_GNUTLS_PROTOCOL_TLS1_1</code></dt>
-<dt> <code>MHD_GNUTLS_PROTOCOL_TLS1_2</code></dt>
-<dt> <code>MHD_GNUTLS_PROTOCOL_UNKNOWN</code></dt>
-</dl>
-</dd></dl>
-
<dl>
-<dt><a name="index-MHD_005fGNUTLS_005fCipherAlgorithm"></a><u>Enumeration:</u>
<b>MHD_GNUTLS_CipherAlgorithm</b></dt>
-<dd><p>List of symmetric ciphers.
-Note that not all listed algorithms are necessarily supported by
-all builds of MHD.
-</p>
-<dl compact="compact">
-<dt> <code>MHD_GNUTLS_CIPHER_UNKNOWN</code></dt>
-<dt> <code>MHD_GNUTLS_CIPHER_NULL</code></dt>
-<dt> <code>MHD_GNUTLS_CIPHER_ARCFOUR_128</code></dt>
-<dt> <code>MHD_GNUTLS_CIPHER_3DES_CBC</code></dt>
-<dt> <code>MHD_GNUTLS_CIPHER_AES_128_CBC</code></dt>
-<dt> <code>MHD_GNUTLS_CIPHER_AES_256_CBC</code></dt>
-</dl>
-</dd></dl>
-
-
-<dl>
<dt><a name="index-MHD_005fConnectionInfoType"></a><u>Enumeration:</u>
<b>MHD_ConnectionInfoType</b></dt>
<dd><p>Values of this enum are used to specify what information about a
connection is desired.
@@ -572,9 +615,15 @@
</p>
</dd>
<dt> <code>MHD_CONNECTION_INFO_PROTOCOL,</code></dt>
-<dd><p>Takes no extra arguments.
+<dd><p>Takes no extra arguments. Allows finding out the TLS/SSL protocol used
+(HTTPS connections only).
</p>
</dd>
+<dt> <code>MHD_CONNECTION_INFO_GNUTLS_SESSION,</code></dt>
+<dd><p>Takes no extra arguments. Allows access to the underlying GNUtls
session
+(HTTPS connections only).
+</p>
+</dd>
</dl>
</dd></dl>
@@ -1358,7 +1407,28 @@
</p></dd></dl>
+
<dl>
+<dt><a
name="index-MHD_005fcreate_005fresponse_005ffrom_005ffd"></a><u>Function:</u>
struct MHD_Response * <b>MHD_create_response_from_fd</b><i> (uint64_t size, int
fd)</i></dt>
+<dd><p>Create a response object. The response object can be extended with
+header information and then it can be used any number of times.
+</p>
+<dl compact="compact">
+<dt> <var>size</var></dt>
+<dd><p>size of the data portion of the response, <code>-1</code> for unknown;
+</p>
+</dd>
+<dt> <var>fd</var></dt>
+<dd><p>file descriptor referring to a file on disk with the data; will be
+closed when response is destroyed
+</p></dd>
+</dl>
+
+<p>Return <code>NULL</code> on error (i.e. invalid arguments, out of memory).
+</p></dd></dl>
+
+
+<dl>
<dt><a
name="index-MHD_005fcreate_005fresponse_005ffrom_005fdata"></a><u>Function:</u>
struct MHD_Response * <b>MHD_create_response_from_data</b><i> (size_t size,
void *data, int must_free, int must_copy)</i></dt>
<dd><p>Create a response object. The response object can be extended with
header information and then it can be used any number of times.
@@ -3400,6 +3470,7 @@
<tr><td></td><td valign="top"><a
href="#index-bind_002c-restricting-bind">bind, restricting bind</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td colspan="3"> <hr></td></tr>
<tr><th><a name="Concept-Index-1_cp_letter-C">C</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a href="#index-cipher">cipher</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-connection_002c-limiting-number-of-connections">connection,
limiting number of connections</a></td><td valign="top"><a
href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-cookie">cookie</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td colspan="3"> <hr></td></tr>
@@ -3434,6 +3505,7 @@
<tr><td></td><td valign="top"><a href="#index-options">options</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td colspan="3"> <hr></td></tr>
<tr><th><a name="Concept-Index-1_cp_letter-P">P</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a
href="#index-performance">performance</a></td><td valign="top"><a
href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-poll">poll</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-POST-method">POST
method</a></td><td valign="top"><a href="#microhttpd_002dconst">2.
Constants</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-POST-method-1">POST
method</a></td><td valign="top"><a href="#microhttpd_002dstruct">3. Structures
type definition</a></td></tr>
@@ -3447,11 +3519,21 @@
<tr><td colspan="3"> <hr></td></tr>
<tr><th><a name="Concept-Index-1_cp_letter-S">S</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-select">select</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-signals">signals</a></td><td
valign="top"><a href="#SIGPIPE">1.1 SIGPIPE</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-SSL">SSL</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-SSL-1">SSL</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-SSL-2">SSL</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-SSL-3">SSL</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-systemd">systemd</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td colspan="3"> <hr></td></tr>
<tr><th><a name="Concept-Index-1_cp_letter-T">T</a></th><td></td><td></td></tr>
<tr><td></td><td valign="top"><a href="#index-timeout">timeout</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a href="#index-timeout-1">timeout</a></td><td
valign="top"><a href="#microhttpd_002dinspect">6. Implementing external
<code>select</code></a></td></tr>
<tr><td></td><td valign="top"><a href="#index-timeout-2">timeout</a></td><td
valign="top"><a href="#microhttpd_002dinspect">6. Implementing external
<code>select</code></a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-TLS">TLS</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-TLS-1">TLS</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-TLS-2">TLS</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
+<tr><td></td><td valign="top"><a href="#index-TLS-3">TLS</a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td colspan="3"> <hr></td></tr>
</table>
<table><tr><th valign="top">Jump to: </th><td><a
href="#Concept-Index-1_cp_letter-B" class="summary-letter"><b>B</b></a>
@@ -3528,6 +3610,7 @@
<tr><td></td><td valign="top"><a
href="#index-MHD_005fcreate_005fpost_005fprocessor"><code>MHD_create_post_processor</code></a></td><td
valign="top"><a href="#microhttpd_002dpost-api">9.1 Programming interface for
the <code>POST</code> processor</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fcreate_005fresponse_005ffrom_005fcallback"><code>MHD_create_response_from_callback</code></a></td><td
valign="top"><a href="#microhttpd_002dresponse-create">8.2 Creating response
objects</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fcreate_005fresponse_005ffrom_005fdata"><code>MHD_create_response_from_data</code></a></td><td
valign="top"><a href="#microhttpd_002dresponse-create">8.2 Creating response
objects</a></td></tr>
+<tr><td></td><td valign="top"><a
href="#index-MHD_005fcreate_005fresponse_005ffrom_005ffd"><code>MHD_create_response_from_fd</code></a></td><td
valign="top"><a href="#microhttpd_002dresponse-create">8.2 Creating response
objects</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fdel_005fresponse_005fheader"><code>MHD_del_response_header</code></a></td><td
valign="top"><a href="#microhttpd_002dresponse-headers">8.3 Adding headers to
a response</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fdestroy_005fpost_005fprocessor"><code>MHD_destroy_post_processor</code></a></td><td
valign="top"><a href="#microhttpd_002dpost-api">9.1 Programming interface for
the <code>POST</code> processor</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fdestroy_005fresponse"><code>MHD_destroy_response</code></a></td><td
valign="top"><a href="#microhttpd_002dresponse-enqueue">8.1 Enqueuing a
response</a></td></tr>
@@ -3590,8 +3673,6 @@
<tr><td></td><td valign="top"><a
href="#index-MHD_005fDaemonInfo"><code>MHD_DaemonInfo</code></a></td><td
valign="top"><a href="#microhttpd_002dstruct">3. Structures type
definition</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fDaemonInfoType"><code>MHD_DaemonInfoType</code></a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fFLAG"><code>MHD_FLAG</code></a></td><td valign="top"><a
href="#microhttpd_002dconst">2. Constants</a></td></tr>
-<tr><td></td><td valign="top"><a
href="#index-MHD_005fGNUTLS_005fCipherAlgorithm"><code>MHD_GNUTLS_CipherAlgorithm</code></a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
-<tr><td></td><td valign="top"><a
href="#index-MHD_005fGNUTLS_005fProtocol"><code>MHD_GNUTLS_Protocol</code></a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fOPTION"><code>MHD_OPTION</code></a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fOptionItem"><code>MHD_OptionItem</code></a></td><td
valign="top"><a href="#microhttpd_002dconst">2. Constants</a></td></tr>
<tr><td></td><td valign="top"><a
href="#index-MHD_005fPostProcessor"><code>MHD_PostProcessor</code></a></td><td
valign="top"><a href="#microhttpd_002dstruct">3. Structures type
definition</a></td></tr>
@@ -3631,7 +3712,10 @@
<div class="contents">
<ul class="toc">
- <li><a name="toc-Introduction" href="#microhttpd_002dintro">1.
Introduction</a></li>
+ <li><a name="toc-Introduction" href="#microhttpd_002dintro">1.
Introduction</a>
+ <ul class="toc">
+ <li><a name="toc-SIGPIPE" href="#SIGPIPE">1.1 SIGPIPE</a></li>
+ </ul></li>
<li><a name="toc-Constants" href="#microhttpd_002dconst">2.
Constants</a></li>
<li><a name="toc-Structures-type-definition"
href="#microhttpd_002dstruct">3. Structures type definition</a></li>
<li><a name="toc-Callback-functions-definition" href="#microhttpd_002dcb">4.
Callback functions definition</a></li>
@@ -3704,7 +3788,7 @@
</tr></table>
<h1>About This Document</h1>
<p>
- This document was generated by <em>Christian Grothoff</em> on <em>January 8,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
+ This document was generated by <em>Christian Grothoff</em> on <em>July 26,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
</p>
<p>
The buttons in the navigation panels have the following meaning:
@@ -3806,7 +3890,7 @@
<hr size="1">
<p>
<font size="-1">
- This document was generated by <em>Christian Grothoff</em> on <em>January 8,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
+ This document was generated by <em>Christian Grothoff</em> on <em>July 26,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
</font>
<br>
Modified: libmicrohttpd-docs/WWW/microhttpd.pdf
===================================================================
(Binary files differ)
Modified: libmicrohttpd-docs/WWW/tutorial.html
===================================================================
--- libmicrohttpd-docs/WWW/tutorial.html 2010-07-26 20:03:04 UTC (rev
12348)
+++ libmicrohttpd-docs/WWW/tutorial.html 2010-07-26 20:03:34 UTC (rev
12349)
@@ -1,14 +1,27 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html401/loose.dtd">
<html>
-<!-- Created on February, 8 2009 by texi2html 1.78 -->
-<!--
-Written by: Lionel Cons <address@hidden> (original author)
+<!-- This tutorial documents GNU libmicrohttpd version 0.9.0, last
+updated 26 Jul 2010.
+
+Copyright (c) 2008 Sebastian Gerhardt.
+
+Copyright (c) 2010 Christian Grothoff.
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the GNU Free Documentation License, Version 1.3
+or any later version published by the Free Software Foundation;
+with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
+Texts. A copy of the license is included in the section entitled "GNU
+Free Documentation License".
+
+ -->
+<!-- Created on July 26, 2010 by texi2html 1.82
+texi2html was written by:
+ Lionel Cons <address@hidden> (original author)
Karl Berry <address@hidden>
Olaf Bachmann <address@hidden>
and many others.
Maintained by: Many creative people.
Send bugs and suggestions to <address@hidden>
-
-->
<head>
<title>A tutorial for GNU libmicrohttpd</title>
@@ -17,11 +30,12 @@
<meta name="keywords" content="A tutorial for GNU libmicrohttpd">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
-<meta name="Generator" content="texi2html 1.78">
+<meta name="Generator" content="texi2html 1.82">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
+blockquote.smallquotation {font-size: smaller}
pre.display {font-family: serif}
pre.format {font-family: serif}
pre.menu-comment {font-family: serif}
@@ -41,70 +55,61 @@
<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#800080" alink="#FF0000">
+<a name="Top"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
+<a name="Top-1"></a>
<h1 class="settitle">Top</h1>
-<pre class="verbatim">Copyright (c) 2008 Sebastian Gerhardt.
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
-Texts. A copy of the license is included in the section entitled "GNU
-Free Documentation License".
-</pre>
-<a name="Top"></a>
-<a name="SEC_Top"></a>
-
<table class="menu" border="0" cellspacing="0">
-<tr><td align="left" valign="top"><a href="#SEC1">1.
Introduction</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Introduction">1.
Introduction</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC2">2. Hello browser
example</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Hello-browser-example">2. Hello
browser example</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC5">3. Exploring
requests</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Exploring-requests">3. Exploring
requests</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC8">4. Response
headers</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Response-headers">4. Response
headers</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC11">5. Supporting basic
authentication</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a
href="#Supporting-basic-authentication">5. Supporting basic
authentication</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC16">6. Processing POST
data</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Processing-POST-data">6.
Processing POST data</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC20">7. Improved processing of
POST data</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a
href="#Improved-processing-of-POST-data">7. Improved processing of POST
data</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC25">8. Adding a layer of
security</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Adding-a-layer-of-security">8.
Adding a layer of security</a></td><td> </td><td align="left"
valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC29">A.
Bibliography</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Bibliography">A.
Bibliography</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC31">B. GNU Free Documentation
License</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#License-text">B. GNU Free
Documentation License</a></td><td> </td><td align="left"
valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC33">C. Example
programs</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#Example-programs">C. Example
programs</a></td><td> </td><td align="left" valign="top">
</td></tr>
</table>
<hr size="1">
<a name="Introduction"></a>
-<a name="SEC1"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC_Top" title="Previous
section in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC2" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Top" title="Previous section
in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#History" title="Next section in
reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[ << ]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC2" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Hello-browser-example" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 1. Introduction </h1>
+<a name="Introduction-1"></a>
+<h1 class="chapter">1. Introduction</h1>
<p>This tutorial is for developers who want to learn how they can add HTTP
serving
capabilities to their applications with the <em>GNU libmicrohttpd</em> library,
abbreviated <em>MHD</em>. The reader will learn how to
@@ -118,35 +123,58 @@
encouraged to study the relevant <em>RFCs</em>, which document the HTTP
standard.
</p>
<p><em>GNU libmicrohttpd</em> is assumed to be already installed. This
tutorial
-is written for version 0.4.0. At the time being,
+is written for version 0.9.0. At the time being,
this tutorial has only been tested on <em>GNU/Linux</em> machines even though
efforts were made not to rely on anything that would prevent the samples from
being
built on similar systems.
</p>
<hr size="6">
+<a name="History"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Introduction" title="Previous
section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Hello-browser-example" title="Next
section in reading order"> > </a>]</td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left">[<a href="#Introduction" title="Beginning of
this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Introduction" title="Up section">
Up </a>]</td>
+<td valign="middle" align="left">[<a href="#Hello-browser-example" title="Next
chapter"> >> </a>]</td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left"> </td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
+<td valign="middle" align="left">[Index]</td>
+<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
+</tr></table>
+<h2 class="section">1.1 History</h2>
+
+<p>This tutorial was originally written by Sebastian Gerhardt for MHD
+0.4.0. It was slighly polished and updated to MHD 0.9.0 by Christian
+Grothoff.
+</p><hr size="6">
<a name="Hello-browser-example"></a>
-<a name="SEC2"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC1" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC5" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#History" title="Previous
section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Exploring-requests" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC1" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC5" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Introduction" title="Beginning of
this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Exploring-requests" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 2. Hello browser example </h1>
+<a name="Hello-browser-example-1"></a>
+<h1 class="chapter">2. Hello browser example</h1>
<p>The most basic task for a HTTP server is to deliver a static text message
to any client connecting to it.
Given that this is also easy to implement, it is an excellent problem to start
with.
</p>
-<p>For now, the particular filename the client asks for shall have no effect
on the message that will
+<p>For now, the particular URI the client asks for shall have no effect on the
message that will
be returned. In addition, the server shall end the connection after the
message has been sent so that
the client will know there is nothing more to expect.
</p>
@@ -155,7 +183,9 @@
lines in by yourself as they will be discussed and explained in detail.
</p>
<p>After the necessary includes and the definition of the port which our
server should listen on
-</p><pre class="verbatim">#include <platform.h>
+</p><pre class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
@@ -176,19 +206,20 @@
daemon to sent the reply.
</p>
<p>Talking about the reply, it is defined as a string right after the function
header
-</p><pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection, const char *url,
- const char *method, const char *version, const char
*upload_data,
+</p><pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection,
+ const char *url,
+ const char *method, const char *version,
+ const char *upload_data,
size_t *upload_data_size, void **con_cls)
{
const char *page = "<html><body>Hello,
browser!</body></html>";
</pre><p>HTTP is a rather strict protocol and the client would certainly
consider it "inappropriate" if we
-just sent the answer string "as is". Instead, it has to be wrapped
in certain layers, called headers,
-of additional information. Luckily, most of the work in this area is done by
the library for us—we
+just sent the answer string "as is". Instead, it has to be wrapped
with additional information stored in so-called headers and footers. Most of
the work in this area is done by the library for us—we
just have to ask. Our reply string packed in the necessary layers will be
called a "response".
To obtain such a response we hand our data (the reply–string) and its
size over to the
<code>MHD_create_response_from_data</code> function. The last two parameters
basically tell <em>MHD</em>
that we do not want it to dispose the message data for us when it has been
sent and there also needs
-no internal copy to be done because the <em>constant</em> string won't change
anyway.
+no internal copy to be done because the <em>constant</em> string won’t
change anyway.
</p>
<pre class="verbatim"> struct MHD_Response *response;
int ret;
@@ -222,13 +253,13 @@
</pre><p>The first parameter is one of three possible modes of operation. Here
we want the daemon to run in
a separate thread and to manage all incoming connections in the same thread.
This means that while
producing the response for one connection, the other connections will be put
on hold. In this
-chapter, where the reply is already known and therefore the request is served
quickly, this poses no problem.
+example, where the reply is already known and therefore the request is served
quickly, this poses no problem.
</p>
<p>We will allow all clients to connect regardless of their name or location,
therefore we do not check
them on connection and set the forth and fifth parameter to NULL.
</p>
<p>Parameter six is the address of the function we want to be called whenever
a new connection has been
-established. Our <code>AnswerToConnection</code> knows best what the client
wants and needs no additional
+established. Our <code>answer_to_connection</code> knows best what the client
wants and needs no additional
information (which could be passed via the next parameter) so the next
parameter is NULL. Likewise,
we do not need to pass extra options to the daemon so we just write the
MHD_OPTION_END as the last parameter.
</p>
@@ -247,15 +278,15 @@
</p>
<p>Compile it with
</p><pre class="verbatim">cc hellobrowser.c -o hellobrowser
-I$PATH_TO_LIBMHD_INCLUDES
- -L$PATH_TO_LIBMHD_INCLUDES -static -lmicrohttpd -pthread
+ -L$PATH_TO_LIBMHD_INCLUDES -lmicrohttpd
</pre><p>with the two paths set accordingly and run it.
</p>
-<p>Now open your favorite Internet browser and go to the address
<code>localhost:8888</code>, provided that
+<p>Now open your favorite Internet browser and go to the address
<code>http://localhost:8888/</code>, provided that 8888
is the port you chose. If everything works as expected, the browser will
present the message of the
static HTML page it got from our minimal server.
</p>
-<a name="SEC3"></a>
-<h2 class="heading"> Remarks </h2>
+<a name="Remarks-1"></a>
+<h2 class="heading">Remarks</h2>
<p>To keep this first example as small as possible, some drastic shortcuts
were taken and are to be
discussed now.
</p>
@@ -272,7 +303,7 @@
right after the response has been transferred then.
</p>
<p>Both of these issues you will find addressed in the official
<code>minimal_example.c</code> residing in
-the <code>src/examples</code> directory of the <em>GNU libmicrohttpd</em>
package. The source code of this
+the <code>src/examples</code> directory of the <em>MHD</em> package. The
source code of this
program should look very familiar to you by now and easy to understand.
</p>
<p>For our example, the <code>must_copy</code> and <code>must_free</code>
parameter at the response construction
@@ -286,13 +317,13 @@
to itself when it is not longer needed or, alternatively, have the library to
make and manage
its own copy of it.
</p>
-<a name="SEC4"></a>
-<h2 class="heading"> Exercises </h2>
+<a name="Exercises"></a>
+<h2 class="heading">Exercises</h2>
<ul>
<li>
-While the server is running, use a program like telnet or netcat to connect to
it. Try to form a
-valid HTTP1.1 request yourself like
-<pre class="verbatim">GET /dontcare HTTP1.1
+While the server is running, use a program like <code>telnet</code> or
<code>netcat</code> to connect to it. Try to form a
+valid HTTP 1.1 request yourself like
+<pre class="verbatim">GET /dontcare HTTP/1.1
Host: itsme
<enter>
</pre><p>and see what the server returns to you.
@@ -320,32 +351,32 @@
</li><li>
<em>Demanding:</em> Write a separate function returning a string containing
some useful information,
-for example, the time. Pass the function's address as the sixth parameter and
evaluate this function
-on every request anew in <code>AnswerToConnection</code>. Remember to free the
memory of the string
+for example, the time. Pass the function’s address as the sixth
parameter and evaluate this function
+on every request anew in <code>answer_to_connection</code>. Remember to free
the memory of the string
every time after satisfying the request.
</li></ul>
<hr size="6">
<a name="Exploring-requests"></a>
-<a name="SEC5"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC2" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC8" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Hello-browser-example"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Response-headers" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC2" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC8" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Hello-browser-example"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Response-headers" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 3. Exploring requests </h1>
+<a name="Exploring-requests-1"></a>
+<h1 class="chapter">3. Exploring requests</h1>
<p>This chapter will deal with the information which the client sends to the
server at every request. We are going to examine the most useful fields of
such an request
and print them out in a readable manner. This could be useful for logging
facilities.
@@ -356,9 +387,12 @@
just return MHD_NO after we have probed the request. This way, the connection
is closed
without much ado by the server.
</p>
-<pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection, const char *url,
- const char *method, const char *version, const char
*upload_data,
- size_t *upload_data_size, void **con_cls)
+<pre class="verbatim">static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url,
+ const char *method, const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
...
return MHD_NO;
@@ -367,53 +401,55 @@
</p>
<p>We begin with the most obvious information available to the server, the
request line. You should
-already have noted that a request consists of a command (or
"method") and a URI (e.g. a filename).
+already have noted that a request consists of a command (or "HTTP
method") and a URI (e.g. a filename).
It also contains a string for the version of the protocol which can be found
in <code>version</code>.
To call it a "new request" is justified because we return only
<code>MHD_NO</code>, thus ensuring the
function will not be called again for this connection.
-</p><pre class="verbatim">printf ("New request %s for %s using version
%s\n", method, url, version);
+</p><pre class="verbatim">printf ("New %s request for %s using version
%s\n", method, url, version);
</pre>
<p>The rest of the information is a bit more hidden. Nevertheless, there is
lot of it sent from common
-Internet browsers. It is stored in "key-name" pairs and we want to
list what we find in the header.
-As there is no mandatory set of keys a client has to send, each key–name
pair is printed out one by
+Internet browsers. It is stored in "key-value" pairs and we want to
list what we find in the header.
+As there is no mandatory set of keys a client has to send, each key-value pair
is printed out one by
one until there are no more left. We do this by writing a separate function
which will be called for
each pair just like the above function is called for each HTTP request.
It can then print out the content of this pair.
-</p><pre class="verbatim">int print_out_key (void *cls, enum MHD_ValueKind
kind, const char *key, const char *value)
+</p><pre class="verbatim">int print_out_key (void *cls, enum MHD_ValueKind
kind,
+ const char *key, const char *value)
{
- printf ("%s = %s\n", key, value);
+ printf ("%s: %s\n", key, value);
return MHD_YES;
}
</pre>
<p>To start the iteration process that calls our new function for every key,
the line
-</p><pre class="verbatim">MHD_get_connection_values (connection,
MHD_HEADER_KIND, print_out_key, NULL);
+</p><pre class="verbatim">MHD_get_connection_values (connection,
MHD_HEADER_KIND, &print_out_key, NULL);
</pre><p>needs to be inserted in the connection callback function too. The
second parameter tells the function
that we are only interested in keys from the general HTTP header of the
request. Our iterating
-function <code>PrintOutKey</code> does not rely on any additional information
to fulfill its duties
+function <code>print_out_key</code> does not rely on any additional
information to fulfill its duties
so the last parameter can be NULL.
</p>
-<p>All in all, this constitutes the complete <code>logger.c</code> program for
this chapter which can be
+<p>All in all, this constitutes the complete <code>logging.c</code> program
for this chapter which can be
found in the <code>examples</code> section.
</p>
<p>Connecting with any modern Internet browser should yield a handful of keys.
You should try to
interpret them with the aid of <em>RFC 2616</em>.
-Especially worth mentioning is the host key which is often used to serve
several different websites
-hosted under one single IP address but reachable by different domain names.
+Especially worth mentioning is the "Host" key which is often used to
serve several different websites
+hosted under one single IP address but reachable by different domain names
(this is called virtual hosting).
</p>
-<a name="SEC6"></a>
-<h2 class="heading"> Conclusion </h2>
+<a name="Conclusion"></a>
+<h2 class="heading">Conclusion</h2>
<p>The introduced capabilities to itemize the content of a simple GET
request—especially the
-URI—should already allow the server to satisfy clients' requests for
small specific resources
-(e.g. files) or even induce alteration of how the server operates. However,
the latter is not
-recommended as the GET method (including its header data) is by convention
considered a "SAFE"
-operation, which should not change the server's state in a significant way,
but temporally actions
-like searching for a passed string is fine.
+URI—should already allow the server to satisfy clients’ requests
for small specific resources
+(e.g. files) or even induce alteration of server state. However, the latter is
not
+recommended as the GET method (including its header data) is by convention
considered a "safe"
+operation, which should not change the server’s state in a significant
way. By convention,
+GET operations can thus be performed by crawlers and other automatic software.
Naturally
+actions like searching for a passed string are fine.
</p>
<p>Of course, no transmission can occur while the return value is still set to
<code>MHD_NO</code> in the
callback function.
</p>
-<a name="SEC7"></a>
-<h2 class="heading"> Exercises </h2>
+<a name="Exercises-2"></a>
+<h2 class="heading">Exercises</h2>
<ul>
<li>
By parsing the <code>url</code> string and delivering responses accordingly,
implement a small server for
@@ -423,40 +459,41 @@
returned accompanied by an informative message.
</li><li>
-A very interesting information has still been ignored by our logger—the
client's IP address.
+A very interesting information has still been ignored by our logger—the
client’s IP address.
Implement a callback function
-<pre class="verbatim">int on_client_connect (void *cls,
- const struct sockaddr *addr,socklen_t addrlen)
-</pre><p>that prints out the IP address in an appropriate format. You might
want to use the posix function
+<pre class="verbatim">static int on_client_connect (void *cls,
+ const struct sockaddr *addr,
+ socklen_t addrlen)
+</pre><p>that prints out the IP address in an appropriate format. You might
want to use the POSIX function
<code>inet_ntoa</code> but bear in mind that <code>addr</code> is actually
just a structure containing other
substructures and is <em>not</em> the variable this function expects.
Make sure to return <code>MHD_YES</code> so that the library knows the client
is allowed to connect
-(and to request). If one wanted to limit access basing on IP addresses, this
would be the place
-to do it. The address of your function will then be passed as the third
parameter of the
+(and to then process the request). If one wanted to limit access basing on IP
addresses, this would be the place
+to do it. The address of your <code>on_client_connect</code> function must be
passed as the third parameter to the
<code>MHD_start_daemon</code> call.
</p>
</li></ul>
<hr size="6">
<a name="Response-headers"></a>
-<a name="SEC8"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC5" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC11" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Exploring-requests"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Supporting-basic-authentication"
title="Next section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC5" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC11" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Exploring-requests"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Supporting-basic-authentication"
title="Next chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 4. Response headers </h1>
+<a name="Response-headers-1"></a>
+<h1 class="chapter">4. Response headers</h1>
<p>Now that we are able to inspect the incoming request in great detail,
this chapter discusses the means to enrich the outgoing responses likewise.
</p>
@@ -468,7 +505,7 @@
</p>
<p>When we responded with HTML page packed in the static string previously,
the client had no choice
-but guessing about how to handle the response, because the server hadn't told
him.
+but guessing about how to handle the response, because the server had not told
him.
What if we had sent a picture or a sound file? Would the message have been
understood
or merely been displayed as an endless stream of random characters in the
browser?
This is what the mime content types are for. The header of the response is
extended
@@ -481,42 +518,55 @@
<pre class="verbatim">#define FILENAME "picture.png"
#define MIMETYPE "image/png"
-int answer_to_connection (void *cls, struct MHD_Connection *connection, const
char *url,
- const char *method, const char *version, const char
*upload_data,
- size_t *upload_data_size, void **con_cls)
+static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url,
+ const char *method, const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
unsigned char *buffer = NULL;
struct MHD_Response *response;
</pre>
-<p>We want the program to load the graphics file into memory:
-</p><pre class="verbatim"> long size;
- FILE *fp;
- int ret = 0;
+<p>We want the program to open the file for reading and determine its size:
+</p><pre class="verbatim"> int fd;
+ int ret;
+ struct stat sbuf;
- if (0 != strcmp(method, "GET")) return MHD_NO;
-
- size = get_file_size (FILENAME);
- if (size != 0)
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO;
+ if ( (-1 == (fd = open (FILENAME, O_RDONLY))) ||
+ (0 != fstat (fd, &sbuf)) )
{
- fp = fopen (FILENAME, "rb");
- if (fp)
- {
- buffer = malloc (size);
-
- if (buffer)
- if (size == fread (buffer, 1, size, fp)) ret = 1;
-
- fclose(fp);
- }
+ /* error accessing file */
+ /* ... (see below) */
}
+ /* ... (see below) */
</pre>
-<p>The <code>GetFileSize</code> function, which returns a size of zero if the
file could not be opened or
-found, is left out on this page for tidiness.
-</p>
-<p>When dealing with files and allocating memory, there is a lot that could go
wrong on the
+<p>When dealing with files, there is a lot that could go wrong on the
server side and if so, the client should be informed with
<code>MHD_HTTP_INTERNAL_SERVER_ERROR</code>.
</p>
-<pre class="verbatim"> if (!ret)
+<pre class="verbatim"> /* error accessing file */
+ if (fd != -1) close (fd);
+ const char *errorstr =
+ "<html><body>An internal server error has occured!\
+ </body></html>";
+ response =
+ MHD_create_response_from_data (strlen (errorstr),
+ (void *) errorstr,
+ MHD_NO, MHD_NO);
+ if (response)
+ {
+ ret =
+ MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
+ response);
+ MHD_destroy_response (response);
+
+ return MHD_YES;
+ }
+ else
+ return MHD_NO;
+ if (!ret)
{
const char *errorstr = "<html><body>An internal server
error has occured!\
</body></html>";
@@ -528,7 +578,9 @@
if (response)
{
- ret = MHD_queue_response (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, response);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ response);
MHD_destroy_response (response);
return MHD_YES;
@@ -540,19 +592,22 @@
Otherwise, the connection would just be closed without comment, leaving the
client curious about
what has happened.
</p>
-<p>But in the case of success a response will be constructed that contains the
buffer filled with the
-file's content.
+<p>But in the case of success a response will be constructed directly from the
file descriptor:
</p>
-<pre class="verbatim">response = MHD_create_response_from_data (size,
(void*)buffer, MHD_YES, MHD_NO);
+<pre class="verbatim"> /* error accessing file */
+ /* ... (see above) */
+ }
+
+ response =
+ MHD_create_response_from_fd (fd, sbuf.st_size);
+ MHD_add_response_header (response, "Content-Type", MIMETYPE);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
</pre>
-<p>Contrary to the above case where a static string will be sent, this time we
have to
-keep track of the dynamically allocated buffer. As discussed in the <a
href="#SEC2">Hello browser example</a>,
-the buffer cannot be safely freed as soon as the function call returns.
Instead, we ask the function
-to keep charge of freeing the buffer itself when it is not longer needed.
Thus, no further <code>free</code>
-command is invoked by us.
+<p>Note that the response object will take care of closing the file desciptor
for us.
</p>
<p>Up to this point, there was little new. The actual novelty is that we
enhance the header with the
-meta data about the content. Aware of the field's name we want to add, it is
as easy as that:
+meta data about the content. Aware of the field’s name we want to add,
it is as easy as that:
</p><pre class="verbatim">MHD_add_response_header(response,
"Content-Type", MIMETYPE);
</pre><p>We do not have to append a colon expected by the protocol hehind the
first
field—<em>GNU libhttpdmicro</em> will take care of this.
@@ -567,8 +622,8 @@
Find a <em>PNG</em> file you like and save it to the directory the example is
run from under the name
<code>picture.png</code>. You should find the image displayed on your browser
if everything worked well.
</p>
-<a name="SEC9"></a>
-<h2 class="heading"> Remarks </h2>
+<a name="Remarks-4"></a>
+<h2 class="heading">Remarks</h2>
<p>The include file of the <em>MHD</em> library comes with the header types
mentioned in <em>RFC 2616</em>
already defined as macros. Thus, we could have written
<code>MHD_HTTP_HEADER_CONTENT_TYPE</code> instead
of <code>"Content-Type"</code> as well. However, one is not limited
to these standard headers and could
@@ -577,17 +632,15 @@
headers to the server as well, opening up yet more possibilities how client
and server could
communicate with each other.
</p>
-<p>The method of creating the response from one big chunk of data is only
feasible for smaller files.
-A public file server satisfying many request at the same time would be choking
under these high
-demands on memory very soon. Serving responses in smaller parts would be more
adequate here and
-will be a topic of a future chapter.
+<p>The method of creating the response from a file on disk only works for
static content.
+Serving dynamically created responses will be a topic of a future chapter.
</p>
-<a name="SEC10"></a>
-<h2 class="heading"> Exercises </h2>
+<a name="Exercises-1"></a>
+<h2 class="heading">Exercises</h2>
<ul>
<li>
-Remember that the original program was written under a few assumptions—a
small, static response
-being one of them. In order to simulate a very large or hard to reach file
that cannot be provided
+Remember that the original program was written under a few assumptions—a
static response
+using a local file being one of them. In order to simulate a very large or
hard to reach file that cannot be provided
instantly, postpone the queuing in the callback with the <code>sleep</code>
function for 30 seconds
<em>if</em> the file <code>/big.png</code> is requested (but deliver the same
as above). A request for
<code>/picture.png</code> should provide just the same but without any
artificial delays.
@@ -601,16 +654,16 @@
</li><li>
Did you succeed in implementing the clock exercise yet? This time, let the
server save the
-program's start time <code>t</code> and implement a response simulating a
countdown that reaches 0 at
+program’s start time <code>t</code> and implement a response simulating
a countdown that reaches 0 at
<code>t+60</code>. Returning a message saying on which point the countdown is,
the response should
ultimately be to reply "Done" if the program has been running long
enough,
-<p>A non official, but widely understood, response header line is
<code>Refresh: DELAY; url=URL</code> with
+<p>An unofficial, but widely understood, response header line is
<code>Refresh: DELAY; url=URL</code> with
the uppercase words substituted to tell the client it should request the given
resource after
the given delay again. Improve your program in that the browser (any modern
browser should work)
automatically reconnects and asks for the status again every 5 seconds or so.
The URL would have
to be composed so that it begins with "http://", followed by the
<em>URI</em> the server is reachable
-from the client's point of view.
+from the client’s point of view.
</p>
<p>Maybe you want also to visualize the countdown as a status bar by creating
a
<code><table></code> consisting of one row and <code>n</code> columns
whose fields contain small images of either
@@ -620,27 +673,27 @@
<hr size="6">
<a name="Supporting-basic-authentication"></a>
-<a name="SEC11"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC8" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC16" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Response-headers"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Processing-POST-data" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC8" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC16" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Response-headers" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Processing-POST-data" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 5. Supporting basic authentication </h1>
+<a name="Supporting-basic-authentication-1"></a>
+<h1 class="chapter">5. Supporting basic authentication</h1>
<p>With the small exception of IP address based access control,
requests from all connecting clients where served equally until now.
-This chapter discusses a first method of client's authentication and
+This chapter discusses a first method of client’s authentication and
its limits.
</p>
<p>A very simple approach feasible with the means already discussed would
@@ -649,9 +702,10 @@
by a certain character, thus the request line might look like
</p><pre class="verbatim">GET /picture.png?mypassword
</pre>
-<p>In a situation where the client is customized enough and the connection
occurs
-through secured lines (e.g., a embedded device directly attached to another
via wire),
-this can be a reasonable choice.
+<p>In the rare situation where the client is customized enough and the
connection occurs
+through secured lines (e.g., a embedded device directly attached to another
via wire)
+and where the ability to embedd a password in the URI or to pass on a URI with
a
+password are desired, this can be a reasonable choice.
</p>
<p>But when it is assumed that the user connecting does so with an ordinary
Internet browser,
this implementation brings some problems about. For example, the URI including
the password
@@ -674,14 +728,15 @@
Thus, we will generate no response until the parameter is
non-null—implying the callback was
called before at least once. We do not need to share information between
different calls of the callback,
so we can set the parameter to any adress that is assured to be not null. The
pointer to the
-<code>connection</code> structure will be pointing to a legal adress, so we
take this.
+<code>connection</code> structure will be pointing to a legal address, so we
take this.
</p>
-<p>Not even the headers will be looked at on the first iteration.
+<p>The first time <code>answer_to_connection</code> is called, we will not
even look at the headers.
</p>
-<pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection,
- const char *url, const char *method, const char
*version,
- const char *upload_data, size_t *upload_data_size,
- void **con_cls)
+<pre class="verbatim">static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char
*version,
+ const char *upload_data, size_t *upload_data_size,
+ void **con_cls)
{
if (0 != strcmp(method, "GET")) return MHD_NO;
if (NULL == *con_cls) {*con_cls = connection; return MHD_YES;}
@@ -691,12 +746,12 @@
...
}
</pre>
-<p>Note how we lop off the connection on the first condition, but return
asking for more on
+<p>Note how we lop off the connection on the first condition (no
"GET" request), but return asking for more on
the other one with <code>MHD_YES</code>.
-With the framework improved, we can proceed to implement the actual
authentication process.
+With this minor change, we can proceed to implement the actual authentication
process.
</p>
-<a name="SEC12"></a>
-<h2 class="heading"> Request for authentication </h2>
+<a name="Request-for-authentication"></a>
+<h2 class="heading">Request for authentication </h2>
<p>Let us assume we had only files not intended to be handed out without the
correct username/password,
so every "GET" request will be challenged.
@@ -704,7 +759,8 @@
<em>WWW-Authenticate</em> response header with the name of the <em>realm</em>
protected.
</p>
<p>We let an extra function function do this.
-</p><pre class="verbatim">int ask_for_authentication (struct MHD_Connection
*connection, const char *realm)
+</p><pre class="verbatim">static int
+ask_for_authentication (struct MHD_Connection *connection, const char *realm)
{
int ret;
struct MHD_Response *response;
@@ -725,20 +781,18 @@
if (!ret) {MHD_destroy_response (response); return MHD_NO;}
ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
-
MHD_destroy_response (response);
-
return ret;
}
</pre>
<p><code>#define</code> the realm name according to your own taste, e.g.
"Maintenance" or "Area51" but
it will need to have extra quotes.
</p>
-<p>But the client may send the authentication right away, so it would be wrong
to ask for
-it without checking the request's header–where the authentication is
expected to be found.
+<p>Since the client may send the authentication right away, it would be wrong
to ask for
+it without checking the request’s header–where the authentication
is expected to be found.
</p>
-<a name="SEC13"></a>
-<h2 class="heading"> Authentication in detail </h2>
+<a name="Authentication-in-detail"></a>
+<h2 class="heading">Authentication in detail</h2>
<p>Checking <em>RFC 2617</em> again, we find that the client will pack the
username and password, by
whatever means he might have obtained them, in a line separated by a
colon—and then encodes
them to <em>Base64</em>. The actual implementation of this encoding are not
within the scope of
@@ -748,8 +802,9 @@
and the resulting line is the value of a request header of the type
"Authorization".
</p>
<p>This header line thus is of interest to the function checking a connection
for a given username/password:
-</p><pre class="verbatim">int is_authenticated (struct MHD_Connection
*connection,
- const char *username, const char *password)
+</p><pre class="verbatim">static int
+is_authenticated (struct MHD_Connection *connection,
+ const char *username, const char *password)
{
const char *headervalue;
...
@@ -797,33 +852,33 @@
</pre>
<p>See the <code>examples</code> directory for the complete example file.
</p>
-<a name="SEC14"></a>
-<h2 class="heading"> Remarks </h2>
+<a name="Remarks-2"></a>
+<h2 class="heading">Remarks</h2>
<p>For a proper server, the conditional statements leading to a return of
<code>MHD_NO</code> should yield a
response with a more precise status code instead of silently closing the
connection. For example,
failures of memory allocation are best reported as <em>internal server
error</em> and unexpected
authentication methods as <em>400 bad request</em>.
</p>
-<a name="SEC15"></a>
-<h2 class="heading"> Exercises </h2>
+<a name="Exercises-3"></a>
+<h2 class="heading">Exercises</h2>
<ul>
<li>
-Make the server respond to wrong credentials (but else correct requests) with
the recommended
+Make the server respond to wrong credentials (but otherwise well-formed
requests) with the recommended
<em>401 unauthorized</em> status code. If the client still does not
authenticate correctly within the
-same connection, close it and store the client's IP address for a certain
time. (It is OK to check for
+same connection, close it and store the client’s IP address for a
certain time. (It is OK to check for
expiration not until the main thread wakes up again on the next connection.)
If the client fails
-authenticating three times during this period, add it to another list whose
entries the
+authenticating three times during this period, add it to another list for
which the
<code>AcceptPolicyCallback</code> function denies connection (temporally).
</li><li>
-With the network utility <em>netcat</em> connect and log the response of a
"GET" request as you
+With the network utility <code>netcat</code> connect and log the response of a
"GET" request as you
did in the exercise of the first example, this time to a file. Now stop the
server and let <em>netcat</em>
listen on the same port the server used to listen on and have it fake being
the proper server by giving
-the file's content as the response (e.g. <code>cat log | nc -l -p
8888</code>). Pretending to think your were
+the file’s content as the response (e.g. <code>cat log | nc -l -p
8888</code>). Pretending to think your were
connecting to the actual server, browse to the eavesdropper and give the
correct credentials.
-<p>Copy and paste the encoded string you see in netcat's output to some of the
Base64 decode tools available online
-and see how both the user's name and password could be completely restored.
+<p>Copy and paste the encoded string you see in <code>netcat</code>’s
output to some of the Base64 decode tools available online
+and see how both the user’s name and password could be completely
restored.
</p>
</li></ul>
@@ -831,37 +886,37 @@
<hr size="6">
<a name="Processing-POST-data"></a>
-<a name="SEC16"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC11" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC20" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a
href="#Supporting-basic-authentication" title="Previous section in reading
order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Improved-processing-of-POST-data"
title="Next section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC11" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC20" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Supporting-basic-authentication"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Improved-processing-of-POST-data"
title="Next chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 6. Processing POST data </h1>
+<a name="Processing-POST-data-1"></a>
+<h1 class="chapter">6. Processing POST data</h1>
<p>The previous chapters already have demonstrated a variety of possibilities
to send information
to the HTTP server, but it is not recommended that the <em>GET</em> method is
used to alter the way
the server operates. To induce changes on the server, the <em>POST</em> method
is preferred over
and is much more powerful than <em>GET</em> and will be introduced in this
chapter.
</p>
-<p>We are going to write an application that asks for the visitor's name and,
after the user has posted it,
-composes an individual response text. Even though it was not mandatory to use
the <em>post</em> method here,
-as there is no permanent change caused by the post, it is an illustrative
example on how to share data
+<p>We are going to write an application that asks for the visitor’s name
and, after the user has posted it,
+composes an individual response text. Even though it was not mandatory to use
the <em>POST</em> method here,
+as there is no permanent change caused by the POST, it is an illustrative
example on how to share data
between different functions for the same connection. Furthermore, the reader
should be able to extend
it easily.
</p>
-<a name="SEC17"></a>
-<h2 class="heading"> GET request </h2>
+<a name="GET-request"></a>
+<h2 class="heading">GET request</h2>
<p>When the first <em>GET</em> request arrives, the server shall respond with
a HTML page containing an
edit field for the name.
</p>
@@ -873,7 +928,7 @@
</body></html>";
</pre>
<p>The <code>action</code> entry is the <em>URI</em> to be called by the
browser when posting, and the
-<code>name</code> will be used later to be sure it is the editbox's content
that has been posted.
+<code>name</code> will be used later to be sure it is the editbox’s
content that has been posted.
</p>
<p>We also prepare the answer page, where the name is to be filled in later,
and an error page
as the response for anything but proper <em>GET</em> and <em>POST</em>
requests:
@@ -883,12 +938,13 @@
const char* errorpage="<html><body>This doesn't seem to be
right.</body></html>";
</pre>
<p>Whenever we need to send a page, we use an extra function
-<code>int SendPage(struct MHD_Connection *connection, const char* page)</code>
-for this, which does not contain anything new and whose implementation is
therefore left out here.
+<code>int send_page(struct MHD_Connection *connection, const char* page)</code>
+for this, which does not contain anything new and whose implementation is
therefore
+not discussed further in the tutorial.
</p>
-<a name="SEC18"></a>
-<h2 class="heading"> POST request </h2>
+<a name="POST-request"></a>
+<h2 class="heading">POST request</h2>
<p>Posted data can be of arbitrary and considerable size; for example, if a
user uploads a big
image to the server. Similar to the case of the header fields, there may also
be different streams
of posted data, such as one containing the text of an editbox and another the
state of a button.
@@ -916,12 +972,13 @@
chunks, we had to expand the namestring dynamically as additional parts of it
with the same <code>key</code>
came in. But in this example, the name is assumed to fit entirely inside one
single packet.
</p>
-<pre class="verbatim">int iterate_post (void *coninfo_cls, enum MHD_ValueKind
kind, const char *key,
- const char *filename, const char *content_type,
- const char *transfer_encoding, const char *data, uint64_t
off, size_t size)
+<pre class="verbatim">static int
+iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
+ const char *filename, const char *content_type,
+ const char *transfer_encoding, const char *data,
+ uint64_t off, size_t size)
{
- struct connection_info_struct *con_info = (struct connection_info_struct*)
coninfo_cls;
-
+ struct connection_info_struct *con_info = coninfo_cls;
if (0 == strcmp (key, "name"))
{
@@ -948,14 +1005,13 @@
string. This cleanup function must take into account that it will also be
called for finished
requests other than <em>POST</em> requests.
</p>
-<pre class="verbatim">void request_completed (void *cls, struct MHD_Connection
*connection, void **con_cls,
+<pre class="verbatim">void request_completed (void *cls, struct MHD_Connection
*connection,
+ void **con_cls,
enum MHD_RequestTerminationCode toe)
{
- struct connection_info_struct *con_info = (struct connection_info_struct*)
*con_cls;
+ struct connection_info_struct *con_info = *con_cls;
-
if (NULL == con_info) return;
-
if (con_info->connectiontype == POST)
{
MHD_destroy_post_processor (con_info->postprocessor);
@@ -971,21 +1027,25 @@
</p>
<pre class="verbatim">...
daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
- &answer_to_connection, NULL,
MHD_OPTION_NOTIFY_COMPLETED,
- request_completed, NULL, MHD_OPTION_END);
+ &answer_to_connection, NULL,
+ MHD_OPTION_NOTIFY_COMPLETED, &request_completed,
NULL,
+ MHD_OPTION_END);
...
</pre>
-<a name="SEC19"></a>
-<h2 class="heading"> Request handling </h2>
+<a name="Request-handling"></a>
+<h2 class="heading">Request handling</h2>
<p>With all other functions prepared, we can now discuss the actual request
handling.
</p>
<p>On the first iteration for a new request, we start by allocating a new
instance of a
-<code>ConnectionInfoStruct</code> structure, which will store all necessary
information for later
+<code>struct connection_info_struct</code> structure, which will store all
necessary information for later
iterations and other functions.
</p>
-<pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection, const char *url,
- const char *method, const char *version, const char
*upload_data,
- size_t *upload_data_size, void **con_cls)
+<pre class="verbatim">static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url,
+ const char *method, const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
if(NULL == *con_cls)
{
@@ -999,15 +1059,15 @@
of the request is stored for convenience.
</p><pre class="verbatim"> if (0 == strcmp (method, "POST"))
{
- con_info->postprocessor = MHD_create_post_processor (connection,
POSTBUFFERSIZE,
- iterate_post,
(void*) con_info);
+ con_info->postprocessor
+ = MHD_create_post_processor (connection, POSTBUFFERSIZE,
+ iterate_post, (void*) con_info);
if (NULL == con_info->postprocessor)
{
free (con_info);
return MHD_NO;
}
-
con_info->connectiontype = POST;
}
else con_info->connectiontype = GET;
@@ -1034,15 +1094,17 @@
if (*upload_data_size != 0)
{
- MHD_post_process(con_info->postprocessor, upload_data,
*upload_data_size);
+ MHD_post_process (con_info->postprocessor, upload_data,
+ *upload_data_size);
*upload_data_size = 0;
return MHD_YES;
}
- else if (NULL != con_info->answerstring) return send_page
(connection, con_info->answerstring);
+ else if (NULL != con_info->answerstring)
+ return send_page (connection, con_info->answerstring);
}
</pre>
-<p>If they are neither <em>GET</em> nor <em>POST</em> requests, the error page
is returned finally.
+<p>Finally, if they are neither <em>GET</em> nor <em>POST</em> requests, the
error page is returned.
</p><pre class="verbatim"> return send_page(connection, errorpage);
}
</pre>
@@ -1050,51 +1112,53 @@
</p>
<hr size="6">
<a name="Improved-processing-of-POST-data"></a>
-<a name="SEC20"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC16" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC25" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Processing-POST-data"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Adding-a-layer-of-security"
title="Next section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC16" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC25" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Processing-POST-data"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Adding-a-layer-of-security"
title="Next chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 7. Improved processing of POST data </h1>
+<a name="Improved-processing-of-POST-data-1"></a>
+<h1 class="chapter">7. Improved processing of POST data</h1>
<p>The previous chapter introduced a way to upload data to the server, but the
developed example program
has some shortcomings, such as not being able to handle larger chunks of data.
In this chapter, we
are going to discuss a more advanced server program that allows clients to
upload a file in order to
-have it stored on the server's filesystem. The server shall also watch and
limit the number of
+have it stored on the server’s filesystem. The server shall also watch
and limit the number of
clients concurrently uploading, responding with a proper busy message if
necessary.
</p>
-<a name="SEC21"></a>
-<h2 class="heading"> Prepared answers </h2>
+<a name="Prepared-answers"></a>
+<h2 class="heading">Prepared answers</h2>
<p>We choose to operate the server with the <code>SELECT_INTERNALLY</code>
method. This makes it easier to
synchronize the global states at the cost of possible delays for other
connections if the processing
of a request is too slow. One of these variables that needs to be shared for
all connections is the
total number of clients that are uploading.
</p>
<pre class="verbatim">#define MAXCLIENTS 2
-static unsigned char nr_of_uploading_clients = 0;
+static unsigned int nr_of_uploading_clients = 0;
</pre>
<p>If there are too many clients uploading, we want the server to respond to
all requests with a busy
message.
-</p><pre class="verbatim">const char* busypage =
"<html><body>This server is busy, please try again
later.</body></html>";
+</p><pre class="verbatim">const char* busypage =
+ "<html><body>This server is busy, please try again
later.</body></html>";
</pre>
<p>Otherwise, the server will send a <em>form</em> that informs the user of
the current number of uploading clients,
and ask her to pick a file on her local filesystem which is to be uploaded.
</p><pre class="verbatim">const char* askpage =
"<html><body>\n\
Upload a file, please!<br>\n\
- There are %d clients uploading at the
moment.<br>\n\
- <form action=\"/filepost\"
method=\"post\" enctype=\"multipart/form-data\">\n\
+ There are %u clients uploading at the
moment.<br>\n\
+ <form action=\"/filepost\"
method=\"post\" \
+ enctype=\"multipart/form-data\">\n\
<input name=\"file\"
type=\"file\">\n\
<input type=\"submit\" value=\" Send
\"></form>\n\
</body></html>";
@@ -1104,20 +1168,24 @@
</pre>
<p>We want the server to report internal errors, such as memory shortage or
file access problems,
adequately.
-</p><pre class="verbatim">const char* servererrorpage =
"<html><body>An internal server error has
occured.</body></html>";
-const char* fileexistspage = "<html><body>This file already
exists.</body></html>";
+</p><pre class="verbatim">const char* servererrorpage
+ = "<html><body>An internal server error has
occured.</body></html>";
+const char* fileexistspage
+ = "<html><body>This file already
exists.</body></html>";
</pre>
<p>It would be tolerable to send all these responses undifferentiated with a
<code>200 HTTP_OK</code>
status code but in order to improve the <code>HTTP</code> conformance of our
server a bit, we extend the
<code>send_page</code> function so that it accepts individual status codes.
</p>
-<pre class="verbatim">int send_page (struct MHD_Connection *connection, const
char* page, int status_code)
+<pre class="verbatim">static int
+send_page (struct MHD_Connection *connection,
+ const char* page, int status_code)
{
int ret;
struct MHD_Response *response;
-
- response = MHD_create_response_from_data (strlen (page), (void*) page,
MHD_NO, MHD_YES);
+ response = MHD_create_response_from_data (strlen (page), (void*) page,
+ MHD_NO, MHD_YES);
if (!response) return MHD_NO;
ret = MHD_queue_response (connection, status_code, response);
@@ -1130,16 +1198,19 @@
become clear later.
</p>
-<a name="SEC22"></a>
-<h2 class="heading"> Connection cycle </h2>
+<a name="Connection-cycle"></a>
+<h2 class="heading">Connection cycle</h2>
<p>The decision whether the server is busy or not is made right at the
beginning of the connection. To
do that at this stage is especially important for <em>POST</em> requests
because if no response is
queued at this point, and <code>MHD_YES</code> returned, <em>MHD</em> will not
sent any queued messages until
a postprocessor has been created and the post iterator is called at least once.
</p>
-<pre class="verbatim">int answer_to_connection (void *cls, struct
MHD_Connection *connection, const char *url,
- const char *method, const char *version, const char
*upload_data,
- size_t *upload_data_size, void **con_cls)
+<pre class="verbatim">static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url,
+ const char *method, const char *version,
+ const char *upload_data,
+ size_t *upload_data_size, void **con_cls)
{
if (NULL == *con_cls)
{
@@ -1174,8 +1245,9 @@
the structure is initialized to "no error".
</p><pre class="verbatim"> if (0 == strcmp (method, "POST"))
{
- con_info->postprocessor = MHD_create_post_processor (connection,
POSTBUFFERSIZE,
- iterate_post,
(void*) con_info);
+ con_info->postprocessor
+ = MHD_create_post_processor (connection, POSTBUFFERSIZE,
+ iterate_post, (void*) con_info);
if (NULL == con_info->postprocessor)
{
@@ -1197,7 +1269,7 @@
</p><pre class="verbatim"> if (0 == strcmp (method, "GET"))
{
int ret;
- char buffer[1024] = {0};
+ char buffer[1024];
sprintf (buffer, askpage, nr_of_uploading_clients);
return send_page (connection, buffer, MHD_HTTP_OK);
@@ -1214,29 +1286,35 @@
if (0 != *upload_data_size)
{
- MHD_post_process(con_info->postprocessor, upload_data,
*upload_data_size);
+ MHD_post_process (con_info->postprocessor,
+ upload_data, *upload_data_size);
*upload_data_size = 0;
return MHD_YES;
}
- else return send_page (connection, con_info->answerstring,
con_info->answercode);
+ else
+ return send_page (connection, con_info->answerstring,
+ con_info->answercode);
}
return send_page(connection, errorpage, MHD_HTTP_BAD_REQUEST);
}
</pre>
-<a name="SEC23"></a>
-<h2 class="heading"> Storing to data </h2>
+<a name="Storing-to-data"></a>
+<h2 class="heading">Storing to data</h2>
<p>Unlike the <code>simplepost.c</code> example, here it is to be expected
that post iterator will be called
several times now. This means that for any given connection (there might be
several concurrent of them)
the posted data has to be written to the correct file. That is why we store a
file handle in every
<code>connection_info</code>, so that the it is preserved between successive
iterations.
-</p><pre class="verbatim">int iterate_post (void *coninfo_cls, enum
MHD_ValueKind kind, const char *key,
- const char *filename, const char *content_type,
- const char *transfer_encoding, const char *data, uint64_t
off, size_t size)
+</p><pre class="verbatim">static int
+iterate_post (void *coninfo_cls, enum MHD_ValueKind kind,
+ const char *key,
+ const char *filename, const char *content_type,
+ const char *transfer_encoding, const char *data,
+ uint64_t off, size_t size)
{
- struct connection_info_struct *con_info = (struct connection_info_struct*)
coninfo_cls;
+ struct connection_info_struct *con_info = coninfo_cls;
</pre>
<p>Because the following actions depend heavily on correct file processing,
which might be error prone,
we default to reporting internal errors in case anything will go wrong.
@@ -1252,10 +1330,11 @@
<p>If the iterator is called for the first time, no file will have been opened
yet. The <code>filename</code>
string contains the name of the file (without any paths) the user selected on
his system. We want to
take this as the name the file will be stored on the server and make sure no
file of that name exists
-(or is being uploaded) before we create one.
+(or is being uploaded) before we create one (note that the code below
technically contains a
+race between the two "fopen" calls, but we will overlook this for
portability sake).
</p><pre class="verbatim"> if (!con_info->fp)
{
- if (NULL != (fp = fopen (filename, "r")) )
+ if (NULL != (fp = fopen (filename, "rb")) )
{
fclose (fp);
con_info->answerstring = fileexistspage;
@@ -1272,7 +1351,8 @@
server only needs to write data to the file if there is some.
</p><pre class="verbatim">if (size > 0)
{
- if (!fwrite (data, size, sizeof(char), con_info->fp)) return MHD_NO;
+ if (!fwrite (data, size, sizeof(char), con_info->fp))
+ return MHD_NO;
}
</pre>
<p>If this point has been reached, everything worked well for this iteration
and the response can
@@ -1286,10 +1366,11 @@
<p>The new client was registered when the postprocessor was created. Likewise,
we unregister the client
on destroying the postprocessor when the request is completed.
-</p><pre class="verbatim">void request_completed (void *cls, struct
MHD_Connection *connection, void **con_cls,
+</p><pre class="verbatim">void request_completed (void *cls, struct
MHD_Connection *connection,
+ void **con_cls,
enum MHD_RequestTerminationCode toe)
{
- struct connection_info_struct *con_info = (struct connection_info_struct*)
*con_cls;
+ struct connection_info_struct *con_info = *con_cls;
if (NULL == con_info) return;
@@ -1312,32 +1393,33 @@
<p>This is essentially the whole example <code>largepost.c</code>.
</p>
-<a name="SEC24"></a>
-<h2 class="heading"> Remarks </h2>
+<a name="Remarks"></a>
+<h2 class="heading">Remarks</h2>
<p>Now that the clients are able to create files on the server, security
aspects are becoming even more
important than before. Aside from proper client authentication, the server
should always make sure
-explicitly that no files will be created outside of a dedicated upload
directory.
+explicitly that no files will be created outside of a dedicated upload
directory. In particular,
+filenames must be checked to not contain strings like "../".
</p>
<hr size="6">
<a name="Adding-a-layer-of-security"></a>
-<a name="SEC25"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC20" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC29" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a
href="#Improved-processing-of-POST-data" title="Previous section in reading
order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Bibliography" title="Next section
in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC20" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC29" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Improved-processing-of-POST-data"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Bibliography" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="chapter"> 8. Adding a layer of security </h1>
+<a name="Adding-a-layer-of-security-1"></a>
+<h1 class="chapter">8. Adding a layer of security</h1>
<p>We left the basic authentication chapter with the unsatisfactory conclusion
that
any traffic, including the credentials, could be intercepted by anyone between
the browser client and the server. Protecting the data while it is sent over
@@ -1349,8 +1431,8 @@
data being sent, with only minimal changes to the actual source code of the
example.
</p>
-<a name="SEC26"></a>
-<h2 class="heading"> Preparation </h2>
+<a name="Preparation"></a>
+<h2 class="heading">Preparation</h2>
<p>First, a private key for the server will be generated. With this key, the
server
will later be able to authenticate itself to the client—preventing
anyone else
@@ -1369,16 +1451,16 @@
have a name that matches the <em>URI</em>, for example, "localhost"
or the domain.
If you plan to have a publicly reachable server, you will need to ask a
trusted third party,
called <em>Certificate Authority</em>, or <em>CA</em>, to attest the
certificate for you. This way,
-any visitor can make sure the server's identity is real.
+any visitor can make sure the server’s identity is real.
</p>
-<p>Whether the server's certificate is signed by us or a third party, once it
has been accepted
+<p>Whether the server’s certificate is signed by us or a third party,
once it has been accepted
by the client, both sides will be communicating over encrypted channels. From
this point on,
-it is the client's turn to authenticate itself. But this has already been
implemented in the basic
+it is the client’s turn to authenticate itself. But this has already
been implemented in the basic
authentication scheme.
</p>
-<a name="SEC27"></a>
-<h2 class="heading"> Changing the source code </h2>
+<a name="Changing-the-source-code"></a>
+<h2 class="heading">Changing the source code</h2>
<p>We merely have to extend the server program so that it loads the two files
into memory,
</p>
@@ -1400,7 +1482,8 @@
</pre>
<p>and then we point the <em>MHD</em> daemon to it upon initalization.
</p><pre class="verbatim">
- daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT,
NULL, NULL,
+ daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
+ PORT, NULL, NULL,
&answer_to_connection, NULL,
MHD_OPTION_HTTPS_MEM_KEY, key_pem,
MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
@@ -1431,8 +1514,8 @@
<p>The rather unexciting file loader can be found in the complete example
<code>tlsauthentication.c</code>.
</p>
-<a name="SEC28"></a>
-<h2 class="heading"> Remarks </h2>
+<a name="Remarks-3"></a>
+<h2 class="heading">Remarks</h2>
<ul>
<li>
While the standard <em>HTTP</em> port is 80, it is 443 for <em>HTTPS</em>. The
common internet browsers assume
@@ -1453,32 +1536,31 @@
The cryptographic facilities consume memory space and computing time. For this
reason, websites usually consists
both of uncritically <em>HTTP</em> parts and secured <em>HTTPS</em>.
+
</li></ul>
-
-
<hr size="6">
<a name="Bibliography"></a>
-<a name="SEC29"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC25" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC31" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Adding-a-layer-of-security"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#License-text" title="Next section
in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC25" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC31" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Adding-a-layer-of-security"
title="Beginning of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#License-text" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="appendix"> A. Bibliography </h1>
-<a name="SEC30"></a>
-<h2 class="heading"> API reference </h2>
+<a name="Bibliography-1"></a>
+<h1 class="appendix">A. Bibliography</h1>
+<a name="API-reference"></a>
+<h2 class="heading">API reference</h2>
<ul>
<li>
The <em>GNU libmicrohttpd</em> manual by Marco Maggi and Christian Grothoff
2008
@@ -1510,24 +1592,24 @@
<hr size="6">
<a name="License-text"></a>
-<a name="SEC31"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC29" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Bibliography" title="Previous
section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC29" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Next chapter">
>> </a>]</td>
+<td valign="middle" align="left">[<a href="#Bibliography" title="Beginning of
this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Next
chapter"> >> </a>]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="appendix"> B. GNU Free Documentation License </h1>
+<a name="GNU-Free-Documentation-License"></a>
+<h1 class="appendix">B. GNU Free Documentation License</h1>
<p align="center"> Version 1.3, 3 November 2008
</p>
@@ -1582,7 +1664,7 @@
</p>
<p>A “Secondary Section” is a named appendix or a front-matter
section
of the Document that deals exclusively with the relationship of the
-publishers or authors of the Document to the Document's overall
+publishers or authors of the Document to the Document’s overall
subject (or to related matters) and contains nothing that could fall
directly within that overall subject. (Thus, if the Document is in
part a textbook of mathematics, a Secondary Section may not explain
@@ -1634,7 +1716,7 @@
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, “Title Page”
means
-the text near the most prominent appearance of the work's title,
+the text near the most prominent appearance of the work’s title,
preceding the beginning of the body of the text.
</p>
<p>The “publisher” means any person or entity that distributes
copies
@@ -1676,7 +1758,7 @@
<p>If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
-Document's license notice requires Cover Texts, you must enclose the
+Document’s license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover. Both covers must also clearly and legibly identify
@@ -1752,7 +1834,7 @@
</li><li>
Preserve in that license notice the full lists of Invariant Sections
-and required Cover Texts given in the Document's license notice.
+and required Cover Texts given in the Document’s license notice.
</li><li>
Include an unaltered copy of this License.
@@ -1802,7 +1884,7 @@
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant. To do this, add their titles to the
-list of Invariant Sections in the Modified Version's license notice.
+list of Invariant Sections in the Modified Version’s license notice.
These titles must be distinct from any other section titles.
</p>
<p>You may add a section Entitled “Endorsements”, provided it
contains
@@ -1871,14 +1953,14 @@
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an “aggregate” if the copyright
resulting from the compilation is not used to limit the legal rights
-of the compilation's users beyond what the individual works permit.
+of the compilation’s users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
</p>
<p>If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
-the entire aggregate, the Document's Cover Texts may be placed on
+the entire aggregate, the Document’s Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
@@ -1951,7 +2033,7 @@
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation. If the Document
specifies that a proxy can decide which future versions of this
-License can be used, that proxy's public statement of acceptance of a
+License can be used, that proxy’s public statement of acceptance of a
version permanently authorizes you to choose that version for the
Document.
</p>
@@ -1988,8 +2070,8 @@
</li></ol>
-<a name="SEC32"></a>
-<h2 class="heading"> ADDENDUM: How to use this License for your documents </h2>
+<a name="ADDENDUM_003a-How-to-use-this-License-for-your-documents"></a>
+<h2 class="heading">ADDENDUM: How to use this License for your documents</h2>
<p>To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and
@@ -2025,67 +2107,69 @@
<hr size="6">
<a name="Example-programs"></a>
-<a name="SEC33"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC31" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC34" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#License-text" title="Previous
section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#hellobrowser_002ec" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC31" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#License-text" title="Beginning of
this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Up section"> Up
</a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h1 class="appendix"> C. Example programs </h1>
+<a name="Example-programs-1"></a>
+<h1 class="appendix">C. Example programs</h1>
<table class="menu" border="0" cellspacing="0">
-<tr><td align="left" valign="top"><a href="#SEC34">C.1
hellobrowser.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#hellobrowser_002ec">C.1
hellobrowser.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC35">C.2
logging.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#logging_002ec">C.2
logging.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC36">C.3
responseheaders.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#responseheaders_002ec">C.3
responseheaders.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC37">C.4
basicauthentication.c</a></td><td> </td><td align="left"
valign="top">
+<tr><td align="left" valign="top"><a href="#basicauthentication_002ec">C.4
basicauthentication.c</a></td><td> </td><td align="left"
valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC38">C.5
simplepost.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#simplepost_002ec">C.5
simplepost.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC39">C.6
largepost.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#largepost_002ec">C.6
largepost.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
-<tr><td align="left" valign="top"><a href="#SEC40">C.7
tlsauthentication.c</a></td><td> </td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#tlsauthentication_002ec">C.7
tlsauthentication.c</a></td><td> </td><td align="left" valign="top">
</td></tr>
</table>
<hr size="6">
<a name="hellobrowser_002ec"></a>
-<a name="SEC34"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC33" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC35" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Example-programs"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#logging_002ec" title="Next section
in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.1 hellobrowser.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="hellobrowser_002ec-1"></a>
+<h2 class="section">C.1 hellobrowser.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
@@ -2123,45 +2207,47 @@
<hr size="6">
<a name="logging_002ec"></a>
-<a name="SEC35"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC34" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC36" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#hellobrowser_002ec"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#responseheaders_002ec" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.2 logging.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="logging_002ec-1"></a>
+<h2 class="section">C.2 logging.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
-int
+static int
print_out_key (void *cls, enum MHD_ValueKind kind, const char *key,
const char *value)
{
- printf ("%s = %s\n", key, value);
+ printf ("%s: %s\n", key, value);
return MHD_YES;
}
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls)
{
- printf ("New request %s for %s using version %s\n", method, url,
version);
+ printf ("New %s request for %s using version %s\n", method, url,
version);
MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key,
NULL);
@@ -2188,25 +2274,27 @@
<hr size="6">
<a name="responseheaders_002ec"></a>
-<a name="SEC36"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC35" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC37" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#logging_002ec" title="Previous
section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#basicauthentication_002ec"
title="Next section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.3 responseheaders.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="responseheaders_002ec-1"></a>
+<h2 class="section">C.3 responseheaders.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#include <time.h>
@@ -2214,73 +2302,32 @@
#define FILENAME "picture.png"
#define MIMETYPE "image/png"
-
-long
-get_file_size (const char *filename)
-{
- FILE *fp;
-
- fp = fopen (filename, "rb");
- if (fp)
- {
- long size;
-
- if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp))))
- size = 0;
-
- fclose (fp);
-
- return size;
- }
- else
- return 0;
-}
-
-
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls)
{
- unsigned char *buffer = NULL;
struct MHD_Response *response;
- long size;
- FILE *fp;
- int ret = 0;
+ int fd;
+ int ret;
+ struct stat sbuf;
if (0 != strcmp (method, "GET"))
return MHD_NO;
- size = get_file_size (FILENAME);
- if (size != 0)
+ if ( (-1 == (fd = open (FILENAME, O_RDONLY))) ||
+ (0 != fstat (fd, &sbuf)) )
{
- fp = fopen (FILENAME, "rb");
- if (fp)
- {
- buffer = malloc (size);
-
- if (buffer)
- if (size == fread (buffer, 1, size, fp))
- ret = 1;
-
- fclose (fp);
- }
- }
-
- if (!ret)
- {
+ /* error accessing file */
+ if (fd != -1) close (fd);
const char *errorstr =
"<html><body>An internal server error has occured!\
</body></html>";
-
- if (buffer)
- free (buffer);
-
response =
- MHD_create_response_from_data (strlen (errorstr), (void *) errorstr,
- MHD_NO, MHD_NO);
-
+ MHD_create_response_from_data (strlen (errorstr),
+ (void *) errorstr,
+ MHD_NO, MHD_NO);
if (response)
{
ret =
@@ -2293,12 +2340,9 @@
else
return MHD_NO;
}
-
response =
- MHD_create_response_from_data (size, (void *) buffer, MHD_YES, MHD_NO);
-
+ MHD_create_response_from_fd (fd, sbuf.st_size);
MHD_add_response_header (response, "Content-Type", MIMETYPE);
-
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
@@ -2326,25 +2370,27 @@
<hr size="6">
<a name="basicauthentication_002ec"></a>
-<a name="SEC37"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC36" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC38" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#responseheaders_002ec"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#simplepost_002ec" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.4 basicauthentication.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="basicauthentication_002ec-1"></a>
+<h2 class="section">C.4 basicauthentication.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#include <time.h>
@@ -2358,7 +2404,7 @@
char *string_to_base64 (const char *message);
-int
+static int
ask_for_authentication (struct MHD_Connection *connection, const char *realm)
{
int ret;
@@ -2392,7 +2438,7 @@
return ret;
}
-int
+static int
is_authenticated (struct MHD_Connection *connection,
const char *username, const char *password)
{
@@ -2418,20 +2464,19 @@
strcat (expected, password);
expected_b64 = string_to_base64 (expected);
+ free (expected);
if (NULL == expected_b64)
- return 0;
+ return 0;
- strcpy (expected, strbase);
authenticated =
(strcmp (headervalue + strlen (strbase), expected_b64) == 0);
free (expected_b64);
-
return authenticated;
}
-int
+static int
secret_page (struct MHD_Connection *connection)
{
int ret;
@@ -2451,7 +2496,7 @@
}
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
@@ -2530,25 +2575,27 @@
<hr size="6">
<a name="simplepost_002ec"></a>
-<a name="SEC38"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC37" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC39" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#basicauthentication_002ec"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#largepost_002ec" title="Next
section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.5 simplepost.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="simplepost_002ec-1"></a>
+<h2 class="section">C.5 simplepost.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
@@ -2580,7 +2627,7 @@
"<html><body>This doesn't seem to be
right.</body></html>";
-int
+static int
send_page (struct MHD_Connection *connection, const char *page)
{
int ret;
@@ -2600,16 +2647,14 @@
}
-int
+static int
iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
const char *filename, const char *content_type,
const char *transfer_encoding, const char *data, uint64_t off,
size_t size)
{
- struct connection_info_struct *con_info =
- (struct connection_info_struct *) coninfo_cls;
+ struct connection_info_struct *con_info = coninfo_cls;
-
if (0 == strcmp (key, "name"))
{
if ((size > 0) && (size <= MAXNAMESIZE))
@@ -2631,14 +2676,12 @@
return MHD_YES;
}
-void
+static void
request_completed (void *cls, struct MHD_Connection *connection,
void **con_cls, enum MHD_RequestTerminationCode toe)
{
- struct connection_info_struct *con_info =
- (struct connection_info_struct *) *con_cls;
+ struct connection_info_struct *con_info = *con_cls;
-
if (NULL == con_info)
return;
@@ -2654,7 +2697,7 @@
}
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
@@ -2720,7 +2763,6 @@
{
struct MHD_Daemon *daemon;
-
daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
&answer_to_connection, NULL,
MHD_OPTION_NOTIFY_COMPLETED, request_completed,
@@ -2738,25 +2780,27 @@
<hr size="6">
<a name="largepost_002ec"></a>
-<a name="SEC39"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC38" title="Previous section
in reading order"> < </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC40" title="Next section in
reading order"> > </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#simplepost_002ec"
title="Previous section in reading order"> < </a>]</td>
+<td valign="middle" align="left">[<a href="#tlsauthentication_002ec"
title="Next section in reading order"> > </a>]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.6 largepost.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="largepost_002ec-1"></a>
+<h2 class="section">C.6 largepost.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
@@ -2766,7 +2810,7 @@
#define GET 0
#define POST 1
-static unsigned char nr_of_uploading_clients = 0;
+static unsigned int nr_of_uploading_clients = 0;
struct connection_info_struct
{
@@ -2779,7 +2823,7 @@
const char *askpage = "<html><body>\n\
Upload a file, please!<br>\n\
- There are %d clients uploading at the
moment.<br>\n\
+ There are %u clients uploading at the
moment.<br>\n\
<form action=\"/filepost\"
method=\"post\" enctype=\"multipart/form-data\">\n\
<input name=\"file\"
type=\"file\">\n\
<input type=\"submit\" value=\" Send
\"></form>\n\
@@ -2799,14 +2843,13 @@
"<html><body>This file already
exists.</body></html>";
-int
+static int
send_page (struct MHD_Connection *connection, const char *page,
int status_code)
{
int ret;
struct MHD_Response *response;
-
response =
MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
MHD_YES);
@@ -2820,15 +2863,14 @@
}
-int
+static int
iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
const char *filename, const char *content_type,
const char *transfer_encoding, const char *data, uint64_t off,
size_t size)
{
+ struct connection_info_struct *con_info = coninfo_cls;
FILE *fp;
- struct connection_info_struct *con_info =
- (struct connection_info_struct *) coninfo_cls;
con_info->answerstring = servererrorpage;
con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR;
@@ -2838,7 +2880,7 @@
if (!con_info->fp)
{
- if (NULL != (fp = fopen (filename, "r")))
+ if (NULL != (fp = fopen (filename, "rb")))
{
fclose (fp);
con_info->answerstring = fileexistspage;
@@ -2863,12 +2905,11 @@
return MHD_YES;
}
-void
+static void
request_completed (void *cls, struct MHD_Connection *connection,
void **con_cls, enum MHD_RequestTerminationCode toe)
{
- struct connection_info_struct *con_info =
- (struct connection_info_struct *) *con_cls;
+ struct connection_info_struct *con_info = *con_cls;
if (NULL == con_info)
return;
@@ -2890,7 +2931,7 @@
}
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
@@ -2938,7 +2979,7 @@
if (0 == strcmp (method, "GET"))
{
int ret;
- char buffer[1024] = { 0 };
+ char buffer[1024];
sprintf (buffer, askpage, nr_of_uploading_clients);
return send_page (connection, buffer, MHD_HTTP_OK);
@@ -2987,25 +3028,27 @@
<hr size="6">
<a name="tlsauthentication_002ec"></a>
-<a name="SEC40"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC39" title="Previous section
in reading order"> < </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#largepost_002ec"
title="Previous section in reading order"> < </a>]</td>
<td valign="middle" align="left">[ > ]</td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Beginning of this
chapter or previous chapter"> << </a>]</td>
-<td valign="middle" align="left">[<a href="#SEC33" title="Up section"> Up
</a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning
of this chapter or previous chapter"> << </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up
section"> Up </a>]</td>
<td valign="middle" align="left">[ >> ]</td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
<td valign="middle" align="left"> </td>
-<td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
-<h2 class="section"> C.7 tlsauthentication.c </h2>
-<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <platform.h>
+<a name="tlsauthentication_002ec-1"></a>
+<h2 class="section">C.7 tlsauthentication.c</h2>
+<table><tr><td> </td><td><pre class="smalldisplay"><pre
class="verbatim">#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/socket.h>
#include <microhttpd.h>
#define PORT 8888
@@ -3017,9 +3060,47 @@
#define SERVERKEYFILE "server.key"
#define SERVERCERTFILE "server.pem"
-char *string_to_base64 (const char *message);
-long
+char *
+string_to_base64 (const char *message)
+{
+ const char *lookup =
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned long l;
+ int i;
+ char *tmp;
+ size_t length = strlen (message);
+
+ tmp = malloc (length * 2);
+ if (NULL == tmp)
+ return tmp;
+
+ tmp[0] = 0;
+
+ for (i = 0; i < length; i += 3)
+ {
+ l = (((unsigned long) message[i]) << 16)
+ | (((i + 1) < length) ? (((unsigned long) message[i + 1]) <<
8) : 0)
+ | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0);
+
+
+ strncat (tmp, &lookup[(l >> 18) & 0x3F], 1);
+ strncat (tmp, &lookup[(l >> 12) & 0x3F], 1);
+
+ if (i + 1 < length)
+ strncat (tmp, &lookup[(l >> 6) & 0x3F], 1);
+ if (i + 2 < length)
+ strncat (tmp, &lookup[l & 0x3F], 1);
+ }
+
+ if (length % 3)
+ strncat (tmp, "===", 3 - length % 3);
+
+ return tmp;
+}
+
+
+static long
get_file_size (const char *filename)
{
FILE *fp;
@@ -3040,7 +3121,7 @@
return 0;
}
-char *
+static char *
load_file (const char *filename)
{
FILE *fp;
@@ -3072,7 +3153,7 @@
return buffer;
}
-int
+static int
ask_for_authentication (struct MHD_Connection *connection, const char *realm)
{
int ret;
@@ -3106,7 +3187,7 @@
return ret;
}
-int
+static int
is_authenticated (struct MHD_Connection *connection,
const char *username, const char *password)
{
@@ -3132,10 +3213,10 @@
strcat (expected, password);
expected_b64 = string_to_base64 (expected);
+ free (expected);
if (NULL == expected_b64)
return 0;
- strcpy (expected, strbase);
authenticated =
(strcmp (headervalue + strlen (strbase), expected_b64) == 0);
@@ -3145,7 +3226,7 @@
}
-int
+static int
secret_page (struct MHD_Connection *connection)
{
int ret;
@@ -3165,7 +3246,7 @@
}
-int
+static int
answer_to_connection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
@@ -3225,51 +3306,12 @@
return 0;
}
-
-
-char *
-string_to_base64 (const char *message)
-{
- const char *lookup =
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- unsigned long l;
- int i;
- char *tmp;
- size_t length = strlen (message);
-
- tmp = malloc (length * 2);
- if (NULL == tmp)
- return tmp;
-
- tmp[0] = 0;
-
- for (i = 0; i < length; i += 3)
- {
- l = (((unsigned long) message[i]) << 16)
- | (((i + 1) < length) ? (((unsigned long) message[i + 1]) <<
8) : 0)
- | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0);
-
-
- strncat (tmp, &lookup[(l >> 18) & 0x3F], 1);
- strncat (tmp, &lookup[(l >> 12) & 0x3F], 1);
-
- if (i + 1 < length)
- strncat (tmp, &lookup[(l >> 6) & 0x3F], 1);
- if (i + 2 < length)
- strncat (tmp, &lookup[l & 0x3F], 1);
- }
-
- if (length % 3)
- strncat (tmp, "===", 3 - length % 3);
-
- return tmp;
-}
</pre></pre></td></tr></table>
<hr size="6">
<a name="SEC_Contents"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
@@ -3278,25 +3320,28 @@
<div class="contents">
<ul class="toc">
- <li><a name="TOC1" href="#SEC1">1. Introduction</a></li>
- <li><a name="TOC2" href="#SEC2">2. Hello browser example</a></li>
- <li><a name="TOC3" href="#SEC5">3. Exploring requests</a></li>
- <li><a name="TOC4" href="#SEC8">4. Response headers</a></li>
- <li><a name="TOC5" href="#SEC11">5. Supporting basic authentication</a></li>
- <li><a name="TOC6" href="#SEC16">6. Processing POST data</a></li>
- <li><a name="TOC7" href="#SEC20">7. Improved processing of POST data</a></li>
- <li><a name="TOC8" href="#SEC25">8. Adding a layer of security</a></li>
- <li><a name="TOC9" href="#SEC29">A. Bibliography</a></li>
- <li><a name="TOC10" href="#SEC31">B. GNU Free Documentation License</a></li>
- <li><a name="TOC11" href="#SEC33">C. Example programs</a>
+ <li><a name="toc-Introduction-1" href="#Introduction">1. Introduction</a>
<ul class="toc">
- <li><a name="TOC12" href="#SEC34">C.1 hellobrowser.c</a></li>
- <li><a name="TOC13" href="#SEC35">C.2 logging.c</a></li>
- <li><a name="TOC14" href="#SEC36">C.3 responseheaders.c</a></li>
- <li><a name="TOC15" href="#SEC37">C.4 basicauthentication.c</a></li>
- <li><a name="TOC16" href="#SEC38">C.5 simplepost.c</a></li>
- <li><a name="TOC17" href="#SEC39">C.6 largepost.c</a></li>
- <li><a name="TOC18" href="#SEC40">C.7 tlsauthentication.c</a></li>
+ <li><a name="toc-History" href="#History">1.1 History</a></li>
+ </ul></li>
+ <li><a name="toc-Hello-browser-example-1" href="#Hello-browser-example">2.
Hello browser example</a></li>
+ <li><a name="toc-Exploring-requests-1" href="#Exploring-requests">3.
Exploring requests</a></li>
+ <li><a name="toc-Response-headers-1" href="#Response-headers">4. Response
headers</a></li>
+ <li><a name="toc-Supporting-basic-authentication-1"
href="#Supporting-basic-authentication">5. Supporting basic
authentication</a></li>
+ <li><a name="toc-Processing-POST-data-1" href="#Processing-POST-data">6.
Processing POST data</a></li>
+ <li><a name="toc-Improved-processing-of-POST-data-1"
href="#Improved-processing-of-POST-data">7. Improved processing of POST
data</a></li>
+ <li><a name="toc-Adding-a-layer-of-security-1"
href="#Adding-a-layer-of-security">8. Adding a layer of security</a></li>
+ <li><a name="toc-Bibliography-1" href="#Bibliography">A.
Bibliography</a></li>
+ <li><a name="toc-GNU-Free-Documentation-License" href="#License-text">B. GNU
Free Documentation License</a></li>
+ <li><a name="toc-Example-programs-1" href="#Example-programs">C. Example
programs</a>
+ <ul class="toc">
+ <li><a name="toc-hellobrowser_002ec-1" href="#hellobrowser_002ec">C.1
hellobrowser.c</a></li>
+ <li><a name="toc-logging_002ec-1" href="#logging_002ec">C.2
logging.c</a></li>
+ <li><a name="toc-responseheaders_002ec-1"
href="#responseheaders_002ec">C.3 responseheaders.c</a></li>
+ <li><a name="toc-basicauthentication_002ec-1"
href="#basicauthentication_002ec">C.4 basicauthentication.c</a></li>
+ <li><a name="toc-simplepost_002ec-1" href="#simplepost_002ec">C.5
simplepost.c</a></li>
+ <li><a name="toc-largepost_002ec-1" href="#largepost_002ec">C.6
largepost.c</a></li>
+ <li><a name="toc-tlsauthentication_002ec-1"
href="#tlsauthentication_002ec">C.7 tlsauthentication.c</a></li>
</ul>
</li>
</ul>
@@ -3304,14 +3349,14 @@
<hr size="1">
<a name="SEC_About"></a>
<table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#SEC_Top" title="Cover (top) of
document">Top</a>]</td>
+<tr><td valign="middle" align="left">[<a href="#Top" title="Cover (top) of
document">Top</a>]</td>
<td valign="middle" align="left">[<a href="#SEC_Contents" title="Table of
contents">Contents</a>]</td>
<td valign="middle" align="left">[Index]</td>
<td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ?
</a>]</td>
</tr></table>
<h1>About This Document</h1>
<p>
- This document was generated by <em>Christian Grothoff</em> on <em>February,
8 2009</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.78</em></a>.
+ This document was generated by <em>Christian Grothoff</em> on <em>July 26,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
</p>
<p>
The buttons in the navigation panels have the following meaning:
@@ -3413,7 +3458,7 @@
<hr size="1">
<p>
<font size="-1">
- This document was generated by <em>Christian Grothoff</em> on <em>February,
8 2009</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.78</em></a>.
+ This document was generated by <em>Christian Grothoff</em> on <em>July 26,
2010</em> using <a href="http://www.nongnu.org/texi2html/"><em>texi2html
1.82</em></a>.
</font>
<br>
Modified: libmicrohttpd-docs/WWW/tutorial.pdf
===================================================================
(Binary files differ)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r12349 - libmicrohttpd-docs/WWW,
gnunet <=