commit c5969a735ab86f8c461b9188853e7bf4dd42d588
parent 53c25f932f5bd45c26af675b4c89d71eb99a9b8c
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 12 Aug 2008 19:49:42 +0000
tutorial
Diffstat:
14 files changed, 1554 insertions(+), 0 deletions(-)
diff --git a/AUTHORS b/AUTHORS
@@ -13,3 +13,4 @@ Sagie Amir
Documentation contributions also came from:
Marco Maggi <marco.maggi-ipsu@poste.it>
+Sebastian Gerhardt <sebgerhardt@gmx.net>
diff --git a/doc/basicauthentication.inc b/doc/basicauthentication.inc
@@ -0,0 +1,208 @@
+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
+its limits.
+
+A very simple approach feasible with the means already discussed would
+be to expect the password in the @emph{URI} string before granting access to
+the secured areas. The password could be separated from the actual resource identifier
+by a certain character, thus the request line might look like
+@verbatim
+GET /picture.png?mypassword
+@end verbatim
+@noindent
+
+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.
+
+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
+stays in the address field or at least in the history of the browser for anybody near enough to see.
+It will also be inconvenient to add the password manually to any new URI when the browser does
+not know how to compose this automatically.
+
+At least the convenience issue can be addressed by employing the simplest built-in password
+facilities of HTTP compliant browsers, hence we want to start there. It will however turn out
+to have still severe weaknesses in terms of security which need consideration.
+
+Before we will start implementing @emph{Basic Authentication} as described in @emph{RFC 2617},
+we should finally abandon the bad practice of responding every request the first time our callback
+is called for a given connection. This is becoming more important now because the client and
+the server will have to talk in a more bi-directional way than before to
+
+But how can we tell whether the callback has been called before for the particular connection?
+Initially, the pointer this parameter references is set by @emph{MHD} in the callback. But it will
+also be "remembered" on the next call (for the same connection).
+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} structure will be pointing to a legal adress, so we take this.
+
+Not even the headers will be looked at on the first iteration.
+
+@verbatim
+int AnswerToConnection(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, unsigned int *upload_data_size, void **con_cls)
+{
+ if (0 != strcmp(method, "GET")) return MHD_NO;
+ if(*con_cls==NULL) {*con_cls=connection; return MHD_YES;}
+
+ ...
+ /* else respond accordingly */
+ ...
+}
+@end verbatim
+@noindent
+
+Note how we lop off the connection on the first condition, but return asking for more on
+the other one with @code{MHD_YES}.
+With the framework improved, we can proceed to implement the actual authentication process.
+
+@heading Request for authentication
+
+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.
+@emph{RFC 2617} describes how the server shall ask for authentication by adding a
+@emph{WWW-Authenticate} response header with the name of the @emph{realm} protected.
+
+We let an extra function function do this.
+@verbatim
+int AskForAuthentication(struct MHD_Connection *connection, const char *realm)
+{
+ int ret;
+ struct MHD_Response *response;
+ char *headervalue;
+ const char *strbase = "Basic realm=";
+
+ response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO);
+ if (!response) return MHD_NO;
+
+ headervalue = malloc( strlen(strbase) + strlen(realm) + 1);
+ if (!headervalue) return MHD_NO;
+
+ strcpy(headervalue, strbase);
+ strcat(headervalue, realm);
+
+ ret = MHD_add_response_header(response, "WWW-Authenticate", headervalue);
+ free(headervalue);
+ if (!ret) {MHD_destroy_response (response); return MHD_NO;}
+
+ ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
+
+ MHD_destroy_response (response);
+
+ return ret;
+}
+@end verbatim
+@noindent
+
+@code{#define} the realm name according to your own taste, e.g. "Maintenance" or "Area51" but
+it will need to have extra quotes.
+
+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.
+
+@heading Authentication in detail
+Checking @emph{RFC 2617} 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 @emph{Base64}. The actual implementation of this encoding are not within the scope of
+this tutorial although a working function is included in the complete source file of the example.
+
+An unencoded word describing the authentication method (here "Basic") will precede the code
+and the resulting line is the value of a request header of the type "Authorization".
+
+This header line thus is of interest to the function checking a connection for a given username/password:
+@verbatim
+int IsAuthenticated(struct MHD_Connection *connection,
+ const char *username, const char *password)
+{
+ const char *headervalue;
+ ...
+
+ headervalue = MHD_lookup_connection_value (connection,
+ MHD_HEADER_KIND, "Authorization");
+
+ if(headervalue == NULL) return 0;
+@end verbatim
+@noindent
+
+where, firstly, the authentication method will be checked.
+@verbatim
+const char *strbase = "Basic ";
+...
+if (strncmp(headervalue, strbase, strlen(strbase))!=0) return 0;
+@end verbatim
+@noindent
+
+Of course, we could decode the passed credentials in the next step and compare them directly to
+the given strings. But as this would involve string parsing, which is more complicated then string
+composing, it is done the other way around---the clear text credentials will be encoded to @emph{Base64}
+and then compared against the headerline. The authentication method string will be left out here as
+it has been checked already at this point.
+@verbatim
+ char *expected_b64, *expected;
+ int authenticated;
+
+ ...
+ strcpy(expected, username);
+ strcat(expected, ":");
+ strcat(expected, password);
+
+ expected_b64 = StringToBase64(expected);
+ if(expected_b64 == NULL) return 0;
+
+ strcpy(expected, strbase);
+
+ authenticated = (strcmp(headervalue+strlen(strbase), expected_b64) == 0);
+
+ free(expected_b64);
+
+ return authenticated;
+}
+@end verbatim
+@noindent
+
+These two functions---together with a response function in case of positive authentication doing little
+new---allow the rest of the callback function to be rather short.
+@verbatim
+ if (!IsAuthenticated(connection, USER, PASSWORD))
+ return AskForAuthentication(connection, REALM);
+
+ return SecretPage(connection);
+}
+@end verbatim
+@noindent
+
+See the @code{examples} directory for the complete example file.
+
+@heading Remarks
+For a proper server, the conditional statements leading to a return of @code{MHD_NO} 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 @emph{internal server error} and unexpected
+authentication methods as @emph{400 bad request}.
+
+@heading Exercises
+@itemize @bullet
+@item
+Make the server respond to wrong credentials (but else correct requests) with the recommended
+@emph{401 unauthorized} 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
+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
+@code{AcceptPolicyCallback} function denies connection (temporally).
+
+@item
+With the network utility @emph{netcat} 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 @emph{netcat}
+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}). Pretending to think your were
+connecting to the actual server, browse to the eavesdropper and give the correct credentials.
+
+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.
+
+@end itemize
+
+
diff --git a/doc/bibliography.inc b/doc/bibliography.inc
@@ -0,0 +1,30 @@
+@itemize @bullet
+@heading API reference
+@item
+The @emph{GNU libmicrohttpd} manual by Christian Grothoff 2008
+@uref{http://gnunet.org/libmicrohttpd/microhttpd.html}
+
+@heading Requests for comments
+All referenced RFCs can be found on the website of @emph{The Internet Engineering Task Force}
+@uref{http://www.ietf.org/}
+
+@item
+@emph{RFC 2616}: Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and T. Berners-Lee,
+"Hypertext Transfer Protocol -- HTTP/1.1", RFC 2016, January 1997.
+
+@item
+@emph{RFC 2617}: Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P.,
+Luotonen, A., and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, June 1999.
+
+
+@heading Recommended readings
+@item
+A well--structured @emph{HTML} reference can be found on
+@uref{http://www.echoecho.com/html.htm}
+
+For those readers understanding German or French, there is an excellent document both for learning
+@emph{HTML} and for reference, whose English version unfortunately has been discontinued.
+@uref{http://de.selfhtml.org/} and @uref{http://fr.selfhtml.org/}
+
+
+@end itemize
diff --git a/doc/examples/basicauthentication.c b/doc/examples/basicauthentication.c
@@ -0,0 +1,152 @@
+#include <microhttpd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define PORT 8888
+
+#define REALM "\"Maintenance\""
+#define USER "a legitimate user"
+#define PASSWORD "and his password"
+
+
+char* StringToBase64(const char *message);
+
+
+int AskForAuthentication(struct MHD_Connection *connection, const char *realm)
+{
+ int ret;
+ struct MHD_Response *response;
+ char *headervalue;
+ const char *strbase = "Basic realm=";
+
+ response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO);
+ if (!response) return MHD_NO;
+
+ headervalue = malloc( strlen(strbase) + strlen(realm) + 1);
+ if (!headervalue) return MHD_NO;
+
+ strcpy(headervalue, strbase);
+ strcat(headervalue, realm);
+
+ ret = MHD_add_response_header(response, "WWW-Authenticate", headervalue);
+ free(headervalue);
+ if (!ret) {MHD_destroy_response (response); return MHD_NO;}
+
+ ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
+
+ MHD_destroy_response (response);
+
+ return ret;
+}
+
+int IsAuthenticated(struct MHD_Connection *connection, const char *username,
+ const char *password)
+{
+ const char *headervalue;
+ char *expected_b64, *expected;
+ const char *strbase = "Basic ";
+ int authenticated;
+
+ headervalue = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "Authorization");
+ if(headervalue == NULL) return 0;
+ if (strncmp(headervalue, strbase, strlen(strbase))!=0) return 0;
+
+ expected = malloc(strlen(username) + 1 + strlen(password) + 1);
+ if(expected == NULL) return 0;
+
+ strcpy(expected, username);
+ strcat(expected, ":");
+ strcat(expected, password);
+
+ expected_b64 = StringToBase64(expected);
+ if(expected_b64 == NULL) return 0;
+
+ strcpy(expected, strbase);
+
+ authenticated = (strcmp(headervalue+strlen(strbase), expected_b64) == 0);
+
+ free(expected_b64);
+
+ return authenticated;
+}
+
+
+int SecretPage(struct MHD_Connection *connection)
+{
+ int ret;
+ struct MHD_Response *response;
+ const char *page = "<html><body>A secret.</body></html>";
+
+ response = MHD_create_response_from_data(strlen(page), (void*)page, MHD_NO, MHD_NO);
+ if (!response) return MHD_NO;
+
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+
+ MHD_destroy_response (response);
+
+ return ret;
+}
+
+
+int AnswerToConnection(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, unsigned int *upload_data_size, void **con_cls)
+{
+ if (0 != strcmp(method, "GET")) return MHD_NO;
+ if(*con_cls==NULL) {*con_cls=connection; return MHD_YES;}
+
+ if (!IsAuthenticated(connection, USER, PASSWORD))
+ return AskForAuthentication(connection, REALM);
+
+ return SecretPage(connection);
+}
+
+
+int main ()
+{
+ struct MHD_Daemon *daemon;
+
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_END);
+
+ if (daemon == NULL) return 1;
+
+ getchar();
+
+ MHD_stop_daemon(daemon);
+ return 0;
+}
+
+
+char* StringToBase64(const char *message)
+{
+ const char *lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned long l;
+ int i;
+ char *tmp;
+ size_t length = strlen(message);
+
+ tmp = malloc(length*2);
+ if (tmp==NULL) 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;
+}
diff --git a/doc/examples/hellobrowser.c b/doc/examples/hellobrowser.c
@@ -0,0 +1,34 @@
+#include <microhttpd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define PORT 8888
+
+int AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+ const char *page = "<html><body>Hello, browser!</body></html>";
+ struct MHD_Response *response;
+ int ret;
+
+ response = MHD_create_response_from_data (strlen (page), (void*) page, MHD_NO, MHD_NO);
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+int main ()
+{
+ struct MHD_Daemon *daemon;
+
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_END);
+ if (daemon == NULL) return 1;
+
+ getchar();
+
+ MHD_stop_daemon(daemon);
+ return 0;
+}
diff --git a/doc/examples/logging.c b/doc/examples/logging.c
@@ -0,0 +1,39 @@
+#include <microhttpd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define PORT 8888
+
+
+int PrintOutKey(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
+{
+ printf("%s = %s\n", key, value);
+ return MHD_YES;
+}
+
+int AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+
+ printf("New request %s for %s using version %s\n", method, url, version);
+
+ MHD_get_connection_values(connection, MHD_HEADER_KIND, PrintOutKey, NULL);
+
+ return MHD_NO;
+}
+
+int main ()
+{
+ struct MHD_Daemon *daemon;
+
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_END);
+ if (daemon == NULL) return 1;
+
+ getchar();
+
+ MHD_stop_daemon(daemon);
+ return 0;
+}
diff --git a/doc/examples/responseheaders.c b/doc/examples/responseheaders.c
@@ -0,0 +1,94 @@
+#include <microhttpd.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define PORT 8888
+#define FILENAME "picture.png"
+#define MIMETYPE "image/png"
+
+
+long GetFileSize(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 AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+ unsigned char *buffer;
+ struct MHD_Response *response;
+ long size;
+ FILE *fp;
+ int ret=0;
+
+ if (0 != strcmp(method, "GET")) return MHD_NO;
+
+ size = GetFileSize(FILENAME);
+ if (size != 0)
+ {
+ fp = fopen(FILENAME, "rb");
+ if (fp)
+ {
+ buffer = malloc(size);
+ if (buffer)
+ if (size == fread(buffer, 1, size, fp)) ret=1;
+ }
+
+ fclose(fp);
+ }
+
+ if (!ret)
+ {
+ 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);
+
+ ret = MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
+ MHD_destroy_response (response);
+ return MHD_YES;
+ }
+
+ response = MHD_create_response_from_data(size, (void*)buffer, MHD_YES, MHD_NO);
+
+ MHD_add_response_header(response, "Content-Type", MIMETYPE);
+
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+
+
+int main ()
+{
+ struct MHD_Daemon *daemon;
+
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_END);
+
+ if (daemon == NULL) return 1;
+
+ getchar();
+
+ MHD_stop_daemon(daemon);
+ return 0;
+}
+
diff --git a/doc/examples/simplepost.c b/doc/examples/simplepost.c
@@ -0,0 +1,157 @@
+#include <microhttpd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define PORT 8888
+#define POSTBUFFERSIZE 512
+#define MAXNAMESIZE 20
+#define MAXANSWERSIZE 512
+
+#define GET 0
+#define POST 1
+
+struct ConnectionInfoStruct
+{
+ int connectiontype;
+ char *answerstring;
+ struct MHD_PostProcessor *postprocessor;
+};
+
+const char* askpage="<html><body>\
+ What's your name, Sir?<br>\
+ <form action=\"/namepost\" method=\"post\">\
+ <input name=\"name\" type=\"text\"\
+ <input type=\"submit\" value=\" Send \"></form>\
+ </body></html>";
+
+const char* greatingpage="<html><body><h1>Welcome, %s!</center></h1></body></html>";
+
+const char* errorpage="<html><body>This doesn't seem to be right.</body></html>";
+
+
+int SendPage(struct MHD_Connection *connection, const char* page)
+{
+ int ret;
+ struct MHD_Response *response;
+
+
+ response = MHD_create_response_from_data(strlen(page), (void*)page, MHD_NO, MHD_NO);
+ if (!response) return MHD_NO;
+
+ ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+
+ MHD_destroy_response(response);
+
+ return ret;
+}
+
+
+int IteratePost(void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
+ const char *filename, const char *content_type,
+ const char *transfer_encoding, const char *data, size_t off, size_t size)
+{
+ struct ConnectionInfoStruct *con_info = (struct ConnectionInfoStruct*)(coninfo_cls);
+
+
+ if (0 == strcmp(key, "name"))
+ {
+ if ((size>0) && (size<=MAXNAMESIZE))
+ {
+ char *answerstring;
+ answerstring = malloc(MAXANSWERSIZE);
+ if (!answerstring) return MHD_NO;
+
+ snprintf(answerstring, MAXANSWERSIZE, greatingpage, data);
+ con_info->answerstring = answerstring;
+ } else con_info->answerstring=NULL;
+
+ return MHD_NO;
+ }
+
+ return MHD_YES;
+}
+
+void RequestCompleted(void *cls, struct MHD_Connection *connection, void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct ConnectionInfoStruct *con_info = (struct ConnectionInfoStruct*)(*con_cls);
+
+
+ if (NULL == con_info) return;
+
+ if (con_info->connectiontype == POST)
+ {
+ MHD_destroy_post_processor(con_info->postprocessor);
+ if (con_info->answerstring) free(con_info->answerstring);
+ }
+
+ free(con_info);
+}
+
+
+int AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+ if(*con_cls==NULL)
+ {
+ struct ConnectionInfoStruct *con_info;
+
+ con_info = malloc(sizeof(struct ConnectionInfoStruct));
+ if (NULL == con_info) return MHD_NO;
+
+ if (0 == strcmp(method, "POST"))
+ {
+ con_info->postprocessor = MHD_create_post_processor(connection, POSTBUFFERSIZE,
+ IteratePost, (void*)con_info);
+
+ if (NULL == con_info->postprocessor)
+ {
+ free(con_info);
+ return MHD_NO;
+ }
+
+ con_info->connectiontype = POST;
+ } else con_info->connectiontype = GET;
+
+ *con_cls = (void*)con_info;
+ return MHD_YES;
+ }
+
+ if (0 == strcmp(method, "GET"))
+ {
+ return SendPage(connection, askpage);
+ }
+
+ if (0 == strcmp(method, "POST"))
+ {
+ struct ConnectionInfoStruct *con_info = *con_cls;
+
+ if (*upload_data_size != 0)
+ {
+ MHD_post_process(con_info->postprocessor, upload_data, *upload_data_size);
+ *upload_data_size = 0;
+ return MHD_YES;
+ } else return SendPage(connection, con_info->answerstring);
+ }
+
+ return SendPage(connection, errorpage);
+}
+
+int main ()
+{
+ struct MHD_Daemon *daemon;
+
+
+ daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_NOTIFY_COMPLETED,
+ RequestCompleted, NULL, MHD_OPTION_END);
+
+ if (NULL == daemon) return 1;
+
+ getchar();
+
+ MHD_stop_daemon(daemon);
+ return 0;
+}
diff --git a/doc/exploringrequests.inc b/doc/exploringrequests.inc
@@ -0,0 +1,104 @@
+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.
+
+The starting point is the @emph{hellobrowser} program with the former response removed.
+
+This time, we just want to collect information in the callback function, thus we will
+just return MHD_NO after we have probed the request. This way, the connection is closed
+without much ado by the server.
+
+@verbatim
+int AnswerToConnection(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, unsigned int *upload_data_size, void **con_cls)
+{
+ ...
+ return MHD_NO;
+}
+@end verbatim
+@noindent
+The ellipsis marks the position where the following instructions shall be inserted.
+
+
+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).
+It also contains a string for the version of the protocol which can be found in @code{version}.
+To call it a "new request" is justified because we return only @code{MHD_NO}, thus ensuring the
+function will not be called again for this connection.
+@verbatim
+printf("New request %s for %s using version %s\n", method, url, version);
+@end verbatim
+@noindent
+
+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
+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.
+@verbatim
+int PrintOutKey(void *cls, enum MHD_ValueKind kind, const char *key,
+ const char *value)
+{
+ printf("%s = %s\n", key, value);
+ return MHD_YES;
+}
+@end verbatim
+@noindent
+
+To start the iteration process that calls our new function for every key, the line
+@verbatim
+MHD_get_connection_values(connection, MHD_HEADER_KIND, PrintOutKey, NULL);
+@end verbatim
+@noindent
+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} does not rely on any additional information to fulfill its duties
+so the last parameter can be NULL.
+
+All in all, this constitutes the complete @code{logger.c} program for this chapter which can be
+found in the @code{examples} section.
+
+Connecting with any modern Internet browser should yield a handful of keys. You should try to
+interpret them with the aid of @emph{RFC 2616}.
+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.
+
+@heading Conclusion
+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.
+
+Of course, no transmission can occur while the return value is still set to @code{MHD_NO} in the
+callback function.
+
+@heading Exercises
+@itemize @bullet
+@item
+By parsing the @code{url} string and delivering responses accordingly, implement a small server for
+"virtual" files. When asked for @code{/index.htm@{l@}}, let the response consist of a HTML page
+containing a link to @code{/another.html} page which is also to be created "on the fly" in case of
+being requested. If neither of these two pages are requested, @code{MHD_HTTP_NOT_FOUND} shall be
+returned accompanied by an informative message.
+
+@item
+A very interesting information has still been ignored by our logger---the client's IP address.
+Implement a callback function
+@verbatim
+int OnClientConnect(void *cls,
+ const struct sockaddr *addr,socklen_t addrlen)
+@end verbatim
+@noindent
+that prints out the IP address in an appropriate format. You might want to use the posix function
+@code{inet_ntoa} but bear in mind that @code{addr} is actually just a structure containing other
+substructures and is @emph{not} the variable this function expects.
+Make sure to return @code{MHD_YES} 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
+@code{MHD_start_daemon} call.
+
+@end itemize
diff --git a/doc/hellobrowser.inc b/doc/hellobrowser.inc
@@ -0,0 +1,201 @@
+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 very easy to implement, it is an excellent problem to start with.
+
+For now, the particular filename 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.
+
+The C program @code{hellobrowser.c}, which is to be found in the examples section, does just that.
+If you are very eager, you can compile and start it right away but it is advisable to type the
+lines in by yourself as they will be discussed and explained in detail.
+
+After the unexciting includes and the definition of the port which our server should listen on
+@verbatim
+#include <microhttpd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+@end verbatim
+@noindent
+the desired behaviour of our server when HTTP request arrive have to be implemented. We already have
+agreed that it should not care about the particular details of the request, such as who is requesting
+what. The server will respond merely with the same small HTML page to every request.
+
+The function we are going to write now will be called by @emph{GNU libmicrohttpd} every time an
+appropriate request comes in. While the name of this callback function is arbitrary, its parameter
+list has to follow a certain layout. So please, ignore the lot of parameters for now, they will be
+explained at the point they are needed. We have to use only one of them,
+@code{struct MHD_Connection *connection}, for the minimalistic functionality we want to archive at the moment.
+
+This parameter is set by the @emph{libmicrohttpd} daemon and holds the necessary information to
+relate the call with a certain connection. Keep in mind that a server might have to satisfy hundreds
+of concurrent connections and we have to make sure that the correct data is sent to the destined
+client. Therefore, this variable is a means to refer to a particular connection if we ask the
+daemon to sent the reply.
+
+Talking about the reply, it is defined as a string right after the function header
+@verbatim
+int AnswerToConnection(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, unsigned int *upload_data_size, void **con_cls)
+{
+ const char *page = "<html><body>Hello, browser!</body></html>";
+@end verbatim
+@noindent
+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 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} function. The last two parameters basically tell @emph{MHD}
+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 @emph{constant} string won't change anyway.
+
+@verbatim
+ struct MHD_Response *response;
+ int ret;
+
+ response = MHD_create_response_from_data(strlen(page),
+ (void*)page, MHD_NO, MHD_NO);
+@end verbatim
+@noindent
+Now that the the response has been laced up, it is ready for delivery and can be queued for sending.
+This is done by passing it to another @emph{GNU libmicrohttpd} function. As all our work was done in
+the scope of one function, the recipient is without doubt the one associated with the
+local variable @code{connection} and consequently this variable is given to the queue function.
+Every HTTP response is accompanied by a status code, here "OK", so that the client knows
+this response is the intended result of his request and not due to some error or malfunction.
+
+Finally, the packet is destroyed and the return value from the queue returned,
+already being set at this point to either MHD_YES or MHD_NO in case of success or failure.
+
+@verbatim
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+@end verbatim
+@noindent
+With the primary task of our server implemented, we can start the actual server daemon which will listen
+on @code{PORT} for connections. This is done in the main function.
+@verbatim
+int main ()
+{
+ struct MHD_Daemon *d;
+
+ d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_END);
+ if (d == NULL) return 1;
+@end verbatim
+@noindent
+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.
+
+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.
+
+Parameter six is the address of the function we want to be called whenever a new connection has been
+established. Our @code{AnswerToConnection} 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.
+
+As the server daemon runs in the background in its own thread, the execution flow in our main
+function will contine right after the call. Because of this, we must delay the execution flow in the
+main thread or else the program will terminate prematurely. We let it pause in a processing-time
+friendly manner by waiting for the enter key to be pressed. In the end, we stop the daemon so it can
+do its cleanup tasks.
+@verbatim
+ getchar();
+
+ MHD_stop_daemon(d);
+ return 0;
+}
+@end verbatim
+@noindent
+The first example is now complete.
+
+Compile it with
+@verbatim
+cc hellobrowser.c -o hellobrowser -I$PATH_TO_LIBMHD_INCLUDES
+ -L$PATH_TO_LIBMHD_INCLUDES -static -lmicrohttpd -pthread
+@end verbatim
+with the two paths set accordingly and run it.
+
+Now open your favorite Internet browser and go to the address @code{localhost:8888}, provided that
+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.
+
+@heading Remarks
+To keep this first example as small as possible, some drastic shortcuts were taken and are to be
+discussed now.
+
+Firstly, there is no distinction made between the kinds of requests a client could send. We implied
+that the client sends a GET request, that means, that he actually asked for some data. Even when
+it is not intended to accept POST requests, a good server should at least recognize that this
+request does not constitute a legal request and answer with an error code. This can be easily
+implemented by checking if the parameter @code{method} equals the string "GET" and returning a
+@code{MHD_NO} if not so.
+
+Secondly, the above practice of queuing a response upon the first call of the callback function
+brings with it some limitations. This is because the content of the message body will not be
+received if a response is queued in the first iteration. Furthermore, the connection will be closed
+right after the response has been transferred then.
+
+Both of these issues you will find addressed in the official @code{minimal_example.c} residing in
+the @code{src/examples} directory of the @emph{GNU libmicrohttpd} package. The source code of this
+program should look very familiar to you by now and easy to understand.
+
+For our example, the @code{must_copy} and @code{must_free} parameter at the response construction
+function could be set to @code{MHD_NO}. In the usual case, responses cannot be sent immediately
+after being queued. For example, there might be other data on the system that needs to be sent with
+a higher priority. Nevertheless, the queue function will return successfully---raising the problem
+that the data we have pointed to may be invalid by the time it is about being sent. This is not an
+issue here because we can expect the @code{page} string, which is a constant @emph{string literal}
+here, to be static. That means it will be present and unchanged for as long as the program runs.
+For dynamic data, one could choose to either have @emph{MHD} free the memory @code{page} points
+to itself when it is not longer needed or, alternatively, have the library to make and manage
+its own copy of it.
+
+@heading Exercises
+@itemize @bullet
+@item
+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
+@verbatim
+GET /dontcare HTTP1.1
+Host: itsme
+<enter>
+@end verbatim
+@noindent
+and see what the server returns to you.
+
+
+@item
+Also, try other requests, like POST, and see how our server does not mind and why.
+How far in malforming a request can you go before the builtin functionality of @emph{MHD} intervenes
+and an altered response is sent? Make sure you read about the status codes in the @emph{RFC}.
+
+
+@item
+Add the option @code{MHD_USE_PEDANTIC_CHECKS} to the start function of the daemon in @code{main}.
+Mind the special format of the parameter list here which is described in the manual. How indulgent
+is the server now to your input?
+
+
+@item
+Let the main function take a string as the first command line argument and pass @code{argv[1]} to
+the @code{MHD_start_daemon} function as the sixth parameter. The address of this string will be
+passed to the callback function via the @code{cls} variable. Decorate the text given at the command
+line when the server is started with proper HTML tags and send it as the response instead of the
+former static string.
+
+
+@item
+@emph{Demanding:} 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}. Remember to free the memory of the string
+every time after satisfying the request.
+
+@end itemize
diff --git a/doc/introduction.inc b/doc/introduction.inc
@@ -0,0 +1,19 @@
+This tutorial is aimed at developers who want to learn how they can add HTTP serving
+capabilities to their applications with the @emph{GNU libmicrohttpd} library,
+abbreviated @emph{MHD}, and who do not know how to start. It tries to help these
+developers to implement common basic HTTP serving tasks by discussing executable
+sample programs implementing different features.
+
+The text is supposed to be a supplement to the API reference manual of
+@emph{GNU libmicrohttpd} and for that reason does not explain many of the parameters.
+Therefore, the reader should always consult the manual to find the exact meaning
+of the functions used in the tutorial. In the same sense, the tutorial seeks to
+encourage the use of the @emph{RFCs}, which document the conventions the Internet
+is built upon.
+
+@emph{GNU libmicrohttpd} is assumed to be already installed and it has been
+written with respect to version @value{VERSION}. As the library is still in its
+beta stages, later versions may show different behaviour. At the time being,
+this tutorial has only been tested on @emph{GNU/Linux} machines even though
+efforts were made not to rely on anything that would prevent the samples from being
+built on similar systems.
diff --git a/doc/processingpost.inc b/doc/processingpost.inc
@@ -0,0 +1,225 @@
+The previous chapters already have demonstrated a variety of possibilities to send information
+to the HTTP server, but it is not recommended that the @emph{GET} method is used to alter the way
+the server operates. To induce changes on the server, the @emph{POST} method is preferred over
+and is much more powerful than @emph{GET} and will be introduced in this chapter.
+
+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 @emph{post} 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.
+
+@heading GET request
+When the first @emph{GET} request arrives, the server shall respond with a HTML page containing an
+edit field for the name.
+
+@verbatim
+const char* askpage="<html><body>\
+ What's your name, Sir?<br>\
+ <form action=\"/namepost\" method=\"post\">\
+ <input name=\"name\" type=\"text\"\
+ <input type=\"submit\" value=\" Send \"></form>\
+ </body></html>";
+@end verbatim
+@noindent
+
+The @code{action} entry is the @emph{URI} to be called by the browser when posting, and the
+@code{name} will be used later to be sure it is the editbox's content that has been posted.
+
+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 @emph{GET} and @emph{POST} requests:
+
+@verbatim
+const char* greatingpage="<html><body><h1>Welcome, %s!</center></h1></body></html>";
+
+const char* errorpage="<html><body>This doesn't seem to be right.</body></html>";
+@end verbatim
+@noindent
+
+Whenever we need to send a page, we use an extra function
+@code{int SendPage(struct MHD_Connection *connection, const char* page)}
+for this, which does not contain anything new and whose implementation is therefore left out here.
+
+
+@heading POST request
+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.
+Likewise, we will have to register an iterator function that is going to be called maybe several times
+not only if there are different POSTs but also if one POST has only been received partly yet and
+needs processing before another chunk can be received.
+
+Such an iterator function is called by a @emph{postprocessor}, which must be created upon arriving
+of the post request. We want the iterator function to read the first post data which is tagged
+@code{name} and to create an individual greeting string based on the template and the name.
+But in order to pass this string to other functions and still be able to differentiate different
+connections, we must first define a structure to share the information, holding the most import entries.
+
+@verbatim
+struct ConnectionInfoStruct
+{
+ int connectiontype;
+ char *answerstring;
+ struct MHD_PostProcessor *postprocessor;
+};
+@end verbatim
+@noindent
+
+With these information available to the iterator function, it is able to fulfill its task.
+Once it has composed the greeting string, it returns @code{MHD_NO} to inform the post processor
+that it does not need to be called again. Note that this function does not handle processing
+of data for the same @code{key}. If we were to expect that the name will be posted in several
+chunks, we had to expand the namestring dynamically as additional parts of it with the same @code{key}
+came in. But in this example, the name is assumed to fit entirely inside one single packet.
+
+@verbatim
+int IteratePost(void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
+ const char *filename, const char *content_type,
+ const char *transfer_encoding, const char *data, size_t off, size_t size)
+{
+ struct ConnectionInfoStruct *con_info = (struct ConnectionInfoStruct*)(coninfo_cls);
+
+
+ if (0 == strcmp(key, "name"))
+ {
+ if ((size>0) && (size<=MAXNAMESIZE))
+ {
+ char *answerstring;
+ answerstring = malloc(MAXANSWERSIZE);
+ if (!answerstring) return MHD_NO;
+
+ snprintf(answerstring, MAXANSWERSIZE, greatingpage, data);
+ con_info->answerstring = answerstring;
+ } else con_info->answerstring=NULL;
+
+ return MHD_NO;
+ }
+
+ return MHD_YES;
+}
+@end verbatim
+@noindent
+
+Once a connection has been established, it can be terminated for many reasons. As these
+reasons include unexpected events, we have to register another function that cleans up any resources
+that might have been allocated for that connection by us, namely the post processor and the greetings
+string. This cleanup function must take into account that it will also be called for finished
+requests other than @emph{POST} requests.
+
+@verbatim
+void RequestCompleted(void *cls, struct MHD_Connection *connection, void **con_cls,
+ enum MHD_RequestTerminationCode toe)
+{
+ struct ConnectionInfoStruct *con_info = (struct ConnectionInfoStruct*)(*con_cls);
+
+
+ if (NULL == con_info) return;
+
+ if (con_info->connectiontype == POST)
+ {
+ MHD_destroy_post_processor(con_info->postprocessor);
+ if (con_info->answerstring) free(con_info->answerstring);
+ }
+
+ free(con_info);
+}
+@end verbatim
+@noindent
+
+@emph{GNU libmicrohttpd} is informed that it shall call the above function when the daemon is started
+in the main function.
+
+@verbatim
+...
+daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
+ &AnswerToConnection, NULL, MHD_OPTION_NOTIFY_COMPLETED,
+ RequestCompleted, NULL, MHD_OPTION_END);
+...
+@end verbatim
+@noindent
+
+@heading Request handling
+With all other functions prepared, we can now discuss the actual request handling.
+
+On the first iteration for a new request, we start by allocating a new instance of a
+@code{ConnectionInfoStruct} structure, which will store all necessary information for later
+iterations and other functions.
+
+@verbatim
+int AnswerToConnection(void *cls, struct MHD_Connection *connection, const char *url,
+ const char *method, const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+ if(*con_cls==NULL)
+ {
+ struct ConnectionInfoStruct *con_info;
+
+ con_info = malloc(sizeof(struct ConnectionInfoStruct));
+ if (NULL == con_info) return MHD_NO;
+@end verbatim
+@noindent
+
+If the new request is a @emph{POST}, the postprocessor must be created now. In addition, the type
+of the request is stored for convenience.
+@verbatim
+ if (0 == strcmp(method, "POST"))
+ {
+ con_info->postprocessor = MHD_create_post_processor(connection, POSTBUFFERSIZE,
+ IteratePost, (void*)con_info);
+
+ if (NULL == con_info->postprocessor)
+ {
+ free(con_info);
+ return MHD_NO;
+ }
+
+ con_info->connectiontype = POST;
+ } else con_info->connectiontype = GET;
+@end verbatim
+@noindent
+
+The address of our structure will both serve as the indicator for successive iterations and to remember
+the particular details about the connection.
+@verbatim
+ *con_cls = (void*)con_info;
+ return MHD_YES;
+ }
+@end verbatim
+@noindent
+
+The rest of the function will not be executed on the first iteration. A @emph{GET} request is easily
+satisfied by sending the question form.
+@verbatim
+ if (0 == strcmp(method, "GET"))
+ {
+ return SendPage(connection, askpage);
+ }
+@end verbatim
+@noindent
+
+In case of @emph{POST}, we invoke the post processor for as long as data keeps incoming, setting
+@code{*upload_data_size} to zero in order to indicate that we have processed---or at least have
+considered---all of it.
+@verbatim
+ if (0 == strcmp(method, "POST"))
+ {
+ struct ConnectionInfoStruct *con_info = *con_cls;
+
+ if (*upload_data_size != 0)
+ {
+ MHD_post_process(con_info->postprocessor, upload_data, *upload_data_size);
+ *upload_data_size = 0;
+ return MHD_YES;
+ } else return SendPage(connection, con_info->answerstring);
+ }
+@end verbatim
+@noindent
+
+If they are neither @emph{GET} nor @emph{POST} requests, the error page is returned finally.
+@verbatim
+ return SendPage(connection, errorpage);
+}
+@end verbatim
+@noindent
+
+These were the important parts of the program @code{simplepost.c}.
diff --git a/doc/responseheaders.inc b/doc/responseheaders.inc
@@ -0,0 +1,171 @@
+Now that we are able to inspect the incoming request in great detail,
+this chapter discusses the means to enrich the outgoing responses likewise.
+
+As you have learned in the @emph{Hello, Browser} chapter, some obligatory
+header fields are added and set automatically for simple responses by the library
+itself but if more advanced features are desired, additional fields have to be created.
+One of the possible fields is the content type field and an example will be developed around it.
+This will lead to an application capable of correctly serving different types of files.
+
+
+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.
+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
+by certain information about how the data is to be interpreted.
+
+To introduce the concept, a picture of the format @emph{PNG} will be sent to the client
+and labeled accordingly with @code{image/png}.
+Once again, we can base the new example on the @code{hellobrowser} program.
+
+@verbatim
+#define FILENAME "picture.png"
+#define MIMETYPE "image/png"
+
+int AnswerToConnection(void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method, const char *version,
+ const char *upload_data, unsigned int *upload_data_size, void **con_cls)
+{
+ struct MHD_Response *response;
+ int ret=0;
+@end verbatim
+@noindent
+
+We want the program to load the graphics file into memory:
+@verbatim
+long size;
+ FILE *fp;
+ int ret=0;
+
+ if (0 != strcmp(method, "GET")) return MHD_NO;
+
+ size = GetFileSize(FILENAME);
+ if (size != 0)
+ {
+ fp = fopen(FILENAME, "rb");
+ if (fp)
+ {
+ buffer = malloc(size);
+ if (buffer)
+ if (size == fread(buffer, 1, size, fp)) ret=1;
+ }
+
+ fclose(fp);
+ }
+@end verbatim
+@noindent
+
+The @code{GetFileSize} function, which returns a size of zero if the file could not be opened or
+found, is left out on this page for tidiness.
+
+When dealing with files and allocating memory, there is a lot that could go wrong on the
+sider side and if so, the client should be informed with @code{MHD_HTTP_INTERNAL_SERVER_ERROR}.
+
+@verbatim
+ if (!ret)
+ {
+ 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);
+
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR, response);
+
+ return MHD_YES;
+ }
+@end verbatim
+@noindent
+
+Note that we nevertheless have to create an response object even for sending a simple error code.
+Otherwise, the connection would just be closed without comment, leaving the client curious about
+what has happened.
+
+But in the case of success a response will be constructed that contains the buffer filled with the
+file's content.
+
+@verbatim
+response = MHD_create_response_from_data(size, (void*)buffer, MHD_YES, MHD_NO);
+@end verbatim
+@noindent
+
+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 @ref{Hello browser example},
+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}
+command is invoked by us.
+
+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:
+@verbatim
+MHD_add_response_header(response, "Content-Type", MIMETYPE);
+@end verbatim
+@noindent
+We do not have to append a colon expected by the protocol hehind the first
+field---@emph{GNU libhttpdmicro} will take care of this.
+
+The function finishes with the well-known lines
+@verbatim
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+ return ret;
+}
+@end verbatim
+@noindent
+
+The complete program @code{responseheaders.c} is in the @code{examples} section as usual.
+Find a @emph{PNG} file you like and save it to the directory the example is run from under the name
+@code{picture.png}. You should find the image displayed on your browser if everything worked well.
+
+@heading Remarks
+The include file of the @emph{MHD} library comes with the header types mentioned in @emph{RFC 2616}
+already defined as macros. Thus, we could have written @code{MHD_HTTP_HEADER_CONTENT_TYPE} instead
+of @code{"Content-Type"} as well. However, one is not limited to these standard headers and could
+add custom response headers without violated the protocol. Whether and how the client would react
+to these custom header is up to the receiver. Likewise, the client is allowed to send custom request
+headers to the server as well, opening up yet more possibilities how client and server could
+communicate with each other.
+
+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.
+
+@heading Exercises
+@itemize @bullet
+
+@item
+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
+instantly, postpone the queuing in the callback with the @code{sleep} function for 30 seconds
+@emph{if} the file @code{/big.png} is requested (but deliver the same as above). A request for
+@code{/picture.png} should provide just the same but without any artificial delays.
+
+Now start two instances of your browser (or even use two machines) and see how the second client
+is put on hold while the first waits for his request on the slow file to be fulfilled.
+
+Finally, change the sourcecode to use @code{MHD_USE_THREAD_PER_CONNECTION} when the daemon is
+started and try again.
+
+
+@item
+Did you succeed in implementing the clock exercise yet? This time, let the server save the
+program's start time @code{t} and implement a response simulating a countdown that reaches 0 at
+@code{t+60}. 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,
+
+A non official, but widely understood, response header line is @code{Refresh: DELAY; url=URL} 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 @emph{URI} the server is reachable
+from the client's point of view.
+
+Maybe you want also to visualize the countdown as a status bar by creating a
+@code{<table>} consisting of one row and @code{n} columns whose fields contain small images of either
+a red or a green light.
+
+@end itemize
diff --git a/doc/tutorial.texi b/doc/tutorial.texi
@@ -0,0 +1,119 @@
+\input texinfo @c -*-texinfo-*-
+@finalout
+@setfilename libmicrohttpdtutorial
+@settitle A tutorial for GNU libmicrohttpd
+@afourpaper
+
+@set VERSION 0.3.1 beta
+
+@titlepage
+@title A Tutorial for GNU libmicrohttpd
+@subtitle written for version @value{VERSION}
+@author Sebastian Gerhardt (@email{sebgerhardt@@gmx.net})
+@page
+@vskip 0pt plus 1filll
+@end titlepage
+
+@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.2
+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".
+@end verbatim
+
+@contents
+
+@ifnottex
+@node Top
+@top Top
+@end ifnottex
+
+@menu
+* Introduction::
+* Hello browser example::
+* Exploring requests::
+* Response headers::
+* A basic authentication::
+* Processing post data::
+* Bibliography::
+* License text::
+* Example programs::
+@end menu
+
+@node Introduction
+@chapter Introduction
+@include introduction.inc
+
+@node Hello browser example
+@chapter Hello browser example
+@include hellobrowser.inc
+
+@node Exploring requests
+@chapter Exploring requests
+@include exploringrequests.inc
+
+@node Response headers
+@chapter Response headers
+@include responseheaders.inc
+
+@node A basic authentication
+@chapter A basic authentication
+@include basicauthentication.inc
+
+@node Processing post data
+@chapter Processing post data
+@include processingpost.inc
+
+
+@node Bibliography
+@appendix Bibliography
+@include bibliography.inc
+
+@node License text
+@appendix GNU Free Documentation License
+@include fdl-1.2.texi
+
+@node Example programs
+@appendix Example programs
+@menu
+* hellobrowser.c::
+* logging.c::
+* responseheaders.c::
+* basicauthentication.c::
+* simplepost.c::
+@end menu
+
+@node hellobrowser.c
+@section hellobrowser.c
+@smalldisplay
+@verbatiminclude examples/hellobrowser.c
+@end smalldisplay
+
+@node logging.c
+@section logging.c
+@smalldisplay
+@verbatiminclude examples/logging.c
+@end smalldisplay
+
+@node responseheaders.c
+@section responseheaders.c
+@smalldisplay
+@verbatiminclude examples/responseheaders.c
+@end smalldisplay
+
+@node basicauthentication.c
+@section basicauthentication.c
+@smalldisplay
+@verbatiminclude examples/basicauthentication.c
+@end smalldisplay
+
+@node simplepost.c
+@section simplepost.c
+@smalldisplay
+@verbatiminclude examples/simplepost.c
+@end smalldisplay
+
+@bye