blob: 2ab229f5e6700a8fcc8bf2a4e885d7873c0e2cdb [file] [log] [blame]
mlumishb892a272014-12-09 16:28:23 -08001#include "channel.h"
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7#include "php.h"
8#include "php_ini.h"
9#include "ext/standard/info.h"
10#include "ext/spl/spl_exceptions.h"
11#include "php_grpc.h"
12
13#include "zend_exceptions.h"
14
15#include <stdbool.h>
16
17#include "grpc/grpc.h"
18#include "grpc/support/log.h"
19#include "grpc/grpc_security.h"
20
21#include "completion_queue.h"
22#include "server.h"
23#include "credentials.h"
24
25/* Frees and destroys an instance of wrapped_grpc_channel */
Craig Tillerb5dcec52015-01-13 11:13:42 -080026void free_wrapped_grpc_channel(void *object TSRMLS_DC) {
27 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object;
28 if (channel->wrapped != NULL) {
mlumishb892a272014-12-09 16:28:23 -080029 grpc_channel_destroy(channel->wrapped);
30 }
31 efree(channel);
32}
33
34/* Initializes an instance of wrapped_grpc_channel to be associated with an
35 * object of a class specified by class_type */
Craig Tillerb5dcec52015-01-13 11:13:42 -080036zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type
37 TSRMLS_DC) {
mlumishb892a272014-12-09 16:28:23 -080038 zend_object_value retval;
39 wrapped_grpc_channel *intern;
Craig Tillerb5dcec52015-01-13 11:13:42 -080040 intern = (wrapped_grpc_channel *)emalloc(sizeof(wrapped_grpc_channel));
mlumishb892a272014-12-09 16:28:23 -080041 memset(intern, 0, sizeof(wrapped_grpc_channel));
42 zend_object_std_init(&intern->std, class_type TSRMLS_CC);
43 object_properties_init(&intern->std, class_type);
44 retval.handle = zend_objects_store_put(
Craig Tillerb5dcec52015-01-13 11:13:42 -080045 intern, (zend_objects_store_dtor_t)zend_objects_destroy_object,
46 free_wrapped_grpc_channel, NULL TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -080047 retval.handlers = zend_get_std_object_handlers();
48 return retval;
49}
50
Craig Tillerb5dcec52015-01-13 11:13:42 -080051void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) {
mlumishb892a272014-12-09 16:28:23 -080052 HashTable *array_hash;
53 HashPosition array_pointer;
54 int args_index;
55 zval **data;
56 char *key;
57 uint key_len;
58 ulong index;
59 array_hash = Z_ARRVAL_P(args_array);
60 args->num_args = zend_hash_num_elements(array_hash);
61 args->args = ecalloc(args->num_args, sizeof(grpc_arg));
62 args_index = 0;
Craig Tillerb5dcec52015-01-13 11:13:42 -080063 for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
64 zend_hash_get_current_data_ex(array_hash, (void **)&data,
65 &array_pointer) == SUCCESS;
66 zend_hash_move_forward_ex(array_hash, &array_pointer)) {
67 if (zend_hash_get_current_key_ex(array_hash, &key, &key_len, &index, 0,
68 &array_pointer) != HASH_KEY_IS_STRING) {
mlumishb892a272014-12-09 16:28:23 -080069 zend_throw_exception(spl_ce_InvalidArgumentException,
Craig Tillerb5dcec52015-01-13 11:13:42 -080070 "args keys must be strings", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -080071 return;
72 }
73 args->args[args_index].key = key;
Craig Tillerb5dcec52015-01-13 11:13:42 -080074 switch (Z_TYPE_P(*data)) {
mlumishb892a272014-12-09 16:28:23 -080075 case IS_LONG:
76 args->args[args_index].value.integer = (int)Z_LVAL_P(*data);
77 break;
78 case IS_STRING:
79 args->args[args_index].value.string = Z_STRVAL_P(*data);
80 break;
81 default:
82 zend_throw_exception(spl_ce_InvalidArgumentException,
Craig Tillerb5dcec52015-01-13 11:13:42 -080083 "args values must be int or string", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -080084 return;
85 }
86 args_index++;
87 }
88}
89
90/**
91 * Construct an instance of the Channel class. If the $args array contains a
92 * "credentials" key mapping to a Credentials object, a secure channel will be
93 * created with those credentials.
94 * @param string $target The hostname to associate with this channel
95 * @param array $args The arguments to pass to the Channel (optional)
96 */
Craig Tillerb5dcec52015-01-13 11:13:42 -080097PHP_METHOD(Channel, __construct) {
mlumishb892a272014-12-09 16:28:23 -080098 wrapped_grpc_channel *channel =
Craig Tillerb5dcec52015-01-13 11:13:42 -080099 (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -0800100 char *target;
101 int target_length;
102 zval *args_array = NULL;
103 grpc_channel_args args;
104 HashTable *array_hash;
105 zval **creds_obj = NULL;
106 wrapped_grpc_credentials *creds = NULL;
107 /* "s|a" == 1 string, 1 optional array */
Craig Tillerb5dcec52015-01-13 11:13:42 -0800108 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &target,
109 &target_length, &args_array) == FAILURE) {
mlumishb892a272014-12-09 16:28:23 -0800110 zend_throw_exception(spl_ce_InvalidArgumentException,
Craig Tillerb5dcec52015-01-13 11:13:42 -0800111 "Channel expects a string and an array", 1 TSRMLS_CC);
mlumishb892a272014-12-09 16:28:23 -0800112 return;
113 }
114 if (args_array == NULL) {
115 channel->wrapped = grpc_channel_create(target, NULL);
116 } else {
117 array_hash = Z_ARRVAL_P(args_array);
Craig Tillerb5dcec52015-01-13 11:13:42 -0800118 if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
119 (void **)&creds_obj) == SUCCESS) {
120 if (zend_get_class_entry(*creds_obj TSRMLS_CC) != grpc_ce_credentials) {
mlumishb892a272014-12-09 16:28:23 -0800121 zend_throw_exception(spl_ce_InvalidArgumentException,
122 "credentials must be a Credentials object",
123 1 TSRMLS_CC);
124 return;
125 }
Craig Tillerb5dcec52015-01-13 11:13:42 -0800126 creds = (wrapped_grpc_credentials *)zend_object_store_get_object(
mlumishb892a272014-12-09 16:28:23 -0800127 *creds_obj TSRMLS_CC);
128 zend_hash_del(array_hash, "credentials", 12);
129 }
130 php_grpc_read_args_array(args_array, &args);
131 if (creds == NULL) {
132 channel->wrapped = grpc_channel_create(target, &args);
133 } else {
134 gpr_log(GPR_DEBUG, "Initialized secure channel");
Craig Tillerb5dcec52015-01-13 11:13:42 -0800135 channel->wrapped =
136 grpc_secure_channel_create(creds->wrapped, target, &args);
mlumishb892a272014-12-09 16:28:23 -0800137 }
138 efree(args.args);
139 }
Craig Tillerb5dcec52015-01-13 11:13:42 -0800140 channel->target = ecalloc(target_length + 1, sizeof(char));
mlumishb892a272014-12-09 16:28:23 -0800141 memcpy(channel->target, target, target_length);
142}
143
144/**
145 * Close the channel
146 */
Craig Tillerb5dcec52015-01-13 11:13:42 -0800147PHP_METHOD(Channel, close) {
mlumishb892a272014-12-09 16:28:23 -0800148 wrapped_grpc_channel *channel =
Craig Tillerb5dcec52015-01-13 11:13:42 -0800149 (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
150 if (channel->wrapped != NULL) {
mlumishb892a272014-12-09 16:28:23 -0800151 grpc_channel_destroy(channel->wrapped);
152 channel->wrapped = NULL;
153 }
154}
155
156static zend_function_entry channel_methods[] = {
Craig Tillerb5dcec52015-01-13 11:13:42 -0800157 PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
Craig Tillerecd49342015-01-18 14:36:47 -0800158 PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) PHP_FE_END};
mlumishb892a272014-12-09 16:28:23 -0800159
Craig Tillerb5dcec52015-01-13 11:13:42 -0800160void grpc_init_channel(TSRMLS_D) {
mlumishb892a272014-12-09 16:28:23 -0800161 zend_class_entry ce;
162 INIT_CLASS_ENTRY(ce, "Grpc\\Channel", channel_methods);
163 ce.create_object = create_wrapped_grpc_channel;
164 grpc_ce_channel = zend_register_internal_class(&ce TSRMLS_CC);
165}