Skip to content

Commit ccda20b

Browse files
committed
ext/sockets: Adding TCP_FUNCTION_BLK socket option for FreeBSD.
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 phpGH-16842
1 parent f44eaac commit ccda20b

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ PHP NEWS
5252
- Sockets:
5353
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.
5454
(David Carlier)
55+
. Added TCP_FUNCTION_BLK to change the TCP stack algorithm on FreeBSD.
56+
(David Carlier)
5557

5658
- Standard:
5759
. Fixed crypt() tests on musl when using --with-external-libcrypt

UPGRADING

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ PHP 8.5 UPGRADE NOTES
137137

138138
- Sockets:
139139
. IPPROTO_ICMP/IPPROTO_ICMPV6.
140+
. TCP_FUNCTION_BLK (FreeBSD only).
140141

141142
========================================
142143
11. Changes to INI File Handling

ext/sockets/sockets.c

+40
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,25 @@ PHP_FUNCTION(socket_get_option)
17031703
}
17041704
}
17051705
#endif
1706+
1707+
#ifdef TCP_FUNCTION_BLK
1708+
case TCP_FUNCTION_BLK: {
1709+
1710+
struct tcp_function_set tsf = {0};
1711+
optlen = sizeof(tsf);
1712+
1713+
if (getsockopt(php_sock->bsd_socket, level, optname, &tsf, &optlen) != 0) {
1714+
PHP_SOCKET_ERROR(php_sock, "Unable to retrieve socket option", errno);
1715+
RETURN_FALSE;
1716+
}
1717+
1718+
array_init(return_value);
1719+
1720+
add_assoc_string(return_value, "function_set_name", tsf.function_set_name);
1721+
add_assoc_long(return_value, "pcbcnt", tsf.pcbcnt);
1722+
return;
1723+
}
1724+
#endif
17061725
}
17071726
}
17081727

@@ -1915,6 +1934,27 @@ PHP_FUNCTION(socket_set_option)
19151934
RETURN_TRUE;
19161935
}
19171936
#endif
1937+
1938+
#ifdef TCP_FUNCTION_BLK
1939+
case TCP_FUNCTION_BLK: {
1940+
if (Z_TYPE_P(arg4) != IS_STRING) {
1941+
php_error_docref(NULL, E_WARNING, "Invalid tcp stack name argument type");
1942+
RETURN_FALSE;
1943+
}
1944+
struct tcp_function_set tfs = {0};
1945+
strlcpy(tfs.function_set_name, Z_STRVAL_P(arg4), TCP_FUNCTION_NAME_LEN_MAX);
1946+
1947+
optlen = sizeof(tfs);
1948+
opt_ptr = &tfs;
1949+
if (setsockopt(php_sock->bsd_socket, level, optname, opt_ptr, optlen) != 0) {
1950+
PHP_SOCKET_ERROR(php_sock, "Unable to set socket option", errno);
1951+
RETURN_FALSE;
1952+
}
1953+
1954+
RETURN_TRUE;
1955+
}
1956+
#endif
1957+
19181958
}
19191959
}
19201960

ext/sockets/sockets.stub.php

+7
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,13 @@
640640
*/
641641
const TCP_KEEPCNT = UNKNOWN;
642642
#endif
643+
#ifdef TCP_FUNCTION_BLK
644+
/**
645+
* @var int
646+
* @cvalue TCP_FUNCTION_BLK
647+
*/
648+
const TCP_FUNCTION_BLK = UNKNOWN;
649+
#endif
643650
/**
644651
* @var int
645652
* @cvalue PHP_NORMAL_READ

ext/sockets/sockets_arginfo.h

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Test if socket_set_option() works, option:TCP_FUNCTION_BLK
3+
--EXTENSIONS--
4+
sockets
5+
--SKIPIF--
6+
<?php
7+
8+
if (!defined("TCP_FUNCTION_BLK")) {
9+
die('SKIP on platforms not supporting TCP_FUNCTION_BLK');
10+
}
11+
?>
12+
--FILE--
13+
<?php
14+
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
15+
16+
if (!$socket) {
17+
die('Unable to create AF_INET socket [socket]');
18+
}
19+
socket_set_option( $socket, SOL_TCP, TCP_FUNCTION_BLK, "nochancetoexist");
20+
// TCP/RACK and other alternate stacks are not present by default, at least `freebsd` is.
21+
var_dump(socket_set_option( $socket, SOL_TCP, TCP_FUNCTION_BLK, "freebsd"));
22+
var_dump(socket_get_option( $socket, SOL_TCP, TCP_FUNCTION_BLK));
23+
socket_close($socket);
24+
?>
25+
--EXPECTF--
26+
Warning: socket_set_option(): Unable to set socket option [2]: No such file or directory in %s on line %d
27+
bool(true)
28+
array(2) {
29+
["function_set_name"]=>
30+
string(7) "freebsd"
31+
["pcbcnt"]=>
32+
int(%d)
33+
}

0 commit comments

Comments
 (0)