Example #1
0
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
    grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer,
    size_t send_buffer_len, grpc_metadata_array *initial_metadata) {
  /* TODO: don't use magic number */
  grpc_op ops[5];
  ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
                                initial_metadata);
  ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  ops[0].data.send_initial_metadata.metadata =
      ctx->send_initial_metadata.metadata;

  ops[1].op = GRPC_OP_SEND_MESSAGE;
  ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  ops[1].data.send_message = ctx->send_message;

  ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;

  ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
  ops[3].data.recv_initial_metadata = &(ctx->recv_initial_metadata);

  ops[4].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  ops[4].data.recv_status_on_client.trailing_metadata =
      &(ctx->recv_status_on_client.trailing_metadata);
  ops[4].data.recv_status_on_client.status =
      &(ctx->recv_status_on_client.status);
  /* not using preallocation for status_details */
  ops[4].data.recv_status_on_client.status_details =
      &(ctx->recv_status_on_client.status_details);
  ops[4].data.recv_status_on_client.status_details_capacity =
      &(ctx->recv_status_on_client.status_details_capacity);

  return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
}
Example #2
0
GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_send_message(grpc_call *call, grpcsharp_batch_context *ctx,
                            const char *send_buffer, size_t send_buffer_len) {
  /* TODO: don't use magic number */
  grpc_op ops[1];
  ops[0].op = GRPC_OP_SEND_MESSAGE;
  ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  ops[0].data.send_message = ctx->send_message;

  return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx);
}
Example #3
0
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
    grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
    size_t send_buffer_len, uint32_t write_flags,
    grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  /* TODO: don't use magic number */
  grpc_op ops[6];
  memset(ops, 0, sizeof(ops));
  ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
                                initial_metadata);
  ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  ops[0].data.send_initial_metadata.metadata =
      ctx->send_initial_metadata.metadata;
  ops[0].flags = initial_metadata_flags;
  ops[0].reserved = NULL;

  ops[1].op = GRPC_OP_SEND_MESSAGE;
  ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  ops[1].data.send_message.send_message = ctx->send_message;
  ops[1].flags = write_flags;
  ops[1].reserved = NULL;

  ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  ops[2].flags = 0;
  ops[2].reserved = NULL;

  ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
  ops[3].data.recv_initial_metadata.recv_initial_metadata =
      &(ctx->recv_initial_metadata);
  ops[3].flags = 0;
  ops[3].reserved = NULL;

  ops[4].op = GRPC_OP_RECV_MESSAGE;
  ops[4].data.recv_message.recv_message = &(ctx->recv_message);
  ops[4].flags = 0;
  ops[4].reserved = NULL;

  ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  ops[5].data.recv_status_on_client.trailing_metadata =
      &(ctx->recv_status_on_client.trailing_metadata);
  ops[5].data.recv_status_on_client.status =
      &(ctx->recv_status_on_client.status);
  ops[5].data.recv_status_on_client.status_details =
      &(ctx->recv_status_on_client.status_details);
  ops[5].flags = 0;
  ops[5].reserved = NULL;

  return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
                                    ctx, NULL);
}
Example #4
0
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
    grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
    size_t send_buffer_len, uint32_t write_flags,
    int32_t send_empty_initial_metadata) {
  /* TODO: don't use magic number */
  grpc_op ops[2];
  memset(ops, 0, sizeof(ops));
  size_t nops = send_empty_initial_metadata ? 2 : 1;
  ops[0].op = GRPC_OP_SEND_MESSAGE;
  ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  ops[0].data.send_message.send_message = ctx->send_message;
  ops[0].flags = write_flags;
  ops[0].reserved = NULL;
  ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
  ops[1].flags = 0;
  ops[1].reserved = NULL;

  return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
}
Example #5
0
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
    grpc_call* call, grpcsharp_batch_context* ctx, grpc_status_code status_code,
    const char* status_details, size_t status_details_len,
    grpc_metadata_array* trailing_metadata, int32_t send_empty_initial_metadata,
    const char* optional_send_buffer, size_t optional_send_buffer_len,
    uint32_t write_flags) {
  /* TODO: don't use magic number */
  grpc_op ops[3];
  memset(ops, 0, sizeof(ops));
  size_t nops = 1;
  grpc_slice status_details_slice =
      grpc_slice_from_copied_buffer(status_details, status_details_len);
  ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  ops[0].data.send_status_from_server.status = status_code;
  ops[0].data.send_status_from_server.status_details = &status_details_slice;
  grpcsharp_metadata_array_move(
      &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
  ops[0].data.send_status_from_server.trailing_metadata_count =
      ctx->send_status_from_server.trailing_metadata.count;
  ops[0].data.send_status_from_server.trailing_metadata =
      ctx->send_status_from_server.trailing_metadata.metadata;
  ops[0].flags = 0;
  ops[0].reserved = NULL;
  if (optional_send_buffer) {
    ops[nops].op = GRPC_OP_SEND_MESSAGE;
    ctx->send_message =
        string_to_byte_buffer(optional_send_buffer, optional_send_buffer_len);
    ops[nops].data.send_message.send_message = ctx->send_message;
    ops[nops].flags = write_flags;
    ops[nops].reserved = NULL;
    nops++;
  }
  if (send_empty_initial_metadata) {
    ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
    ops[nops].flags = 0;
    ops[nops].reserved = NULL;
    nops++;
  }
  grpc_call_error ret = grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
  grpc_slice_unref(status_details_slice);
  return ret;
}
Example #6
0
/**
 * Start a batch of RPC actions.
 * @param array batch Array of actions to take
 * @return object Object with results of all actions
 */
PHP_METHOD(Call, startBatch) {
  wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis());
  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;
  zend_string *key;
  zend_ulong index;
  
  grpc_metadata_array metadata;
  grpc_metadata_array trailing_metadata;
  grpc_metadata_array recv_metadata;
  grpc_metadata_array recv_trailing_metadata;
  grpc_status_code status;
  char *status_details = NULL;
  size_t status_details_capacity = 0;
  grpc_byte_buffer *message;
  int cancelled;
  grpc_call_error error;
  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);
  object_init(return_value);
  
  /* "a" == 1 array */
#ifndef FAST_ZPP
  if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
    zend_throw_exception(spl_ce_InvalidArgumentException,
                         "start_batch expects an array", 1);
    goto cleanup;
  }
#else
  ZEND_PARSE_PARAMETERS_START(1, 1)
    Z_PARAM_ARRAY(array)
  ZEND_PARSE_PARAMETERS_END();
#endif

  array_hash = HASH_OF(array);
  //TODO(thinkerou): why phpunit wrong when use ZEND_HASH_FOREACH_VAL marco?
  //ZEND_HASH_FOREACH_VAL(array_hash, value) {
  for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer);
       (value = zend_hash_get_current_data_ex(array_hash,
                                              &array_pointer)) != NULL;
       zend_hash_move_forward_ex(array_hash, &array_pointer)) {
    if (zend_hash_get_current_key_ex(array_hash, &key, &index,
                                     &array_pointer) != HASH_KEY_IS_LONG) {
      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;
          }
          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,
                                 "Status code must be an integer", 1);
            goto cleanup;
          }
          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,
                                 "Status details must be a string", 1);
            goto cleanup;
          }
          ops[op_num].data.send_status_from_server.status_details =
              Z_STRVAL_P(inner_value);
        } else {
          zend_throw_exception(spl_ce_InvalidArgumentException,
                               "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();

  error = grpc_call_start_batch(call->wrapped, ops, op_num,
                                call->wrapped, NULL);
  if (error != GRPC_CALL_OK) {
    zend_throw_exception(spl_ce_LogicException,
                         "start_batch was called incorrectly",
                         (long)error);
    goto cleanup;
  }
  grpc_completion_queue_pluck(completion_queue, call->wrapped,
                              gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
  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);
        //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(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);
        //Z_DELREF_P(array);
        add_property_long(&recv_status, "code", status);
        add_property_string(&recv_status, "details", status_details);
        add_property_zval(return_value, "status", &recv_status);
        //Z_DELREF_P(&recv_status);
        break;
      case GRPC_OP_RECV_CLOSE_ON_SERVER:
        add_property_bool(return_value, "cancelled", cancelled);
        break;
      default:
        break;
    }
  }

cleanup:
  grpc_metadata_array_destroy(&metadata);
  grpc_metadata_array_destroy(&trailing_metadata);
  grpc_metadata_array_destroy(&recv_metadata);
  grpc_metadata_array_destroy(&recv_trailing_metadata);
  if (status_details != NULL) {
    gpr_free(status_details);
  }
  for (int i = 0; i < op_num; i++) {
    if (ops[i].op == GRPC_OP_SEND_MESSAGE) {
      grpc_byte_buffer_destroy(ops[i].data.send_message);
    }
    if (ops[i].op == GRPC_OP_RECV_MESSAGE) {
      grpc_byte_buffer_destroy(message);
    }
  }
  RETURN_DESTROY_ZVAL(return_value);
}