diff options
Diffstat (limited to 'src/php')
33 files changed, 1705 insertions, 331 deletions
diff --git a/src/php/README.md b/src/php/README.md index 6cc1ba4d46..8abedc40a3 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -5,7 +5,7 @@ This directory contains source code for PHP implementation of gRPC layered on sh #Status -Beta +GA ## Environment @@ -43,7 +43,7 @@ $ sudo mv phpunit-old.phar /usr/bin/phpunit Install the gRPC PHP extension ```sh -sudo pecl install grpc-beta +sudo pecl install grpc ``` This will compile and install the gRPC PHP extension into the standard PHP extension directory. You should be able to run the [unit tests](#unit-tests), with the PHP extension installed. @@ -75,7 +75,7 @@ $ sudo make install Install the gRPC PHP extension from PECL ```sh -$ sudo pecl install grpc-beta +$ sudo pecl install grpc ``` Or, compile from source @@ -148,7 +148,7 @@ Alternatively, you can download `protoc` binaries from [the protocol buffers Git You need to install `protoc-gen-php` to generate stub class `.php` files from service definition `.proto` files. ```sh -$ cd grpc/src/php/vendor/datto/protobuf-php # if you had run `composer install` in the previous step +$ cd grpc/src/php/vendor/stanley-cheung/protobuf-php # if you had run `composer install` in the previous step OR diff --git a/src/php/composer.json b/src/php/composer.json index 01674a25db..23bfcedbe6 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,20 +2,14 @@ "name": "grpc/grpc", "type": "library", "description": "gRPC library for PHP", - "version": "0.14.0", "keywords": ["rpc"], "homepage": "http://grpc.io", "license": "BSD-3-Clause", - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/stanley-cheung/Protobuf-PHP" - } - ], + "version": "1.0.0", "require": { "php": ">=5.5.0", - "datto/protobuf-php": "dev-master", - "google/auth": "v0.7" + "stanley-cheung/protobuf-php": "dev-master", + "google/auth": "v0.9" }, "autoload": { "psr-4": { diff --git a/src/php/ext/grpc/byte_buffer.c b/src/php/ext/grpc/byte_buffer.c index 2bf9e00305..3be1429f13 100644 --- a/src/php/ext/grpc/byte_buffer.c +++ b/src/php/ext/grpc/byte_buffer.c @@ -65,15 +65,13 @@ void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string, *out_length = 0; return; } - size_t length = grpc_byte_buffer_length(buffer); + + gpr_slice slice = grpc_byte_buffer_reader_readall(&reader); + size_t length = GPR_SLICE_LENGTH(slice); char *string = ecalloc(length + 1, sizeof(char)); - size_t offset = 0; - gpr_slice next; - while (grpc_byte_buffer_reader_next(&reader, &next) != 0) { - memcpy(string + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next)); - offset += GPR_SLICE_LENGTH(next); - gpr_slice_unref(next); - } + memcpy(string, GPR_SLICE_START_PTR(slice), length); + gpr_slice_unref(slice); + *out_string = string; *out_length = length; } diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index 2cd45f10dc..bd1eccb01b 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -59,12 +59,15 @@ zend_class_entry *grpc_ce_call; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call */ void free_wrapped_grpc_call(void *object TSRMLS_DC) { wrapped_grpc_call *call = (wrapped_grpc_call *)object; if (call->owned && call->wrapped != NULL) { grpc_call_destroy(call->wrapped); } + zend_object_std_dtor(&call->std TSRMLS_CC); efree(call); } @@ -203,6 +206,131 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { return true; } +#else + +static zend_object_handlers call_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call */ +static void free_wrapped_grpc_call(zend_object *object) { + wrapped_grpc_call *call = wrapped_grpc_call_from_obj(object); + if (call->owned && call->wrapped != NULL) { + grpc_call_destroy(call->wrapped); + } + zend_object_std_dtor(&call->std); +} + +/* Initializes an instance of wrapped_grpc_call to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_call(zend_class_entry *class_type) { + wrapped_grpc_call *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_call) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &call_ce_handlers; + return &intern->std; +} + +/* Wraps a grpc_call struct in a PHP object. Owned indicates whether the + struct should be destroyed at the end of the object's lifecycle */ +void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object) { + object_init_ex(call_object, grpc_ce_call); + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(call_object); + call->wrapped = wrapped; + call->owned = owned; +} + +/* Creates and returns a PHP array object with the data in a + * grpc_metadata_array. Returns NULL on failure */ +void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, + zval *array) { + int count = metadata_array->count; + grpc_metadata *elements = metadata_array->metadata; + int i; + zval *data; + HashTable *array_hash; + zval inner_array; + char *str_key; + char *str_val; + size_t key_len; + + array_init(array); + array_hash = HASH_OF(array); + grpc_metadata *elem; + for (i = 0; i < count; i++) { + elem = &elements[i]; + key_len = strlen(elem->key); + str_key = ecalloc(key_len + 1, sizeof(char)); + memcpy(str_key, elem->key, key_len); + str_val = ecalloc(elem->value_length + 1, sizeof(char)); + memcpy(str_val, elem->value, elem->value_length); + if ((data = zend_hash_str_find(array_hash, str_key, key_len)) != NULL) { + if (Z_TYPE_P(data) != IS_ARRAY) { + zend_throw_exception(zend_exception_get_default(), + "Metadata hash somehow contains wrong types.", + 1); + efree(str_key); + efree(str_val); + return; + } + add_next_index_stringl(data, str_val, elem->value_length); + } else { + array_init(&inner_array); + add_next_index_stringl(&inner_array, str_val, elem->value_length); + add_assoc_zval(array, str_key, &inner_array); + } + } +} + +/* Populates a grpc_metadata_array with the data in a PHP array object. + Returns true on success and false on failure */ +bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { + zval *inner_array; + zval *value; + HashTable *array_hash; + HashTable *inner_array_hash; + zend_string *key; + if (Z_TYPE_P(array) != IS_ARRAY) { + return false; + } + grpc_metadata_array_init(metadata); + array_hash = HASH_OF(array); + + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { + if (key == NULL) { + return false; + } + if (Z_TYPE_P(inner_array) != IS_ARRAY) { + return false; + } + inner_array_hash = HASH_OF(inner_array); + metadata->capacity += zend_hash_num_elements(inner_array_hash); + } + ZEND_HASH_FOREACH_END(); + + metadata->metadata = gpr_malloc(metadata->capacity * sizeof(grpc_metadata)); + + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, inner_array) { + if (key == NULL) { + return false; + } + inner_array_hash = HASH_OF(inner_array); + + ZEND_HASH_FOREACH_VAL(inner_array_hash, value) { + if (Z_TYPE_P(value) != IS_STRING) { + return false; + } + metadata->metadata[metadata->count].key = ZSTR_VAL(key); + metadata->metadata[metadata->count].value = Z_STRVAL_P(value); + metadata->metadata[metadata->count].value_length = Z_STRLEN_P(value); + metadata->count += 1; + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + return true; +} + +#endif + /** * Constructs a new instance of the Call class. * @param Channel $channel The channel to associate the call with. Must not be @@ -211,30 +339,38 @@ bool create_metadata_array(zval *array, grpc_metadata_array *metadata) { * @param Timeval $absolute_deadline The deadline for completing the call */ PHP_METHOD(Call, __construct) { - wrapped_grpc_call *call = - (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); zval *channel_obj; char *method; - int method_len; zval *deadline_obj; char *host_override = NULL; +#if PHP_MAJOR_VERSION < 7 + int method_len; int host_override_len = 0; + wrapped_grpc_call *call = + (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t method_len; + size_t host_override_len = 0; + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif + /* "OsO|s" == 1 Object, 1 string, 1 Object, 1 optional string */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", - &channel_obj, grpc_ce_channel, - &method, &method_len, - &deadline_obj, grpc_ce_timeval, - &host_override, &host_override_len) - == FAILURE) { - zend_throw_exception( - spl_ce_InvalidArgumentException, - "Call expects a Channel, a String, a Timeval and an optional String", - 1 TSRMLS_CC); + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OsO|s", &channel_obj, + grpc_ce_channel, &method, &method_len, + &deadline_obj, grpc_ce_timeval, &host_override, + &host_override_len) == FAILURE) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Call expects a Channel, a String, a Timeval and " + "an optional String", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object( channel_obj TSRMLS_CC); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(channel_obj); +#endif if (channel->wrapped == NULL) { zend_throw_exception(spl_ce_InvalidArgumentException, "Call cannot be constructed from a closed Channel", @@ -242,12 +378,17 @@ PHP_METHOD(Call, __construct) { return; } add_property_zval(getThis(), "channel", channel_obj); +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *deadline = (wrapped_grpc_timeval *)zend_object_store_get_object( deadline_obj TSRMLS_CC); - call->wrapped = grpc_channel_create_call( - channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, completion_queue, method, - host_override, deadline->wrapped, NULL); +#else + wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); +#endif + call->wrapped = + grpc_channel_create_call(channel->wrapped, NULL, GRPC_PROPAGATE_DEFAULTS, + completion_queue, method, host_override, + deadline->wrapped, NULL); call->owned = true; } @@ -257,22 +398,40 @@ PHP_METHOD(Call, __construct) { * @return object Object with results of all actions */ PHP_METHOD(Call, startBatch) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); - grpc_op ops[8]; - size_t op_num = 0; - zval *array; zval **value; zval **inner_value; - HashTable *array_hash; HashPosition array_pointer; - HashTable *status_hash; - HashTable *message_hash; zval **message_value; zval **message_flags; char *key; uint key_len; ulong index; + zval *result; + zval *recv_status; + MAKE_STD_ZVAL(result); + object_init(result); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); + zval *value; + zval *inner_value; + zval *message_value; + zval *message_flags; + zend_string *key; + zend_ulong index; + zval recv_status; + object_init(return_value); +#endif + + grpc_op ops[8]; + size_t op_num = 0; + zval *array; + HashTable *array_hash; + HashTable *status_hash; + HashTable *message_hash; + grpc_metadata_array metadata; grpc_metadata_array trailing_metadata; grpc_metadata_array recv_metadata; @@ -283,17 +442,16 @@ PHP_METHOD(Call, startBatch) { grpc_byte_buffer *message; int cancelled; grpc_call_error error; - zval *result; char *message_str; size_t message_len; - zval *recv_status; + + grpc_metadata_array_init(&metadata); grpc_metadata_array_init(&trailing_metadata); grpc_metadata_array_init(&recv_metadata); grpc_metadata_array_init(&recv_trailing_metadata); - MAKE_STD_ZVAL(result); - object_init(result); memset(ops, 0, sizeof(ops)); + /* "a" == 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { @@ -301,6 +459,9 @@ PHP_METHOD(Call, startBatch) { "start_batch expects an array", 1 TSRMLS_CC); goto cleanup; } + +#if PHP_MAJOR_VERSION < 7 + array_hash = Z_ARRVAL_P(array); for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); zend_hash_get_current_data_ex(array_hash, (void**)&value, @@ -313,124 +474,250 @@ PHP_METHOD(Call, startBatch) { goto cleanup; } switch(index) { - case GRPC_OP_SEND_INITIAL_METADATA: - if (!create_metadata_array(*value, &metadata)) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!create_metadata_array(*value, &metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad metadata value given", 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].data.send_initial_metadata.count = + metadata.count; + ops[op_num].data.send_initial_metadata.metadata = + metadata.metadata; + break; + case GRPC_OP_SEND_MESSAGE: + if (Z_TYPE_PP(value) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an array for send message", + 1 TSRMLS_CC); + goto cleanup; + } + message_hash = Z_ARRVAL_PP(value); + if (zend_hash_find(message_hash, "flags", sizeof("flags"), + (void **)&message_flags) == SUCCESS) { + if (Z_TYPE_PP(message_flags) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad metadata value given", 1 TSRMLS_CC); - goto cleanup; + "Expected an int for message flags", + 1 TSRMLS_CC); } - ops[op_num].data.send_initial_metadata.count = - metadata.count; - ops[op_num].data.send_initial_metadata.metadata = - metadata.metadata; - break; - case GRPC_OP_SEND_MESSAGE: - if (Z_TYPE_PP(value) != IS_ARRAY) { + ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + } + if (zend_hash_find(message_hash, "message", sizeof("message"), + (void **)&message_value) != SUCCESS || + Z_TYPE_PP(message_value) != IS_STRING) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected a string for send message", + 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].data.send_message = + string_to_byte_buffer(Z_STRVAL_PP(message_value), + Z_STRLEN_PP(message_value)); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + status_hash = Z_ARRVAL_PP(value); + if (zend_hash_find(status_hash, "metadata", sizeof("metadata"), + (void **)&inner_value) == SUCCESS) { + if (!create_metadata_array(*inner_value, &trailing_metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an array for send message", + "Bad trailing metadata value given", 1 TSRMLS_CC); goto cleanup; } - message_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(message_hash, "flags", sizeof("flags"), - (void **)&message_flags) == SUCCESS) { - if (Z_TYPE_PP(message_flags) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected an int for message flags", - 1 TSRMLS_CC); - } - ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + ops[op_num].data.send_status_from_server.trailing_metadata = + trailing_metadata.metadata; + ops[op_num].data.send_status_from_server.trailing_metadata_count = + trailing_metadata.count; + } + if (zend_hash_find(status_hash, "code", sizeof("code"), + (void**)&inner_value) == SUCCESS) { + if (Z_TYPE_PP(inner_value) != IS_LONG) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Status code must be an integer", + 1 TSRMLS_CC); + goto cleanup; } - if (zend_hash_find(message_hash, "message", sizeof("message"), - (void **)&message_value) != SUCCESS || - Z_TYPE_PP(message_value) != IS_STRING) { + ops[op_num].data.send_status_from_server.status = + Z_LVAL_PP(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Integer status code is required", + 1 TSRMLS_CC); + goto cleanup; + } + if (zend_hash_find(status_hash, "details", sizeof("details"), + (void**)&inner_value) == SUCCESS) { + if (Z_TYPE_PP(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Expected a string for send message", + "Status details must be a string", 1 TSRMLS_CC); goto cleanup; } - ops[op_num].data.send_message = - string_to_byte_buffer(Z_STRVAL_PP(message_value), - Z_STRLEN_PP(message_value)); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - status_hash = Z_ARRVAL_PP(value); - if (zend_hash_find(status_hash, "metadata", sizeof("metadata"), - (void **)&inner_value) == SUCCESS) { - if (!create_metadata_array(*inner_value, &trailing_metadata)) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Bad trailing metadata value given", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.trailing_metadata = - trailing_metadata.metadata; - ops[op_num].data.send_status_from_server.trailing_metadata_count = - trailing_metadata.count; + ops[op_num].data.send_status_from_server.status_details = + Z_STRVAL_PP(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "String status details is required", + 1 TSRMLS_CC); + goto cleanup; + } + break; + case GRPC_OP_RECV_INITIAL_METADATA: + ops[op_num].data.recv_initial_metadata = &recv_metadata; + break; + case GRPC_OP_RECV_MESSAGE: + ops[op_num].data.recv_message = &message; + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + ops[op_num].data.recv_status_on_client.trailing_metadata = + &recv_trailing_metadata; + ops[op_num].data.recv_status_on_client.status = &status; + ops[op_num].data.recv_status_on_client.status_details = + &status_details; + ops[op_num].data.recv_status_on_client.status_details_capacity = + &status_details_capacity; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + ops[op_num].data.recv_close_on_server.cancelled = &cancelled; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "Unrecognized key in batch", 1 TSRMLS_CC); + goto cleanup; + } + ops[op_num].op = (grpc_op_type)index; + ops[op_num].flags = 0; + ops[op_num].reserved = NULL; + op_num++; + } + +#else + +array_hash = HASH_OF(array); + ZEND_HASH_FOREACH_KEY_VAL(array_hash, index, key, value) { + if (key) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "batch keys must be integers", 1); + goto cleanup; + } + + switch(index) { + case GRPC_OP_SEND_INITIAL_METADATA: + if (!create_metadata_array(value, &metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad metadata value given", 1); + goto cleanup; + } + ops[op_num].data.send_initial_metadata.count = metadata.count; + ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; + break; + case GRPC_OP_SEND_MESSAGE: + if (Z_TYPE_P(value) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an array for send message", 1); + goto cleanup; + } + message_hash = HASH_OF(value); + if ((message_flags = + zend_hash_str_find(message_hash, "flags", + sizeof("flags") - 1)) != NULL) { + if (Z_TYPE_P(message_flags) != IS_LONG) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an int for message flags", 1); + } + ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; + } + if ((message_value = zend_hash_str_find(message_hash, "message", + sizeof("message") - 1)) + == NULL || Z_TYPE_P(message_value) != IS_STRING) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected a string for send message", 1); + goto cleanup; + } + ops[op_num].data.send_message = + string_to_byte_buffer(Z_STRVAL_P(message_value), + Z_STRLEN_P(message_value)); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + status_hash = HASH_OF(value); + if ((inner_value = zend_hash_str_find(status_hash, "metadata", + sizeof("metadata") - 1)) + != NULL) { + if (!create_metadata_array(inner_value, &trailing_metadata)) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Bad trailing metadata value given", 1); + goto cleanup; } - if (zend_hash_find(status_hash, "code", sizeof("code"), - (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_LONG) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status code must be an integer", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status = - Z_LVAL_PP(inner_value); - } else { + ops[op_num].data.send_status_from_server.trailing_metadata = + trailing_metadata.metadata; + ops[op_num].data.send_status_from_server.trailing_metadata_count = + trailing_metadata.count; + } + if ((inner_value = zend_hash_str_find(status_hash, "code", + sizeof("code") - 1)) != NULL) { + if (Z_TYPE_P(inner_value) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, - "Integer status code is required", - 1 TSRMLS_CC); + "Status code must be an integer", 1); goto cleanup; } - if (zend_hash_find(status_hash, "details", sizeof("details"), - (void**)&inner_value) == SUCCESS) { - if (Z_TYPE_PP(inner_value) != IS_STRING) { - zend_throw_exception(spl_ce_InvalidArgumentException, - "Status details must be a string", - 1 TSRMLS_CC); - goto cleanup; - } - ops[op_num].data.send_status_from_server.status_details = - Z_STRVAL_PP(inner_value); - } else { + ops[op_num].data.send_status_from_server.status = + Z_LVAL_P(inner_value); + } else { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Integer status code is required", 1); + goto cleanup; + } + if ((inner_value = zend_hash_str_find(status_hash, "details", + sizeof("details") - 1)) != NULL) { + if (Z_TYPE_P(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, - "String status details is required", - 1 TSRMLS_CC); + "Status details must be a string", 1); goto cleanup; } - break; - case GRPC_OP_RECV_INITIAL_METADATA: - ops[op_num].data.recv_initial_metadata = &recv_metadata; - break; - case GRPC_OP_RECV_MESSAGE: - ops[op_num].data.recv_message = &message; - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - ops[op_num].data.recv_status_on_client.trailing_metadata = - &recv_trailing_metadata; - ops[op_num].data.recv_status_on_client.status = &status; - ops[op_num].data.recv_status_on_client.status_details = - &status_details; - ops[op_num].data.recv_status_on_client.status_details_capacity = - &status_details_capacity; - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - ops[op_num].data.recv_close_on_server.cancelled = &cancelled; - break; - default: + ops[op_num].data.send_status_from_server.status_details = + Z_STRVAL_P(inner_value); + } else { zend_throw_exception(spl_ce_InvalidArgumentException, - "Unrecognized key in batch", 1 TSRMLS_CC); + "String status details is required", 1); goto cleanup; + } + break; + case GRPC_OP_RECV_INITIAL_METADATA: + ops[op_num].data.recv_initial_metadata = &recv_metadata; + break; + case GRPC_OP_RECV_MESSAGE: + ops[op_num].data.recv_message = &message; + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + ops[op_num].data.recv_status_on_client.trailing_metadata = + &recv_trailing_metadata; + ops[op_num].data.recv_status_on_client.status = &status; + ops[op_num].data.recv_status_on_client.status_details = + &status_details; + ops[op_num].data.recv_status_on_client.status_details_capacity = + &status_details_capacity; + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + ops[op_num].data.recv_close_on_server.cancelled = &cancelled; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "Unrecognized key in batch", 1); + goto cleanup; } ops[op_num].op = (grpc_op_type)index; ops[op_num].flags = 0; ops[op_num].reserved = NULL; op_num++; } + ZEND_HASH_FOREACH_END(); + +#endif + error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped, NULL); if (error != GRPC_CALL_OK) { @@ -441,52 +728,98 @@ PHP_METHOD(Call, startBatch) { } grpc_completion_queue_pluck(completion_queue, call->wrapped, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +#if PHP_MAJOR_VERSION < 7 for (int i = 0; i < op_num; i++) { switch(ops[i].op) { - case GRPC_OP_SEND_INITIAL_METADATA: - add_property_bool(result, "send_metadata", true); - break; - case GRPC_OP_SEND_MESSAGE: - add_property_bool(result, "send_message", true); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - add_property_bool(result, "send_close", true); - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - add_property_bool(result, "send_status", true); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); - add_property_zval(result, "metadata", array); - Z_DELREF_P(array); - break; - case GRPC_OP_RECV_MESSAGE: - byte_buffer_to_string(message, &message_str, &message_len); - if (message_str == NULL) { - add_property_null(result, "message"); - } else { - add_property_stringl(result, "message", message_str, message_len, - false); - } - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - MAKE_STD_ZVAL(recv_status); - object_init(recv_status); - array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); - add_property_zval(recv_status, "metadata", array); - Z_DELREF_P(array); - add_property_long(recv_status, "code", status); - add_property_string(recv_status, "details", status_details, true); - add_property_zval(result, "status", recv_status); - Z_DELREF_P(recv_status); - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - add_property_bool(result, "cancelled", cancelled); - break; - default: - break; + case GRPC_OP_SEND_INITIAL_METADATA: + add_property_bool(result, "send_metadata", true); + break; + case GRPC_OP_SEND_MESSAGE: + add_property_bool(result, "send_message", true); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + add_property_bool(result, "send_close", true); + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + add_property_bool(result, "send_status", true); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + array = grpc_parse_metadata_array(&recv_metadata TSRMLS_CC); + add_property_zval(result, "metadata", array); + Z_DELREF_P(array); + break; + case GRPC_OP_RECV_MESSAGE: + byte_buffer_to_string(message, &message_str, &message_len); + if (message_str == NULL) { + add_property_null(result, "message"); + } else { + add_property_stringl(result, "message", message_str, message_len, + false); + } + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + MAKE_STD_ZVAL(recv_status); + object_init(recv_status); + array = grpc_parse_metadata_array(&recv_trailing_metadata TSRMLS_CC); + add_property_zval(recv_status, "metadata", array); + Z_DELREF_P(array); + add_property_long(recv_status, "code", status); + add_property_string(recv_status, "details", status_details, true); + add_property_zval(result, "status", recv_status); + Z_DELREF_P(recv_status); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + add_property_bool(result, "cancelled", cancelled); + break; + default: + break; + } + } +#else + for (int i = 0; i < op_num; i++) { + switch(ops[i].op) { + case GRPC_OP_SEND_INITIAL_METADATA: + add_property_bool(return_value, "send_metadata", true); + break; + case GRPC_OP_SEND_MESSAGE: + add_property_bool(return_value, "send_message", true); + break; + case GRPC_OP_SEND_CLOSE_FROM_CLIENT: + add_property_bool(return_value, "send_close", true); + break; + case GRPC_OP_SEND_STATUS_FROM_SERVER: + add_property_bool(return_value, "send_status", true); + break; + case GRPC_OP_RECV_INITIAL_METADATA: + grpc_parse_metadata_array(&recv_metadata, array); + add_property_zval(return_value, "metadata", array); + break; + case GRPC_OP_RECV_MESSAGE: + byte_buffer_to_string(message, &message_str, &message_len); + if (message_str == NULL) { + add_property_null(return_value, "message"); + } else { + add_property_stringl(return_value, "message", message_str, + message_len); + } + break; + case GRPC_OP_RECV_STATUS_ON_CLIENT: + object_init(&recv_status); + grpc_parse_metadata_array(&recv_trailing_metadata, array); + add_property_zval(&recv_status, "metadata", array); + add_property_long(&recv_status, "code", status); + add_property_string(&recv_status, "details", status_details); + add_property_zval(return_value, "status", &recv_status); + break; + case GRPC_OP_RECV_CLOSE_ON_SERVER: + add_property_bool(return_value, "cancelled", cancelled); + break; + default: + break; } } +#endif + cleanup: grpc_metadata_array_destroy(&metadata); grpc_metadata_array_destroy(&trailing_metadata); @@ -503,7 +836,11 @@ cleanup: grpc_byte_buffer_destroy(message); } } +#if PHP_MAJOR_VERSION < 7 RETURN_DESTROY_ZVAL(result); +#else + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -511,9 +848,14 @@ cleanup: * @return string The URI of the endpoint */ PHP_METHOD(Call, getPeer) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_STRING(grpc_call_get_peer(call->wrapped), 1); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); + RETURN_STRING(grpc_call_get_peer(call->wrapped)); +#endif } /** @@ -521,8 +863,12 @@ PHP_METHOD(Call, getPeer) { * has not already ended with another status. */ PHP_METHOD(Call, cancel) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif grpc_call_cancel(call->wrapped, NULL); } @@ -543,12 +889,17 @@ PHP_METHOD(Call, setCredentials) { return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call_credentials *creds = (wrapped_grpc_call_credentials *)zend_object_store_get_object( creds_obj TSRMLS_CC); - wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_call_credentials *creds = + Z_WRAPPED_GRPC_CALL_CREDS_P(creds_obj); + wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); +#endif grpc_call_error error = GRPC_CALL_ERROR; error = grpc_call_set_credentials(call->wrapped, creds->wrapped); @@ -556,16 +907,23 @@ PHP_METHOD(Call, setCredentials) { } static zend_function_entry call_methods[] = { - PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC) - PHP_FE_END}; + PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Call, setCredentials, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_call(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Call", call_methods); ce.create_object = create_wrapped_grpc_call; grpc_ce_call = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&call_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + call_ce_handlers.offset = XtOffsetOf(wrapped_grpc_call, std); + call_ce_handlers.free_obj = free_wrapped_grpc_call; +#endif } diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h index 36c5f2d272..9fc52d7820 100644 --- a/src/php/ext/grpc/call.h +++ b/src/php/ext/grpc/call.h @@ -48,17 +48,15 @@ /* Class entry for the Call PHP class */ extern zend_class_entry *grpc_ce_call; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_call that can be associated with a PHP object */ typedef struct wrapped_grpc_call { zend_object std; - bool owned; grpc_call *wrapped; } wrapped_grpc_call; -/* Initializes the Call PHP class */ -void grpc_init_call(TSRMLS_D); - /* Creates a Call object that wraps the given grpc_call struct */ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); @@ -66,6 +64,36 @@ zval *grpc_php_wrap_call(grpc_call *wrapped, bool owned TSRMLS_DC); * call metadata */ zval *grpc_parse_metadata_array(grpc_metadata_array *metadata_array TSRMLS_DC); +#else + +/* Wrapper struct for grpc_call that can be associated with a PHP object */ +typedef struct wrapped_grpc_call { + bool owned; + grpc_call *wrapped; + zend_object std; +} wrapped_grpc_call; + +static inline wrapped_grpc_call +*wrapped_grpc_call_from_obj(zend_object *obj) { + return (wrapped_grpc_call*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_call, std)); +} + +#define Z_WRAPPED_GRPC_CALL_P(zv) wrapped_grpc_call_from_obj(Z_OBJ_P((zv))) + +/* Creates a Call object that wraps the given grpc_call struct */ +void grpc_php_wrap_call(grpc_call *wrapped, bool owned, zval *call_object); + +/* Creates and returns a PHP associative array of metadata from a C array of + * call metadata */ +void grpc_parse_metadata_array(grpc_metadata_array *metadata_array, + zval *array); + +#endif /* PHP_MAJOR_VERSION */ + +/* Initializes the Call PHP class */ +void grpc_init_call(TSRMLS_D); + /* Populates a grpc_metadata_array with the data in a PHP array object. Returns true on success and false on failure */ bool create_metadata_array(zval *array, grpc_metadata_array *metadata); diff --git a/src/php/ext/grpc/call_credentials.c b/src/php/ext/grpc/call_credentials.c index ec0e6b9181..70aaffb848 100644 --- a/src/php/ext/grpc/call_credentials.c +++ b/src/php/ext/grpc/call_credentials.c @@ -53,6 +53,8 @@ zend_class_entry *grpc_ce_call_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call_credentials */ void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) { wrapped_grpc_call_credentials *creds = @@ -60,6 +62,7 @@ void free_wrapped_grpc_call_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_call_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -94,6 +97,43 @@ zval *grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped TSRMLS_DC) { return credentials_object; } +#else + +static zend_object_handlers call_credentials_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call_credentials */ +static void free_wrapped_grpc_call_credentials(zend_object *object) { + wrapped_grpc_call_credentials *creds = + wrapped_grpc_call_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_call_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instance of wrapped_grpc_call_credentials to be + * associated with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_call_credentials(zend_class_entry + *class_type) { + wrapped_grpc_call_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_call_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &call_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_call_credentials(grpc_call_credentials *wrapped, + zval *credentials_object) { + object_init_ex(credentials_object, grpc_ce_call_credentials); + wrapped_grpc_call_credentials *credentials = + Z_WRAPPED_GRPC_CALL_CREDS_P(credentials_object); + credentials->wrapped = wrapped; +} + +#endif + /** * Create composite credentials from two existing credentials. * @param CallCredentials cred1 The first credential @@ -113,6 +153,7 @@ PHP_METHOD(CallCredentials, createComposite) { 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_call_credentials *cred1 = (wrapped_grpc_call_credentials *)zend_object_store_get_object( cred1_obj TSRMLS_CC); @@ -124,6 +165,17 @@ PHP_METHOD(CallCredentials, createComposite) { NULL); zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + wrapped_grpc_call_credentials *cred1 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred1_obj); + wrapped_grpc_call_credentials *cred2 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); + grpc_call_credentials *creds = + grpc_composite_call_credentials_create(cred1->wrapped, + cred2->wrapped, NULL); + grpc_php_wrap_call_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -141,13 +193,10 @@ PHP_METHOD(CallCredentials, createFromPlugin) { memset(fci_cache, 0, sizeof(zend_fcall_info_cache)); /* "f" == 1 function */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f", fci, - fci_cache, - fci->params, - fci->param_count) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "f*", fci, fci_cache, + fci->params, fci->param_count) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, - "createFromPlugin expects 1 callback", - 1 TSRMLS_CC); + "createFromPlugin expects 1 callback", 1 TSRMLS_CC); return; } @@ -165,10 +214,15 @@ PHP_METHOD(CallCredentials, createFromPlugin) { plugin.state = (void *)state; plugin.type = ""; - grpc_call_credentials *creds = grpc_metadata_credentials_create_from_plugin( - plugin, NULL); + grpc_call_credentials *creds = + grpc_metadata_credentials_create_from_plugin(plugin, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_call_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_call_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /* Callback function for plugin creds API */ @@ -181,6 +235,7 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, /* prepare to call the user callback function with info from the * grpc_auth_metadata_context */ +#if PHP_MAJOR_VERSION < 7 zval **params[1]; zval *arg; zval *retval; @@ -192,21 +247,41 @@ void plugin_get_metadata(void *ptr, grpc_auth_metadata_context context, state->fci->param_count = 1; state->fci->params = params; state->fci->retval_ptr_ptr = &retval; +#else + zval arg; + zval retval; + object_init(&arg); + add_property_string(&arg, "service_url", context.service_url); + add_property_string(&arg, "method_name", context.method_name); + state->fci->param_count = 1; + state->fci->params = &arg; + state->fci->retval = &retval; +#endif /* call the user callback function */ zend_call_function(state->fci, state->fci_cache TSRMLS_CC); +#if PHP_MAJOR_VERSION < 7 if (Z_TYPE_P(retval) != IS_ARRAY) { +#else + if (Z_TYPE_P(&retval) != IS_ARRAY) { +#endif zend_throw_exception(spl_ce_InvalidArgumentException, "plugin callback must return metadata array", 1 TSRMLS_CC); + return; } grpc_metadata_array metadata; +#if PHP_MAJOR_VERSION < 7 if (!create_metadata_array(retval, &metadata)) { +#else + if (!create_metadata_array(&retval, &metadata)) { +#endif zend_throw_exception(spl_ce_InvalidArgumentException, "invalid metadata", 1 TSRMLS_CC); grpc_metadata_array_destroy(&metadata); + return; } /* TODO: handle error */ @@ -229,11 +304,21 @@ static zend_function_entry call_credentials_methods[] = { ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(CallCredentials, createFromPlugin, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_FE_END}; + PHP_FE_END +}; void grpc_init_call_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\CallCredentials", call_credentials_methods); ce.create_object = create_wrapped_grpc_call_credentials; grpc_ce_call_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&call_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + call_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_call_credentials, std); + call_credentials_ce_handlers.free_obj = + free_wrapped_grpc_call_credentials; +#endif } diff --git a/src/php/ext/grpc/call_credentials.h b/src/php/ext/grpc/call_credentials.h index d2f6a92449..e05e14698b 100755 --- a/src/php/ext/grpc/call_credentials.h +++ b/src/php/ext/grpc/call_credentials.h @@ -49,14 +49,37 @@ /* Class entry for the CallCredentials PHP class */ extern zend_class_entry *grpc_ce_call_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_call_credentials that can be associated * with a PHP object */ typedef struct wrapped_grpc_call_credentials { zend_object std; + grpc_call_credentials *wrapped; +} wrapped_grpc_call_credentials; +#else + +/* Wrapper struct for grpc_call_credentials that can be associated + * with a PHP object */ +typedef struct wrapped_grpc_call_credentials { grpc_call_credentials *wrapped; + zend_object std; } wrapped_grpc_call_credentials; +static inline wrapped_grpc_call_credentials +*wrapped_grpc_call_creds_from_obj(zend_object *obj) { + return + (wrapped_grpc_call_credentials*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_call_credentials, + std)); +} + +#define Z_WRAPPED_GRPC_CALL_CREDS_P(zv) \ + wrapped_grpc_call_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Struct to hold callback function for plugin creds API */ typedef struct plugin_state { zend_fcall_info *fci; diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 9f0431908f..6737e340f9 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -48,7 +48,6 @@ #include <stdbool.h> #include <grpc/grpc.h> -#include <grpc/support/log.h> #include <grpc/grpc_security.h> #include "completion_queue.h" @@ -58,12 +57,15 @@ zend_class_entry *grpc_ce_channel; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_channel */ void free_wrapped_grpc_channel(void *object TSRMLS_DC) { wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object; if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); } + zend_object_std_dtor(&channel->std TSRMLS_CC); efree(channel); } @@ -84,7 +86,8 @@ zend_object_value create_wrapped_grpc_channel(zend_class_entry *class_type return retval; } -void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_DC) { +void php_grpc_read_args_array(zval *args_array, + grpc_channel_args *args TSRMLS_DC) { HashTable *array_hash; HashPosition array_pointer; int args_index; @@ -108,23 +111,88 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_D } args->args[args_index].key = key; switch (Z_TYPE_P(*data)) { - case IS_LONG: - args->args[args_index].value.integer = (int)Z_LVAL_P(*data); - args->args[args_index].type = GRPC_ARG_INTEGER; - break; - case IS_STRING: - args->args[args_index].value.string = Z_STRVAL_P(*data); - args->args[args_index].type = GRPC_ARG_STRING; - break; - default: - zend_throw_exception(spl_ce_InvalidArgumentException, - "args values must be int or string", 1 TSRMLS_CC); - return; + case IS_LONG: + args->args[args_index].value.integer = (int)Z_LVAL_P(*data); + args->args[args_index].type = GRPC_ARG_INTEGER; + break; + case IS_STRING: + args->args[args_index].value.string = Z_STRVAL_P(*data); + args->args[args_index].type = GRPC_ARG_STRING; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "args values must be int or string", 1 TSRMLS_CC); + return; } args_index++; } } +#else + +static zend_object_handlers channel_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_channel */ +static void free_wrapped_grpc_channel(zend_object *object) { + wrapped_grpc_channel *channel = wrapped_grpc_channel_from_obj(object); + if (channel->wrapped != NULL) { + grpc_channel_destroy(channel->wrapped); + } + zend_object_std_dtor(&channel->std); +} + +/* Initializes an instance of wrapped_grpc_channel to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_channel(zend_class_entry *class_type) { + wrapped_grpc_channel *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_channel) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &channel_ce_handlers; + return &intern->std; +} + +void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args) { + HashTable *array_hash; + int args_index; + zval *data; + zend_string *key; + array_hash = HASH_OF(args_array); + if (!array_hash) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "array_hash is NULL", 1); + return; + } + args->num_args = zend_hash_num_elements(array_hash); + args->args = ecalloc(args->num_args, sizeof(grpc_arg)); + args_index = 0; + ZEND_HASH_FOREACH_STR_KEY_VAL(array_hash, key, data) { + if (key == NULL) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "args keys must be strings", 1); + } + args->args[args_index].key = ZSTR_VAL(key); + switch (Z_TYPE_P(data)) { + case IS_LONG: + args->args[args_index].value.integer = (int)Z_LVAL_P(data); + args->args[args_index].type = GRPC_ARG_INTEGER; + break; + case IS_STRING: + args->args[args_index].value.string = Z_STRVAL_P(data); + args->args[args_index].type = GRPC_ARG_STRING; + break; + default: + zend_throw_exception(spl_ce_InvalidArgumentException, + "args values must be int or string", 1); + return; + } + args_index++; + } ZEND_HASH_FOREACH_END(); +} + +#endif + /** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel @@ -133,16 +201,23 @@ void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args TSRMLS_D * @param array $args The arguments to pass to the Channel (optional) */ PHP_METHOD(Channel, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object( getThis() TSRMLS_CC); - char *target; + zval **creds_obj = NULL; int target_length; +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); + zval *creds_obj = NULL; + size_t target_length; +#endif + char *target; zval *args_array = NULL; grpc_channel_args args; HashTable *array_hash; - zval **creds_obj = NULL; wrapped_grpc_channel_credentials *creds = NULL; + /* "sa" == 1 string, 1 array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &target, &target_length, &args_array) == FAILURE) { @@ -150,6 +225,7 @@ PHP_METHOD(Channel, __construct) { "Channel expects a string and an array", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 array_hash = Z_ARRVAL_P(args_array); if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), (void **)&creds_obj) == SUCCESS) { @@ -168,11 +244,28 @@ PHP_METHOD(Channel, __construct) { zend_hash_del(array_hash, "credentials", 12); } } +#else + array_hash = HASH_OF(args_array); + if ((creds_obj = zend_hash_str_find(array_hash, "credentials", + sizeof("credentials") - 1)) != NULL) { + if (Z_TYPE_P(creds_obj) == IS_NULL) { + creds = NULL; + zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); + } else if (Z_OBJ_P(creds_obj)->ce != grpc_ce_channel_credentials) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "credentials must be a ChannelCredentials object", + 1); + return; + } else { + creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj); + zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); + } + } +#endif php_grpc_read_args_array(args_array, &args TSRMLS_CC); if (creds == NULL) { channel->wrapped = grpc_insecure_channel_create(target, &args, NULL); } else { - gpr_log(GPR_DEBUG, "Initialized secure channel"); channel->wrapped = grpc_secure_channel_create(creds->wrapped, target, &args, NULL); } @@ -184,9 +277,14 @@ PHP_METHOD(Channel, __construct) { * @return string The URI of the endpoint */ PHP_METHOD(Channel, getTarget) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); + (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); + RETURN_STRING(grpc_channel_get_target(channel->wrapped)); +#endif } /** @@ -195,12 +293,17 @@ PHP_METHOD(Channel, getTarget) { * @return long The grpc connectivity state */ PHP_METHOD(Channel, getConnectivityState) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); - bool try_to_connect; +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif + bool try_to_connect = false; + /* "|b" == 1 optional bool */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &try_to_connect) + == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "getConnectivityState expects a bool", 1 TSRMLS_CC); return; @@ -217,10 +320,16 @@ PHP_METHOD(Channel, getConnectivityState) { * before deadline */ PHP_METHOD(Channel, watchConnectivityState) { +#if PHP_MAJOR_VERSION < 7 + long last_state; wrapped_grpc_channel *channel = (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); - long last_state; +#else + zend_long last_state; + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif 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) { @@ -230,15 +339,20 @@ PHP_METHOD(Channel, watchConnectivityState) { return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *deadline = (wrapped_grpc_timeval *)zend_object_store_get_object( deadline_obj TSRMLS_CC); - grpc_channel_watch_connectivity_state( - channel->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); +#else + wrapped_grpc_timeval *deadline = Z_WRAPPED_GRPC_TIMEVAL_P(deadline_obj); +#endif + grpc_channel_watch_connectivity_state(channel->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); RETURN_BOOL(event.success); } @@ -246,8 +360,12 @@ PHP_METHOD(Channel, watchConnectivityState) { * Close the channel */ PHP_METHOD(Channel, close) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel *channel = - (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); + (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); +#endif if (channel->wrapped != NULL) { grpc_channel_destroy(channel->wrapped); channel->wrapped = NULL; @@ -255,16 +373,24 @@ PHP_METHOD(Channel, close) { } static zend_function_entry channel_methods[] = { - PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) - PHP_FE_END}; + PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, getConnectivityState, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, watchConnectivityState, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_channel(TSRMLS_D) { 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); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&channel_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + channel_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_channel, std); + channel_ce_handlers.free_obj = free_wrapped_grpc_channel; +#endif } diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h index cc5823ee7f..ea5efeaf86 100755 --- a/src/php/ext/grpc/channel.h +++ b/src/php/ext/grpc/channel.h @@ -48,17 +48,38 @@ /* Class entry for the PHP Channel class */ extern zend_class_entry *grpc_ce_channel; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_channel that can be associated with a PHP object */ typedef struct wrapped_grpc_channel { zend_object std; + grpc_channel *wrapped; +} wrapped_grpc_channel; +#else + +/* Wrapper struct for grpc_channel that can be associated with a PHP object */ +typedef struct wrapped_grpc_channel { grpc_channel *wrapped; + zend_object std; } wrapped_grpc_channel; +static inline wrapped_grpc_channel +*wrapped_grpc_channel_from_obj(zend_object *obj) { + return (wrapped_grpc_channel*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_channel, std)); +} + +#define Z_WRAPPED_GRPC_CHANNEL_P(zv) \ + wrapped_grpc_channel_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Channel class */ void grpc_init_channel(TSRMLS_D); /* 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); +void php_grpc_read_args_array(zval *args_array, grpc_channel_args *args + TSRMLS_DC); #endif /* NET_GRPC_PHP_GRPC_CHANNEL_H_ */ diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index b76fb105f3..16ba0368eb 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -52,7 +52,6 @@ #include <grpc/grpc_security.h> zend_class_entry *grpc_ce_channel_credentials; - static char *default_pem_root_certs = NULL; static grpc_ssl_roots_override_result get_ssl_roots_override( @@ -64,6 +63,8 @@ static grpc_ssl_roots_override_result get_ssl_roots_override( return GRPC_SSL_ROOTS_OVERRIDE_OK; } +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_channel_credentials */ void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) { wrapped_grpc_channel_credentials *creds = @@ -71,6 +72,7 @@ void free_wrapped_grpc_channel_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_channel_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -94,7 +96,8 @@ zend_object_value create_wrapped_grpc_channel_credentials( return retval; } -zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS_DC) { +zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials + *wrapped TSRMLS_DC) { zval *credentials_object; MAKE_STD_ZVAL(credentials_object); object_init_ex(credentials_object, grpc_ce_channel_credentials); @@ -105,6 +108,43 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS return credentials_object; } +#else + +static zend_object_handlers channel_credentials_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_channel_credentials */ +static void free_wrapped_grpc_channel_credentials(zend_object *object) { + wrapped_grpc_channel_credentials *creds = + wrapped_grpc_channel_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_channel_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instance of wrapped_grpc_channel_credentials to be + * associated with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_channel_credentials(zend_class_entry + *class_type) { + wrapped_grpc_channel_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_channel_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &channel_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped, + 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; +} + +#endif + /** * Set default roots pem. * @param string pem_roots PEM encoding of the server root certificates @@ -112,7 +152,13 @@ zval *grpc_php_wrap_channel_credentials(grpc_channel_credentials *wrapped TSRMLS */ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { char *pem_roots; +#if PHP_MAJOR_VERSION < 7 int pem_roots_length; +#else + size_t pem_roots_length; +#endif + + /* "s" == 1 string */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pem_roots, &pem_roots_length) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, @@ -129,8 +175,13 @@ PHP_METHOD(ChannelCredentials, setDefaultRootsPem) { */ PHP_METHOD(ChannelCredentials, createDefault) { grpc_channel_credentials *creds = grpc_google_default_credentials_create(); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -146,11 +197,15 @@ PHP_METHOD(ChannelCredentials, createSsl) { char *pem_root_certs = NULL; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; +#if PHP_MAJOR_VERSION < 7 int root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; +#else + size_t root_certs_length = 0, private_key_length = 0, cert_chain_length = 0; +#endif pem_key_cert_pair.private_key = pem_key_cert_pair.cert_chain = NULL; - /* "|s!s!s! == 3 optional nullable strings */ + /* "|s!s!s!" == 3 optional nullable strings */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!s!", &pem_root_certs, &root_certs_length, &pem_key_cert_pair.private_key, @@ -164,8 +219,13 @@ PHP_METHOD(ChannelCredentials, createSsl) { grpc_channel_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -178,7 +238,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { zval *cred1_obj; zval *cred2_obj; - /* "OO" == 3 Objects */ + /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &cred1_obj, grpc_ce_channel_credentials, &cred2_obj, grpc_ce_call_credentials) == FAILURE) { @@ -186,6 +246,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { "createComposite expects 2 Credentials", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_channel_credentials *cred1 = (wrapped_grpc_channel_credentials *)zend_object_store_get_object( cred1_obj TSRMLS_CC); @@ -197,6 +258,17 @@ PHP_METHOD(ChannelCredentials, createComposite) { NULL); zval *creds_object = grpc_php_wrap_channel_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + wrapped_grpc_channel_credentials *cred1 = + Z_WRAPPED_GRPC_CHANNEL_CREDS_P(cred1_obj); + wrapped_grpc_call_credentials *cred2 = + Z_WRAPPED_GRPC_CALL_CREDS_P(cred2_obj); + grpc_channel_credentials *creds = + grpc_composite_channel_credentials_create(cred1->wrapped, + cred2->wrapped, NULL); + grpc_php_wrap_channel_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -218,7 +290,8 @@ static zend_function_entry channel_credentials_methods[] = { ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(ChannelCredentials, createInsecure, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_FE_END}; + PHP_FE_END +}; void grpc_init_channel_credentials(TSRMLS_D) { zend_class_entry ce; @@ -227,4 +300,13 @@ void grpc_init_channel_credentials(TSRMLS_D) { grpc_set_ssl_roots_override_callback(get_ssl_roots_override); ce.create_object = create_wrapped_grpc_channel_credentials; grpc_ce_channel_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&channel_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + channel_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_channel_credentials, std); + channel_credentials_ce_handlers.free_obj = + free_wrapped_grpc_channel_credentials; +#endif } diff --git a/src/php/ext/grpc/channel_credentials.h b/src/php/ext/grpc/channel_credentials.h index d89984ce60..44071b10f1 100755 --- a/src/php/ext/grpc/channel_credentials.h +++ b/src/php/ext/grpc/channel_credentials.h @@ -49,14 +49,37 @@ /* Class entry for the ChannelCredentials PHP class */ extern zend_class_entry *grpc_ce_channel_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_channel_credentials that can be associated * with a PHP object */ typedef struct wrapped_grpc_channel_credentials { zend_object std; + grpc_channel_credentials *wrapped; +} wrapped_grpc_channel_credentials; +#else + +/* Wrapper struct for grpc_channel_credentials that can be associated + * with a PHP object */ +typedef struct wrapped_grpc_channel_credentials { grpc_channel_credentials *wrapped; + zend_object std; } wrapped_grpc_channel_credentials; +static inline wrapped_grpc_channel_credentials +*wrapped_grpc_channel_creds_from_obj(zend_object *obj) { + return + (wrapped_grpc_channel_credentials *) + ((char*)(obj) - + XtOffsetOf(wrapped_grpc_channel_credentials, std)); +} + +#define Z_WRAPPED_GRPC_CHANNEL_CREDS_P(zv) \ + wrapped_grpc_channel_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the ChannelCredentials PHP class */ void grpc_init_channel_credentials(TSRMLS_D); diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c index f4cb5b28cc..5edfa2da7d 100644 --- a/src/php/ext/grpc/php_grpc.c +++ b/src/php/ext/grpc/php_grpc.c @@ -64,15 +64,19 @@ const zend_function_entry grpc_functions[] = { */ zend_module_entry grpc_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER, #endif - "grpc", grpc_functions, PHP_MINIT(grpc), - PHP_MSHUTDOWN(grpc), NULL, NULL, - PHP_MINFO(grpc), + "grpc", + grpc_functions, + PHP_MINIT(grpc), + PHP_MSHUTDOWN(grpc), + NULL, + NULL, + PHP_MINFO(grpc), #if ZEND_MODULE_API_NO >= 20010901 - PHP_GRPC_VERSION, + PHP_GRPC_VERSION, #endif - STANDARD_MODULE_PROPERTIES}; + STANDARD_MODULE_PROPERTIES}; /* }}} */ #ifdef COMPILE_DL_GRPC @@ -82,23 +86,24 @@ ZEND_GET_MODULE(grpc) /* {{{ PHP_INI */ /* Remove comments and fill if you need to have entries in php.ini -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, -global_value, zend_grpc_globals, grpc_globals) - STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, -OnUpdateString, global_string, zend_grpc_globals, grpc_globals) -PHP_INI_END() + PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, + global_value, zend_grpc_globals, grpc_globals) + STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, + OnUpdateString, global_string, zend_grpc_globals, + grpc_globals) + PHP_INI_END() */ /* }}} */ /* {{{ php_grpc_init_globals */ /* Uncomment this function if you have INI entries -static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) -{ - grpc_globals->global_value = 0; - grpc_globals->global_string = NULL; -} + static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) + { + grpc_globals->global_value = 0; + grpc_globals->global_string = NULL; + } */ /* }}} */ @@ -106,7 +111,7 @@ static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) */ PHP_MINIT_FUNCTION(grpc) { /* If you have INI entries, uncomment these lines - REGISTER_INI_ENTRIES(); + REGISTER_INI_ENTRIES(); */ /* Register call error constants */ grpc_init(); @@ -246,8 +251,10 @@ PHP_MINIT_FUNCTION(grpc) { */ PHP_MSHUTDOWN_FUNCTION(grpc) { /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); + UNREGISTER_INI_ENTRIES(); */ + // WARNING: This function IS being called by PHP when the extension + // is unloaded but the logs were somehow suppressed. grpc_shutdown_timeval(TSRMLS_C); grpc_php_shutdown_completion_queue(TSRMLS_C); grpc_shutdown(); @@ -263,7 +270,7 @@ PHP_MINFO_FUNCTION(grpc) { php_info_print_table_end(); /* Remove comments if you have entries in php.ini - DISPLAY_INI_ENTRIES(); + DISPLAY_INI_ENTRIES(); */ } /* }}} */ @@ -272,12 +279,3 @@ PHP_MINFO_FUNCTION(grpc) { function definition, where the functions purpose is also documented. Please follow this convention for the convenience of others editing your code. */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index 1d4834c50f..bd7ee75a6f 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -72,8 +72,8 @@ PHP_MSHUTDOWN_FUNCTION(grpc); PHP_MINFO_FUNCTION(grpc); /* - Declare any global variables you may need between the BEGIN - and END macros here: + Declare any global variables you may need between the BEGIN + and END macros here: ZEND_BEGIN_MODULE_GLOBALS(grpc) ZEND_END_MODULE_GLOBALS(grpc) diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index 6df2e4f978..50fb2d0cf9 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -48,7 +48,6 @@ #include <stdbool.h> #include <grpc/grpc.h> -#include <grpc/support/log.h> #include <grpc/grpc_security.h> #include "completion_queue.h" @@ -59,6 +58,8 @@ zend_class_entry *grpc_ce_server; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_server */ void free_wrapped_grpc_server(void *object TSRMLS_DC) { wrapped_grpc_server *server = (wrapped_grpc_server *)object; @@ -69,6 +70,7 @@ void free_wrapped_grpc_server(void *object TSRMLS_DC) { gpr_inf_future(GPR_CLOCK_REALTIME), NULL); grpc_server_destroy(server->wrapped); } + zend_object_std_dtor(&server->std TSRMLS_CC); efree(server); } @@ -91,15 +93,51 @@ zend_object_value create_wrapped_grpc_server(zend_class_entry *class_type return retval; } +#else + +static zend_object_handlers server_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_server */ +static void free_wrapped_grpc_server(zend_object *object) { + wrapped_grpc_server *server = wrapped_grpc_server_from_obj(object); + if (server->wrapped != NULL) { + grpc_server_shutdown_and_notify(server->wrapped, completion_queue, NULL); + grpc_server_cancel_all_calls(server->wrapped); + grpc_completion_queue_pluck(completion_queue, NULL, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_server_destroy(server->wrapped); + } + zend_object_std_dtor(&server->std); +} + +/* Initializes an instance of wrapped_grpc_call to be associated with an object + * of a class specified by class_type */ +zend_object *create_wrapped_grpc_server(zend_class_entry *class_type) { + wrapped_grpc_server *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_server) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &server_ce_handlers; + return &intern->std; +} + +#endif + /** * Constructs a new instance of the Server class * @param array $args The arguments to pass to the server (optional) */ PHP_METHOD(Server, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server *server = (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif zval *args_array = NULL; grpc_channel_args args; + /* "|a" == 1 optional array */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", &args_array) == FAILURE) { @@ -111,6 +149,8 @@ PHP_METHOD(Server, __construct) { if (args_array == NULL) { server->wrapped = grpc_server_create(NULL, NULL); } else { + //TODO(thinkerou): deal it if key of array is long, crash now on php7 + // and update unit test case php_grpc_read_args_array(args_array, &args TSRMLS_CC); server->wrapped = grpc_server_create(&args, NULL); efree(args.args); @@ -127,15 +167,22 @@ PHP_METHOD(Server, __construct) { */ PHP_METHOD(Server, requestCall) { grpc_call_error error_code; - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); grpc_call *call; grpc_call_details details; grpc_metadata_array metadata; - zval *result; grpc_event event; + +#if PHP_MAJOR_VERSION < 7 + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); + zval *result; MAKE_STD_ZVAL(result); object_init(result); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); + object_init(return_value); +#endif + grpc_call_details_init(&details); grpc_metadata_array_init(&metadata); error_code = @@ -147,23 +194,48 @@ PHP_METHOD(Server, requestCall) { goto cleanup; } event = grpc_completion_queue_pluck(completion_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); if (!event.success) { zend_throw_exception(spl_ce_LogicException, "Failed to request a call for some reason", 1 TSRMLS_CC); goto cleanup; } +#if PHP_MAJOR_VERSION < 7 add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC)); add_property_string(result, "method", details.method, true); add_property_string(result, "host", details.host, true); add_property_zval(result, "absolute_deadline", grpc_php_wrap_timeval(details.deadline TSRMLS_CC)); - add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata TSRMLS_CC)); + add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata + TSRMLS_CC)); + cleanup: grpc_call_details_destroy(&details); grpc_metadata_array_destroy(&metadata); RETURN_DESTROY_ZVAL(result); + +#else + + zval zv_call; + zval zv_timeval; + zval zv_md; + grpc_php_wrap_call(call, true, &zv_call); + grpc_php_wrap_timeval(details.deadline, &zv_timeval); + grpc_parse_metadata_array(&metadata, &zv_md); + + add_property_zval(return_value, "call", &zv_call); + add_property_string(return_value, "method", details.method); + add_property_string(return_value, "host", details.host); + add_property_zval(return_value, "absolute_deadline", &zv_timeval); + add_property_zval(return_value, "metadata", &zv_md); + + cleanup: + grpc_call_details_destroy(&details); + grpc_metadata_array_destroy(&metadata); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -172,13 +244,19 @@ cleanup: * @return true on success, false on failure */ PHP_METHOD(Server, addHttp2Port) { - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); const char *addr; +#if PHP_MAJOR_VERSION < 7 int addr_len; + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t addr_len; + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif + /* "s" == 1 string */ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) == - FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &addr, &addr_len) + == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "add_http2_port expects a string", 1 TSRMLS_CC); return; @@ -187,11 +265,17 @@ PHP_METHOD(Server, addHttp2Port) { } PHP_METHOD(Server, addSecureHttp2Port) { - wrapped_grpc_server *server = - (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); const char *addr; - int addr_len; zval *creds_obj; +#if PHP_MAJOR_VERSION < 7 + int addr_len; + wrapped_grpc_server *server = + (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + size_t addr_len; + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif + /* "sO" == 1 string, 1 object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len, &creds_obj, grpc_ce_server_credentials) == @@ -201,9 +285,14 @@ PHP_METHOD(Server, addSecureHttp2Port) { "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server_credentials *creds = (wrapped_grpc_server_credentials *)zend_object_store_get_object( creds_obj TSRMLS_CC); +#else + wrapped_grpc_server_credentials *creds = + Z_WRAPPED_GRPC_SERVER_CREDS_P(creds_obj); +#endif RETURN_LONG(grpc_server_add_secure_http2_port(server->wrapped, addr, creds->wrapped)); } @@ -213,21 +302,33 @@ PHP_METHOD(Server, addSecureHttp2Port) { * @return Void */ PHP_METHOD(Server, start) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_server *server = (wrapped_grpc_server *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_server *server = Z_WRAPPED_GRPC_SERVER_P(getThis()); +#endif grpc_server_start(server->wrapped); } static zend_function_entry server_methods[] = { - PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) PHP_FE_END}; + PHP_ME(Server, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Server, requestCall, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, addHttp2Port, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, addSecureHttp2Port, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Server, start, NULL, ZEND_ACC_PUBLIC) + PHP_FE_END +}; void grpc_init_server(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Server", server_methods); ce.create_object = create_wrapped_grpc_server; grpc_ce_server = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&server_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + server_ce_handlers.offset = XtOffsetOf(wrapped_grpc_server, std); + server_ce_handlers.free_obj = free_wrapped_grpc_server; +#endif } diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h index 022257f37c..a7df456a11 100755 --- a/src/php/ext/grpc/server.h +++ b/src/php/ext/grpc/server.h @@ -48,13 +48,33 @@ /* Class entry for the Server PHP class */ extern zend_class_entry *grpc_ce_server; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_server that can be associated with a PHP object */ typedef struct wrapped_grpc_server { zend_object std; + grpc_server *wrapped; +} wrapped_grpc_server; +#else + +/* Wrapper struct for grpc_server that can be associated with a PHP object */ +typedef struct wrapped_grpc_server { grpc_server *wrapped; + zend_object std; } wrapped_grpc_server; +static inline wrapped_grpc_server +*wrapped_grpc_server_from_obj(zend_object *obj) { + return (wrapped_grpc_server*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_server, std)); +} + +#define Z_WRAPPED_GRPC_SERVER_P(zv) \ + wrapped_grpc_server_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Server class */ void grpc_init_server(TSRMLS_D); diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index 505da10a28..296632d5bd 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -51,6 +51,8 @@ zend_class_entry *grpc_ce_server_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instace of wrapped_grpc_server_credentials */ void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { wrapped_grpc_server_credentials *creds = @@ -58,6 +60,7 @@ void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) { if (creds->wrapped != NULL) { grpc_server_credentials_release(creds->wrapped); } + zend_object_std_dtor(&creds->std TSRMLS_CC); efree(creds); } @@ -81,7 +84,8 @@ zend_object_value create_wrapped_grpc_server_credentials( return retval; } -zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_DC) { +zval *grpc_php_wrap_server_credentials(grpc_server_credentials + *wrapped TSRMLS_DC) { zval *server_credentials_object; MAKE_STD_ZVAL(server_credentials_object); object_init_ex(server_credentials_object, grpc_ce_server_credentials); @@ -92,6 +96,43 @@ zval *grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped TSRMLS_D return server_credentials_object; } +#else + +static zend_object_handlers server_credentials_ce_handlers; + +/* Frees and destroys an instace of wrapped_grpc_server_credentials */ +static void free_wrapped_grpc_server_credentials(zend_object *object) { + wrapped_grpc_server_credentials *creds = + wrapped_grpc_server_creds_from_obj(object); + if (creds->wrapped != NULL) { + grpc_server_credentials_release(creds->wrapped); + } + zend_object_std_dtor(&creds->std); +} + +/* Initializes an instace of wrapped_grpc_server_credentials to be associated + * with an object of a class specified by class_type */ +zend_object *create_wrapped_grpc_server_credentials(zend_class_entry + *class_type) { + wrapped_grpc_server_credentials *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_server_credentials) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &server_credentials_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_server_credentials(grpc_server_credentials *wrapped, + zval *server_credentials_object) { + object_init_ex(server_credentials_object, grpc_ce_server_credentials); + wrapped_grpc_server_credentials *server_credentials = + Z_WRAPPED_GRPC_SERVER_CREDS_P(server_credentials_object); + server_credentials->wrapped = wrapped; +} + +#endif + /** * Create SSL credentials. * @param string pem_root_certs PEM encoding of the server root certificates @@ -103,7 +144,11 @@ PHP_METHOD(ServerCredentials, createSsl) { char *pem_root_certs = 0; grpc_ssl_pem_key_cert_pair pem_key_cert_pair; +#if PHP_MAJOR_VERSION < 7 int root_certs_length = 0, private_key_length, cert_chain_length; +#else + size_t root_certs_length = 0, private_key_length, cert_chain_length; +#endif /* "s!ss" == 1 nullable string, 2 strings */ /* TODO: support multiple key cert pairs. */ @@ -120,17 +165,33 @@ PHP_METHOD(ServerCredentials, createSsl) { grpc_server_credentials *creds = grpc_ssl_server_credentials_create_ex( pem_root_certs, &pem_key_cert_pair, 1, GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE, NULL); +#if PHP_MAJOR_VERSION < 7 zval *creds_object = grpc_php_wrap_server_credentials(creds TSRMLS_CC); RETURN_DESTROY_ZVAL(creds_object); +#else + grpc_php_wrap_server_credentials(creds, return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } static zend_function_entry server_credentials_methods[] = { - PHP_ME(ServerCredentials, createSsl, NULL, - ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END}; + PHP_ME(ServerCredentials, createSsl, NULL, + ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_FE_END + }; void grpc_init_server_credentials(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\ServerCredentials", server_credentials_methods); ce.create_object = create_wrapped_grpc_server_credentials; grpc_ce_server_credentials = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&server_credentials_ce_handlers, + zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + server_credentials_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_server_credentials, std); + server_credentials_ce_handlers.free_obj = + free_wrapped_grpc_server_credentials; +#endif } diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h index 7101d65000..d37fafc0dc 100755 --- a/src/php/ext/grpc/server_credentials.h +++ b/src/php/ext/grpc/server_credentials.h @@ -49,14 +49,34 @@ /* Class entry for the Server_Credentials PHP class */ extern zend_class_entry *grpc_ce_server_credentials; +#if PHP_MAJOR_VERSION < 7 + /* Wrapper struct for grpc_server_credentials that can be associated with a PHP * object */ typedef struct wrapped_grpc_server_credentials { zend_object std; + grpc_server_credentials *wrapped; +} wrapped_grpc_server_credentials; +#else + +typedef struct wrapped_grpc_server_credentials { grpc_server_credentials *wrapped; + zend_object std; } wrapped_grpc_server_credentials; +static inline wrapped_grpc_server_credentials +*wrapped_grpc_server_creds_from_obj(zend_object *obj) { + return (wrapped_grpc_server_credentials*) + ((char*)(obj) - + XtOffsetOf(wrapped_grpc_server_credentials, std)); +} + +#define Z_WRAPPED_GRPC_SERVER_CREDS_P(zv) \ + wrapped_grpc_server_creds_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initializes the Server_Credentials PHP class */ void grpc_init_server_credentials(TSRMLS_D); diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c index 5e242162a8..8dc997c2dd 100644 --- a/src/php/ext/grpc/timeval.c +++ b/src/php/ext/grpc/timeval.c @@ -52,8 +52,14 @@ zend_class_entry *grpc_ce_timeval; +#if PHP_MAJOR_VERSION < 7 + /* Frees and destroys an instance of wrapped_grpc_call */ -void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { efree(object); } +void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { + wrapped_grpc_timeval *timeval = (wrapped_grpc_timeval *)object; + zend_object_std_dtor(&timeval->std TSRMLS_CC); + efree(timeval); +} /* Initializes an instance of wrapped_grpc_timeval to be associated with an * object of a class specified by class_type */ @@ -83,14 +89,50 @@ zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC) { return timeval_object; } +#else + +static zend_object_handlers timeval_ce_handlers; + +/* Frees and destroys an instance of wrapped_grpc_call */ +static void free_wrapped_grpc_timeval(zend_object *object) { + wrapped_grpc_timeval *timeval = wrapped_grpc_timeval_from_obj(object); + zend_object_std_dtor(&timeval->std); +} + +/* Initializes an instance of wrapped_grpc_timeval to be associated with an + * object of a class specified by class_type */ +zend_object *create_wrapped_grpc_timeval(zend_class_entry *class_type) { + wrapped_grpc_timeval *intern; + intern = ecalloc(1, sizeof(wrapped_grpc_timeval) + + zend_object_properties_size(class_type)); + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &timeval_ce_handlers; + return &intern->std; +} + +void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object) { + object_init_ex(timeval_object, grpc_ce_timeval); + wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(timeval_object); + memcpy(&timeval->wrapped, &wrapped, sizeof(gpr_timespec)); +} + +#endif + /** * Constructs a new instance of the Timeval class * @param long $usec The number of microseconds in the interval */ PHP_METHOD(Timeval, __construct) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *timeval = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); long microseconds; +#else + wrapped_grpc_timeval *timeval = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + zend_long microseconds; +#endif + /* "l" == 1 long */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", µseconds) == FAILURE) { @@ -110,6 +152,7 @@ PHP_METHOD(Timeval, __construct) { */ PHP_METHOD(Timeval, add) { zval *other_obj; + /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { @@ -117,13 +160,23 @@ PHP_METHOD(Timeval, add) { "add expects a Timeval", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *self = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); wrapped_grpc_timeval *other = (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); zval *sum = - grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) TSRMLS_CC); + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(sum); +#else + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + + grpc_php_wrap_timeval(gpr_time_add(self->wrapped, other->wrapped), + return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -134,6 +187,7 @@ PHP_METHOD(Timeval, add) { */ PHP_METHOD(Timeval, subtract) { zval *other_obj; + /* "O" == 1 Object */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &other_obj, grpc_ce_timeval) == FAILURE) { @@ -141,13 +195,22 @@ PHP_METHOD(Timeval, subtract) { "subtract expects a Timeval", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *self = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); wrapped_grpc_timeval *other = (wrapped_grpc_timeval *)zend_object_store_get_object(other_obj TSRMLS_CC); zval *diff = - grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) TSRMLS_CC); + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped) + TSRMLS_CC); RETURN_DESTROY_ZVAL(diff); +#else + wrapped_grpc_timeval *self = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); + wrapped_grpc_timeval *other = Z_WRAPPED_GRPC_TIMEVAL_P(other_obj); + grpc_php_wrap_timeval(gpr_time_sub(self->wrapped, other->wrapped), + return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -158,7 +221,9 @@ PHP_METHOD(Timeval, subtract) { * @return long */ PHP_METHOD(Timeval, compare) { - zval *a_obj, *b_obj; + zval *a_obj; + zval *b_obj; + /* "OO" == 2 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OO", &a_obj, grpc_ce_timeval, &b_obj, @@ -167,10 +232,15 @@ PHP_METHOD(Timeval, compare) { "compare expects two Timevals", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *a = (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); wrapped_grpc_timeval *b = (wrapped_grpc_timeval *)zend_object_store_get_object(b_obj TSRMLS_CC); +#else + wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); + wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); +#endif long result = gpr_time_cmp(a->wrapped, b->wrapped); RETURN_LONG(result); } @@ -183,7 +253,10 @@ PHP_METHOD(Timeval, compare) { * @return bool True if $a and $b are within $threshold, False otherwise */ PHP_METHOD(Timeval, similar) { - zval *a_obj, *b_obj, *thresh_obj; + zval *a_obj; + zval *b_obj; + zval *thresh_obj; + /* "OOO" == 3 Objects */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "OOO", &a_obj, grpc_ce_timeval, &b_obj, grpc_ce_timeval, @@ -192,6 +265,7 @@ PHP_METHOD(Timeval, similar) { "compare expects three Timevals", 1 TSRMLS_CC); return; } +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *a = (wrapped_grpc_timeval *)zend_object_store_get_object(a_obj TSRMLS_CC); wrapped_grpc_timeval *b = @@ -199,6 +273,11 @@ PHP_METHOD(Timeval, similar) { wrapped_grpc_timeval *thresh = (wrapped_grpc_timeval *)zend_object_store_get_object( thresh_obj TSRMLS_CC); +#else + wrapped_grpc_timeval *a = Z_WRAPPED_GRPC_TIMEVAL_P(a_obj); + wrapped_grpc_timeval *b = Z_WRAPPED_GRPC_TIMEVAL_P(b_obj); + wrapped_grpc_timeval *thresh = Z_WRAPPED_GRPC_TIMEVAL_P(thresh_obj); +#endif int result = gpr_time_similar(a->wrapped, b->wrapped, thresh->wrapped); RETURN_BOOL(result); } @@ -208,8 +287,13 @@ PHP_METHOD(Timeval, similar) { * @return Timeval The current time */ PHP_METHOD(Timeval, now) { +#if PHP_MAJOR_VERSION < 7 zval *now = grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(now); +#else + grpc_php_wrap_timeval(gpr_now(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -217,11 +301,18 @@ PHP_METHOD(Timeval, now) { * @return Timeval Zero length time interval */ PHP_METHOD(Timeval, zero) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_zero = grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_ZVAL(grpc_php_timeval_zero, false, /* Copy original before returning? */ true /* Destroy original before returning */); +#else + grpc_php_wrap_timeval(gpr_time_0(GPR_CLOCK_REALTIME), return_value); + RETURN_ZVAL(return_value, + false, /* Copy original before returning? */ + true /* Destroy original before returning */); +#endif } /** @@ -229,9 +320,14 @@ PHP_METHOD(Timeval, zero) { * @return Timeval Infinite future time value */ PHP_METHOD(Timeval, infFuture) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_inf_future = grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_future); +#else + grpc_php_wrap_timeval(gpr_inf_future(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -239,9 +335,14 @@ PHP_METHOD(Timeval, infFuture) { * @return Timeval Infinite past time value */ PHP_METHOD(Timeval, infPast) { +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_timeval_inf_past = grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME) TSRMLS_CC); RETURN_DESTROY_ZVAL(grpc_php_timeval_inf_past); +#else + grpc_php_wrap_timeval(gpr_inf_past(GPR_CLOCK_REALTIME), return_value); + RETURN_DESTROY_ZVAL(return_value); +#endif } /** @@ -249,28 +350,41 @@ PHP_METHOD(Timeval, infPast) { * @return void */ PHP_METHOD(Timeval, sleepUntil) { +#if PHP_MAJOR_VERSION < 7 wrapped_grpc_timeval *this = (wrapped_grpc_timeval *)zend_object_store_get_object(getThis() TSRMLS_CC); +#else + wrapped_grpc_timeval *this = Z_WRAPPED_GRPC_TIMEVAL_P(getThis()); +#endif gpr_sleep_until(this->wrapped); } static zend_function_entry timeval_methods[] = { - PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) - PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) - PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_FE_END}; + PHP_ME(Timeval, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) + PHP_ME(Timeval, add, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, compare, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, infFuture, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, infPast, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, now, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, similar, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(Timeval, sleepUntil, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, subtract, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Timeval, zero, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_FE_END +}; void grpc_init_timeval(TSRMLS_D) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Grpc\\Timeval", timeval_methods); ce.create_object = create_wrapped_grpc_timeval; grpc_ce_timeval = zend_register_internal_class(&ce TSRMLS_CC); +#if PHP_MAJOR_VERSION >= 7 + memcpy(&timeval_ce_handlers, zend_get_std_object_handlers(), + sizeof(zend_object_handlers)); + timeval_ce_handlers.offset = + XtOffsetOf(wrapped_grpc_timeval, std); + timeval_ce_handlers.free_obj = free_wrapped_grpc_timeval; +#endif } void grpc_shutdown_timeval(TSRMLS_D) {} diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h index 7456eb6d58..d4eb2facde 100755 --- a/src/php/ext/grpc/timeval.h +++ b/src/php/ext/grpc/timeval.h @@ -50,12 +50,31 @@ extern zend_class_entry *grpc_ce_timeval; /* Wrapper struct for timeval that can be associated with a PHP object */ +#if PHP_MAJOR_VERSION < 7 + typedef struct wrapped_grpc_timeval { zend_object std; + gpr_timespec wrapped; +} wrapped_grpc_timeval; +#else + +typedef struct wrapped_grpc_timeval { gpr_timespec wrapped; + zend_object std; } wrapped_grpc_timeval; +static inline wrapped_grpc_timeval +*wrapped_grpc_timeval_from_obj(zend_object *obj) { + return (wrapped_grpc_timeval*)((char*)(obj) - + XtOffsetOf(wrapped_grpc_timeval, std)); +} + +#define Z_WRAPPED_GRPC_TIMEVAL_P(zv) \ + wrapped_grpc_timeval_from_obj(Z_OBJ_P((zv))) + +#endif /* PHP_MAJOR_VERSION */ + /* Initialize the Timeval PHP class */ void grpc_init_timeval(TSRMLS_D); @@ -63,6 +82,10 @@ void grpc_init_timeval(TSRMLS_D); void grpc_shutdown_timeval(TSRMLS_D); /* Creates a Timeval object that wraps the given timeval struct */ +#if PHP_MAJOR_VERSION < 7 zval *grpc_php_wrap_timeval(gpr_timespec wrapped TSRMLS_DC); +#else +void grpc_php_wrap_timeval(gpr_timespec wrapped, zval *timeval_object); +#endif /* PHP_MAJOR_VERSION */ #endif /* NET_GRPC_PHP_GRPC_TIMEVAL_H_ */ diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php index df3fe85d44..2fec1bd9cc 100755..100644 --- a/src/php/lib/Grpc/BaseStub.php +++ b/src/php/lib/Grpc/BaseStub.php @@ -84,8 +84,8 @@ class BaseStub } if ($channel) { if (!is_a($channel, 'Channel')) { - throw new \Exception("The channel argument is not a". - "Channel object"); + throw new \Exception('The channel argument is not a'. + 'Channel object'); } $this->channel = $channel; } else { diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php index 95e51c5088..c2fdb94b86 100644 --- a/src/php/lib/Grpc/BidiStreamingCall.php +++ b/src/php/lib/Grpc/BidiStreamingCall.php @@ -113,6 +113,7 @@ class BidiStreamingCall extends AbstractCall ]); $this->trailing_metadata = $status_event->status->metadata; + return $status_event->status; } } diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php index 315a406735..4050f7ed06 100644 --- a/src/php/lib/Grpc/ClientStreamingCall.php +++ b/src/php/lib/Grpc/ClientStreamingCall.php @@ -88,6 +88,7 @@ class ClientStreamingCall extends AbstractCall $status = $event->status; $this->trailing_metadata = $status->metadata; + return [$this->deserializeResponse($event->message), $status]; } } diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php index 53599fe4ae..ba89d9f972 100644 --- a/src/php/lib/Grpc/ServerStreamingCall.php +++ b/src/php/lib/Grpc/ServerStreamingCall.php @@ -92,6 +92,7 @@ class ServerStreamingCall extends AbstractCall ]); $this->trailing_metadata = $status_event->status->metadata; + return $status_event->status; } } diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php index b114b771b8..a71b05dc93 100644 --- a/src/php/lib/Grpc/UnaryCall.php +++ b/src/php/lib/Grpc/UnaryCall.php @@ -77,6 +77,7 @@ class UnaryCall extends AbstractCall $status = $event->status; $this->trailing_metadata = $status->metadata; + return [$this->deserializeResponse($event->message), $status]; } } diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 43b3199d92..bf40549a04 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -450,7 +450,7 @@ function statusCodeAndMessage($stub) { $echo_status = new grpc\testing\EchoStatus(); $echo_status->setCode(2); - $echo_status->setMessage("test status message"); + $echo_status->setMessage('test status message'); $request = new grpc\testing\SimpleRequest(); $request->setResponseStatus($echo_status); @@ -460,7 +460,7 @@ function statusCodeAndMessage($stub) hardAssert($status->code === 2, 'Received unexpected status code'); - hardAssert($status->details === "test status message", + hardAssert($status->details === 'test status message', 'Received unexpected status details'); $streaming_call = $stub->FullDuplexCall(); @@ -473,7 +473,7 @@ function statusCodeAndMessage($stub) $status = $streaming_call->getStatus(); hardAssert($status->code === 2, 'Received unexpected status code'); - hardAssert($status->details === "test status message", + hardAssert($status->details === 'test status message', 'Received unexpected status details'); } @@ -570,9 +570,9 @@ function _makeStub($args) } if ($test_case == 'unimplemented_method') { - $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts); + $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts); } else { - $stub = new grpc\testing\TestServiceClient($server_address, $opts); + $stub = new grpc\testing\TestServiceClient($server_address, $opts); } return $stub; diff --git a/src/php/tests/unit_tests/CallCredentialsTest.php b/src/php/tests/unit_tests/CallCredentialsTest.php index 5fec06cd13..1994c8afe5 100644 --- a/src/php/tests/unit_tests/CallCredentialsTest.php +++ b/src/php/tests/unit_tests/CallCredentialsTest.php @@ -148,7 +148,8 @@ class CallCredentialsTest extends PHPUnit_Framework_TestCase $this->call_credentials, $call_credentials2 ); - $this->assertSame('Grpc\CallCredentials', get_class($call_credentials3)); + $this->assertSame('Grpc\CallCredentials', + get_class($call_credentials3)); } /** diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php index fa026f0935..d736f51546 100755..100644 --- a/src/php/tests/unit_tests/CallTest.php +++ b/src/php/tests/unit_tests/CallTest.php @@ -50,6 +50,18 @@ class CallTest extends PHPUnit_Framework_TestCase Grpc\Timeval::infFuture()); } + public function tearDown() + { + unset($this->call); + unset($this->channel); + } + + public function testConstructor() + { + $this->assertSame('Grpc\Call', get_class($this->call)); + $this->assertObjectHasAttribute('channel', $this->call); + } + public function testAddEmptyMetadata() { $batch = [ @@ -81,7 +93,8 @@ class CallTest extends PHPUnit_Framework_TestCase { $batch = [ Grpc\OP_SEND_INITIAL_METADATA => ['key1' => ['value1'], - 'key2' => ['value2', 'value3'], ], + 'key2' => ['value2', + 'value3'], ], ]; $result = $this->call->startBatch($batch); $this->assertTrue($result->send_metadata); @@ -118,4 +131,38 @@ class CallTest extends PHPUnit_Framework_TestCase ]; $result = $this->call->startBatch($batch); } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstuctor() + { + $this->call = new Grpc\Call(); + $this->assertNull($this->call); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstuctor2() + { + $this->call = new Grpc\Call('hi', 'hi', 'hi'); + $this->assertNull($this->call); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidSetCredentials() + { + $this->call->setCredentials('hi'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidSetCredentials2() + { + $this->call->setCredentials([]); + } } diff --git a/src/php/tests/unit_tests/ChannelCredentialsTest.php b/src/php/tests/unit_tests/ChannelCredentialsTest.php index 56c1d8f006..e822929ccd 100644 --- a/src/php/tests/unit_tests/ChannelCredentialsTest.php +++ b/src/php/tests/unit_tests/ChannelCredentialsTest.php @@ -42,10 +42,23 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase { } - public function testCreateDefault() + public function testCreateSslWith3Null() { - $channel_credentials = Grpc\ChannelCredentials::createDefault(); - $this->assertSame('Grpc\ChannelCredentials', get_class($channel_credentials)); + $channel_credentials = Grpc\ChannelCredentials::createSsl(null, null, + null); + $this->assertNotNull($channel_credentials); + } + + public function testCreateSslWith3NullString() + { + $channel_credentials = Grpc\ChannelCredentials::createSsl('', '', ''); + $this->assertNotNull($channel_credentials); + } + + public function testCreateInsecure() + { + $channel_credentials = Grpc\ChannelCredentials::createInsecure(); + $this->assertNull($channel_credentials); } /** @@ -64,10 +77,4 @@ class ChanellCredentialsTest extends PHPUnit_Framework_TestCase $channel_credentials = Grpc\ChannelCredentials::createComposite( 'something', 'something'); } - - public function testCreateInsecure() - { - $channel_credentials = Grpc\ChannelCredentials::createInsecure(); - $this->assertNull($channel_credentials); - } } diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php index a1f9053c39..4b35b1a28c 100644 --- a/src/php/tests/unit_tests/ChannelTest.php +++ b/src/php/tests/unit_tests/ChannelTest.php @@ -40,6 +40,7 @@ class ChannelTest extends PHPUnit_Framework_TestCase public function tearDown() { + unset($this->channel); } public function testInsecureCredentials() @@ -53,6 +54,82 @@ class ChannelTest extends PHPUnit_Framework_TestCase $this->assertSame('Grpc\Channel', get_class($this->channel)); } + public function testGetConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithInt() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(123); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithString() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState('hello'); + $this->assertEquals(0, $state); + } + + public function testGetConnectivityStateWithBool() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $state = $this->channel->getConnectivityState(true); + $this->assertEquals(0, $state); + } + + public function testGetTarget() + { + $this->channel = new Grpc\Channel('localhost:8888', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $target = $this->channel->getTarget(); + $this->assertTrue(is_string($target)); + } + + public function testWatchConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $time = new Grpc\Timeval(1000); + $state = $this->channel->watchConnectivityState(123, $time); + $this->assertTrue($state); + unset($time); + } + + public function testClose() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->assertNotNull($this->channel); + $this->channel->close(); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstructorWithNull() + { + $this->channel = new Grpc\Channel(); + $this->assertNull($this->channel); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidConstructorWith() + { + $this->channel = new Grpc\Channel('localhost', 'invalid'); + $this->assertNull($this->channel); + } + /** * @expectedException InvalidArgumentException */ @@ -78,4 +155,34 @@ class ChannelTest extends PHPUnit_Framework_TestCase ] ); } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidGetConnectivityStateWithArray() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->getConnectivityState([]); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidWatchConnectivityState() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->watchConnectivityState([]); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidWatchConnectivityState2() + { + $this->channel = new Grpc\Channel('localhost:0', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + $this->channel->watchConnectivityState(1, 'hi'); + } } diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php index 2b09f9d112..09364580c0 100755..100644 --- a/src/php/tests/unit_tests/EndToEndTest.php +++ b/src/php/tests/unit_tests/EndToEndTest.php @@ -521,7 +521,8 @@ class EndToEndTest extends PHPUnit_Framework_TestCase public function testGetConnectivityState() { - $this->assertTrue($this->channel->getConnectivityState() == Grpc\CHANNEL_IDLE); + $this->assertTrue($this->channel->getConnectivityState() == + Grpc\CHANNEL_IDLE); } public function testWatchConnectivityStateFailed() diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index c388ee5031..c388ee5031 100755..100644 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php index 76aaa06970..f2346ab113 100644 --- a/src/php/tests/unit_tests/ServerTest.php +++ b/src/php/tests/unit_tests/ServerTest.php @@ -36,10 +36,70 @@ class ServerTest extends PHPUnit_Framework_TestCase { public function setUp() { + $this->server = null; } public function tearDown() { + unset($this->server); + } + + public function testConstructorWithNull() + { + $this->server = new Grpc\Server(); + $this->assertNotNull($this->server); + } + + public function testConstructorWithNullArray() + { + $this->server = new Grpc\Server([]); + $this->assertNotNull($this->server); + } + + public function testConstructorWithArray() + { + // key of array must be string + $this->server = new Grpc\Server(['ip' => '127.0.0.1', + 'port' => '8080', ]); + $this->assertNotNull($this->server); + } + + public function testRequestCall() + { + $this->server = new Grpc\Server(); + $port = $this->server->addHttp2Port('0.0.0.0:8888'); + $this->server->start(); + $channel = new Grpc\Channel('localhost:8888', + ['credentials' => Grpc\ChannelCredentials::createInsecure()]); + + $deadline = Grpc\Timeval::infFuture(); + $call = new Grpc\Call($channel, 'dummy_method', $deadline); + + $event = $call->startBatch([Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, + ]); + + $c = $this->server->requestCall(); + $this->assertObjectHasAttribute('call', $c); + $this->assertObjectHasAttribute('method', $c); + $this->assertSame('dummy_method', $c->method); + $this->assertObjectHasAttribute('host', $c); + $this->assertTrue(is_string($c->host)); + $this->assertObjectHasAttribute('absolute_deadline', $c); + $this->assertObjectHasAttribute('metadata', $c); + + unset($call); + unset($channel); + } + + private function createSslObj() + { + $server_credentials = Grpc\ServerCredentials::createSsl( + null, + file_get_contents(dirname(__FILE__).'/../data/server1.key'), + file_get_contents(dirname(__FILE__).'/../data/server1.pem')); + + return $server_credentials; } /** @@ -47,7 +107,8 @@ class ServerTest extends PHPUnit_Framework_TestCase */ public function testInvalidConstructor() { - $server = new Grpc\Server('invalid_host'); + $this->server = new Grpc\Server('invalid_host'); + $this->assertNull($this->server); } /** @@ -56,7 +117,7 @@ class ServerTest extends PHPUnit_Framework_TestCase public function testInvalidAddHttp2Port() { $this->server = new Grpc\Server([]); - $this->port = $this->server->addHttp2Port(['0.0.0.0:0']); + $port = $this->server->addHttp2Port(['0.0.0.0:0']); } /** @@ -65,6 +126,24 @@ class ServerTest extends PHPUnit_Framework_TestCase public function testInvalidAddSecureHttp2Port() { $this->server = new Grpc\Server([]); - $this->port = $this->server->addSecureHttp2Port(['0.0.0.0:0']); + $port = $this->server->addSecureHttp2Port(['0.0.0.0:0']); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidAddSecureHttp2Port2() + { + $this->server = new Grpc\Server(); + $port = $this->server->addSecureHttp2Port('0.0.0.0:0'); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testInvalidAddSecureHttp2Port3() + { + $this->server = new Grpc\Server(); + $port = $this->server->addSecureHttp2Port('0.0.0.0:0', 'invalid'); } } diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php index a3dbce079f..2d19f64c79 100755..100644 --- a/src/php/tests/unit_tests/TimevalTest.php +++ b/src/php/tests/unit_tests/TimevalTest.php @@ -33,6 +33,57 @@ */ class TimevalTest extends PHPUnit_Framework_TestCase { + public function setUp() + { + } + + public function tearDown() + { + unset($this->time); + } + + public function testConstructorWithInt() + { + $this->time = new Grpc\Timeval(1234); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithNegative() + { + $this->time = new Grpc\Timeval(-123); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithZero() + { + $this->time = new Grpc\Timeval(0); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithOct() + { + $this->time = new Grpc\Timeval(0123); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithHex() + { + $this->time = new Grpc\Timeval(0x1A); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + + public function testConstructorWithFloat() + { + $this->time = new Grpc\Timeval(123.456); + $this->assertNotNull($this->time); + $this->assertSame('Grpc\Timeval', get_class($this->time)); + } + public function testCompareSame() { $zero = Grpc\Timeval::zero(); @@ -70,6 +121,7 @@ class TimevalTest extends PHPUnit_Framework_TestCase public function testNowAndAdd() { $now = Grpc\Timeval::now(); + $this->assertNotNull($now); $delta = new Grpc\Timeval(1000); $deadline = $now->add($delta); $this->assertGreaterThan(0, Grpc\Timeval::compare($deadline, $now)); @@ -154,5 +206,6 @@ class TimevalTest extends PHPUnit_Framework_TestCase public function testSimilarInvalidParam() { $a = Grpc\Timeval::similar(1000, 1100, 1200); + $this->assertNull($delta); } } |