aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c546
1 files changed, 384 insertions, 162 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 791e17d4..a298a1a4 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -636,6 +636,79 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
636 636
637 637
638/** 638/**
639 * Obtain the select() file descriptor sets for the
640 * given @a urh.
641 *
642 * @param urh upgrade handle to wait for
643 * @param[out] rs read set to initialize
644 * @param[out] ws write set to initialize
645 * @param[out] max_fd maximum FD to update
646 * @param fd_setsize value of FD_SETSIZE
647 * @return #MHD_YES on success, #MHD_NO on error
648 */
649static int
650urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
651 fd_set *rs,
652 fd_set *ws,
653 MHD_socket *max_fd,
654 unsigned int fd_setsize)
655{
656 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
657 (! MHD_add_to_fd_set_ (urh->mhd.socket,
658 rs,
659 max_fd,
660 fd_setsize)) )
661 return MHD_NO;
662 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
663 (! MHD_add_to_fd_set_ (urh->mhd.socket,
664 ws,
665 max_fd,
666 fd_setsize)) )
667 return MHD_NO;
668 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
669 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
670 rs,
671 max_fd,
672 fd_setsize)) )
673 return MHD_NO;
674 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
675 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
676 ws,
677 max_fd,
678 fd_setsize)) )
679 return MHD_NO;
680 return MHD_YES;
681}
682
683
684/**
685 * Update the @a urh based on the ready FDs in the @a rs and @a ws.
686 *
687 * @param urh upgrade handle to update
688 * @param rs read result from select()
689 * @param ws write result from select()
690 */
691static void
692urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
693 const fd_set *rs,
694 const fd_set *ws)
695{
696 if (FD_ISSET (urh->connection->socket_fd,
697 rs))
698 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
699 if (FD_ISSET (urh->connection->socket_fd,
700 ws))
701 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
702 if (FD_ISSET (urh->mhd.socket,
703 rs))
704 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
705 if (FD_ISSET (urh->mhd.socket,
706 ws))
707 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
708}
709
710
711/**
639 * Obtain the `select()` sets for this daemon. 712 * Obtain the `select()` sets for this daemon.
640 * Daemon's FDs will be added to fd_sets. To get only 713 * Daemon's FDs will be added to fd_sets. To get only
641 * daemon FDs in fd_sets, call FD_ZERO for each fd_set 714 * daemon FDs in fd_sets, call FD_ZERO for each fd_set
@@ -733,29 +806,12 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
733 } 806 }
734 for (urh = daemon->urh_head; NULL != urh; urh = urh->next) 807 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
735 { 808 {
736 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && 809 if (MHD_NO ==
737 (! MHD_add_to_fd_set_ (urh->mhd.socket, 810 urh_to_fdset (urh,
738 read_fd_set, 811 read_fd_set,
739 max_fd, 812 write_fd_set,
740 fd_setsize)) ) 813 max_fd,
741 result = MHD_NO; 814 fd_setsize))
742 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
743 (! MHD_add_to_fd_set_ (urh->mhd.socket,
744 write_fd_set,
745 max_fd,
746 fd_setsize)) )
747 result = MHD_NO;
748 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
749 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
750 read_fd_set,
751 max_fd,
752 fd_setsize)) )
753 result = MHD_NO;
754 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
755 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
756 write_fd_set,
757 max_fd,
758 fd_setsize)) )
759 result = MHD_NO; 815 result = MHD_NO;
760 } 816 }
761#if DEBUG_CONNECT 817#if DEBUG_CONNECT
@@ -825,6 +881,251 @@ call_handlers (struct MHD_Connection *con,
825} 881}
826 882
827 883
884#if HTTPS_SUPPORT
885/**
886 * Performs bi-directional forwarding on upgraded HTTPS connections
887 * based on the readyness state stored in the @a urh handle.
888 *
889 * @param urh handle to process
890 */
891static void
892process_urh (struct MHD_UpgradeResponseHandle *urh)
893{
894 /* handle reading from TLS client and writing to application */
895 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
896 (urh->in_buffer_off < urh->in_buffer_size) )
897 {
898 ssize_t res;
899
900 res = gnutls_record_recv (urh->connection->tls_session,
901 &urh->in_buffer[urh->in_buffer_off],
902 urh->in_buffer_size - urh->in_buffer_off);
903 if ( (GNUTLS_E_AGAIN == res) ||
904 (GNUTLS_E_INTERRUPTED == res) )
905 {
906 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
907 }
908 else if (res > 0)
909 {
910 urh->in_buffer_off += res;
911 }
912 }
913 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
914 (urh->in_buffer_off > 0) )
915 {
916 size_t res;
917
918 res = write (urh->mhd.socket,
919 urh->in_buffer,
920 urh->in_buffer_off);
921 if (-1 == res)
922 {
923 /* FIXME: differenciate by errno? */
924 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
925 }
926 else
927 {
928 if (urh->in_buffer_off != res)
929 {
930 memmove (urh->in_buffer,
931 &urh->in_buffer[res],
932 urh->in_buffer_off - res);
933 urh->in_buffer_off -= res;
934 }
935 else
936 {
937 urh->in_buffer_off = 0;
938 }
939 }
940 }
941
942 /* handle reading from application and writing to HTTPS client */
943 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
944 (urh->out_buffer_off < urh->out_buffer_size) )
945 {
946 size_t res;
947
948 res = read (urh->mhd.socket,
949 &urh->out_buffer[urh->out_buffer_off],
950 urh->out_buffer_size - urh->out_buffer_off);
951 if (-1 == res)
952 {
953 /* FIXME: differenciate by errno? */
954 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
955 }
956 else
957 {
958 urh->out_buffer_off += res;
959 }
960 }
961 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
962 (urh->out_buffer_off > 0) )
963 {
964 ssize_t res;
965
966 res = gnutls_record_send (urh->connection->tls_session,
967 urh->out_buffer,
968 urh->out_buffer_off);
969 if ( (GNUTLS_E_AGAIN == res) ||
970 (GNUTLS_E_INTERRUPTED == res) )
971 {
972 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
973 }
974 else if (res > 0)
975 {
976 if (urh->out_buffer_off != res)
977 {
978 memmove (urh->out_buffer,
979 &urh->out_buffer[res],
980 urh->out_buffer_off - res);
981 urh->out_buffer_off -= res;
982 }
983 else
984 {
985 urh->out_buffer_off = 0;
986 }
987 }
988 }
989}
990#endif
991
992
993/**
994 * Main function of the thread that handles an individual connection
995 * after it was "upgraded" when #MHD_USE_THREAD_PER_CONNECTION is set.
996 *
997 * @param con the connection this thread will handle
998 */
999static void
1000thread_main_connection_upgrade (struct MHD_Connection *con)
1001{
1002 struct MHD_Daemon *daemon = con->daemon;
1003
1004 if (0 == (daemon->options & MHD_USE_SSL))
1005 {
1006 /* Here, we need to block until the application
1007 signals us that it is done with the socket */
1008 MHD_semaphore_down (con->upgrade_sem);
1009 MHD_semaphore_destroy (con->upgrade_sem);
1010 con->upgrade_sem = NULL;
1011 return;
1012 }
1013#if HTTPS_SUPPORT
1014 {
1015 struct MHD_UpgradeResponseHandle *urh = con->urh;
1016
1017 /* Here, we need to bi-directionally forward
1018 until the application tells us that it is done
1019 with the socket; */
1020 if (0 == (daemon->options & MHD_USE_POLL))
1021 {
1022 while (MHD_CONNECTION_UPGRADE == con->state)
1023 {
1024 /* use select */
1025 fd_set rs;
1026 fd_set ws;
1027 MHD_socket max_fd;
1028 int num_ready;
1029 int result;
1030
1031 FD_ZERO (&rs);
1032 FD_ZERO (&ws);
1033 max_fd = MHD_INVALID_SOCKET;
1034 result = urh_to_fdset (urh,
1035 &rs,
1036 &ws,
1037 &max_fd,
1038 FD_SETSIZE);
1039 if (MHD_NO == result)
1040 {
1041#ifdef HAVE_MESSAGES
1042 MHD_DLOG (con->daemon,
1043 "Error preparing select\n");
1044#endif
1045 break;
1046 }
1047 num_ready = MHD_SYS_select_ (max_fd + 1,
1048 &rs,
1049 &ws,
1050 NULL,
1051 NULL);
1052 if (num_ready < 0)
1053 {
1054 const int err = MHD_socket_get_error_();
1055
1056 if (MHD_SCKT_ERR_IS_EINTR_(err))
1057 continue;
1058#ifdef HAVE_MESSAGES
1059 MHD_DLOG (con->daemon,
1060 "Error during select (%d): `%s'\n",
1061 err,
1062 MHD_socket_strerr_ (err));
1063#endif
1064 break;
1065 }
1066 urh_from_fdset (urh,
1067 &rs,
1068 &ws);
1069 process_urh (urh);
1070 }
1071 }
1072#ifdef HAVE_POLL
1073 else
1074 {
1075 /* use poll() */
1076 struct pollfd p[2];
1077 const unsigned int timeout = UINT_MAX;
1078
1079 p[0].fd = urh->connection->socket_fd;
1080 p[1].fd = urh->mhd.socket;
1081 while (MHD_CONNECTION_UPGRADE == con->state)
1082 {
1083 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->app.celi))
1084 p[0].events |= POLLIN;
1085 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
1086 p[0].events |= POLLOUT;
1087 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi))
1088 p[1].events |= POLLIN;
1089 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
1090 p[1].events |= POLLOUT;
1091
1092 if (MHD_sys_poll_ (p,
1093 2,
1094 timeout) < 0)
1095 {
1096 const int err = MHD_socket_get_error_ ();
1097
1098 if (MHD_SCKT_ERR_IS_EINTR_ (err))
1099 continue;
1100#ifdef HAVE_MESSAGES
1101 MHD_DLOG (con->daemon,
1102 "Error during poll: `%s'\n",
1103 MHD_socket_strerr_ (err));
1104#endif
1105 break;
1106 }
1107 if (0 != (p[0].revents & POLLIN))
1108 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1109 if (0 != (p[0].revents & POLLOUT))
1110 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
1111 if (0 != (p[1].revents & POLLIN))
1112 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1113 if (0 != (p[1].revents & POLLOUT))
1114 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
1115 process_urh (urh);
1116 }
1117 }
1118 /* end POLL */
1119#endif
1120 /* end HTTPS */
1121#else
1122 /* HTTPS option set, but compiled without HTTPS */
1123 MHD_PANIC ("This should not be possible\n");
1124#endif
1125 }
1126}
1127
1128
828/** 1129/**
829 * Main function of the thread that handles an individual 1130 * Main function of the thread that handles an individual
830 * connection when #MHD_USE_THREAD_PER_CONNECTION is set. 1131 * connection when #MHD_USE_THREAD_PER_CONNECTION is set.
@@ -836,6 +1137,7 @@ static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
836thread_main_handle_connection (void *data) 1137thread_main_handle_connection (void *data)
837{ 1138{
838 struct MHD_Connection *con = data; 1139 struct MHD_Connection *con = data;
1140 struct MHD_Daemon *daemon = con->daemon;
839 int num_ready; 1141 int num_ready;
840 fd_set rs; 1142 fd_set rs;
841 fd_set ws; 1143 fd_set ws;
@@ -844,7 +1146,7 @@ thread_main_handle_connection (void *data)
844 struct timeval *tvp; 1146 struct timeval *tvp;
845 time_t now; 1147 time_t now;
846#if WINDOWS 1148#if WINDOWS
847 MHD_pipe spipe = con->daemon->wpipe[0]; 1149 MHD_pipe spipe = daemon->wpipe[0];
848#ifdef HAVE_POLL 1150#ifdef HAVE_POLL
849 int extra_slot; 1151 int extra_slot;
850#endif /* HAVE_POLL */ 1152#endif /* HAVE_POLL */
@@ -855,11 +1157,13 @@ thread_main_handle_connection (void *data)
855#ifdef HAVE_POLL 1157#ifdef HAVE_POLL
856 struct pollfd p[1 + EXTRA_SLOTS]; 1158 struct pollfd p[1 + EXTRA_SLOTS];
857#endif 1159#endif
1160#undef EXTRA_SLOTS
858 1161
859 while ( (MHD_YES != con->daemon->shutdown) && 1162 while ( (MHD_YES != daemon->shutdown) &&
860 (MHD_CONNECTION_CLOSED != con->state) ) 1163 (MHD_CONNECTION_CLOSED != con->state) )
861 { 1164 {
862 unsigned const int timeout = con->daemon->connection_timeout; 1165 const unsigned int timeout = daemon->connection_timeout;
1166
863 tvp = NULL; 1167 tvp = NULL;
864#if HTTPS_SUPPORT 1168#if HTTPS_SUPPORT
865 if (MHD_YES == con->tls_read_ready) 1169 if (MHD_YES == con->tls_read_ready)
@@ -870,7 +1174,8 @@ thread_main_handle_connection (void *data)
870 tvp = &tv; 1174 tvp = &tv;
871 } 1175 }
872#endif 1176#endif
873 if (NULL == tvp && timeout > 0) 1177 if ( (NULL == tvp) &&
1178 (timeout > 0) )
874 { 1179 {
875 now = MHD_monotonic_sec_counter(); 1180 now = MHD_monotonic_sec_counter();
876 if (now - con->last_activity > timeout) 1181 if (now - con->last_activity > timeout)
@@ -884,35 +1189,48 @@ thread_main_handle_connection (void *data)
884 if (seconds_left > TIMEVAL_TV_SEC_MAX) 1189 if (seconds_left > TIMEVAL_TV_SEC_MAX)
885 tv.tv_sec = TIMEVAL_TV_SEC_MAX; 1190 tv.tv_sec = TIMEVAL_TV_SEC_MAX;
886 else 1191 else
887 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE)seconds_left; 1192 tv.tv_sec = (_MHD_TIMEVAL_TV_SEC_TYPE) seconds_left;
888#endif /* _WIN32 */ 1193#endif /* _WIN32 */
889 } 1194 }
890 tv.tv_usec = 0; 1195 tv.tv_usec = 0;
891 tvp = &tv; 1196 tvp = &tv;
892 } 1197 }
893 if (0 == (con->daemon->options & MHD_USE_POLL)) 1198 if (0 == (daemon->options & MHD_USE_POLL))
894 { 1199 {
895 /* use select */ 1200 /* use select */
896 int err_state = 0; 1201 int err_state = 0;
1202
897 FD_ZERO (&rs); 1203 FD_ZERO (&rs);
898 FD_ZERO (&ws); 1204 FD_ZERO (&ws);
899 maxsock = MHD_INVALID_SOCKET; 1205 maxsock = MHD_INVALID_SOCKET;
900 switch (con->event_loop_info) 1206 switch (con->event_loop_info)
901 { 1207 {
902 case MHD_EVENT_LOOP_INFO_READ: 1208 case MHD_EVENT_LOOP_INFO_READ:
903 if (!MHD_add_to_fd_set_ (con->socket_fd, &rs, &maxsock, FD_SETSIZE)) 1209 if (! MHD_add_to_fd_set_ (con->socket_fd,
1210 &rs,
1211 &maxsock,
1212 FD_SETSIZE))
904 err_state = 1; 1213 err_state = 1;
905 break; 1214 break;
906 case MHD_EVENT_LOOP_INFO_WRITE: 1215 case MHD_EVENT_LOOP_INFO_WRITE:
907 if (!MHD_add_to_fd_set_ (con->socket_fd, &ws, &maxsock, FD_SETSIZE)) 1216 if (! MHD_add_to_fd_set_ (con->socket_fd,
1217 &ws,
1218 &maxsock,
1219 FD_SETSIZE))
908 err_state = 1; 1220 err_state = 1;
909 if ( (con->read_buffer_size > con->read_buffer_offset) && 1221 if ( (con->read_buffer_size > con->read_buffer_offset) &&
910 (!MHD_add_to_fd_set_ (con->socket_fd, &rs, &maxsock, FD_SETSIZE)) ) 1222 (! MHD_add_to_fd_set_ (con->socket_fd,
1223 &rs,
1224 &maxsock,
1225 FD_SETSIZE)) )
911 err_state = 1; 1226 err_state = 1;
912 break; 1227 break;
913 case MHD_EVENT_LOOP_INFO_BLOCK: 1228 case MHD_EVENT_LOOP_INFO_BLOCK:
914 if ( (con->read_buffer_size > con->read_buffer_offset) && 1229 if ( (con->read_buffer_size > con->read_buffer_offset) &&
915 (!MHD_add_to_fd_set_ (con->socket_fd, &rs, &maxsock, FD_SETSIZE)) ) 1230 (! MHD_add_to_fd_set_ (con->socket_fd,
1231 &rs,
1232 &maxsock,
1233 FD_SETSIZE)) )
916 err_state = 1; 1234 err_state = 1;
917 tv.tv_sec = 0; 1235 tv.tv_sec = 0;
918 tv.tv_usec = 0; 1236 tv.tv_usec = 0;
@@ -925,7 +1243,10 @@ thread_main_handle_connection (void *data)
925#if WINDOWS 1243#if WINDOWS
926 if (MHD_INVALID_PIPE_ != spipe) 1244 if (MHD_INVALID_PIPE_ != spipe)
927 { 1245 {
928 if (!MHD_add_to_fd_set_ (spipe, &rs, &maxsock, FD_SETSIZE)) 1246 if (! MHD_add_to_fd_set_ (spipe,
1247 &rs,
1248 &maxsock,
1249 FD_SETSIZE))
929 err_state = 1; 1250 err_state = 1;
930 } 1251 }
931#endif 1252#endif
@@ -938,10 +1259,15 @@ thread_main_handle_connection (void *data)
938 goto exit; 1259 goto exit;
939 } 1260 }
940 1261
941 num_ready = MHD_SYS_select_ (maxsock + 1, &rs, &ws, NULL, tvp); 1262 num_ready = MHD_SYS_select_ (maxsock + 1,
1263 &rs,
1264 &ws,
1265 NULL,
1266 tvp);
942 if (num_ready < 0) 1267 if (num_ready < 0)
943 { 1268 {
944 const int err = MHD_socket_get_error_(); 1269 const int err = MHD_socket_get_error_();
1270
945 if (MHD_SCKT_ERR_IS_EINTR_(err)) 1271 if (MHD_SCKT_ERR_IS_EINTR_(err))
946 continue; 1272 continue;
947#ifdef HAVE_MESSAGES 1273#ifdef HAVE_MESSAGES
@@ -960,8 +1286,10 @@ thread_main_handle_connection (void *data)
960#endif 1286#endif
961 if (MHD_NO == 1287 if (MHD_NO ==
962 call_handlers (con, 1288 call_handlers (con,
963 FD_ISSET (con->socket_fd, &rs), 1289 FD_ISSET (con->socket_fd,
964 FD_ISSET (con->socket_fd, &ws), 1290 &rs),
1291 FD_ISSET (con->socket_fd,
1292 &ws),
965 MHD_NO)) 1293 MHD_NO))
966 goto exit; 1294 goto exit;
967 } 1295 }
@@ -969,7 +1297,9 @@ thread_main_handle_connection (void *data)
969 else 1297 else
970 { 1298 {
971 /* use poll */ 1299 /* use poll */
972 memset (&p, 0, sizeof (p)); 1300 memset (&p,
1301 0,
1302 sizeof (p));
973 p[0].fd = con->socket_fd; 1303 p[0].fd = con->socket_fd;
974 switch (con->event_loop_info) 1304 switch (con->event_loop_info)
975 { 1305 {
@@ -1004,11 +1334,11 @@ thread_main_handle_connection (void *data)
1004#endif 1334#endif
1005 if (MHD_sys_poll_ (p, 1335 if (MHD_sys_poll_ (p,
1006#if WINDOWS 1336#if WINDOWS
1007 1 + extra_slot, 1337 1 + extra_slot,
1008#else 1338#else
1009 1, 1339 1,
1010#endif 1340#endif
1011 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0) 1341 (NULL == tvp) ? -1 : tv.tv_sec * 1000) < 0)
1012 { 1342 {
1013 if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_)) 1343 if (MHD_SCKT_LAST_ERR_IS_(MHD_SCKT_EINTR_))
1014 continue; 1344 continue;
@@ -1033,6 +1363,11 @@ thread_main_handle_connection (void *data)
1033 goto exit; 1363 goto exit;
1034 } 1364 }
1035#endif 1365#endif
1366 if (MHD_CONNECTION_UPGRADE == con->state)
1367 {
1368 thread_main_connection_upgrade (con);
1369 break;
1370 }
1036 } 1371 }
1037 if (MHD_CONNECTION_IN_CLEANUP != con->state) 1372 if (MHD_CONNECTION_IN_CLEANUP != con->state)
1038 { 1373 {
@@ -1054,14 +1389,15 @@ exit:
1054 con->response = NULL; 1389 con->response = NULL;
1055 } 1390 }
1056 1391
1057 if (NULL != con->daemon->notify_connection) 1392 if (NULL != daemon->notify_connection)
1058 con->daemon->notify_connection (con->daemon->notify_connection_cls, 1393 con->daemon->notify_connection (daemon->notify_connection_cls,
1059 con, 1394 con,
1060 &con->socket_context, 1395 &con->socket_context,
1061 MHD_CONNECTION_NOTIFY_CLOSED); 1396 MHD_CONNECTION_NOTIFY_CLOSED);
1062 if (MHD_INVALID_SOCKET != con->socket_fd) 1397 if (MHD_INVALID_SOCKET != con->socket_fd)
1063 { 1398 {
1064 shutdown (con->socket_fd, SHUT_WR); 1399 shutdown (con->socket_fd,
1400 SHUT_WR);
1065 if (0 != MHD_socket_close_ (con->socket_fd)) 1401 if (0 != MHD_socket_close_ (con->socket_fd))
1066 MHD_PANIC ("close failed\n"); 1402 MHD_PANIC ("close failed\n");
1067 con->socket_fd = MHD_INVALID_SOCKET; 1403 con->socket_fd = MHD_INVALID_SOCKET;
@@ -1433,7 +1769,7 @@ internal_add_connection (struct MHD_Daemon *daemon,
1433 { 1769 {
1434 /* in turbo mode, we assume that non-blocking was already set 1770 /* in turbo mode, we assume that non-blocking was already set
1435 by 'accept4' or whoever calls 'MHD_add_connection' */ 1771 by 'accept4' or whoever calls 'MHD_add_connection' */
1436 if (!MHD_socket_nonblocking_ (connection->socket_fd)) 1772 if (! MHD_socket_nonblocking_ (connection->socket_fd))
1437 { 1773 {
1438#ifdef HAVE_MESSAGES 1774#ifdef HAVE_MESSAGES
1439 MHD_DLOG (connection->daemon, 1775 MHD_DLOG (connection->daemon,
@@ -2168,115 +2504,6 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
2168} 2504}
2169 2505
2170 2506
2171#if HTTPS_SUPPORT
2172/**
2173 * Performs bi-directional forwarding on upgraded HTTPS connections
2174 * based on the readyness state stored in the @a urh handle.
2175 *
2176 * @param urh handle to process
2177 */
2178static void
2179process_urh (struct MHD_UpgradeResponseHandle *urh)
2180{
2181 /* handle reading from TLS client and writing to application */
2182 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) &&
2183 (urh->in_buffer_off < urh->in_buffer_size) )
2184 {
2185 ssize_t res;
2186
2187 res = gnutls_record_recv (urh->connection->tls_session,
2188 &urh->in_buffer[urh->in_buffer_off],
2189 urh->in_buffer_size - urh->in_buffer_off);
2190 if ( (GNUTLS_E_AGAIN == res) ||
2191 (GNUTLS_E_INTERRUPTED == res) )
2192 {
2193 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
2194 }
2195 else if (res > 0)
2196 {
2197 urh->in_buffer_off += res;
2198 }
2199 }
2200 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
2201 (urh->in_buffer_off > 0) )
2202 {
2203 size_t res;
2204
2205 res = write (urh->mhd.socket,
2206 urh->in_buffer,
2207 urh->in_buffer_off);
2208 if (-1 == res)
2209 {
2210 /* FIXME: differenciate by errno? */
2211 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
2212 }
2213 else
2214 {
2215 if (urh->in_buffer_off != res)
2216 {
2217 memmove (urh->in_buffer,
2218 &urh->in_buffer[res],
2219 urh->in_buffer_off - res);
2220 urh->in_buffer_off -= res;
2221 }
2222 else
2223 {
2224 urh->in_buffer_off = 0;
2225 }
2226 }
2227 }
2228
2229 /* handle reading from application and writing to HTTPS client */
2230 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
2231 (urh->out_buffer_off < urh->out_buffer_size) )
2232 {
2233 size_t res;
2234
2235 res = read (urh->mhd.socket,
2236 &urh->out_buffer[urh->out_buffer_off],
2237 urh->out_buffer_size - urh->out_buffer_off);
2238 if (-1 == res)
2239 {
2240 /* FIXME: differenciate by errno? */
2241 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
2242 }
2243 else
2244 {
2245 urh->out_buffer_off += res;
2246 }
2247 }
2248 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
2249 (urh->out_buffer_off > 0) )
2250 {
2251 ssize_t res;
2252
2253 res = gnutls_record_send (urh->connection->tls_session,
2254 urh->out_buffer,
2255 urh->out_buffer_off);
2256 if ( (GNUTLS_E_AGAIN == res) ||
2257 (GNUTLS_E_INTERRUPTED == res) )
2258 {
2259 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
2260 }
2261 else if (res > 0)
2262 {
2263 if (urh->out_buffer_off != res)
2264 {
2265 memmove (urh->out_buffer,
2266 &urh->out_buffer[res],
2267 urh->out_buffer_off - res);
2268 urh->out_buffer_off -= res;
2269 }
2270 else
2271 {
2272 urh->out_buffer_off = 0;
2273 }
2274 }
2275 }
2276}
2277#endif
2278
2279
2280/** 2507/**
2281 * Run webserver operations. This method should be called by clients 2508 * Run webserver operations. This method should be called by clients
2282 * in combination with #MHD_get_fdset if the client-controlled select 2509 * in combination with #MHD_get_fdset if the client-controlled select
@@ -2362,14 +2589,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
2362 for (urh = daemon->urh_head; NULL != urh; urh = urh->next) 2589 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2363 { 2590 {
2364 /* update urh state based on select() output */ 2591 /* update urh state based on select() output */
2365 if (FD_ISSET (urh->connection->socket_fd, read_fd_set)) 2592 urh_from_fdset (urh,
2366 urh->app.celi |= MHD_EPOLL_STATE_READ_READY; 2593 read_fd_set,
2367 if (FD_ISSET (urh->connection->socket_fd, write_fd_set)) 2594 write_fd_set);
2368 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
2369 if (FD_ISSET (urh->mhd.socket, read_fd_set))
2370 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
2371 if (FD_ISSET (urh->mhd.socket, write_fd_set))
2372 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
2373 /* call generic forwarding function for passing data */ 2595 /* call generic forwarding function for passing data */
2374 process_urh (urh); 2596 process_urh (urh);
2375 } 2597 }