From 233e9d797932519fa9971fe6ec2b44c54cea9324 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 4 May 2024 13:04:39 +0100 Subject: [PATCH 1/3] GH-14111 main/streams: adding SO_LINGER to stream options. --- ext/ftp/ftp.c | 2 +- ext/standard/tests/network/gh14111.phpt | 23 +++++++++ main/network.c | 25 ++++++++- main/php_network.h | 6 ++- main/streams/xp_socket.c | 68 ++++++++++++++++++++++++- 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 ext/standard/tests/network/gh14111.phpt diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 4693787607b43..74ad1bd21811b 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -129,7 +129,7 @@ ftp_open(const char *host, short port, zend_long timeout_sec) ftp->fd = php_network_connect_socket_to_host(host, (unsigned short) (port ? port : 21), SOCK_STREAM, - 0, &tv, NULL, NULL, NULL, 0, STREAM_SOCKOP_NONE); + 0, &tv, NULL, NULL, NULL, 0, STREAM_SOCKOP_NONE, -1); if (ftp->fd == -1) { goto bail; } diff --git a/ext/standard/tests/network/gh14111.phpt b/ext/standard/tests/network/gh14111.phpt new file mode 100644 index 0000000000000..436fb8486a87e --- /dev/null +++ b/ext/standard/tests/network/gh14111.phpt @@ -0,0 +1,23 @@ +--TEST-- +Testing so_linger `socket` option. +--SKIPIF-- + +--FILE-- + ['so_linger' => false]]); +var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); +$context = stream_context_create(['socket' => ['so_linger' => PHP_INT_MAX + 1]]); +var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); +$context = stream_context_create(['socket' => ['so_linger' => 3]]); +var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); +?> +--EXPECTF-- +Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `so_linger` value in %s on line %d +bool(false) + +Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `so_linger` value in %s on line %d +bool(false) +bool(true) diff --git a/main/network.c b/main/network.c index b015b59c86e21..9e4963ce4eaac 100644 --- a/main/network.c +++ b/main/network.c @@ -402,7 +402,7 @@ static inline void sub_times(struct timeval a, struct timeval b, struct timeval * */ /* {{{ php_network_bind_socket_to_local_addr */ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, - int socktype, long sockopts, zend_string **error_string, int *error_code + int socktype, long sockopts, long linger, zend_string **error_string, int *error_code ) { int num_addrs, n, err = 0; @@ -470,6 +470,15 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&sockoptval, sizeof(sockoptval)); } #endif +#ifdef SO_LINGER + if (sockopts & STREAM_SOCKOP_SO_LINGER) { + struct linger val = { + .l_onoff = (linger > 0), + .l_linger = (int)linger + }; + setsockopt(sock, IPPROTO_TCP, SO_LINGER, (char*)&val, sizeof(val)); + } +#endif n = bind(sock, sa, socklen); @@ -766,7 +775,8 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, /* {{{ php_network_connect_socket_to_host */ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, - int *error_code, const char *bindto, unsigned short bindport, long sockopts + int *error_code, const char *bindto, unsigned short bindport, long sockopts, + long linger ) { int num_addrs, n, fatal = 0; @@ -896,6 +906,17 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, sizeof(val)); } } +#endif +#ifdef SO_LINGER + { + if (sockopts & STREAM_SOCKOP_SO_LINGER) { + struct linger val = { + .l_onoff = linger > 0, + .l_linger = (int)linger + }; + setsockopt(sock, IPPROTO_TCP, SO_LINGER, (char*)&val, sizeof(val)); + } + } #endif n = php_network_connect_socket(sock, sa, socklen, asynchronous, timeout ? &working_timeout : NULL, diff --git a/main/php_network.h b/main/php_network.h index a31bc57b76aee..e971b536bc606 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -116,6 +116,7 @@ typedef int php_socket_t; #define STREAM_SOCKOP_IPV6_V6ONLY (1 << 3) #define STREAM_SOCKOP_IPV6_V6ONLY_ENABLED (1 << 4) #define STREAM_SOCKOP_TCP_NODELAY (1 << 5) +#define STREAM_SOCKOP_SO_LINGER (1 << 6) /* uncomment this to debug poll(2) emulation on systems that have poll(2) */ @@ -265,7 +266,8 @@ PHPAPI void php_network_freeaddresses(struct sockaddr **sal); PHPAPI php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, - int *error_code, const char *bindto, unsigned short bindport, long sockopts + int *error_code, const char *bindto, unsigned short bindport, long sockopts, + long linger ); PHPAPI int php_network_connect_socket(php_socket_t sockfd, @@ -280,7 +282,7 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd, php_network_connect_socket((sock), (addr), (addrlen), 0, (timeout), NULL, NULL) PHPAPI php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, - int socktype, long sockopts, zend_string **error_string, int *error_code + int socktype, long sockopts, long linger, zend_string **error_string, int *error_code ); PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 3d035de6edb21..59c633f3f01f3 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -659,12 +659,41 @@ static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno return parse_ip_address_ex(xparam->inputs.name, xparam->inputs.namelen, portno, xparam->want_errortext, &xparam->outputs.error_text); } +static long parse_linger(zval *arg, bool *failed) +{ + zend_long lval; + *failed = false; + if (Z_TYPE_P(arg) == IS_STRING) { + zend_string *val = Z_STR_P(arg); + uint8_t r = is_numeric_string(ZSTR_VAL(val), ZSTR_LEN(val), &lval, NULL, false); + + switch (r) { + case IS_LONG: + break; + default: + *failed = true; + return -1; + } + } else if (Z_TYPE_P(arg) == IS_LONG) { + lval = Z_LVAL_P(arg); + } else { + *failed = true; + return -1; + } + + if (lval < 0 || lval > INT_MAX) { + *failed = true; + } + return (long)lval; +} + static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *sock, php_stream_xport_param *xparam) { char *host = NULL; int portno, err; long sockopts = STREAM_SOCKOP_NONE; + long linger = -1; zval *tmpzval = NULL; #ifdef AF_UNIX @@ -724,9 +753,27 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * } #endif +#ifdef SO_LINGER + if (PHP_STREAM_CONTEXT(stream) + && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_linger")) != NULL) { + bool failed; + linger = parse_linger(tmpzval, &failed); + + if (failed) { + if (xparam->want_errortext) { + xparam->outputs.error_text = strpprintf(0, "Invalid `so_linger` value"); + } + return -1; + } else { + sockopts |= STREAM_SOCKOP_SO_LINGER; + } + } +#endif + sock->socket = php_network_bind_socket_to_local_addr(host, portno, stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM, sockopts, + linger, xparam->want_errortext ? &xparam->outputs.error_text : NULL, &err ); @@ -747,6 +794,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ int ret; zval *tmpzval = NULL; long sockopts = STREAM_SOCKOP_NONE; + long linger = -1; #ifdef AF_UNIX if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) { @@ -802,6 +850,23 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ } #endif +#ifdef SO_LINGER + if (PHP_STREAM_CONTEXT(stream) + && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_linger")) != NULL) { + bool failed; + linger = parse_linger(tmpzval, &failed); + + if (failed) { + if (xparam->want_errortext) { + xparam->outputs.error_text = strpprintf(0, "Invalid `so_linger` value"); + } + return -1; + } else { + sockopts |= STREAM_SOCKOP_SO_LINGER; + } + } +#endif + if (stream->ops != &php_stream_udp_socket_ops /* TCP_NODELAY is only applicable for TCP */ #ifdef AF_UNIX && stream->ops != &php_stream_unix_socket_ops @@ -826,7 +891,8 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ &err, bindto, bindport, - sockopts + sockopts, + linger ); ret = sock->socket == -1 ? -1 : 0; From 3118ca3c69a8e72c5c10201f3ffd707f99f7c025 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 7 Jun 2024 20:43:32 +0100 Subject: [PATCH 2/3] changes from feedback --- ext/ftp/ftp.c | 2 +- ext/standard/tests/network/gh14111.phpt | 14 ++++----- main/network.c | 8 +++-- main/php_network.h | 4 +-- main/streams/xp_socket.c | 39 +++++++++++++++++-------- 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 74ad1bd21811b..2821fa47e984b 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -129,7 +129,7 @@ ftp_open(const char *host, short port, zend_long timeout_sec) ftp->fd = php_network_connect_socket_to_host(host, (unsigned short) (port ? port : 21), SOCK_STREAM, - 0, &tv, NULL, NULL, NULL, 0, STREAM_SOCKOP_NONE, -1); + 0, &tv, NULL, NULL, NULL, 0, STREAM_SOCKOP_NONE, NULL); if (ftp->fd == -1) { goto bail; } diff --git a/ext/standard/tests/network/gh14111.phpt b/ext/standard/tests/network/gh14111.phpt index 436fb8486a87e..6913c5963dd7a 100644 --- a/ext/standard/tests/network/gh14111.phpt +++ b/ext/standard/tests/network/gh14111.phpt @@ -1,23 +1,23 @@ --TEST-- -Testing so_linger `socket` option. +Testing linger `socket` option. --SKIPIF-- --FILE-- ['so_linger' => false]]); +$context = stream_context_create(['socket' => ['linger' => false]]); var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); -$context = stream_context_create(['socket' => ['so_linger' => PHP_INT_MAX + 1]]); +$context = stream_context_create(['socket' => ['linger' => PHP_INT_MAX + 1]]); var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); -$context = stream_context_create(['socket' => ['so_linger' => 3]]); +$context = stream_context_create(['socket' => ['linger' => 3]]); var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); ?> --EXPECTF-- -Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `so_linger` value in %s on line %d +Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `linger` value in %s on line %d bool(false) -Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `so_linger` value in %s on line %d +Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `linger` value in %s on line %d bool(false) bool(true) diff --git a/main/network.c b/main/network.c index 9e4963ce4eaac..441655e761691 100644 --- a/main/network.c +++ b/main/network.c @@ -402,7 +402,7 @@ static inline void sub_times(struct timeval a, struct timeval b, struct timeval * */ /* {{{ php_network_bind_socket_to_local_addr */ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, - int socktype, long sockopts, long linger, zend_string **error_string, int *error_code + int socktype, long sockopts, void *option, zend_string **error_string, int *error_code ) { int num_addrs, n, err = 0; @@ -472,6 +472,8 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po #endif #ifdef SO_LINGER if (sockopts & STREAM_SOCKOP_SO_LINGER) { + ZEND_ASSERT(option != NULL); + long linger = *(long *)option; struct linger val = { .l_onoff = (linger > 0), .l_linger = (int)linger @@ -776,7 +778,7 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code, const char *bindto, unsigned short bindport, long sockopts, - long linger + void *option ) { int num_addrs, n, fatal = 0; @@ -910,6 +912,8 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short #ifdef SO_LINGER { if (sockopts & STREAM_SOCKOP_SO_LINGER) { + ZEND_ASSERT(option != NULL); + long linger = *(long *)option; struct linger val = { .l_onoff = linger > 0, .l_linger = (int)linger diff --git a/main/php_network.h b/main/php_network.h index e971b536bc606..ae5d5eb4c9adf 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -267,7 +267,7 @@ PHPAPI void php_network_freeaddresses(struct sockaddr **sal); PHPAPI php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short port, int socktype, int asynchronous, struct timeval *timeout, zend_string **error_string, int *error_code, const char *bindto, unsigned short bindport, long sockopts, - long linger + void *option ); PHPAPI int php_network_connect_socket(php_socket_t sockfd, @@ -282,7 +282,7 @@ PHPAPI int php_network_connect_socket(php_socket_t sockfd, php_network_connect_socket((sock), (addr), (addrlen), 0, (timeout), NULL, NULL) PHPAPI php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned port, - int socktype, long sockopts, long linger, zend_string **error_string, int *error_code + int socktype, long sockopts, void *option, zend_string **error_string, int *error_code ); PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock, diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 59c633f3f01f3..32890d370f822 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -694,6 +694,7 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * int portno, err; long sockopts = STREAM_SOCKOP_NONE; long linger = -1; + void *option = NULL; zval *tmpzval = NULL; #ifdef AF_UNIX @@ -755,25 +756,30 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * #ifdef SO_LINGER if (PHP_STREAM_CONTEXT(stream) - && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_linger")) != NULL) { + && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "linger")) != NULL) { bool failed; linger = parse_linger(tmpzval, &failed); if (failed) { if (xparam->want_errortext) { - xparam->outputs.error_text = strpprintf(0, "Invalid `so_linger` value"); + xparam->outputs.error_text = strpprintf(0, "Invalid `linger` value"); + } + if (host) { + efree(host); } return -1; } else { sockopts |= STREAM_SOCKOP_SO_LINGER; } + + option = &linger; } #endif sock->socket = php_network_bind_socket_to_local_addr(host, portno, stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM, sockopts, - linger, + option, xparam->want_errortext ? &xparam->outputs.error_text : NULL, &err ); @@ -795,6 +801,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ zval *tmpzval = NULL; long sockopts = STREAM_SOCKOP_NONE; long linger = -1; + void *option = NULL; #ifdef AF_UNIX if (stream->ops == &php_stream_unix_socket_ops || stream->ops == &php_stream_unixdg_socket_ops) { @@ -852,30 +859,38 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ #ifdef SO_LINGER if (PHP_STREAM_CONTEXT(stream) - && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_linger")) != NULL) { + && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "linger")) != NULL) { bool failed; linger = parse_linger(tmpzval, &failed); if (failed) { if (xparam->want_errortext) { - xparam->outputs.error_text = strpprintf(0, "Invalid `so_linger` value"); + xparam->outputs.error_text = strpprintf(0, "Invalid `linger` value"); + } + if (host) { + efree(host); + } + if (bindto) { + efree(bindto); } return -1; } else { sockopts |= STREAM_SOCKOP_SO_LINGER; } + + option = &linger; } #endif if (stream->ops != &php_stream_udp_socket_ops /* TCP_NODELAY is only applicable for TCP */ #ifdef AF_UNIX - && stream->ops != &php_stream_unix_socket_ops - && stream->ops != &php_stream_unixdg_socket_ops + && stream->ops != &php_stream_unix_socket_ops + && stream->ops != &php_stream_unixdg_socket_ops #endif - && PHP_STREAM_CONTEXT(stream) - && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL - && zend_is_true(tmpzval) - ) { + && PHP_STREAM_CONTEXT(stream) + && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL + && zend_is_true(tmpzval) + ) { sockopts |= STREAM_SOCKOP_TCP_NODELAY; } @@ -892,7 +907,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ bindto, bindport, sockopts, - linger + option ); ret = sock->socket == -1 ? -1 : 0; From 95d107e10e38aeb5cac85f1a8824768d395ef15b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 7 Jun 2024 21:39:30 +0100 Subject: [PATCH 3/3] change test to non online --- ext/standard/tests/network/gh14111.phpt | 39 +++++++++++++++++-------- main/network.c | 8 ++--- main/php_network.h | 8 +++++ main/streams/xp_socket.c | 4 +-- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/ext/standard/tests/network/gh14111.phpt b/ext/standard/tests/network/gh14111.phpt index 6913c5963dd7a..9cfc9b016914e 100644 --- a/ext/standard/tests/network/gh14111.phpt +++ b/ext/standard/tests/network/gh14111.phpt @@ -1,23 +1,38 @@ --TEST-- Testing linger `socket` option. ---SKIPIF-- - --FILE-- ['linger' => false]]); -var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); +$socket = stream_socket_client("tcp://127.0.0.1:$port", $errno, $errstr, 0, STREAM_CLIENT_CONNECT, $context); +var_dump($socket); $context = stream_context_create(['socket' => ['linger' => PHP_INT_MAX + 1]]); -var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); -$context = stream_context_create(['socket' => ['linger' => 3]]); -var_dump(file_get_contents('https://httpbin.org/get', false, $context) !== false); +$socket = stream_socket_client("tcp://127.0.0.1:$port", $errno, $errstr, 0, STREAM_CLIENT_CONNECT, $context); +var_dump($socket); +$context = stream_context_create(['socket' => ['linger' => 5]]); +$socket = stream_socket_client("tcp://127.0.0.1:$port", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $context); +var_dump($socket); +stream_set_blocking($socket, true); +var_dump(stream_socket_sendto($socket, "data")); +$data = base64_decode("1oIBAAABAAAAAAAAB2V4YW1wbGUDb3JnAAABAAE="); +stream_set_blocking($socket, 0); +stream_socket_sendto($socket, $data); +stream_socket_shutdown($socket, STREAM_SHUT_RDWR); +stream_socket_shutdown($server, STREAM_SHUT_RDWR); ?> --EXPECTF-- -Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `linger` value in %s on line %d +Warning: stream_socket_client(): Unable to connect to tcp://127.0.0.1:%d (Invalid `linger` value) in %s on line %d bool(false) -Warning: file_get_contents(https://httpbin.org/get): Failed to open stream: Invalid `linger` value in %s on line %d +Warning: stream_socket_client(): Unable to connect to tcp://127.0.0.1:%d (Invalid `linger` value) in %s on line %d bool(false) -bool(true) +resource(%d) of type (stream) +int(4) diff --git a/main/network.c b/main/network.c index 441655e761691..c9d6f4acb2af1 100644 --- a/main/network.c +++ b/main/network.c @@ -470,7 +470,7 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&sockoptval, sizeof(sockoptval)); } #endif -#ifdef SO_LINGER +#ifdef PHP_SO_LINGER if (sockopts & STREAM_SOCKOP_SO_LINGER) { ZEND_ASSERT(option != NULL); long linger = *(long *)option; @@ -478,7 +478,7 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned po .l_onoff = (linger > 0), .l_linger = (int)linger }; - setsockopt(sock, IPPROTO_TCP, SO_LINGER, (char*)&val, sizeof(val)); + setsockopt(sock, IPPROTO_TCP, PHP_SO_LINGER, (char*)&val, sizeof(val)); } #endif @@ -909,7 +909,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short } } #endif -#ifdef SO_LINGER +#ifdef PHP_SO_LINGER { if (sockopts & STREAM_SOCKOP_SO_LINGER) { ZEND_ASSERT(option != NULL); @@ -918,7 +918,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short .l_onoff = linger > 0, .l_linger = (int)linger }; - setsockopt(sock, IPPROTO_TCP, SO_LINGER, (char*)&val, sizeof(val)); + setsockopt(sock, IPPROTO_TCP, PHP_SO_LINGER, (char*)&val, sizeof(val)); } } #endif diff --git a/main/php_network.h b/main/php_network.h index ae5d5eb4c9adf..9a05dc8f21587 100644 --- a/main/php_network.h +++ b/main/php_network.h @@ -54,6 +54,14 @@ # define PHP_IS_TRANSIENT_ERROR(err) (err == EAGAIN) #endif +#ifdef SO_LINGER +# ifdef SO_LINGER_SEC +# define PHP_SO_LINGER SO_LINGER_SEC +# else +# define PHP_SO_LINGER SO_LINGER +# endif +#endif + #ifdef PHP_WIN32 #define php_socket_errno() WSAGetLastError() #else diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 32890d370f822..7bbc88ac02930 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -754,7 +754,7 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * } #endif -#ifdef SO_LINGER +#ifdef PHP_SO_LINGER if (PHP_STREAM_CONTEXT(stream) && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "linger")) != NULL) { bool failed; @@ -857,7 +857,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ } #endif -#ifdef SO_LINGER +#ifdef PHP_SO_LINGER if (PHP_STREAM_CONTEXT(stream) && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "linger")) != NULL) { bool failed;