mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix TCP_KEEPALIVE no inheriting for accepted sockets on MacOS
This commit is contained in:
@@ -2219,25 +2219,32 @@ static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb)
|
||||
static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock,
|
||||
php_stream_xport_param *xparam STREAMS_DC) /* {{{ */
|
||||
{
|
||||
bool nodelay = false;
|
||||
php_sockvals sockvals = {0};
|
||||
zval *tmpzval = NULL;
|
||||
|
||||
xparam->outputs.client = NULL;
|
||||
|
||||
if (PHP_STREAM_CONTEXT(stream) &&
|
||||
(tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL &&
|
||||
zend_is_true(tmpzval)) {
|
||||
nodelay = true;
|
||||
if (PHP_STREAM_CONTEXT(stream)) {
|
||||
tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay");
|
||||
if (tmpzval != NULL && zend_is_true(tmpzval)) {
|
||||
sockvals.mask |= PHP_SOCKVAL_TCP_NODELAY;
|
||||
sockvals.tcp_nodelay = 1;
|
||||
}
|
||||
tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_keepidle");
|
||||
if (tmpzval != NULL && Z_TYPE_P(tmpzval) == IS_LONG) {
|
||||
sockvals.mask |= PHP_SOCKVAL_TCP_KEEPIDLE;
|
||||
sockvals.keepalive.keepidle = Z_LVAL_P(tmpzval);
|
||||
}
|
||||
}
|
||||
|
||||
php_socket_t clisock = php_network_accept_incoming(sock->s.socket,
|
||||
php_socket_t clisock = php_network_accept_incoming_ex(sock->s.socket,
|
||||
xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
|
||||
xparam->want_addr ? &xparam->outputs.addr : NULL,
|
||||
xparam->want_addr ? &xparam->outputs.addrlen : NULL,
|
||||
xparam->inputs.timeout,
|
||||
xparam->want_errortext ? &xparam->outputs.error_text : NULL,
|
||||
&xparam->outputs.error_code,
|
||||
nodelay);
|
||||
&sockvals);
|
||||
|
||||
if (clisock != SOCK_ERR) {
|
||||
php_openssl_netstream_data_t *clisockdata = (php_openssl_netstream_data_t*) emalloc(sizeof(*clisockdata));
|
||||
|
||||
@@ -801,15 +801,22 @@ PHPAPI int php_network_get_sock_name(php_socket_t sock,
|
||||
* version of the address will be emalloc'd and returned.
|
||||
* */
|
||||
|
||||
/* {{{ php_network_accept_incoming */
|
||||
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
|
||||
/* Accept a client connection from a server socket,
|
||||
* using an optional timeout.
|
||||
* Returns the peer address in addr/addrlen (it will emalloc
|
||||
* these, so be sure to efree the result).
|
||||
* If you specify textaddr, a text-printable
|
||||
* version of the address will be emalloc'd and returned.
|
||||
* */
|
||||
|
||||
PHPAPI php_socket_t php_network_accept_incoming_ex(php_socket_t srvsock,
|
||||
zend_string **textaddr,
|
||||
struct sockaddr **addr,
|
||||
socklen_t *addrlen,
|
||||
struct timeval *timeout,
|
||||
zend_string **error_string,
|
||||
int *error_code,
|
||||
int tcp_nodelay
|
||||
php_sockvals *sockvals
|
||||
)
|
||||
{
|
||||
php_socket_t clisock = -1;
|
||||
@@ -833,11 +840,19 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
|
||||
textaddr,
|
||||
addr, addrlen
|
||||
);
|
||||
if (tcp_nodelay) {
|
||||
#ifdef TCP_NODELAY
|
||||
if (PHP_SOCKVAL_IS_SET(sockvals, PHP_SOCKVAL_TCP_NODELAY)) {
|
||||
int tcp_nodelay = 1;
|
||||
setsockopt(clisock, IPPROTO_TCP, TCP_NODELAY, (char*)&tcp_nodelay, sizeof(tcp_nodelay));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef TCP_KEEPALIVE
|
||||
/* MacOS does not inherit TCP_KEEPALIVE so it needs to be set */
|
||||
if (PHP_SOCKVAL_IS_SET(sockvals, PHP_SOCKVAL_TCP_KEEPIDLE)) {
|
||||
setsockopt(clisock, IPPROTO_TCP, TCP_KEEPALIVE,
|
||||
(char*)&sockvals->keepalive.keepidle, sizeof(sockvals->keepalive.keepidle));
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
error = php_socket_errno();
|
||||
}
|
||||
@@ -852,7 +867,22 @@ PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
|
||||
|
||||
return clisock;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
|
||||
zend_string **textaddr,
|
||||
struct sockaddr **addr,
|
||||
socklen_t *addrlen,
|
||||
struct timeval *timeout,
|
||||
zend_string **error_string,
|
||||
int *error_code,
|
||||
int tcp_nodelay
|
||||
)
|
||||
{
|
||||
php_sockvals sockvals = { .mask = tcp_nodelay ? PHP_SOCKVAL_TCP_NODELAY : 0 };
|
||||
|
||||
return php_network_accept_incoming_ex(srvsock, textaddr, addr, addrlen, timeout, error_string,
|
||||
error_code, &sockvals);
|
||||
}
|
||||
|
||||
/* Connect to a remote host using an interruptible connect with optional timeout.
|
||||
* Optionally, the connect can be made asynchronously, which will implicitly
|
||||
|
||||
@@ -267,12 +267,16 @@ typedef struct {
|
||||
} php_sockaddr_storage;
|
||||
#endif
|
||||
|
||||
#define PHP_SOCKVAL_TCP_KEEPIDLE (1 << 0)
|
||||
#define PHP_SOCKVAL_TCP_KEEPCNT (1 << 1)
|
||||
#define PHP_SOCKVAL_TCP_KEEPINTVL (1 << 2)
|
||||
#define PHP_SOCKVAL_TCP_NODELAY (1 << 0)
|
||||
#define PHP_SOCKVAL_TCP_KEEPIDLE (1 << 1)
|
||||
#define PHP_SOCKVAL_TCP_KEEPCNT (1 << 2)
|
||||
#define PHP_SOCKVAL_TCP_KEEPINTVL (1 << 3)
|
||||
|
||||
#define PHP_SOCKVAL_IS_SET(sockvals, opt) (sockvals->mask & opt)
|
||||
|
||||
typedef struct {
|
||||
unsigned int mask;
|
||||
int tcp_nodelay;
|
||||
struct {
|
||||
int keepidle;
|
||||
int keepcnt;
|
||||
@@ -313,6 +317,16 @@ PHPAPI php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsi
|
||||
int socktype, long sockopts, zend_string **error_string, int *error_code
|
||||
);
|
||||
|
||||
PHPAPI php_socket_t php_network_accept_incoming_ex(php_socket_t srvsock,
|
||||
zend_string **textaddr,
|
||||
struct sockaddr **addr,
|
||||
socklen_t *addrlen,
|
||||
struct timeval *timeout,
|
||||
zend_string **error_string,
|
||||
int *error_code,
|
||||
php_sockvals *sockvals
|
||||
);
|
||||
|
||||
PHPAPI php_socket_t php_network_accept_incoming(php_socket_t srvsock,
|
||||
zend_string **textaddr,
|
||||
struct sockaddr **addr,
|
||||
|
||||
@@ -964,25 +964,32 @@ out:
|
||||
static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t *sock,
|
||||
php_stream_xport_param *xparam STREAMS_DC)
|
||||
{
|
||||
bool nodelay = 0;
|
||||
php_sockvals sockvals = {0};
|
||||
zval *tmpzval = NULL;
|
||||
|
||||
xparam->outputs.client = NULL;
|
||||
|
||||
if ((NULL != PHP_STREAM_CONTEXT(stream)) &&
|
||||
(tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL &&
|
||||
zend_is_true(tmpzval)) {
|
||||
nodelay = 1;
|
||||
if (PHP_STREAM_CONTEXT(stream)) {
|
||||
tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay");
|
||||
if (tmpzval != NULL && zend_is_true(tmpzval)) {
|
||||
sockvals.mask |= PHP_SOCKVAL_TCP_NODELAY;
|
||||
sockvals.tcp_nodelay = 1;
|
||||
}
|
||||
tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_keepidle");
|
||||
if (tmpzval != NULL && Z_TYPE_P(tmpzval) == IS_LONG) {
|
||||
sockvals.mask |= PHP_SOCKVAL_TCP_KEEPIDLE;
|
||||
sockvals.keepalive.keepidle = Z_LVAL_P(tmpzval);
|
||||
}
|
||||
}
|
||||
|
||||
php_socket_t clisock = php_network_accept_incoming(sock->socket,
|
||||
php_socket_t clisock = php_network_accept_incoming_ex(sock->socket,
|
||||
xparam->want_textaddr ? &xparam->outputs.textaddr : NULL,
|
||||
xparam->want_addr ? &xparam->outputs.addr : NULL,
|
||||
xparam->want_addr ? &xparam->outputs.addrlen : NULL,
|
||||
xparam->inputs.timeout,
|
||||
xparam->want_errortext ? &xparam->outputs.error_text : NULL,
|
||||
&xparam->outputs.error_code,
|
||||
nodelay);
|
||||
&sockvals);
|
||||
|
||||
if (clisock != SOCK_ERR) {
|
||||
php_netstream_data_t *clisockdata = (php_netstream_data_t*) emalloc(sizeof(*clisockdata));
|
||||
|
||||
Reference in New Issue
Block a user