]> git.pld-linux.org Git - packages/libmicrohttpd.git/blob - libmicrohttpd-missing-files.patch
- updated to 0.9.20
[packages/libmicrohttpd.git] / libmicrohttpd-missing-files.patch
1 --- libmicrohttpd-0.9.16/doc/chapters/sessions.inc.orig 1970-01-01 01:00:00.000000000 +0100
2 +++ libmicrohttpd-0.9.16/doc/chapters/sessions.inc      2011-11-06 06:41:40.346690352 +0100
3 @@ -0,0 +1,71 @@
4 +This chapter discusses how one should manage sessions, that is, share state between multiple
5 +HTTP requests from the same user.  We use a simple example where the user submits multiple
6 +forms and the server is supposed to accumulate state from all of these forms.  Naturally, as
7 +this is a network protocol, our session mechanism must support having many users with
8 +many concurrent sessions at the same time.
9 +
10 +In order to track users, we use a simple session cookie.  A session cookie expires when the
11 +user closes the browser.  Changing from session cookies to persistent cookies only requires
12 +adding an expiration time to the cookie.  The server creates a fresh session cookie whenever
13 +a request without a cookie is received, or if the supplied session cookie is not known to
14 +the server.
15 +
16 +@heading Looking up the cookie
17 +
18 +Since MHD parses the HTTP cookie header for us, looking up an existing cookie
19 +is straightforward:
20 +
21 +@verbatim
22 +FIXME.
23 +@end verbatim
24 +
25 +Here, FIXME is the name we chose for our session cookie.
26 +
27 +
28 +@heading Setting the cookie header
29 +
30 +MHD requires the user to provide the full cookie format string in order to set
31 +cookies.  In order to generate a unique cookie, our example creates a random
32 +64-character text string to be used as the value of the cookie:
33 +
34 +@verbatim
35 +FIXME.
36 +@end verbatim
37 +
38 +Given this cookie value, we can then set the cookie header in our HTTP response 
39 +as follows:
40 +
41 +@verbatim
42 +FIXME.
43 +@end verbatim
44 +
45 +
46 +@heading Remark: Session expiration
47 +
48 +It is of course possible that clients stop their interaction with the
49 +server at any time.  In order to avoid using too much storage, the
50 +server must thus discard inactive sessions at some point.  Our example
51 +implements this by discarding inactive sessions after a certain amount
52 +of time.  Alternatively, the implementation may limit the total number
53 +of active sessions.  Which bounds are used for idle sessions or the
54 +total number of sessions obviously depends largely on the type of
55 +the application and available server resources.
56 +
57 +@heading Example code
58 +
59 +A sample application implementing a website with multiple
60 +forms (which are dynamically created using values from previous
61 +POST requests from the same session) is available
62 +as the example @code{sessions.c}.
63 +
64 +Note that the example uses a simple, $O(n)$ linked list traversal to
65 +look up sessions and to expire old sessions.  Using a hash table and a
66 +heap would be more appropriate if a large number of concurrent
67 +sessions is expected.
68 +
69 +@heading Remarks
70 +
71 +Naturally, it is quite conceivable to store session data in a database
72 +instead of in memory.  Still, having mechanisms to expire data
73 +associated with long-time idle sessions (where the business process
74 +has still not finished) is likely a good idea.
75 --- libmicrohttpd-0.9.16/doc/examples/sessions.c.orig   1970-01-01 01:00:00.000000000 +0100
76 +++ libmicrohttpd-0.9.16/doc/examples/sessions.c        2011-11-06 06:41:35.430023520 +0100
77 @@ -0,0 +1,748 @@
78 +/*
79 +     This file is part of libmicrohttpd
80 +     (C) 2011 Christian Grothoff (and other contributing authors)
81 +
82 +     This library is free software; you can redistribute it and/or
83 +     modify it under the terms of the GNU Lesser General Public
84 +     License as published by the Free Software Foundation; either
85 +     version 2.1 of the License, or (at your option) any later version.
86 +
87 +     This library is distributed in the hope that it will be useful,
88 +     but WITHOUT ANY WARRANTY; without even the implied warranty of
89 +     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
90 +     Lesser General Public License for more details.
91 +
92 +     You should have received a copy of the GNU Lesser General Public
93 +     License along with this library; if not, write to the Free Software
94 +     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
95 +*/
96 +/**
97 + * @file post_example.c
98 + * @brief example for processing POST requests using libmicrohttpd
99 + * @author Christian Grothoff
100 + */
101 +
102 +/* needed for asprintf */
103 +#define _GNU_SOURCE
104 +
105 +
106 +#include <stdlib.h>
107 +#include <string.h>
108 +#include <stdio.h>
109 +#include <errno.h>
110 +#include <time.h>
111 +#include <microhttpd.h>
112 +
113 +/**
114 + * Invalid method page.
115 + */
116 +#define METHOD_ERROR "<html><head><title>Illegal request</title></head><body>Go away.</body></html>"
117 +
118 +/**
119 + * Invalid URL page.
120 + */
121 +#define NOT_FOUND_ERROR "<html><head><title>Not found</title></head><body>Go away.</body></html>"
122 +
123 +/**
124 + * Front page. (/)
125 + */
126 +#define MAIN_PAGE "<html><head><title>Welcome</title></head><body><form action=\"/2\" method=\"post\">What is your name? <input type=\"text\" name=\"v1\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
127 +
128 +/**
129 + * Second page. (/2)
130 + */
131 +#define SECOND_PAGE "<html><head><title>Tell me more</title></head><body><a href=\"/\">previous</a> <form action=\"/S\" method=\"post\">%s, what is your job? <input type=\"text\" name=\"v2\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
132 +
133 +/**
134 + * Second page (/S)
135 + */
136 +#define SUBMIT_PAGE "<html><head><title>Ready to submit?</title></head><body><form action=\"/F\" method=\"post\"><a href=\"/2\">previous </a> <input type=\"hidden\" name=\"DONE\" value=\"yes\" /><input type=\"submit\" value=\"Submit\" /></body></html>"
137 +
138 +/**
139 + * Last page.
140 + */
141 +#define LAST_PAGE "<html><head><title>Thank you</title></head><body>Thank you.</body></html>"
142 +
143 +/**
144 + * Name of our cookie.
145 + */
146 +#define COOKIE_NAME "session"
147 +
148 +
149 +/**
150 + * State we keep for each user/session/browser.
151 + */
152 +struct Session
153 +{
154 +  /**
155 +   * We keep all sessions in a linked list.
156 +   */
157 +  struct Session *next;
158 +
159 +  /**
160 +   * Unique ID for this session. 
161 +   */
162 +  char sid[33];
163 +
164 +  /**
165 +   * Reference counter giving the number of connections
166 +   * currently using this session.
167 +   */
168 +  unsigned int rc;
169 +
170 +  /**
171 +   * Time when this session was last active.
172 +   */
173 +  time_t start;
174 +
175 +  /**
176 +   * String submitted via form.
177 +   */
178 +  char value_1[64];
179 +
180 +  /**
181 +   * Another value submitted via form.
182 +   */
183 +  char value_2[64];
184 +
185 +};
186 +
187 +
188 +/**
189 + * Data kept per request.
190 + */
191 +struct Request
192 +{
193 +
194 +  /**
195 +   * Associated session.
196 +   */
197 +  struct Session *session;
198 +
199 +  /**
200 +   * Post processor handling form data (IF this is
201 +   * a POST request).
202 +   */
203 +  struct MHD_PostProcessor *pp;
204 +
205 +  /**
206 +   * URL to serve in response to this POST (if this request 
207 +   * was a 'POST')
208 +   */
209 +  const char *post_url;
210 +
211 +};
212 +
213 +
214 +/**
215 + * Linked list of all active sessions.  Yes, O(n) but a
216 + * hash table would be overkill for a simple example...
217 + */
218 +static struct Session *sessions;
219 +
220 +
221 +
222 +
223 +/**
224 + * Return the session handle for this connection, or 
225 + * create one if this is a new user.
226 + */
227 +static struct Session *
228 +get_session (struct MHD_Connection *connection)
229 +{
230 +  struct Session *ret;
231 +  const char *cookie;
232 +
233 +  cookie = MHD_lookup_connection_value (connection,
234 +                                       MHD_COOKIE_KIND,
235 +                                       COOKIE_NAME);
236 +  if (cookie != NULL)
237 +    {
238 +      /* find existing session */
239 +      ret = sessions;
240 +      while (NULL != ret)
241 +       {
242 +         if (0 == strcmp (cookie, ret->sid))
243 +           break;
244 +         ret = ret->next;
245 +       }
246 +      if (NULL != ret)
247 +       {
248 +         ret->rc++;
249 +         return ret;
250 +       }
251 +    }
252 +  /* create fresh session */
253 +  ret = calloc (1, sizeof (struct Session));
254 +  if (NULL == ret)
255 +    {                                          
256 +      fprintf (stderr, "calloc error: %s\n", strerror (errno));
257 +      return NULL; 
258 +    }
259 +  /* not a super-secure way to generate a random session ID,
260 +     but should do for a simple example... */
261 +  snprintf (ret->sid,
262 +           sizeof (ret->sid),
263 +           "%X%X%X%X",
264 +           (unsigned int) random (),
265 +           (unsigned int) random (),
266 +           (unsigned int) random (),
267 +           (unsigned int) random ());
268 +  ret->rc++;  
269 +  ret->start = time (NULL);
270 +  ret->next = sessions;
271 +  sessions = ret;
272 +  return ret;
273 +}
274 +
275 +
276 +/**
277 + * Type of handler that generates a reply.
278 + *
279 + * @param cls content for the page (handler-specific)
280 + * @param mime mime type to use
281 + * @param session session information
282 + * @param connection connection to process
283 + * @param MHD_YES on success, MHD_NO on failure
284 + */
285 +typedef int (*PageHandler)(const void *cls,
286 +                          const char *mime,
287 +                          struct Session *session,
288 +                          struct MHD_Connection *connection);
289 +
290 +
291 +/**
292 + * Entry we generate for each page served.
293 + */ 
294 +struct Page
295 +{
296 +  /**
297 +   * Acceptable URL for this page.
298 +   */
299 +  const char *url;
300 +
301 +  /**
302 +   * Mime type to set for the page.
303 +   */
304 +  const char *mime;
305 +
306 +  /**
307 +   * Handler to call to generate response.
308 +   */
309 +  PageHandler handler;
310 +
311 +  /**
312 +   * Extra argument to handler.
313 +   */ 
314 +  const void *handler_cls;
315 +};
316 +
317 +
318 +/**
319 + * Add header to response to set a session cookie.
320 + *
321 + * @param session session to use
322 + * @param response response to modify
323 + */ 
324 +static void
325 +add_session_cookie (struct Session *session,
326 +                   struct MHD_Response *response)
327 +{
328 +  char cstr[256];
329 +  snprintf (cstr,
330 +           sizeof (cstr),
331 +           "%s=%s",
332 +           COOKIE_NAME,
333 +           session->sid);
334 +  if (MHD_NO == 
335 +      MHD_add_response_header (response,
336 +                              MHD_HTTP_HEADER_SET_COOKIE,
337 +                              cstr))
338 +    {
339 +      fprintf (stderr, 
340 +              "Failed to set session cookie header!\n");
341 +    }
342 +}
343 +
344 +
345 +/**
346 + * Handler that returns a simple static HTTP page that
347 + * is passed in via 'cls'.
348 + *
349 + * @param cls a 'const char *' with the HTML webpage to return
350 + * @param mime mime type to use
351 + * @param session session handle 
352 + * @param connection connection to use
353 + */
354 +static int
355 +serve_simple_form (const void *cls,
356 +                  const char *mime,
357 +                  struct Session *session,
358 +                  struct MHD_Connection *connection)
359 +{
360 +  int ret;
361 +  const char *form = cls;
362 +  struct MHD_Response *response;
363 +
364 +  /* return static form */
365 +  response = MHD_create_response_from_buffer (strlen (form),
366 +                                             (void *) form,
367 +                                             MHD_RESPMEM_PERSISTENT);
368 +  add_session_cookie (session, response);
369 +  MHD_add_response_header (response,
370 +                          MHD_HTTP_HEADER_CONTENT_ENCODING,
371 +                          mime);
372 +  ret = MHD_queue_response (connection, 
373 +                           MHD_HTTP_OK, 
374 +                           response);
375 +  MHD_destroy_response (response);
376 +  return ret;
377 +}
378 +
379 +
380 +/**
381 + * Handler that adds the 'v1' value to the given HTML code.
382 + *
383 + * @param cls a 'const char *' with the HTML webpage to return
384 + * @param mime mime type to use
385 + * @param session session handle 
386 + * @param connection connection to use
387 + */
388 +static int
389 +fill_v1_form (const void *cls,
390 +             const char *mime,
391 +             struct Session *session,
392 +             struct MHD_Connection *connection)
393 +{
394 +  int ret;
395 +  const char *form = cls;
396 +  char *reply;
397 +  struct MHD_Response *response;
398 +
399 +  if (-1 == asprintf (&reply,
400 +                     form,
401 +                     session->value_1))
402 +    {
403 +      /* oops */
404 +      return MHD_NO;
405 +    }
406 +  /* return static form */
407 +  response = MHD_create_response_from_buffer (strlen (reply),
408 +                                             (void *) reply,
409 +                                             MHD_RESPMEM_MUST_FREE);
410 +  add_session_cookie (session, response);
411 +  MHD_add_response_header (response,
412 +                          MHD_HTTP_HEADER_CONTENT_ENCODING,
413 +                          mime);
414 +  ret = MHD_queue_response (connection, 
415 +                           MHD_HTTP_OK, 
416 +                           response);
417 +  MHD_destroy_response (response);
418 +  return ret;
419 +}
420 +
421 +
422 +/**
423 + * Handler that adds the 'v1' and 'v2' values to the given HTML code.
424 + *
425 + * @param cls a 'const char *' with the HTML webpage to return
426 + * @param mime mime type to use
427 + * @param session session handle 
428 + * @param connection connection to use
429 + */
430 +static int
431 +fill_v1_v2_form (const void *cls,
432 +                const char *mime,
433 +                struct Session *session,
434 +                struct MHD_Connection *connection)
435 +{
436 +  int ret;
437 +  const char *form = cls;
438 +  char *reply;
439 +  struct MHD_Response *response;
440 +
441 +  if (-1 == asprintf (&reply,
442 +                     form,
443 +                     session->value_1,
444 +                     session->value_2))
445 +    {
446 +      /* oops */
447 +      return MHD_NO;
448 +    }
449 +  /* return static form */
450 +  response = MHD_create_response_from_buffer (strlen (reply),
451 +                                             (void *) reply,
452 +                                             MHD_RESPMEM_MUST_FREE);
453 +  add_session_cookie (session, response);
454 +  MHD_add_response_header (response,
455 +                          MHD_HTTP_HEADER_CONTENT_ENCODING,
456 +                          mime);
457 +  ret = MHD_queue_response (connection, 
458 +                           MHD_HTTP_OK, 
459 +                           response);
460 +  MHD_destroy_response (response);
461 +  return ret;
462 +}
463 +
464 +
465 +/**
466 + * Handler used to generate a 404 reply.
467 + *
468 + * @param cls a 'const char *' with the HTML webpage to return
469 + * @param mime mime type to use
470 + * @param session session handle 
471 + * @param connection connection to use
472 + */
473 +static int
474 +not_found_page (const void *cls,
475 +               const char *mime,
476 +               struct Session *session,
477 +               struct MHD_Connection *connection)
478 +{
479 +  int ret;
480 +  struct MHD_Response *response;
481 +
482 +  /* unsupported HTTP method */
483 +  response = MHD_create_response_from_buffer (strlen (NOT_FOUND_ERROR),
484 +                                             (void *) NOT_FOUND_ERROR,
485 +                                             MHD_RESPMEM_PERSISTENT);
486 +  ret = MHD_queue_response (connection, 
487 +                           MHD_HTTP_NOT_FOUND, 
488 +                           response);
489 +  MHD_add_response_header (response,
490 +                          MHD_HTTP_HEADER_CONTENT_ENCODING,
491 +                          mime);
492 +  MHD_destroy_response (response);
493 +  return ret;
494 +}
495 +
496 +
497 +/**
498 + * List of all pages served by this HTTP server.
499 + */
500 +static struct Page pages[] = 
501 +  {
502 +    { "/", "text/html",  &fill_v1_form, MAIN_PAGE },
503 +    { "/2", "text/html", &fill_v1_v2_form, SECOND_PAGE },
504 +    { "/S", "text/html", &serve_simple_form, SUBMIT_PAGE },
505 +    { "/F", "text/html", &serve_simple_form, LAST_PAGE },
506 +    { NULL, NULL, &not_found_page, NULL } /* 404 */
507 +  };
508 +
509 +
510 +
511 +/**
512 + * Iterator over key-value pairs where the value
513 + * maybe made available in increments and/or may
514 + * not be zero-terminated.  Used for processing
515 + * POST data.
516 + *
517 + * @param cls user-specified closure
518 + * @param kind type of the value
519 + * @param key 0-terminated key for the value
520 + * @param filename name of the uploaded file, NULL if not known
521 + * @param content_type mime-type of the data, NULL if not known
522 + * @param transfer_encoding encoding of the data, NULL if not known
523 + * @param data pointer to size bytes of data at the
524 + *              specified offset
525 + * @param off offset of data in the overall value
526 + * @param size number of bytes in data available
527 + * @return MHD_YES to continue iterating,
528 + *         MHD_NO to abort the iteration
529 + */
530 +static int
531 +post_iterator (void *cls,
532 +              enum MHD_ValueKind kind,
533 +              const char *key,
534 +              const char *filename,
535 +              const char *content_type,
536 +              const char *transfer_encoding,
537 +              const char *data, uint64_t off, size_t size)
538 +{
539 +  struct Request *request = cls;
540 +  struct Session *session = request->session;
541 +
542 +  if (0 == strcmp ("DONE", key))
543 +    {
544 +      fprintf (stdout,
545 +              "Session `%s' submitted `%s', `%s'\n",
546 +              session->sid,
547 +              session->value_1,
548 +              session->value_2);
549 +      return MHD_YES;
550 +    }
551 +  if (0 == strcmp ("v1", key))
552 +    {
553 +      if (size + off > sizeof(session->value_1))
554 +       size = sizeof (session->value_1) - off;
555 +      memcpy (&session->value_1[off],
556 +             data,
557 +             size);
558 +      if (size + off < sizeof (session->value_1))
559 +       session->value_1[size+off] = '\0';
560 +      return MHD_YES;
561 +    }
562 +  if (0 == strcmp ("v2", key))
563 +    {
564 +      if (size + off > sizeof(session->value_2))
565 +       size = sizeof (session->value_2) - off;
566 +      memcpy (&session->value_2[off],
567 +             data,
568 +             size);
569 +      if (size + off < sizeof (session->value_2))
570 +       session->value_2[size+off] = '\0';
571 +      return MHD_YES;
572 +    }
573 +  fprintf (stderr, "Unsupported form value `%s'\n", key);
574 +  return MHD_YES;
575 +}
576 +
577 +
578 +/**
579 + * Main MHD callback for handling requests.
580 + *
581 + *
582 + * @param cls argument given together with the function
583 + *        pointer when the handler was registered with MHD
584 + * @param url the requested url
585 + * @param method the HTTP method used ("GET", "PUT", etc.)
586 + * @param version the HTTP version string (i.e. "HTTP/1.1")
587 + * @param upload_data the data being uploaded (excluding HEADERS,
588 + *        for a POST that fits into memory and that is encoded
589 + *        with a supported encoding, the POST data will NOT be
590 + *        given in upload_data and is instead available as
591 + *        part of MHD_get_connection_values; very large POST
592 + *        data *will* be made available incrementally in
593 + *        upload_data)
594 + * @param upload_data_size set initially to the size of the
595 + *        upload_data provided; the method must update this
596 + *        value to the number of bytes NOT processed;
597 + * @param con_cls pointer that the callback can set to some
598 + *        address and that will be preserved by MHD for future
599 + *        calls for this request; since the access handler may
600 + *        be called many times (i.e., for a PUT/POST operation
601 + *        with plenty of upload data) this allows the application
602 + *        to easily associate some request-specific state.
603 + *        If necessary, this state can be cleaned up in the
604 + *        global "MHD_RequestCompleted" callback (which
605 + *        can be set with the MHD_OPTION_NOTIFY_COMPLETED).
606 + *        Initially, <tt>*con_cls</tt> will be NULL.
607 + * @return MHS_YES if the connection was handled successfully,
608 + *         MHS_NO if the socket must be closed due to a serios
609 + *         error while handling the request
610 + */
611 +static int
612 +create_response (void *cls,
613 +                struct MHD_Connection *connection,
614 +                const char *url,
615 +                const char *method,
616 +                const char *version,
617 +                const char *upload_data, 
618 +                size_t *upload_data_size,
619 +                void **ptr)
620 +{
621 +  struct MHD_Response *response;
622 +  struct Request *request;
623 +  struct Session *session;
624 +  int ret;
625 +  unsigned int i;
626 +
627 +  request = *ptr;
628 +  if (NULL == request)
629 +    {
630 +      request = calloc (1, sizeof (struct Request));
631 +      if (NULL == request)
632 +       {
633 +         fprintf (stderr, "calloc error: %s\n", strerror (errno));
634 +         return MHD_NO;
635 +       }
636 +      *ptr = request;
637 +      if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
638 +       {
639 +         request->pp = MHD_create_post_processor (connection, 1024,
640 +                                                  &post_iterator, request);
641 +         if (NULL == request->pp)
642 +           {
643 +             fprintf (stderr, "Failed to setup post processor for `%s'\n",
644 +                      url);
645 +             return MHD_NO; /* internal error */
646 +           }
647 +       }
648 +      return MHD_YES;
649 +    }
650 +  if (NULL == request->session)
651 +    {
652 +      request->session = get_session (connection);
653 +      if (NULL == request->session)
654 +       {
655 +         fprintf (stderr, "Failed to setup session for `%s'\n",
656 +                  url);
657 +         return MHD_NO; /* internal error */
658 +       }
659 +    }
660 +  session = request->session;
661 +  session->start = time (NULL);
662 +  if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
663 +    {      
664 +      /* evaluate POST data */
665 +      MHD_post_process (request->pp,
666 +                       upload_data,
667 +                       *upload_data_size);
668 +      if (0 != *upload_data_size)
669 +       {
670 +         *upload_data_size = 0;
671 +         return MHD_YES;
672 +       }
673 +      /* done with POST data, serve response */
674 +      MHD_destroy_post_processor (request->pp);
675 +      request->pp = NULL;
676 +      method = MHD_HTTP_METHOD_GET; /* fake 'GET' */
677 +      if (NULL != request->post_url)
678 +       url = request->post_url;
679 +    }
680 +
681 +  if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
682 +       (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
683 +    {
684 +      /* find out which page to serve */
685 +      i=0;
686 +      while ( (pages[i].url != NULL) &&
687 +             (0 != strcmp (pages[i].url, url)) )
688 +       i++;
689 +      ret = pages[i].handler (pages[i].handler_cls, 
690 +                             pages[i].mime,
691 +                             session, connection);
692 +      if (ret != MHD_YES)
693 +       fprintf (stderr, "Failed to create page for `%s'\n",
694 +                url);
695 +      return ret;
696 +    }
697 +  /* unsupported HTTP method */
698 +  response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
699 +                                             (void *) METHOD_ERROR,
700 +                                             MHD_RESPMEM_PERSISTENT);
701 +  ret = MHD_queue_response (connection, 
702 +                           MHD_HTTP_METHOD_NOT_ACCEPTABLE, 
703 +                           response);
704 +  MHD_destroy_response (response);
705 +  return ret;
706 +}
707 +
708 +
709 +/**
710 + * Callback called upon completion of a request.
711 + * Decrements session reference counter.
712 + *
713 + * @param cls not used
714 + * @param connection connection that completed
715 + * @param con_cls session handle
716 + * @param toe status code
717 + */
718 +static void
719 +request_completed_callback (void *cls,
720 +                           struct MHD_Connection *connection,
721 +                           void **con_cls,
722 +                           enum MHD_RequestTerminationCode toe)
723 +{
724 +  struct Request *request = *con_cls;
725 +
726 +  if (NULL == request)
727 +    return;
728 +  if (NULL != request->session)
729 +    request->session->rc--;
730 +  if (NULL != request->pp)
731 +    MHD_destroy_post_processor (request->pp);
732 +  free (request);
733 +}
734 +
735 +
736 +/**
737 + * Clean up handles of sessions that have been idle for
738 + * too long.
739 + */
740 +static void
741 +expire_sessions ()
742 +{
743 +  struct Session *pos;
744 +  struct Session *prev;
745 +  struct Session *next;
746 +  time_t now;
747 +
748 +  now = time (NULL);
749 +  prev = NULL;
750 +  pos = sessions;
751 +  while (NULL != pos)
752 +    {
753 +      next = pos->next;
754 +      if (now - pos->start > 60 * 60)
755 +       {
756 +         /* expire sessions after 1h */
757 +         if (NULL == prev)
758 +           sessions = pos->next;
759 +         else
760 +           prev->next = next;
761 +         free (pos);
762 +       }
763 +      else
764 +        prev = pos;
765 +      pos = next;
766 +    }      
767 +}
768 +
769 +
770 +/**
771 + * Call with the port number as the only argument.
772 + * Never terminates (other than by signals, such as CTRL-C).
773 + */
774 +int
775 +main (int argc, char *const *argv)
776 +{
777 +  struct MHD_Daemon *d;
778 +  struct timeval tv;
779 +  struct timeval *tvp;
780 +  fd_set rs;
781 +  fd_set ws;
782 +  fd_set es;
783 +  int max;
784 +  unsigned MHD_LONG_LONG mhd_timeout;
785 +
786 +  if (argc != 2)
787 +    {
788 +      printf ("%s PORT\n", argv[0]);
789 +      return 1;
790 +    }
791 +  /* initialize PRNG */
792 +  srandom ((unsigned int) time (NULL));
793 +  d = MHD_start_daemon (MHD_USE_DEBUG,
794 +                        atoi (argv[1]),
795 +                        NULL, NULL, 
796 +                       &create_response, NULL, 
797 +                       MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15,
798 +                       MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL,
799 +                       MHD_OPTION_END);
800 +  if (NULL == d)
801 +    return 1;
802 +  while (1)
803 +    {
804 +      expire_sessions ();
805 +      max = 0;
806 +      FD_ZERO (&rs);
807 +      FD_ZERO (&ws);
808 +      FD_ZERO (&es);
809 +      if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
810 +       break; /* fatal internal error */
811 +      if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)        
812 +       {
813 +         tv.tv_sec = mhd_timeout / 1000;
814 +         tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
815 +         tvp = &tv;      
816 +       }
817 +      else
818 +       tvp = NULL;
819 +      select (max + 1, &rs, &ws, &es, tvp);
820 +      MHD_run (d);
821 +    }
822 +  MHD_stop_daemon (d);
823 +  return 0;
824 +}
825 +
This page took 0.075079 seconds and 3 git commands to generate.