aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-02-15 07:38:38 +0100
committerChristian Grothoff <christian@grothoff.org>2018-02-15 07:38:38 +0100
commit5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822 (patch)
tree4af4b56bc36350918c99530c2380b6f9032b1531
parent9562d1656d683cce2a2557fc0c2e5573fabfc6bb (diff)
downloadlibmicrohttpd-5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822.tar.gz
libmicrohttpd-5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822.zip
implementing thread_main_connection_upgrade
-rw-r--r--src/lib/connection_add.c42
-rw-r--r--src/lib/daemon_poll.c60
-rw-r--r--src/lib/daemon_poll.h12
-rw-r--r--src/lib/daemon_select.c92
-rw-r--r--src/lib/daemon_select.h12
5 files changed, 218 insertions, 0 deletions
diff --git a/src/lib/connection_add.c b/src/lib/connection_add.c
index 94d37442..fbd7b85f 100644
--- a/src/lib/connection_add.c
+++ b/src/lib/connection_add.c
@@ -24,6 +24,48 @@
24#include "internal.h" 24#include "internal.h"
25#include "connection_add.h" 25#include "connection_add.h"
26#include "daemon_ip_limit.h" 26#include "daemon_ip_limit.h"
27#include "daemon_select.h"
28#include "daemon_poll.h"
29
30
31#ifdef UPGRADE_SUPPORT
32/**
33 * Main function of the thread that handles an individual connection
34 * after it was "upgraded" when #MHD_USE_THREAD_PER_CONNECTION is set.
35 * @remark To be called only from thread that process
36 * connection's recv(), send() and response.
37 *
38 * @param con the connection this thread will handle
39 */
40static void
41thread_main_connection_upgrade (struct MHD_Connection *con)
42{
43#ifdef HTTPS_SUPPORT
44 struct MHD_UpgradeResponseHandle *urh = con->request.urh;
45 struct MHD_Daemon *daemon = con->daemon;
46
47 /* Here, we need to bi-directionally forward
48 until the application tells us that it is done
49 with the socket; */
50 if ( (NULL != daemon->tls_api) &&
51 (MHD_ELS_POLL != daemon->event_loop_syscall) )
52 {
53 MHD_daemon_upgrade_connection_with_select (con);
54 }
55#ifdef HAVE_POLL
56 else if (NULL != daemon->tls_api)
57 {
58 MHD_daemon_upgrade_connection_with_poll_ (con);
59 }
60#endif
61 /* end HTTPS */
62#endif /* HTTPS_SUPPORT */
63 /* TLS forwarding was finished. Cleanup socketpair. */
64 MHD_connection_finish_forward_ (con);
65 /* Do not set 'urh->clean_ready' yet as 'urh' will be used
66 * in connection thread for a little while. */
67}
68#endif /* UPGRADE_SUPPORT */
27 69
28 70
29/** 71/**
diff --git a/src/lib/daemon_poll.c b/src/lib/daemon_poll.c
index bc705aea..92093652 100644
--- a/src/lib/daemon_poll.c
+++ b/src/lib/daemon_poll.c
@@ -450,4 +450,64 @@ MHD_daemon_poll_ (struct MHD_Daemon *daemon,
450#endif 450#endif
451} 451}
452 452
453
454#ifdef HTTPS_SUPPORT
455/**
456 * Process upgraded connection with a poll() loop.
457 * We are in our own thread, only processing @a con
458 *
459 * @param con connection to process
460 */
461void
462MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con)
463{
464 struct MHD_UpgradeResponseHandle *urh = con->request.urh;
465 struct MHD_Daemon *daemon = con->daemon;
466 struct pollfd p[2];
467
468 memset (p,
469 0,
470 sizeof (p));
471 p[0].fd = urh->connection->socket_fd;
472 p[1].fd = urh->mhd.socket;
473
474 while ( (0 != urh->in_buffer_size) ||
475 (0 != urh->out_buffer_size) ||
476 (0 != urh->in_buffer_used) ||
477 (0 != urh->out_buffer_used) )
478 {
479 int timeout;
480
481 urh_update_pollfd (urh,
482 p);
483
484 if ( (con->tls_read_ready) &&
485 (urh->in_buffer_used < urh->in_buffer_size))
486 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
487 else
488 timeout = -1;
489
490 if (MHD_sys_poll_ (p,
491 2,
492 timeout) < 0)
493 {
494 const int err = MHD_socket_get_error_ ();
495
496 if (MHD_SCKT_ERR_IS_EINTR_ (err))
497 continue;
498#ifdef HAVE_MESSAGES
499 MHD_DLOG (con->daemon,
500 MHD_SC_UNEXPECTED_POLL_ERROR,
501 _("Error during poll: `%s'\n"),
502 MHD_socket_strerr_ (err));
503#endif
504 break;
505 }
506 urh_from_pollfd (urh,
507 p);
508 process_urh (urh);
509 }
510}
511#endif
512
453/* end of daemon_poll.c */ 513/* end of daemon_poll.c */
diff --git a/src/lib/daemon_poll.h b/src/lib/daemon_poll.h
index c5dbb88b..8295cc56 100644
--- a/src/lib/daemon_poll.h
+++ b/src/lib/daemon_poll.h
@@ -68,4 +68,16 @@ MHD_daemon_poll_ (struct MHD_Daemon *daemon,
68#endif 68#endif
69 69
70 70
71#ifdef HTTPS_SUPPORT
72/**
73 * Process upgraded connection with a poll() loop.
74 * We are in our own thread, only processing @a con
75 *
76 * @param con connection to process
77 */
78void
79MHD_daemon_upgrade_connection_with_poll_ (struct MHD_Connection *con)
80 MHD_NONNULL(1);
81#endif
82
71#endif 83#endif
diff --git a/src/lib/daemon_select.c b/src/lib/daemon_select.c
index 338b12d5..5d8a7ecc 100644
--- a/src/lib/daemon_select.c
+++ b/src/lib/daemon_select.c
@@ -477,6 +477,98 @@ internal_run_from_select (struct MHD_Daemon *daemon,
477} 477}
478 478
479 479
480#ifdef HTTPS_SUPPORT
481/**
482 * Process upgraded connection with a select loop.
483 * We are in our own thread, only processing @a con
484 *
485 * @param con connection to process
486 */
487void
488MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
489{
490 struct MHD_UpgradeResponseHandle *urh = con->request.urh;
491 struct MHD_Daemon *daemon = con->daemon;
492
493 while ( (0 != urh->in_buffer_size) ||
494 (0 != urh->out_buffer_size) ||
495 (0 != urh->in_buffer_used) ||
496 (0 != urh->out_buffer_used) )
497 {
498 /* use select */
499 fd_set rs;
500 fd_set ws;
501 fd_set es;
502 MHD_socket max_fd;
503 int num_ready;
504 bool result;
505
506 FD_ZERO (&rs);
507 FD_ZERO (&ws);
508 FD_ZERO (&es);
509 max_fd = MHD_INVALID_SOCKET;
510 result = urh_to_fdset (urh,
511 &rs,
512 &ws,
513 &es,
514 &max_fd,
515 FD_SETSIZE);
516 if (! result)
517 {
518#ifdef HAVE_MESSAGES
519 MHD_DLOG (con->daemon,
520 MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE,
521 _("Error preparing select\n"));
522#endif
523 break;
524 }
525 /* FIXME: does this check really needed? */
526 if (MHD_INVALID_SOCKET != max_fd)
527 {
528 struct timeval* tvp;
529 struct timeval tv;
530 if ( (con->tls_read_ready) &&
531 (urh->in_buffer_used < urh->in_buffer_size))
532 { /* No need to wait if incoming data is already pending in TLS buffers. */
533 tv.tv_sec = 0;
534 tv.tv_usec = 0;
535 tvp = &tv;
536 }
537 else
538 tvp = NULL;
539 num_ready = MHD_SYS_select_ (max_fd + 1,
540 &rs,
541 &ws,
542 &es,
543 tvp);
544 }
545 else
546 num_ready = 0;
547 if (num_ready < 0)
548 {
549 const int err = MHD_socket_get_error_();
550
551 if (MHD_SCKT_ERR_IS_EINTR_(err))
552 continue;
553#ifdef HAVE_MESSAGES
554 MHD_DLOG (con->daemon,
555 MHD_SC_UNEXPECTED_SELECT_ERROR,
556 _("Error during select (%d): `%s'\n"),
557 err,
558 MHD_socket_strerr_ (err));
559#endif
560 break;
561 }
562 urh_from_fdset (urh,
563 &rs,
564 &ws,
565 &es);
566 process_urh (urh);
567 }
568}
569#endif
570
571
480/** 572/**
481 * Run webserver operations. This method should be called by clients 573 * Run webserver operations. This method should be called by clients
482 * in combination with #MHD_get_fdset and #MHD_get_timeout() if the 574 * in combination with #MHD_get_fdset and #MHD_get_timeout() if the
diff --git a/src/lib/daemon_select.h b/src/lib/daemon_select.h
index 3625ea87..ec1c5770 100644
--- a/src/lib/daemon_select.h
+++ b/src/lib/daemon_select.h
@@ -40,4 +40,16 @@ MHD_daemon_select_ (struct MHD_Daemon *daemon,
40 MHD_NONNULL(1); 40 MHD_NONNULL(1);
41 41
42 42
43#ifdef HTTPS_SUPPORT
44/**
45 * Process upgraded connection with a select loop.
46 * We are in our own thread, only processing @a con
47 *
48 * @param con connection to process
49 */
50void
51MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con)
52 MHD_NONNULL(1);
53#endif
54
43#endif 55#endif