aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd')
-rw-r--r--src/microhttpd/daemon.c64
-rw-r--r--src/microhttpd/internal.h7
-rw-r--r--src/microhttpd/response.c70
-rw-r--r--src/microhttpd/test_upgrade_ssl.c4
4 files changed, 78 insertions, 67 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 62cd3ce8..08709c80 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -883,6 +883,61 @@ call_handlers (struct MHD_Connection *con,
883 883
884#if HTTPS_SUPPORT 884#if HTTPS_SUPPORT
885/** 885/**
886 * This function finishes the process of closing the
887 * connection associated with the @a urh. It should
888 * be called if the `was_closed` flag is set and the
889 * buffer has been drained.
890 *
891 * @param urh handle to the upgraded response we are finished with
892 */
893static void
894finish_upgrade_close (struct MHD_UpgradeResponseHandle *urh)
895{
896 struct MHD_Connection *connection = urh->connection;
897 struct MHD_Daemon *daemon = connection->daemon;
898
899 DLL_remove (daemon->urh_head,
900 daemon->urh_tail,
901 urh);
902 if (0 != (daemon->options & MHD_USE_EPOLL))
903 {
904 /* epoll documentation suggests that closing a FD
905 automatically removes it from the epoll set; however,
906 this is not true as if we fail to do manually remove it,
907 we are still seeing an event for this fd in epoll,
908 causing grief (use-after-free...) --- at least on my
909 system. */
910 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
911 EPOLL_CTL_DEL,
912 connection->socket_fd,
913 NULL))
914 MHD_PANIC ("Failed to remove FD from epoll set\n");
915 }
916 if (MHD_INVALID_SOCKET != urh->mhd.socket)
917 {
918 /* epoll documentation suggests that closing a FD
919 automatically removes it from the epoll set; however,
920 this is not true as if we fail to do manually remove it,
921 we are still seeing an event for this fd in epoll,
922 causing grief (use-after-free...) --- at least on my
923 system. */
924 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
925 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
926 EPOLL_CTL_DEL,
927 urh->mhd.socket,
928 NULL)) )
929 MHD_PANIC ("Failed to remove FD from epoll set\n");
930 if (0 != MHD_socket_close_ (urh->mhd.socket))
931 MHD_PANIC ("close failed\n");
932 }
933 MHD_resume_connection (connection);
934 MHD_connection_close_ (connection,
935 MHD_REQUEST_TERMINATED_COMPLETED_OK);
936 free (urh);
937}
938
939
940/**
886 * Performs bi-directional forwarding on upgraded HTTPS connections 941 * Performs bi-directional forwarding on upgraded HTTPS connections
887 * based on the readyness state stored in the @a urh handle. 942 * based on the readyness state stored in the @a urh handle.
888 * 943 *
@@ -891,6 +946,8 @@ call_handlers (struct MHD_Connection *con,
891static void 946static void
892process_urh (struct MHD_UpgradeResponseHandle *urh) 947process_urh (struct MHD_UpgradeResponseHandle *urh)
893{ 948{
949 int fin_read;
950
894 /* handle reading from TLS client and writing to application */ 951 /* handle reading from TLS client and writing to application */
895 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && 952 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
896 (urh->in_buffer_off < urh->in_buffer_size) ) 953 (urh->in_buffer_off < urh->in_buffer_size) )
@@ -957,7 +1014,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
957 { 1014 {
958 urh->out_buffer_off += res; 1015 urh->out_buffer_off += res;
959 } 1016 }
1017 fin_read = (0 == res);
960 } 1018 }
1019 else
1020 fin_read = 0;
961 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && 1021 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
962 (urh->out_buffer_off > 0) ) 1022 (urh->out_buffer_off > 0) )
963 { 1023 {
@@ -986,6 +1046,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
986 } 1046 }
987 } 1047 }
988 } 1048 }
1049 if ( (fin_read) &&
1050 (0 == urh->out_buffer_off) &&
1051 (MHD_YES == urh->was_closed) )
1052 finish_upgrade_close (urh);
989} 1053}
990#endif 1054#endif
991 1055
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index 7a1e58e1..9549b19a 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1036,6 +1036,13 @@ struct MHD_UpgradeResponseHandle
1036 * nothing left. 1036 * nothing left.
1037 */ 1037 */
1038 char e_buf[RESERVE_EBUF_SIZE]; 1038 char e_buf[RESERVE_EBUF_SIZE];
1039
1040 /**
1041 * Set to #MHD_YES after the application closed the socket
1042 * via #MHD_UPGRADE_ACTION_CLOSE.
1043 */
1044 int was_closed;
1045
1039#endif 1046#endif
1040 1047
1041}; 1048};
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index aa79196d..c08117d7 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -632,55 +632,27 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
632 /* just need to signal the thread that we are done */ 632 /* just need to signal the thread that we are done */
633 MHD_semaphore_up (connection->upgrade_sem); 633 MHD_semaphore_up (connection->upgrade_sem);
634 } 634 }
635#if HTTPS_SUPPORT
635 else 636 else
636 { 637 {
637 /* signal thread by shutdown() of 'app' socket */ 638 /* signal thread by shutdown() of 'app' socket */
638 shutdown (urh->app.socket, SHUT_RDWR); 639 shutdown (urh->app.socket,
640 SHUT_RDWR);
639 } 641 }
642#endif
640 return MHD_YES; 643 return MHD_YES;
641 } 644 }
642#if HTTPS_SUPPORT 645#if HTTPS_SUPPORT
643 if (0 != (daemon->options & MHD_USE_SSL) ) 646 if (0 != (daemon->options & MHD_USE_SSL) )
644 { 647 {
645 DLL_remove (daemon->urh_head, 648 urh->was_closed = MHD_YES;
646 daemon->urh_tail,
647 urh);
648 if (0 != (daemon->options & MHD_USE_EPOLL))
649 {
650 /* epoll documentation suggests that closing a FD
651 automatically removes it from the epoll set; however,
652 this is not true as if we fail to do manually remove it,
653 we are still seeing an event for this fd in epoll,
654 causing grief (use-after-free...) --- at least on my
655 system. */
656 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
657 EPOLL_CTL_DEL,
658 connection->socket_fd,
659 NULL))
660 MHD_PANIC ("Failed to remove FD from epoll set\n");
661 }
662 if (MHD_INVALID_SOCKET != urh->app.socket) 649 if (MHD_INVALID_SOCKET != urh->app.socket)
663 { 650 {
664 if (0 != MHD_socket_close_ (urh->app.socket)) 651 if (0 != MHD_socket_close_ (urh->app.socket))
665 MHD_PANIC ("close failed\n"); 652 MHD_PANIC ("close failed\n");
653 urh->app.socket = MHD_INVALID_SOCKET;
666 } 654 }
667 if (MHD_INVALID_SOCKET != urh->mhd.socket) 655 return MHD_YES;
668 {
669 /* epoll documentation suggests that closing a FD
670 automatically removes it from the epoll set; however,
671 this is not true as if we fail to do manually remove it,
672 we are still seeing an event for this fd in epoll,
673 causing grief (use-after-free...) --- at least on my
674 system. */
675 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
676 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
677 EPOLL_CTL_DEL,
678 urh->mhd.socket,
679 NULL)) )
680 MHD_PANIC ("Failed to remove FD from epoll set\n");
681 if (0 != MHD_socket_close_ (urh->mhd.socket))
682 MHD_PANIC ("close failed\n");
683 }
684 } 656 }
685#endif 657#endif
686 MHD_resume_connection (connection); 658 MHD_resume_connection (connection);
@@ -688,34 +660,6 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
688 MHD_REQUEST_TERMINATED_COMPLETED_OK); 660 MHD_REQUEST_TERMINATED_COMPLETED_OK);
689 free (urh); 661 free (urh);
690 return MHD_YES; 662 return MHD_YES;
691 case MHD_UPGRADE_ACTION_CORK:
692 /* FIXME: not implemented */
693 return MHD_NO;
694 case MHD_UPGRADE_ACTION_FLUSH:
695#if HTTPS_SUPPORT
696 if (0 != (daemon->options & MHD_USE_SSL))
697 {
698 int avail;
699
700 /* First, check that our pipe is empty, to be sure we do
701 have it all in the buffer. */
702 if ( (0 ==
703#if WINDOWS
704 ioctlsocket
705#else
706 ioctl
707#endif
708 (urh->mhd.socket,
709 FIONREAD,
710 &avail)) &&
711 (0 != avail) )
712 return MHD_NO;
713 /* then, refuse 'flush' unless our buffer is empty */
714 if (0 != urh->out_buffer_off)
715 return MHD_NO;
716 }
717#endif
718 return MHD_YES;
719 default: 663 default:
720 /* we don't understand this one */ 664 /* we don't understand this one */
721 return MHD_NO; 665 return MHD_NO;
diff --git a/src/microhttpd/test_upgrade_ssl.c b/src/microhttpd/test_upgrade_ssl.c
index 5c663dd9..8077f402 100644
--- a/src/microhttpd/test_upgrade_ssl.c
+++ b/src/microhttpd/test_upgrade_ssl.c
@@ -259,10 +259,6 @@ run_usock (void *cls)
259 "Finished"); 259 "Finished");
260 fprintf (stderr, 260 fprintf (stderr,
261 "Closing socket\n"); 261 "Closing socket\n");
262 while (MHD_NO ==
263 MHD_upgrade_action (urh,
264 MHD_UPGRADE_ACTION_FLUSH))
265 usleep (1000);
266 MHD_upgrade_action (urh, 262 MHD_upgrade_action (urh,
267 MHD_UPGRADE_ACTION_CLOSE); 263 MHD_UPGRADE_ACTION_CLOSE);
268 fprintf (stderr, 264 fprintf (stderr,