/* * Copy argument */ static int md_command_cparg(AXP *axp, uint32_t pm_type, int tag, const char *buf, size_t len, tr_ctx_t *tr_ctx) { struct md_command_args *arg = tr_ctx->arg; uint32_t mod_id; if (arg->already_running) { tr_ctx->result = 302; return 0; } switch (tag) { case ARMS_TAG_START_CPARG: break; case ARMS_TAG_END_CPARG: if (arg->mod_count < 1) { tr_ctx->result = 203;/*Parameter Problem*/ } break; case ARMS_TAG_MDCOMMAND: if (tr_ctx->read_done) break; arg->mod_count++; if (arg->mod_count > 1) { tr_ctx->result = 422;/*Multiple Request*/ return -1; } mod_id = get_module_id(axp, tag); arg->mod_id = mod_id; if (sizeof(arg->request) < len) { tr_ctx->result = 402;/*SA Failure*/ return -1; } if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) { /* decode base64 */ len = arms_base64_decode_stream(&arg->base64, arg->request, sizeof(arg->request), buf, len); } else { memcpy(arg->request, buf, len); } arg->req_len = len; break; default: break; } return 0; }
/* * Copy argument */ static int configure_cparg(AXP *axp, uint32_t pm_type, int tag, const char *buf, size_t len, tr_ctx_t *tr_ctx) { struct configure_args *arg = tr_ctx->arg; arms_context_t *res = arms_get_context(); uint32_t mod_id; const char *mod_ver = NULL; const char *mod_loc = NULL; arms_config_cb_t config_cb; int flag, err; static int module_added = 0; if (tr_ctx->result == 302) return 0; if (arg->already_running) { tr_ctx->result = 302; return 0; } config_cb = res->callbacks.config_cb; switch (tag) { case ARMS_TAG_START_CPARG: module_added = 1; arg->first = 1; break; case ARMS_TAG_END_CPARG: /* call sync_module if <md-config> is not included. */ if (module_added) { configure_module_cb.udata = res; init_module_cb(&configure_module_cb); err = sync_module(); if (err < 0) { tr_ctx->result = 411;/*Commit failure*/ return -1; } module_added = 0; } break; case ARMS_TAG_MODULE: mod_id = get_module_id(axp, tag); mod_ver = get_module_ver(axp, tag); /* add module id to 'new' */ err = add_module(mod_id, mod_ver, buf); if (err < 0) { tr_ctx->result = 411;/*Commit failure*/ return -1; } break; case ARMS_TAG_MDCONF: if (module_added) { /* * move module id from 'new' to 'current' */ configure_module_cb.udata = res; init_module_cb(&configure_module_cb); err = sync_module(); if (err < 0) { tr_ctx->result = 411;/*Commit failure*/ return -1; } module_added = 0; } mod_id = get_module_id(axp, tag); if (!arms_module_is_exist(mod_id)) { /* * <md-config> found, but <module> not found. */ tr_ctx->result = 415;/*System Error*/ return -1; } mod_ver = lookup_module_ver(mod_id); mod_loc = lookup_module_location(mod_id); if (mod_loc == NULL) mod_loc = ""; if (config_cb == NULL) break; if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) { /* decode base64 */ len = arms_base64_decode_stream(&arg->base64, arg->request, sizeof(arg->request) - 1, buf, len); arg->request[len] = '\0'; buf = arg->request; } /* * buf, len is prepared. * if res->fragment == 0 and AXP_PARSE_CONTENT, * buffered part of config. */ if (res->fragment == 0) { arg->catbuf = REALLOC(arg->catbuf, arg->catlen + len); if (arg->catbuf == NULL) { /*Resource Exhausted*/ tr_ctx->result = 413; return -1; } memcpy(arg->catbuf + arg->catlen, buf, len); arg->catlen += len; if (tr_ctx->parse_state == AXP_PARSE_CONTENT) { /* wait for next data */ return 0; } /* AXP_PARSE_END */ buf = arg->catbuf; len = arg->catlen; } /* set fragment flag */ flag = 0; if (arg->first) { flag |= ARMS_FRAG_FIRST; arg->first = 0; } /* continued' config */ if (tr_ctx->parse_state == AXP_PARSE_CONTENT) { flag |= ARMS_FRAG_CONTINUE; } /* callback it */ do { int slen; /* call config callback */ if (res->fragment != 0 && len > res->fragment) { slen = res->fragment; } else { slen = len; /* if last fragment */ if (tr_ctx->parse_state == AXP_PARSE_END) { flag |= ARMS_FRAG_FINISHED; /* prepare for next md-config */ arg->first = 1; } } err = (*config_cb) (mod_id, mod_ver, mod_loc, ARMS_PUSH_STORE_CONFIG, buf, slen, flag, res->udata); if (err) { arg->errs++; tr_ctx->result = 410; return -1; } buf += slen; len -= slen; flag &= ~ARMS_FRAG_FIRST; flag |= ARMS_FRAG_CONTINUE; } while(len > 0); if (arg->catbuf != NULL) { /* reset for next module id */ FREE(arg->catbuf); arg->catbuf = NULL; arg->catlen = 0; } break; default: break; } return 0; }
/* AXP Extention handler */ static int store_tag(AXP *axp, int when, int type, int tag, const char *buf, size_t len, void *u) { /* * note: max size of encoded text via expat is 64kirobyte. * decoded binary size is 3/4 of encoded text. * + 2: module bytes */ static char decbuf[AXP_BUFSIZE * 3 / 4 + 2 + 1]; tr_ctx_t *tr_ctx = u; rspull_context_t *ctx = tr_ctx->arg; arms_context_t *res = arms_get_context(); uint32_t mod_id = 0; const char *mod_ver = NULL; const char *mod_loc = NULL; static int module_added = 0; arms_config_cb_t func; int flag, err = 0; /* Emergency stop requested */ if (tr_ctx->read_done) { return 0; } if ((func = res->callbacks.config_cb) == NULL) { return -1; } switch (tag) { case ARMS_TAG_MODULE: if (when != AXP_PARSE_END) return 0; /* chained to new module storage */ mod_id = get_module_id(axp, ARMS_TAG_MODULE); mod_ver = get_module_ver(axp, ARMS_TAG_MODULE); err = add_module(mod_id, mod_ver, (const char *)buf); if (err < 0) { tr_ctx->res_result = 415;/*System Error*/ tr_ctx->read_done = 1; err = 0; /* not parser err */ break; } module_added = 1; break; case ARMS_TAG_MDCONF: if (module_added) { /* module db: new -> current */ configure_module_cb.udata = res; init_module_cb(&configure_module_cb); err = sync_module(); if (err < 0) { tr_ctx->res_result = 415;/*System Error*/ tr_ctx->read_done = 1; break; } module_added = 0; } if (when == AXP_PARSE_START) { ctx->data.first_fragment = 1; return 0; } /* chained to md-config storage */ mod_id = get_module_id(axp, ARMS_TAG_MDCONF); if (!arms_module_is_exist(mod_id)) { /* * <md-config> found, but <module> not found. */ tr_ctx->res_result = 415;/*System Error*/ tr_ctx->read_done = 1; break; } mod_ver = lookup_module_ver(mod_id); mod_loc = lookup_module_location(mod_id); if (arms_get_encoding(axp, tag) == ARMS_DATA_BINARY) { int newlen; newlen = arms_base64_decode_stream(&ctx->base64, decbuf, sizeof(decbuf) - 1, buf, len); if (newlen < 0) { libarms_log(ARMS_LOG_EBASE64_DECODE, "base64 decode error " "srclen %d, dstlen %d", len, sizeof(decbuf) - 1); tr_ctx->res_result = 402;/*SA Failure*/ tr_ctx->read_done = 1; break; } len = newlen; decbuf[len] = '\0'; buf = decbuf; } /* * buf, len is prepared. * if res->fragment == 0 and AXP_PARSE_CONTENT, * buffered part of config. */ if (res->fragment == 0) { ctx->catbuf = REALLOC(ctx->catbuf, ctx->catlen + len); if (ctx->catbuf == NULL) { /*Resource Exhausted*/ tr_ctx->result = 413; return -1; } memcpy(ctx->catbuf + ctx->catlen, buf, len); ctx->catlen += len; if (when == AXP_PARSE_CONTENT) { /* wait for next data */ return 0; } /* AXP_PARSE_END */ buf = ctx->catbuf; len = ctx->catlen; } /* CONTENT or END */ flag = 0; if (ctx->data.first_fragment == 1) { flag |= ARMS_FRAG_FIRST; ctx->data.first_fragment = 0; } /* continued' config */ if (when == AXP_PARSE_CONTENT) { flag |= ARMS_FRAG_CONTINUE; } /* callback it */ do { int slen; /* call config callback */ if (res->fragment != 0 && len > res->fragment) { slen = res->fragment; } else { slen = len; /* if last fragment */ if (when == AXP_PARSE_END) flag |= ARMS_FRAG_FINISHED; } err = (*func)(mod_id, mod_ver, /* version */ mod_loc, /* infostring */ ARMS_PULL_STORE_CONFIG, buf, slen, flag, res->udata); if (err < 0) { res->trigger = "invalid config"; tr_ctx->res_result = 415;/*System Error*/ tr_ctx->read_done = 1; err = 0; /* not parser err */ break; } buf += slen; len -= slen; flag &= ~ARMS_FRAG_FIRST; flag |= ARMS_FRAG_CONTINUE; } while(len > 0); if (ctx->catbuf != NULL) { /* reset for next module id */ FREE(ctx->catbuf); ctx->catbuf = NULL; ctx->catlen = 0; } break; case ARMS_TAG_PUSH_ADDRESS: if (when != AXP_PARSE_END) return 0; if (ctx->pa_index < MAX_RS_INFO) { res->rs_push_address[ctx->pa_index++] = STRDUP(buf); } break; case ARMS_TAG_PULL_SERVER_URL: if (when != AXP_PARSE_END) return 0; if (ctx->pu_index < MAX_RS_INFO) { res->rs_pull_url[ctx->pu_index++] = STRDUP(buf); } break; case ARMS_TAG_MSG: if (when != AXP_PARSE_END) return 0; if (module_added) { /* care no <md-config> case. */ configure_module_cb.udata = res; init_module_cb(&configure_module_cb); err = sync_module(); if (err < 0) { tr_ctx->res_result = 415;/*System Error*/ tr_ctx->read_done = 1; break; } module_added = 0; } if (acmi_get_num_server(res->acmi, ACMI_CONFIG_CONFSOL) == ctx->pu_index) { res->rs_pull_1st = acmi_get_current_server(res->acmi, ACMI_CONFIG_CONFSOL); } else { res->rs_pull_1st = -1; } tr_ctx->read_done = 1; break; default: break; } return err; }