gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r14587 - libmicrohttpd-docs/WWW


From: gnunet
Subject: [GNUnet-SVN] r14587 - libmicrohttpd-docs/WWW
Date: Fri, 4 Mar 2011 11:25:26 +0100

Author: grothoff
Date: 2011-03-04 11:25:26 +0100 (Fri, 04 Mar 2011)
New Revision: 14587

Modified:
   libmicrohttpd-docs/WWW/microhttpd.html
   libmicrohttpd-docs/WWW/microhttpd.pdf
   libmicrohttpd-docs/WWW/tutorial.html
   libmicrohttpd-docs/WWW/tutorial.pdf
Log:
doc

Modified: libmicrohttpd-docs/WWW/microhttpd.html
===================================================================
--- libmicrohttpd-docs/WWW/microhttpd.html      2011-03-04 09:58:58 UTC (rev 
14586)
+++ libmicrohttpd-docs/WWW/microhttpd.html      2011-03-04 10:25:26 UTC (rev 
14587)
@@ -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.9.7, last
-updated 7 February 2011. It is built upon the documentation in the
+updated 4 March 2011. It is built upon the documentation in the
 header file microhttpd.h.
 
 
-Copyright C 2007, 2008, 2009, 2010 Christian Grothoff
+Copyright C 2007, 2008, 2009, 2010, 2011 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
@@ -16,7 +16,7 @@
 
 GNU libmicrohttpd is a GNU package.
  -->
-<!-- Created on February 13, 2011 by texi2html 1.82
+<!-- Created on March 4, 2011 by texi2html 1.82
 texi2html was written by: 
             Lionel Cons <address@hidden> (original author)
             Karl Berry  <address@hidden>
@@ -67,11 +67,11 @@
 <a name="The-GNU-libmicrohttpd-Library"></a>
 <h1 class="settitle">The GNU libmicrohttpd Library</h1>
 <p>This manual documents GNU libmicrohttpd version 0.9.7, last
-updated 7 February 2011. It is built upon the documentation in the
+updated 4 March 2011. It is built upon the documentation in the
 header file &lsquo;<tt>microhttpd.h</tt>&rsquo;.
 </p>
 
-<p>Copyright &copy; 2007, 2008, 2009, 2010 Christian Grothoff
+<p>Copyright &copy; 2007, 2008, 2009, 2010, 2011 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
@@ -1315,7 +1315,42 @@
 </p></dd></dl>
 
 
+<dl>
+<dt><a name="index-MHD_005fadd_005fconnection"></a><u>Function:</u> void 
<b>MHD_add_connection</b><i> (struct MHD_Daemon *daemon, int client_socket, 
const struct sockaddr *addr, socklen_t addrlen)</i></dt>
+<dd><p>Add another client connection to the set of connections 
+managed by MHD.  This API is usually not needed (since
+MHD will accept inbound connections on the server socket).
+Use this API in special cases, for example if your HTTP
+server is behind NAT and needs to connect out to the 
+HTTP client.
+</p>
+<p>The given client socket will be managed (and closed!) by MHD after
+this call and must no longer be used directly by the application
+afterwards.
+</p>
+<dl compact="compact">
+<dt> <var>daemon</var> </dt>
+<dd><p>daemon that manages the connection
+</p></dd>
+<dt> <var>client_socket</var> </dt>
+<dd><p>socket to manage (MHD will expect to receive an HTTP request from this 
socket next).
+</p></dd>
+<dt> <var>addr</var> </dt>
+<dd><p>IP address of the client
+</p></dd>
+<dt> <var>addrlen</var> </dt>
+<dd><p>number of bytes in addr
+</p></dd>
+</dl>
 
+<p>This function will return <code>MHD_YES</code> on success, 
+<code>MHD_NO</code> if this daemon could
+not handle the connection (i.e. malloc failed, etc).
+The socket will be closed in any case.
+</p></dd></dl>
+
+
+
 <hr size="6">
 <a name="microhttpd_002dinspect"></a>
 <table cellpadding="1" cellspacing="1" border="0">
@@ -4181,6 +4216,7 @@
 <tr><td></td><td valign="top"><a 
href="#index-_002aMHD_005fRequestCompletedCallback"><code>*MHD_RequestCompletedCallback</code></a></td><td
 valign="top"><a href="#microhttpd_002dcb">4. Callback functions 
definition</a></td></tr>
 <tr><td colspan="3"> <hr></td></tr>
 <tr><th><a 
name="Function-and-Data-Index-1_fn_letter-M">M</a></th><td></td><td></td></tr>
+<tr><td></td><td valign="top"><a 
href="#index-MHD_005fadd_005fconnection"><code>MHD_add_connection</code></a></td><td
 valign="top"><a href="#microhttpd_002dinit">5. Starting and stopping the 
server</a></td></tr>
 <tr><td></td><td valign="top"><a 
href="#index-MHD_005fadd_005fresponse_005ffooter"><code>MHD_add_response_footer</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_005fadd_005fresponse_005fheader"><code>MHD_add_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_005fbasic_005fauth_005fget_005fusername_005fpassword"><code>MHD_basic_auth_get_username_password</code></a></td><td
 valign="top"><a href="#microhttpd_002ddauth-basic">9.1 Using Basic 
Authentication</a></td></tr>
@@ -4380,7 +4416,7 @@
 </tr></table>
 <h1>About This Document</h1>
 <p>
-  This document was generated by <em>Christian Grothoff</em> on <em>February 
13, 2011</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>March 4, 
2011</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:
@@ -4482,7 +4518,7 @@
 <hr size="1">
 <p>
  <font size="-1">
-  This document was generated by <em>Christian Grothoff</em> on <em>February 
13, 2011</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>March 4, 
2011</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        2011-03-04 09:58:58 UTC (rev 
14586)
+++ libmicrohttpd-docs/WWW/tutorial.html        2011-03-04 10:25:26 UTC (rev 
14587)
@@ -1,11 +1,11 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html401/loose.dtd";>
 <html>
-<!-- This tutorial documents GNU libmicrohttpd version 0.9.4, last
-updated 26 Dec 2010. 
+<!-- This tutorial documents GNU libmicrohttpd version 0.9.8, last
+updated 28 Feb 2010. 
 
 Copyright (c)  2008  Sebastian Gerhardt.
 
-Copyright (c)  2010  Christian Grothoff.
+Copyright (c)  2010, 2011  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;
@@ -14,7 +14,7 @@
 Free Documentation License".
 
  -->
-<!-- Created on January 1, 2011 by texi2html 1.82
+<!-- Created on March 4, 2011 by texi2html 1.82
 texi2html was written by: 
             Lionel Cons <address@hidden> (original author)
             Karl Berry  <address@hidden>
@@ -80,8 +80,10 @@
 </td></tr>
 <tr><td align="left" valign="top"><a 
href="#Improved-processing-of-POST-data">7. Improved processing of POST 
data</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
 </td></tr>
-<tr><td align="left" valign="top"><a href="#Adding-a-layer-of-security">8. 
Adding a layer of security</a></td><td>&nbsp;&nbsp;</td><td align="left" 
valign="top">
+<tr><td align="left" valign="top"><a href="#Session-management">8. Session 
management</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
 </td></tr>
+<tr><td align="left" valign="top"><a href="#Adding-a-layer-of-security">9. 
Adding a layer of security</a></td><td>&nbsp;&nbsp;</td><td align="left" 
valign="top">
+</td></tr>
 <tr><td align="left" valign="top"><a href="#Bibliography">A. 
Bibliography</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
 </td></tr>
 <tr><td align="left" valign="top"><a href="#License-text">B. GNU Free 
Documentation License</a></td><td>&nbsp;&nbsp;</td><td align="left" 
valign="top">
@@ -123,7 +125,7 @@
 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.9.4.  At the time being, 
+is written for version 0.9.8.  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.
@@ -221,15 +223,15 @@
 just sent the answer string &quot;as is&quot;. 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&mdash;we
 just have to ask. Our reply string packed in the necessary layers will be 
called a &quot;response&quot;.
 To obtain such a response we hand our data (the reply&ndash;string) and its 
size over to the 
-<code>MHD_create_response_from_data</code> function. The last two parameters 
basically tell <em>MHD</em>
+<code>MHD_create_response_from_buffer</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&rsquo;t 
change anyway.
 </p>
 <pre class="verbatim">  struct MHD_Response *response;
   int ret;
 
-  response = MHD_create_response_from_data (strlen (page),
-                                            (void*) page, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (page),
+                                            (void*) page, 
MHD_RESPMEM_PERSISTENT);
 
 </pre>
 <p>Now that the the response has been laced up, it is ready for delivery and 
can be queued for sending. 
@@ -296,7 +298,7 @@
 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="Remarks"></a>
+<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. 
@@ -563,9 +565,9 @@
         &quot;&lt;html&gt;&lt;body&gt;An internal server error has occured!\
                               &lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (errorstr), 
-                                      (void *) errorstr, 
-                                      MHD_NO, MHD_NO);
+       MHD_create_response_from_buffer (strlen (errorstr), 
+                                        (void *) errorstr, 
+                                        MHD_RESPMEM_PERSISTENT);
       if (response)
         {
           ret =
@@ -584,8 +586,8 @@
 
       if (buffer) free(buffer);
     
-      response = MHD_create_response_from_data(strlen(errorstr), 
(void*)errorstr,
-                                               MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen(errorstr), (void*) 
errorstr,
+                                                  MHD_RESPMEM_PERSISTENT);
 
       if (response)
         {     
@@ -610,7 +612,7 @@
     }
 
   response =
-    MHD_create_response_from_fd (fd, sbuf.st_size);
+    MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0);
   MHD_add_response_header (response, &quot;Content-Type&quot;, MIMETYPE);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
@@ -633,7 +635,7 @@
 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="Remarks-4"></a>
+<a name="Remarks-5"></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
@@ -805,8 +807,8 @@
     {
       const char *page = &quot;&lt;html&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                      MHD_NO);
+       MHD_create_response_from_buffer (strlen (page), (void *) page, 
+                                      MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_basic_auth_fail_response (connection,
                                                &quot;my realm&quot;,
                                                response);
@@ -815,8 +817,8 @@
     {
       const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                      MHD_NO);
+       MHD_create_response_from_buffer (strlen (page), (void *) page, 
+                                      MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     }
   MHD_destroy_response (response);
@@ -825,7 +827,7 @@
 </pre>
 <p>See the <code>examples</code> directory for the complete example file.
 </p>
-<a name="Remarks-2"></a>
+<a name="Remarks-3"></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,
@@ -1087,11 +1089,11 @@
 <a name="Improved-processing-of-POST-data"></a>
 <table cellpadding="1" cellspacing="1" border="0">
 <tr><td valign="middle" align="left">[<a href="#Processing-POST-data" 
title="Previous section in reading order"> &lt; </a>]</td>
-<td valign="middle" align="left">[<a href="#Adding-a-layer-of-security" 
title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Session-management" title="Next 
section in reading order"> &gt; </a>]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left">[<a href="#Processing-POST-data" 
title="Beginning of this chapter or previous chapter"> &lt;&lt; </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"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Session-management" title="Next 
chapter"> &gt;&gt; </a>]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left"> &nbsp; </td>
@@ -1157,8 +1159,8 @@
   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_buffer (strlen (page), (void*) page, 
+                                             MHD_RESPMEM_MUST_COPY);
   if (!response) return MHD_NO;
  
   ret = MHD_queue_response (connection, status_code, response);
@@ -1366,7 +1368,7 @@
 <p>This is essentially the whole example <code>largepost.c</code>.
 </p>
 
-<a name="Remarks-1"></a>
+<a name="Remarks-2"></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
@@ -1374,13 +1376,104 @@
 filenames must be checked to not contain strings like &quot;../&quot;.
 </p>
 <hr size="6">
-<a name="Adding-a-layer-of-security"></a>
+<a name="Session-management"></a>
 <table cellpadding="1" cellspacing="1" border="0">
 <tr><td valign="middle" align="left">[<a 
href="#Improved-processing-of-POST-data" title="Previous section in reading 
order"> &lt; </a>]</td>
-<td valign="middle" align="left">[<a href="#Bibliography" title="Next section 
in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Adding-a-layer-of-security" 
title="Next section in reading order"> &gt; </a>]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left">[<a href="#Improved-processing-of-POST-data" 
title="Beginning of this chapter or previous chapter"> &lt;&lt; </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"> &gt;&gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </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>
+<a name="Session-management-1"></a>
+<h1 class="chapter">8. Session management</h1>
+<p>This chapter discusses how one should manage sessions, that is, share state 
between multiple
+HTTP requests from the same user.  We use a simple example where the user 
submits multiple
+forms and the server is supposed to accumulate state from all of these forms.  
Naturally, as
+this is a network protocol, our session mechanism must support having many 
users with
+many concurrent sessions at the same time.
+</p>
+<p>In order to track users, we use a simple session cookie.  A session cookie 
expires when the
+user closes the browser.  Changing from session cookies to persistent cookies 
only requires
+adding an expiration time to the cookie.  The server creates a fresh session 
cookie whenever
+a request without a cookie is received, or if the supplied session cookie is 
not known to
+the server.
+</p>
+<a name="Looking-up-the-cookie"></a>
+<h2 class="heading">Looking up the cookie</h2>
+
+<p>Since MHD parses the HTTP cookie header for us, looking up an existing 
cookie
+is straightforward:
+</p>
+<pre class="verbatim">FIXME.
+</pre>
+<p>Here, FIXME is the name we chose for our session cookie.
+</p>
+
+<a name="Setting-the-cookie-header"></a>
+<h2 class="heading">Setting the cookie header</h2>
+
+<p>MHD requires the user to provide the full cookie format string in order to 
set
+cookies.  In order to generate a unique cookie, our example creates a random
+64-character text string to be used as the value of the cookie:
+</p>
+<pre class="verbatim">FIXME.
+</pre>
+<p>Given this cookie value, we can then set the cookie header in our HTTP 
response 
+as follows:
+</p>
+<pre class="verbatim">FIXME.
+</pre>
+
+<a name="Remark_003a-Session-expiration"></a>
+<h2 class="heading">Remark: Session expiration</h2>
+
+<p>It is of course possible that clients stop their interaction with the
+server at any time.  In order to avoid using too much storage, the
+server must thus discard inactive sessions at some point.  Our example
+implements this by discarding inactive sessions after a certain amount
+of time.  Alternatively, the implementation may limit the total number
+of active sessions.  Which bounds are used for idle sessions or the
+total number of sessions obviously depends largely on the type of
+the application and available server resources.
+</p>
+<a name="Example-code"></a>
+<h2 class="heading">Example code</h2>
+
+<p>A sample application implementing a website with multiple
+forms (which are dynamically created using values from previous
+POST requests from the same session) is available
+as the example <code>sessions.c</code>.
+</p>
+<p>Note that the example uses a simple, $O(n)$ linked list traversal to
+look up sessions and to expire old sessions.  Using a hash table and a
+heap would be more appropriate if a large number of concurrent
+sessions is expected.
+</p>
+<a name="Remarks"></a>
+<h2 class="heading">Remarks</h2>
+
+<p>Naturally, it is quite conceivable to store session data in a database
+instead of in memory.  Still, having mechanisms to expire data
+associated with long-time idle sessions (where the business process
+has still not finished) is likely a good idea.
+</p>
+<hr size="6">
+<a name="Adding-a-layer-of-security"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#Session-management" 
title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Bibliography" title="Next section 
in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Session-management" 
title="Beginning of this chapter or previous chapter"> &lt;&lt; </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"> &gt;&gt; </a>]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left"> &nbsp; </td>
@@ -1392,7 +1485,7 @@
 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? 
</a>]</td>
 </tr></table>
 <a name="Adding-a-layer-of-security-1"></a>
-<h1 class="chapter">8. Adding a layer of security</h1>
+<h1 class="chapter">9. 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 
@@ -1488,7 +1581,7 @@
 <p>The rather unexciting file loader can be found in the complete example 
<code>tlsauthentication.c</code>.
 </p>
 
-<a name="Remarks-3"></a>
+<a name="Remarks-4"></a>
 <h2 class="heading">Remarks</h2>
 <ul>
 <li>
@@ -2286,8 +2379,10 @@
 </td></tr>
 <tr><td align="left" valign="top"><a href="#largepost_002ec">C.6 
largepost.c</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
 </td></tr>
-<tr><td align="left" valign="top"><a href="#tlsauthentication_002ec">C.7 
tlsauthentication.c</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
+<tr><td align="left" valign="top"><a href="#sessions_002ec">C.7 
sessions.c</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
 </td></tr>
+<tr><td align="left" valign="top"><a href="#tlsauthentication_002ec">C.8 
tlsauthentication.c</a></td><td>&nbsp;&nbsp;</td><td align="left" valign="top">
+</td></tr>
 </table>
 
 <hr size="6">
@@ -2328,8 +2423,8 @@
   int ret;
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page, 
+                                    MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
 
@@ -2445,6 +2540,9 @@
 #include &lt;sys/socket.h&gt;
 #include &lt;microhttpd.h&gt;
 #include &lt;time.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;fcntl.h&gt;
+#include &lt;string.h&gt;
 
 #define PORT 8888
 #define FILENAME &quot;picture.png&quot;
@@ -2473,9 +2571,9 @@
         &quot;&lt;html&gt;&lt;body&gt;An internal server error has occured!\
                               &lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (errorstr), 
-                                      (void *) errorstr, 
-                                      MHD_NO, MHD_NO);
+       MHD_create_response_from_buffer (strlen (errorstr), 
+                                        (void *) errorstr, 
+                                        MHD_RESPMEM_PERSISTENT);
       if (response)
         {
           ret =
@@ -2489,7 +2587,7 @@
         return MHD_NO;
     }
   response =
-    MHD_create_response_from_fd (fd, sbuf.st_size);
+    MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0);
   MHD_add_response_header (response, &quot;Content-Type&quot;, MIMETYPE);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
@@ -2578,8 +2676,8 @@
     {
       const char *page = &quot;&lt;html&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                      MHD_NO);
+       MHD_create_response_from_buffer (strlen (page), (void *) page,
+                                        MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_basic_auth_fail_response (connection,
                                                &quot;my realm&quot;,
                                                response);
@@ -2588,8 +2686,8 @@
     {
       const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
       response =
-       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                      MHD_NO);
+       MHD_create_response_from_buffer (strlen (page), (void *) page,
+                                        MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     }
   MHD_destroy_response (response);
@@ -2676,8 +2774,8 @@
 
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page,
+                                    MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 
@@ -2823,7 +2921,7 @@
 <a name="largepost_002ec"></a>
 <table cellpadding="1" cellspacing="1" border="0">
 <tr><td valign="middle" align="left">[<a href="#simplepost_002ec" 
title="Previous section in reading order"> &lt; </a>]</td>
-<td valign="middle" align="left">[<a href="#tlsauthentication_002ec" 
title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left">[<a href="#sessions_002ec" title="Next 
section in reading order"> &gt; </a>]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left">[<a href="#Example-programs" title="Beginning 
of this chapter or previous chapter"> &lt;&lt; </a>]</td>
 <td valign="middle" align="left">[<a href="#Example-programs" title="Up 
section"> Up </a>]</td>
@@ -2892,8 +2990,8 @@
   struct MHD_Response *response;
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_YES);
+    MHD_create_response_from_buffer (strlen (page), (void *) page,
+                                    MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 
@@ -3068,9 +3166,779 @@
 </pre></pre></td></tr></table>
 
 <hr size="6">
+<a name="sessions_002ec"></a>
+<table cellpadding="1" cellspacing="1" border="0">
+<tr><td valign="middle" align="left">[<a href="#largepost_002ec" 
title="Previous section in reading order"> &lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#tlsauthentication_002ec" 
title="Next section in reading order"> &gt; </a>]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Beginning 
of this chapter or previous chapter"> &lt;&lt; </a>]</td>
+<td valign="middle" align="left">[<a href="#Example-programs" title="Up 
section"> Up </a>]</td>
+<td valign="middle" align="left">[ &gt;&gt; ]</td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </td>
+<td valign="middle" align="left"> &nbsp; </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>
+<a name="sessions_002ec-1"></a>
+<h2 class="section">C.7 sessions.c</h2>
+<table><tr><td>&nbsp;</td><td><pre class="smalldisplay"><pre 
class="verbatim">/*
+     This file is part of libmicrohttpd
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     This library is free software; you can redistribute it and/or
+     modify it under the terms of the GNU Lesser General Public
+     License as published by the Free Software Foundation; either
+     version 2.1 of the License, or (at your option) any later version.
+
+     This library is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Lesser General Public License for more details.
+
+     You should have received a copy of the GNU Lesser General Public
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 
 USA
+*/
+/**
+ * @file post_example.c
+ * @brief example for processing POST requests using libmicrohttpd
+ * @author Christian Grothoff
+ */
+
+/* needed for asprintf */
+#define _GNU_SOURCE
+
+
+#include &lt;stdlib.h&gt;
+#include &lt;string.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;errno.h&gt;
+#include &lt;time.h&gt;
+#include &lt;microhttpd.h&gt;
+
+/**
+ * Invalid method page.
+ */
+#define METHOD_ERROR &quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Illegal 
request&lt;/title&gt;&lt;/head&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Invalid URL page.
+ */
+#define NOT_FOUND_ERROR &quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Not 
found&lt;/title&gt;&lt;/head&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Front page. (/)
+ */
+#define MAIN_PAGE 
&quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Welcome&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;form
 action=\&quot;/2\&quot; method=\&quot;post\&quot;&gt;What is your name? 
&lt;input type=\&quot;text\&quot; name=\&quot;v1\&quot; value=\&quot;%s\&quot; 
/&gt;&lt;input type=\&quot;submit\&quot; value=\&quot;Next\&quot; 
/&gt;&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Second page. (/2)
+ */
+#define SECOND_PAGE &quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Tell me 
more&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;a 
href=\&quot;/\&quot;&gt;previous&lt;/a&gt; &lt;form action=\&quot;/S\&quot; 
method=\&quot;post\&quot;&gt;%s, what is your job? &lt;input 
type=\&quot;text\&quot; name=\&quot;v2\&quot; value=\&quot;%s\&quot; 
/&gt;&lt;input type=\&quot;submit\&quot; value=\&quot;Next\&quot; 
/&gt;&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Second page (/S)
+ */
+#define SUBMIT_PAGE &quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Ready to 
submit?&lt;/title&gt;&lt;/head&gt;&lt;body&gt;&lt;form action=\&quot;/F\&quot; 
method=\&quot;post\&quot;&gt;&lt;a href=\&quot;/2\&quot;&gt;previous &lt;/a&gt; 
&lt;input type=\&quot;hidden\&quot; name=\&quot;DONE\&quot; 
value=\&quot;yes\&quot; /&gt;&lt;input type=\&quot;submit\&quot; 
value=\&quot;Submit\&quot; /&gt;&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Last page.
+ */
+#define LAST_PAGE &quot;&lt;html&gt;&lt;head&gt;&lt;title&gt;Thank 
you&lt;/title&gt;&lt;/head&gt;&lt;body&gt;Thank 
you.&lt;/body&gt;&lt;/html&gt;&quot;
+
+/**
+ * Name of our cookie.
+ */
+#define COOKIE_NAME &quot;session&quot;
+
+
+/**
+ * State we keep for each user/session/browser.
+ */
+struct Session
+{
+  /**
+   * We keep all sessions in a linked list.
+   */
+  struct Session *next;
+
+  /**
+   * Unique ID for this session. 
+   */
+  char sid[33];
+
+  /**
+   * Reference counter giving the number of connections
+   * currently using this session.
+   */
+  unsigned int rc;
+
+  /**
+   * Time when this session was last active.
+   */
+  time_t start;
+
+  /**
+   * String submitted via form.
+   */
+  char value_1[64];
+
+  /**
+   * Another value submitted via form.
+   */
+  char value_2[64];
+
+};
+
+
+/**
+ * Data kept per request.
+ */
+struct Request
+{
+
+  /**
+   * Associated session.
+   */
+  struct Session *session;
+
+  /**
+   * Post processor handling form data (IF this is
+   * a POST request).
+   */
+  struct MHD_PostProcessor *pp;
+
+  /**
+   * URL to serve in response to this POST (if this request 
+   * was a 'POST')
+   */
+  const char *post_url;
+
+};
+
+
+/**
+ * Linked list of all active sessions.  Yes, O(n) but a
+ * hash table would be overkill for a simple example...
+ */
+static struct Session *sessions;
+
+
+
+
+/**
+ * Return the session handle for this connection, or 
+ * create one if this is a new user.
+ */
+static struct Session *
+get_session (struct MHD_Connection *connection)
+{
+  struct Session *ret;
+  const char *cookie;
+
+  cookie = MHD_lookup_connection_value (connection,
+                                       MHD_COOKIE_KIND,
+                                       COOKIE_NAME);
+  if (cookie != NULL)
+    {
+      /* find existing session */
+      ret = sessions;
+      while (NULL != ret)
+       {
+         if (0 == strcmp (cookie, ret-&gt;sid))
+           break;
+         ret = ret-&gt;next;
+       }
+      if (NULL != ret)
+       {
+         ret-&gt;rc++;
+         return ret;
+       }
+    }
+  /* create fresh session */
+  ret = calloc (1, sizeof (struct Session));
+  if (NULL == ret)
+    {                                          
+      fprintf (stderr, &quot;calloc error: %s\n&quot;, strerror (errno));
+      return NULL; 
+    }
+  /* not a super-secure way to generate a random session ID,
+     but should do for a simple example... */
+  snprintf (ret-&gt;sid,
+           sizeof (ret-&gt;sid),
+           &quot;%X%X%X%X&quot;,
+           (unsigned int) random (),
+           (unsigned int) random (),
+           (unsigned int) random (),
+           (unsigned int) random ());
+  ret-&gt;rc++;  
+  ret-&gt;start = time (NULL);
+  ret-&gt;next = sessions;
+  sessions = ret;
+  return ret;
+}
+
+
+/**
+ * Type of handler that generates a reply.
+ *
+ * @param cls content for the page (handler-specific)
+ * @param mime mime type to use
+ * @param session session information
+ * @param connection connection to process
+ * @param MHD_YES on success, MHD_NO on failure
+ */
+typedef int (*PageHandler)(const void *cls,
+                          const char *mime,
+                          struct Session *session,
+                          struct MHD_Connection *connection);
+
+
+/**
+ * Entry we generate for each page served.
+ */ 
+struct Page
+{
+  /**
+   * Acceptable URL for this page.
+   */
+  const char *url;
+
+  /**
+   * Mime type to set for the page.
+   */
+  const char *mime;
+
+  /**
+   * Handler to call to generate response.
+   */
+  PageHandler handler;
+
+  /**
+   * Extra argument to handler.
+   */ 
+  const void *handler_cls;
+};
+
+
+/**
+ * Add header to response to set a session cookie.
+ *
+ * @param session session to use
+ * @param response response to modify
+ */ 
+static void
+add_session_cookie (struct Session *session,
+                   struct MHD_Response *response)
+{
+  char cstr[256];
+  snprintf (cstr,
+           sizeof (cstr),
+           &quot;%s=%s&quot;,
+           COOKIE_NAME,
+           session-&gt;sid);
+  if (MHD_NO == 
+      MHD_add_response_header (response,
+                              MHD_HTTP_HEADER_SET_COOKIE,
+                              cstr))
+    {
+      fprintf (stderr, 
+              &quot;Failed to set session cookie header!\n&quot;);
+    }
+}
+
+
+/**
+ * Handler that returns a simple static HTTP page that
+ * is passed in via 'cls'.
+ *
+ * @param cls a 'const char *' with the HTML webpage to return
+ * @param mime mime type to use
+ * @param session session handle 
+ * @param connection connection to use
+ */
+static int
+serve_simple_form (const void *cls,
+                  const char *mime,
+                  struct Session *session,
+                  struct MHD_Connection *connection)
+{
+  int ret;
+  const char *form = cls;
+  struct MHD_Response *response;
+
+  /* return static form */
+  response = MHD_create_response_from_buffer (strlen (form),
+                                             (void *) form,
+                                             MHD_RESPMEM_PERSISTENT);
+  add_session_cookie (session, response);
+  MHD_add_response_header (response,
+                          MHD_HTTP_HEADER_CONTENT_ENCODING,
+                          mime);
+  ret = MHD_queue_response (connection, 
+                           MHD_HTTP_OK, 
+                           response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+/**
+ * Handler that adds the 'v1' value to the given HTML code.
+ *
+ * @param cls a 'const char *' with the HTML webpage to return
+ * @param mime mime type to use
+ * @param session session handle 
+ * @param connection connection to use
+ */
+static int
+fill_v1_form (const void *cls,
+             const char *mime,
+             struct Session *session,
+             struct MHD_Connection *connection)
+{
+  int ret;
+  const char *form = cls;
+  char *reply;
+  struct MHD_Response *response;
+
+  if (-1 == asprintf (&amp;reply,
+                     form,
+                     session-&gt;value_1))
+    {
+      /* oops */
+      return MHD_NO;
+    }
+  /* return static form */
+  response = MHD_create_response_from_buffer (strlen (reply),
+                                             (void *) reply,
+                                             MHD_RESPMEM_MUST_FREE);
+  add_session_cookie (session, response);
+  MHD_add_response_header (response,
+                          MHD_HTTP_HEADER_CONTENT_ENCODING,
+                          mime);
+  ret = MHD_queue_response (connection, 
+                           MHD_HTTP_OK, 
+                           response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+/**
+ * Handler that adds the 'v1' and 'v2' values to the given HTML code.
+ *
+ * @param cls a 'const char *' with the HTML webpage to return
+ * @param mime mime type to use
+ * @param session session handle 
+ * @param connection connection to use
+ */
+static int
+fill_v1_v2_form (const void *cls,
+                const char *mime,
+                struct Session *session,
+                struct MHD_Connection *connection)
+{
+  int ret;
+  const char *form = cls;
+  char *reply;
+  struct MHD_Response *response;
+
+  if (-1 == asprintf (&amp;reply,
+                     form,
+                     session-&gt;value_1,
+                     session-&gt;value_2))
+    {
+      /* oops */
+      return MHD_NO;
+    }
+  /* return static form */
+  response = MHD_create_response_from_buffer (strlen (reply),
+                                             (void *) reply,
+                                             MHD_RESPMEM_MUST_FREE);
+  add_session_cookie (session, response);
+  MHD_add_response_header (response,
+                          MHD_HTTP_HEADER_CONTENT_ENCODING,
+                          mime);
+  ret = MHD_queue_response (connection, 
+                           MHD_HTTP_OK, 
+                           response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+/**
+ * Handler used to generate a 404 reply.
+ *
+ * @param cls a 'const char *' with the HTML webpage to return
+ * @param mime mime type to use
+ * @param session session handle 
+ * @param connection connection to use
+ */
+static int
+not_found_page (const void *cls,
+               const char *mime,
+               struct Session *session,
+               struct MHD_Connection *connection)
+{
+  int ret;
+  struct MHD_Response *response;
+
+  /* unsupported HTTP method */
+  response = MHD_create_response_from_buffer (strlen (NOT_FOUND_ERROR),
+                                             (void *) NOT_FOUND_ERROR,
+                                             MHD_RESPMEM_PERSISTENT);
+  ret = MHD_queue_response (connection, 
+                           MHD_HTTP_NOT_FOUND, 
+                           response);
+  MHD_add_response_header (response,
+                          MHD_HTTP_HEADER_CONTENT_ENCODING,
+                          mime);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+/**
+ * List of all pages served by this HTTP server.
+ */
+static struct Page pages[] = 
+  {
+    { &quot;/&quot;, &quot;text/html&quot;,  &amp;fill_v1_form, MAIN_PAGE },
+    { &quot;/2&quot;, &quot;text/html&quot;, &amp;fill_v1_v2_form, SECOND_PAGE 
},
+    { &quot;/S&quot;, &quot;text/html&quot;, &amp;serve_simple_form, 
SUBMIT_PAGE },
+    { &quot;/F&quot;, &quot;text/html&quot;, &amp;serve_simple_form, LAST_PAGE 
},
+    { NULL, NULL, &amp;not_found_page, NULL } /* 404 */
+  };
+
+
+
+/**
+ * Iterator over key-value pairs where the value
+ * maybe made available in increments and/or may
+ * not be zero-terminated.  Used for processing
+ * POST data.
+ *
+ * @param cls user-specified closure
+ * @param kind type of the value
+ * @param key 0-terminated key for the value
+ * @param filename name of the uploaded file, NULL if not known
+ * @param content_type mime-type of the data, NULL if not known
+ * @param transfer_encoding encoding of the data, NULL if not known
+ * @param data pointer to size bytes of data at the
+ *              specified offset
+ * @param off offset of data in the overall value
+ * @param size number of bytes in data available
+ * @return MHD_YES to continue iterating,
+ *         MHD_NO to abort the iteration
+ */
+static int
+post_iterator (void *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 Request *request = cls;
+  struct Session *session = request-&gt;session;
+
+  if (0 == strcmp (&quot;DONE&quot;, key))
+    {
+      fprintf (stdout,
+              &quot;Session `%s' submitted `%s', `%s'\n&quot;,
+              session-&gt;sid,
+              session-&gt;value_1,
+              session-&gt;value_2);
+      return MHD_YES;
+    }
+  if (0 == strcmp (&quot;v1&quot;, key))
+    {
+      if (size + off &gt; sizeof(session-&gt;value_1))
+       size = sizeof (session-&gt;value_1) - off;
+      memcpy (&amp;session-&gt;value_1[off],
+             data,
+             size);
+      if (size + off &lt; sizeof (session-&gt;value_1))
+       session-&gt;value_1[size+off] = '\0';
+      return MHD_YES;
+    }
+  if (0 == strcmp (&quot;v2&quot;, key))
+    {
+      if (size + off &gt; sizeof(session-&gt;value_2))
+       size = sizeof (session-&gt;value_2) - off;
+      memcpy (&amp;session-&gt;value_2[off],
+             data,
+             size);
+      if (size + off &lt; sizeof (session-&gt;value_2))
+       session-&gt;value_2[size+off] = '\0';
+      return MHD_YES;
+    }
+  fprintf (stderr, &quot;Unsupported form value `%s'\n&quot;, key);
+  return MHD_YES;
+}
+
+
+/**
+ * Main MHD callback for handling requests.
+ *
+ *
+ * @param cls argument given together with the function
+ *        pointer when the handler was registered with MHD
+ * @param url the requested url
+ * @param method the HTTP method used (&quot;GET&quot;, &quot;PUT&quot;, etc.)
+ * @param version the HTTP version string (i.e. &quot;HTTP/1.1&quot;)
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ *        for a POST that fits into memory and that is encoded
+ *        with a supported encoding, the POST data will NOT be
+ *        given in upload_data and is instead available as
+ *        part of MHD_get_connection_values; very large POST
+ *        data *will* be made available incrementally in
+ *        upload_data)
+ * @param upload_data_size set initially to the size of the
+ *        upload_data provided; the method must update this
+ *        value to the number of bytes NOT processed;
+ * @param con_cls pointer that the callback can set to some
+ *        address and that will be preserved by MHD for future
+ *        calls for this request; since the access handler may
+ *        be called many times (i.e., for a PUT/POST operation
+ *        with plenty of upload data) this allows the application
+ *        to easily associate some request-specific state.
+ *        If necessary, this state can be cleaned up in the
+ *        global &quot;MHD_RequestCompleted&quot; callback (which
+ *        can be set with the MHD_OPTION_NOTIFY_COMPLETED).
+ *        Initially, &lt;tt&gt;*con_cls&lt;/tt&gt; will be NULL.
+ * @return MHS_YES if the connection was handled successfully,
+ *         MHS_NO if the socket must be closed due to a serios
+ *         error while handling the request
+ */
+static int
+create_response (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 **ptr)
+{
+  struct MHD_Response *response;
+  struct Request *request;
+  struct Session *session;
+  int ret;
+  unsigned int i;
+
+  request = *ptr;
+  if (NULL == request)
+    {
+      request = calloc (1, sizeof (struct Request));
+      if (NULL == request)
+       {
+         fprintf (stderr, &quot;calloc error: %s\n&quot;, strerror (errno));
+         return MHD_NO;
+       }
+      *ptr = request;
+      if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
+       {
+         request-&gt;pp = MHD_create_post_processor (connection, 1024,
+                                                  &amp;post_iterator, request);
+         if (NULL == request-&gt;pp)
+           {
+             fprintf (stderr, &quot;Failed to setup post processor for 
`%s'\n&quot;,
+                      url);
+             return MHD_NO; /* internal error */
+           }
+       }
+      return MHD_YES;
+    }
+  if (NULL == request-&gt;session)
+    {
+      request-&gt;session = get_session (connection);
+      if (NULL == request-&gt;session)
+       {
+         fprintf (stderr, &quot;Failed to setup session for `%s'\n&quot;,
+                  url);
+         return MHD_NO; /* internal error */
+       }
+    }
+  session = request-&gt;session;
+  session-&gt;start = time (NULL);
+  if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
+    {      
+      /* evaluate POST data */
+      MHD_post_process (request-&gt;pp,
+                       upload_data,
+                       *upload_data_size);
+      if (0 != *upload_data_size)
+       {
+         *upload_data_size = 0;
+         return MHD_YES;
+       }
+      /* done with POST data, serve response */
+      MHD_destroy_post_processor (request-&gt;pp);
+      request-&gt;pp = NULL;
+      method = MHD_HTTP_METHOD_GET; /* fake 'GET' */
+      if (NULL != request-&gt;post_url)
+       url = request-&gt;post_url;
+    }
+
+  if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
+       (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
+    {
+      /* find out which page to serve */
+      i=0;
+      while ( (pages[i].url != NULL) &amp;&amp;
+             (0 != strcmp (pages[i].url, url)) )
+       i++;
+      ret = pages[i].handler (pages[i].handler_cls, 
+                             pages[i].mime,
+                             session, connection);
+      if (ret != MHD_YES)
+       fprintf (stderr, &quot;Failed to create page for `%s'\n&quot;,
+                url);
+      return ret;
+    }
+  /* unsupported HTTP method */
+  response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
+                                             (void *) METHOD_ERROR,
+                                             MHD_RESPMEM_PERSISTENT);
+  ret = MHD_queue_response (connection, 
+                           MHD_HTTP_METHOD_NOT_ACCEPTABLE, 
+                           response);
+  MHD_destroy_response (response);
+  return ret;
+}
+
+
+/**
+ * Callback called upon completion of a request.
+ * Decrements session reference counter.
+ *
+ * @param cls not used
+ * @param connection connection that completed
+ * @param con_cls session handle
+ * @param toe status code
+ */
+static void
+request_completed_callback (void *cls,
+                           struct MHD_Connection *connection,
+                           void **con_cls,
+                           enum MHD_RequestTerminationCode toe)
+{
+  struct Request *request = *con_cls;
+
+  if (NULL == request)
+    return;
+  if (NULL != request-&gt;session)
+    request-&gt;session-&gt;rc--;
+  if (NULL != request-&gt;pp)
+    MHD_destroy_post_processor (request-&gt;pp);
+  free (request);
+}
+
+
+/**
+ * Clean up handles of sessions that have been idle for
+ * too long.
+ */
+static void
+expire_sessions ()
+{
+  struct Session *pos;
+  struct Session *prev;
+  struct Session *next;
+  time_t now;
+
+  now = time (NULL);
+  prev = NULL;
+  pos = sessions;
+  while (NULL != pos)
+    {
+      next = pos-&gt;next;
+      if (now - pos-&gt;start &gt; 60 * 60)
+       {
+         /* expire sessions after 1h */
+         if (NULL == prev)
+           sessions = pos-&gt;next;
+         else
+           prev-&gt;next = next;
+         free (pos);
+       }
+      else
+        prev = pos;
+      pos = next;
+    }      
+}
+
+
+/**
+ * Call with the port number as the only argument.
+ * Never terminates (other than by signals, such as CTRL-C).
+ */
+int
+main (int argc, char *const *argv)
+{
+  struct MHD_Daemon *d;
+  struct timeval tv;
+  struct timeval *tvp;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  unsigned MHD_LONG_LONG mhd_timeout;
+
+  if (argc != 2)
+    {
+      printf (&quot;%s PORT\n&quot;, argv[0]);
+      return 1;
+    }
+  /* initialize PRNG */
+  srandom ((unsigned int) time (NULL));
+  d = MHD_start_daemon (MHD_USE_DEBUG,
+                        atoi (argv[1]),
+                        NULL, NULL, 
+                       &amp;create_response, NULL, 
+                       MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15,
+                       MHD_OPTION_NOTIFY_COMPLETED, 
&amp;request_completed_callback, NULL,
+                       MHD_OPTION_END);
+  if (NULL == d)
+    return 1;
+  while (1)
+    {
+      expire_sessions ();
+      max = 0;
+      FD_ZERO (&amp;rs);
+      FD_ZERO (&amp;ws);
+      FD_ZERO (&amp;es);
+      if (MHD_YES != MHD_get_fdset (d, &amp;rs, &amp;ws, &amp;es, &amp;max))
+       break; /* fatal internal error */
+      if (MHD_get_timeout (d, &amp;mhd_timeout) == MHD_YES)    
+       {
+         tv.tv_sec = mhd_timeout / 1000;
+         tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
+         tvp = &amp;tv;          
+       }
+      else
+       tvp = NULL;
+      select (max + 1, &amp;rs, &amp;ws, &amp;es, tvp);
+      MHD_run (d);
+    }
+  MHD_stop_daemon (d);
+  return 0;
+}
+
+</pre></pre></td></tr></table>
+
+<hr size="6">
 <a name="tlsauthentication_002ec"></a>
 <table cellpadding="1" cellspacing="1" border="0">
-<tr><td valign="middle" align="left">[<a href="#largepost_002ec" 
title="Previous section in reading order"> &lt; </a>]</td>
+<tr><td valign="middle" align="left">[<a href="#sessions_002ec" 
title="Previous section in reading order"> &lt; </a>]</td>
 <td valign="middle" align="left">[ &gt; ]</td>
 <td valign="middle" align="left"> &nbsp; </td>
 <td valign="middle" align="left">[<a href="#Example-programs" title="Beginning 
of this chapter or previous chapter"> &lt;&lt; </a>]</td>
@@ -3086,7 +3954,7 @@
 <td valign="middle" align="left">[<a href="#SEC_About" title="About (help)"> ? 
</a>]</td>
 </tr></table>
 <a name="tlsauthentication_002ec-1"></a>
-<h2 class="section">C.7 tlsauthentication.c</h2>
+<h2 class="section">C.8 tlsauthentication.c</h2>
 <table><tr><td>&nbsp;</td><td><pre class="smalldisplay"><pre 
class="verbatim">#include &lt;sys/types.h&gt;
 #include &lt;sys/select.h&gt;
 #include &lt;sys/socket.h&gt;
@@ -3202,7 +4070,8 @@
   char *headervalue;
   const char *strbase = &quot;Basic realm=&quot;;
 
-  response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (0, NULL, 
+                                             MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 
@@ -3275,8 +4144,8 @@
   const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page, 
+                                    MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 
@@ -3371,7 +4240,8 @@
   <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-Session-management-1" href="#Session-management">8. Session 
management</a></li>
+  <li><a name="toc-Adding-a-layer-of-security-1" 
href="#Adding-a-layer-of-security">9. 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>
@@ -3382,7 +4252,8 @@
     <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>
+    <li><a name="toc-sessions_002ec-1" href="#sessions_002ec">C.7 
sessions.c</a></li>
+    <li><a name="toc-tlsauthentication_002ec-1" 
href="#tlsauthentication_002ec">C.8 tlsauthentication.c</a></li>
   </ul>
 </li>
 </ul>
@@ -3397,7 +4268,7 @@
 </tr></table>
 <h1>About This Document</h1>
 <p>
-  This document was generated by <em>Christian Grothoff</em> on <em>January 1, 
2011</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>March 4, 
2011</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:
@@ -3499,7 +4370,7 @@
 <hr size="1">
 <p>
  <font size="-1">
-  This document was generated by <em>Christian Grothoff</em> on <em>January 1, 
2011</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>March 4, 
2011</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)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]