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