26 #include <ext/standard/php_var.h>
27 #include <ext/standard/sha1.h>
28 #include <zend_smart_str.h>
29 #include <ext/spl/spl_exceptions.h>
30 #include <zend_exceptions.h>
97 zend_object_std_init(&
intern->std, class_type TSRMLS_CC);
98 object_properties_init(&
intern->std, class_type);
103 static const char* ignoredKeys[] = {
106 "grpc_target_persist_bound",
109 for (
int i = 0;
i <
sizeof(ignoredKeys) /
sizeof(ignoredKeys[0]);
i++) {
110 if (strcmp(
key, ignoredKeys[
i]) == 0) {
119 HashTable *array_hash;
121 array_hash = Z_ARRVAL_P(args_array);
123 zend_throw_exception(spl_ce_InvalidArgumentException,
124 "array_hash is NULL", 1 TSRMLS_CC);
128 args->args = ecalloc(zend_hash_num_elements(array_hash),
sizeof(
grpc_arg));
136 if (
key_type != HASH_KEY_IS_STRING) {
137 zend_throw_exception(spl_ce_InvalidArgumentException,
138 "args keys must be strings", 1 TSRMLS_CC);
146 args->args[args_index].key =
key;
147 switch (Z_TYPE_P(
data)) {
149 args->args[args_index].value.integer = (
int)Z_LVAL_P(
data);
153 args->args[args_index].value.string = Z_STRVAL_P(
data);
157 zend_throw_exception(spl_ce_InvalidArgumentException,
158 "args values must be int or string", 1 TSRMLS_CC);
163 args->num_args = args_index;
169 unsigned char digest[20];
173 PHP_SHA1Final(digest, &
context);
174 make_sha1_digest(sha1str, digest);
188 if (strcmp(le->channel->target,
target) == 0) {
190 if (le->channel->ref_count == 1) {
192 strlen(le->channel->key)
194 target_bound_status->current_count -= 1;
195 if (target_bound_status->current_count < target_bound_status->upper_bound) {
222 new_rsrc.ptr = target_bound_status;
225 target, key_len, (
void *)&new_rsrc);
235 return target_bound_status;
242 wrapped_grpc_channel_credentials *creds) {
260 wrapped_grpc_channel_credentials *creds,
263 int target_upper_bound TSRMLS_DC) {
270 target, target_bound_status TSRMLS_CC)) {
275 " target %s is maxed out bounded.\n",
target);
276 gpr_log(
GPR_INFO,
"[Warning] Target upper bound: %d. Current size: %d.\n",
293 le->channel =
channel->wrapper;
322 wrapped_grpc_channel *
channel =
324 zval *creds_obj = NULL;
327 zval *args_array = NULL;
329 HashTable *array_hash;
330 wrapped_grpc_channel_credentials *creds = NULL;
332 bool force_new =
false;
333 zval *force_new_obj = NULL;
334 int target_upper_bound = -1;
337 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"sa", &
target,
338 &target_length, &args_array) == FAILURE) {
339 zend_throw_exception(spl_ce_InvalidArgumentException,
340 "Channel expects a string and an array", 1 TSRMLS_CC);
343 array_hash = Z_ARRVAL_P(args_array);
345 (
void **)&creds_obj) ==
SUCCESS) {
346 if (Z_TYPE_P(creds_obj) == IS_NULL) {
350 zend_throw_exception(spl_ce_InvalidArgumentException,
351 "credentials must be a ChannelCredentials object",
360 (
void **)&force_new_obj) ==
SUCCESS) {
367 sizeof(
"grpc_target_persist_bound"),
368 (
void **)&force_new_obj) ==
SUCCESS) {
369 if (Z_TYPE_P(force_new_obj) != IS_LONG) {
370 zend_throw_exception(spl_ce_InvalidArgumentException,
371 "plist_bound must be a number",
374 target_upper_bound = (
int)Z_LVAL_P(force_new_obj);
390 char sha1str[41] = { 0 };
391 unsigned char digest[20] = { 0 };
394 for (
int i = 0;
i <
args.num_args;
i++) {
396 switch (
args.args[
i].type) {
404 zend_throw_exception(spl_ce_InvalidArgumentException,
405 "args values must be int or string", 1 TSRMLS_CC);
409 PHP_SHA1Final(digest, &
context);
410 make_sha1_digest(sha1str, digest);
413 if (creds != NULL && creds->hashstr != NULL) {
414 key_len += strlen(creds->hashstr);
416 char *
key = malloc(key_len + 1);
418 strcat(
key, sha1str);
419 if (creds != NULL && creds->hashstr != NULL) {
420 strcat(
key, creds->hashstr);
423 channel->wrapper->ref_count = 0;
427 channel->wrapper->creds_hashstr = NULL;
428 channel->wrapper->creds = creds;
430 if (creds != NULL && creds->hashstr != NULL) {
431 php_grpc_int creds_hashstr_len = strlen(creds->hashstr);
432 char *channel_creds_hashstr = malloc(creds_hashstr_len + 1);
433 strcpy(channel_creds_hashstr, creds->hashstr);
434 channel->wrapper->creds_hashstr = channel_creds_hashstr;
438 if (force_new || (creds != NULL && creds->has_call_creds)) {
450 if (strcmp(
target, le->channel->target) != 0 ||
451 strcmp(sha1str, le->channel->args_hashstr) != 0 ||
452 (creds != NULL && creds->hashstr != NULL &&
453 strcmp(creds->hashstr, le->channel->creds_hashstr) != 0)) {
463 channel->wrapper = le->channel;
476 wrapped_grpc_channel *
channel =
478 if (
channel->wrapper == NULL) {
479 zend_throw_exception(spl_ce_RuntimeException,
481 "Channel is already closed.", 1 TSRMLS_CC);
497 wrapped_grpc_channel *
channel =
499 if (
channel->wrapper == NULL) {
500 zend_throw_exception(spl_ce_RuntimeException,
501 "getConnectivityState error."
502 "Channel is already closed.", 1 TSRMLS_CC);
508 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"|b", &
try_to_connect)
510 zend_throw_exception(spl_ce_InvalidArgumentException,
511 "getConnectivityState expects a bool", 1 TSRMLS_CC);
529 wrapped_grpc_channel *
channel =
531 if (
channel->wrapper == NULL) {
532 zend_throw_exception(spl_ce_RuntimeException,
533 "watchConnectivityState error"
534 "Channel is already closed.", 1 TSRMLS_CC);
542 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"lO",
543 &last_state, &deadline_obj,
545 zend_throw_exception(spl_ce_InvalidArgumentException,
546 "watchConnectivityState expects 1 long 1 timeval",
552 wrapped_grpc_timeval *deadline =
562 RETURN_BOOL(event.success);
570 wrapped_grpc_channel *
channel =
572 if (
channel->wrapper != NULL) {
598 if (le->channel != NULL) {
617 #ifdef GRPC_PHP_DEBUG
637 return "TRANSIENT_FAILURE";
649 wrapped_grpc_channel *
channel =
651 array_init(return_value);
654 sizeof(
"target"),
channel->wrapper->target,
true);
659 sizeof(
"target_upper_bound"), target_bound_status->
upper_bound);
661 sizeof(
"target_current_size"), target_bound_status->
current_count);
664 sizeof(
"key"),
channel->wrapper->key,
true);
667 sizeof(
"ref_count"),
channel->wrapper->ref_count);
673 sizeof(
"connectivity_status"),
state);
676 grpc_connectivity_state_name(
state),
true);
679 sizeof(
"is_valid"), (
channel->wrapper == NULL));
687 array_init(return_value);
701 sizeof(
"target"), le->channel->target,
true);
706 sizeof(
"target_upper_bound"), target_bound_status->
upper_bound);
708 sizeof(
"target_current_size"), target_bound_status->
current_count);
711 sizeof(
"key"), le->channel->key,
true);
714 sizeof(
"ref_count"), le->channel->ref_count);
720 sizeof(
"connectivity_status"),
state);
723 grpc_connectivity_state_name(
state),
true);
724 add_assoc_zval(return_value, le->channel->key, ret_arr);
731 ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 2)
733 ZEND_ARG_INFO(0,
args)
736 ZEND_BEGIN_ARG_INFO_EX(arginfo_getTarget, 0, 0, 0)
739 ZEND_BEGIN_ARG_INFO_EX(arginfo_getConnectivityState, 0, 0, 0)
743 ZEND_BEGIN_ARG_INFO_EX(arginfo_watchConnectivityState, 0, 0, 2)
744 ZEND_ARG_INFO(0, last_state)
745 ZEND_ARG_INFO(0, deadline)
748 ZEND_BEGIN_ARG_INFO_EX(arginfo_close, 0, 0, 0)
751 #ifdef GRPC_PHP_DEBUG
752 ZEND_BEGIN_ARG_INFO_EX(arginfo_getChannelInfo, 0, 0, 0)
755 ZEND_BEGIN_ARG_INFO_EX(arginfo_cleanPersistentList, 0, 0, 0)
758 ZEND_BEGIN_ARG_INFO_EX(arginfo_getPersistentList, 0, 0, 0)
764 PHP_ME(
Channel, __construct, arginfo_construct,
765 ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
766 PHP_ME(
Channel, getTarget, arginfo_getTarget,
768 PHP_ME(
Channel, getConnectivityState, arginfo_getConnectivityState,
770 PHP_ME(
Channel, watchConnectivityState, arginfo_watchConnectivityState,
774 #ifdef GRPC_PHP_DEBUG
775 PHP_ME(
Channel, getChannelInfo, arginfo_getChannelInfo,
777 PHP_ME(
Channel, cleanPersistentList, arginfo_cleanPersistentList,
779 PHP_ME(
Channel, getPersistentList, arginfo_getPersistentList,
791 le_plink = zend_register_list_destructors_ex(
795 le_bound = zend_register_list_destructors_ex(