📄 loose.c
字号:
str* uri; struct socket_info *si; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "after_strict: Error while parsing the first route URI\n"); return RR_ERROR; } if ( enable_double_rr && is_2rr(&puri.params) &&#ifdef ENABLE_USER_CHECK is_myself(&puri.user, &puri.host, puri.port_no)#else is_myself(&puri.host, puri.port_no)#endif ) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { _m->force_send_socket = si; } else { LOG(L_WARN,"WARNING:rr:after_loose: no socket found for " "match second RR\n"); } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_strict: Cannot remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LOG(L_ERR, "after_strict: Error while searching next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ DBG("after_strict: No next URI found\n"); return NOT_RR_DRIVEN; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; /* parse the new found uri */ uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "after_strict: Error while parsing URI\n"); return RR_ERROR; } } /* set the hooks for the params -bogdan * important note: RURI is already parsed by the above function, so * we just used it without any checking */ routed_msg_id = _m->id; routed_params = _m->parsed_uri.params; if (is_strict(&puri.params)) { DBG("after_strict: Next hop: '%.*s' is strict router\n", uri->len, ZSW(uri->s)); /* Previous hop was a strict router and the next hop is strict * router too. There is no need to save R-URI again because it * is saved already. In fact, in this case we will behave exactly * like a strict router. */ /* Note: when there is only one Route URI left (endpoint), it will * always be a strict router because endpoints don't use ;lr parameter * In this case we will simply put the URI in R-URI and forward it, * which will work perfectly */ if (rewrite_uri(_m, uri) < 0) { LOG(L_ERR, "after_strict: Error while rewriting request URI\n"); return RR_ERROR; } if (rt->next) { rem_off = hdr->body.s; rem_len = rt->next->nameaddr.name.s - hdr->body.s; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LOG(L_ERR, "after_strict: Cannot remove Route HF\n"); return RR_ERROR; } } else { DBG("after_strict: Next hop: '%.*s' is loose router\n", uri->len, ZSW(uri->s)); if (set_dst_uri(_m, uri) < 0) { LOG(L_ERR, "after_strict: Error while setting dst_uri\n"); return RR_ERROR; } /* Next hop is a loose router - Which means that is is not endpoint yet * In This case we have to recover from previous strict routing, that * means we have to find the last Route URI and put in in R-URI and * remove the last Route URI. */ if (rt != hdr->parsed) { /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ rem_off = hdr->body.s; rem_len = rt->nameaddr.name.s - hdr->body.s; if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LOG(L_ERR, "after_strict: Can't remove Route HF\n"); return RR_ERROR; } } res = find_rem_target(_m, &hdr, &rt, &prev); if (res < 0) { LOG(L_ERR, "after_strict: Error while looking for last " "Route URI\n"); return RR_ERROR; } else if (res > 0) { /* No remote target is an error */ return RR_ERROR; } uri = &rt->nameaddr.uri; if (rewrite_uri(_m, uri) < 0) { LOG(L_ERR, "after_strict: Can't rewrite R-URI\n"); return RR_ERROR; } /* The first character if uri will be either '<' when it is the * only URI in a Route header field or ',' if there is more than * one URI in the header field */ DBG("after_strict: The last route URI: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); if (prev) { rem_off = prev->nameaddr.name.s + prev->len; rem_len = rt->nameaddr.name.s + rt->len - rem_off; } else { rem_off = hdr->name.s; rem_len = hdr->len; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LOG(L_ERR, "after_strict: Can't remove Route HF\n"); return RR_ERROR; } } /* run RR callbacks -bogdan */ run_rr_callbacks( _m, &routed_params ); return RR_DRIVEN;}static inline int after_loose(struct sip_msg* _m, int preloaded){ struct hdr_field* hdr; struct sip_uri puri; rr_t* rt; int res; int status;#ifdef ENABLE_USER_CHECK int ret;#endif str* uri; struct socket_info *si; hdr = _m->route; rt = (rr_t*)hdr->parsed; uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "after_loose: Error while parsing the first route URI\n"); return RR_ERROR; } /* IF the URI was added by me, remove it */#ifdef ENABLE_USER_CHECK ret=is_myself(&puri.user, &puri.host, puri.port_no); if (ret>0)#else if (is_myself(&puri.host, puri.port_no))#endif { DBG("after_loose: Topmost route URI: '%.*s' is me\n", uri->len, ZSW(uri->s)); /* set the hooks for the params -bogdan */ routed_msg_id = _m->id; routed_params = puri.params; if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_loose: Can't remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LOG(L_ERR, "after_loose: Error while finding next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ DBG("after_loose: No next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&puri.params)) { /* double route may occure due different IP and port, so force as * send interface the one advertise in second Route */ if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) { LOG(L_ERR, "after_loose: Error while parsing the " "double route URI\n"); return RR_ERROR; } si = grep_sock_info( &puri.host, puri.port_no, puri.proto); if (si) { _m->force_send_socket = si; } else { LOG(L_WARN,"WARNING:rr:after_loose: no socket found for " "match second RR\n"); } if (!rt->next) { /* No next route in the same header, remove the whole header * field immediately */ if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) { LOG(L_ERR, "after_loose: Can't remove Route HF\n"); return RR_ERROR; } res = find_next_route(_m, &hdr); if (res < 0) { LOG(L_ERR,"after_loose: Error while finding next route\n"); return RR_ERROR; } if (res > 0) { /* No next route found */ DBG("after_loose: No next URI found\n"); status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); goto done; } rt = (rr_t*)hdr->parsed; } else rt = rt->next; } uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LOG(L_ERR, "after_loose: Error while parsing the first route URI\n"); return RR_ERROR; } } else {#ifdef ENABLE_USER_CHECK /* check if it the ignored user */ if(ret < 0) return NOT_RR_DRIVEN;#endif DBG("after_loose: Topmost URI is NOT myself\n"); } DBG("after_loose: URI to be processed: '%.*s'\n", uri->len, ZSW(uri->s)); if (is_strict(&puri.params)) { DBG("after_loose: Next URI is a strict router\n"); if (handle_sr(_m, hdr, rt) < 0) { LOG(L_ERR, "after_loose: Error while handling strict router\n"); return RR_ERROR; } } else { /* Next hop is loose router */ DBG("after_loose: Next URI is a loose router\n"); if (set_dst_uri(_m, uri) < 0) { LOG(L_ERR, "after_loose: Error while setting dst_uri\n"); return RR_ERROR; } /* There is a previous route uri which was 2nd uri of mine * and must be removed here */ if (rt != hdr->parsed) { if (!del_lump(_m, hdr->body.s - _m->buf, rt->nameaddr.name.s - hdr->body.s, 0)) { LOG(L_ERR, "after_loose: Can't remove Route HF\n"); return RR_ERROR; } } } status = RR_DRIVEN;done: /* run RR callbacks -bogdan */ run_rr_callbacks( _m, &routed_params ); return status;}/* * Do loose routing as defined in RFC3621 */int loose_route(struct sip_msg* _m, char* _s1, char* _s2){ int ret; if (find_first_route(_m) != 0) { DBG("loose_route: There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LOG(L_ERR, "loose_route: Error while parsing Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else {#ifdef ENABLE_USER_CHECK if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host, _m->parsed_uri.port_no)) {#else if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)) {#endif return after_strict(_m); } else { return after_loose(_m, 0); } }}int check_route_param(struct sip_msg * msg, regex_t* re){ regmatch_t pmatch; char bk; str params; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) return -1; /* check if params are present */ if ( !routed_params.s || !routed_params.len ) return -1; /* include also the first ';' */ for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ ); /* do the well-known trick to convert to null terminted */ bk = params.s[params.len]; params.s[params.len] = 0; DBG("DEBUG:rr:check_route_param: params are <%s>\n", params.s); if (regexec( re, params.s, 1, &pmatch, 0)!=0) { params.s[params.len] = bk; return -1; } else { params.s[params.len] = bk; return 0; }}int get_route_param( struct sip_msg *msg, str *name, str *val){ char *p; char *end; char c; int quoted; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) goto notfound; /* check if params are present */ if ( !routed_params.s || !routed_params.len ) goto notfound; end = routed_params.s + routed_params.len; p = routed_params.s; /* parse the parameters string and find the "name" param */ while ( end-p>name->len+2 ) { if (p!=routed_params.s) { /* go to first ';' char */ for( quoted=0 ; p<end && !(*p==';' && !quoted) ; p++ ) if ( (*p=='"' || *p=='\'') && *(p-1)!='\\' ) quoted ^= 0x1; if (p==end) goto notfound; p++; } /* get first non space char */ while( p<end && (*p==' ' || *p=='\t') ) p++; /* check the name - length first and content after */ if ( end-p<name->len+2 ) goto notfound; if ( memcmp(p,name->s,name->len)!=0 ) { p++; continue; } p+=name->len; while( p<end && (*p==' ' || *p=='\t') ) p++; if (p==end|| *p==';') { /* empty val */ val->len = 0; val->s = 0; goto found; } if (*(p++)!='=') continue; while( p<end && (*p==' ' || *p=='\t') ) p++; if (p==end) goto notfound; /* get value */ if ( *p=='\'' || *p=='"') { for( val->s = ++p ; p<end ; p++) { if ((*p=='"' || *p=='\'') && *(p-1)!='\\' ) break; } } else { for( val->s=p ; p<end ; p++) { if ( (c=*p)==';' || c==' ' || c=='\t' ) break; } } val->len = p-val->s; if (val->len==0) val->s = 0; goto found; }notfound: return -1;found: return 0;}int is_direction(struct sip_msg * msg, int dir){ static str ftag_param = {"ftag",4}; static unsigned int last_id = (unsigned int)-1; static unsigned int last_dir = 0; str ftag_val; str tag; if ( last_id==msg->id && last_dir!=0) { if (last_dir==RR_FLOW_UPSTREAM) goto upstream; else goto downstream; } ftag_val.s = 0; ftag_val.len = 0; if (get_route_param( msg, &ftag_param, &ftag_val)!=0) { DBG("DEBUG:rr:is_direction: param ftag not found\n"); goto downstream; } if ( ftag_val.s==0 || ftag_val.len==0 ) { DBG("DEBUG:rr:is_direction: param ftag has empty val\n"); goto downstream; } /* get the tag value from FROM hdr */ if ( parse_from_header(msg)!=0 ) goto downstream; tag = ((struct to_body*)msg->from->parsed)->tag_value; if (tag.s==0 || tag.len==0) goto downstream; /* compare the 2 strings */ if (tag.len!=ftag_val.len || memcmp(tag.s,ftag_val.s,ftag_val.len)) goto upstream;downstream: last_id = msg->id; last_dir = RR_FLOW_DOWNSTREAM; return (dir==RR_FLOW_DOWNSTREAM)?0:-1;upstream: last_id = msg->id; last_dir = RR_FLOW_UPSTREAM; return (dir==RR_FLOW_UPSTREAM)?0:-1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -