Пример #1
0
/* Extract a single optional/required or multiple repeated sub messages from native
   php types into the given protobuf message. Allocates memory for the created messages */
int
message_proto (const ProtobufCMessage* message, const ProtobufCFieldDescriptor* field, zval** val)
{
    if (Z_TYPE_PP(val) != IS_ARRAY)
        return 1;

    const void* member = get_member(message, field);
    unsigned int* quantifier = get_quantifier(message, field);
    ProtobufCMessageDescriptor* descriptor = (ProtobufCMessageDescriptor*)field->descriptor;

    if (field->label == PROTOBUF_C_LABEL_REQUIRED)
    {
        ProtobufCMessage* base = emalloc(descriptor->sizeof_message);
        protobuf_c_message_init(descriptor, base);
        php_message(base, val[0]);
        memcpy((void*)member, (void*)&base, sizeof(void*));
    }
    else if (field->label == PROTOBUF_C_LABEL_REPEATED)
    {
        HashPosition pos;
        HashTable* hash_table = Z_ARRVAL_PP(val);

        size_t* num_elements = emalloc(sizeof(size_t));
        num_elements[0] = (size_t)zend_hash_num_elements(hash_table);

        zval** data;
        char* key;
        int i, key_len, curr = 0;
        long index;
        
        void** values = emalloc(sizeof(void*) * *num_elements);

        zend_hash_internal_pointer_reset_ex(hash_table, &pos);
        for (;; zend_hash_move_forward_ex(hash_table, &pos)) {
            zend_hash_get_current_data_ex(hash_table, (void**)&data, &pos);

            i = zend_hash_get_current_key_ex(hash_table, &key, &key_len, &index, 0, &pos);
            if (i == HASH_KEY_NON_EXISTANT) {
                break;
            }

            void* curr_value = emalloc(descriptor->sizeof_message);
            protobuf_c_message_init(descriptor, curr_value);
            php_message((ProtobufCMessage*)curr_value, data[0]);
            values[curr] = curr_value;
            curr++;
        }

        memcpy((void*)member, (void*)&values, sizeof(void*));
        memcpy((void*)quantifier, (void*)num_elements, sizeof(void*));
    }

    return 0;
}
Пример #2
0
tz_return_t TZEExecuteProtobufFn(const ProtobufCMessageDescriptor *res_descr,
                                 tze_pb_execute_fn *exec,

                                 const ProtobufCMessage *req,
                                 ProtobufCMessage **res,
                                 tz_return_t *puiRv)
{
  tz_return_t err=0;

  if(res_descr && res) {
    *res = malloc(res_descr->sizeof_message);
    if(!*res) {
      err = TZ_ERROR_MEMORY;
      goto out;
    }
    protobuf_c_message_init(res_descr, *res);
  }

  if(res_descr) {
    *puiRv = exec(req, *res);
  } else {
    *puiRv = exec(req, NULL);
  }

  if (*puiRv && res) {
    /* Note that we interpret non-zero puiRv to mean there is no
       encodable result. In case the invoked function wants to return
       an error and additional information, puiRv should be 0, and the
       error + addtl info should be encoded in 'res' */
    free(*res);
    *res=NULL;
  }
  
 out:
  return err;
}
Пример #3
0
audited_err_t audited_start_cmd(const Audited__StartReq *startreq,
                                Audited__StartRes *startres)
{
  audited_err_t rv=0;
  ProtobufCMessage *req=NULL;
  audited_cmd_t *cmd_desc=NULL;
  char *audit_string=NULL;
  uint32_t pending_cmd_id;
  bool saved_pending_cmd=false;

  if(!did_init) {
    rv = AUDITED_EBADSTATE;
    goto out;
  }

  if (startreq->cmd >= audited_cmds_num) {
    rv = AUDITED_EBADAUDITEDCMD;
    goto out;
  }
  cmd_desc = &audited_cmds[startreq->cmd];
  assert(cmd_desc);

  req = protobuf_c_message_unpack(cmd_desc->req_descriptor,
                                  NULL,
                                  startreq->cmd_input.len,
                                  startreq->cmd_input.data);
  CHECK(req, AUDITED_EDECODE, "protobuf_c_message_unpack");

  assert(cmd_desc->audit_string);
  startres->svc_err = cmd_desc->audit_string(req,
                                             &audit_string);
  CHECK_RV((unsigned int)startres->svc_err, rv, "audit_string()");

  pending_cmd_id = audited_save_pending_cmd(cmd_desc, req, audit_string);
  CHECK(pending_cmd_id >= 0, AUDITED_ESAVE, "audited_save_pending_cmd");
  saved_pending_cmd=true;

  startres->res = malloc(sizeof(Audited__StartRes__Res));
  CHECK_MEM(startres->res, AUDITED_ENOMEM);

  *(startres->res) = (Audited__StartRes__Res)
    {
      .base = PROTOBUF_C_MESSAGE_INIT (&audited__start_res__res__descriptor),
      .pending_cmd_id = pending_cmd_id,
      .audit_nonce.data = pending_cmds[pending_cmd_id].audit_nonce,
      .audit_nonce.len = pending_cmds[pending_cmd_id].audit_nonce_len,
      .audit_string = audit_string,
    };

 out:
  if (rv || startres->svc_err) {
    if (saved_pending_cmd) {
      audited_release_pending_cmd_id(pending_cmd_id);
    } else {
      free(audit_string);
      if(req) {
        protobuf_c_message_free_unpacked(req, NULL);
      }
    }
    free(startres->res);
    startres->res=NULL;
  }
  return rv;
}

audited_err_t audited_execute_cmd(const Audited__ExecuteReq *exec_req,
                                  Audited__ExecuteRes *exec_res)
{
  audited_err_t rv;
  audited_pending_cmd_t *cmd=NULL;
  ProtobufCMessage *res=NULL;
  bool got_res=false;

  if(!did_init) {
    rv = AUDITED_EBADSTATE;
    goto out;
  }

  cmd = audited_pending_cmd_of_id(exec_req->pending_cmd_id);
  CHECK(cmd >= 0, AUDITED_EBADCMDHANDLE,
        "audited_pending_cmd_of_id(%d)", (unsigned int)exec_req->pending_cmd_id);

  rv = audited_check_cmd_auth(cmd,
                              exec_req->audit_token.data,
                              exec_req->audit_token.len);
  CHECK_RV(rv, rv, "audited_check_cmd_auth");

  assert(cmd->fns);
  assert(cmd->fns->execute);
  assert(cmd->fns->res_descriptor);

  res = malloc(cmd->fns->res_descriptor->sizeof_message);
  CHECK_MEM(res, AUDITED_ENOMEM);
  protobuf_c_message_init(cmd->fns->res_descriptor, res);

  exec_res->svc_err = cmd->fns->execute(cmd->req, res);
  CHECK_RV((unsigned int)exec_res->svc_err, rv, "execute()");
  got_res=true;

  exec_res->cmd_output.len = protobuf_c_message_get_packed_size(res);
  exec_res->cmd_output.data = malloc(exec_res->cmd_output.len);
  CHECK_MEM(exec_res->cmd_output.data, AUDITED_ENOMEM);
  protobuf_c_message_pack(res, exec_res->cmd_output.data);
  exec_res->has_cmd_output=true;

 out:
  if (got_res && cmd->fns->release_res) {
    cmd->fns->release_res(res);
  }
  if (res) {
    free(res);
    res=NULL;
  }
  audited_release_pending_cmd_id(exec_req->pending_cmd_id);
  return rv;
}
Пример #4
0
int keyspec_export_ebuf(rw_keyspec_instance_t* instance,
                        ProtobufCMessage* msg,
                        const char* m_rname,
                        const char* ts_fname,
                        const char* es_fname)
{
  RW_ASSERT(instance);

  /*
   * This is a kind of hack to export error records.
   * Assumptions about protobufc structure is made here.
   * Not worring as it is just a debug code. 
   */
  RW_ASSERT(msg);
  RW_ASSERT(m_rname);
  RW_ASSERT(ts_fname);
  RW_ASSERT(es_fname);

  const ProtobufCFieldDescriptor* mfdesc = 
      protobuf_c_message_descriptor_get_field_by_name(msg->descriptor, m_rname);
  
  if (!mfdesc) {
    return 0;
  }

  // Make sure to assert all the assumptions!
  RW_ASSERT(mfdesc->type == PROTOBUF_C_TYPE_MESSAGE);
  RW_ASSERT(mfdesc->label == PROTOBUF_C_LABEL_REPEATED);
  RW_ASSERT(!(mfdesc->rw_flags & RW_PROTOBUF_FOPT_INLINE));

  const ProtobufCFieldDescriptor* tsfdesc = 
      protobuf_c_message_descriptor_get_field_by_name(mfdesc->msg_desc, ts_fname);

  if (!tsfdesc) {
    return 0;
  }

  RW_ASSERT(tsfdesc->type == PROTOBUF_C_TYPE_STRING);
  RW_ASSERT(tsfdesc->label == PROTOBUF_C_LABEL_OPTIONAL);
  RW_ASSERT(tsfdesc->rw_flags & RW_PROTOBUF_FOPT_INLINE);

  const ProtobufCFieldDescriptor* esfdesc =
      protobuf_c_message_descriptor_get_field_by_name(mfdesc->msg_desc, es_fname);

  if (!esfdesc) {
    return 0;
  }

  RW_ASSERT(esfdesc->type == PROTOBUF_C_TYPE_STRING);
  RW_ASSERT(esfdesc->label == PROTOBUF_C_LABEL_OPTIONAL);
  RW_ASSERT(esfdesc->rw_flags & RW_PROTOBUF_FOPT_INLINE);

  // Make sure that the field is not allocated earlier.
  RW_ASSERT(!STRUCT_MEMBER(ProtobufCMessage**, msg, mfdesc->offset));
  RW_ASSERT(!STRUCT_MEMBER(uint32_t, msg, mfdesc->quantifier_offset));

  CircularErrorBuffer& errorbuf = CircularErrorBuffer::get_instance();

  ProtobufCMessage** records = (ProtobufCMessage **)protobuf_c_instance_alloc(
      instance->pbc_instance, errorbuf.get_capacity()*sizeof(void*));

  // Caution! dont call any function that may log error.
  time_t stime = time(NULL);
  unsigned tot_records = 0;

  /* 
   * Export the records in last-in-first out order so that the
   * recent errors are at the top.
   */
  size_t idx = errorbuf.get_last_index();
  size_t cap = errorbuf.get_capacity();

  for (size_t c = 0; c < cap; c++) {
    const ErrRecord* r = errorbuf[idx];
    if (!idx) { idx = (cap - 1); }
    else { idx--; }

    if (r->time <= stime && r->time ) {
      struct tm tm;
      localtime_r((const time_t*)(&r->time), &tm);

      ProtobufCMessage* record = (ProtobufCMessage *)protobuf_c_instance_alloc(
          instance->pbc_instance, mfdesc->msg_desc->sizeof_message);
      protobuf_c_message_init(mfdesc->msg_desc, record);

      char *tbuf = STRUCT_MEMBER_PTR(char, record, tsfdesc->offset);
      strftime(tbuf, tsfdesc->data_size, "%Y%m%d-%H%M%S", &tm);
      // Set the has field.
      STRUCT_MEMBER(uint32_t, record, tsfdesc->quantifier_offset) = 1;

      char *estr = STRUCT_MEMBER_PTR(char, record, esfdesc->offset);
      RW_ASSERT(esfdesc->data_size >= sizeof(r->errmsg));
      strncpy(estr, (const char*)r->errmsg, sizeof(r->errmsg)-1);
      estr[sizeof(r->errmsg)-1] = 0;
      // Set the has field.
      STRUCT_MEMBER(uint32_t, record, esfdesc->quantifier_offset) = 1;

      records[tot_records++] = record;
    }
  }

  if (tot_records) {
    STRUCT_MEMBER(ProtobufCMessage**, msg, mfdesc->offset) = records;
    STRUCT_MEMBER(uint32_t, msg, mfdesc->quantifier_offset) = tot_records;
  } else {