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.c145
1 files changed, 111 insertions, 34 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 487575e0..929a76ba 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -653,25 +653,29 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
653 MHD_socket *max_fd, 653 MHD_socket *max_fd,
654 unsigned int fd_setsize) 654 unsigned int fd_setsize)
655{ 655{
656 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && 656 if ( (urh->out_buffer_off < urh->out_buffer_size) &&
657 (MHD_INVALID_SOCKET != urh->mhd.socket) &&
657 (! MHD_add_to_fd_set_ (urh->mhd.socket, 658 (! MHD_add_to_fd_set_ (urh->mhd.socket,
658 rs, 659 rs,
659 max_fd, 660 max_fd,
660 fd_setsize)) ) 661 fd_setsize)) )
661 return MHD_NO; 662 return MHD_NO;
662 if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && 663 if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
664 (MHD_INVALID_SOCKET != urh->mhd.socket) &&
663 (! MHD_add_to_fd_set_ (urh->mhd.socket, 665 (! MHD_add_to_fd_set_ (urh->mhd.socket,
664 ws, 666 ws,
665 max_fd, 667 max_fd,
666 fd_setsize)) ) 668 fd_setsize)) )
667 return MHD_NO; 669 return MHD_NO;
668 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && 670 if ( (urh->in_buffer_off < urh->in_buffer_size) &&
671 (MHD_INVALID_SOCKET != urh->connection->socket_fd) &&
669 (! MHD_add_to_fd_set_ (urh->connection->socket_fd, 672 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
670 rs, 673 rs,
671 max_fd, 674 max_fd,
672 fd_setsize)) ) 675 fd_setsize)) )
673 return MHD_NO; 676 return MHD_NO;
674 if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && 677 if ( (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
678 (MHD_INVALID_SOCKET != urh->connection->socket_fd) &&
675 (! MHD_add_to_fd_set_ (urh->connection->socket_fd, 679 (! MHD_add_to_fd_set_ (urh->connection->socket_fd,
676 ws, 680 ws,
677 max_fd, 681 max_fd,
@@ -966,6 +970,12 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
966 { 970 {
967 urh->in_buffer_off += res; 971 urh->in_buffer_off += res;
968 } 972 }
973 if (0 == res)
974 {
975 /* connection was shut down, signal by shrinking buffer,
976 which will eventually ensure this FD is no longer listed. */
977 urh->in_buffer_size = urh->in_buffer_off;
978 }
969 } 979 }
970 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && 980 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
971 (urh->in_buffer_off > 0) ) 981 (urh->in_buffer_off > 0) )
@@ -977,8 +987,18 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
977 urh->in_buffer_off); 987 urh->in_buffer_off);
978 if (-1 == res) 988 if (-1 == res)
979 { 989 {
980 /* FIXME: differenciate by errno? */ 990 int err = MHD_socket_get_error_ ();
981 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; 991
992 if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) ||
993 (MHD_SCKT_ERR_IS_EAGAIN_ (err)) )
994 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
995 else
996 {
997 /* persistent / unrecoverable error, treat as
998 if connection was shut down */
999 urh->in_buffer_size = 0;
1000 urh->in_buffer_off = 0;
1001 }
982 } 1002 }
983 else 1003 else
984 { 1004 {
@@ -1014,6 +1034,12 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1014 { 1034 {
1015 urh->out_buffer_off += res; 1035 urh->out_buffer_off += res;
1016 } 1036 }
1037 if (0 == res)
1038 {
1039 /* connection was shut down, signal by shrinking buffer,
1040 which will eventually ensure this FD is no longer listed. */
1041 urh->out_buffer_size = urh->out_buffer_off;
1042 }
1017 fin_read = (0 == res); 1043 fin_read = (0 == res);
1018 } 1044 }
1019 else 1045 else
@@ -1045,6 +1071,13 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1045 urh->out_buffer_off = 0; 1071 urh->out_buffer_off = 0;
1046 } 1072 }
1047 } 1073 }
1074 else
1075 {
1076 /* persistent / unrecoverable error, treat as
1077 if connection was shut down */
1078 urh->out_buffer_size = 0;
1079 urh->out_buffer_off = 0;
1080 }
1048 } 1081 }
1049 if ( (fin_read) && 1082 if ( (fin_read) &&
1050 (0 == urh->out_buffer_off) && 1083 (0 == urh->out_buffer_off) &&
@@ -1064,20 +1097,10 @@ static void
1064thread_main_connection_upgrade (struct MHD_Connection *con) 1097thread_main_connection_upgrade (struct MHD_Connection *con)
1065{ 1098{
1066 struct MHD_Daemon *daemon = con->daemon; 1099 struct MHD_Daemon *daemon = con->daemon;
1100 struct MHD_UpgradeResponseHandle *urh = con->urh;
1067 1101
1068 if (0 == (daemon->options & MHD_USE_SSL))
1069 {
1070 /* Here, we need to block until the application
1071 signals us that it is done with the socket */
1072 MHD_semaphore_down (con->upgrade_sem);
1073 MHD_semaphore_destroy (con->upgrade_sem);
1074 con->upgrade_sem = NULL;
1075 return;
1076 }
1077#if HTTPS_SUPPORT 1102#if HTTPS_SUPPORT
1078 { 1103 {
1079 struct MHD_UpgradeResponseHandle *urh = con->urh;
1080
1081 /* Here, we need to bi-directionally forward 1104 /* Here, we need to bi-directionally forward
1082 until the application tells us that it is done 1105 until the application tells us that it is done
1083 with the socket; */ 1106 with the socket; */
@@ -1108,11 +1131,14 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1108#endif 1131#endif
1109 break; 1132 break;
1110 } 1133 }
1111 num_ready = MHD_SYS_select_ (max_fd + 1, 1134 if (MHD_INVALID_SOCKET != max_fd)
1112 &rs, 1135 num_ready = MHD_SYS_select_ (max_fd + 1,
1113 &ws, 1136 &rs,
1114 NULL, 1137 &ws,
1115 NULL); 1138 NULL,
1139 NULL);
1140 else
1141 num_ready = 0;
1116 if (num_ready < 0) 1142 if (num_ready < 0)
1117 { 1143 {
1118 const int err = MHD_socket_get_error_(); 1144 const int err = MHD_socket_get_error_();
@@ -1131,31 +1157,37 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1131 &rs, 1157 &rs,
1132 &ws); 1158 &ws);
1133 process_urh (urh); 1159 process_urh (urh);
1160 if ( (0 == urh->out_buffer_size) &&
1161 (0 == urh->in_buffer_size) )
1162 break; /* connections died, we have no more purpose here */
1134 } 1163 }
1135 } 1164 }
1136#ifdef HAVE_POLL 1165#ifdef HAVE_POLL
1137 else 1166 else
1138 { 1167 {
1139 /* use poll() */ 1168 /* use poll() */
1140 struct pollfd p[2];
1141 const unsigned int timeout = UINT_MAX; 1169 const unsigned int timeout = UINT_MAX;
1142 1170
1143 p[0].fd = urh->connection->socket_fd;
1144 p[1].fd = urh->mhd.socket;
1145 while (MHD_CONNECTION_UPGRADE == con->state) 1171 while (MHD_CONNECTION_UPGRADE == con->state)
1146 { 1172 {
1147 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) 1173 struct pollfd p[2];
1174
1175 memset (p, 0, sizeof (struct pollfd) * 2);
1176 p[0].fd = urh->connection->socket_fd;
1177 p[1].fd = urh->mhd.socket;
1178 if (urh->in_buffer_off < urh->in_buffer_size)
1148 p[0].events |= POLLIN; 1179 p[0].events |= POLLIN;
1149 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) 1180 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
1150 p[0].events |= POLLOUT; 1181 p[0].events |= POLLOUT;
1151 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) 1182 if (urh->out_buffer_off < urh->out_buffer_size)
1152 p[1].events |= POLLIN; 1183 p[1].events |= POLLIN;
1153 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) 1184 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
1154 p[1].events |= POLLOUT; 1185 p[1].events |= POLLOUT;
1155 1186
1156 if (MHD_sys_poll_ (p, 1187 if ( (0 != (p[0].events | p[1].events)) &&
1157 2, 1188 (MHD_sys_poll_ (p,
1158 timeout) < 0) 1189 2,
1190 timeout) < 0) )
1159 { 1191 {
1160 const int err = MHD_socket_get_error_ (); 1192 const int err = MHD_socket_get_error_ ();
1161 1193
@@ -1177,6 +1209,9 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1177 if (0 != (p[1].revents & POLLOUT)) 1209 if (0 != (p[1].revents & POLLOUT))
1178 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY; 1210 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
1179 process_urh (urh); 1211 process_urh (urh);
1212 if ( (0 == urh->out_buffer_size) &&
1213 (0 == urh->in_buffer_size) )
1214 break; /* connections died, we have no more purpose here */
1180 } 1215 }
1181 } 1216 }
1182 /* end POLL */ 1217 /* end POLL */
@@ -1187,6 +1222,13 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1187 MHD_PANIC ("This should not be possible\n"); 1222 MHD_PANIC ("This should not be possible\n");
1188#endif 1223#endif
1189 } 1224 }
1225
1226 /* Here, we need to block until the application
1227 signals us that it is done with the socket */
1228 MHD_semaphore_down (con->upgrade_sem);
1229 MHD_semaphore_destroy (con->upgrade_sem);
1230 con->upgrade_sem = NULL;
1231 free (urh);
1190} 1232}
1191 1233
1192 1234
@@ -2598,6 +2640,7 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
2598 struct MHD_Connection *next; 2640 struct MHD_Connection *next;
2599#if HTTPS_SUPPORT 2641#if HTTPS_SUPPORT
2600 struct MHD_UpgradeResponseHandle *urh; 2642 struct MHD_UpgradeResponseHandle *urh;
2643 struct MHD_UpgradeResponseHandle *urhn;
2601#endif 2644#endif
2602 unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY | 2645 unsigned int mask = MHD_USE_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNALLY |
2603 MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION; 2646 MHD_USE_SELECT_INTERNALLY | MHD_USE_POLL_INTERNALLY | MHD_USE_THREAD_PER_CONNECTION;
@@ -2650,8 +2693,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
2650 2693
2651 /* handle upgraded HTTPS connections */ 2694 /* handle upgraded HTTPS connections */
2652#if HTTPS_SUPPORT 2695#if HTTPS_SUPPORT
2653 for (urh = daemon->urh_head; NULL != urh; urh = urh->next) 2696 for (urh = daemon->urh_head; NULL != urh; urh = urhn)
2654 { 2697 {
2698 urhn = urh->next;
2655 /* update urh state based on select() output */ 2699 /* update urh state based on select() output */
2656 urh_from_fdset (urh, 2700 urh_from_fdset (urh,
2657 read_fd_set, 2701 read_fd_set,
@@ -2934,13 +2978,13 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2934 for (urh = daemon->urh_head; NULL != urh; urh = urh->next) 2978 for (urh = daemon->urh_head; NULL != urh; urh = urh->next)
2935 { 2979 {
2936 p[poll_server+i].fd = urh->connection->socket_fd; 2980 p[poll_server+i].fd = urh->connection->socket_fd;
2937 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) 2981 if (urh->in_buffer_off < urh->in_buffer_size)
2938 p[poll_server+i].events |= POLLIN; 2982 p[poll_server+i].events |= POLLIN;
2939 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) 2983 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi))
2940 p[poll_server+i].events |= POLLOUT; 2984 p[poll_server+i].events |= POLLOUT;
2941 i++; 2985 i++;
2942 p[poll_server+i].fd = urh->mhd.socket; 2986 p[poll_server+i].fd = urh->mhd.socket;
2943 if (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) 2987 if (urh->out_buffer_off < urh->out_buffer_size)
2944 p[poll_server+i].events |= POLLIN; 2988 p[poll_server+i].events |= POLLIN;
2945 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) 2989 if (0 == (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi))
2946 p[poll_server+i].events |= POLLOUT; 2990 p[poll_server+i].events |= POLLOUT;
@@ -2952,7 +2996,9 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2952 free(p); 2996 free(p);
2953 return MHD_YES; 2997 return MHD_YES;
2954 } 2998 }
2955 if (MHD_sys_poll_(p, poll_server + num_connections, timeout) < 0) 2999 if (MHD_sys_poll_(p,
3000 poll_server + num_connections,
3001 timeout) < 0)
2956 { 3002 {
2957 const int err = MHD_socket_get_error_ (); 3003 const int err = MHD_socket_get_error_ ();
2958 if (MHD_SCKT_ERR_IS_EINTR_ (err)) 3004 if (MHD_SCKT_ERR_IS_EINTR_ (err))
@@ -2988,17 +3034,20 @@ MHD_poll_all (struct MHD_Daemon *daemon,
2988 next = pos->next; 3034 next = pos->next;
2989 /* first, sanity checks */ 3035 /* first, sanity checks */
2990 if (i >= num_connections) 3036 if (i >= num_connections)
2991 continue; /* connection list changed somehow, retry later ... */ 3037 break; /* connection list changed somehow, retry later ... */
2992 if (p[poll_server+i].fd != pos->socket_fd) 3038 if (p[poll_server+i].fd != pos->socket_fd)
2993 continue; /* fd mismatch, something else happened, retry later ... */ 3039 continue; /* fd mismatch, something else happened, retry later ... */
2994 call_handlers (pos, 3040 call_handlers (pos,
2995 0 != (p[poll_server+i].revents & POLLIN), 3041 0 != (p[poll_server+i].revents & POLLIN),
2996 0 != (p[poll_server+i].revents & POLLOUT), 3042 0 != (p[poll_server+i].revents & POLLOUT),
2997 MHD_NO); 3043 MHD_NO);
3044 i++;
2998 } 3045 }
2999#if HTTPS_SUPPORT 3046#if HTTPS_SUPPORT
3000 for (urh = daemon->urh_head; NULL != urh; urh = urhn) 3047 for (urh = daemon->urh_head; NULL != urh; urh = urhn)
3001 { 3048 {
3049 if (i >= num_connections)
3050 break; /* connection list changed somehow, retry later ... */
3002 urhn = urh->next; 3051 urhn = urh->next;
3003 if (p[poll_server+i].fd != urh->connection->socket_fd) 3052 if (p[poll_server+i].fd != urh->connection->socket_fd)
3004 continue; /* fd mismatch, something else happened, retry later ... */ 3053 continue; /* fd mismatch, something else happened, retry later ... */
@@ -3148,6 +3197,7 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
3148 struct epoll_event events[MAX_EVENTS]; 3197 struct epoll_event events[MAX_EVENTS];
3149 int num_events; 3198 int num_events;
3150 unsigned int i; 3199 unsigned int i;
3200 unsigned int j;
3151 3201
3152 num_events = MAX_EVENTS; 3202 num_events = MAX_EVENTS;
3153 while (MAX_EVENTS == num_events) 3203 while (MAX_EVENTS == num_events)
@@ -3172,7 +3222,34 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
3172 for (i=0;i<(unsigned int) num_events;i++) 3222 for (i=0;i<(unsigned int) num_events;i++)
3173 { 3223 {
3174 struct UpgradeEpollHandle *ueh = events[i].data.ptr; 3224 struct UpgradeEpollHandle *ueh = events[i].data.ptr;
3175 struct MHD_UpgradeResponseHandle *urh = ueh->urh; 3225 struct MHD_UpgradeResponseHandle *urh;
3226
3227 if (NULL == ueh)
3228 continue; /* was killed, see below */
3229 urh = ueh->urh;
3230
3231 /* In case we get two events for the same upgrade handle,
3232 squash them together (otherwise the first one may
3233 cause us to free the 'urh', and the second one then
3234 causes a use-after-free). */
3235 for (j=i+1;j< (unsigned int) num_events;j++)
3236 {
3237 struct UpgradeEpollHandle *uehj = events[j].data.ptr;
3238 struct MHD_UpgradeResponseHandle *urhj;
3239
3240 if (NULL == uehj)
3241 continue; /* was killed, see below */
3242 urhj = uehj->urh;
3243
3244 if (urh == urhj) /* yep, indeed the same! */
3245 {
3246 if (0 != (events[j].events & EPOLLIN))
3247 uehj->celi |= MHD_EPOLL_STATE_READ_READY;
3248 if (0 != (events[j].events & EPOLLOUT))
3249 uehj->celi |= MHD_EPOLL_STATE_WRITE_READY;
3250 }
3251 events[j].data.ptr = NULL; /* kill this one */
3252 }
3176 3253
3177 /* Update our state based on what is ready according to epoll() */ 3254 /* Update our state based on what is ready according to epoll() */
3178 if (0 != (events[i].events & EPOLLIN)) 3255 if (0 != (events[i].events & EPOLLIN))