wez Fri Feb 28 14:53:21 2003 EDT
Modified files:
/php4 NEWS configure.in
/php4/ext/ftp ftp.c
/php4/ext/openssl xp_ssl.c
/php4/ext/standard basic_functions.c file.c file.h fsock.c
streamsfuncs.c
/php4/main network.c php_network.h
/php4/main/streams php_stream_transport.h transports.c xp_socket.c
Log:
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.
Index: php4/NEWS
diff -u php4/NEWS:1.1361 php4/NEWS:1.1362
--- php4/NEWS:1.1361 Thu Feb 27 10:52:38 2003
+++ php4/NEWS Fri Feb 28 14:53:19 2003
@@ -21,8 +21,16 @@
of the specified parameters to be passed as extra parameters to the sendmail
binary. These parameters will always replace the value of the 5th parameter
to mail(), even in safe mode. (Derick)
+- Added new "transport" layer for sockets and associated functions. (Wez)
+ . 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.
+ . generic crypto interface for streams (supports dynamic loading of OpenSSL)
+- Added memory mapping support under win32 to improve performance of
+ readfile(), fpassthru() and some internal streams operations. (Wez)
- Added DBA handler 'inifile' to support ini files. (Marcus)
-- Added filter support. See README.input_filter. (Rasmus)
+- Added input filter support. See README.input_filter. (Rasmus)
- Added "session.hash_function" and "session.hash_bits_per_character". (Sascha)
- Added lightweight streaming input abstraction to the Zend Engine scanners
that provides uniform support for include()'ing data from PHP streams across
Index: php4/configure.in
diff -u php4/configure.in:1.427 php4/configure.in:1.428
--- php4/configure.in:1.427 Thu Feb 27 12:43:36 2003
+++ php4/configure.in Fri Feb 28 14:53:19 2003
@@ -1,4 +1,4 @@
-dnl ## $Id: configure.in,v 1.427 2003/02/27 17:43:36 wez Exp $ -*- sh -*-
+dnl ## $Id: configure.in,v 1.428 2003/02/28 19:53:19 wez Exp $ -*- sh -*-
dnl ## Process this file with autoconf to produce a configure script.
divert(1)
@@ -461,6 +461,8 @@
getrusage \
gettimeofday \
gmtime_r \
+inet_ntoa \
+inet_ntop \
isascii \
link \
localtime_r \
Index: php4/ext/ftp/ftp.c
diff -u php4/ext/ftp/ftp.c:1.81 php4/ext/ftp/ftp.c:1.82
--- php4/ext/ftp/ftp.c:1.81 Fri Feb 28 02:25:14 2003
+++ php4/ext/ftp/ftp.c Fri Feb 28 14:53:19 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: ftp.c,v 1.81 2003/02/28 07:25:14 sniper Exp $ */
+/* $Id: ftp.c,v 1.82 2003/02/28 19:53:19 wez Exp $ */
#include "php.h"
@@ -135,7 +135,9 @@
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;
}
Index: php4/ext/openssl/xp_ssl.c
diff -u php4/ext/openssl/xp_ssl.c:1.3 php4/ext/openssl/xp_ssl.c:1.4
--- php4/ext/openssl/xp_ssl.c:1.3 Fri Feb 28 02:25:14 2003
+++ php4/ext/openssl/xp_ssl.c Fri Feb 28 14:53:20 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: xp_ssl.c,v 1.3 2003/02/28 07:25:14 sniper Exp $ */
+/* $Id: xp_ssl.c,v 1.4 2003/02/28 19:53:20 wez Exp $ */
#include "php.h"
#include "ext/standard/file.h"
@@ -288,7 +288,6 @@
method = TLSv1_server_method();
break;
default:
- printf("unknown method\n");
return -1;
}
@@ -307,19 +306,16 @@
}
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 @@
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 @@
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 @@
}
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 @@
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 @@
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;
}
Index: php4/ext/standard/basic_functions.c
diff -u php4/ext/standard/basic_functions.c:1.591
php4/ext/standard/basic_functions.c:1.592
--- php4/ext/standard/basic_functions.c:1.591 Thu Feb 27 13:16:34 2003
+++ php4/ext/standard/basic_functions.c Fri Feb 28 14:53:20 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: basic_functions.c,v 1.591 2003/02/27 18:16:34 wez Exp $ */
+/* $Id: basic_functions.c,v 1.592 2003/02/28 19:53:20 wez Exp $ */
#include "php.h"
#include "php_streams.h"
@@ -96,8 +96,8 @@
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 @@
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)
Index: php4/ext/standard/file.c
diff -u php4/ext/standard/file.c:1.321 php4/ext/standard/file.c:1.322
--- php4/ext/standard/file.c:1.321 Fri Feb 28 02:57:00 2003
+++ php4/ext/standard/file.c Fri Feb 28 14:53:20 2003
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: file.c,v 1.321 2003/02/28 07:57:00 hholzgra Exp $ */
+/* $Id: file.c,v 1.322 2003/02/28 19:53:20 wez Exp $ */
/* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */
@@ -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 @@
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);
Index: php4/ext/standard/file.h
diff -u php4/ext/standard/file.h:1.78 php4/ext/standard/file.h:1.79
--- php4/ext/standard/file.h:1.78 Thu Feb 27 17:23:39 2003
+++ php4/ext/standard/file.h Fri Feb 28 14:53:20 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: file.h,v 1.78 2003/02/27 22:23:39 wez Exp $ */
+/* $Id: file.h,v 1.79 2003/02/28 19:53:20 wez Exp $ */
/* Synced with php 3.0 revision 1.30 1999-06-16 [ssb] */
@@ -54,13 +54,6 @@
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_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);
Index: php4/ext/standard/fsock.c
diff -u php4/ext/standard/fsock.c:1.110 php4/ext/standard/fsock.c:1.111
--- php4/ext/standard/fsock.c:1.110 Thu Feb 27 12:43:37 2003
+++ php4/ext/standard/fsock.c Fri Feb 28 14:53:20 2003
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fsock.c,v 1.110 2003/02/27 17:43:37 wez Exp $ */
+/* $Id: fsock.c,v 1.111 2003/02/28 19:53:20 wez Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -83,7 +83,7 @@
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) {
@@ -101,6 +101,10 @@
ZVAL_STRING(zerrstr, errstr, 0);
}
RETURN_FALSE;
+ }
+
+ if (errstr) {
+ efree(errstr);
}
php_stream_to_zval(stream, return_value);
Index: php4/ext/standard/streamsfuncs.c
diff -u php4/ext/standard/streamsfuncs.c:1.1 php4/ext/standard/streamsfuncs.c:1.2
--- php4/ext/standard/streamsfuncs.c:1.1 Thu Feb 27 17:43:51 2003
+++ php4/ext/standard/streamsfuncs.c Fri Feb 28 14:53:20 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: streamsfuncs.c,v 1.1 2003/02/27 22:43:51 wez Exp $ */
+/* $Id: streamsfuncs.c,v 1.2 2003/02/28 19:53:20 wez Exp $ */
#include "php.h"
#include "php_globals.h"
@@ -27,11 +27,238 @@
#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 */
Index: php4/main/network.c
diff -u php4/main/network.c:1.93 php4/main/network.c:1.94
--- php4/main/network.c:1.93 Thu Feb 27 19:08:00 2003
+++ php4/main/network.c Fri Feb 28 14:53:21 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: network.c,v 1.93 2003/02/28 00:08:00 iliaa Exp $ */
+/* $Id: network.c,v 1.94 2003/02/28 19:53:21 wez Exp $ */
/*#define DEBUG_MAIN_NETWORK 1*/
@@ -275,9 +275,6 @@
# endif
#endif
-
-
-
/* Connect to a socket using an interruptible connect with optional timeout.
* Optionally, the connect can be made asynchronously, which will implicitly
* enable non-blocking mode on the socket.
@@ -376,163 +373,276 @@
}
/* }}} */
-/* {{{ php_connect_nonb */
-PHPAPI int php_connect_nonb(int sockfd,
- const struct sockaddr *addr,
- socklen_t addrlen,
- struct timeval *timeout)
+/* {{{ sub_times */
+static inline void sub_times(struct timeval a, struct timeval b, struct timeval
*result)
{
-#if (!defined(__BEOS__) && !defined(PHP_WIN32)) && (defined(O_NONBLOCK) ||
defined(O_NDELAY))
+ result->tv_usec = a.tv_usec - b.tv_usec;
+ if (result->tv_usec < 0L) {
+ a.tv_sec--;
+ result->tv_usec += 1000000L;
+ }
+ result->tv_sec = a.tv_sec - b.tv_sec;
+ if (result->tv_sec < 0L) {
+ result->tv_sec++;
+ result->tv_usec -= 1000000L;
+ }
+}
+/* }}} */
+/* Bind to a local IP address.
+ * Returns the bound socket, or -1 on failure.
+ * */
+/* {{{ php_network_bind_socket_to_local_addr */
+int php_network_bind_socket_to_local_addr(const char *host, unsigned port,
+ int socktype, char **error_string, int *error_code
+ TSRMLS_DC)
+{
+ int num_addrs, sock, n, err = 0;
+ struct sockaddr **sal, **psal, *sa;
+ socklen_t socklen;
- int flags;
- int n;
- int error = 0;
- socklen_t len;
- int ret = 0;
- fd_set rset;
- fd_set wset;
- fd_set eset;
+ num_addrs = php_network_getaddresses(host, &psal, error_string TSRMLS_CC);
- if (timeout == NULL) {
- /* blocking mode */
- return connect(sockfd, addr, addrlen);
+ if (num_addrs == 0) {
+ /* could not resolve address(es) */
+ return -1;
}
-
- flags = fcntl(sockfd, F_GETFL, 0);
- fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
- if ((n = connect(sockfd, addr, addrlen)) < 0) {
- if (errno != EINPROGRESS) {
- return -1;
- }
- }
+ for (sal = psal; *sal != NULL; sal++) {
+ sa = *sal;
- if (n == 0) {
- goto ok;
- }
+ /* create a socket for this address */
+ sock = socket(sa->sa_family, socktype, 0);
- FD_ZERO(&rset);
- FD_ZERO(&eset);
- FD_SET(sockfd, &rset);
- FD_SET(sockfd, &eset);
+ if (sock == SOCK_ERR) {
+ continue;
+ }
- wset = rset;
+ switch (sa->sa_family) {
+#if HAVE_GETADDRINFO && HAVE_IPV6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)sa)->sin6_family =
sa->sa_family;
+ ((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
+ socklen = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ case AF_INET:
+ ((struct sockaddr_in *)sa)->sin_family = sa->sa_family;
+ ((struct sockaddr_in *)sa)->sin_port = htons(port);
+ socklen = sizeof(struct sockaddr_in);
+ break;
+ default:
+ /* Unknown family */
+ sa = NULL;
+ }
- if ((n = select(sockfd + 1, &rset, &wset, &eset, timeout)) == 0) {
- error = ETIMEDOUT;
- }
+ if (sa) {
+ /* attempt to bind */
+
+#ifdef SO_REUSEADDR
+ {
+ int val = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val,
sizeof(val));
+ }
+#endif
+
+ n = bind(sock, sa, socklen);
- if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
- len = sizeof(error);
- /*
- BSD-derived systems set errno correctly
- Solaris returns -1 from getsockopt in case of error
- */
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
- ret = -1;
+ if (n != SOCK_CONN_ERR) {
+ goto bound;
+ }
+
+ err = php_socket_errno();
}
- } else {
- /* whoops: sockfd has disappeared */
- ret = -1;
- }
-ok:
- fcntl(sockfd, F_SETFL, flags);
+ close(sock);
+ }
+ sock = -1;
- if(error) {
- errno = error;
- ret = -1;
+ if (error_code) {
+ *error_code = err;
}
- return ret;
-#else /* !defined(PHP_WIN32) && ... */
-#ifdef PHP_WIN32
- return php_connect_nonb_win32((SOCKET) sockfd, addr, addrlen, timeout);
-#endif
- return connect(sockfd, addr, addrlen);
-#endif
+ if (error_string) {
+ *error_string = php_socket_strerror(err, NULL, 0);
+ }
+
+bound:
+
+ php_network_freeaddresses(psal);
+
+ return sock;
+
}
/* }}} */
-#ifdef PHP_WIN32
-/* {{{ php_connect_nonb_win32 */
-PHPAPI int php_connect_nonb_win32(SOCKET sockfd,
- const struct sockaddr *addr,
- socklen_t addrlen,
- struct timeval *timeout)
+static void populate_name(
+ /* input address */
+ struct sockaddr *sa, socklen_t sl,
+ /* output readable address */
+ char **textaddr, long *textaddrlen,
+ /* output address */
+ struct sockaddr **addr,
+ socklen_t *addrlen
+ TSRMLS_DC)
{
- int error = 0, error_len, ret;
- u_long non_block = TRUE, block = FALSE;
-
- fd_set rset, wset;
-
- if (timeout == NULL) {
- /* blocking mode */
- return connect(sockfd, addr, addrlen);
+ if (addr) {
+ *addr = emalloc(sl);
+ memcpy(*addr, sa, sl);
+ *addrlen = sl;
}
-
- /* Set the socket to be non-blocking */
- ioctlsocket(sockfd, FIONBIO, &non_block);
- if (connect(sockfd, addr, addrlen) == SOCKET_ERROR) {
- if (WSAGetLastError() != WSAEWOULDBLOCK) {
- return SOCKET_ERROR;
- }
- }
+ if (textaddr) {
+#if HAVE_IPV6 && HAVE_INET_NTOP
+ char abuf[256];
+#endif
+ char *buf = NULL;
- FD_ZERO(&rset);
- FD_SET(sockfd, &rset);
+ switch (sa->sa_family) {
+ case AF_INET:
+ /* generally not thread safe, but it *is* thread safe
under win32 */
+ buf = inet_ntoa(((struct sockaddr_in*)sa)->sin_addr);
+ if (buf) {
+ *textaddrlen = strlen(buf);
+ *textaddr = estrndup(buf, *textaddrlen);
+ }
- FD_ZERO(&wset);
- FD_SET(sockfd, &wset);
+ break;
- if ((ret = select(sockfd + 1, &rset, &wset, NULL, timeout)) == 0) {
- WSASetLastError(WSAETIMEDOUT);
- return SOCKET_ERROR;
- }
+#if HAVE_IPV6
+ case AF_INET6:
+ buf = (char*)inet_ntop(sa->sa_family, &((struct
sockaddr_in6*)sa)->sin6_addr, (char *)&abuf, sizeof(abuf));
+ if (buf) {
+ *textaddrlen = strlen(buf);
+ *textaddr = estrndup(buf, *textaddrlen);
+ }
- if (ret == SOCKET_ERROR) {
- return SOCKET_ERROR;
- }
+ break;
+#endif
+#ifdef AF_UNIX
+ case AF_UNIX:
+ {
+ struct sockaddr_un *ua = (struct
sockaddr_un*)sa;
+
+ if (ua->sun_path[0] == '\0') {
+ /* abstract name */
+ int len = strlen(ua->sun_path + 1) + 1;
+ *textaddrlen = len;
+ *textaddr = emalloc(len + 1);
+ memcpy(*textaddr, ua->sun_path, len);
+ (*textaddr)[len] = '\0';
+ } else {
+ *textaddrlen = strlen(ua->sun_path);
+ *textaddr = estrndup(ua->sun_path,
*textaddrlen);
+ }
+ }
+ break;
+#endif
- if(FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
- error_len = sizeof(error);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char *) &error,
&error_len) == SOCKET_ERROR) {
- return SOCKET_ERROR;
}
- } else {
- /* whoops: sockfd has disappeared */
- return SOCKET_ERROR;
+
}
+}
- /* Set the socket back to blocking */
- ioctlsocket(sockfd, FIONBIO, &block);
+PHPAPI int php_network_get_peer_name(int sock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen
+ TSRMLS_DC)
+{
+ php_sockaddr_storage sa;
+ socklen_t sl = sizeof(sa);
+
+ if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) {
+ populate_name((struct sockaddr*)&sa, sl,
+ textaddr, textaddrlen,
+ addr, addrlen
+ TSRMLS_CC);
+ return 0;
+ }
+ return -1;
+}
- if (error) {
- WSASetLastError(error);
- return SOCKET_ERROR;
+PHPAPI int php_network_get_sock_name(int sock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen
+ TSRMLS_DC)
+{
+ php_sockaddr_storage sa;
+ socklen_t sl = sizeof(sa);
+
+ if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) {
+ populate_name((struct sockaddr*)&sa, sl,
+ textaddr, textaddrlen,
+ addr, addrlen
+ TSRMLS_CC);
+ return 0;
}
+ return -1;
- return 0;
}
-/* }}} */
-#endif
-/* {{{ sub_times */
-static inline void sub_times(struct timeval a, struct timeval b, struct timeval
*result)
+
+/* Accept a client connection from a server socket,
+ * using an optional timeout.
+ * Returns the peer address in addr/addrlen (it will emalloc
+ * these, so be sure to efree the result).
+ * If you specify textaddr/textaddrlen, a text-printable
+ * version of the address will be emalloc'd and returned.
+ * */
+
+/* {{{ php_network_accept_incoming */
+PHPAPI int php_network_accept_incoming(int srvsock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen,
+ struct timeval *timeout,
+ char **error_string,
+ int *error_code
+ TSRMLS_DC)
{
- result->tv_usec = a.tv_usec - b.tv_usec;
- if (result->tv_usec < 0L) {
- a.tv_sec--;
- result->tv_usec += 1000000L;
+ int clisock = -1;
+ fd_set rset;
+ int error, n;
+ php_sockaddr_storage sa;
+ socklen_t sl;
+
+ FD_ZERO(&rset);
+ FD_SET(srvsock, &rset);
+
+ n = select(srvsock + 1, &rset, NULL, NULL, timeout);
+
+ if (n == 0) {
+ error = PHP_TIMEOUT_ERROR_VALUE;
+ } else if (n == -1) {
+ error = php_socket_errno();
+ } else if (FD_ISSET(srvsock, &rset)) {
+ sl = sizeof(sa);
+
+ clisock = accept(srvsock, (struct sockaddr*)&sa, &sl);
+
+ if (clisock >= 0) {
+ populate_name((struct sockaddr*)&sa, sl,
+ textaddr, textaddrlen,
+ addr, addrlen
+ TSRMLS_CC);
+ } else {
+ error = php_socket_errno();
+ }
}
- result->tv_sec = a.tv_sec - b.tv_sec;
- if (result->tv_sec < 0L) {
- result->tv_sec++;
- result->tv_usec -= 1000000L;
+
+ if (error_code) {
+ *error_code = error;
+ }
+ if (error_string) {
+ *error_string = php_socket_strerror(error, NULL, 0);
}
+
+ return clisock;
}
/* }}} */
+
+
/* Connect to a remote host using an interruptible connect with optional timeout.
* Optionally, the connect can be made asynchronously, which will implicitly
@@ -651,110 +761,6 @@
php_network_freeaddresses(psal);
return sock;
-}
-/* }}} */
-
-
-
-/* {{{ php_hostconnect
- * Creates a socket of type socktype and connects to the given host and
- * port, returns the created socket on success, else returns -1.
- * timeout gives timeout in seconds, 0 means blocking mode.
- */
-int php_hostconnect(const char *host, unsigned short port, int socktype, struct
timeval *timeout TSRMLS_DC)
-{
- int n, repeatto, s;
- struct sockaddr **sal, **psal;
- struct timeval individual_timeout;
- int set_timeout = 0;
- int err;
-
- n = php_network_getaddresses(host, &sal, NULL TSRMLS_CC);
-
- if (n == 0)
- return -1;
-
- if (timeout != NULL) {
- /* is this a good idea? 5s? */
- repeatto = timeout->tv_sec / n > 5;
- if (repeatto) {
- individual_timeout.tv_sec = timeout->tv_sec / n;
- } else {
- individual_timeout.tv_sec = timeout->tv_sec;
- }
-
- individual_timeout.tv_usec = timeout->tv_usec;
- } else {
- individual_timeout.tv_sec = 0;
- individual_timeout.tv_usec = 0;
- }
-
- /* Boolean indicating whether to pass a timeout */
- set_timeout = individual_timeout.tv_sec + individual_timeout.tv_usec;
-
- psal = sal;
- while (*sal != NULL) {
- s = socket((*sal)->sa_family, socktype, 0);
- if (s != SOCK_ERR) {
- switch ((*sal)->sa_family) {
-#if defined( HAVE_GETADDRINFO ) && defined( HAVE_IPV6 )
- case AF_INET6:
- {
- struct sockaddr_in6 *sa =
- (struct sockaddr_in6 *)*sal;
-
- sa->sin6_family = (*sal)->sa_family;
- sa->sin6_port = htons(port);
- if (php_connect_nonb(s, (struct
sockaddr *) sa,
- sizeof(*sa),
(set_timeout) ? &individual_timeout : NULL) != SOCK_CONN_ERR)
- goto ok;
- }
- break;
-#endif
- case AF_INET:
- {
- struct sockaddr_in *sa =
- (struct sockaddr_in *)*sal;
-
- sa->sin_family = (*sal)->sa_family;
- sa->sin_port = htons(port);
- if (php_connect_nonb(s, (struct
sockaddr *) sa,
- sizeof(*sa),
(set_timeout) ? &individual_timeout : NULL) != SOCK_CONN_ERR)
- goto ok;
-
- }
- break;
- }
-#ifdef PHP_WIN32
- /* Preserve the last error */
- err = WSAGetLastError();
-#else
- err = errno;
-#endif
- close (s);
- }
- sal++;
-
- if (err == PHP_TIMEOUT_ERROR_VALUE) {
- /* if the first attempt timed out, it's highly likely
- * that any subsequent attempts will do so also */
- break;
- }
-
- }
- php_network_freeaddresses(psal);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "php_hostconnect: connect failed");
-
-#ifdef PHP_WIN32
- /* Restore the last error */
- WSASetLastError(err);
-#endif
-
- return -1;
-
- ok:
- php_network_freeaddresses(psal);
- return s;
}
/* }}} */
Index: php4/main/php_network.h
diff -u php4/main/php_network.h:1.41 php4/main/php_network.h:1.42
--- php4/main/php_network.h:1.41 Fri Feb 28 02:25:14 2003
+++ php4/main/php_network.h Fri Feb 28 14:53:21 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_network.h,v 1.41 2003/02/28 07:25:14 sniper Exp $ */
+/* $Id: php_network.h,v 1.42 2003/02/28 19:53:21 wez Exp $ */
#ifndef _PHP_NETWORK_H
#define _PHP_NETWORK_H
@@ -119,12 +119,33 @@
char **error_string,
int *error_code);
-int php_hostconnect(const char *host, unsigned short port, int socktype, struct
timeval *timeout TSRMLS_DC);
-PHPAPI int php_connect_nonb(int sockfd, const struct sockaddr *addr, socklen_t
addrlen, struct timeval *timeout);
+#define php_connect_nonb(sock, addr, addrlen, timeout) \
+ php_network_connect_socket((sock), (addr), (addrlen), 0, (timeout), NULL, NULL)
-#ifdef PHP_WIN32
-PHPAPI int php_connect_nonb_win32(SOCKET sockfd, const struct sockaddr *addr,
socklen_t addrlen, struct timeval *timeout);
-#endif
+PHPAPI int php_network_bind_socket_to_local_addr(const char *host, unsigned port,
+ int socktype, char **error_string, int *error_code
+ TSRMLS_DC);
+
+PHPAPI int php_network_accept_incoming(int srvsock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen,
+ struct timeval *timeout,
+ char **error_string,
+ int *error_code
+ TSRMLS_DC);
+
+PHPAPI int php_network_get_sock_name(int sock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen
+ TSRMLS_DC);
+
+PHPAPI int php_network_get_peer_name(int sock,
+ char **textaddr, long *textaddrlen,
+ struct sockaddr **addr,
+ socklen_t *addrlen
+ TSRMLS_DC);
void php_any_addr(int family, php_sockaddr_storage *addr, unsigned short port);
int php_sockaddr_size(php_sockaddr_storage *addr);
@@ -134,6 +155,7 @@
char is_blocked;
struct timeval timeout;
char timeout_event;
+ size_t ownsize;
};
typedef struct _php_netstream_data_t php_netstream_data_t;
extern php_stream_ops php_stream_socket_ops;
Index: php4/main/streams/php_stream_transport.h
diff -u php4/main/streams/php_stream_transport.h:1.1
php4/main/streams/php_stream_transport.h:1.2
--- php4/main/streams/php_stream_transport.h:1.1 Thu Feb 27 12:43:38 2003
+++ php4/main/streams/php_stream_transport.h Fri Feb 28 14:53:21 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_stream_transport.h,v 1.1 2003/02/27 17:43:38 wez Exp $ */
+/* $Id: php_stream_transport.h,v 1.2 2003/02/28 19:53:21 wez Exp $ */
typedef php_stream *(php_stream_transport_factory_func)(const char *proto, long
protolen,
char *resourcename, long resourcenamelen,
@@ -72,19 +72,27 @@
/* Get the next client and their address as a string, or the underlying address
* structure. You must efree either of these if you request them */
PHPAPI int php_stream_xport_accept(php_stream *stream, php_stream **client,
- char **textaddr, long *textaddrlen,
+ char **textaddr, int *textaddrlen,
void **addr, size_t *addrlen,
struct timeval *timeout,
char **error_text
TSRMLS_DC);
+/* Get the name of either the socket or it's peer */
+PHPAPI int php_stream_xport_get_name(php_stream *stream, int want_peer,
+ char **textaddr, int *textaddrlen,
+ void **addr, size_t *addrlen
+ TSRMLS_DC);
+
/* Structure definition for the set_option interface that the above functions wrap */
typedef struct _php_stream_xport_param {
enum {
STREAM_XPORT_OP_BIND, STREAM_XPORT_OP_CONNECT,
STREAM_XPORT_OP_LISTEN, STREAM_XPORT_OP_ACCEPT,
- STREAM_XPORT_OP_CONNECT_ASYNC
+ STREAM_XPORT_OP_CONNECT_ASYNC,
+ STREAM_XPORT_OP_GET_NAME,
+ STREAM_XPORT_OP_GET_PEER_NAME
} op;
int want_addr:1;
int want_textaddr:1;
@@ -99,7 +107,7 @@
struct {
php_stream *client;
int returncode;
- void *addr;
+ struct sockaddr *addr;
size_t addrlen;
char *textaddr;
long textaddrlen;
Index: php4/main/streams/transports.c
diff -u php4/main/streams/transports.c:1.2 php4/main/streams/transports.c:1.3
--- php4/main/streams/transports.c:1.2 Thu Feb 27 13:06:30 2003
+++ php4/main/streams/transports.c Fri Feb 28 14:53:21 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: transports.c,v 1.2 2003/02/27 18:06:30 wez Exp $ */
+/* $Id: transports.c,v 1.3 2003/02/28 19:53:21 wez Exp $ */
#include "php.h"
#include "php_streams_int.h"
@@ -252,7 +252,7 @@
/* Get the next client and their address (as a string) */
PHPAPI int php_stream_xport_accept(php_stream *stream, php_stream **client,
- char **textaddr, long *textaddrlen,
+ char **textaddr, int *textaddrlen,
void **addr, size_t *addrlen,
struct timeval *timeout,
char **error_text
@@ -263,7 +263,7 @@
memset(¶m, 0, sizeof(param));
- param.op = STREAM_XPORT_OP_BIND;
+ param.op = STREAM_XPORT_OP_ACCEPT;
param.inputs.timeout = timeout;
param.want_addr = addr ? 1 : 0;
param.want_textaddr = textaddr ? 1 : 0;
@@ -283,6 +283,37 @@
}
if (error_text) {
*error_text = param.outputs.error_text;
+ }
+
+ return param.outputs.returncode;
+ }
+ return ret;
+}
+
+PHPAPI int php_stream_xport_get_name(php_stream *stream, int want_peer,
+ char **textaddr, int *textaddrlen,
+ void **addr, size_t *addrlen
+ TSRMLS_DC)
+{
+ php_stream_xport_param param;
+ int ret;
+
+ memset(¶m, 0, sizeof(param));
+
+ param.op = want_peer ? STREAM_XPORT_OP_GET_PEER_NAME :
STREAM_XPORT_OP_GET_NAME;
+ param.want_addr = addr ? 1 : 0;
+ param.want_textaddr = textaddr ? 1 : 0;
+
+ ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m);
+
+ if (ret == PHP_STREAM_OPTION_RETURN_OK) {
+ if (addr) {
+ *addr = param.outputs.addr;
+ *addrlen = param.outputs.addrlen;
+ }
+ if (textaddr) {
+ *textaddr = param.outputs.textaddr;
+ *textaddrlen = param.outputs.textaddrlen;
}
return param.outputs.returncode;
Index: php4/main/streams/xp_socket.c
diff -u php4/main/streams/xp_socket.c:1.3 php4/main/streams/xp_socket.c:1.4
--- php4/main/streams/xp_socket.c:1.3 Thu Feb 27 14:10:24 2003
+++ php4/main/streams/xp_socket.c Fri Feb 28 14:53:21 2003
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: xp_socket.c,v 1.3 2003/02/27 19:10:24 wez Exp $ */
+/* $Id: xp_socket.c,v 1.4 2003/02/28 19:53:21 wez Exp $ */
#include "php.h"
#include "ext/standard/file.h"
@@ -217,6 +217,25 @@
xparam->outputs.returncode =
listen(sock->socket, 5);
return PHP_STREAM_OPTION_RETURN_OK;
+ case STREAM_XPORT_OP_GET_NAME:
+ xparam->outputs.returncode =
php_network_get_sock_name(sock->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
+ TSRMLS_CC);
+ return PHP_STREAM_OPTION_RETURN_OK;
+
+ case STREAM_XPORT_OP_GET_PEER_NAME:
+ xparam->outputs.returncode =
php_network_get_peer_name(sock->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
+ TSRMLS_CC);
+ return PHP_STREAM_OPTION_RETURN_OK;
+
+
default:
return PHP_STREAM_OPTION_RETURN_NOTIMPL;
}
@@ -311,17 +330,97 @@
/* network socket operations */
+#ifdef AF_UNIX
+static inline int parse_unix_address(php_stream_xport_param *xparam, struct
sockaddr_un *unix_addr TSRMLS_DC)
+{
+ memset(unix_addr, 0, sizeof(*unix_addr));
+ unix_addr->sun_family = AF_UNIX;
+
+ /* we need to be binary safe on systems that support an abstract
+ * namespace */
+ if (xparam->inputs.namelen >= sizeof(unix_addr->sun_path)) {
+ /* On linux, when the path begins with a NUL byte we are
+ * referring to an abstract namespace. In theory we should
+ * allow an extra byte below, since we don't need the NULL.
+ * BUT, to get into this branch of code, the name is too long,
+ * so we don't care. */
+ xparam->inputs.namelen = sizeof(unix_addr->sun_path) - 1;
+ }
+
+ memcpy(unix_addr->sun_path, xparam->inputs.name, xparam->inputs.namelen);
+
+ return 1;
+}
+#endif
+
+static inline char *parse_ip_address(php_stream_xport_param *xparam, int *portno
TSRMLS_DC)
+{
+ char *colon;
+ char *host = NULL;
+
+ colon = memchr(xparam->inputs.name, ':', xparam->inputs.namelen);
+ if (colon) {
+ *portno = atoi(colon + 1);
+ host = estrndup(xparam->inputs.name, colon - xparam->inputs.name);
+ } else {
+ if (xparam->want_errortext) {
+ spprintf(&xparam->outputs.error_text, 0, "Failed to parse
address \"%s\"", xparam->inputs.name);
+ }
+ return NULL;
+ }
+
+ return host;
+}
+
static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t *sock,
php_stream_xport_param *xparam TSRMLS_DC)
{
+ char *host = NULL;
+ int portno, err;
+
+#ifdef AF_UNIX
+ if (stream->ops == &php_stream_unix_socket_ops || stream->ops ==
&php_stream_unixdg_socket_ops) {
+ struct sockaddr_un unix_addr;
+
+ sock->socket = socket(PF_UNIX, stream->ops ==
&php_stream_unix_socket_ops ? SOCK_STREAM : SOCK_DGRAM, 0);
+
+ if (sock->socket == SOCK_ERR) {
+ if (xparam->want_errortext) {
+ spprintf(&xparam->outputs.error_text, 0, "Failed to
create unix%s socket %s",
+ stream->ops ==
&php_stream_unix_socket_ops ? "" : "datagram",
+ strerror(errno));
+ }
+ return -1;
+ }
+
+ parse_unix_address(xparam, &unix_addr TSRMLS_CC);
+
+ return bind(sock->socket, &unix_addr, sizeof(unix_addr));
+ }
+#endif
+
+ host = parse_ip_address(xparam, &portno TSRMLS_CC);
- return -1;
+ if (host == NULL) {
+ return -1;
+ }
+
+ sock->socket = php_network_bind_socket_to_local_addr(host, portno,
+ stream->ops == &php_stream_udp_socket_ops ? SOCK_DGRAM :
SOCK_STREAM,
+ xparam->want_errortext ? &xparam->outputs.error_text : NULL,
+ &err
+ TSRMLS_CC);
+
+ if (host) {
+ efree(host);
+ }
+
+ return sock->socket == -1 ? -1 : 0;
}
static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_t
*sock,
php_stream_xport_param *xparam TSRMLS_DC)
{
- char *colon;
char *host = NULL;
int portno, err;
int ret;
@@ -339,21 +438,7 @@
return -1;
}
- memset(&unix_addr, 0, sizeof(unix_addr));
- unix_addr.sun_family = AF_UNIX;
-
- /* we need to be binary safe on systems that support an abstract
- * namespace */
- if (xparam->inputs.namelen >= sizeof(unix_addr.sun_path)) {
- /* On linux, when the path begins with a NUL byte we are
- * referring to an abstract namespace. In theory we should
- * allow an extra byte below, since we don't need the NULL.
- * BUT, to get into this branch of code, the name is too long,
- * so we don't care. */
- xparam->inputs.namelen = sizeof(unix_addr.sun_path) - 1;
- }
-
- memcpy(unix_addr.sun_path, xparam->inputs.name,
xparam->inputs.namelen);
+ parse_unix_address(xparam, &unix_addr TSRMLS_CC);
ret = php_network_connect_socket(sock->socket,
(const struct sockaddr *)&unix_addr, sizeof(unix_addr),
@@ -366,15 +451,10 @@
goto out;
}
#endif
-
- colon = memchr(xparam->inputs.name, ':', xparam->inputs.namelen);
- if (colon) {
- portno = atoi(colon + 1);
- host = estrndup(xparam->inputs.name, colon - xparam->inputs.name);
- } else {
- if (xparam->want_errortext) {
- spprintf(&xparam->outputs.error_text, 0, "Failed to parse
address \"%s\"", xparam->inputs.name);
- }
+
+ host = parse_ip_address(xparam, &portno TSRMLS_CC);
+
+ if (host == NULL) {
return -1;
}
@@ -409,9 +489,42 @@
}
static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t
*sock,
- php_stream_xport_param *xparam TSRMLS_DC)
+ php_stream_xport_param *xparam STREAMS_DC TSRMLS_DC)
{
- return -1;
+ int clisock;
+
+ xparam->outputs.client = NULL;
+
+ clisock = php_network_accept_incoming(sock->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_netstream_data_t *clisockdata;
+
+ clisockdata = pemalloc(sizeof(*clisockdata), stream->is_persistent);
+
+ if (clisockdata == NULL) {
+ close(clisock);
+ /* technically a fatal error */
+ } else {
+ memcpy(clisockdata, sock, sizeof(*clisockdata));
+ clisockdata->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_tcp_sockop_set_option(php_stream *stream, int option, int value, void
*ptrparam TSRMLS_DC)
@@ -435,7 +548,7 @@
case STREAM_XPORT_OP_ACCEPT:
- xparam->outputs.returncode =
php_tcp_sockop_accept(stream, sock, xparam TSRMLS_CC);
+ xparam->outputs.returncode =
php_tcp_sockop_accept(stream, sock, xparam STREAMS_CC TSRMLS_CC);
return PHP_STREAM_OPTION_RETURN_OK;
default:
/* fall through */
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php