diff options
| author | Wez Furlong <wez@php.net> | 2003-02-28 19:53:21 +0000 |
|---|---|---|
| committer | Wez Furlong <wez@php.net> | 2003-02-28 19:53:21 +0000 |
| commit | 1b53a2d12e520adec5cbbc60bf8f2b6d8e54eece (patch) | |
| tree | 9ec880f9d210dc979ef007e1d69c4c53666f8a46 /ext | |
| parent | 14bf872003ff96b60960d5b822a0bb846bff176f (diff) | |
| download | php-git-1b53a2d12e520adec5cbbc60bf8f2b6d8e54eece.tar.gz | |
New user-space functions:
. stream_socket_client() - similar to fsockopen(), but more powerful.
. stream_socket_server() - Creates a server socket.
. stream_socket_accept() - Accept a client connection.
. stream_socket_get_name() - Get local or remote name of socket.
Tidy up some leaks and debug printfs.
Move more streams functions into streamsfuncs.c and streamsfuncs.h.
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/ftp/ftp.c | 4 | ||||
| -rw-r--r-- | ext/openssl/xp_ssl.c | 59 | ||||
| -rw-r--r-- | ext/standard/basic_functions.c | 6 | ||||
| -rw-r--r-- | ext/standard/file.c | 8 | ||||
| -rw-r--r-- | ext/standard/file.h | 15 | ||||
| -rw-r--r-- | ext/standard/fsock.c | 6 | ||||
| -rw-r--r-- | ext/standard/streamsfuncs.c | 227 |
7 files changed, 299 insertions, 26 deletions
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c index 8ceb938c7d..4601a6e321 100644 --- a/ext/ftp/ftp.c +++ b/ext/ftp/ftp.c @@ -135,7 +135,9 @@ ftp_open(const char *host, short port, long timeout_sec TSRMLS_DC) tv.tv_sec = timeout_sec; tv.tv_usec = 0; - ftp->fd = php_hostconnect(host, (unsigned short) (port ? port : 21), SOCK_STREAM, &tv TSRMLS_CC); + ftp->fd = php_network_connect_socket_to_host(host, + (unsigned short) (port ? port : 21), SOCK_STREAM, + 0, &tv, NULL, NULL TSRMLS_CC); if (ftp->fd == -1) { goto bail; } diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 4e9a0ac11a..69f11a287e 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -288,7 +288,6 @@ static inline int php_openssl_setup_crypto(php_stream *stream, method = TLSv1_server_method(); break; default: - printf("unknown method\n"); return -1; } @@ -307,19 +306,16 @@ static inline int php_openssl_setup_crypto(php_stream *stream, } if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { - printf("failed to set fd %d\n", sslsock->s.socket); handle_ssl_error(stream, 0 TSRMLS_CC); } if (cparam->inputs.session) { - printf("sess=%p\n", cparam->inputs.session); if (cparam->inputs.session->ops != &php_openssl_socket_ops) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied session stream must be an SSL enabled stream"); } else { SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); } } -printf("crypto prepared for fd=%d\n", sslsock->s.socket); return 0; } @@ -337,13 +333,11 @@ static inline int php_openssl_enable_crypto(php_stream *stream, if (n <= 0) { retry = handle_ssl_error(stream, n TSRMLS_CC); - printf("error; retry = %d\n", retry); } else { break; } } while (retry); - printf("enabled_crypto: n=%d\n", n); if (n == 1) { sslsock->ssl_active = 1; } @@ -359,6 +353,47 @@ static inline int php_openssl_enable_crypto(php_stream *stream, return -1; } +static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_netstream_data_t *sock, + php_stream_xport_param *xparam STREAMS_DC TSRMLS_DC) +{ + int clisock; + + xparam->outputs.client = NULL; + + clisock = php_network_accept_incoming(sock->s.socket, + xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, + xparam->want_textaddr ? &xparam->outputs.textaddrlen : 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 + TSRMLS_CC); + + if (clisock >= 0) { + php_openssl_netstream_data_t *clisockdata; + + clisockdata = pemalloc(sizeof(*clisockdata), stream->is_persistent); + + if (clisockdata == NULL) { + close(clisock); + /* technically a fatal error */ + } else { + /* copy underlying tcp fields */ + memset(clisockdata, 0, sizeof(*clisockdata)); + memcpy(clisockdata, sock, sizeof(clisockdata->s)); + + clisockdata->s.socket = clisock; + + xparam->outputs.client = php_stream_alloc_rel(stream->ops, clisockdata, NULL, "r+"); + if (xparam->outputs.client) { + xparam->outputs.client->context = stream->context; + } + } + } + + return xparam->outputs.client == NULL ? -1 : 0; +} static int php_openssl_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) { php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; @@ -403,6 +438,14 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val } return PHP_STREAM_OPTION_RETURN_OK; break; + + case STREAM_XPORT_OP_ACCEPT: + /* we need to copy the additional fields that the underlying tcp transport + * doesn't know about */ + xparam->outputs.returncode = php_openssl_tcp_sockop_accept(stream, sslsock, xparam STREAMS_CC TSRMLS_CC); + return PHP_STREAM_OPTION_RETURN_OK; + break; + default: /* fall through */ break; @@ -464,7 +507,7 @@ PHPAPI php_stream *php_openssl_ssl_socket_factory(const char *proto, long protol php_openssl_netstream_data_t *sslsock = NULL; sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0); - memset(sslsock, 0, sizeof(php_openssl_netstream_data_t)); + memset(sslsock, 0, sizeof(*sslsock)); sslsock->s.is_blocked = 1; sslsock->s.timeout.tv_sec = FG(default_socket_timeout); @@ -488,6 +531,8 @@ PHPAPI php_stream *php_openssl_ssl_socket_factory(const char *proto, long protol sslsock->enable_on_connect = 1; sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT; } + +printf("enable_on_connect = %d --> proto %s\n", sslsock->enable_on_connect, proto); return stream; } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 56d25da5e2..d9ef2ebb6c 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -96,8 +96,8 @@ int basic_globals_id; php_basic_globals basic_globals; #endif - #include "php_fopen_wrappers.h" +#include "streamsfuncs.h" static unsigned char first_and_second__args_force_ref[] = { 2, BYREF_FORCE, BYREF_FORCE }; static unsigned char second_and_third_args_force_ref[] = { 3, BYREF_NONE, BYREF_FORCE, BYREF_FORCE }; @@ -679,6 +679,10 @@ function_entry basic_functions[] = { PHP_FE(stream_context_get_options, NULL) PHP_FE(stream_filter_prepend, NULL) PHP_FE(stream_filter_append, NULL) + PHP_FE(stream_socket_client, second_and_third_args_force_ref) + PHP_FE(stream_socket_server, second_and_third_args_force_ref) + PHP_FE(stream_socket_accept, third_arg_force_ref) + PHP_FE(stream_socket_get_name, NULL) PHP_FE(fgetcsv, NULL) PHP_FE(flock, NULL) PHP_FE(get_meta_tags, NULL) diff --git a/ext/standard/file.c b/ext/standard/file.c index 280b49b789..54472d4bf5 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -82,7 +82,7 @@ #endif #include "fsock.h" #include "fopen_wrappers.h" -#include "php_streams.h" +#include "streamsfuncs.h" #include "php_globals.h" #ifdef HAVE_SYS_FILE_H @@ -187,6 +187,12 @@ PHP_MINIT_FUNCTION(file) REGISTER_LONG_CONSTANT("STREAM_FILTER_WRITE", PHP_STREAM_FILTER_WRITE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_FILTER_ALL", PHP_STREAM_FILTER_ALL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CLIENT_PERSISTENT", PHP_STREAM_CLIENT_PERSISTENT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CLIENT_ASYNC_CONNECT", PHP_STREAM_CLIENT_ASYNC_CONNECT, CONST_CS | CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("STREAM_SERVER_BIND", STREAM_XPORT_BIND, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_SERVER_LISTEN", STREAM_XPORT_LISTEN, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FILE_USE_INCLUDE_PATH", PHP_FILE_USE_INCLUDE_PATH, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILE_IGNORE_NEW_LINES", PHP_FILE_IGNORE_NEW_LINES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILE_SKIP_EMPTY_LINES", PHP_FILE_SKIP_EMPTY_LINES, CONST_CS | CONST_PERSISTENT); diff --git a/ext/standard/file.h b/ext/standard/file.h index e32eac24fd..faa389fc67 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -54,13 +54,6 @@ PHP_FUNCTION(unlink); PHP_FUNCTION(copy); PHP_FUNCTION(file); PHP_FUNCTION(file_get_contents); -PHP_FUNCTION(set_socket_blocking); /* deprecated */ -PHP_FUNCTION(stream_set_blocking); -PHP_FUNCTION(stream_select); -PHP_FUNCTION(stream_set_timeout); -PHP_FUNCTION(stream_set_write_buffer); -PHP_FUNCTION(stream_get_wrappers); -PHP_FUNCTION(stream_get_line); PHP_FUNCTION(get_meta_tags); PHP_FUNCTION(flock); PHP_FUNCTION(fd_set); @@ -72,14 +65,6 @@ PHP_FUNCTION(fnmatch); PHP_NAMED_FUNCTION(php_if_ftruncate); PHP_NAMED_FUNCTION(php_if_fstat); -PHP_FUNCTION(stream_get_meta_data); -PHP_FUNCTION(stream_register_wrapper); -PHP_FUNCTION(stream_context_create); -PHP_FUNCTION(stream_context_set_params); -PHP_FUNCTION(stream_context_set_option); -PHP_FUNCTION(stream_context_get_options); -PHP_FUNCTION(stream_filter_prepend); -PHP_FUNCTION(stream_filter_append); PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_le_stream_context(void); diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index 8f41cf4d3f..ddc0812c48 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -83,7 +83,7 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) efree(hostname); } if (stream == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d", host, port); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s:%d (%s)", host, port, errstr == NULL ? "Unknown error" : errstr); } if (hashkey) { @@ -102,6 +102,10 @@ static void php_fsockopen_stream(INTERNAL_FUNCTION_PARAMETERS, int persistent) } RETURN_FALSE; } + + if (errstr) { + efree(errstr); + } php_stream_to_zval(stream, return_value); } diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 1a054fe00e..110058ac26 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -27,12 +27,239 @@ #include "php_open_temporary_file.h" #include "ext/standard/basic_functions.h" #include "php_ini.h" +#include "streamsfuncs.h" #ifndef PHP_WIN32 #define php_select(m, r, w, e, t) select(m, r, w, e, t) #endif +static php_stream_context *decode_context_param(zval *contextresource TSRMLS_DC); + +/* Streams based network functions */ + +/* {{{ proto resource stream_socket_client(string remoteaddress [, long &errcode, string &errstring, double timeout, long flags, resource context]) + Open a client connection to a remote address */ +PHP_FUNCTION(stream_socket_client) +{ + char *host; + long host_len; + zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL; + double timeout = FG(default_socket_timeout); + unsigned long conv; + struct timeval tv; + char *hashkey = NULL; + php_stream *stream = NULL; + int err; + long flags = 0; + char *errstr = NULL; + php_stream_context *context = NULL; + + RETVAL_FALSE; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zzd!lr", &host, &host_len, &zerrno, &zerrstr, &timeout, &flags, &zcontext) == FAILURE) { + RETURN_FALSE; + } + + if (zcontext) { + context = decode_context_param(zcontext TSRMLS_CC); + } + + if (flags & PHP_STREAM_CLIENT_PERSISTENT) { + spprintf(&hashkey, 0, "stream_socket_client__%s", host); + } + + /* prepare the timeout value for use */ + conv = (unsigned long) (timeout * 1000000.0); + tv.tv_sec = conv / 1000000; + tv.tv_usec = conv % 1000000; + + if (zerrno) { + zval_dtor(zerrno); + ZVAL_LONG(zerrno, 0); + } + if (zerrstr) { + zval_dtor(zerrstr); + ZVAL_STRING(zerrstr, "", 1); + } + + stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS, + STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT | + (flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0), + hashkey, &tv, context, &errstr, &err); + + if (stream == NULL) { + /* host might contain binary characters */ + char *quoted_host = php_addslashes(host, host_len, NULL, 0 TSRMLS_CC); + + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s (%s)", quoted_host, errstr == NULL ? "Unknown error" : errstr); + efree(quoted_host); + } + + if (hashkey) { + efree(hashkey); + } + + if (stream == NULL) { + if (zerrno) { + zval_dtor(zerrno); + ZVAL_LONG(zerrno, err); + } + if (zerrstr && errstr) { + /* no need to dup; we need to efree buf anyway */ + zval_dtor(zerrstr); + ZVAL_STRING(zerrstr, errstr, 0); + } else if (errstr) { + efree(errstr); + } + RETURN_FALSE; + } + + if (errstr) { + efree(errstr); + } + + php_stream_to_zval(stream, return_value); +} +/* }}} */ + +/* {{{ proto resource stream_socket_server(string localaddress [, long &errcode, string &errstring, long flags, resource context]) + Create a server socket bound to localaddress */ +PHP_FUNCTION(stream_socket_server) +{ + char *host; + long host_len; + zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL; + php_stream *stream = NULL; + int err; + long flags = STREAM_XPORT_BIND | STREAM_XPORT_LISTEN; + char *errstr = NULL; + php_stream_context *context = NULL; + + RETVAL_FALSE; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zzlr", &host, &host_len, &zerrno, &zerrstr, &flags, &zcontext) == FAILURE) { + RETURN_FALSE; + } + + if (zcontext) { + context = decode_context_param(zcontext TSRMLS_CC); + } + + if (zerrno) { + zval_dtor(zerrno); + ZVAL_LONG(zerrno, 0); + } + if (zerrstr) { + zval_dtor(zerrstr); + ZVAL_STRING(zerrstr, "", 1); + } + + stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS, + STREAM_XPORT_SERVER | flags, + NULL, NULL, context, &errstr, &err); + + if (stream == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to connect to %s (%s)", host, errstr == NULL ? "Unknown error" : errstr); + } + + if (stream == NULL) { + if (zerrno) { + zval_dtor(zerrno); + ZVAL_LONG(zerrno, err); + } + if (zerrstr && errstr) { + /* no need to dup; we need to efree buf anyway */ + zval_dtor(zerrstr); + ZVAL_STRING(zerrstr, errstr, 0); + } + RETURN_FALSE; + } + + if (errstr) { + efree(errstr); + } + + php_stream_to_zval(stream, return_value); + +} +/* }}} */ + +/* {{{ proto resource stream_socket_accept(resource serverstream, [ double timeout, string &peername ]) + Accept a client connection from a server socket */ +PHP_FUNCTION(stream_socket_accept) +{ + double timeout = FG(default_socket_timeout); + zval *peername = NULL; + unsigned long conv; + struct timeval tv; + php_stream *stream = NULL, *clistream = NULL; + zval *zstream; + + char *errstr = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|dz!", &zstream, &timeout, &peername) == FAILURE) { + RETURN_FALSE; + } + + php_stream_from_zval(stream, &zstream); + + /* prepare the timeout value for use */ + conv = (unsigned long) (timeout * 1000000.0); + tv.tv_sec = conv / 1000000; + tv.tv_usec = conv % 1000000; + + if (peername) { + zval_dtor(peername); + ZVAL_STRING(peername, "", 1); + } + + if (0 == php_stream_xport_accept(stream, &clistream, + peername ? &Z_STRVAL_P(peername) : NULL, + peername ? &Z_STRLEN_P(peername) : NULL, + NULL, NULL, + &tv, &errstr + TSRMLS_CC) && clistream) { + + php_stream_to_zval(clistream, return_value); + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "accept failed: %s", errstr ? errstr : "Unknown error"); + + RETVAL_FALSE; + } + + if (errstr) { + efree(errstr); + } +} +/* }}} */ + +/* {{{ proto string stream_socket_get_name(resource stream, bool want_peer) + Returns either the locally bound or remote name for a socket stream */ +PHP_FUNCTION(stream_socket_get_name) +{ + php_stream *stream; + zval *zstream; + zend_bool want_peer; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb", &zstream, &want_peer) == FAILURE) { + RETURN_FALSE; + } + + php_stream_from_zval(stream, &zstream); + + Z_TYPE_P(return_value) = IS_STRING; + + if (0 != php_stream_xport_get_name(stream, want_peer, + &Z_STRVAL_P(return_value), + &Z_STRLEN_P(return_value), + NULL, NULL + TSRMLS_CC)) { + RETURN_FALSE; + } +} +/* }}} */ + /* {{{ proto resource stream_get_meta_data(resource fp) Retrieves header/meta data from streams/file pointers */ PHP_FUNCTION(stream_get_meta_data) |
