summaryrefslogtreecommitdiff
path: root/main/streams/xp_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/streams/xp_socket.c')
-rw-r--r--main/streams/xp_socket.c93
1 files changed, 64 insertions, 29 deletions
diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c
index 13ed703682..cc76ace510 100644
--- a/main/streams/xp_socket.c
+++ b/main/streams/xp_socket.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2015 The PHP Group |
+ | Copyright (c) 1997-2016 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -77,10 +77,10 @@ retry:
didwrite = send(sock->socket, buf, XP_SOCK_BUF_SIZE(count), (sock->is_blocked && ptimeout) ? MSG_DONTWAIT : 0);
if (didwrite <= 0) {
- long err = php_socket_errno();
+ int err = php_socket_errno();
char *estr;
- if (sock->is_blocked && err == EWOULDBLOCK) {
+ if (sock->is_blocked && (err == EWOULDBLOCK || err == EAGAIN)) {
int retval;
sock->timeout_event = 0;
@@ -152,6 +152,7 @@ static size_t php_sockop_read(php_stream *stream, char *buf, size_t count)
{
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
ssize_t nr_bytes = 0;
+ int err;
if (!sock || sock->socket == -1) {
return 0;
@@ -164,8 +165,9 @@ static size_t php_sockop_read(php_stream *stream, char *buf, size_t count)
}
nr_bytes = recv(sock->socket, buf, XP_SOCK_BUF_SIZE(count), (sock->is_blocked && sock->timeout.tv_sec != -1) ? MSG_DONTWAIT : 0);
+ err = php_socket_errno();
- stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && php_socket_errno() != EWOULDBLOCK));
+ stream->eof = (nr_bytes == 0 || (nr_bytes == -1 && err != EWOULDBLOCK && err != EAGAIN));
if (nr_bytes > 0) {
php_stream_notify_progress_increment(PHP_STREAM_CONTEXT(stream), nr_bytes, 0);
@@ -314,7 +316,17 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void
if (sock->socket == -1) {
alive = 0;
} else if (php_pollfd_for(sock->socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
- if (0 >= recv(sock->socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EWOULDBLOCK) {
+#ifdef PHP_WIN32
+ int ret;
+#else
+ ssize_t ret;
+#endif
+ int err;
+
+ ret = recv(sock->socket, &buf, sizeof(buf), MSG_PEEK);
+ err = php_socket_errno();
+ if (0 == ret || /* the counterpart did properly shutdown*/
+ (0 > ret && err != EWOULDBLOCK && err != EAGAIN)) { /* there was an unrecoverable error */
alive = 0;
}
}
@@ -623,6 +635,16 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *
return -1;
}
+#ifdef IPV6_V6ONLY
+ if (PHP_STREAM_CONTEXT(stream)
+ && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "ipv6_v6only")) != NULL
+ && Z_TYPE_P(tmpzval) != IS_NULL
+ ) {
+ sockopts |= STREAM_SOCKOP_IPV6_V6ONLY;
+ sockopts |= STREAM_SOCKOP_IPV6_V6ONLY_ENABLED * zend_is_true(tmpzval);
+ }
+#endif
+
#ifdef SO_REUSEPORT
if (PHP_STREAM_CONTEXT(stream)
&& (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "so_reuseport")) != NULL
@@ -720,6 +742,18 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_
}
#endif
+ if (stream->ops != &php_stream_udp_socket_ops /* TCP_NODELAY is only applicable for TCP */
+#ifdef AF_UNIX
+ && stream->ops != &php_stream_unix_socket_ops
+ && stream->ops != &php_stream_unixdg_socket_ops
+#endif
+ && PHP_STREAM_CONTEXT(stream)
+ && (tmpzval = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "tcp_nodelay")) != NULL
+ && zend_is_true(tmpzval)
+ ) {
+ sockopts |= STREAM_SOCKOP_TCP_NODELAY;
+ }
+
/* 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. */
@@ -761,36 +795,37 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t
php_stream_xport_param *xparam STREAMS_DC)
{
int clisock;
+ zend_bool nodelay = 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;
+ }
+
clisock = php_network_accept_incoming(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
- );
+ 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);
if (clisock >= 0) {
- php_netstream_data_t *clisockdata;
-
- clisockdata = emalloc(sizeof(*clisockdata));
-
- if (clisockdata == NULL) {
- close(clisock);
- /* technically a fatal error */
- } else {
- memcpy(clisockdata, sock, sizeof(*clisockdata));
- clisockdata->socket = clisock;
-
- xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
- if (xparam->outputs.client) {
- xparam->outputs.client->ctx = stream->ctx;
- if (stream->ctx) {
- GC_REFCOUNT(stream->ctx)++;
- }
+ php_netstream_data_t *clisockdata = (php_netstream_data_t*) emalloc(sizeof(*clisockdata));
+
+ memcpy(clisockdata, sock, sizeof(*clisockdata));
+ clisockdata->socket = clisock;
+
+ xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+");
+ if (xparam->outputs.client) {
+ xparam->outputs.client->ctx = stream->ctx;
+ if (stream->ctx) {
+ GC_REFCOUNT(stream->ctx)++;
}
}
}