int arms_dump_state(arms_context_t *res, char *state, size_t size) { struct arms_dumped_state *newstate; MD5_CTX md5ctx; int i; /* check size */ if (size < arms_size_of_state()) return ARMS_ESIZE; newstate = CALLOC(1, sizeof(struct arms_dumped_state)); if (newstate == NULL) return ARMS_EFATAL; /* create new state array */ memset(newstate, 0, sizeof(*newstate)); newstate->state_version = ARMS_STATE_VERSION; DUMP(rs_endpoint); DUMP(rs_preshared_key); /* acmi (RS list) */ for (i = 0; i < 5; i++) { char *cert; acmi_get_url_idx(res->acmi, ACMI_CONFIG_CONFSOL, newstate->rsinfo[i].url, URL_MAX_LEN + 1, i); cert = acmi_get_cert_idx(res->acmi, ACMI_CONFIG_CONFSOL, i); if ((cert != NULL) && (strlen(cert) < sizeof(newstate->rsinfo[i].cert)) ) { strncpy(newstate->rsinfo[i].cert, cert, sizeof(newstate->rsinfo[i].cert)); } } newstate->current_server = acmi_get_current_server(res->acmi, ACMI_CONFIG_CONFSOL); newstate->retry_max = acmi_get_rmax(res->acmi, ACMI_CONFIG_CONFSOL); newstate->retry_int = acmi_get_rint(res->acmi, ACMI_CONFIG_CONFSOL); newstate->lltimeout = acmi_get_lltimeout(res->acmi, ACMI_CONFIG_CONFSOL); newstate->result = res->result; newstate->num_line = acmi_get_lines(res->acmi, ACMI_CONFIG_CONFSOL, newstate->line_defs); newstate->last_line = res->last_line; #if 0 /* compare with previus state array */ if (!memcmp(&newstate, state, sizeof(*newstate))) return ARMS_ENOCHANGE; #endif MD5_Init(&md5ctx); MD5_Update(&md5ctx, newstate, sizeof(*newstate) - sizeof(newstate->digest)); MD5_Final(newstate->digest, &md5ctx); /* copy new array to specified address */ memcpy(state, newstate, sizeof(*newstate)); FREE(newstate); 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; }