summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/streams/php_stream_context.h8
-rwxr-xr-xmain/streams/streams.c69
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;
+}
/* }}} */
/*