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(