Adds TCP_CONGESTION socket option for Linux/FreeBSD.

Closes #8824.
This commit is contained in:
David Carlier 2022-06-18 19:16:49 +01:00
parent f26f6d9479
commit a193427333
3 changed files with 77 additions and 0 deletions

3
NEWS
View File

@ -7,6 +7,9 @@ PHP NEWS
IP-relative calls and jumps.
(Su Tao, Wang Xue, Chen Hu, Lizhen Lizhen, Dmitry)
- Sockets:
. Added TCP_CONGESTION socket option. (David Carlier)
- Zip:
. Implement fseek for zip stream when possible with libzip 1.9.1. (Remi)

View File

@ -627,6 +627,9 @@ static PHP_MINIT_FUNCTION(sockets)
REGISTER_LONG_CONSTANT("SKF_AD_MAX", SKF_AD_MAX, CONST_CS | CONST_PERSISTENT);
#endif
#ifdef TCP_CONGESTION
REGISTER_LONG_CONSTANT("TCP_CONGESTION", TCP_CONGESTION, CONST_CS | CONST_PERSISTENT);
#endif
#ifdef TCP_NODELAY
REGISTER_LONG_CONSTANT("TCP_NODELAY", TCP_NODELAY, CONST_CS | CONST_PERSISTENT);
#endif
@ -1883,6 +1886,26 @@ PHP_FUNCTION(socket_get_option)
}
#endif
if (level == IPPROTO_TCP) {
switch (optname) {
#ifdef TCP_CONGESTION
case TCP_CONGESTION: {
char name[16];
optlen = sizeof(name);
if (getsockopt(php_sock->bsd_socket, level, optname, name, &optlen) != 0) {
PHP_SOCKET_ERROR(php_sock, "Unable to retrieve socket option", errno);
RETURN_FALSE;
} else {
array_init(return_value);
add_assoc_string(return_value, "name", name);
return;
}
}
#endif
}
}
if (level == SOL_SOCKET) {
switch (optname) {
case SO_LINGER:
@ -2040,6 +2063,28 @@ PHP_FUNCTION(socket_set_option)
}
#endif
if (level == IPPROTO_TCP) {
switch (optname) {
#ifdef TCP_CONGESTION
case TCP_CONGESTION: {
if (Z_TYPE_P(arg4) == IS_STRING) {
opt_ptr = Z_STRVAL_P(arg4);
optlen = Z_STRLEN_P(arg4);
} else {
opt_ptr = "";
optlen = 0;
}
if (setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen) != 0) {
PHP_SOCKET_ERROR(php_sock, "Unable to set socket option", errno);
RETURN_FALSE;
}
RETURN_TRUE;
}
#endif
}
}
switch (optname) {
case SO_LINGER: {
const char l_onoff_key[] = "l_onoff";

View File

@ -0,0 +1,29 @@
--TEST--
Test TCP_CONGESTION constant with allowed algos for unprivileged accounts.
--EXTENSIONS--
sockets
--SKIPIF--
<?php
if (!defined('TCP_CONGESTION')) {
die('skip TCP_CONGESTION test');
}
--FILE--
<?php
if (str_contains(PHP_OS, 'Linux')) {
$algo = 'cubic';
} else {
$algo = 'newreno';
}
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$socket) die ("socket failed");
$r = socket_get_option($socket, SOL_TCP, TCP_CONGESTION);
echo "current tcp congestion algo " . $r['name'] . "\n";
var_dump(socket_set_option($socket, SOL_TCP, TCP_CONGESTION, $algo));
$r = socket_get_option($socket, SOL_TCP, TCP_CONGESTION);
echo "new tcp congestion algo " . $r['name'];
?>
--EXPECTF--
current tcp congestion algo %s
bool(true)
new tcp congestion algo %s