diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 3e5084e837642..bec0fcd21eb49 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1981,6 +1981,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_socket_server, 0, 0, 1) ZEND_ARG_INFO(0, context) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO(arginfo_stream_socket_listen, 0) + ZEND_ARG_INFO(0, serverstream) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_socket_accept, 0, 0, 1) ZEND_ARG_INFO(0, serverstream) ZEND_ARG_INFO(0, timeout) @@ -3125,6 +3129,7 @@ const zend_function_entry basic_functions[] = { /* {{{ */ PHP_FE(stream_filter_remove, arginfo_stream_filter_remove) PHP_FE(stream_socket_client, arginfo_stream_socket_client) PHP_FE(stream_socket_server, arginfo_stream_socket_server) + PHP_FE(stream_socket_listen, arginfo_stream_socket_listen) PHP_FE(stream_socket_accept, arginfo_stream_socket_accept) PHP_FE(stream_socket_get_name, arginfo_stream_socket_get_name) PHP_FE(stream_socket_recvfrom, arginfo_stream_socket_recvfrom) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 0610ecfc49fd7..6b0e653dc35cf 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -235,6 +235,40 @@ PHP_FUNCTION(stream_socket_server) } /* }}} */ +/* {{{ proto bool stream_socket_listen(resource serverstream) + Listen for client connections on a socket previously bound via stream_socket_server() */ +PHP_FUNCTION(stream_socket_listen) +{ + php_stream *stream = NULL; + zval *zstream = NULL, **zbacklog = NULL; + int backlog = 32; + char *error_text = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) == FAILURE) { + RETURN_FALSE; + } + + php_stream_from_zval(stream, &zstream); + + if (stream->context && php_stream_context_get_option(stream->context, "socket", "backlog", &zbacklog) == SUCCESS) { + zval *ztmp = *zbacklog; + convert_to_long_ex(&ztmp); + backlog = Z_LVAL_P(ztmp); + if (ztmp != *zbacklog) { + zval_ptr_dtor(&ztmp); + } + } + + if (0 != php_stream_xport_listen(stream, backlog, &error_text TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, error_text == NULL ? "Unknown error" : error_text); + RETURN_FALSE; + } else { + php_stream_to_zval(stream, return_value); + RETURN_TRUE; + } +} +/* }}} */ + /* {{{ proto resource stream_socket_accept(resource serverstream, [ double timeout [, string &peername ]]) Accept a client connection from a server socket */ PHP_FUNCTION(stream_socket_accept) diff --git a/ext/standard/streamsfuncs.h b/ext/standard/streamsfuncs.h index b662de5e4fa9e..250f305b9e1f7 100644 --- a/ext/standard/streamsfuncs.h +++ b/ext/standard/streamsfuncs.h @@ -25,6 +25,7 @@ PHP_FUNCTION(stream_socket_client); PHP_FUNCTION(stream_socket_server); +PHP_FUNCTION(stream_socket_listen); PHP_FUNCTION(stream_socket_accept); PHP_FUNCTION(stream_socket_get_name); PHP_FUNCTION(stream_socket_recvfrom); diff --git a/ext/standard/tests/streams/stream_socket_listen.phpt b/ext/standard/tests/streams/stream_socket_listen.phpt new file mode 100644 index 0000000000000..095dc505082a6 --- /dev/null +++ b/ext/standard/tests/streams/stream_socket_listen.phpt @@ -0,0 +1,40 @@ +--TEST-- +Tests that stream_socket_listen() listens on a previously bound socket +--FILE-- + +===DONE=== + +--EXPECTF-- +bool(true) +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +string(3) "foo" +===DONE=== diff --git a/main/streams/transports.c b/main/streams/transports.c index 2d31074ded807..0ea8796e124bf 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -275,6 +275,9 @@ PHPAPI int php_stream_xport_listen(php_stream *stream, int backlog, char **error } return param.outputs.returncode; + + } else if (ret == PHP_STREAM_OPTION_RETURN_NOTIMPL) { + *error_text = "listening not supported on this stream"; } return ret;