diff options
| -rw-r--r-- | main/streams/php_stream_context.h | 8 | ||||
| -rwxr-xr-x | main/streams/streams.c | 69 |
2 files changed, 77 insertions, 0 deletions
diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h index 7bc0233028..296687e6a3 100644 --- a/main/streams/php_stream_context.h +++ b/main/streams/php_stream_context.h @@ -53,6 +53,7 @@ struct _php_stream_notifier { struct _php_stream_context { php_stream_notifier *notifier; zval *options; /* hash keyed by wrapper family or specific wrapper */ + zval *links; /* hash keyed by hostent for connection pooling */ int rsrc_id; /* used for auto-cleanup */ }; @@ -63,6 +64,13 @@ PHPAPI int php_stream_context_get_option(php_stream_context *context, PHPAPI int php_stream_context_set_option(php_stream_context *context, const char *wrappername, const char *optionname, zval *optionvalue); +PHPAPI int php_stream_context_get_link(php_stream_context *context, + const char *hostent, php_stream **stream); +PHPAPI int php_stream_context_set_link(php_stream_context *context, + const char *hostent, php_stream *stream); +PHPAPI int php_stream_context_del_link(php_stream_context *context, + php_stream *stream); + PHPAPI php_stream_notifier *php_stream_notification_alloc(void); PHPAPI void php_stream_notification_free(php_stream_notifier *notifier); diff --git a/main/streams/streams.c b/main/streams/streams.c index ee0eba027e..2d84f680ab 100755 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -306,6 +306,11 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov zend_list_delete(stream->rsrc_id); } + /* Remove stream from any context link list */ + if (stream->context && stream->context->links) { + php_stream_context_del_link(stream->context, stream); + } + if (close_options & PHP_STREAM_FREE_CALL_DTOR) { if (release_cast && stream->fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE) { /* calling fclose on an fopencookied stream will ultimately @@ -1626,6 +1631,10 @@ PHPAPI void php_stream_context_free(php_stream_context *context) php_stream_notification_free(context->notifier); context->notifier = NULL; } + if (context->links) { + zval_ptr_dtor(&context->links); + context->links = NULL; + } efree(context); } @@ -1688,6 +1697,66 @@ PHPAPI int php_stream_context_set_option(php_stream_context *context, } return zend_hash_update(Z_ARRVAL_PP(wrapperhash), (char*)optionname, strlen(optionname)+1, (void**)&copied_val, sizeof(zval *), NULL); } + +PHPAPI int php_stream_context_get_link(php_stream_context *context, + const char *hostent, php_stream **stream) +{ + php_stream **pstream; + + if (!stream || !hostent || !context || !(context->links)) { + return FAILURE; + } + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1, (void**)&pstream)) { + *stream = *pstream; + return SUCCESS; + } + return FAILURE; +} + +PHPAPI int php_stream_context_set_link(php_stream_context *context, + const char *hostent, php_stream *stream) +{ + if (!context) { + return FAILURE; + } + if (!context->links) { + ALLOC_INIT_ZVAL(context->links); + array_init(context->links); + } + if (!stream) { + /* Delete any entry for <hostent> */ + return zend_hash_del(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1); + } + return zend_hash_update(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1, (void**)&stream, sizeof(php_stream *), NULL); +} + +PHPAPI int php_stream_context_del_link(php_stream_context *context, + php_stream *stream) +{ + php_stream **pstream; + char *hostent; + int ret = SUCCESS; + + if (!context || !context->links || !stream) { + return FAILURE; + } + + for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(context->links)); + SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(context->links), (void**)&pstream); + zend_hash_move_forward(Z_ARRVAL_P(context->links))) { + if (*pstream == stream) { + if (SUCCESS == zend_hash_get_current_key(Z_ARRVAL_P(context->links), &hostent, NULL, 0)) { + if (FAILURE == zend_hash_del(Z_ARRVAL_P(context->links), (char*)hostent, strlen(hostent)+1)) { + ret = FAILURE; + } + } else { + ret = FAILURE; + } + } + } + + return ret; +} /* }}} */ /* |
