@@ -452,9 +452,9 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd,
452452/* Bind to a local IP address.
453453 * Returns the bound socket, or -1 on failure.
454454 * */
455- /* {{{ php_network_bind_socket_to_local_addr */
456- php_socket_t php_network_bind_socket_to_local_addr ( const char * host , unsigned port ,
457- int socktype , long sockopts , zend_string * * error_string , int * error_code
455+ php_socket_t php_network_bind_socket_to_local_addr_ex ( const char * host , unsigned port ,
456+ int socktype , long sockopts , php_sockvals * sockvals , zend_string * * error_string ,
457+ int * error_code
458458 )
459459{
460460 int num_addrs , n , err = 0 ;
@@ -533,6 +533,35 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
533533 setsockopt (sock , IPPROTO_TCP , TCP_NODELAY , (char * )& sockoptval , sizeof (sockoptval ));
534534 }
535535#endif
536+ #ifdef SO_KEEPALIVE
537+ if (sockopts & STREAM_SOCKOP_SO_KEEPALIVE ) {
538+ setsockopt (sock , SOL_SOCKET , SO_KEEPALIVE , (char * )& sockoptval , sizeof (sockoptval ));
539+ }
540+ #endif
541+
542+ /* Set socket values if provided */
543+ if (sockvals != NULL ) {
544+ #if defined(TCP_KEEPIDLE )
545+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPIDLE ) {
546+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPIDLE , (char * )& sockvals -> keepalive .keepidle , sizeof (sockvals -> keepalive .keepidle ));
547+ }
548+ #elif defined(TCP_KEEPALIVE )
549+ /* macOS uses TCP_KEEPALIVE instead of TCP_KEEPIDLE */
550+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPIDLE ) {
551+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPALIVE , (char * )& sockvals -> keepalive .keepidle , sizeof (sockvals -> keepalive .keepidle ));
552+ }
553+ #endif
554+ #ifdef TCP_KEEPINTVL
555+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPINTVL ) {
556+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPINTVL , (char * )& sockvals -> keepalive .keepintvl , sizeof (sockvals -> keepalive .keepintvl ));
557+ }
558+ #endif
559+ #ifdef TCP_KEEPCNT
560+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPCNT ) {
561+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPCNT , (char * )& sockvals -> keepalive .keepcnt , sizeof (sockvals -> keepalive .keepcnt ));
562+ }
563+ #endif
564+ }
536565
537566 n = bind (sock , sa , socklen );
538567
@@ -560,7 +589,13 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po
560589 return sock ;
561590
562591}
563- /* }}} */
592+
593+ php_socket_t php_network_bind_socket_to_local_addr (const char * host , unsigned port ,
594+ int socktype , long sockopts , zend_string * * error_string , int * error_code
595+ )
596+ {
597+ return php_network_bind_socket_to_local_addr_ex (host , port , socktype , sockopts , NULL , error_string , error_code );
598+ }
564599
565600PHPAPI zend_result php_network_parse_network_address_with_port (const char * addr , size_t addrlen , struct sockaddr * sa , socklen_t * sl )
566601{
@@ -824,11 +859,9 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
824859 * enable non-blocking mode on the socket.
825860 * Returns the connected (or connecting) socket, or -1 on failure.
826861 * */
827-
828- /* {{{ php_network_connect_socket_to_host */
829- php_socket_t php_network_connect_socket_to_host (const char * host , unsigned short port ,
862+ php_socket_t php_network_connect_socket_to_host_ex (const char * host , unsigned short port ,
830863 int socktype , int asynchronous , struct timeval * timeout , zend_string * * error_string ,
831- int * error_code , const char * bindto , unsigned short bindport , long sockopts
864+ int * error_code , const char * bindto , unsigned short bindport , long sockopts , php_sockvals * sockvals
832865 )
833866{
834867 int num_addrs , n , fatal = 0 ;
@@ -952,6 +985,40 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
952985 }
953986 }
954987#endif
988+
989+ #ifdef SO_KEEPALIVE
990+ {
991+ int val = 1 ;
992+ if (sockopts & STREAM_SOCKOP_SO_KEEPALIVE ) {
993+ setsockopt (sock , SOL_SOCKET , SO_KEEPALIVE , (char * )& val , sizeof (val ));
994+ }
995+ }
996+ #endif
997+
998+ /* Set socket values if provided */
999+ if (sockvals != NULL ) {
1000+ #if defined(TCP_KEEPIDLE )
1001+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPIDLE ) {
1002+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPIDLE , (char * )& sockvals -> keepalive .keepidle , sizeof (sockvals -> keepalive .keepidle ));
1003+ }
1004+ #elif defined(TCP_KEEPALIVE )
1005+ /* macOS uses TCP_KEEPALIVE instead of TCP_KEEPIDLE */
1006+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPIDLE ) {
1007+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPALIVE , (char * )& sockvals -> keepalive .keepidle , sizeof (sockvals -> keepalive .keepidle ));
1008+ }
1009+ #endif
1010+ #ifdef TCP_KEEPINTVL
1011+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPINTVL ) {
1012+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPINTVL , (char * )& sockvals -> keepalive .keepintvl , sizeof (sockvals -> keepalive .keepintvl ));
1013+ }
1014+ #endif
1015+ #ifdef TCP_KEEPCNT
1016+ if (sockvals -> mask & PHP_SOCKVAL_TCP_KEEPCNT ) {
1017+ setsockopt (sock , IPPROTO_TCP , TCP_KEEPCNT , (char * )& sockvals -> keepalive .keepcnt , sizeof (sockvals -> keepalive .keepcnt ));
1018+ }
1019+ #endif
1020+ }
1021+
9551022 n = php_network_connect_socket (sock , sa , socklen , asynchronous ,
9561023 timeout ? & working_timeout : NULL ,
9571024 error_string , error_code );
@@ -998,7 +1065,15 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
9981065
9991066 return sock ;
10001067}
1001- /* }}} */
1068+
1069+ php_socket_t php_network_connect_socket_to_host (const char * host , unsigned short port ,
1070+ int socktype , int asynchronous , struct timeval * timeout , zend_string * * error_string ,
1071+ int * error_code , const char * bindto , unsigned short bindport , long sockopts
1072+ )
1073+ {
1074+ return php_network_connect_socket_to_host_ex (host , port , socktype , asynchronous , timeout ,
1075+ error_string , error_code , bindto , bindport , sockopts , NULL );
1076+ }
10021077
10031078/* {{{ php_any_addr
10041079 * Fills any (wildcard) address into php_sockaddr_storage
0 commit comments