Browse Source

Added function stream_socket_shutdown(). It is a wraper for system shutdown() function, that shut downs part of a full-duplex connection

migration/RELEASE_1_0_0
Dmitry Stogov 20 years ago
parent
commit
938f3d6efa
  1. 11
      ext/standard/basic_functions.c
  2. 4
      ext/standard/file.c
  3. 30
      ext/standard/streamsfuncs.c
  4. 1
      ext/standard/streamsfuncs.h
  5. 65
      ext/standard/tests/network/shutdown.phpt
  6. 15
      main/streams/php_stream_transport.h
  7. 19
      main/streams/transports.c
  8. 18
      main/streams/xp_socket.c

11
ext/standard/basic_functions.c

@ -2449,6 +2449,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_stream_resolve_include_path, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, context)
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
@ -3563,6 +3571,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

4
ext/standard/file.c

@ -227,6 +227,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)

30
ext/standard/streamsfuncs.c

@ -1645,6 +1645,36 @@ PHP_FUNCTION(stream_resolve_include_path)
}
/* }}} */
#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

1
ext/standard/streamsfuncs.h

@ -54,6 +54,7 @@ PHP_FUNCTION(stream_filter_append);
PHP_FUNCTION(stream_filter_remove);
PHP_FUNCTION(stream_encoding);
PHP_FUNCTION(stream_socket_enable_crypto);
PHP_FUNCTION(stream_socket_shutdown);
PHP_FUNCTION(stream_socket_pair);
PHP_FUNCTION(stream_resolve_include_path);

65
ext/standard/tests/network/shutdown.phpt

@ -0,0 +1,65 @@
--TEST--
stream_socket_shutdown() test on IPv4 TCP Loopback
--SKIPIF--
<?php
function_exists('stream_socket_shutdown') or die('skip stream_socket_shutdown() is not supported.');
?>
--FILE--
<?php
/* Setup socket server */
$server = stream_socket_server('tcp://127.0.0.1:31337');
if (!$server) {
die('Unable to create AF_INET socket [server]');
}
/* Connect and send request 1 */
$client1 = stream_socket_client('tcp://127.0.0.1:31337');
if (!$client1) {
die('Unable to create AF_INET socket [client]');
}
@fwrite($client1, "Client 1\n");
stream_socket_shutdown($client1, STREAM_SHUT_WR);
@fwrite($client1, "Error 1\n");
/* Connect and send request 2 */
$client2 = stream_socket_client('tcp://127.0.0.1:31337');
if (!$client2) {
die('Unable to create AF_INET socket [client]');
}
@fwrite($client2, "Client 2\n");
stream_socket_shutdown($client2, STREAM_SHUT_WR);
@fwrite($client2, "Error 2\n");
/* Accept connection 1 */
$socket = stream_socket_accept($server);
if (!$socket) {
die('Unable to accept connection');
}
@fwrite($socket, fgets($socket));
@fwrite($socket, fgets($socket));
fclose($socket);
/* Read Response 1 */
echo fgets($client1);
echo fgets($client1);
/* Accept connection 2 */
$socket = stream_socket_accept($server);
if (!$socket) {
die('Unable to accept connection');
}
@fwrite($socket, fgets($socket));
@fwrite($socket, fgets($socket));
fclose($socket);
/* Read Response 2 */
echo fgets($client2);
echo fgets($client2);
fclose($client1);
fclose($client2);
fclose($server);
?>
--EXPECT--
Client 1
Client 2

15
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;

19
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(&param, 0, sizeof(param));
param.op = STREAM_XPORT_OP_SHUTDOWN;
param.how = how;
ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, &param);
if (ret == PHP_STREAM_OPTION_RETURN_OK) {
return param.outputs.returncode;
}
return -1;
}
/*
* Local variables:

18
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;
}

Loading…
Cancel
Save