com php-src: Add SO_REUSEPORT + SO_BROADCAST support via socket stream context option: ext/ftp/ftp. c main/network.c main/php_network.h
main/streams/xp _socket.c
| From: | rdlowrey@php.net | Date: | Wed, 06 Aug 2014 02:43:12 +0000 |
| Subject: | com php-src: Add SO_REUSEPORT + SO_BROADCAST support via socket stream context option: ext/ftp/ftp. c main/network.c main/php_network.h main/streams/xp _socket.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-79742@lists.php.net to get a copy of this message | ||
Commit: 60552a887104e83c7e6425f0625ffa9d19e5a8dc
Author: Daniel Lowrey <rdlowrey@php.net> Mon, 4 Aug 2014 12:41:51 -0400
Parents: 29eb0ea68605e81822e34d5a95443f2c176b2c73
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=60552a887104e83c7e6425f0625ffa9d19e5a8dc
Log:
Add SO_REUSEPORT + SO_BROADCAST support via socket stream context option
Changed paths:
M ext/ftp/ftp.c
M main/network.c
M main/php_network.h
M main/streams/xp_socket.c
Diff:
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 558463b..d05f0ee 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -136,7 +136,7 @@ ftp_open(const char *host, short port, long timeout_sec TSRMLS_DC)
ftp->fd = php_network_connect_socket_to_host(host,
(unsigned short) (port ? port : 21), SOCK_STREAM,
- 0, &tv, NULL, NULL, NULL, 0 TSRMLS_CC);
+ 0, &tv, NULL, NULL, NULL, 0, STREAM_SOCKOP_NONE TSRMLS_CC);
if (ftp->fd == -1) {
goto bail;
}
diff --git a/main/network.c b/main/network.c
index fc2a94b..39f5a22 100644
--- a/main/network.c
+++ b/main/network.c
@@ -416,13 +416,14 @@ 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, char **error_string, int *error_code
+ int socktype, long sockopts, char **error_string, int *error_code
TSRMLS_DC)
{
int num_addrs, n, err = 0;
php_socket_t sock;
struct sockaddr **sal, **psal, *sa;
socklen_t socklen;
+ int sockoptval = 1;
num_addrs = php_network_getaddresses(host, socktype, &psal, error_string TSRMLS_CC);
@@ -464,9 +465,16 @@ php_socket_t php_network_bind_socket_to_local_addr(const char *host, unsigned
po
/* attempt to bind */
#ifdef SO_REUSEADDR
- {
- int val = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&val, sizeof(val));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&sockoptval, sizeof(sockoptval));
+#endif
+#ifdef SO_REUSEPORT
+ if (sockopts & STREAM_SOCKOP_SO_REUSEPORT) {
+ setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&sockoptval, sizeof(sockoptval));
+ }
+#endif
+#ifdef SO_BROADCAST
+ if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&sockoptval, sizeof(sockoptval));
}
#endif
@@ -762,7 +770,7 @@ 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, char **error_string,
- int *error_code, char *bindto, unsigned short bindport
+ int *error_code, char *bindto, unsigned short bindport, long sockopts
TSRMLS_DC)
{
int num_addrs, n, fatal = 0;
@@ -864,6 +872,7 @@ php_socket_t php_network_connect_socket_to_host(const char *host, unsigned short
}
}
#endif
+
if (!local_address || bind(sock, local_address, local_address_len)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to bind to '%s:%d', system
said: %s", bindto, bindport, strerror(errno));
}
@@ -878,6 +887,14 @@ skip_bind:
*error_string = NULL;
}
+#ifdef SO_BROADCAST
+ {
+ int val = 1;
+ if (sockopts & STREAM_SOCKOP_SO_BROADCAST) {
+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&val, sizeof(val));
+ }
+ }
+#endif
n = php_network_connect_socket(sock, sa, socklen, asynchronous,
timeout ? &working_timeout : NULL,
error_string, error_code);
diff --git a/main/php_network.h b/main/php_network.h
index d69bba3..95299e6 100644
--- a/main/php_network.h
+++ b/main/php_network.h
@@ -105,6 +105,11 @@ typedef int php_socket_t;
# define SOCK_RECV_ERR -1
#endif
+#define STREAM_SOCKOP_NONE 1 << 0
+#define STREAM_SOCKOP_SO_REUSEPORT 1 << 1
+#define STREAM_SOCKOP_SO_BROADCAST 1 << 2
+
+
/* uncomment this to debug poll(2) emulation on systems that have poll(2) */
/* #define PHP_USE_POLL_2_EMULATION 1 */
@@ -229,7 +234,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, char **error_string,
- int *error_code, char *bindto, unsigned short bindport
+ int *error_code, char *bindto, unsigned short bindport, long sockopts
TSRMLS_DC);
PHPAPI int php_network_connect_socket(php_socket_t sockfd,
@@ -244,7 +249,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, char **error_string, int *error_code
+ int socktype, long sockopts, char **error_string, int *error_code
TSRMLS_DC);
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 a6dc115..c7b5a70 100644
--- a/main/streams/xp_socket.c
+++ b/main/streams/xp_socket.c
@@ -570,6 +570,8 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *
{
char *host = NULL;
int portno, err;
+ long sockopts = STREAM_SOCKOP_NONE;
+ zval **tmpzval = NULL;
#ifdef AF_UNIX
if (stream->ops == &php_stream_unix_socket_ops || stream->ops ==
&php_stream_unixdg_socket_ops) {
@@ -599,8 +601,28 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t
*
return -1;
}
+#ifdef SO_REUSEPORT
+ if (stream->context
+ && php_stream_context_get_option(stream->context, "socket",
"so_reuseport", &tmpzval) == SUCCESS
+ && zend_is_true(*tmpzval)
+ ) {
+ sockopts |= STREAM_SOCKOP_SO_REUSEPORT;
+ }
+#endif
+
+#ifdef SO_BROADCAST
+ if (&php_stream_udp_socket_ops /* SO_BROADCAST is only applicable for UDP */
+ && stream->context
+ && php_stream_context_get_option(stream->context, "socket",
"so_broadcast", &tmpzval) == SUCCESS
+ && zend_is_true(*tmpzval)
+ ) {
+ sockopts |= STREAM_SOCKOP_SO_BROADCAST;
+ }
+#endif
+
sock->socket = php_network_bind_socket_to_local_addr(host, portno,
stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM : SOCK_STREAM,
+ sockopts,
xparam->want_errortext ? &xparam->outputs.error_text : NULL,
&err
TSRMLS_CC);
@@ -620,6 +642,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_
int err = 0;
int ret;
zval **tmpzval = NULL;
+ long sockopts = STREAM_SOCKOP_NONE;
#ifdef AF_UNIX
if (stream->ops == &php_stream_unix_socket_ops || stream->ops ==
&php_stream_unixdg_socket_ops) {
@@ -665,6 +688,16 @@ static inline int php_tcp_sockop_connect(php_stream *stream,
php_netstream_data_
bindto = parse_ip_address_ex(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), &bindport,
xparam->want_errortext, &xparam->outputs.error_text TSRMLS_CC);
}
+#ifdef SO_BROADCAST
+ if (&php_stream_udp_socket_ops /* SO_BROADCAST is only applicable for UDP */
+ && stream->context
+ && php_stream_context_get_option(stream->context, "socket",
"so_broadcast", &tmpzval) == SUCCESS
+ && zend_is_true(*tmpzval)
+ ) {
+ sockopts |= STREAM_SOCKOP_SO_BROADCAST;
+ }
+#endif
+
/* Note: the test here for php_stream_udp_socket_ops is important, because we
* want the default to be TCP sockets so that the openssl extension can
* re-use this code. */
@@ -676,7 +709,8 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_
xparam->want_errortext ? &xparam->outputs.error_text : NULL,
&err,
bindto,
- bindport
+ bindport,
+ sockopts
TSRMLS_CC);
ret = sock->socket == -1 ? -1 : 0;