Skip to content

Commit

Permalink
ext/sockets: Adding TCP_FUNCTION_BLK socket option for FreeBSD.
Browse files Browse the repository at this point in the history
Allows to select an alternate TCP stack. For example with RACK,
a fast loss detection relying on timestamp per packet.

While it works system-wide, it can also apply in an individual socket level too.

close GH-16842
  • Loading branch information
devnexen committed Nov 21, 2024
1 parent f44eaac commit ccda20b
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 1 deletion.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ PHP NEWS
- Sockets:
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
(David Carlier)
. Added TCP_FUNCTION_BLK to change the TCP stack algorithm on FreeBSD.
(David Carlier)

- Standard:
. Fixed crypt() tests on musl when using --with-external-libcrypt
Expand Down
1 change: 1 addition & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ PHP 8.5 UPGRADE NOTES

- Sockets:
. IPPROTO_ICMP/IPPROTO_ICMPV6.
. TCP_FUNCTION_BLK (FreeBSD only).

========================================
11. Changes to INI File Handling
Expand Down
40 changes: 40 additions & 0 deletions ext/sockets/sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -1703,6 +1703,25 @@ PHP_FUNCTION(socket_get_option)
}
}
#endif

#ifdef TCP_FUNCTION_BLK
case TCP_FUNCTION_BLK: {

struct tcp_function_set tsf = {0};
optlen = sizeof(tsf);

if (getsockopt(php_sock->bsd_socket, level, optname, &tsf, &optlen) != 0) {
PHP_SOCKET_ERROR(php_sock, "Unable to retrieve socket option", errno);
RETURN_FALSE;
}

array_init(return_value);

add_assoc_string(return_value, "function_set_name", tsf.function_set_name);
add_assoc_long(return_value, "pcbcnt", tsf.pcbcnt);
return;
}
#endif
}
}

Expand Down Expand Up @@ -1915,6 +1934,27 @@ PHP_FUNCTION(socket_set_option)
RETURN_TRUE;
}
#endif

#ifdef TCP_FUNCTION_BLK
case TCP_FUNCTION_BLK: {
if (Z_TYPE_P(arg4) != IS_STRING) {
php_error_docref(NULL, E_WARNING, "Invalid tcp stack name argument type");
RETURN_FALSE;
}
struct tcp_function_set tfs = {0};
strlcpy(tfs.function_set_name, Z_STRVAL_P(arg4), TCP_FUNCTION_NAME_LEN_MAX);

optlen = sizeof(tfs);
opt_ptr = &tfs;
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

}
}

Expand Down
7 changes: 7 additions & 0 deletions ext/sockets/sockets.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,13 @@
*/
const TCP_KEEPCNT = UNKNOWN;
#endif
#ifdef TCP_FUNCTION_BLK
/**
* @var int
* @cvalue TCP_FUNCTION_BLK
*/
const TCP_FUNCTION_BLK = UNKNOWN;
#endif
/**
* @var int
* @cvalue PHP_NORMAL_READ
Expand Down
5 changes: 4 additions & 1 deletion ext/sockets/sockets_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions ext/sockets/tests/socket_set_option_tsf.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
Test if socket_set_option() works, option:TCP_FUNCTION_BLK
--EXTENSIONS--
sockets
--SKIPIF--
<?php

if (!defined("TCP_FUNCTION_BLK")) {
die('SKIP on platforms not supporting TCP_FUNCTION_BLK');
}
?>
--FILE--
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if (!$socket) {
die('Unable to create AF_INET socket [socket]');
}
socket_set_option( $socket, SOL_TCP, TCP_FUNCTION_BLK, "nochancetoexist");
// TCP/RACK and other alternate stacks are not present by default, at least `freebsd` is.
var_dump(socket_set_option( $socket, SOL_TCP, TCP_FUNCTION_BLK, "freebsd"));
var_dump(socket_get_option( $socket, SOL_TCP, TCP_FUNCTION_BLK));
socket_close($socket);
?>
--EXPECTF--
Warning: socket_set_option(): Unable to set socket option [2]: No such file or directory in %s on line %d
bool(true)
array(2) {
["function_set_name"]=>
string(7) "freebsd"
["pcbcnt"]=>
int(%d)
}

0 comments on commit ccda20b

Please sign in to comment.