Browse Source

Remove php_stream_sock_set_blocking and replace with

php_stream_set_option which can be used in a similar way as ioctl()
to set options for streams.

Current options include buffering and blocking support.

o Buffer control is support for stdio based streams.
o Blocking/non-blocking is supported for stdio and socket based streams.
experimental/new_apache_hooks
Wez Furlong 24 years ago
parent
commit
5f9a5a7c8e
  1. 25
      ext/standard/file.c
  2. 56
      main/network.c
  3. 1
      main/php_network.h
  4. 17
      main/php_streams.h
  5. 66
      main/streams.c

25
ext/standard/file.c

@ -957,7 +957,7 @@ PHPAPI PHP_FUNCTION(feof)
/* }}} */
/* {{{ proto bool socket_set_blocking(resource socket, int mode)
Set blocking/non-blocking mode on a socket */
Set blocking/non-blocking mode on a socket or stream */
PHP_FUNCTION(socket_set_blocking)
{
zval **arg1, **arg2;
@ -974,11 +974,9 @@ PHP_FUNCTION(socket_set_blocking)
convert_to_long_ex(arg2);
block = Z_LVAL_PP(arg2);
if (php_stream_is((php_stream*)what, PHP_STREAM_IS_SOCKET)) {
php_stream_sock_set_blocking((php_stream*)what, block == 0 ? 0 : 1 TSRMLS_CC);
RETURN_TRUE;
}
RETURN_FALSE;
if (php_stream_set_option((php_stream*)what, PHP_STREAM_OPTION_BLOCKING, block == 0 ? 0 : 1, NULL) == -1)
RETURN_FALSE;
RETURN_TRUE;
}
/* }}} */
@ -1344,9 +1342,9 @@ PHPAPI PHP_FUNCTION(fflush)
PHP_FUNCTION(set_file_buffer)
{
zval **arg1, **arg2;
int ret, type, buff;
int ret, type;
size_t buff;
php_stream *stream;
FILE * fp;
switch (ZEND_NUM_ARGS()) {
case 2:
@ -1359,21 +1357,18 @@ PHP_FUNCTION(set_file_buffer)
/* NOTREACHED */
break;
}
stream = (php_stream*)zend_fetch_resource(arg1 TSRMLS_CC,-1, "File-Handle", &type, 1, le_stream);
ZEND_VERIFY_RESOURCE(stream);
if (!php_stream_is(stream, PHP_STREAM_IS_STDIO) || FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
RETURN_FALSE;
}
convert_to_long_ex(arg2);
buff = Z_LVAL_PP(arg2);
/* if buff is 0 then set to non-buffered */
if (buff == 0){
ret = setvbuf(fp, NULL, _IONBF, 0);
if (buff == 0) {
ret = php_stream_set_option(stream, PHP_STREAM_OPTION_BUFFER, PHP_STREAM_BUFFER_NONE, NULL);
} else {
ret = setvbuf(fp, NULL, _IOFBF, buff);
ret = php_stream_set_option(stream, PHP_STREAM_OPTION_BUFFER, PHP_STREAM_BUFFER_FULL, &buff);
}
RETURN_LONG(ret);

56
main/network.c

@ -13,6 +13,7 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Stig Venaas <venaas@uninett.no> |
| Streams work by Wez Furlong <wez@thebrainroom.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
@ -668,28 +669,6 @@ PHPAPI int php_set_sock_blocking(int socketd, int block TSRMLS_DC)
return ret;
}
PHPAPI int php_stream_sock_set_blocking(php_stream *stream, int mode TSRMLS_DC)
{
int oldmode;
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET))
return 0;
oldmode = sock->is_blocked;
/* no need to change anything */
if (mode == oldmode)
return oldmode;
if (SUCCESS == php_set_sock_blocking(sock->socket, mode TSRMLS_CC)) {
sock->is_blocked = mode;
return oldmode;
}
return -1;
}
PHPAPI size_t php_stream_sock_set_chunk_size(php_stream *stream, size_t size TSRMLS_DC)
{
size_t oldsize;
@ -887,9 +866,9 @@ DUMP_SOCK_STATE("check for EOF", sock);
* socket is still active, try to read a chunk of data,
* but lets not block. */
sock->timeout_event = 0;
save_blocked = php_stream_sock_set_blocking(stream, 1 TSRMLS_CC);
save_blocked = php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, 0, NULL);
php_sock_stream_read_internal(stream, sock TSRMLS_CC);
php_stream_sock_set_blocking(stream, save_blocked TSRMLS_CC);
php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, save_blocked, NULL);
if (sock->eof)
return EOF;
@ -961,6 +940,32 @@ static int php_sockop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC
return fstat(sock->socket, &ssb->sb);
}
static int php_sockop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
{
int oldmode;
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
switch(option) {
case PHP_STREAM_OPTION_BLOCKING:
oldmode = sock->is_blocked;
/* no need to change anything */
if (value == oldmode)
return oldmode;
if (SUCCESS == php_set_sock_blocking(sock->socket, value TSRMLS_CC)) {
sock->is_blocked = value;
return oldmode;
}
return -1;
default:
return -1;
}
}
static int php_sockop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
{
php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract;
@ -1065,7 +1070,8 @@ php_stream_ops php_stream_socket_ops = {
"socket",
NULL, php_sockop_gets,
php_sockop_cast,
php_sockop_stat
php_sockop_stat,
php_sockop_set_option
};

1
main/php_network.h

@ -144,7 +144,6 @@ PHPAPI php_stream *_php_stream_sock_open_unix(const char *path, int pathlen, int
/* }}} */
PHPAPI void php_stream_sock_set_timeout(php_stream *stream, struct timeval *timeout TSRMLS_DC);
PHPAPI int php_stream_sock_set_blocking(php_stream *stream, int mode TSRMLS_DC);
/* set the chunk size for the stream; return the old chunk size */
PHPAPI size_t php_stream_sock_set_chunk_size(php_stream *stream, size_t size TSRMLS_DC);

17
main/php_streams.h

@ -101,7 +101,7 @@ typedef void (*php_stream_notification_func)(php_stream_context *context,
typedef struct _php_stream_statbuf {
struct stat sb; /* regular info */
/* extended info to go here some day */
/* extended info to go here some day: content-type etc. etc. */
} php_stream_statbuf;
typedef struct _php_stream_dirent {
@ -147,6 +147,7 @@ typedef struct _php_stream_ops {
char *(*gets)(php_stream *stream, char *buf, size_t size TSRMLS_DC);
int (*cast)(php_stream *stream, int castas, void **ret TSRMLS_DC);
int (*stat)(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC);
int (*set_option)(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC);
} php_stream_ops;
typedef struct _php_stream_wrapper_ops {
@ -283,6 +284,19 @@ PHPAPI php_stream_dirent *_php_stream_readdir(php_stream *dirstream, php_stream_
#define php_stream_closedir(dirstream) php_stream_close((dirstream))
#define php_stream_rewinddir(dirstream) php_stream_rewind((dirstream))
PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC);
#define php_stream_set_option(stream, option, value, ptrvalue) _php_stream_set_option((stream), (option), (value), (ptrvalue) TSRMLS_CC)
/* change the blocking mode of stream: value == 1 => blocking, value == 0 => non-blocking. */
#define PHP_STREAM_OPTION_BLOCKING 1
/* change the buffering mode of stream. value is a PHP_STREAM_BUFFER_XXXX value, ptrparam is a ptr to a size_t holding
* the required buffer size */
#define PHP_STREAM_OPTION_BUFFER 2
#define PHP_STREAM_BUFFER_NONE 0 /* unbuffered */
#define PHP_STREAM_BUFFER_LINE 1 /* line buffered */
#define PHP_STREAM_BUFFER_FULL 2 /* fully buffered */
/* copy up to maxlen bytes from src to dest. If maxlen is PHP_STREAM_COPY_ALL, copy until eof(src).
* Uses mmap if the src is a plain file and at offset 0 */
@ -419,6 +433,7 @@ PHPAPI int php_stream_context_set_option(php_stream_context *context,
PHPAPI php_stream_notifier *php_stream_notification_alloc(void);
PHPAPI void php_stream_notification_free(php_stream_notifier *notifier);
/* not all notification codes are implemented */
#define PHP_STREAM_NOTIFY_RESOLVE 1
#define PHP_STREAM_NOTIFY_CONNECT 2
#define PHP_STREAM_NOTIFY_AUTH_REQUIRED 3

66
main/streams.c

@ -33,6 +33,8 @@
#include <sys/mman.h>
#endif
#include <fcntl.h>
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
@ -311,6 +313,13 @@ PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_
return -1;
}
PHPAPI int _php_stream_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
{
if (stream->ops->set_option)
return stream->ops->set_option(stream, option, value, ptrparam TSRMLS_CC);
return -1;
}
PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
{
size_t bcount = 0;
@ -742,13 +751,68 @@ static int php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC
return fstat(fd, &ssb->sb);
}
static int php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam TSRMLS_DC)
{
php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract;
size_t size;
int fd;
int flags;
int oldval;
switch(option) {
case PHP_STREAM_OPTION_BLOCKING:
fd = fileno(data->file);
if (fd == -1)
return -1;
#ifdef O_NONBLOCK
flags = fcntl(fd, F_GETFL, 0);
oldval = (flags & O_NONBLOCK) ? 0 : 1;
if (value)
flags ^= O_NONBLOCK;
else
flags |= O_NONBLOCK;
if (-1 == fcntl(fd, F_SETFL, flags))
return -1;
return oldval;
#else
return -1; /* not yet implemented */
#endif
case PHP_STREAM_OPTION_BUFFER:
if (ptrparam)
size = *(size_t *)ptrparam;
else
size = BUFSIZ;
switch(value) {
case PHP_STREAM_BUFFER_NONE:
return setvbuf(data->file, NULL, _IONBF, 0);
case PHP_STREAM_BUFFER_LINE:
return setvbuf(data->file, NULL, _IOLBF, size);
case PHP_STREAM_BUFFER_FULL:
return setvbuf(data->file, NULL, _IOFBF, size);
default:
return -1;
}
break;
default:
return -1;
}
}
PHPAPI php_stream_ops php_stream_stdio_ops = {
php_stdiop_write, php_stdiop_read,
php_stdiop_close, php_stdiop_flush,
"STDIO",
php_stdiop_seek,
php_stdiop_gets, php_stdiop_cast,
php_stdiop_stat
php_stdiop_stat,
php_stdiop_set_option
};
/* }}} */

Loading…
Cancel
Save