From: Dmitry Stogov Date: Tue, 19 Dec 2006 08:58:58 +0000 (+0000) Subject: Added function stream_socket_shutdown(). It is a wraper for system shutdown() functio... X-Git-Tag: php-5.2.1RC2~161 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03312cc0d9594b1c70cb563a8e3450be5cc6f505;p=php Added function stream_socket_shutdown(). It is a wraper for system shutdown() function, that shut downs part of a full-duplex connection --- diff --git a/NEWS b/NEWS index 81d7a2b96a..afb8a502ad 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? Dec 2006, PHP 5.2.1RC2 +- Added function stream_socket_shutdown(). It is a wraper for system shutdown() + function, that shut downs part of a full-duplex connection. (Dmitry) - Added internal heap protection (Dmitry) . safe unlinking . cookies diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 65de5bc149..fec5918e15 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2443,6 +2443,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_socket_enable_crypto, 0, 0, 2) ZEND_ARG_INFO(0, cryptokind) ZEND_ARG_INFO(0, sessionstream) ZEND_END_ARG_INFO() + +#ifdef HAVE_SHUTDOWN +static +ZEND_BEGIN_ARG_INFO(arginfo_stream_socket_shutdown, 0) + ZEND_ARG_INFO(0, stream) + ZEND_ARG_INFO(0, how) +ZEND_END_ARG_INFO() +#endif /* }}} */ /* {{{ string.c */ static @@ -3517,6 +3525,9 @@ zend_function_entry basic_functions[] = { PHP_FE(stream_socket_recvfrom, arginfo_stream_socket_recvfrom) PHP_FE(stream_socket_sendto, arginfo_stream_socket_sendto) PHP_FE(stream_socket_enable_crypto, arginfo_stream_socket_enable_crypto) +#ifdef HAVE_SHUTDOWN + PHP_FE(stream_socket_shutdown, arginfo_stream_socket_shutdown) +#endif #if HAVE_SOCKETPAIR PHP_FE(stream_socket_pair, arginfo_stream_socket_pair) #endif diff --git a/ext/standard/file.c b/ext/standard/file.c index 6c98b541a8..8eafe896b1 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -228,6 +228,10 @@ PHP_MINIT_FUNCTION(file) REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER", STREAM_CRYPTO_METHOD_SSLv23_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER", STREAM_CRYPTO_METHOD_TLS_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_SHUT_RD", STREAM_SHUT_RD, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_SHUT_WR", STREAM_SHUT_WR, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_SHUT_RDWR", STREAM_SHUT_RDWR, CONST_CS|CONST_PERSISTENT); + #ifdef PF_INET REGISTER_LONG_CONSTANT("STREAM_PF_INET", PF_INET, CONST_CS|CONST_PERSISTENT); #elif defined(AF_INET) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index df29974952..3fbc4dd6ba 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -1341,6 +1341,36 @@ PHP_FUNCTION(stream_socket_enable_crypto) } /* }}} */ +#ifdef HAVE_SHUTDOWN +/* {{{ proto int stream_socket_shutdown(resource stream, int how) + causes all or part of a full-duplex connection on the socket associated + with stream to be shut down. If how is SHUT_RD, further receptions will + be disallowed. If how is SHUT_WR, further transmissions will be disallowed. + If how is SHUT_RDWR, further receptions and transmissions will be + disallowed. */ +PHP_FUNCTION(stream_socket_shutdown) +{ + long how; + zval *zstream; + php_stream *stream; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zstream, &how) == FAILURE) { + RETURN_FALSE; + } + + if (how != STREAM_SHUT_RD && + how != STREAM_SHUT_WR && + how != STREAM_SHUT_RDWR) { + RETURN_FALSE; + } + + php_stream_from_zval(stream, &zstream); + + RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how TSRMLS_CC) == 0); +} +#endif +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/ext/standard/streamsfuncs.h b/ext/standard/streamsfuncs.h index 57c5e0290a..017b56f4a1 100644 --- a/ext/standard/streamsfuncs.h +++ b/ext/standard/streamsfuncs.h @@ -53,6 +53,7 @@ PHP_FUNCTION(stream_filter_prepend); PHP_FUNCTION(stream_filter_append); PHP_FUNCTION(stream_filter_remove); PHP_FUNCTION(stream_socket_enable_crypto); +PHP_FUNCTION(stream_socket_shutdown); PHP_FUNCTION(stream_socket_pair); /* diff --git a/ext/standard/tests/network/shutdown.phpt b/ext/standard/tests/network/shutdown.phpt new file mode 100755 index 0000000000..f9ab66476f --- /dev/null +++ b/ext/standard/tests/network/shutdown.phpt @@ -0,0 +1,65 @@ +--TEST-- +stream_socket_shutdown() test on IPv4 TCP Loopback +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Client 1 +Client 2 diff --git a/main/streams/php_stream_transport.h b/main/streams/php_stream_transport.h index f9da47bee7..0252ec3ea8 100644 --- a/main/streams/php_stream_transport.h +++ b/main/streams/php_stream_transport.h @@ -104,8 +104,19 @@ PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t bufle * sending it as OOB data */ PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t buflen, long flags, void *addr, socklen_t addrlen TSRMLS_DC); + +typedef enum { + STREAM_SHUT_RD, + STREAM_SHUT_WR, + STREAM_SHUT_RDWR +} stream_shutdown_t; + +/* Similar to shutdown() system call; shut down part of a full-duplex + * connection */ +PHPAPI int php_stream_xport_shutdown(php_stream *stream, stream_shutdown_t how TSRMLS_DC); END_EXTERN_C() + /* Structure definition for the set_option interface that the above functions wrap */ typedef struct _php_stream_xport_param { @@ -116,11 +127,13 @@ typedef struct _php_stream_xport_param { STREAM_XPORT_OP_GET_NAME, STREAM_XPORT_OP_GET_PEER_NAME, STREAM_XPORT_OP_RECV, - STREAM_XPORT_OP_SEND + STREAM_XPORT_OP_SEND, + STREAM_XPORT_OP_SHUTDOWN } op; unsigned int want_addr:1; unsigned int want_textaddr:1; unsigned int want_errortext:1; + stream_shutdown_t how:3; struct { char *name; diff --git a/main/streams/transports.c b/main/streams/transports.c index c10a4acfcf..54375b74ee 100644 --- a/main/streams/transports.c +++ b/main/streams/transports.c @@ -486,6 +486,25 @@ PHPAPI int php_stream_xport_sendto(php_stream *stream, const char *buf, size_t b return -1; } +/* Similar to shutdown() system call; shut down part of a full-duplex + * connection */ +PHPAPI int php_stream_xport_shutdown(php_stream *stream, stream_shutdown_t how TSRMLS_DC) +{ + php_stream_xport_param param; + int ret = 0; + + memset(¶m, 0, sizeof(param)); + + param.op = STREAM_XPORT_OP_SHUTDOWN; + param.how = how; + + ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); + + if (ret == PHP_STREAM_OPTION_RETURN_OK) { + return param.outputs.returncode; + } + return -1; +} /* * Local variables: diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index af2a060cff..6528a95b64 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -369,6 +369,24 @@ static int php_sockop_set_option(php_stream *stream, int option, int value, void return PHP_STREAM_OPTION_RETURN_OK; +#ifdef HAVE_SHUTDOWN +# ifndef SHUT_RD +# define SHUT_RD 0 +# endif +# ifndef SHUT_WR +# define SHUT_WR 1 +# endif +# ifndef SHUT_RDWR +# define SHUT_RDWR 2 +# endif + case STREAM_XPORT_OP_SHUTDOWN: { + static const int shutdown_how[] = {SHUT_RD, SHUT_WR, SHUT_RDWR}; + + xparam->outputs.returncode = shutdown(sock->socket, shutdown_how[xparam->how]); + return PHP_STREAM_OPTION_RETURN_OK; + } +#endif + default: return PHP_STREAM_OPTION_RETURN_NOTIMPL; }