aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2017-03-02 22:17:11 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2017-03-13 23:48:17 +0300
commit1855c73cd340ae6273251728e8d6d500b2c1119b (patch)
treeb19ed47f90b98d6313f3859af1d099cfc192c2aa /src/microhttpd/daemon.c
parent8dadd66ddef2d9320b0a60b9bf7881f42b127c93 (diff)
downloadlibmicrohttpd-1855c73cd340ae6273251728e8d6d500b2c1119b.tar.gz
libmicrohttpd-1855c73cd340ae6273251728e8d6d500b2c1119b.zip
Corrected monitor 'upgraded' sockets for errors, corrected handling of error and
streamlined forwarding processing logic. Added some comments.
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c309
1 files changed, 191 insertions, 118 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index bc10c795..b89c3d57 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -698,6 +698,8 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
698 const MHD_socket mhd_sckt = urh->mhd.socket; 698 const MHD_socket mhd_sckt = urh->mhd.socket;
699 bool res = true; 699 bool res = true;
700 700
701 /* Do not add to 'es' only if socket is closed
702 * or not used anymore. */
701 if (MHD_INVALID_SOCKET != conn_sckt) 703 if (MHD_INVALID_SOCKET != conn_sckt)
702 { 704 {
703 if ( (urh->in_buffer_used < urh->in_buffer_size) && 705 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
@@ -712,7 +714,12 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
712 max_fd, 714 max_fd,
713 fd_setsize)) ) 715 fd_setsize)) )
714 res = false; 716 res = false;
715 if (0 != urh->in_buffer_size) 717 /* Do not monitor again for errors if error was detected before as
718 * error state is remembered. */
719 if ((0 == urh->app.celi & MHD_EPOLL_STATE_ERROR) &&
720 ((0 != urh->in_buffer_size) ||
721 (0 != urh->out_buffer_size) ||
722 (0 != urh->out_buffer_used)))
716 MHD_add_to_fd_set_ (conn_sckt, 723 MHD_add_to_fd_set_ (conn_sckt,
717 es, 724 es,
718 max_fd, 725 max_fd,
@@ -732,7 +739,12 @@ urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
732 max_fd, 739 max_fd,
733 fd_setsize)) ) 740 fd_setsize)) )
734 res = false; 741 res = false;
735 if (0 != urh->out_buffer_size) 742 /* Do not monitor again for errors if error was detected before as
743 * error state is remembered. */
744 if ((0 == urh->mhd.celi & MHD_EPOLL_STATE_ERROR) &&
745 ((0 != urh->out_buffer_size) ||
746 (0 != urh->in_buffer_size) ||
747 (0 != urh->in_buffer_used)))
736 MHD_add_to_fd_set_ (mhd_sckt, 748 MHD_add_to_fd_set_ (mhd_sckt,
737 es, 749 es,
738 max_fd, 750 max_fd,
@@ -761,8 +773,9 @@ urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
761 const MHD_socket conn_sckt = urh->connection->socket_fd; 773 const MHD_socket conn_sckt = urh->connection->socket_fd;
762 const MHD_socket mhd_sckt = urh->mhd.socket; 774 const MHD_socket mhd_sckt = urh->mhd.socket;
763 775
764 urh->app.celi = MHD_EPOLL_STATE_UNREADY; 776 /* Reset read/write ready, preserve error state. */
765 urh->mhd.celi = MHD_EPOLL_STATE_UNREADY; 777 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY && ~MHD_EPOLL_STATE_WRITE_READY);
778 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY && ~MHD_EPOLL_STATE_WRITE_READY);
766 779
767 if (MHD_INVALID_SOCKET != conn_sckt) 780 if (MHD_INVALID_SOCKET != conn_sckt)
768 { 781 {
@@ -799,17 +812,31 @@ urh_update_pollfd(struct MHD_UpgradeResponseHandle *urh,
799{ 812{
800 p[0].events = 0; 813 p[0].events = 0;
801 p[1].events = 0; 814 p[1].events = 0;
815
802 if (urh->in_buffer_used < urh->in_buffer_size) 816 if (urh->in_buffer_used < urh->in_buffer_size)
803 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC; 817 p[0].events |= POLLIN;
804 if (0 != urh->out_buffer_used) 818 if (0 != urh->out_buffer_used)
805 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC; 819 p[0].events |= POLLOUT;
806 if (0 != urh->in_buffer_size) 820
821 /* Do not monitor again for errors if error was detected before as
822 * error state is remembered. */
823 if ((0 == urh->app.celi & MHD_EPOLL_STATE_ERROR) &&
824 ((0 != urh->in_buffer_size) ||
825 (0 != urh->out_buffer_size) ||
826 (0 != urh->out_buffer_used)))
807 p[0].events |= MHD_POLL_EVENTS_ERR_DISC; 827 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
828
808 if (urh->out_buffer_used < urh->out_buffer_size) 829 if (urh->out_buffer_used < urh->out_buffer_size)
809 p[1].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC; 830 p[1].events |= POLLIN;
810 if (0 != urh->in_buffer_used) 831 if (0 != urh->in_buffer_used)
811 p[1].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC; 832 p[1].events |= POLLOUT;
812 if (0 != urh->out_buffer_size) 833
834 /* Do not monitor again for errors if error was detected before as
835 * error state is remembered. */
836 if ((0 == urh->mhd.celi & MHD_EPOLL_STATE_ERROR) &&
837 ((0 != urh->out_buffer_size) ||
838 (0 != urh->in_buffer_size) ||
839 (0 != urh->in_buffer_used)))
813 p[1].events |= MHD_POLL_EVENTS_ERR_DISC; 840 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
814} 841}
815 842
@@ -839,18 +866,26 @@ static void
839urh_from_pollfd(struct MHD_UpgradeResponseHandle *urh, 866urh_from_pollfd(struct MHD_UpgradeResponseHandle *urh,
840 struct pollfd p[2]) 867 struct pollfd p[2])
841{ 868{
869 /* Reset read/write ready, preserve error state. */
870 urh->app.celi &= (~MHD_EPOLL_STATE_READ_READY && ~MHD_EPOLL_STATE_WRITE_READY);
871 urh->mhd.celi &= (~MHD_EPOLL_STATE_READ_READY && ~MHD_EPOLL_STATE_WRITE_READY);
872
842 if (0 != (p[0].revents & POLLIN)) 873 if (0 != (p[0].revents & POLLIN))
843 urh->app.celi |= MHD_EPOLL_STATE_READ_READY; 874 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
844 if (0 != (p[0].revents & POLLOUT)) 875 if (0 != (p[0].revents & POLLOUT))
845 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY; 876 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
846 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC)) 877 if (0 != (p[0].revents & POLLHUP))
878 urh->app.celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
879 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERRROR))
847 urh->app.celi |= MHD_EPOLL_STATE_ERROR; 880 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
848 if (0 != (p[1].revents & POLLIN)) 881 if (0 != (p[1].revents & POLLIN))
849 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY; 882 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
850 if (0 != (p[1].revents & POLLOUT)) 883 if (0 != (p[1].revents & POLLOUT))
851 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY; 884 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
852 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERR_DISC)) 885 if (0 != (p[1].revents & POLLHUP))
853 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR; 886 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
887 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERRROR))
888 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
854} 889}
855#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 890#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
856 891
@@ -1165,6 +1200,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1165 * each time. */ 1200 * each time. */
1166 struct MHD_Connection * const connection = urh->connection; 1201 struct MHD_Connection * const connection = urh->connection;
1167 struct MHD_Daemon * const daemon = connection->daemon; 1202 struct MHD_Daemon * const daemon = connection->daemon;
1203 /* Prevent data races. */
1204 bool was_closed;
1168 if (daemon->shutdown) 1205 if (daemon->shutdown)
1169 { 1206 {
1170 /* Daemon shutting down, application will not receive any more data. */ 1207 /* Daemon shutting down, application will not receive any more data. */
@@ -1177,7 +1214,8 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1177#endif 1214#endif
1178 urh->was_closed = true; 1215 urh->was_closed = true;
1179 } 1216 }
1180 if (urh->was_closed) 1217 was_closed = urh->was_closed;
1218 if (was_closed)
1181 { 1219 {
1182 /* Application was closed connections: no more data 1220 /* Application was closed connections: no more data
1183 * can be forwarded to application socket. */ 1221 * can be forwarded to application socket. */
@@ -1191,6 +1229,13 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1191#endif 1229#endif
1192 1230
1193 } 1231 }
1232 /* If application signaled MHD about socket closure then
1233 * check for any pending data even if socket is not marked
1234 * as 'ready' (signal may arrive after poll()/select()).
1235 * Socketpair for forwarding is always in non-blocking mode
1236 * so no risk that recv() will block the thread. */
1237 if (0 != urh->out_buffer_size)
1238 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1194 /* Discard any data received form remote. */ 1239 /* Discard any data received form remote. */
1195 urh->in_buffer_used = 0; 1240 urh->in_buffer_used = 0;
1196 /* Do not try to push data to application. */ 1241 /* Do not try to push data to application. */
@@ -1201,13 +1246,19 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1201 connection->tls_read_ready = false; 1246 connection->tls_read_ready = false;
1202 } 1247 }
1203 1248
1204 /* Some platforms (W32, possibly Darwin) may discard data in system buffers 1249 /* On some platforms (W32, possibly Darwin) failed send() (send() will always
1205 * received by system but unread by recv() if remote side was disconnected 1250 * fail after remote disconnect was detected) may discard data in system
1206 * and failed send() attempted (send() will always fail after remote disconnect 1251 * buffers received by system but not yet read by recv().
1207 * was detected).
1208 * So, before trying send() on any socket, recv() must be performed at first 1252 * So, before trying send() on any socket, recv() must be performed at first
1209 * otherwise last part of incoming data may be lost. */ 1253 * otherwise last part of incoming data may be lost. */
1210 1254
1255 /* If disconnect or error was detected - try to read from socket
1256 * to dry data possibly pending is system buffers. */
1257 if (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi))
1258 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1259 if (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi))
1260 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1261
1211 /* 1262 /*
1212 * handle reading from remote TLS client 1263 * handle reading from remote TLS client
1213 */ 1264 */
@@ -1226,9 +1277,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1226 res = gnutls_record_recv (connection->tls_session, 1277 res = gnutls_record_recv (connection->tls_session,
1227 &urh->in_buffer[urh->in_buffer_used], 1278 &urh->in_buffer[urh->in_buffer_used],
1228 buf_size); 1279 buf_size);
1229 if (GNUTLS_E_AGAIN == res) 1280 if (0 < res)
1230 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1231 else if (res > 0)
1232 { 1281 {
1233 urh->in_buffer_used += res; 1282 urh->in_buffer_used += res;
1234 if (buf_size > (size_t)res) 1283 if (buf_size > (size_t)res)
@@ -1236,26 +1285,34 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1236 else if (0 < gnutls_record_check_pending (connection->tls_session)) 1285 else if (0 < gnutls_record_check_pending (connection->tls_session))
1237 connection->tls_read_ready = true; 1286 connection->tls_read_ready = true;
1238 } 1287 }
1239 else if ( (0 >= res ) && 1288 else /* 0 >= res */
1240 (GNUTLS_E_INTERRUPTED != res) )
1241 { 1289 {
1242 /* Connection was shut down or got unrecoverable error. 1290 if (GNUTLS_E_INTERRUPTED != res)
1243 * Reading from remote client is not required anymore. */ 1291 {
1292 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1293 if (GNUTLS_E_AGAIN != res)
1294 {
1295 /* Unrecoverable error on socket was detected or
1296 * socket was disconnected/shut down. */
1297 /* Stop trying to read from this TLS socket. */
1298 urh->in_buffer_size = 0;
1299 }
1300 }
1301 }
1302 if (MHD_EPOLL_STATE_ERROR ==
1303 ((MHD_EPOLL_STATE_ERROR | MHD_EPOLL_STATE_READ_READY) & urh->app.celi))
1304 {
1305 /* Unrecoverable error on socket was detected and all
1306 * pending data was read from system buffers. */
1307 /* Stop trying to read from this TLS socket. */
1244 urh->in_buffer_size = 0; 1308 urh->in_buffer_size = 0;
1245 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1246 } 1309 }
1247 } 1310 }
1248 1311
1249 /* 1312 /*
1250 * handle reading from application 1313 * handle reading from application
1251 */ 1314 */
1252 /* If application signaled MHD about socket closure then 1315 if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1253 * check for any pending data even if socket is not marked
1254 * as 'ready' (signal may arrive after poll()/select()).
1255 * Socketpair for forwarding is always in non-blocking mode
1256 * so no risk that recv() will block the thread. */
1257 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) ||
1258 (urh->was_closed) ) &&
1259 (urh->out_buffer_used < urh->out_buffer_size) ) 1316 (urh->out_buffer_used < urh->out_buffer_size) )
1260 { 1317 {
1261 ssize_t res; 1318 ssize_t res;
@@ -1268,44 +1325,41 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1268 res = MHD_recv_ (urh->mhd.socket, 1325 res = MHD_recv_ (urh->mhd.socket,
1269 &urh->out_buffer[urh->out_buffer_used], 1326 &urh->out_buffer[urh->out_buffer_used],
1270 buf_size); 1327 buf_size);
1271 if (0 > res) 1328 if (0 < res)
1329 {
1330 urh->out_buffer_used += res;
1331 if (buf_size > (size_t)res)
1332 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1333 }
1334 else /* 0 >= res */
1272 { 1335 {
1273 if (urh->was_closed) 1336 const int err = MHD_socket_get_error_ ();
1337 if ((0 == res) ||
1338 ((! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1339 (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err))))
1274 { 1340 {
1275 /* All data was received and application will not
1276 * forward any more data. */
1277 /* Do not try to pull data from application. */
1278 urh->out_buffer_size = 0;
1279 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; 1341 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1280 } 1342 if ((0 == res) ||
1281 else 1343 (was_closed) ||
1282 { 1344 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1283 const int err = MHD_socket_get_error_ (); 1345 (! MHD_SCKT_ERR_IS_EAGAIN_ (err)))
1284 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
1285 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1286 else if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1287 (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
1288 { 1346 {
1289 /* persistent / unrecoverable error, treat as 1347 /* Socket disconnect/shutdown was detected;
1290 if connection was shut down */ 1348 * Application signaled about closure of 'upgraded' socket;
1291 /* Do not try to pull data from application. */ 1349 * or persistent / unrecoverable error. */
1350 /* Do not try to pull more data from application. */
1292 urh->out_buffer_size = 0; 1351 urh->out_buffer_size = 0;
1293 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1294 } 1352 }
1295 } 1353 }
1296 } 1354 }
1297 else 1355 if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) &&
1298 { 1356 ( (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) ||
1299 urh->out_buffer_used += res; 1357 (was_closed) ) )
1300 if (buf_size > (size_t)res)
1301 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1302 }
1303 if (0 == res)
1304 { 1358 {
1305 /* Connection was shut down or got unrecoverable error. 1359 /* Unrecoverable error on socket was detected and all
1306 Do not try to pull data from application. */ 1360 * pending data was read from system buffers. */
1361 /* Do not try to pull more data from application. */
1307 urh->out_buffer_size = 0; 1362 urh->out_buffer_size = 0;
1308 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1309 } 1363 }
1310 } 1364 }
1311 1365
@@ -1325,40 +1379,49 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1325 res = gnutls_record_send (connection->tls_session, 1379 res = gnutls_record_send (connection->tls_session,
1326 urh->out_buffer, 1380 urh->out_buffer,
1327 data_size); 1381 data_size);
1328 if (GNUTLS_E_AGAIN == res) 1382 if (0 < res)
1329 { 1383 {
1330 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY; 1384 const size_t next_out_buffer_used = urh->out_buffer_used - res;
1331 } 1385 if (0 != next_out_buffer_used)
1332 else if (res > 0)
1333 {
1334 if (urh->out_buffer_used != res)
1335 { 1386 {
1336 memmove (urh->out_buffer, 1387 memmove (urh->out_buffer,
1337 &urh->out_buffer[res], 1388 &urh->out_buffer[res],
1338 urh->out_buffer_used - res); 1389 next_out_buffer_used);
1339 urh->out_buffer_used -= res;
1340 if (data_size > (size_t)res) 1390 if (data_size > (size_t)res)
1341 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY; 1391 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1342 } 1392 }
1343 else 1393 urh->out_buffer_used = next_out_buffer_used;
1394 }
1395 else /* 0 >= res */
1396 {
1397 if (GNUTLS_E_INTERRUPTED != res)
1344 { 1398 {
1345 urh->out_buffer_used = 0; 1399 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1400 if (GNUTLS_E_INTERRUPTED != res)
1401 {
1402 /* TLS connection shut down or
1403 * persistent / unrecoverable error. */
1404#ifdef HAVE_MESSAGES
1405 MHD_DLOG (daemon,
1406 _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1407 " bytes of data received from application: %s\n"),
1408 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1409 gnutls_strerror(res));
1410#endif
1411 /* Discard any data unsent to remote. */
1412 urh->out_buffer_used = 0;
1413 /* Do not try to pull more data from application. */
1414 urh->out_buffer_size = 0;
1415 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1416 }
1346 } 1417 }
1347 } 1418 }
1348 else if (GNUTLS_E_INTERRUPTED != res) 1419 if ( (0 == urh->out_buffer_used) &&
1420 (0 != (MHD_EPOLL_STATE_ERROR & urh->app.celi)) )
1349 { 1421 {
1350 /* persistent / unrecoverable error, treat as 1422 /* Unrecoverable error on socket was detected and all
1351 if connection was shut down. */ 1423 * pending data was sent to remote. */
1352#ifdef HAVE_MESSAGES 1424 /* Do not try to send to remote anymore. */
1353 MHD_DLOG (daemon,
1354 _("Failed to forward to remote client " MHD_UNSIGNED_LONG_LONG_PRINTF \
1355 " bytes of data received from application: %s\n"),
1356 (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
1357 gnutls_strerror(res));
1358#endif
1359 /* Discard any data unsent to remote. */
1360 urh->out_buffer_used = 0;
1361 /* Do not try to sent to remote anymore. */
1362 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY; 1425 urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1363 /* Do not try to pull more data from application. */ 1426 /* Do not try to pull more data from application. */
1364 urh->out_buffer_size = 0; 1427 urh->out_buffer_size = 0;
@@ -1370,7 +1433,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1370 * handle writing to application 1433 * handle writing to application
1371 */ 1434 */
1372 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) && 1435 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1373 (urh->in_buffer_used > 0) ) 1436 (urh->in_buffer_used > 0) )
1374 { 1437 {
1375 ssize_t res; 1438 ssize_t res;
1376 size_t data_size; 1439 size_t data_size;
@@ -1382,50 +1445,56 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1382 res = MHD_send_ (urh->mhd.socket, 1445 res = MHD_send_ (urh->mhd.socket,
1383 urh->in_buffer, 1446 urh->in_buffer,
1384 data_size); 1447 data_size);
1385 if (0 > res) 1448 if (0 < res)
1386 { 1449 {
1387 int err = MHD_socket_get_error_ (); 1450 const size_t next_in_buffer_used = urh->in_buffer_used - res;
1388 1451 if (0 != next_in_buffer_used)
1389 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
1390 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1391 else if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1392 (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
1393 {
1394 /* persistent / unrecoverable error, treat as
1395 if connection was shut down. */
1396#ifdef HAVE_MESSAGES
1397 MHD_DLOG (daemon,
1398 _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1399 " bytes of data received from remote side: %s\n"),
1400 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1401 MHD_socket_strerr_ (err));
1402#endif
1403 /* Discard any data received form remote. */
1404 urh->in_buffer_used = 0;
1405 /* Do not try to push data to application. */
1406 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1407 /* Reading from remote client is not required anymore. */
1408 urh->in_buffer_size = 0;
1409 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1410 connection->tls_read_ready = false;
1411 }
1412 }
1413 else
1414 {
1415 if (urh->in_buffer_used != res)
1416 { 1452 {
1417 memmove (urh->in_buffer, 1453 memmove (urh->in_buffer,
1418 &urh->in_buffer[res], 1454 &urh->in_buffer[res],
1419 urh->in_buffer_used - res); 1455 next_in_buffer_used);
1420 urh->in_buffer_used -= res;
1421 if (data_size > (size_t)res) 1456 if (data_size > (size_t)res)
1422 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY; 1457 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1423 } 1458 }
1424 else 1459 urh->in_buffer_used = next_in_buffer_used;
1460 }
1461 else /* 0 >= res */
1462 {
1463 const int err = MHD_socket_get_error_ ();
1464 if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1465 (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
1425 { 1466 {
1426 urh->in_buffer_used = 0; 1467 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1468 if (! MHD_SCKT_ERR_IS_EAGAIN_ (err))
1469 {
1470 /* Socketpair connection shut down or
1471 * persistent / unrecoverable error. */
1472#ifdef HAVE_MESSAGES
1473 MHD_DLOG (daemon,
1474 _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1475 " bytes of data received from remote side: %s\n"),
1476 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1477 MHD_socket_strerr_ (err));
1478#endif
1479 /* Discard any data received form remote. */
1480 urh->in_buffer_used = 0;
1481 /* Reading from remote client is not required anymore. */
1482 urh->in_buffer_size = 0;
1483 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1484 connection->tls_read_ready = false;
1485 }
1427 } 1486 }
1428 } 1487 }
1488 if ( (0 !=urh->in_buffer_used) &&
1489 (0 != (MHD_EPOLL_STATE_ERROR & urh->mhd.celi)) )
1490 {
1491 /* Do not try to push data to application. */
1492 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1493 /* Reading from remote client is not required anymore. */
1494 urh->in_buffer_size = 0;
1495 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1496 connection->tls_read_ready = false;
1497 }
1429 } 1498 }
1430 1499
1431 /* Check whether data is present in TLS buffers 1500 /* Check whether data is present in TLS buffers
@@ -3835,6 +3904,10 @@ run_epoll_for_upgrade (struct MHD_Daemon *daemon)
3835 ueh->celi |= MHD_EPOLL_STATE_READ_READY; 3904 ueh->celi |= MHD_EPOLL_STATE_READ_READY;
3836 if (0 != (events[i].events & EPOLLOUT)) 3905 if (0 != (events[i].events & EPOLLOUT))
3837 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY; 3906 ueh->celi |= MHD_EPOLL_STATE_WRITE_READY;
3907 if (0 != (events[i].events & EPOLLHUP))
3908 ueh->celi |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY;
3909 if (0 != (events[i].events & (EPOLLERR | EPOLLPRI)))
3910 ueh->celi |= MHD_EPOLL_STATE_ERROR;
3838 3911
3839 process_urh (urh); 3912 process_urh (urh);
3840 /* Finished forwarding? */ 3913 /* Finished forwarding? */