/* 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; }
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; }
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; }
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 {