wez Sat Nov 29 16:46:50 2003 EDT Modified files: /php-src/ext/standard basic_functions.c file.c streamsfuncs.c streamsfuncs.h /php-src/ext/standard/tests/network tcp4loop.phpt /php-src/main network.c php_network.h /php-src/main/streams php_stream_transport.h transports.c xp_socket.c Log: Add stream_socket_sendto and stream_socket_recvfrom which work very much like sendto() and recvfrom() syscalls.
Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.643 php-src/ext/standard/basic_functions.c:1.644 --- php-src/ext/standard/basic_functions.c:1.643 Sun Nov 23 20:17:27 2003 +++ php-src/ext/standard/basic_functions.c Sat Nov 29 16:46:47 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.643 2003/11/24 01:17:27 iliaa Exp $ */ +/* $Id: basic_functions.c,v 1.644 2003/11/29 21:46:47 wez Exp $ */ #include "php.h" #include "php_streams.h" @@ -731,10 +731,12 @@ 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(stream_socket_recvfrom, fourth_arg_force_ref) + PHP_FE(stream_socket_sendto, NULL) PHP_FE(stream_copy_to_stream, NULL) PHP_FE(stream_get_contents, NULL) PHP_FE(fgetcsv, NULL) - PHP_FE(flock, NULL) + PHP_FE(flock, third_arg_force_ref) PHP_FE(get_meta_tags, NULL) PHP_FE(stream_set_write_buffer, NULL) PHP_FALIAS(set_file_buffer, stream_set_write_buffer, NULL) @@ -1098,7 +1100,7 @@ REGISTER_LONG_CONSTANT("INI_PERDIR", ZEND_INI_PERDIR, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INI_SYSTEM", ZEND_INI_SYSTEM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("INI_ALL", ZEND_INI_ALL, CONST_CS | CONST_PERSISTENT); - + REGISTER_LONG_CONSTANT("SUNFUNCS_RET_TIMESTAMP", SUNFUNCS_RET_TIMESTAMP, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SUNFUNCS_RET_STRING", SUNFUNCS_RET_STRING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SUNFUNCS_RET_DOUBLE", SUNFUNCS_RET_DOUBLE, CONST_CS | CONST_PERSISTENT); Index: php-src/ext/standard/file.c diff -u php-src/ext/standard/file.c:1.366 php-src/ext/standard/file.c:1.367 --- php-src/ext/standard/file.c:1.366 Sun Nov 23 20:42:43 2003 +++ php-src/ext/standard/file.c Sat Nov 29 16:46:47 2003 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.c,v 1.366 2003/11/24 01:42:43 iliaa Exp $ */ +/* $Id: file.c,v 1.367 2003/11/29 21:46:47 wez Exp $ */ /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */ @@ -201,6 +201,10 @@ 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_CLIENT_CONNECT", PHP_STREAM_CLIENT_CONNECT, CONST_CS | CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("STREAM_PEEK", STREAM_PEEK, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_OOB", STREAM_OOB, 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); Index: php-src/ext/standard/streamsfuncs.c diff -u php-src/ext/standard/streamsfuncs.c:1.29 php-src/ext/standard/streamsfuncs.c:1.30 --- php-src/ext/standard/streamsfuncs.c:1.29 Fri Nov 28 13:33:14 2003 +++ php-src/ext/standard/streamsfuncs.c Sat Nov 29 16:46:47 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: streamsfuncs.c,v 1.29 2003/11/28 18:33:14 iliaa Exp $ */ +/* $Id: streamsfuncs.c,v 1.30 2003/11/29 21:46:47 wez Exp $ */ #include "php.h" #include "php_globals.h" @@ -54,7 +54,7 @@ char *hashkey = NULL; php_stream *stream = NULL; int err; - long flags = 0; + long flags = PHP_STREAM_CLIENT_CONNECT; char *errstr = NULL; php_stream_context *context = NULL; @@ -85,7 +85,7 @@ } stream = php_stream_xport_create(host, host_len, ENFORCE_SAFE_MODE | REPORT_ERRORS, - STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT | + STREAM_XPORT_CLIENT | (flags & PHP_STREAM_CLIENT_CONNECT ? STREAM_XPORT_CONNECT : 0) | (flags & PHP_STREAM_CLIENT_ASYNC_CONNECT ? STREAM_XPORT_CONNECT_ASYNC : 0), hashkey, &tv, context, &errstr, &err); @@ -136,7 +136,7 @@ long host_len; zval *zerrno = NULL, *zerrstr = NULL, *zcontext = NULL; php_stream *stream = NULL; - int err; + int err = 0; long flags = STREAM_XPORT_BIND | STREAM_XPORT_LISTEN; char *errstr = NULL; php_stream_context *context = NULL; @@ -266,6 +266,85 @@ } /* }}} */ +/* {{{ proto long stream_socket_sendto(resouce stream, string data [, long flags [, string target_addr]]) + Send data to a socket stream. If target_addr is specified it must be in dotted quad (or [ipv6]) format */ +PHP_FUNCTION(stream_socket_sendto) +{ + php_stream *stream; + zval *zstream; + long flags = 0; + char *data, *target_addr = NULL; + long datalen, target_addr_len = 0; + php_sockaddr_storage sa; + socklen_t sl = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ls", &zstream, &data, &datalen, &flags, &target_addr, &target_addr_len) == FAILURE) { + RETURN_FALSE; + } + php_stream_from_zval(stream, &zstream); + + if (target_addr) { + /* parse the address */ + if (FAILURE == php_network_parse_network_address_with_port(target_addr, target_addr_len, (struct sockaddr*)&sa, &sl TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to parse `%s' into a valid network address", target_addr); + RETURN_FALSE; + } + } + + RETURN_LONG(php_stream_xport_sendto(stream, data, datalen, flags, target_addr ? &sa : NULL, sl TSRMLS_CC)); +} +/* }}} */ + +/* {{{ proto string stream_socket_recvfrom(resource stream, long amount [, long flags [, string &remote_addr]]) + Receives data from a socket stream */ +PHP_FUNCTION(stream_socket_recvfrom) +{ + php_stream *stream; + zval *zstream, *zremote = NULL; + long to_read = 0; + char *read_buf; + long flags = 0; + int recvd; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|lz", &zstream, &to_read, &flags, &zremote) == FAILURE) { + RETURN_FALSE; + } + + php_stream_from_zval(stream, &zstream); + + if (zremote) { + zval_dtor(zremote); + ZVAL_NULL(zremote); + Z_STRLEN_P(zremote) = 0; + } + + read_buf = emalloc(to_read + 1); + + recvd = php_stream_xport_recvfrom(stream, read_buf, to_read, flags, NULL, NULL, + zremote ? &Z_STRVAL_P(zremote) : NULL, + zremote ? &Z_STRLEN_P(zremote) : NULL + TSRMLS_CC); + + if (recvd >= 0) { + if (zremote && Z_STRLEN_P(zremote)) { + Z_TYPE_P(zremote) = IS_STRING; + } + read_buf[recvd] = '\0'; + + if (PG(magic_quotes_runtime)) { + Z_TYPE_P(return_value) = IS_STRING; + Z_STRVAL_P(return_value) = php_addslashes(Z_STRVAL_P(return_value), + Z_STRLEN_P(return_value), &Z_STRLEN_P(return_value), 1 TSRMLS_CC); + return; + } else { + RETURN_STRINGL(read_buf, recvd, 0); + } + } + + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto long stream_get_contents(resource source [, long maxlen ]) Reads all remaining bytes (or up to maxlen bytes) from a stream and returns them as a string. */ PHP_FUNCTION(stream_get_contents) Index: php-src/ext/standard/streamsfuncs.h diff -u php-src/ext/standard/streamsfuncs.h:1.6 php-src/ext/standard/streamsfuncs.h:1.7 --- php-src/ext/standard/streamsfuncs.h:1.6 Wed Oct 8 06:07:25 2003 +++ php-src/ext/standard/streamsfuncs.h Sat Nov 29 16:46:47 2003 @@ -16,16 +16,19 @@ +----------------------------------------------------------------------+ */ -/* $Id: streamsfuncs.h,v 1.6 2003/10/08 10:07:25 wez Exp $ */ +/* $Id: streamsfuncs.h,v 1.7 2003/11/29 21:46:47 wez Exp $ */ /* Flags for stream_socket_client */ #define PHP_STREAM_CLIENT_PERSISTENT 1 #define PHP_STREAM_CLIENT_ASYNC_CONNECT 2 +#define PHP_STREAM_CLIENT_CONNECT 4 PHP_FUNCTION(stream_socket_client); PHP_FUNCTION(stream_socket_server); PHP_FUNCTION(stream_socket_accept); PHP_FUNCTION(stream_socket_get_name); +PHP_FUNCTION(stream_socket_recvfrom); +PHP_FUNCTION(stream_socket_sendto); PHP_FUNCTION(stream_copy_to_stream); PHP_FUNCTION(stream_get_contents); Index: php-src/ext/standard/tests/network/tcp4loop.phpt diff -u php-src/ext/standard/tests/network/tcp4loop.phpt:1.1 php-src/ext/standard/tests/network/tcp4loop.phpt:1.2 --- php-src/ext/standard/tests/network/tcp4loop.phpt:1.1 Sun Aug 10 21:30:55 2003 +++ php-src/ext/standard/tests/network/tcp4loop.phpt Sat Nov 29 16:46:48 2003 @@ -1,7 +1,7 @@ --TEST-- Streams Based IPv4 TCP Loopback test --FILE-- -<?php +<?php # vim:ft=php: /* Setup socket server */ $server = stream_socket_server('tcp://127.0.0.1:31337'); if (!$server) { Index: php-src/main/network.c diff -u php-src/main/network.c:1.103 php-src/main/network.c:1.104 --- php-src/main/network.c:1.103 Mon Aug 11 20:58:52 2003 +++ php-src/main/network.c Sat Nov 29 16:46:49 2003 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: network.c,v 1.103 2003/08/12 00:58:52 iliaa Exp $ */ +/* $Id: network.c,v 1.104 2003/11/29 21:46:49 wez Exp $ */ /*#define DEBUG_MAIN_NETWORK 1*/ @@ -478,7 +478,94 @@ } /* }}} */ -static void populate_name( +PHPAPI int php_network_parse_network_address_with_port(const char *addr, long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC) +{ + char *colon; + char *host = NULL; + int is_v6; + char *tmp; + int ret = FAILURE; + short port; + struct sockaddr_in *in4 = (struct sockaddr_in*)sa; + struct sockaddr **sal, **psal; + int n; + char *errstr = NULL; +#ifdef HAVE_IPV6 + char *p; + struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa; +#endif + + if (*addr == '[') { + colon = memchr(addr + 1, ']', addrlen-1); + if (!colon || colon[1] != ':') { + return 0; + } + port = atoi(colon + 2); + addr++; + } else { + colon = memchr(addr, ':', addrlen); + port = atoi(colon + 1); + } + + tmp = estrndup(addr, colon - addr); + + /* first, try interpreting the address as a numeric address */ + +#if HAVE_IPV6 && HAVE_INET_PTON + if (inet_pton(AF_INET6, tmp, &in6->sin6_addr) > 0) { + in6->sin6_port = htons(port); + in6->sin6_family = AF_INET6; + *sl = sizeof(struct sockaddr_in6); + ret = SUCCESS; + goto out; + } +#endif + if (inet_aton(tmp, &in4->sin_addr) > 0) { + in4->sin_port = htons(port); + in4->sin_family = AF_INET; + *sl = sizeof(struct sockaddr_in); + ret = SUCCESS; + goto out; + } + + /* looks like we'll need to resolve it */ + n = php_network_getaddresses(tmp, SOCK_DGRAM, &psal, &errstr TSRMLS_CC); + + if (n == 0) { + if (errstr) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to resolve `%s': %s", tmp, errstr); + STR_FREE(errstr); + } + goto out; + } + + /* copy the details from the first item */ + switch ((*psal)->sa_family) { +#if HAVE_GETADDRINFO && HAVE_IPV6 + case AF_INET6: + *in6 = **(struct sockaddr_in6**)psal; + in6->sin6_port = htons(port); + *sl = sizeof(struct sockaddr_in6); + ret = SUCCESS; + break; +#endif + case AF_INET: + *in4 = **(struct sockaddr_in**)psal; + in4->sin_port = htons(port); + *sl = sizeof(struct sockaddr_in); + ret = SUCCESS; + break; + } + + php_network_freeaddresses(psal); + +out: + STR_FREE(tmp); + return ret; +} + + +PHPAPI void php_network_populate_name_from_sockaddr( /* input address */ struct sockaddr *sa, socklen_t sl, /* output readable address */ @@ -556,7 +643,7 @@ socklen_t sl = sizeof(sa); if (getpeername(sock, (struct sockaddr*)&sa, &sl) == 0) { - populate_name((struct sockaddr*)&sa, sl, + php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, textaddr, textaddrlen, addr, addrlen TSRMLS_CC); @@ -575,7 +662,7 @@ socklen_t sl = sizeof(sa); if (getsockname(sock, (struct sockaddr*)&sa, &sl) == 0) { - populate_name((struct sockaddr*)&sa, sl, + php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, textaddr, textaddrlen, addr, addrlen TSRMLS_CC); @@ -625,7 +712,7 @@ clisock = accept(srvsock, (struct sockaddr*)&sa, &sl); if (clisock >= 0) { - populate_name((struct sockaddr*)&sa, sl, + php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, textaddr, textaddrlen, addr, addrlen TSRMLS_CC); Index: php-src/main/php_network.h diff -u php-src/main/php_network.h:1.45 php-src/main/php_network.h:1.46 --- php-src/main/php_network.h:1.45 Sun Jun 15 19:34:45 2003 +++ php-src/main/php_network.h Sat Nov 29 16:46:49 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_network.h,v 1.45 2003/06/15 23:34:45 edink Exp $ */ +/* $Id: php_network.h,v 1.46 2003/11/29 21:46:49 wez Exp $ */ #ifndef _PHP_NETWORK_H #define _PHP_NETWORK_H @@ -173,6 +173,18 @@ /* open a connection to a host using php_hostconnect and return a stream */ PHPAPI php_stream *_php_stream_sock_open_host(const char *host, unsigned short port, int socktype, struct timeval *timeout, const char *persistent_id STREAMS_DC TSRMLS_DC); +PHPAPI void php_network_populate_name_from_sockaddr( + /* 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); + +PHPAPI int php_network_parse_network_address_with_port(const char *addr, + long addrlen, struct sockaddr *sa, socklen_t *sl TSRMLS_DC); #define php_stream_sock_open_from_socket(socket, persistent) _php_stream_sock_open_from_socket((socket), (persistent) STREAMS_CC TSRMLS_CC) #define php_stream_sock_open_host(host, port, socktype, timeout, persistent) _php_stream_sock_open_host((host), (port), (socktype), (timeout), (persistent) STREAMS_CC TSRMLS_CC) Index: php-src/main/streams/php_stream_transport.h diff -u php-src/main/streams/php_stream_transport.h:1.6 php-src/main/streams/php_stream_transport.h:1.7 --- php-src/main/streams/php_stream_transport.h:1.6 Sun Aug 17 09:49:52 2003 +++ php-src/main/streams/php_stream_transport.h Sat Nov 29 16:46:50 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_stream_transport.h,v 1.6 2003/08/17 13:49:52 sas Exp $ */ +/* $Id: php_stream_transport.h,v 1.7 2003/11/29 21:46:50 wez Exp $ */ #if HAVE_SYS_SOCKET_H # include <sys/socket.h> @@ -88,6 +88,22 @@ void **addr, socklen_t *addrlen TSRMLS_DC); +enum php_stream_xport_send_recv_flags { + STREAM_OOB = 1, + STREAM_PEEK = 2 +}; + +/* Similar to recv() system call; read data from the stream, optionally + * peeking, optionally retrieving OOB data */ +PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t buflen, + long flags, void **addr, socklen_t *addrlen, + char **textaddr, int *textaddrlen TSRMLS_DC); + +/* Similar to send() system call; send data to the stream, optionally + * 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); + /* Structure definition for the set_option interface that the above functions wrap */ typedef struct _php_stream_xport_param { @@ -96,7 +112,9 @@ STREAM_XPORT_OP_LISTEN, STREAM_XPORT_OP_ACCEPT, STREAM_XPORT_OP_CONNECT_ASYNC, STREAM_XPORT_OP_GET_NAME, - STREAM_XPORT_OP_GET_PEER_NAME + STREAM_XPORT_OP_GET_PEER_NAME, + STREAM_XPORT_OP_RECV, + STREAM_XPORT_OP_SEND } op; unsigned int want_addr:1; unsigned int want_textaddr:1; @@ -107,6 +125,11 @@ long namelen; int backlog; struct timeval *timeout; + struct sockaddr *addr; + socklen_t addrlen; + char *buf; + size_t buflen; + long flags; } inputs; struct { php_stream *client; Index: php-src/main/streams/transports.c diff -u php-src/main/streams/transports.c:1.7 php-src/main/streams/transports.c:1.8 --- php-src/main/streams/transports.c:1.7 Thu Nov 27 12:39:01 2003 +++ php-src/main/streams/transports.c Sat Nov 29 16:46:50 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: transports.c,v 1.7 2003/11/27 17:39:01 wez Exp $ */ +/* $Id: transports.c,v 1.8 2003/11/29 21:46:50 wez Exp $ */ #include "php.h" #include "php_streams_int.h" @@ -77,6 +77,10 @@ if (PHP_STREAM_OPTION_RETURN_OK == php_stream_set_option(stream, PHP_STREAM_OPTION_CHECK_LIVENESS, 0, NULL)) { return stream; } + /* dead - kill it */ + php_stream_close(stream); + stream = NULL; + /* fall through */ case PHP_STREAM_PERSISTENT_FAILURE: @@ -366,6 +370,112 @@ return ret; } +/* Similar to recv() system call; read data from the stream, optionally + * peeking, optionally retrieving OOB data */ +PHPAPI int php_stream_xport_recvfrom(php_stream *stream, char *buf, size_t buflen, + long flags, void **addr, socklen_t *addrlen, char **textaddr, int *textaddrlen + TSRMLS_DC) +{ + php_stream_xport_param param; + int ret = 0; + int recvd_len = 0; + int oob; + + if (flags == 0 && addr == NULL) { + return php_stream_read(stream, buf, buflen); + } + + if (stream->readfilters.head) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot peek or fetch OOB data from a filtered stream"); + return -1; + } + + oob = (flags & STREAM_OOB) == STREAM_OOB; + + if (!oob && addr == NULL) { + /* must be peeking at regular data; copy content from the buffer + * first, then adjust the pointer/len before handing off to the + * stream */ + recvd_len = stream->writepos - stream->readpos; + if (recvd_len > buflen) { + recvd_len = buflen; + } + if (recvd_len) { + memcpy(buf, stream->readbuf, recvd_len); + buf += recvd_len; + buflen -= recvd_len; + } + /* if we filled their buffer, return */ + if (buflen == 0) { + return recvd_len; + } + } + + /* otherwise, we are going to bypass the buffer */ + + memset(¶m, 0, sizeof(param)); + + param.op = STREAM_XPORT_OP_RECV; + param.want_addr = addr ? 1 : 0; + param.want_textaddr = textaddr ? 1 : 0; + param.inputs.buf = buf; + param.inputs.buflen = buflen; + param.inputs.flags = flags; + + 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 recvd_len + param.outputs.returncode; + } + return recvd_len ? recvd_len : -1; +} + +/* Similar to send() system call; send data to the stream, optionally + * 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) +{ + php_stream_xport_param param; + int ret = 0; + int oob; + + if (flags == 0 && addr == NULL) { + return php_stream_write(stream, buf, buflen); + } + + oob = (flags & STREAM_OOB) == STREAM_OOB; + + if ((oob || addr) && stream->writefilters.head) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot write OOB data, or data to a targeted address on a filtered stream"); + return -1; + } + + memset(¶m, 0, sizeof(param)); + + param.op = STREAM_XPORT_OP_SEND; + param.want_addr = addr ? 1 : 0; + param.inputs.buf = (char*)buf; + param.inputs.buflen = buflen; + param.inputs.flags = flags; + param.inputs.addr = addr; + param.inputs.addrlen = addrlen; + + ret = php_stream_set_option(stream, PHP_STREAM_OPTION_XPORT_API, 0, ¶m); + + if (ret == PHP_STREAM_OPTION_RETURN_OK) { + return param.outputs.returncode; + } + return -1; +} + /* * Local variables: Index: php-src/main/streams/xp_socket.c diff -u php-src/main/streams/xp_socket.c:1.17 php-src/main/streams/xp_socket.c:1.18 --- php-src/main/streams/xp_socket.c:1.17 Fri Nov 28 18:20:23 2003 +++ php-src/main/streams/xp_socket.c Sat Nov 29 16:46:50 2003 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: xp_socket.c,v 1.17 2003/11/28 23:20:23 wez Exp $ */ +/* $Id: xp_socket.c,v 1.18 2003/11/29 21:46:50 wez Exp $ */ #include "php.h" #include "ext/standard/file.h" @@ -193,9 +193,30 @@ return fstat(sock->socket, &ssb->sb); } +static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t buflen, int flags, + char **textaddr, long *textaddrlen, + struct sockaddr **addr, socklen_t *addrlen + TSRMLS_DC) +{ + php_sockaddr_storage sa; + socklen_t sl = sizeof(sa); + int ret; + int want_addr = textaddr || addr; + + if (want_addr) { + ret = recvfrom(sock->socket, buf, buflen, flags, (struct sockaddr*)&sa, &sl); + php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl, + textaddr, textaddrlen, addr, addrlen TSRMLS_CC); + } else { + ret = recv(sock->socket, buf, buflen, flags); + } + + return ret; +} + static int php_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC) { - int oldmode; + int oldmode, flags; php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; php_stream_xport_param *xparam; @@ -280,6 +301,42 @@ TSRMLS_CC); return PHP_STREAM_OPTION_RETURN_OK; + case STREAM_XPORT_OP_SEND: + flags = 0; + if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) { + flags |= MSG_OOB; + } + xparam->outputs.returncode = sendto(sock->socket, + xparam->inputs.buf, xparam->inputs.buflen, + flags, + xparam->inputs.addr, + xparam->inputs.addrlen); + if (xparam->outputs.returncode == -1) { + char *err = php_socket_strerror(php_socket_errno(), NULL, 0); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "%s\n", err); + efree(err); + } + return PHP_STREAM_OPTION_RETURN_OK; + + case STREAM_XPORT_OP_RECV: + flags = 0; + if ((xparam->inputs.flags & STREAM_OOB) == STREAM_OOB) { + flags |= MSG_OOB; + } + if ((xparam->inputs.flags & STREAM_PEEK) == STREAM_PEEK) { + flags |= MSG_PEEK; + } + xparam->outputs.returncode = sock_recvfrom(sock, + xparam->inputs.buf, xparam->inputs.buflen, + flags, + 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;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php