diff options
Diffstat (limited to 'ext/standard/fsock.c')
-rw-r--r-- | ext/standard/fsock.c | 767 |
1 files changed, 0 insertions, 767 deletions
diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c deleted file mode 100644 index a4f5148b5a..0000000000 --- a/ext/standard/fsock.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP version 4.0 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2001 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.02 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/2_02.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Paul Panotzki - Bunyip Information Systems | - | Jim Winstead <jimw@php.net> | - | Sascha Schumann <sascha@schumann.cx> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* Synced with php 3.0 revision 1.121 1999-06-18 [ssb] */ -/* Synced with php 3.0 revision 1.133 1999-07-21 [sas] */ - -#include "php.h" -#include "php_globals.h" -#include <stdlib.h> -#include <stddef.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_FCNTL_H -# include <fcntl.h> -#endif - -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif - -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef PHP_WIN32 -#include <winsock.h> -#else -#include <netinet/in.h> -#include <netdb.h> -#if HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -#endif -#ifdef PHP_WIN32 -#undef AF_UNIX -#endif -#if defined(AF_UNIX) -#include <sys/un.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#include <string.h> -#include <errno.h> - -#include "base64.h" -#include "file.h" -#include "url.h" -#include "fsock.h" - -#include "php_network.h" - -#ifdef ZTS -static int fsock_globals_id; -#else -extern int le_fp; -#endif - -#define CLOSE_SOCK(free_sock) \ - if(socketd >= 0) { \ - close(socketd); \ - } \ - if (free_sock) { \ - efree(sock); \ - } \ - if (key) { \ - efree(key); \ - } - -#define SEARCHCR() \ - p = memchr(READPTR(sock), '\n', MIN(TOREAD(sock), maxlen)); - -#ifdef PHP_WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#else -#include "build-defs.h" -#endif - -/* {{{ php_lookup_hostname */ - -/* - * Converts a host name to an IP address. - */ -PHPAPI int php_lookup_hostname(const char *addr, struct in_addr *in) -{ - struct hostent *host_info; - - if (!inet_aton(addr, in)) { - /* XXX NOT THREAD SAFE */ - host_info = gethostbyname(addr); - if (host_info == 0) { - /* Error: unknown host */ - return -1; - } - *in = *((struct in_addr *) host_info->h_addr); - } - return 0; -} -/* }}} */ -/* {{{ php_is_persistent_sock */ - -PHPAPI int php_is_persistent_sock(int sock) -{ - char *key; - FLS_FETCH(); - - if (zend_hash_find(&FG(ht_fsock_socks), (char *) &sock, sizeof(sock), - (void **) &key) == SUCCESS) { - return 1; - } - return 0; -} -/* }}} */ -/* {{{ php_fsockopen() */ - -/* - This function takes an optional third argument which should be - passed by reference. The error code from the connect call is written - to this variable. -*/ -static void php_fsockopen(INTERNAL_FUNCTION_PARAMETERS, int persistent) { - pval **args[5]; - int *sock=emalloc(sizeof(int)); - int *sockp; - int arg_count=ZEND_NUM_ARGS(); - int socketd = -1; - unsigned char udp = 0; - struct timeval timeout = { 60, 0 }; - unsigned short portno; - unsigned long conv; - char *key = NULL; - FLS_FETCH(); - - if (arg_count > 5 || arg_count < 2 || zend_get_parameters_array_ex(arg_count,args)==FAILURE) { - CLOSE_SOCK(1); - WRONG_PARAM_COUNT; - } - switch(arg_count) { - case 5: - convert_to_double_ex(args[4]); - conv = (unsigned long) ((*args[4])->value.dval * 1000000.0); - timeout.tv_sec = conv / 1000000; - timeout.tv_usec = conv % 1000000; - /* fall-through */ - case 4: - zval_dtor(*args[3]); - ZVAL_STRING(*args[3],"",1); - /* fall-through */ - case 3: - zval_dtor(*args[2]); - ZVAL_LONG(*args[2],0); - break; - } - convert_to_string_ex(args[0]); - convert_to_long_ex(args[1]); - portno = (unsigned short) (*args[1])->value.lval; - - key = emalloc((*args[0])->value.str.len + 10); - sprintf(key, "%s:%d", (*args[0])->value.str.val, portno); - - if (persistent && zend_hash_find(&FG(ht_fsock_keys), key, strlen(key) + 1, - (void *) &sockp) == SUCCESS) { - CLOSE_SOCK(0); - *sock = *sockp; - ZEND_REGISTER_RESOURCE(return_value,sock,php_file_le_socket()); - return; - } - - if (portno) { - struct sockaddr_in server; - - memset(&server, 0, sizeof(server)); - if(Z_STRLEN_PP(args[0]) >= 6 && !memcmp(Z_STRVAL_PP(args[0]), "udp://", sizeof("udp://")-1)) { - udp = 1; - } - - socketd = socket(AF_INET,udp ? SOCK_DGRAM : SOCK_STREAM,0); - - if (socketd == SOCK_ERR) { - CLOSE_SOCK(1); - RETURN_FALSE; - } - - server.sin_family = AF_INET; - - if(php_lookup_hostname(udp ? &(*args[0])->value.str.val[6] : (*args[0])->value.str.val,&server.sin_addr)) { - CLOSE_SOCK(1); - RETURN_FALSE; - } - - server.sin_port = htons(portno); - - if (php_connect_nonb(socketd, (struct sockaddr *)&server, sizeof(server), &timeout) == SOCK_CONN_ERR) { - CLOSE_SOCK(1); - - if (arg_count>2) { - zval_dtor(*args[2]); - ZVAL_LONG(*args[2],errno); - } - if (arg_count>3) { - zval_dtor(*args[3]); - ZVAL_STRING(*args[3],strerror(errno),1); - } - RETURN_FALSE; - } -#if defined(AF_UNIX) - } else { - /* Unix domain socket. s->strval is socket name. */ - struct sockaddr_un unix_addr; - socketd = socket(AF_UNIX,SOCK_STREAM,0); - if (socketd == SOCK_ERR) { - CLOSE_SOCK(1); - RETURN_FALSE; - } - - memset(&unix_addr, (char)0, sizeof(unix_addr)); - unix_addr.sun_family = AF_UNIX; - strlcpy(unix_addr.sun_path, (*args[0])->value.str.val, sizeof(unix_addr.sun_path)); - - if (php_connect_nonb(socketd, (struct sockaddr *) &unix_addr, sizeof(unix_addr), &timeout) == SOCK_CONN_ERR) { - CLOSE_SOCK(1); - if (arg_count>2) { - zval_dtor(*args[2]); - ZVAL_LONG(*args[2],errno); - } - if (arg_count>3) { - zval_dtor(*args[3]); - ZVAL_STRING(*args[3],strerror(errno),1); - } - RETURN_FALSE; - } -#endif /* AF_UNIX */ - } - -#if 0 - if ((fp = fdopen (socketd, "r+")) == NULL){ - RETURN_LONG(-6); /* FIXME */ - } - -#ifdef HAVE_SETVBUF - if ((setvbuf(fp, NULL, _IONBF, 0)) != 0){ - RETURN_LONG(-7); /* FIXME */ - } -#endif -#endif - - *sock=socketd; - if (persistent) { - zend_hash_update(&FG(ht_fsock_keys), key, strlen(key) + 1, - sock, sizeof(*sock), NULL); - zend_hash_update(&FG(ht_fsock_socks), (char *) sock, sizeof(*sock), - key, strlen(key) + 1, NULL); - } - if(key) efree(key); - - ZEND_REGISTER_RESOURCE(return_value,sock,php_file_le_socket()); -} -/* }}} */ - -/* {{{ proto int fsockopen(string hostname, int port [, int errno [, string errstr [, double timeout]]]) - Open Internet or Unix domain socket connection */ -PHP_FUNCTION(fsockopen) -{ - php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); -} -/* }}} */ -/* {{{ proto int pfsockopen(string hostname, int port [, int errno [, string errstr [, double timeout]]]) - Open persistent Internet or Unix domain socket connection */ -PHP_FUNCTION(pfsockopen) -{ - php_fsockopen(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); -} -/* }}} */ - -#define SOCK_DESTROY(sock) \ - if(sock->readbuf) pefree(sock->readbuf, sock->persistent); \ - if(sock->prev) sock->prev->next = sock->next; \ - if(sock->next) sock->next->prev = sock->prev; \ - if(sock == FG(phpsockbuf)) \ - FG(phpsockbuf) = sock->next; \ - pefree(sock, sock->persistent) - -PHPAPI void php_cleanup_sockbuf(int persistent FLS_DC) -{ - php_sockbuf *now, *next; - - for(now = FG(phpsockbuf); now; now = next) { - next = now->next; - if(now->persistent == persistent) { - SOCK_DESTROY(now); - } - } -} - -#define TOREAD(sock) ((sock)->writepos - (sock)->readpos) -#define READPTR(sock) ((sock)->readbuf + (sock)->readpos) -#define WRITEPTR(sock) ((sock)->readbuf + (sock)->writepos) -#define SOCK_FIND(sock,socket) \ - php_sockbuf *sock; \ - FLS_FETCH(); \ - sock = php_sockfind(socket FLS_CC); \ - if(!sock) sock = php_sockcreate(socket FLS_CC) - -static php_sockbuf *php_sockfind(int socket FLS_DC) -{ - php_sockbuf *buf = NULL, *tmp; - - for(tmp = FG(phpsockbuf); tmp; tmp = tmp->next) - if(tmp->socket == socket) { - buf = tmp; - break; - } - - return buf; -} - -static php_sockbuf *php_sockcreate(int socket FLS_DC) -{ - php_sockbuf *sock; - int persistent = php_is_persistent_sock(socket); - - sock = pecalloc(sizeof(*sock), 1, persistent); - sock->socket = socket; - if((sock->next = FG(phpsockbuf))) - FG(phpsockbuf)->prev = sock; - sock->persistent = persistent; - sock->is_blocked = 1; - sock->chunk_size = FG(def_chunk_size); - sock->timeout.tv_sec = -1; - FG(phpsockbuf) = sock; - - return sock; -} - -PHPAPI php_sockbuf *php_get_socket(int socket) -{ - SOCK_FIND(sock, socket); - return sock; -} - -PHPAPI size_t php_sock_set_def_chunk_size(size_t size) -{ - size_t old; - FLS_FETCH(); - - old = FG(def_chunk_size); - - if(size <= PHP_FSOCK_CHUNK_SIZE || size > 0) - FG(def_chunk_size) = size; - - return old; -} - -PHPAPI int php_sockdestroy(int socket) -{ - int ret = 0; - php_sockbuf *sock; - FLS_FETCH(); - - sock = php_sockfind(socket FLS_CC); - if(sock) { - ret = 1; - SOCK_DESTROY(sock); - } - - return ret; -} - -#if !defined(PHP_WIN32) -#undef closesocket -#define closesocket close -#endif - -#ifndef HAVE_SHUTDOWN -#undef shutdown -#define shutdown -#endif - -#define SOCK_CLOSE(s) shutdown(s, 0); closesocket(s) - -PHPAPI int php_sock_close(int socket) -{ - int ret = 0; - php_sockbuf *sock; - FLS_FETCH(); - - sock = php_sockfind(socket FLS_CC); - if(sock) { - if(!sock->persistent) { - SOCK_CLOSE(sock->socket); - SOCK_DESTROY(sock); - } - } else { - SOCK_CLOSE(socket); - } - - return ret; -} - -#define MAX_CHUNKS_PER_READ 10 - -static void php_sockwait_for_data(php_sockbuf *sock) -{ - fd_set fdr, tfdr; - int retval; - struct timeval timeout, *ptimeout; - - FD_ZERO(&fdr); - FD_SET(sock->socket, &fdr); - sock->timeout_event = 0; - - if (sock->timeout.tv_sec == -1) - ptimeout = NULL; - else - ptimeout = &timeout; - - while(1) { - tfdr = fdr; - timeout = sock->timeout; - - retval = select(sock->socket + 1, &tfdr, NULL, NULL, ptimeout); - - if (retval == 0) - sock->timeout_event = 1; - - if (retval >= 0) - break; - } -} - -static size_t php_sockread_internal(php_sockbuf *sock) -{ - char buf[PHP_FSOCK_CHUNK_SIZE]; - int nr_bytes; - size_t nr_read = 0; - - /* For blocking sockets, we wait until there is some - data to read (real data or EOF) - - Otherwise, recv() may time out and return 0 and - therefore sock->eof would be set errornously. - */ - - - if(sock->is_blocked) { - php_sockwait_for_data(sock); - if (sock->timeout_event) - return 0; - } - - /* read at a maximum sock->chunk_size */ - nr_bytes = recv(sock->socket, buf, sock->chunk_size, 0); - if(nr_bytes > 0) { - if(sock->writepos + nr_bytes > sock->readbuflen) { - sock->readbuflen += sock->chunk_size; - sock->readbuf = perealloc(sock->readbuf, sock->readbuflen, - sock->persistent); - } - memcpy(WRITEPTR(sock), buf, nr_bytes); - sock->writepos += nr_bytes; - nr_read = nr_bytes; - } else if(nr_bytes == 0 || (nr_bytes < 0 && errno != EWOULDBLOCK)) { - sock->eof = 1; - } - - return nr_read; -} - -static void php_sockread_total(php_sockbuf *sock, size_t maxread) -{ - while(!sock->eof && TOREAD(sock) < maxread && !sock->timeout_event) { - php_sockread_internal(sock); - } -} - -static size_t php_sockread(php_sockbuf *sock) -{ - size_t nr_bytes; - size_t nr_read = 0; - int i; - - for(i = 0; !sock->eof && i < MAX_CHUNKS_PER_READ; i++) { - nr_bytes = php_sockread_internal(sock); - if(nr_bytes == 0) break; - nr_read += nr_bytes; - } - - return nr_read; -} - -PHPAPI int php_sockset_blocking(int socket, int mode) -{ - int old; - SOCK_FIND(sock, socket); - - old = sock->is_blocked; - - sock->is_blocked = mode; - - return old; -} - -PHPAPI void php_sockset_timeout(int socket, struct timeval *timeout) -{ - SOCK_FIND(sock, socket); - - sock->timeout = *timeout; - sock->timeout_event = 0; -} - -#define SOCK_FIND_AND_READ_MAX(max) \ - SOCK_FIND(sock, socket); \ - if(sock->is_blocked) php_sockread_total(sock, max); else php_sockread(sock) - -/* {{{ php_sock_fgets() */ -/* - * FIXME: fgets depends on '\n' as line delimiter - */ -static char * php_sock_fgets_internal(char * buf, size_t maxlen, php_sockbuf * sock) -{ - char *p = NULL; - char *ret = NULL; - size_t amount = 0; - - if (maxlen==0) { - buf[0] = 0; - return buf; - } - - SEARCHCR(); - - if(!p) { - if(sock->is_blocked) { - while(!p && !sock->eof && !sock->timeout_event && TOREAD(sock) < maxlen) { - php_sockread_internal(sock); - SEARCHCR(); - } - } else { - php_sockread(sock); - SEARCHCR(); - } - } - - - if(p) { - amount = (ptrdiff_t) p - (ptrdiff_t) READPTR(sock) + 1; - } else { - amount = TOREAD(sock); - } - - amount = MIN(amount, maxlen); - - if(amount > 0) { - memcpy(buf, READPTR(sock), amount); - sock->readpos += amount; - } - buf[amount] = '\0'; - - /* signal error only, if we don't return data from this call and - if there is no data to read and if the eof flag is set */ - if(amount || TOREAD(sock) || !sock->eof) { - ret = buf; - } - - return ret; -} -PHPAPI char *php_sock_fgets(char *buf, size_t maxlen, int socket) -{ - SOCK_FIND(sock, socket); - return php_sock_fgets_internal(buf, maxlen, sock); -} - - -/* }}} */ - -/* - * FIXME: fgetc returns EOF, if no data is available on a nonblocking socket. - * I don't have any documentation on the semantics of fgetc in this case. - * - * ss@2ns.de 19990528 - */ - -PHPAPI int php_sock_fgetc(int socket) -{ - int ret = EOF; - SOCK_FIND_AND_READ_MAX(1); - - if(TOREAD(sock) > 0) { - ret = *READPTR(sock); - sock->readpos++; - } - - return ret; -} - -PHPAPI int php_sock_feof(int socket) -{ - int ret = 0; - SOCK_FIND(sock, socket); - - if(!sock->is_blocked) - php_sockread(sock); - - if(!TOREAD(sock) && sock->eof) - ret = 1; - - return ret; -} - -/* {{{ stream abstraction */ -#if HAVE_PHP_STREAM -static size_t php_sockop_write(php_stream * stream, const char * buf, size_t count) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - return send(sock->socket, buf, count, 0); -} - -static size_t php_sockop_read(php_stream * stream, char * buf, size_t count) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - size_t ret = 0; - - if (sock->is_blocked) - php_sockread_total(sock, count); - else - php_sockread(sock); - - if(count < 0) - return ret; - - ret = MIN(TOREAD(sock), count); - if (ret) { - memcpy(buf, READPTR(sock), ret); - sock->readpos += ret; - } - - return ret; -} - -static int php_sockop_close(php_stream * stream) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - - SOCK_CLOSE(sock->socket); - SOCK_DESTROY(sock); - - return 0; -} - -static int php_sockop_flush(php_stream * stream) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - return fsync(sock->socket); -} - -static int php_sockop_cast(php_stream * stream, int castas, void ** ret) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - - switch(castas) { - case PHP_STREAM_AS_STDIO: - if (ret) { - /* DANGER!: data buffered in stream->readbuf will be forgotten! */ - if (TOREAD(sock) > 0) - zend_error(E_WARNING, "%s(): buffered data lost during conversion to FILE*!", get_active_function_name()); - *ret = fdopen(sock->socket, stream->mode); - if (*ret) - return SUCCESS; - return FAILURE; - } - return SUCCESS; - case PHP_STREAM_AS_FD: - case PHP_STREAM_AS_SOCKETD: - if (ret) - *ret = (void*)sock->socket; - return SUCCESS; - default: - return FAILURE; - } -} - -static char * php_sockop_gets(php_stream * stream, char *buf, size_t size) -{ - php_sockbuf * sock = (php_sockbuf*)stream->abstract; - return php_sock_fgets_internal(buf, size, sock); -} - -php_stream_ops php_stream_socket_ops = { - php_sockop_write, php_sockop_read, - php_sockop_close, php_sockop_flush, - NULL, php_sockop_gets, - php_sockop_cast, - "socket" -}; -#endif -/* }}} */ - -/* {{{ php_sock_fread() */ - -PHPAPI size_t php_sock_fread(char *ptr, size_t size, int socket) -{ - size_t ret = 0; - SOCK_FIND_AND_READ_MAX(size); - - if(size < 0) - return ret; - - ret = MIN(TOREAD(sock), size); - if(ret) { - memcpy(ptr, READPTR(sock), ret); - sock->readpos += ret; - } - - return ret; -} - -/* }}} */ - -/* {{{ module start/shutdown functions */ - - /* {{{ php_msock_destroy */ -PHPAPI void php_msock_destroy(int *data) -{ - close(*data); -} -/* }}} */ - - - -PHP_RSHUTDOWN_FUNCTION(fsock) -{ - FLS_FETCH(); - - php_cleanup_sockbuf(0 FLS_CC); - return SUCCESS; -} -/* }}} */ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 tw=78 fdm=marker - * vim<600: sw=4 ts=4 tw=78 - */ |