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.c140
1 files changed, 79 insertions, 61 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0049b562..f25ccd4d 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1201,7 +1201,16 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1201 connection->tls_read_ready = false; 1201 connection->tls_read_ready = false;
1202 } 1202 }
1203 1203
1204 /* handle reading from TLS client and writing to application */ 1204 /* Some platforms (W32, possibly Darwin) may discard data in system buffers
1205 * received by system but unread by recv() if remote side was disconnected
1206 * and failed send() attempted (send() will always fail after remote disconnect
1207 * was detected).
1208 * So, before trying send() on any socket, recv() must be performed at first
1209 * otherwise last part of incoming data may be lost. */
1210
1211 /*
1212 * handle reading from remote TLS client
1213 */
1205 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) || 1214 if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
1206 (connection->tls_read_ready) ) && 1215 (connection->tls_read_ready) ) &&
1207 (urh->in_buffer_used < urh->in_buffer_size) ) 1216 (urh->in_buffer_used < urh->in_buffer_size) )
@@ -1236,67 +1245,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1236 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY; 1245 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1237 } 1246 }
1238 } 1247 }
1239 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1240 (urh->in_buffer_used > 0) )
1241 {
1242 ssize_t res;
1243 size_t data_size;
1244
1245 data_size = urh->in_buffer_used;
1246 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1247 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1248
1249 res = MHD_send_ (urh->mhd.socket,
1250 urh->in_buffer,
1251 data_size);
1252 if (0 > res)
1253 {
1254 int err = MHD_socket_get_error_ ();
1255
1256 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
1257 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1258 else if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
1259 (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
1260 {
1261 /* persistent / unrecoverable error, treat as
1262 if connection was shut down. */
1263#ifdef HAVE_MESSAGES
1264 MHD_DLOG (daemon,
1265 _("Failed to forward to application " MHD_UNSIGNED_LONG_LONG_PRINTF \
1266 " bytes of data received from remote side: %s\n"),
1267 (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
1268 MHD_socket_strerr_ (err));
1269#endif
1270 /* Discard any data received form remote. */
1271 urh->in_buffer_used = 0;
1272 /* Do not try to push data to application. */
1273 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1274 /* Reading from remote client is not required anymore. */
1275 urh->in_buffer_size = 0;
1276 urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
1277 connection->tls_read_ready = false;
1278 }
1279 }
1280 else
1281 {
1282 if (urh->in_buffer_used != res)
1283 {
1284 memmove (urh->in_buffer,
1285 &urh->in_buffer[res],
1286 urh->in_buffer_used - res);
1287 urh->in_buffer_used -= res;
1288 if (data_size > (size_t)res)
1289 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1290 }
1291 else
1292 {
1293 urh->in_buffer_used = 0;
1294 }
1295 }
1296 }
1297
1298 /* handle reading from application and writing to HTTPS client */
1299 1248
1249 /*
1250 * handle reading from application
1251 */
1300 /* If application signaled MHD about socket closure then 1252 /* If application signaled MHD about socket closure then
1301 * check for any pending data even if socket is not marked 1253 * check for any pending data even if socket is not marked
1302 * as 'ready' (signal may arrive after poll()/select()). 1254 * as 'ready' (signal may arrive after poll()/select()).
@@ -1356,6 +1308,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1356 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY; 1308 urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
1357 } 1309 }
1358 } 1310 }
1311
1312 /*
1313 * handle writing to remote HTTPS client
1314 */
1359 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) && 1315 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
1360 (urh->out_buffer_used > 0) ) 1316 (urh->out_buffer_used > 0) )
1361 { 1317 {
@@ -1410,6 +1366,68 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1410 } 1366 }
1411 } 1367 }
1412 1368
1369 /*
1370 * handle writing to application
1371 */
1372 if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
1373 (urh->in_buffer_used > 0) )
1374 {
1375 ssize_t res;
1376 size_t data_size;
1377
1378 data_size = urh->in_buffer_used;
1379 if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
1380 data_size = MHD_SCKT_SEND_MAX_SIZE_;
1381
1382 res = MHD_send_ (urh->mhd.socket,
1383 urh->in_buffer,
1384 data_size);
1385 if (0 > res)
1386 {
1387 int err = MHD_socket_get_error_ ();
1388
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 {
1417 memmove (urh->in_buffer,
1418 &urh->in_buffer[res],
1419 urh->in_buffer_used - res);
1420 urh->in_buffer_used -= res;
1421 if (data_size > (size_t)res)
1422 urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
1423 }
1424 else
1425 {
1426 urh->in_buffer_used = 0;
1427 }
1428 }
1429 }
1430
1413 /* Check whether data is present in TLS buffers 1431 /* Check whether data is present in TLS buffers
1414 * and incoming forward buffer have some space. */ 1432 * and incoming forward buffer have some space. */
1415 if ( (connection->tls_read_ready) && 1433 if ( (connection->tls_read_ready) &&