diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 72cf476f..b61b3b99 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -1003,7 +1003,16 @@ MHD_cleanup_upgraded_connection_ (struct MHD_Connection *connection) | |||
1003 | static void | 1003 | static void |
1004 | process_urh (struct MHD_UpgradeResponseHandle *urh) | 1004 | process_urh (struct MHD_UpgradeResponseHandle *urh) |
1005 | { | 1005 | { |
1006 | int fin_read; | 1006 | if (MHD_NO != urh->was_closed) |
1007 | { | ||
1008 | /* Application was closed connections: no more data | ||
1009 | * can be forwarded to application socket. */ | ||
1010 | urh->in_buffer_size = 0; | ||
1011 | urh->in_buffer_off = 0; | ||
1012 | urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; | ||
1013 | /* Reading from remote client is not required anymore. */ | ||
1014 | urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY; | ||
1015 | } | ||
1007 | 1016 | ||
1008 | /* handle reading from TLS client and writing to application */ | 1017 | /* handle reading from TLS client and writing to application */ |
1009 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && | 1018 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) && |
@@ -1086,9 +1095,15 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
1086 | } | 1095 | } |
1087 | 1096 | ||
1088 | /* handle reading from application and writing to HTTPS client */ | 1097 | /* handle reading from application and writing to HTTPS client */ |
1089 | if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) && | 1098 | if ( ((0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) || |
1099 | (MHD_NO != urh->was_closed)) && | ||
1090 | (urh->out_buffer_off < urh->out_buffer_size) ) | 1100 | (urh->out_buffer_off < urh->out_buffer_size) ) |
1091 | { | 1101 | { |
1102 | /* If application signaled MHD about socket closure then | ||
1103 | * check for any pending data even if socket is not marked | ||
1104 | * as 'ready' (signal may arrive after poll()/select()). | ||
1105 | * Socketpair for forwarding is always in non-blocking mode | ||
1106 | * so no risk that recv() will block the thread. */ | ||
1092 | ssize_t res; | 1107 | ssize_t res; |
1093 | size_t buf_size; | 1108 | size_t buf_size; |
1094 | 1109 | ||
@@ -1101,18 +1116,27 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
1101 | buf_size); | 1116 | buf_size); |
1102 | if (-1 == res) | 1117 | if (-1 == res) |
1103 | { | 1118 | { |
1104 | int err = MHD_socket_get_error_ (); | 1119 | if (MHD_NO != urh->was_closed) |
1105 | |||
1106 | if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) || | ||
1107 | (MHD_SCKT_ERR_IS_EAGAIN_ (err)) ) | ||
1108 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; | ||
1109 | else if (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) | ||
1110 | { | 1120 | { |
1111 | /* persistent / unrecoverable error, treat as | 1121 | /* Connection was shuted down or all data received and |
1112 | if connection was shut down */ | 1122 | * application will not forward any more data. */ |
1113 | urh->out_buffer_size = 0; | 1123 | urh->out_buffer_size = 0; |
1114 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; | 1124 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; |
1115 | } | 1125 | } |
1126 | else | ||
1127 | { | ||
1128 | const int err = MHD_socket_get_error_ (); | ||
1129 | if ( (MHD_SCKT_ERR_IS_EINTR_ (err)) || | ||
1130 | (MHD_SCKT_ERR_IS_EAGAIN_ (err)) ) | ||
1131 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; | ||
1132 | else if (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) | ||
1133 | { | ||
1134 | /* persistent / unrecoverable error, treat as | ||
1135 | if connection was shut down */ | ||
1136 | urh->out_buffer_size = 0; | ||
1137 | urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; | ||
1138 | } | ||
1139 | } | ||
1116 | } | 1140 | } |
1117 | else | 1141 | else |
1118 | { | 1142 | { |
@@ -1126,10 +1150,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
1126 | urh->out_buffer_size = 0; | 1150 | urh->out_buffer_size = 0; |
1127 | urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; | 1151 | urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; |
1128 | } | 1152 | } |
1129 | fin_read = (0 == res); | ||
1130 | } | 1153 | } |
1131 | else | ||
1132 | fin_read = 0; | ||
1133 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && | 1154 | if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && |
1134 | (urh->out_buffer_off > 0) ) | 1155 | (urh->out_buffer_off > 0) ) |
1135 | { | 1156 | { |
@@ -1175,9 +1196,9 @@ process_urh (struct MHD_UpgradeResponseHandle *urh) | |||
1175 | } | 1196 | } |
1176 | } | 1197 | } |
1177 | /* cleanup connection if it was closed and all data was sent */ | 1198 | /* cleanup connection if it was closed and all data was sent */ |
1178 | if ( (MHD_YES == urh->was_closed) && | 1199 | if ( (MHD_NO != urh->was_closed) && |
1179 | (0 == urh->out_buffer_off) && | 1200 | (0 == urh->out_buffer_size) && |
1180 | (MHD_YES == fin_read) ) | 1201 | (0 == urh->out_buffer_off) ) |
1181 | { | 1202 | { |
1182 | MHD_cleanup_upgraded_connection_ (urh->connection); | 1203 | MHD_cleanup_upgraded_connection_ (urh->connection); |
1183 | } | 1204 | } |