/** * @brief ht dmq callback */ int dlg_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* node) { int content_length; str body; dlg_cell_t *dlg; int unref = 0; int ret; srjson_doc_t jdoc, prof_jdoc; srjson_t *it = NULL; dlg_dmq_action_t action = DLG_DMQ_NONE; dlg_iuid_t iuid; str profiles = {0, 0}, callid = {0, 0}, tag1 = {0,0}, tag2 = {0,0}, contact1 = {0,0}, contact2 = {0,0}, k={0,0}, v={0,0}; str cseq1 = {0,0}, cseq2 = {0,0}, route_set1 = {0,0}, route_set2 = {0,0}, from_uri = {0,0}, to_uri = {0,0}, req_uri = {0,0}; unsigned int init_ts = 0, start_ts = 0, lifetime = 0; unsigned int state = 1; srjson_t *vj; /* received dmq message */ LM_DBG("dmq message received\n"); if(!msg->content_length) { LM_ERR("no content length header found\n"); goto invalid2; } content_length = get_content_length(msg); if(!content_length) { LM_DBG("content length is 0\n"); goto invalid2; } body.s = get_body(msg); body.len = content_length; if (!body.s) { LM_ERR("unable to get body\n"); goto error; } /* parse body */ LM_DBG("body: %.*s\n", body.len, body.s); srjson_InitDoc(&jdoc, NULL); jdoc.buf = body; if(jdoc.root == NULL) { jdoc.root = srjson_Parse(&jdoc, jdoc.buf.s); if(jdoc.root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc.buf.s); goto invalid; } } for(it=jdoc.root->child; it; it = it->next) { if ((it->string == NULL) || (strcmp(it->string, "vars")==0)) continue; LM_DBG("found field: %s\n", it->string); if (strcmp(it->string, "action")==0) { action = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "h_entry")==0) { iuid.h_entry = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "h_id")==0) { iuid.h_id = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "init_ts")==0) { init_ts = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "start_ts")==0) { start_ts = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "state")==0) { state = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "lifetime")==0) { lifetime = SRJSON_GET_UINT(it); } else if (strcmp(it->string, "callid")==0) { callid.s = it->valuestring; callid.len = strlen(callid.s); } else if (strcmp(it->string, "profiles")==0) { profiles.s = it->valuestring; profiles.len = strlen(profiles.s); } else if (strcmp(it->string, "tag1")==0) { tag1.s = it->valuestring; tag1.len = strlen(tag1.s); } else if (strcmp(it->string, "tag2")==0) { tag2.s = it->valuestring; tag2.len = strlen(tag2.s); } else if (strcmp(it->string, "cseq1")==0) { cseq1.s = it->valuestring; cseq1.len = strlen(cseq1.s); } else if (strcmp(it->string, "cseq2")==0) { cseq2.s = it->valuestring; cseq2.len = strlen(cseq2.s); } else if (strcmp(it->string, "route_set1")==0) { route_set1.s = it->valuestring; route_set1.len = strlen(route_set1.s); } else if (strcmp(it->string, "route_set2")==0) { route_set2.s = it->valuestring; route_set2.len = strlen(route_set2.s); } else if (strcmp(it->string, "contact1")==0) { contact1.s = it->valuestring; contact1.len = strlen(contact1.s); } else if (strcmp(it->string, "contact2")==0) { contact2.s = it->valuestring; contact2.len = strlen(contact2.s); } else if (strcmp(it->string, "from_uri")==0) { from_uri.s = it->valuestring; from_uri.len = strlen(from_uri.s); } else if (strcmp(it->string, "to_uri")==0) { to_uri.s = it->valuestring; to_uri.len = strlen(to_uri.s); } else if (strcmp(it->string, "req_uri")==0) { req_uri.s = it->valuestring; req_uri.len = strlen(req_uri.s); } else { LM_ERR("unrecognized field in json object\n"); } } dlg = dlg_get_by_iuid(&iuid); if (dlg) { LM_DBG("found dialog [%u:%u] at %p\n", iuid.h_entry, iuid.h_id, dlg); unref++; } switch(action) { case DLG_DMQ_UPDATE: LM_DBG("Updating dlg [%u:%u] with callid [%.*s]\n", iuid.h_entry, iuid.h_id, callid.len, callid.s); if (!dlg) { dlg = build_new_dlg(&callid, &from_uri, &to_uri, &tag1, &req_uri); if (!dlg) { LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != iuid.h_entry){ LM_ERR("inconsistent hash data from peer: " "make sure all Kamailio's use the same hash size\n"); shm_free(dlg); goto error; } /* link the dialog */ link_dlg(dlg, 0, 0); dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); /* override generated h_id */ dlg->h_id = iuid.h_id; /* prevent DB sync */ dlg->dflags &= ~(DLG_FLAG_NEW|DLG_FLAG_CHANGED); dlg->iflags |= DLG_IFLAG_DMQ_SYNC; } else { /* remove existing profiles */ if (dlg->profile_links!=NULL) { destroy_linkers(dlg->profile_links); dlg->profile_links = NULL; } } dlg->init_ts = init_ts; dlg->start_ts = start_ts; vj = srjson_GetObjectItem(&jdoc, jdoc.root, "vars"); if(vj!=NULL) { for(it=vj->child; it; it = it->next) { k.s = it->string; k.len = strlen(k.s); v.s = it->valuestring; v.len = strlen(v.s); set_dlg_variable(dlg, &k, &v); } } /* add profiles */ if(profiles.s!=NULL) { srjson_InitDoc(&prof_jdoc, NULL); prof_jdoc.buf = profiles; dlg_json_to_profiles(dlg, &prof_jdoc); srjson_DestroyDoc(&prof_jdoc); } if (state == dlg->state) { break; } /* intentional fallthrough */ case DLG_DMQ_STATE: if (!dlg) { LM_ERR("dialog [%u:%u] not found\n", iuid.h_entry, iuid.h_id); goto error; } if (state < dlg->state) { LM_NOTICE("Ignoring backwards state change on dlg [%u:%u]" " with callid [%.*s] from state [%u] to state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state, state); break; } LM_DBG("State update dlg [%u:%u] with callid [%.*s] from state [%u]" " to state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state, state); switch (state) { case DLG_STATE_EARLY: dlg->start_ts = start_ts; dlg->lifetime = lifetime; dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); break; case DLG_STATE_CONFIRMED: dlg->start_ts = start_ts; dlg->lifetime = lifetime; dlg_set_leg_info(dlg, &tag1, &route_set1, &contact1, &cseq1, 0); dlg_set_leg_info(dlg, &tag2, &route_set2, &contact2, &cseq2, 1); if (insert_dlg_timer( &dlg->tl, dlg->lifetime ) != 0) { LM_CRIT("Unable to insert dlg timer %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } else { /* dialog pointer inserted in timer list */ dlg_ref(dlg, 1); } break; case DLG_STATE_DELETED: if (dlg->state == DLG_STATE_CONFIRMED) { ret = remove_dialog_timer(&dlg->tl); if (ret == 0) { /* one extra unref due to removal from timer list */ unref++; } else if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } } /* prevent DB sync */ dlg->dflags |= DLG_FLAG_NEW; /* keep dialog around for a bit, to prevent out-of-order * syncs to reestablish the dlg */ dlg->init_ts = time(NULL); break; default: LM_ERR("unhandled state update to state %u\n", state); dlg_unref(dlg, unref); goto error; } dlg->state = state; break; case DLG_DMQ_RM: if (!dlg) { LM_DBG("dialog [%u:%u] not found\n", iuid.h_entry, iuid.h_id); goto error; } LM_DBG("Removed dlg [%u:%u] with callid [%.*s] int state [%u]\n", iuid.h_entry, iuid.h_id, dlg->callid.len, dlg->callid.s, dlg->state); if (dlg->state==DLG_STATE_CONFIRMED || dlg->state==DLG_STATE_EARLY) { ret = remove_dialog_timer(&dlg->tl); if (ret == 0) { /* one extra unref due to removal from timer list */ unref++; } else if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u]\n", dlg, dlg->h_entry, dlg->h_id); } } /* prevent DB sync */ dlg->dflags |= DLG_FLAG_NEW; unref++; break; case DLG_DMQ_SYNC: dmq_send_all_dlgs(0); break; case DLG_DMQ_NONE: break; } if (dlg && unref) dlg_unref(dlg, unref); srjson_DestroyDoc(&jdoc); resp->reason = dmq_200_rpl; resp->resp_code = 200; return 0; invalid: srjson_DestroyDoc(&jdoc); invalid2: resp->reason = dmq_400_rpl; resp->resp_code = 400; return 0; error: srjson_DestroyDoc(&jdoc); resp->reason = dmq_500_rpl; resp->resp_code = 500; return 0; }
int rtjson_prepare_branch(sip_msg_t *msg, srjson_doc_t *jdoc, srjson_t *nj) { srjson_t *rj = NULL; srjson_t *tj = NULL; srjson_t *vj = NULL; str xdsp = {0}; str xuri = {0}; str xhdr = {0}; unsigned int fr = 0; unsigned int fr_inv = 0; struct lump *anchor = NULL; char *s; if(tmb.set_fr!=NULL) { rj = srjson_GetObjectItem(jdoc, nj, "fr_timer"); if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) { fr = SRJSON_GET_UINT(rj); } rj = srjson_GetObjectItem(jdoc, nj, "fr_inv_timer"); if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) { fr_inv = SRJSON_GET_UINT(rj); } if(fr || fr_inv) tmb.set_fr(msg, fr_inv, fr); } rj = srjson_GetObjectItem(jdoc, nj, "headers"); if(rj==NULL || rj->type!=srjson_Object || rj->child==NULL) { LM_DBG("no header operations - done\n"); return 0; } tj = srjson_GetObjectItem(jdoc, rj, "extra"); if(tj!=NULL && tj->type==srjson_String && tj->valuestring!=0) { xhdr.s = tj->valuestring; xhdr.len = strlen(xhdr.s); } if(xhdr.len>4) { LM_DBG("appending extra headers: [%.*s]\n", xhdr.len, xhdr.s); anchor = anchor_lump(msg, msg->unparsed - msg->buf, 0, 0); if(anchor == 0) { LM_ERR("can't get anchor\n"); return -1; } s = pkg_malloc(xhdr.len+1); if(s==NULL) { LM_ERR("no more pkg\n"); return -1; } strncpy(s, xhdr.s, xhdr.len); s[xhdr.len] = '\0'; if (insert_new_lump_before(anchor, s, xhdr.len, 0) == 0) { LM_ERR("can't insert lump\n"); pkg_free(s); return -1; } } if(uacb.replace_from!=NULL) { tj = srjson_GetObjectItem(jdoc, rj, "from"); if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) { vj = srjson_GetObjectItem(jdoc, tj, "display"); if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) { xdsp.s = vj->valuestring; xdsp.len = strlen(xdsp.s); } vj = srjson_GetObjectItem(jdoc, tj, "uri"); if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) { xuri.s = vj->valuestring; xuri.len = strlen(xuri.s); } if(xdsp.len>0 || xuri.len>0) { uacb.replace_from(msg, &xdsp, &xuri); } } } if(uacb.replace_to!=NULL) { tj = srjson_GetObjectItem(jdoc, rj, "to"); if(tj!=NULL && tj->type==srjson_Object && rj->child!=NULL) { vj = srjson_GetObjectItem(jdoc, tj, "display"); if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) { xdsp.s = vj->valuestring; xdsp.len = strlen(xdsp.s); } vj = srjson_GetObjectItem(jdoc, tj, "uri"); if(vj!=NULL && vj->type==srjson_String && vj->valuestring!=0) { xuri.s = vj->valuestring; xuri.len = strlen(xuri.s); } if(xdsp.len>0 || xuri.len>0) { uacb.replace_to(msg, &xdsp, &xuri); } } } return 0; }
/** * json de-serialization of dialog profiles */ int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc) { srjson_t *aj = NULL; srjson_t *it = NULL; srjson_t *jt = NULL; dlg_profile_table_t *profile; str name; str val; str puid; time_t expires; int flags; if(dlg==NULL || jdoc==NULL || jdoc->buf.s==NULL) return -1; if(jdoc->root == NULL) { jdoc->root = srjson_Parse(jdoc, jdoc->buf.s); if(jdoc->root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc->buf.s); return -1; } } aj = srjson_GetObjectItem(jdoc, jdoc->root, "profiles"); if(aj!=NULL) { for(it=aj->child; it; it = it->next) { name.s = val.s = puid.s = NULL; expires = 0; flags = 0; for(jt = it->child; jt; jt = jt->next) { if(strcmp(jt->string, "name")==0) { name.s = jt->valuestring; name.len = strlen(name.s); } else if(strcmp(jt->string, "value")==0) { val.s = jt->valuestring; val.len = strlen(val.s); } else if(strcmp(jt->string, "puid")==0) { puid.s = jt->valuestring; puid.len = strlen(puid.s); } else if(strcmp(jt->string, "expires")==0) { expires = (time_t)SRJSON_GET_ULONG(jt); } else if(strcmp(jt->string, "flags")==0) { flags = SRJSON_GET_UINT(jt); } } if(name.s==NULL) continue; profile = search_dlg_profile(&name); if(profile==NULL) { LM_ERR("profile [%.*s] not found\n", name.len, name.s); continue; } if(val.s!=NULL) { if(profile->has_value) { if(dlg_add_profile(dlg, &val, profile, &puid, expires, flags) < 0) LM_ERR("dynamic profile cannot be added, ignore!\n"); else LM_DBG("dynamic profile added [%s : %s]\n", name.s, val.s); } } else { if(!profile->has_value) { if(dlg_add_profile(dlg, NULL, profile, &puid, expires, flags) < 0) LM_ERR("static profile cannot be added, ignore!\n"); else LM_DBG("static profile added [%s]\n", name.s); } } } } return 0; }
int rtjson_init_serial(sip_msg_t *msg, srjson_doc_t *jdoc, sr_xavp_t *iavp) { srjson_t *tj = NULL; srjson_t *nj = NULL; srjson_t *rj = NULL; str val; unsigned int bflags = 0; unsigned int old_bflags = 0; struct socket_info* fsocket = NULL; tj = srjson_GetObjectItem(jdoc, jdoc->root, "routes"); if(tj==NULL || tj->type!=srjson_Array || tj->child==NULL) { LM_ERR("missing or invalid routes field\n"); goto error; } nj = tj->child; clear_branches(); rj = srjson_GetObjectItem(jdoc, nj, "uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite r-uri to: [%.*s]\n", val.len, val.s); if (rewrite_uri(msg, &val) < 0) { LM_ERR("unable to rewrite Request-URI\n"); goto error; } } reset_dst_uri(msg); reset_path_vector(msg); reset_instance(msg); reset_ruid(msg); reset_ua(msg); reset_force_socket(msg); msg->reg_id = 0; set_ruri_q(0); rj = srjson_GetObjectItem(jdoc, nj, "dst_uri"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite dst-uri to: [%.*s]\n", val.len, val.s); if (set_dst_uri(msg, &val) < 0) { LM_ERR("unable to set destination uri\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "path"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("rewrite path to: [%.*s]\n", val.len, val.s); if (set_path_vector(msg, &val) < 0) { LM_ERR("unable to set path\n"); goto error; } } rj = srjson_GetObjectItem(jdoc, nj, "socket"); if(rj!=NULL && rj->type==srjson_String && rj->valuestring!=NULL) { val.s = rj->valuestring; val.len = strlen(val.s); LM_DBG("trying to set send socket to: [%.*s]\n", val.len, val.s); fsocket = lookup_local_socket(&val); if(fsocket) { set_force_socket(msg, fsocket); } } rj = srjson_GetObjectItem(jdoc, nj, "branch_flags"); if(rj!=NULL && rj->type==srjson_Number && SRJSON_GET_UINT(rj)!=0) { bflags = SRJSON_GET_UINT(rj); old_bflags = 0; getbflagsval(0, &old_bflags); setbflagsval(0, old_bflags|bflags); } iavp->val.v.i++; return 0; error: return -1; }