summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2003-02-28 19:53:21 +0000
committerWez Furlong <wez@php.net>2003-02-28 19:53:21 +0000
commit1b53a2d12e520adec5cbbc60bf8f2b6d8e54eece (patch)
tree9ec880f9d210dc979ef007e1d69c4c53666f8a46 /ext
parent14bf872003ff96b60960d5b822a0bb846bff176f (diff)
downloadphp-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.c4
-rw-r--r--ext/openssl/xp_ssl.c59
-rw-r--r--ext/standard/basic_functions.c6
-rw-r--r--ext/standard/file.c8
-rw-r--r--ext/standard/file.h15
-rw-r--r--ext/standard/fsock.c6
-rw-r--r--ext/standard/streamsfuncs.c227
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)