@@ -299,6 +299,35 @@ typedef int php_non_blocking_flags_t;
299
299
fcntl(sock, F_SETFL, save)
300
300
#endif
301
301
302
+ #if HAVE_GETTIMEOFDAY
303
+ /* Subtract times */
304
+ static inline void sub_times (struct timeval a , struct timeval b , struct timeval * result )
305
+ {
306
+ result -> tv_usec = a .tv_usec - b .tv_usec ;
307
+ if (result -> tv_usec < 0L ) {
308
+ a .tv_sec -- ;
309
+ result -> tv_usec += 1000000L ;
310
+ }
311
+ result -> tv_sec = a .tv_sec - b .tv_sec ;
312
+ if (result -> tv_sec < 0L ) {
313
+ result -> tv_sec ++ ;
314
+ result -> tv_usec -= 1000000L ;
315
+ }
316
+ }
317
+
318
+ static inline void php_network_set_limit_time (struct timeval * limit_time ,
319
+ struct timeval * timeout )
320
+ {
321
+ gettimeofday (limit_time , NULL );
322
+ limit_time -> tv_sec += timeout -> tv_sec ;
323
+ limit_time -> tv_usec += timeout -> tv_usec ;
324
+ if (limit_time -> tv_usec >= 1000000 ) {
325
+ limit_time -> tv_usec -= 1000000 ;
326
+ limit_time -> tv_sec ++ ;
327
+ }
328
+ }
329
+ #endif
330
+
302
331
/* Connect to a socket using an interruptible connect with optional timeout.
303
332
* Optionally, the connect can be made asynchronously, which will implicitly
304
333
* enable non-blocking mode on the socket.
@@ -351,25 +380,53 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
351
380
* expected when a connection is actively refused. This way,
352
381
* php_pollfd_for will return a mask with POLLOUT if the connection
353
382
* is successful and with POLLPRI otherwise. */
354
- if (( n = php_pollfd_for ( sockfd , POLLOUT |POLLPRI , timeout )) == 0 ) {
383
+ int events = POLLOUT |POLLPRI ;
355
384
#else
356
- if ((n = php_pollfd_for (sockfd , PHP_POLLREADABLE |POLLOUT , timeout )) == 0 ) {
385
+ int events = PHP_POLLREADABLE |POLLOUT ;
386
+ #endif
387
+ struct timeval working_timeout ;
388
+ #if HAVE_GETTIMEOFDAY
389
+ struct timeval limit_time , time_now ;
390
+ #endif
391
+ if (timeout ) {
392
+ memcpy (& working_timeout , timeout , sizeof (working_timeout ));
393
+ #if HAVE_GETTIMEOFDAY
394
+ php_network_set_limit_time (& limit_time , & working_timeout );
357
395
#endif
358
- error = PHP_TIMEOUT_ERROR_VALUE ;
359
396
}
360
397
361
- if (n > 0 ) {
362
- len = sizeof (error );
363
- /*
364
- BSD-derived systems set errno correctly
365
- Solaris returns -1 from getsockopt in case of error
366
- */
367
- if (getsockopt (sockfd , SOL_SOCKET , SO_ERROR , (char * )& error , & len ) != 0 ) {
398
+ while (true) {
399
+ n = php_pollfd_for (sockfd , events , timeout ? & working_timeout : NULL );
400
+ if (n < 0 ) {
401
+ if (errno == EINTR ) {
402
+ #if HAVE_GETTIMEOFDAY
403
+ if (timeout ) {
404
+ gettimeofday (& time_now , NULL );
405
+
406
+ if (!timercmp (& time_now , & limit_time , < )) {
407
+ /* time limit expired; no need for another poll */
408
+ error = PHP_TIMEOUT_ERROR_VALUE ;
409
+ break ;
410
+ } else {
411
+ /* work out remaining time */
412
+ sub_times (limit_time , time_now , & working_timeout );
413
+ }
414
+ }
415
+ #endif
416
+ continue ;
417
+ }
368
418
ret = -1 ;
419
+ } else if (n == 0 ) {
420
+ error = PHP_TIMEOUT_ERROR_VALUE ;
421
+ } else {
422
+ len = sizeof (error );
423
+ /* BSD-derived systems set errno correctly.
424
+ * Solaris returns -1 from getsockopt in case of error. */
425
+ if (getsockopt (sockfd , SOL_SOCKET , SO_ERROR , (char * )& error , & len ) != 0 ) {
426
+ ret = -1 ;
427
+ }
369
428
}
370
- } else {
371
- /* whoops: sockfd has disappeared */
372
- ret = -1 ;
429
+ break ;
373
430
}
374
431
375
432
ok :
@@ -392,22 +449,6 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
392
449
}
393
450
/* }}} */
394
451
395
- /* {{{ sub_times */
396
- static inline void sub_times (struct timeval a , struct timeval b , struct timeval * result )
397
- {
398
- result -> tv_usec = a .tv_usec - b .tv_usec ;
399
- if (result -> tv_usec < 0L ) {
400
- a .tv_sec -- ;
401
- result -> tv_usec += 1000000L ;
402
- }
403
- result -> tv_sec = a .tv_sec - b .tv_sec ;
404
- if (result -> tv_sec < 0L ) {
405
- result -> tv_sec ++ ;
406
- result -> tv_usec -= 1000000L ;
407
- }
408
- }
409
- /* }}} */
410
-
411
452
/* Bind to a local IP address.
412
453
* Returns the bound socket, or -1 on failure.
413
454
* */
@@ -777,7 +818,6 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
777
818
}
778
819
/* }}} */
779
820
780
-
781
821
/* Connect to a remote host using an interruptible connect with optional timeout.
782
822
* Optionally, the connect can be made asynchronously, which will implicitly
783
823
* enable non-blocking mode on the socket.
@@ -809,13 +849,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
809
849
if (timeout ) {
810
850
memcpy (& working_timeout , timeout , sizeof (working_timeout ));
811
851
#if HAVE_GETTIMEOFDAY
812
- gettimeofday (& limit_time , NULL );
813
- limit_time .tv_sec += working_timeout .tv_sec ;
814
- limit_time .tv_usec += working_timeout .tv_usec ;
815
- if (limit_time .tv_usec >= 1000000 ) {
816
- limit_time .tv_usec -= 1000000 ;
817
- limit_time .tv_sec ++ ;
818
- }
852
+ php_network_set_limit_time (& limit_time , & working_timeout );
819
853
#endif
820
854
}
821
855
0 commit comments