⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loose.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -