diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-02-15 07:38:38 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-02-15 07:38:38 +0100 |
commit | 5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822 (patch) | |
tree | 4af4b56bc36350918c99530c2380b6f9032b1531 | |
parent | 9562d1656d683cce2a2557fc0c2e5573fabfc6bb (diff) | |
download | libmicrohttpd-5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822.tar.gz libmicrohttpd-5c8fbeb97b01f8d4bb25a01e8ad70ebcd95bb822.zip |
implementing thread_main_connection_upgrade
-rw-r--r-- | src/lib/connection_add.c | 42 | ||||
-rw-r--r-- | src/lib/daemon_poll.c | 60 | ||||
-rw-r--r-- | src/lib/daemon_poll.h | 12 | ||||
-rw-r--r-- | src/lib/daemon_select.c | 92 | ||||
-rw-r--r-- | src/lib/daemon_select.h | 12 |
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 | */ | ||
40 | static void | ||
41 | thread_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 | */ | ||
461 | void | ||
462 | MHD_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 | */ | ||
78 | void | ||
79 | MHD_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 | */ | ||
487 | void | ||
488 | MHD_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 | */ | ||
50 | void | ||
51 | MHD_daemon_upgrade_connection_with_select_ (struct MHD_Connection *con) | ||
52 | MHD_NONNULL(1); | ||
53 | #endif | ||
54 | |||
43 | #endif | 55 | #endif |