diff options
Diffstat (limited to 'src/microhttpd/mhd_sockets.c')
-rw-r--r-- | src/microhttpd/mhd_sockets.c | 282 |
1 files changed, 152 insertions, 130 deletions
diff --git a/src/microhttpd/mhd_sockets.c b/src/microhttpd/mhd_sockets.c index b4e73480..38c6ecd4 100644 --- a/src/microhttpd/mhd_sockets.c +++ b/src/microhttpd/mhd_sockets.c | |||
@@ -37,10 +37,10 @@ | |||
37 | * @param err the WinSock error code. | 37 | * @param err the WinSock error code. |
38 | * @return pointer to string description of specified WinSock error. | 38 | * @return pointer to string description of specified WinSock error. |
39 | */ | 39 | */ |
40 | const char* MHD_W32_strerror_winsock_(int err) | 40 | const char*MHD_W32_strerror_winsock_ (int err) |
41 | { | 41 | { |
42 | switch (err) | 42 | switch (err) |
43 | { | 43 | { |
44 | case 0: | 44 | case 0: |
45 | return "No error"; | 45 | return "No error"; |
46 | case WSA_INVALID_HANDLE: | 46 | case WSA_INVALID_HANDLE: |
@@ -233,7 +233,7 @@ const char* MHD_W32_strerror_winsock_(int err) | |||
233 | return "Invalid QoS shaping rate object"; | 233 | return "Invalid QoS shaping rate object"; |
234 | case WSA_QOS_RESERVED_PETYPE: | 234 | case WSA_QOS_RESERVED_PETYPE: |
235 | return "Reserved policy QoS element type"; | 235 | return "Reserved policy QoS element type"; |
236 | } | 236 | } |
237 | return "Unknown winsock error"; | 237 | return "Unknown winsock error"; |
238 | } | 238 | } |
239 | 239 | ||
@@ -246,113 +246,114 @@ const char* MHD_W32_strerror_winsock_(int err) | |||
246 | * @return non-zero if succeeded, zero otherwise | 246 | * @return non-zero if succeeded, zero otherwise |
247 | */ | 247 | */ |
248 | int | 248 | int |
249 | MHD_W32_socket_pair_(SOCKET sockets_pair[2], int non_blk) | 249 | MHD_W32_socket_pair_ (SOCKET sockets_pair[2], int non_blk) |
250 | { | 250 | { |
251 | int i; | 251 | int i; |
252 | 252 | ||
253 | if (! sockets_pair) | 253 | if (! sockets_pair) |
254 | { | 254 | { |
255 | WSASetLastError (WSAEFAULT); | 255 | WSASetLastError (WSAEFAULT); |
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
259 | #define PAIRMAXTRYIES 800 | 259 | #define PAIRMAXTRYIES 800 |
260 | for (i = 0; i < PAIRMAXTRYIES; i++) | 260 | for (i = 0; i < PAIRMAXTRYIES; i++) |
261 | { | ||
262 | struct sockaddr_in listen_addr; | ||
263 | SOCKET listen_s; | ||
264 | static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */ | ||
265 | int addr_len = c_addinlen; | ||
266 | unsigned long on_val = 1; | ||
267 | unsigned long off_val = 0; | ||
268 | |||
269 | listen_s = socket (AF_INET, | ||
270 | SOCK_STREAM, | ||
271 | IPPROTO_TCP); | ||
272 | if (INVALID_SOCKET == listen_s) | ||
273 | break; /* can't create even single socket */ | ||
274 | |||
275 | listen_addr.sin_family = AF_INET; | ||
276 | listen_addr.sin_port = 0; /* same as htons(0) */ | ||
277 | listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | ||
278 | if ( ((0 == bind (listen_s, | ||
279 | (struct sockaddr*) &listen_addr, | ||
280 | c_addinlen)) && | ||
281 | (0 == listen (listen_s, | ||
282 | 1) ) && | ||
283 | (0 == getsockname (listen_s, | ||
284 | (struct sockaddr*) &listen_addr, | ||
285 | &addr_len))) ) | ||
261 | { | 286 | { |
262 | struct sockaddr_in listen_addr; | 287 | SOCKET client_s = socket (AF_INET, |
263 | SOCKET listen_s; | 288 | SOCK_STREAM, |
264 | static const int c_addinlen = sizeof(struct sockaddr_in); /* help compiler to optimize */ | 289 | IPPROTO_TCP); |
265 | int addr_len = c_addinlen; | 290 | struct sockaddr_in accepted_from_addr; |
266 | unsigned long on_val = 1; | 291 | struct sockaddr_in client_addr; |
267 | unsigned long off_val = 0; | 292 | SOCKET server_s; |
268 | 293 | ||
269 | listen_s = socket (AF_INET, | 294 | if (INVALID_SOCKET == client_s) |
270 | SOCK_STREAM, | 295 | { |
271 | IPPROTO_TCP); | 296 | /* try again */ |
272 | if (INVALID_SOCKET == listen_s) | 297 | closesocket (listen_s); |
273 | break; /* can't create even single socket */ | 298 | continue; |
274 | 299 | } | |
275 | listen_addr.sin_family = AF_INET; | 300 | |
276 | listen_addr.sin_port = 0; /* same as htons(0) */ | 301 | if ( (0 != ioctlsocket (client_s, |
277 | listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | 302 | FIONBIO, |
278 | if ( (0 == bind (listen_s, | 303 | &on_val)) || |
279 | (struct sockaddr*) &listen_addr, | 304 | ( (0 != connect (client_s, |
280 | c_addinlen) && | 305 | (struct sockaddr*) &listen_addr, |
281 | (0 == listen (listen_s, | 306 | c_addinlen)) && |
282 | 1) ) && | 307 | (WSAGetLastError () != WSAEWOULDBLOCK)) ) |
283 | (0 == getsockname (listen_s, | 308 | { |
284 | (struct sockaddr*) &listen_addr, | 309 | /* try again */ |
285 | &addr_len))) ) | 310 | closesocket (listen_s); |
286 | { | 311 | closesocket (client_s); |
287 | SOCKET client_s = socket(AF_INET, | 312 | continue; |
288 | SOCK_STREAM, | 313 | } |
289 | IPPROTO_TCP); | 314 | |
290 | struct sockaddr_in accepted_from_addr; | 315 | addr_len = c_addinlen; |
291 | struct sockaddr_in client_addr; | 316 | server_s = accept (listen_s, |
292 | SOCKET server_s; | 317 | (struct sockaddr*) &accepted_from_addr, |
293 | 318 | &addr_len); | |
294 | if (INVALID_SOCKET == client_s) | 319 | if (INVALID_SOCKET == server_s) |
295 | { | 320 | { |
296 | /* try again */ | 321 | /* try again */ |
297 | closesocket (listen_s); | 322 | closesocket (listen_s); |
298 | continue; | 323 | closesocket (client_s); |
299 | } | 324 | continue; |
300 | 325 | } | |
301 | if ( (0 != ioctlsocket (client_s, | 326 | |
302 | FIONBIO, | 327 | addr_len = c_addinlen; |
303 | &on_val)) || | 328 | if ( (0 == getsockname (client_s, |
304 | ( (0 != connect (client_s, | 329 | (struct sockaddr*) &client_addr, |
305 | (struct sockaddr*) &listen_addr, | 330 | &addr_len)) && |
306 | c_addinlen)) && | 331 | (accepted_from_addr.sin_family == client_addr.sin_family) && |
307 | (WSAGetLastError() != WSAEWOULDBLOCK)) ) | 332 | (accepted_from_addr.sin_port == client_addr.sin_port) && |
308 | { | 333 | (accepted_from_addr.sin_addr.s_addr == |
309 | /* try again */ | 334 | client_addr.sin_addr.s_addr) && |
310 | closesocket (listen_s); | 335 | ( (0 != non_blk) ? |
311 | closesocket (client_s); | 336 | (0 == ioctlsocket (server_s, |
312 | continue; | 337 | FIONBIO, |
313 | } | 338 | &on_val)) : |
314 | 339 | (0 == ioctlsocket (client_s, | |
315 | addr_len = c_addinlen; | 340 | FIONBIO, |
316 | server_s = accept (listen_s, | 341 | &off_val)) ) ) |
317 | (struct sockaddr*) &accepted_from_addr, | 342 | { |
318 | &addr_len); | 343 | closesocket (listen_s); |
319 | if (INVALID_SOCKET == server_s) | 344 | sockets_pair[0] = server_s; |
320 | { | 345 | sockets_pair[1] = client_s; |
321 | /* try again */ | 346 | return ! 0; |
322 | closesocket (listen_s); | 347 | } |
323 | closesocket (client_s); | 348 | closesocket (server_s); |
324 | continue; | 349 | closesocket (client_s); |
325 | } | ||
326 | |||
327 | addr_len = c_addinlen; | ||
328 | if ( (0 == getsockname (client_s, | ||
329 | (struct sockaddr*) &client_addr, | ||
330 | &addr_len)) && | ||
331 | (accepted_from_addr.sin_family == client_addr.sin_family) && | ||
332 | (accepted_from_addr.sin_port == client_addr.sin_port) && | ||
333 | (accepted_from_addr.sin_addr.s_addr == client_addr.sin_addr.s_addr) && | ||
334 | ( (0 != non_blk) ? | ||
335 | (0 == ioctlsocket(server_s, | ||
336 | FIONBIO, | ||
337 | &on_val)) : | ||
338 | (0 == ioctlsocket(client_s, | ||
339 | FIONBIO, | ||
340 | &off_val)) ) ) | ||
341 | { | ||
342 | closesocket (listen_s); | ||
343 | sockets_pair[0] = server_s; | ||
344 | sockets_pair[1] = client_s; | ||
345 | return !0; | ||
346 | } | ||
347 | closesocket (server_s); | ||
348 | closesocket (client_s); | ||
349 | } | ||
350 | closesocket(listen_s); | ||
351 | } | 350 | } |
351 | closesocket (listen_s); | ||
352 | } | ||
352 | 353 | ||
353 | sockets_pair[0] = INVALID_SOCKET; | 354 | sockets_pair[0] = INVALID_SOCKET; |
354 | sockets_pair[1] = INVALID_SOCKET; | 355 | sockets_pair[1] = INVALID_SOCKET; |
355 | WSASetLastError(WSAECONNREFUSED); | 356 | WSASetLastError (WSAECONNREFUSED); |
356 | 357 | ||
357 | return 0; | 358 | return 0; |
358 | } | 359 | } |
@@ -383,9 +384,9 @@ MHD_add_to_fd_set_ (MHD_socket fd, | |||
383 | set, | 384 | set, |
384 | fd_setsize)) | 385 | fd_setsize)) |
385 | return 0; | 386 | return 0; |
386 | MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_(fd, | 387 | MHD_SCKT_ADD_FD_TO_FDSET_SETSIZE_ (fd, |
387 | set, | 388 | set, |
388 | fd_setsize); | 389 | fd_setsize); |
389 | if ( (NULL != max_fd) && | 390 | if ( (NULL != max_fd) && |
390 | ( (fd > *max_fd) || | 391 | ( (fd > *max_fd) || |
391 | (MHD_INVALID_SOCKET == *max_fd) ) ) | 392 | (MHD_INVALID_SOCKET == *max_fd) ) ) |
@@ -424,7 +425,7 @@ MHD_socket_nonblocking_ (MHD_socket sock) | |||
424 | &flags)) | 425 | &flags)) |
425 | return 0; | 426 | return 0; |
426 | #endif /* MHD_WINSOCK_SOCKETS */ | 427 | #endif /* MHD_WINSOCK_SOCKETS */ |
427 | return !0; | 428 | return ! 0; |
428 | } | 429 | } |
429 | 430 | ||
430 | 431 | ||
@@ -452,12 +453,12 @@ MHD_socket_noninheritable_ (MHD_socket sock) | |||
452 | flags | FD_CLOEXEC)) ) | 453 | flags | FD_CLOEXEC)) ) |
453 | return 0; | 454 | return 0; |
454 | #elif defined(MHD_WINSOCK_SOCKETS) | 455 | #elif defined(MHD_WINSOCK_SOCKETS) |
455 | if (! SetHandleInformation ((HANDLE)sock, | 456 | if (! SetHandleInformation ((HANDLE) sock, |
456 | HANDLE_FLAG_INHERIT, | 457 | HANDLE_FLAG_INHERIT, |
457 | 0)) | 458 | 0)) |
458 | return 0; | 459 | return 0; |
459 | #endif /* MHD_WINSOCK_SOCKETS */ | 460 | #endif /* MHD_WINSOCK_SOCKETS */ |
460 | return !0; | 461 | return ! 0; |
461 | } | 462 | } |
462 | 463 | ||
463 | 464 | ||
@@ -508,14 +509,34 @@ MHD_socket_cork_ (MHD_socket sock, | |||
508 | const MHD_SCKT_OPT_BOOL_ on_val = 1; | 509 | const MHD_SCKT_OPT_BOOL_ on_val = 1; |
509 | 510 | ||
510 | /* Disable extra buffering */ | 511 | /* Disable extra buffering */ |
511 | return (0 == setsockopt (sock, | 512 | if (0 != setsockopt (sock, |
512 | IPPROTO_TCP, | 513 | IPPROTO_TCP, |
513 | MHD_TCP_CORK_NOPUSH, | 514 | MHD_TCP_CORK_NOPUSH, |
514 | (const void *) (on ? &on_val : &off_val), | 515 | (const void *) (on ? &on_val : &off_val), |
515 | sizeof (off_val))); | 516 | sizeof (off_val))) |
517 | return 0; /* failed */ | ||
518 | #if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9 | ||
519 | /* FreeBSD do not need zero-send for flushing starting from version 9 */ | ||
520 | return 1; | ||
521 | #elif defined(TCP_NOPUSH) && ! defined(TCP_CORK) | ||
522 | { | ||
523 | const int dummy = 0; | ||
524 | /* Force flush data with zero send otherwise Darwin and some BSD systems | ||
525 | will add 5 seconds delay. Not required with TCP_CORK as switching off | ||
526 | TCP_CORK always flushes socket buffer. */ | ||
527 | if (0 > send (sock, | ||
528 | &dummy, | ||
529 | 0)) | ||
530 | return 0; /* even force flush failed!? */ | ||
531 | return 1; /* success */ | ||
532 | } | ||
516 | #else | 533 | #else |
517 | return 0; | 534 | return 0; |
518 | #endif /* MHD_TCP_CORK_NOPUSH */ | 535 | #endif |
536 | #elif | ||
537 | /* do not have MHD_TCP_CORK_NOPUSH at all */ | ||
538 | return 0; | ||
539 | #endif | ||
519 | } | 540 | } |
520 | 541 | ||
521 | 542 | ||
@@ -559,7 +580,8 @@ MHD_socket_create_listen_ (int pf) | |||
559 | int nosigpipe_set; | 580 | int nosigpipe_set; |
560 | #endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ | 581 | #endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ |
561 | 582 | ||
562 | #if defined(MHD_POSIX_SOCKETS) && ( defined(SOCK_CLOEXEC) || defined(SOCK_NOSIGPIPE) ) | 583 | #if defined(MHD_POSIX_SOCKETS) && (defined(SOCK_CLOEXEC) || \ |
584 | defined(SOCK_NOSIGPIPE) ) | ||
563 | fd = socket (pf, | 585 | fd = socket (pf, |
564 | SOCK_STREAM | SOCK_CLOEXEC | MAYBE_SOCK_NOSIGPIPE, | 586 | SOCK_STREAM | SOCK_CLOEXEC | MAYBE_SOCK_NOSIGPIPE, |
565 | 0); | 587 | 0); |
@@ -574,36 +596,36 @@ MHD_socket_create_listen_ (int pf) | |||
574 | NULL, | 596 | NULL, |
575 | 0, | 597 | 0, |
576 | WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); | 598 | WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); |
577 | cloexec_set = !0; | 599 | cloexec_set = ! 0; |
578 | #else /* !SOCK_CLOEXEC */ | 600 | #else /* !SOCK_CLOEXEC */ |
579 | fd = MHD_INVALID_SOCKET; | 601 | fd = MHD_INVALID_SOCKET; |
580 | #endif /* !SOCK_CLOEXEC */ | 602 | #endif /* !SOCK_CLOEXEC */ |
581 | if (MHD_INVALID_SOCKET == fd) | 603 | if (MHD_INVALID_SOCKET == fd) |
582 | { | 604 | { |
583 | fd = socket (pf, | 605 | fd = socket (pf, |
584 | SOCK_STREAM, | 606 | SOCK_STREAM, |
585 | 0); | 607 | 0); |
586 | cloexec_set = 0; | 608 | cloexec_set = 0; |
587 | } | 609 | } |
588 | if (MHD_INVALID_SOCKET == fd) | 610 | if (MHD_INVALID_SOCKET == fd) |
589 | return MHD_INVALID_SOCKET; | 611 | return MHD_INVALID_SOCKET; |
590 | 612 | ||
591 | #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_) | 613 | #if defined(SOCK_NOSIGPIPE) || defined(MHD_socket_nosignal_) |
592 | if ( ( (! nosigpipe_set) | 614 | if ( ( (! nosigpipe_set) |
593 | #ifdef MHD_socket_nosignal_ | 615 | #ifdef MHD_socket_nosignal_ |
594 | || (! MHD_socket_nosignal_(fd)) | 616 | || (! MHD_socket_nosignal_ (fd)) |
595 | #endif /* MHD_socket_nosignal_ */ | 617 | #endif /* MHD_socket_nosignal_ */ |
596 | ) && (0 == MAYBE_MSG_NOSIGNAL) ) | 618 | ) && (0 == MAYBE_MSG_NOSIGNAL) ) |
597 | { | 619 | { |
598 | /* SIGPIPE disable is possible on this platform | 620 | /* SIGPIPE disable is possible on this platform |
599 | * (so application expect that it will be disabled), | 621 | * (so application expect that it will be disabled), |
600 | * but failed to be disabled here and it is not | 622 | * but failed to be disabled here and it is not |
601 | * possible to disable SIGPIPE by MSG_NOSIGNAL. */ | 623 | * possible to disable SIGPIPE by MSG_NOSIGNAL. */ |
602 | const int err = MHD_socket_get_error_ (); | 624 | const int err = MHD_socket_get_error_ (); |
603 | (void) MHD_socket_close_ (fd); | 625 | (void) MHD_socket_close_ (fd); |
604 | MHD_socket_fset_error_ (err); | 626 | MHD_socket_fset_error_ (err); |
605 | return MHD_INVALID_SOCKET; | 627 | return MHD_INVALID_SOCKET; |
606 | } | 628 | } |
607 | #endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ | 629 | #endif /* SOCK_NOSIGPIPE || MHD_socket_nosignal_ */ |
608 | if (! cloexec_set) | 630 | if (! cloexec_set) |
609 | (void) MHD_socket_noninheritable_ (fd); | 631 | (void) MHD_socket_noninheritable_ (fd); |