📄 loose.c
字号:
pkg_free(s); LOG(L_ERR, "save_ruri: Cannot insert lump\n"); return -4; } return 0;}/* * Logic necessary to forward request to strict routers * * Returns 0 on success, negative number on an error */static inline int handle_sr(struct sip_msg* _m, struct hdr_field* _hdr, rr_t* _r){ str* uri; char* rem_off; int rem_len; uri = &_r->nameaddr.uri; /* Next hop is strict router, save R-URI here */ if (save_ruri(_m) < 0) { LOG(L_ERR, "handle_sr: Error while saving Request-URI\n"); return -1; } /* Put the first Route in Request-URI */ if (rewrite_uri(_m, uri) < 0) { LOG(L_ERR, "handle_sr: Error while rewriting request URI\n"); return -2; } if (!_r->next) { rem_off = _hdr->name.s; rem_len = _hdr->len; } else { rem_off = _hdr->body.s; rem_len = _r->next->nameaddr.name.s - _hdr->body.s; } if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) { LOG(L_ERR, "handle_sr: Can't remove Route HF\n"); return -9; } return 0;}/* * Find last route in the last Route header field, * if there was a previous route in the last Route header * field, it will be saved in _p parameter */static inline int find_rem_target(struct sip_msg* _m, struct hdr_field** _h, rr_t** _l, rr_t** _p){ struct hdr_field* ptr, *last; if (parse_headers(_m, HDR_EOH, 0) == -1) { LOG(L_ERR, "find_rem_target: Error while parsing message header\n"); return -1; } ptr = _m->route; last = 0; while(ptr) { if (ptr->type == HDR_ROUTE) last = ptr; ptr = ptr->next; } if (last) { if (parse_rr(last) < 0) { LOG(L_ERR, "find_rem_target: Error while parsing last Route HF\n"); return -2; } *_p = 0; *_l = (rr_t*)last->parsed; while ((*_l)->next) { *_p = *_l; *_l = (*_l)->next; } return 0; } else { LOG(L_ERR, "find_rem_target: Can't find last Route HF\n"); return 1; }}/* * Previous hop was a strict router, handle this case */static inline int after_strict(struct sip_msg* _m){ int res, rem_len; struct hdr_field* hdr; struct sip_uri puri; rr_t* rt, *prev; char* rem_off; str* uri; 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; }#ifdef ENABLE_USER_CHECK if (is_myself(&puri.user, &puri.host, puri.port_no))#else if (is_myself(&puri.host, puri.port_no))#endif { /* if (enable_double_rr && is_2rr(&_ruri->params)) { */ /* DBG("ras(): Removing 2nd URI of mine: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); */ 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; } uri = &rt->nameaddr.uri; if (parse_uri(uri->s, uri->len, &puri) == -1) { LOG(L_ERR, "after_strict: Error while parsing URI\n"); return RR_ERROR; } 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; } } 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; #ifdef ENABLE_USER_CHECK int ret;#endif str* uri; 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)); 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"); return (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); } rt = (rr_t*)hdr->parsed; } else rt = rt->next; if (enable_double_rr && is_2rr(&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"); return (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN); } 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; } } } return RR_DRIVEN;}/* * 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) == -1) { 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, &_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); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -