summaryrefslogtreecommitdiff
path: root/ext/standard/streamsfuncs.c
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/standard/streamsfuncs.c
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/standard/streamsfuncs.c')
-rw-r--r--ext/standard/streamsfuncs.c227
1 files changed, 227 insertions, 0 deletions
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)