📄 lcr_mod.c
字号:
new_ruri.len = gw_uri_val.s.len + _m->parsed_uri.user.len + 1; new_ruri.s = pkg_malloc(new_ruri.len); if (!new_ruri.s) { LOG(L_ERR, "next_gw(): No memory for new R-URI.\n"); return -1; } at_char = memchr(gw_uri_val.s.s, '@', gw_uri_val.s.len); if (!at_char) { pkg_free(new_ruri.s); LOG(L_ERR, "next_gw(): No @ in gateway URI.\n"); return -1; } strip_char = memchr(gw_uri_val.s.s, '|', gw_uri_val.s.len); if (!strip_char || strip_char > at_char) { pkg_free(new_ruri.s); LOG(L_ERR, "next_gw(): No strip character | " "before @ in gateway URI.\n"); return -1; } at = new_ruri.s; memcpy(at, gw_uri_val.s.s, strip_char - gw_uri_val.s.s); sscanf(strip_char+1,"%d",&strip); at = at + (strip_char - gw_uri_val.s.s); if (_m->parsed_uri.user.len - strip > 0) { memcpy(at, _m->parsed_uri.user.s + strip, _m->parsed_uri.user.len - strip); at = at + _m->parsed_uri.user.len - strip; } if (*(at - 1) != ':') { memcpy(at, at_char, gw_uri_val.s.len - (at_char - gw_uri_val.s.s)); at = at + gw_uri_val.s.len - (at_char - gw_uri_val.s.s); } else { memcpy(at, at_char + 1, gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s)); at = at + gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s); } *at = '\0'; /* Save Request-URI user for use in FAILURE_ROUTE */ val.s = _m->parsed_uri.user; add_avp(ruri_user_avp_name_str|AVP_VAL_STR, ruri_user_name, val); DBG("load_gws(): DEBUG: Added ruri_user_avp <%.*s>\n", val.s.len, val.s.s); /* Rewrite Request URI */ act.type = SET_URI_T; act.p1_type = STRING_ST; act.p1.string = new_ruri.s; rval = do_action(&act, _m); pkg_free(new_ruri.s); destroy_avp(gw_uri_avp); if (rval != 1) { LOG(L_ERR, "next_gw(): ERROR: do_action failed with return " "value <%d>\n", rval); return -1; } return 1; } else if (route_type == FAILURE_ROUTE) { /* Create new Request-URI taking URI user from ruri_user AVP and other parts of from gateway URI AVP. */ ruri_user_avp = search_first_avp(ruri_user_avp_name_str, ruri_user_name, &ruri_user_val, 0); if (!ruri_user_avp) { LOG(L_ERR, "next_gw(): No ruri_user AVP\n"); return -1; } new_ruri.len = gw_uri_val.s.len + ruri_user_val.s.len + 1; new_ruri.s = pkg_malloc(new_ruri.len); if (!new_ruri.s) { LOG(L_ERR, "next_gw(): No memory for new R-URI.\n"); return -1; } at_char = memchr(gw_uri_val.s.s, '@', gw_uri_val.s.len); if (!at_char) { pkg_free(new_ruri.s); LOG(L_ERR, "next_gw(): No @ in gateway URI.\n"); return -1; } strip_char = memchr(gw_uri_val.s.s, '|', gw_uri_val.s.len); if (!strip_char || strip_char > at_char) { pkg_free(new_ruri.s); LOG(L_ERR, "next_gw(): No strip character | " "before @ in gateway URI.\n"); return -1; } at = new_ruri.s; memcpy(at, gw_uri_val.s.s, strip_char - gw_uri_val.s.s); sscanf(strip_char+1,"%d",&strip); at = at + (strip_char - gw_uri_val.s.s); if (ruri_user_val.s.len - strip > 0) { memcpy(at, ruri_user_val.s.s + strip, ruri_user_val.s.len - strip); at = at + ruri_user_val.s.len - strip; } if (*(at - 1) != ':') { memcpy(at, at_char, gw_uri_val.s.len - (at_char - gw_uri_val.s.s)); at = at + gw_uri_val.s.len - (at_char - gw_uri_val.s.s); } else { memcpy(at, at_char + 1, gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s)); at = at + gw_uri_val.s.len - (at_char + 1 - gw_uri_val.s.s); } *at = '\0'; act.type = APPEND_BRANCH_T; act.p1_type = STRING_ST; act.p1.string = new_ruri.s; act.p2_type = NUMBER_ST; act.p2.number = 0; rval = do_action(&act, _m); pkg_free(new_ruri.s); destroy_avp(gw_uri_avp); if (rval != 1) { LOG(L_ERR, "next_gw(): ERROR: do_action failed with return " "value <%d>\n", rval); return -1; } return 1; } /* unsupported route type */ return -1;}/* * Checks if request comes from a gateway */static int do_from_gw(struct sip_msg* _m, int grp_id){ int i; unsigned int src_addr; src_addr = _m->rcv.src_ip.u.addr32[0]; for (i = 0; i < MAX_NO_OF_GWS; i++) { if ((*gws)[i].ip_addr == 0) { return -1; } if ((*gws)[i].ip_addr == src_addr && (grp_id < 0 || (*gws)[i].grp_id == grp_id)) { return 1; } } return -1;}/* * Checks if request comes from a gateway, taking * into account the group id. */int from_gw_grp(struct sip_msg* _m, char* _s1, char* _s2){ int grp_id; grp_id = (int)(long)_s1; return do_from_gw(_m, grp_id);}/* * Checks if request comes from a gateway, ignoring * the group id. */int from_gw(struct sip_msg* _m, char* _s1, char* _s2){ return do_from_gw(_m, -1);}/* * Checks if in-dialog request goes to gateway */static int do_to_gw(struct sip_msg* _m, int grp_id){ char host[16]; struct in_addr addr; unsigned int i; if((_m->parsed_uri_ok == 0) && (parse_sip_msg_uri(_m) < 0)) { LOG(L_ERR, "LCR: to_gw: ERROR while parsing the R-URI\n"); return -1; } if (_m->parsed_uri.host.len > 15) { return -1; } memcpy(host, _m->parsed_uri.host.s, _m->parsed_uri.host.len); host[_m->parsed_uri.host.len] = 0; if (!inet_aton(host, &addr)) { return -1; } for (i = 0; i < MAX_NO_OF_GWS; i++) { if ((*gws)[i].ip_addr == 0) { return -1; } if ((*gws)[i].ip_addr == addr.s_addr && (grp_id < 0 || (*gws)[i].grp_id == grp_id)) { return 1; } } return -1;}/* * Checks if in-dialog request goes to gateway, taking * into account the group id. */int to_gw_grp(struct sip_msg* _m, char* _s1, char* _s2){ int grp_id; grp_id = (int)(long)_s1; return do_to_gw(_m, grp_id);}/* * Checks if in-dialog request goes to gateway, ignoring * the group id. */int to_gw(struct sip_msg* _m, char* _s1, char* _s2){ return do_to_gw(_m, -1);}/* * Frees contact list used by load_contacts function */static inline void free_contact_list(struct contact *curr) { struct contact *prev; while (curr) { prev = curr; curr = curr->next; pkg_free(prev); }}/* * Loads contacts in destination set into "lcr_contact" AVP in reverse * priority order and associated each contact with Q_FLAG telling if * contact is the last one in its priority class. Finally, removes * all branches from destination set. */int load_contacts(struct sip_msg* msg, char* key, char* value){ str branch, *ruri; qvalue_t q, ruri_q; struct contact *contacts, *next, *prev, *curr; int_str val; int idx; /* Check if anything needs to be done */ if (nr_branches == 0) { DBG("load_contacts(): DEBUG: Nothing to do - no branches!\n"); return 1; } ruri = GET_RURI(msg); if (!ruri) { LOG(L_ERR, "ERROR: load_contacts(): No Request-URI found\n"); return -1; } ruri_q = get_ruri_q(); for( idx=0 ; (branch.s=get_branch(idx,&branch.len,&q,0,0,0,0))!=0 ; idx++ ) { if (q != ruri_q) { goto rest; } } DBG("load_contacts(): DEBUG: Nothing to do - all same q!\n"); return 1;rest: /* Insert Request-URI to contact list */ contacts = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!contacts) { LOG(L_ERR, "ERROR: load_contacts(): No memory for Request-URI\n"); return -1; } contacts->uri.s = ruri->s; contacts->uri.len = ruri->len; contacts->q = ruri_q; contacts->next = (struct contact *)0; /* Insert branch URIs to contact list in increasing q order */ for( idx=0 ; (branch.s=get_branch(idx,&branch.len,&q,0,0,0,0))!=0 ; idx++ ) { next = (struct contact *)pkg_malloc(sizeof(struct contact)); if (!next) { LOG(L_ERR, "ERROR: load_contacts(): No memory for branch URI\n"); free_contact_list(contacts); return -1; } next->uri = branch; next->q = q; prev = (struct contact *)0; curr = contacts; while (curr && (curr->q < q)) { prev = curr; curr = curr->next; } if (!curr) { next->next = (struct contact *)0; prev->next = next; } else { next->next = curr; if (prev) { prev->next = next; } else { contacts = next; } } } /* Assign values for q_flags */ curr = contacts; curr->q_flag = 0; while (curr->next) { if (curr->q < curr->next->q) { curr->next->q_flag = Q_FLAG; } else { curr->next->q_flag = 0; } curr = curr->next; } /* Add contacts to "contacts" AVP */ curr = contacts; while (curr) { val.s = curr->uri; add_avp(contact_avp_name_str|AVP_VAL_STR|(curr->q_flag), contact_name, val); DBG("load_contacts(): DEBUG: Loaded <%s>, q_flag <%d>\n", val.s.s, curr->q_flag); curr = curr->next; } /* Clear all branches */ clear_branches(); /* Free contacts list */ free_contact_list(contacts); return 1;}/* * Adds to request a destination set that includes all highest priority * class contacts in "lcr_contact" AVP. If called from a route block, * rewrites the request uri with first contact and adds the remaining * contacts as branches. If called from failure route block, adds all * contacts as brances. Removes added contacts from "lcr_contact" AVP. */int next_contacts(struct sip_msg* msg, char* key, char* value){ struct usr_avp *avp, *prev; int_str val; struct action act; int rval; if ( route_type == REQUEST_ROUTE) { /* Find first lcr_contact_avp value */ avp = search_first_avp(contact_avp_name_str, contact_name, &val, 0); if (!avp) { DBG("next_contacts(): DEBUG: No AVPs -- we are done!\n"); return 1; } /* Set Request-URI */ act.type = SET_URI_T; act.p1_type = STRING_ST; act.p1.string = val.s.s; rval = do_action(&act, msg); if (rval != 1) { destroy_avp(avp); return rval; } DBG("next_contacts(): DEBUG: R-URI is <%s>\n", val.s.s); if (avp->flags & Q_FLAG) { destroy_avp(avp); /* Set fr_inv_timer */ val.n = inv_timer_next; if (add_avp(AVP_NAME_STR, inv_timer_name, val) != 0) { LOG(L_ERR, "next_contacts(): ERROR: setting of " "fr_inv_timer_avp failed\n"); return -1; } return 1; } /* Append branches until out of branches or Q_FLAG is set */ prev = avp; while ((avp = search_next_avp(avp, &val))) { destroy_avp(prev); act.type = APPEND_BRANCH_T; act.p1_type = STRING_ST; act.p1.string = val.s.s; act.p2_type = NUMBER_ST; act.p2.number = 0; rval = do_action(&act, msg); if (rval != 1) { destroy_avp(avp); LOG(L_ERR, "next_contacts(): ERROR: do_action failed " "with return value <%d>\n", rval); return -1; } DBG("next_contacts(): DEBUG: Branch is <%s>\n", val.s.s); if (avp->flags & Q_FLAG) { destroy_avp(avp); val.n = inv_timer_next; if (add_avp(AVP_NAME_STR, inv_timer_name, val) != 0) { LOG(L_ERR, "next_contacts(): ERROR: setting of " "fr_inv_timer_avp failed\n"); return -1; } return 1; } prev = avp; } } else if ( route_type == FAILURE_ROUTE) { avp = search_first_avp(contact_avp_name_str, contact_name, &val, 0); if (!avp) return -1; prev = avp; do { act.type = APPEND_BRANCH_T; act.p1_type = STRING_ST; act.p1.string = val.s.s; act.p2_type = NUMBER_ST; act.p2.number = 0; rval = do_action(&act, msg); if (rval != 1) { destroy_avp(avp); return rval; } DBG("next_contacts(): DEBUG: New branch is <%s>\n", val.s.s); if (avp->flags & Q_FLAG) { destroy_avp(avp); return 1; } prev = avp; avp = search_next_avp(avp, &val); destroy_avp(prev); } while (avp); /* Restore fr_inv_timer */ val.n = inv_timer; if (add_avp(AVP_NAME_STR, inv_timer_name, val) != 0) { LOG(L_ERR, "next_contacts(): ERROR: setting of " "fr_inv_timer_avp failed\n"); return -1; } } else { /* unsupported rout type */ return -1; } return 1;}/* * Convert string parameter to integer for functions that expect an integer. * Taken from mediaproxy module. */static int fixstring2int(void **param, int param_count){ unsigned long number; int err; if (param_count == 1) { number = str2s(*param, strlen(*param), &err); if (err == 0) { pkg_free(*param); *param = (void*)number; return 0; } else { LOG(L_ERR, "lcr/fixstring2int(): ERROR: bad number `%s'\n", (char*)(*param)); return E_CFG; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -