PHP: persistent channel
This commit is contained in:
parent
1ba000e1e2
commit
5b3dc4aa75
|
|
@ -214,10 +214,12 @@ PHP_METHOD(Call, __construct) {
|
|||
return;
|
||||
}
|
||||
wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj);
|
||||
if (channel->wrapped == NULL) {
|
||||
gpr_mu_lock(&channel->wrapper->mu);
|
||||
if (channel->wrapper->wrapped == NULL) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"Call cannot be constructed from a closed Channel",
|
||||
1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
add_property_zval(getThis(), "channel", channel_obj);
|
||||
|
|
@ -226,13 +228,15 @@ PHP_METHOD(Call, __construct) {
|
|||
grpc_slice host_slice = host_override != NULL ?
|
||||
grpc_slice_from_copied_string(host_override) : grpc_empty_slice();
|
||||
call->wrapped =
|
||||
grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS,
|
||||
grpc_channel_create_call(channel->wrapper->wrapped, NULL,
|
||||
GRPC_PROPAGATE_DEFAULTS,
|
||||
completion_queue, method_slice,
|
||||
host_override != NULL ? &host_slice : NULL,
|
||||
deadline->wrapped, NULL);
|
||||
grpc_slice_unref(method_slice);
|
||||
grpc_slice_unref(host_slice);
|
||||
call->owned = true;
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
|
|||
zend_fcall_info *fci;
|
||||
zend_fcall_info_cache *fci_cache;
|
||||
|
||||
fci = (zend_fcall_info *)emalloc(sizeof(zend_fcall_info));
|
||||
fci_cache = (zend_fcall_info_cache *)emalloc(sizeof(zend_fcall_info_cache));
|
||||
fci = (zend_fcall_info *)malloc(sizeof(zend_fcall_info));
|
||||
fci_cache = (zend_fcall_info_cache *)malloc(sizeof(zend_fcall_info_cache));
|
||||
memset(fci, 0, sizeof(zend_fcall_info));
|
||||
memset(fci_cache, 0, sizeof(zend_fcall_info_cache));
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ PHP_METHOD(CallCredentials, createFromPlugin) {
|
|||
}
|
||||
|
||||
plugin_state *state;
|
||||
state = (plugin_state *)emalloc(sizeof(plugin_state));
|
||||
state = (plugin_state *)malloc(sizeof(plugin_state));
|
||||
memset(state, 0, sizeof(plugin_state));
|
||||
|
||||
/* save the user provided PHP callback function */
|
||||
|
|
@ -210,13 +210,13 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context,
|
|||
/* Cleanup function for plugin creds API */
|
||||
void plugin_destroy_state(void *ptr) {
|
||||
plugin_state *state = (plugin_state *)ptr;
|
||||
efree(state->fci);
|
||||
efree(state->fci_cache);
|
||||
free(state->fci);
|
||||
free(state->fci_cache);
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
PHP_GRPC_FREE_STD_ZVAL(state->fci->params);
|
||||
PHP_GRPC_FREE_STD_ZVAL(state->fci->retval);
|
||||
#endif
|
||||
efree(state);
|
||||
free(state);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_createComposite, 0, 0, 2)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@
|
|||
#include <php.h>
|
||||
#include <php_ini.h>
|
||||
#include <ext/standard/info.h>
|
||||
#include <ext/standard/php_var.h>
|
||||
#include <ext/standard/sha1.h>
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
#include <ext/standard/php_smart_str.h>
|
||||
#else
|
||||
#include <zend_smart_str.h>
|
||||
#endif
|
||||
#include <ext/spl/spl_exceptions.h>
|
||||
#include "php_grpc.h"
|
||||
|
||||
|
|
@ -44,11 +51,25 @@ zend_class_entry *grpc_ce_channel;
|
|||
#if PHP_MAJOR_VERSION >= 7
|
||||
static zend_object_handlers channel_ce_handlers;
|
||||
#endif
|
||||
static gpr_mu global_persistent_list_mu;
|
||||
int le_plink;
|
||||
|
||||
/* Frees and destroys an instance of wrapped_grpc_channel */
|
||||
PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
|
||||
if (p->wrapped != NULL) {
|
||||
grpc_channel_destroy(p->wrapped);
|
||||
if (p->wrapper != NULL) {
|
||||
gpr_mu_lock(&p->wrapper->mu);
|
||||
if (p->wrapper->wrapped != NULL) {
|
||||
php_grpc_zend_resource *rsrc;
|
||||
php_grpc_int key_len = strlen(p->wrapper->key);
|
||||
// only destroy the channel here if not found in the persistent list
|
||||
gpr_mu_lock(&global_persistent_list_mu);
|
||||
if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), p->wrapper->key,
|
||||
key_len, rsrc))) {
|
||||
grpc_channel_destroy(p->wrapper->wrapped);
|
||||
}
|
||||
gpr_mu_unlock(&global_persistent_list_mu);
|
||||
}
|
||||
gpr_mu_unlock(&p->wrapper->mu);
|
||||
}
|
||||
PHP_GRPC_FREE_WRAPPED_FUNC_END()
|
||||
|
||||
|
|
@ -62,15 +83,15 @@ php_grpc_zend_object create_wrapped_grpc_channel(zend_class_entry *class_type
|
|||
PHP_GRPC_FREE_CLASS_OBJECT(wrapped_grpc_channel, channel_ce_handlers);
|
||||
}
|
||||
|
||||
void php_grpc_read_args_array(zval *args_array,
|
||||
grpc_channel_args *args TSRMLS_DC) {
|
||||
int php_grpc_read_args_array(zval *args_array,
|
||||
grpc_channel_args *args TSRMLS_DC) {
|
||||
HashTable *array_hash;
|
||||
int args_index;
|
||||
array_hash = Z_ARRVAL_P(args_array);
|
||||
if (!array_hash) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"array_hash is NULL", 1 TSRMLS_CC);
|
||||
return;
|
||||
return FAILURE;
|
||||
}
|
||||
args->num_args = zend_hash_num_elements(array_hash);
|
||||
args->args = ecalloc(args->num_args, sizeof(grpc_arg));
|
||||
|
|
@ -84,7 +105,7 @@ void php_grpc_read_args_array(zval *args_array,
|
|||
if (key_type != HASH_KEY_IS_STRING) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"args keys must be strings", 1 TSRMLS_CC);
|
||||
return;
|
||||
return FAILURE;
|
||||
}
|
||||
args->args[args_index].key = key;
|
||||
switch (Z_TYPE_P(data)) {
|
||||
|
|
@ -99,16 +120,78 @@ void php_grpc_read_args_array(zval *args_array,
|
|||
default:
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"args values must be int or string", 1 TSRMLS_CC);
|
||||
return;
|
||||
return FAILURE;
|
||||
}
|
||||
args_index++;
|
||||
PHP_GRPC_HASH_FOREACH_END()
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void generate_sha1_str(char *sha1str, char *str, php_grpc_int len) {
|
||||
PHP_SHA1_CTX context;
|
||||
unsigned char digest[20];
|
||||
sha1str[0] = '\0';
|
||||
PHP_SHA1Init(&context);
|
||||
PHP_GRPC_SHA1Update(&context, str, len);
|
||||
PHP_SHA1Final(digest, &context);
|
||||
make_sha1_digest(sha1str, digest);
|
||||
}
|
||||
|
||||
void create_channel(
|
||||
wrapped_grpc_channel *channel,
|
||||
char *target,
|
||||
grpc_channel_args args,
|
||||
wrapped_grpc_channel_credentials *creds) {
|
||||
if (creds == NULL) {
|
||||
channel->wrapper->wrapped = grpc_insecure_channel_create(target, &args,
|
||||
NULL);
|
||||
} else {
|
||||
channel->wrapper->wrapped =
|
||||
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
|
||||
}
|
||||
efree(args.args);
|
||||
}
|
||||
|
||||
void create_and_add_channel_to_persistent_list(
|
||||
wrapped_grpc_channel *channel,
|
||||
char *target,
|
||||
grpc_channel_args args,
|
||||
wrapped_grpc_channel_credentials *creds,
|
||||
char *key,
|
||||
php_grpc_int key_len) {
|
||||
php_grpc_zend_resource new_rsrc;
|
||||
channel_persistent_le_t *le;
|
||||
// this links each persistent list entry to a destructor
|
||||
new_rsrc.type = le_plink;
|
||||
le = malloc(sizeof(channel_persistent_le_t));
|
||||
|
||||
create_channel(channel, target, args, creds);
|
||||
|
||||
le->channel = channel->wrapper;
|
||||
new_rsrc.ptr = le;
|
||||
gpr_mu_lock(&global_persistent_list_mu);
|
||||
PHP_GRPC_PERSISTENT_LIST_UPDATE(&EG(persistent_list), key, key_len,
|
||||
(void *)&new_rsrc);
|
||||
gpr_mu_unlock(&global_persistent_list_mu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an instance of the Channel class. If the $args array contains a
|
||||
* "credentials" key mapping to a ChannelCredentials object, a secure channel
|
||||
* will be created with those credentials.
|
||||
* Construct an instance of the Channel class.
|
||||
*
|
||||
* By default, the underlying grpc_channel is "persistent". That is, given
|
||||
* the same set of parameters passed to the constructor, the same underlying
|
||||
* grpc_channel will be returned.
|
||||
*
|
||||
* If the $args array contains a "credentials" key mapping to a
|
||||
* ChannelCredentials object, a secure channel will be created with those
|
||||
* credentials.
|
||||
*
|
||||
* If the $args array contains a "force_new" key mapping to a boolean value
|
||||
* of "true", a new underlying grpc_channel will be created regardless. If
|
||||
* there are any opened channels on the same hostname, user must manually
|
||||
* call close() on those dangling channels before the end of the PHP
|
||||
* script.
|
||||
*
|
||||
* @param string $target The hostname to associate with this channel
|
||||
* @param array $args_array The arguments to pass to the Channel
|
||||
*/
|
||||
|
|
@ -121,6 +204,9 @@ PHP_METHOD(Channel, __construct) {
|
|||
grpc_channel_args args;
|
||||
HashTable *array_hash;
|
||||
wrapped_grpc_channel_credentials *creds = NULL;
|
||||
php_grpc_zend_resource *rsrc;
|
||||
bool force_new = false;
|
||||
zval *force_new_obj = NULL;
|
||||
|
||||
/* "sa" == 1 string, 1 array */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target,
|
||||
|
|
@ -131,7 +217,7 @@ PHP_METHOD(Channel, __construct) {
|
|||
}
|
||||
array_hash = Z_ARRVAL_P(args_array);
|
||||
if (php_grpc_zend_hash_find(array_hash, "credentials", sizeof("credentials"),
|
||||
(void **)&creds_obj) == SUCCESS) {
|
||||
(void **)&creds_obj) == SUCCESS) {
|
||||
if (Z_TYPE_P(creds_obj) == IS_NULL) {
|
||||
creds = NULL;
|
||||
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
|
||||
|
|
@ -146,14 +232,82 @@ PHP_METHOD(Channel, __construct) {
|
|||
php_grpc_zend_hash_del(array_hash, "credentials", sizeof("credentials"));
|
||||
}
|
||||
}
|
||||
php_grpc_read_args_array(args_array, &args TSRMLS_CC);
|
||||
if (creds == NULL) {
|
||||
channel->wrapped = grpc_insecure_channel_create(target, &args, NULL);
|
||||
} else {
|
||||
channel->wrapped =
|
||||
grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
|
||||
if (php_grpc_zend_hash_find(array_hash, "force_new", sizeof("force_new"),
|
||||
(void **)&force_new_obj) == SUCCESS) {
|
||||
if (PHP_GRPC_BVAL_IS_TRUE(force_new_obj)) {
|
||||
force_new = true;
|
||||
}
|
||||
php_grpc_zend_hash_del(array_hash, "force_new", sizeof("force_new"));
|
||||
}
|
||||
|
||||
// parse the rest of the channel args array
|
||||
if (php_grpc_read_args_array(args_array, &args TSRMLS_CC) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct a hashkey for the persistent channel
|
||||
// Currently, the hashkey contains 3 parts:
|
||||
// 1. hostname
|
||||
// 2. hash value of the channel args array (excluding "credentials"
|
||||
// and "force_new")
|
||||
// 3. (optional) hash value of the ChannelCredentials object
|
||||
php_serialize_data_t var_hash;
|
||||
smart_str buf = {0};
|
||||
PHP_VAR_SERIALIZE_INIT(var_hash);
|
||||
PHP_GRPC_VAR_SERIALIZE(&buf, args_array, &var_hash);
|
||||
PHP_VAR_SERIALIZE_DESTROY(var_hash);
|
||||
|
||||
char sha1str[41];
|
||||
generate_sha1_str(sha1str, PHP_GRPC_SERIALIZED_BUF_STR(buf),
|
||||
PHP_GRPC_SERIALIZED_BUF_LEN(buf));
|
||||
|
||||
php_grpc_int key_len = target_length + strlen(sha1str);
|
||||
if (creds != NULL && creds->hashstr != NULL) {
|
||||
key_len += strlen(creds->hashstr);
|
||||
}
|
||||
char *key = malloc(key_len + 1);
|
||||
strcpy(key, target);
|
||||
strcat(key, sha1str);
|
||||
if (creds != NULL && creds->hashstr != NULL) {
|
||||
strcat(key, creds->hashstr);
|
||||
}
|
||||
channel->wrapper = malloc(sizeof(grpc_channel_wrapper));
|
||||
channel->wrapper->key = key;
|
||||
channel->wrapper->target = target;
|
||||
channel->wrapper->args_hashstr = sha1str;
|
||||
if (creds != NULL && creds->hashstr != NULL) {
|
||||
channel->wrapper->creds_hashstr = creds->hashstr;
|
||||
}
|
||||
gpr_mu_init(&channel->wrapper->mu);
|
||||
smart_str_free(&buf);
|
||||
|
||||
if (force_new) {
|
||||
php_grpc_delete_persistent_list_entry(key, key_len TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (creds != NULL && creds->has_call_creds) {
|
||||
// If the ChannelCredentials object was composed with a CallCredentials
|
||||
// object, there is no way we can tell them apart. Do NOT persist
|
||||
// them. They should be individually destroyed.
|
||||
create_channel(channel, target, args, creds);
|
||||
} else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
|
||||
key_len, rsrc))) {
|
||||
create_and_add_channel_to_persistent_list(
|
||||
channel, target, args, creds, key, key_len);
|
||||
} else {
|
||||
// Found a previously stored channel in the persistent list
|
||||
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
|
||||
if (strcmp(target, le->channel->target) != 0 ||
|
||||
strcmp(sha1str, le->channel->args_hashstr) != 0 ||
|
||||
(creds != NULL && creds->hashstr != NULL &&
|
||||
strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
|
||||
// somehow hash collision
|
||||
create_and_add_channel_to_persistent_list(
|
||||
channel, target, args, creds, key, key_len);
|
||||
} else {
|
||||
channel->wrapper = le->channel;
|
||||
}
|
||||
}
|
||||
efree(args.args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -162,7 +316,16 @@ PHP_METHOD(Channel, __construct) {
|
|||
*/
|
||||
PHP_METHOD(Channel, getTarget) {
|
||||
wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
|
||||
PHP_GRPC_RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1);
|
||||
gpr_mu_lock(&channel->wrapper->mu);
|
||||
if (channel->wrapper->wrapped == NULL) {
|
||||
zend_throw_exception(spl_ce_RuntimeException,
|
||||
"Channel already closed", 1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
char *target = grpc_channel_get_target(channel->wrapper->wrapped);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
PHP_GRPC_RETURN_STRING(target, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -172,6 +335,14 @@ PHP_METHOD(Channel, getTarget) {
|
|||
*/
|
||||
PHP_METHOD(Channel, getConnectivityState) {
|
||||
wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
|
||||
gpr_mu_lock(&channel->wrapper->mu);
|
||||
if (channel->wrapper->wrapped == NULL) {
|
||||
zend_throw_exception(spl_ce_RuntimeException,
|
||||
"Channel already closed", 1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
|
||||
bool try_to_connect = false;
|
||||
|
||||
/* "|b" == 1 optional bool */
|
||||
|
|
@ -179,10 +350,18 @@ PHP_METHOD(Channel, getConnectivityState) {
|
|||
== FAILURE) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"getConnectivityState expects a bool", 1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
RETURN_LONG(grpc_channel_check_connectivity_state(channel->wrapped,
|
||||
(int)try_to_connect));
|
||||
int state = grpc_channel_check_connectivity_state(channel->wrapper->wrapped,
|
||||
(int)try_to_connect);
|
||||
// this can happen if another shared Channel object close the underlying
|
||||
// channel
|
||||
if (state == GRPC_CHANNEL_SHUTDOWN) {
|
||||
channel->wrapper->wrapped = NULL;
|
||||
}
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
RETURN_LONG(state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -194,25 +373,37 @@ PHP_METHOD(Channel, getConnectivityState) {
|
|||
*/
|
||||
PHP_METHOD(Channel, watchConnectivityState) {
|
||||
wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
|
||||
gpr_mu_lock(&channel->wrapper->mu);
|
||||
if (channel->wrapper->wrapped == NULL) {
|
||||
zend_throw_exception(spl_ce_RuntimeException,
|
||||
"Channel already closed", 1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
|
||||
php_grpc_long last_state;
|
||||
zval *deadline_obj;
|
||||
|
||||
/* "lO" == 1 long 1 object */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lO",
|
||||
&last_state, &deadline_obj, grpc_ce_timeval) == FAILURE) {
|
||||
&last_state, &deadline_obj,
|
||||
grpc_ce_timeval) == FAILURE) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException,
|
||||
"watchConnectivityState expects 1 long 1 timeval", 1 TSRMLS_CC);
|
||||
"watchConnectivityState expects 1 long 1 timeval",
|
||||
1 TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
return;
|
||||
}
|
||||
|
||||
wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj);
|
||||
grpc_channel_watch_connectivity_state(channel->wrapped,
|
||||
grpc_channel_watch_connectivity_state(channel->wrapper->wrapped,
|
||||
(grpc_connectivity_state)last_state,
|
||||
deadline->wrapped, completion_queue,
|
||||
NULL);
|
||||
grpc_event event =
|
||||
grpc_completion_queue_pluck(completion_queue, NULL,
|
||||
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
||||
grpc_completion_queue_pluck(completion_queue, NULL,
|
||||
gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
RETURN_BOOL(event.success);
|
||||
}
|
||||
|
||||
|
|
@ -222,10 +413,48 @@ PHP_METHOD(Channel, watchConnectivityState) {
|
|||
*/
|
||||
PHP_METHOD(Channel, close) {
|
||||
wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis());
|
||||
if (channel->wrapped != NULL) {
|
||||
grpc_channel_destroy(channel->wrapped);
|
||||
channel->wrapped = NULL;
|
||||
gpr_mu_lock(&channel->wrapper->mu);
|
||||
if (channel->wrapper->wrapped != NULL) {
|
||||
grpc_channel_destroy(channel->wrapper->wrapped);
|
||||
channel->wrapper->wrapped = NULL;
|
||||
}
|
||||
|
||||
php_grpc_delete_persistent_list_entry(channel->wrapper->key,
|
||||
strlen(channel->wrapper->key)
|
||||
TSRMLS_CC);
|
||||
gpr_mu_unlock(&channel->wrapper->mu);
|
||||
}
|
||||
|
||||
// Delete an entry from the persistent list
|
||||
// Note: this does not destroy or close the underlying grpc_channel
|
||||
void php_grpc_delete_persistent_list_entry(char *key, php_grpc_int key_len
|
||||
TSRMLS_DC) {
|
||||
php_grpc_zend_resource *rsrc;
|
||||
gpr_mu_lock(&global_persistent_list_mu);
|
||||
if (PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
|
||||
key_len, rsrc)) {
|
||||
channel_persistent_le_t *le;
|
||||
le = (channel_persistent_le_t *)rsrc->ptr;
|
||||
le->channel = NULL;
|
||||
php_grpc_zend_hash_del(&EG(persistent_list), key, key_len+1);
|
||||
}
|
||||
gpr_mu_unlock(&global_persistent_list_mu);
|
||||
}
|
||||
|
||||
// A destructor associated with each list entry from the persistent list
|
||||
static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
|
||||
TSRMLS_DC) {
|
||||
channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
|
||||
if (le->channel != NULL) {
|
||||
gpr_mu_lock(&le->channel->mu);
|
||||
if (le->channel->wrapped != NULL) {
|
||||
grpc_channel_destroy(le->channel->wrapped);
|
||||
free(le->channel->key);
|
||||
free(le->channel);
|
||||
}
|
||||
gpr_mu_unlock(&le->channel->mu);
|
||||
}
|
||||
free(le);
|
||||
}
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
|
||||
|
|
@ -262,10 +491,13 @@ static zend_function_entry channel_methods[] = {
|
|||
PHP_FE_END
|
||||
};
|
||||
|
||||
void grpc_init_channel(TSRMLS_D) {
|
||||
GRPC_STARTUP_FUNCTION(channel) {
|
||||
zend_class_entry ce;
|
||||
INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods);
|
||||
ce.create_object = create_wrapped_grpc_channel;
|
||||
grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC);
|
||||
le_plink = zend_register_list_destructors_ex(
|
||||
NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
|
||||
PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,9 +33,18 @@
|
|||
/* Class entry for the PHP Channel class */
|
||||
extern zend_class_entry *grpc_ce_channel;
|
||||
|
||||
typedef struct _grpc_channel_wrapper {
|
||||
grpc_channel *wrapped;
|
||||
char *key;
|
||||
char *target;
|
||||
char *args_hashstr;
|
||||
char *creds_hashstr;
|
||||
gpr_mu mu;
|
||||
} grpc_channel_wrapper;
|
||||
|
||||
/* Wrapper struct for grpc_channel that can be associated with a PHP object */
|
||||
PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel)
|
||||
grpc_channel *wrapped;
|
||||
grpc_channel_wrapper *wrapper;
|
||||
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel)
|
||||
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
|
|
@ -57,10 +66,20 @@ static inline wrapped_grpc_channel
|
|||
#endif /* PHP_MAJOR_VERSION */
|
||||
|
||||
/* Initializes the Channel class */
|
||||
void grpc_init_channel(TSRMLS_D);
|
||||
GRPC_STARTUP_FUNCTION(channel);
|
||||
|
||||
/* Iterates through a PHP array and populates args with the contents */
|
||||
void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args
|
||||
TSRMLS_DC);
|
||||
int php_grpc_read_args_array(zval *args_array, grpc_channel_args *args
|
||||
TSRMLS_DC);
|
||||
|
||||
void generate_sha1_str(char *sha1str, char *str, php_grpc_int len);
|
||||
|
||||
void php_grpc_delete_persistent_list_entry(char *key, php_grpc_int key_len
|
||||
TSRMLS_DC);
|
||||
|
||||
typedef struct _channel_persistent_le {
|
||||
grpc_channel_wrapper *channel;
|
||||
} channel_persistent_le_t;
|
||||
|
||||
|
||||
#endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@
|
|||
#include <php.h>
|
||||
#include <php_ini.h>
|
||||
#include <ext/standard/info.h>
|
||||
#include <ext/standard/sha1.h>
|
||||
#include <ext/spl/spl_exceptions.h>
|
||||
#include "channel.h"
|
||||
#include "php_grpc.h"
|
||||
|
||||
#include <zend_exceptions.h>
|
||||
|
|
@ -69,14 +71,17 @@ php_grpc_zend_object create_wrapped_grpc_channel_credentials(
|
|||
channel_credentials_ce_handlers);
|
||||
}
|
||||
|
||||
zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials
|
||||
*wrapped TSRMLS_DC) {
|
||||
zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped,
|
||||
char *hashstr,
|
||||
zend_bool has_call_creds TSRMLS_DC) {
|
||||
zval *credentials_object;
|
||||
PHP_GRPC_MAKE_STD_ZVAL(credentials_object);
|
||||
object_init_ex(credentials_object, grpc_ce_channel_credentials);
|
||||
wrapped_grpc_channel_credentials *credentials =
|
||||
Z_WRAPPED_GRPC_CHANNEL_CREDS_P(credentials_object);
|
||||
credentials->wrapped = wrapped;
|
||||
credentials->hashstr = hashstr;
|
||||
credentials->has_call_creds = has_call_creds;
|
||||
return credentials_object;
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +111,8 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) {
|
|||
*/
|
||||
PHP_METHOD(ChannelCredentials, createDefault) {
|
||||
grpc_channel_credentials *creds = grpc_google_default_credentials_create();
|
||||
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
|
||||
zval *creds_object = grpc_php_wrap_channel_credentials(creds, NULL, false
|
||||
TSRMLS_CC);
|
||||
RETURN_DESTROY_ZVAL(creds_object);
|
||||
}
|
||||
|
||||
|
|
@ -140,10 +146,24 @@ PHP_METHOD(ChannelCredentials, createSsl) {
|
|||
"createSsl expects 3 optional strings", 1 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
php_grpc_int hashkey_len = root_certs_length + cert_chain_length;
|
||||
char hashkey[hashkey_len];
|
||||
if (root_certs_length > 0) {
|
||||
strcpy(hashkey, pem_root_certs);
|
||||
}
|
||||
if (cert_chain_length > 0) {
|
||||
strcpy(hashkey, pem_key_cert_pair.cert_chain);
|
||||
}
|
||||
|
||||
char *hashstr = malloc(41);
|
||||
generate_sha1_str(hashstr, hashkey, hashkey_len);
|
||||
|
||||
grpc_channel_credentials *creds = grpc_ssl_credentials_create(
|
||||
pem_root_certs,
|
||||
pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL);
|
||||
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
|
||||
zval *creds_object = grpc_php_wrap_channel_credentials(creds, hashstr, false
|
||||
TSRMLS_CC);
|
||||
RETURN_DESTROY_ZVAL(creds_object);
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +192,9 @@ PHP_METHOD(ChannelCredentials, createComposite) {
|
|||
grpc_channel_credentials *creds =
|
||||
grpc_composite_channel_credentials_create(cred1->wrapped, cred2->wrapped,
|
||||
NULL);
|
||||
zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC);
|
||||
zval *creds_object =
|
||||
grpc_php_wrap_channel_credentials(creds, cred1->hashstr, true
|
||||
TSRMLS_CC);
|
||||
RETURN_DESTROY_ZVAL(creds_object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ extern zend_class_entry *grpc_ce_channel_credentials;
|
|||
* with a PHP object */
|
||||
PHP_GRPC_WRAP_OBJECT_START(wrapped_grpc_channel_credentials)
|
||||
grpc_channel_credentials *wrapped;
|
||||
char *hashstr;
|
||||
zend_bool has_call_creds;
|
||||
PHP_GRPC_WRAP_OBJECT_END(wrapped_grpc_channel_credentials)
|
||||
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
|
|
|
|||
|
|
@ -113,6 +113,20 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
|
|||
}
|
||||
|
||||
#define php_grpc_zend_hash_del zend_hash_del
|
||||
#define php_grpc_zend_resource zend_rsrc_list_entry
|
||||
|
||||
#define PHP_GRPC_BVAL_IS_TRUE(zv) Z_LVAL_P(zv)
|
||||
#define PHP_GRPC_VAR_SERIALIZE(buf, zv, hash) \
|
||||
php_var_serialize(buf, &zv, hash TSRMLS_CC)
|
||||
#define PHP_GRPC_SERIALIZED_BUF_STR(buf) buf.c
|
||||
#define PHP_GRPC_SERIALIZED_BUF_LEN(buf) buf.len
|
||||
#define PHP_GRPC_SHA1Update(cxt, str, len) \
|
||||
PHP_SHA1Update(cxt, (const unsigned char *)str, len)
|
||||
#define PHP_GRPC_PERSISTENT_LIST_FIND(plist, key, len, rsrc) \
|
||||
zend_hash_find(plist, key, len+1, (void **)&rsrc) != FAILURE
|
||||
#define PHP_GRPC_PERSISTENT_LIST_UPDATE(plist, key, len, rsrc) \
|
||||
zend_hash_update(plist, key, len+1, rsrc, sizeof(php_grpc_zend_resource), \
|
||||
NULL)
|
||||
|
||||
#define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC)
|
||||
|
||||
|
|
@ -200,6 +214,20 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
|
|||
static inline int php_grpc_zend_hash_del(HashTable *ht, char *key, int len) {
|
||||
return zend_hash_str_del(ht, key, len - 1);
|
||||
}
|
||||
#define php_grpc_zend_resource zend_resource
|
||||
|
||||
#define PHP_GRPC_BVAL_IS_TRUE(zv) Z_TYPE_P(zv) == IS_TRUE
|
||||
#define PHP_GRPC_VAR_SERIALIZE(buf, zv, hash) \
|
||||
php_var_serialize(buf, zv, hash)
|
||||
#define PHP_GRPC_SERIALIZED_BUF_STR(buf) ZSTR_VAL(buf.s)
|
||||
#define PHP_GRPC_SERIALIZED_BUF_LEN(buf) ZSTR_LEN(buf.s)
|
||||
#define PHP_GRPC_SHA1Update(cxt, str, len) \
|
||||
PHP_SHA1Update(cxt, (unsigned char *)str, len)
|
||||
#define PHP_GRPC_PERSISTENT_LIST_FIND(plist, key, len, rsrc) \
|
||||
(rsrc = zend_hash_str_find_ptr(plist, key, len)) != NULL
|
||||
#define PHP_GRPC_PERSISTENT_LIST_UPDATE(plist, key, len, rsrc) \
|
||||
zend_hash_str_update_mem(plist, key, len, rsrc, \
|
||||
sizeof(php_grpc_zend_resource))
|
||||
|
||||
#define PHP_GRPC_GET_CLASS_ENTRY(object) Z_OBJ_P(object)->ce
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ PHP_MINIT_FUNCTION(grpc) {
|
|||
CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
grpc_init_call(TSRMLS_C);
|
||||
grpc_init_channel(TSRMLS_C);
|
||||
GRPC_STARTUP(channel);
|
||||
grpc_init_server(TSRMLS_C);
|
||||
grpc_init_timeval(TSRMLS_C);
|
||||
grpc_init_channel_credentials(TSRMLS_C);
|
||||
|
|
|
|||
|
|
@ -74,4 +74,8 @@ ZEND_END_MODULE_GLOBALS(grpc)
|
|||
#define GRPC_G(v) (grpc_globals.v)
|
||||
#endif
|
||||
|
||||
#define GRPC_STARTUP_FUNCTION(module) ZEND_MINIT_FUNCTION(grpc_##module)
|
||||
#define GRPC_STARTUP(module) \
|
||||
ZEND_MODULE_STARTUP_N(grpc_##module)(INIT_FUNC_ARGS_PASSTHRU)
|
||||
|
||||
#endif /* PHP_GRPC_H */
|
||||
|
|
|
|||
|
|
@ -37,8 +37,7 @@ class CallTest extends PHPUnit_Framework_TestCase
|
|||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->call);
|
||||
unset($this->channel);
|
||||
$this->channel->close();
|
||||
}
|
||||
|
||||
public function testConstructor()
|
||||
|
|
|
|||
|
|
@ -25,17 +25,15 @@ class ChannelTest extends PHPUnit_Framework_TestCase
|
|||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->channel);
|
||||
if (!empty($this->channel)) {
|
||||
$this->channel->close();
|
||||
}
|
||||
}
|
||||
|
||||
public function testInsecureCredentials()
|
||||
{
|
||||
$this->channel = new Grpc\Channel(
|
||||
'localhost:0',
|
||||
[
|
||||
'credentials' => Grpc\ChannelCredentials::createInsecure(),
|
||||
]
|
||||
);
|
||||
$this->channel = new Grpc\Channel('localhost:0',
|
||||
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
|
||||
$this->assertSame('Grpc\Channel', get_class($this->channel));
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +109,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase
|
|||
*/
|
||||
public function testInvalidConstructorWith()
|
||||
{
|
||||
$this->channel = new Grpc\Channel('localhost', 'invalid');
|
||||
$this->channel = new Grpc\Channel('localhost:0', 'invalid');
|
||||
$this->assertNull($this->channel);
|
||||
}
|
||||
|
||||
|
|
@ -120,12 +118,8 @@ class ChannelTest extends PHPUnit_Framework_TestCase
|
|||
*/
|
||||
public function testInvalidCredentials()
|
||||
{
|
||||
$this->channel = new Grpc\Channel(
|
||||
'localhost:0',
|
||||
[
|
||||
'credentials' => new Grpc\Timeval(100),
|
||||
]
|
||||
);
|
||||
$this->channel = new Grpc\Channel('localhost:0',
|
||||
['credentials' => new Grpc\Timeval(100)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,12 +127,8 @@ class ChannelTest extends PHPUnit_Framework_TestCase
|
|||
*/
|
||||
public function testInvalidOptionsArray()
|
||||
{
|
||||
$this->channel = new Grpc\Channel(
|
||||
'localhost:0',
|
||||
[
|
||||
'abc' => [],
|
||||
]
|
||||
);
|
||||
$this->channel = new Grpc\Channel('localhost:0',
|
||||
['abc' => []]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -170,4 +160,431 @@ class ChannelTest extends PHPUnit_Framework_TestCase
|
|||
['credentials' => Grpc\ChannelCredentials::createInsecure()]);
|
||||
$this->channel->watchConnectivityState(1, 'hi');
|
||||
}
|
||||
|
||||
|
||||
public function assertConnecting($state) {
|
||||
$this->assertTrue($state == GRPC\CHANNEL_CONNECTING ||
|
||||
$state == GRPC\CHANNEL_TRANSIENT_FAILURE);
|
||||
}
|
||||
|
||||
public function waitUntilNotIdle($channel) {
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$now = Grpc\Timeval::now();
|
||||
$deadline = $now->add(new Grpc\Timeval(1000));
|
||||
if ($channel->watchConnectivityState(GRPC\CHANNEL_IDLE,
|
||||
$deadline)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$this->assertTrue(false);
|
||||
}
|
||||
|
||||
public function testPersistentChannelSameHost()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
// the underlying grpc channel is the same by default
|
||||
// when connecting to the same host
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
// both channels should be IDLE
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
// both channels should now be in the CONNECTING state
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelDifferentHost()
|
||||
{
|
||||
// two different underlying channels because different hostname
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:2', []);
|
||||
|
||||
// both channels should be IDLE
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
// channel1 should now be in the CONNECTING state
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
// channel2 should still be in the IDLE state
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelSameArgs()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelDifferentArgs()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', ["abc" => "def"]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelSameChannelCredentials()
|
||||
{
|
||||
$creds1 = Grpc\ChannelCredentials::createSsl();
|
||||
$creds2 = Grpc\ChannelCredentials::createSsl();
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds1]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds2]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelDifferentChannelCredentials()
|
||||
{
|
||||
$creds1 = Grpc\ChannelCredentials::createSsl();
|
||||
$creds2 = Grpc\ChannelCredentials::createSsl(
|
||||
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds1]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds2]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelSameChannelCredentialsRootCerts()
|
||||
{
|
||||
$creds1 = Grpc\ChannelCredentials::createSsl(
|
||||
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
|
||||
$creds2 = Grpc\ChannelCredentials::createSsl(
|
||||
file_get_contents(dirname(__FILE__).'/../data/ca.pem'));
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds1]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds2]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelDifferentSecureChannelCredentials()
|
||||
{
|
||||
$creds1 = Grpc\ChannelCredentials::createSsl();
|
||||
$creds2 = Grpc\ChannelCredentials::createInsecure();
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds1]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds2]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
*/
|
||||
public function testPersistentChannelSharedChannelClose()
|
||||
{
|
||||
// same underlying channel
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
// close channel1
|
||||
$this->channel1->close();
|
||||
|
||||
// channel2 is now in SHUTDOWN state
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_FATAL_FAILURE, $state);
|
||||
|
||||
// calling it again will result in an exception because the
|
||||
// channel is already closed
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
}
|
||||
|
||||
public function testPersistentChannelCreateAfterClose()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
$this->channel1->close();
|
||||
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', []);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelSharedMoreThanTwo()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel3 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
// all 3 channels should be in CONNECTING state
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel3->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
}
|
||||
|
||||
public function callbackFunc($context)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function callbackFunc2($context)
|
||||
{
|
||||
return ["k1" => "v1"];
|
||||
}
|
||||
|
||||
public function testPersistentChannelWithCallCredentials()
|
||||
{
|
||||
$creds = Grpc\ChannelCredentials::createSsl();
|
||||
$callCreds = Grpc\CallCredentials::createFromPlugin(
|
||||
[$this, 'callbackFunc']);
|
||||
$credsWithCallCreds = Grpc\ChannelCredentials::createComposite(
|
||||
$creds, $callCreds);
|
||||
|
||||
// If a ChannelCredentials object is composed with a
|
||||
// CallCredentials object, the underlying grpc channel will
|
||||
// always be created new and NOT persisted.
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" =>
|
||||
$credsWithCallCreds]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" =>
|
||||
$credsWithCallCreds]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelWithDifferentCallCredentials()
|
||||
{
|
||||
$callCreds1 = Grpc\CallCredentials::createFromPlugin(
|
||||
[$this, 'callbackFunc']);
|
||||
$callCreds2 = Grpc\CallCredentials::createFromPlugin(
|
||||
[$this, 'callbackFunc2']);
|
||||
|
||||
$creds1 = Grpc\ChannelCredentials::createSsl();
|
||||
$creds2 = Grpc\ChannelCredentials::createComposite(
|
||||
$creds1, $callCreds1);
|
||||
$creds3 = Grpc\ChannelCredentials::createComposite(
|
||||
$creds1, $callCreds2);
|
||||
|
||||
// Similar to the test above, anytime a ChannelCredentials
|
||||
// object is composed with a CallCredentials object, the
|
||||
// underlying grpc channel will always be separate and not
|
||||
// persisted
|
||||
$this->channel1 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds1]);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds2]);
|
||||
$this->channel3 = new Grpc\Channel('localhost:1',
|
||||
["credentials" => $creds3]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
$state = $this->channel3->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
$this->channel3->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelForceNew()
|
||||
{
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
// even though all the channel params are the same, channel2
|
||||
// has a new and different underlying channel
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["force_new" => true]);
|
||||
|
||||
// try to connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
// any dangling old connection to the same host must be
|
||||
// manually closed
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelForceNewOldChannelIdle()
|
||||
{
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["force_new" => true]);
|
||||
$this->channel3 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
// try to connect on channel2
|
||||
$state = $this->channel2->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel2);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
$state = $this->channel3->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
$this->channel2->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelForceNewOldChannelClose()
|
||||
{
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["force_new" => true]);
|
||||
$this->channel3 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
$this->channel1->close();
|
||||
|
||||
$state = $this->channel2->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
$state = $this->channel3->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
$this->channel2->close();
|
||||
$this->channel3->close();
|
||||
}
|
||||
|
||||
public function testPersistentChannelForceNewNewChannelClose()
|
||||
{
|
||||
|
||||
$this->channel1 = new Grpc\Channel('localhost:1', []);
|
||||
$this->channel2 = new Grpc\Channel('localhost:1',
|
||||
["force_new" => true]);
|
||||
$this->channel3 = new Grpc\Channel('localhost:1', []);
|
||||
|
||||
$this->channel2->close();
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertEquals(GRPC\CHANNEL_IDLE, $state);
|
||||
|
||||
// can still connect on channel1
|
||||
$state = $this->channel1->getConnectivityState(true);
|
||||
$this->waitUntilNotIdle($this->channel1);
|
||||
|
||||
$state = $this->channel1->getConnectivityState();
|
||||
$this->assertConnecting($state);
|
||||
|
||||
$this->channel1->close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
|
|||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->channel);
|
||||
unset($this->server);
|
||||
$this->channel->close();
|
||||
}
|
||||
|
||||
public function testSimpleRequestBody()
|
||||
|
|
@ -516,7 +515,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
|
||||
|
||||
$now = Grpc\Timeval::now();
|
||||
$delta = new Grpc\Timeval(500000); // should timeout
|
||||
$delta = new Grpc\Timeval(50000); // should timeout
|
||||
$deadline = $now->add($delta);
|
||||
|
||||
$this->assertFalse($this->channel->watchConnectivityState(
|
||||
|
|
@ -545,7 +544,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase
|
|||
$this->assertTrue($idle_state == Grpc\CHANNEL_IDLE);
|
||||
|
||||
$now = Grpc\Timeval::now();
|
||||
$delta = new Grpc\Timeval(100000);
|
||||
$delta = new Grpc\Timeval(50000);
|
||||
$deadline = $now->add($delta);
|
||||
|
||||
$this->assertFalse($this->channel->watchConnectivityState(
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase
|
|||
|
||||
public function tearDown()
|
||||
{
|
||||
unset($this->channel);
|
||||
unset($this->server);
|
||||
$this->channel->close();
|
||||
}
|
||||
|
||||
public function testSimpleRequestBody()
|
||||
|
|
|
|||
Loading…
Reference in New Issue