dispatch.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 1,013 行 · 第 1/2 页

C
1,013
字号
	}		from   = get_from(msg)->uri;	trim(&from);	if (get_uri_hash_keys(&key1, &key2, &from, 0, ds_flags)<0)		return -1;	*hash = ds_get_hash(&key1, &key2);		return 0;}/** * */int ds_hash_touri(struct sip_msg *msg, unsigned int *hash){	str to;	str key1;	str key2;		if(msg==NULL || hash == NULL)	{		LOG(L_ERR, "DISPATCHER:ds_hash_touri: bad parameters\n");		return -1;	}	if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) ||				(msg->to==0)))	{		LOG(L_ERR, "DISPATCHER:ds_hash_touri:ERROR cannot parse To hdr\n");		return -1;	}			to   = get_to(msg)->uri;	trim(&to);		if (get_uri_hash_keys(&key1, &key2, &to, 0, ds_flags)<0)		return -1;	*hash = ds_get_hash(&key1, &key2);		return 0;}/** * */int ds_hash_callid(struct sip_msg *msg, unsigned int *hash){	str cid;	if(msg==NULL || hash == NULL)	{		LOG(L_ERR, "DISPATCHER:ds_hash_callid: bad parameters\n");		return -1;	}		if(msg->callid==NULL && ((parse_headers(msg, HDR_CALLID_F, 0)==-1) ||				(msg->callid==NULL)) )	{		LOG(L_ERR, "DISPATCHER:ds_hash_callid:ERROR cannot parse Call-Id\n");		return -1;	}		cid.s   = msg->callid->body.s;	cid.len = msg->callid->body.len;	trim(&cid);		*hash = ds_get_hash(&cid, NULL);		return 0;}int ds_hash_ruri(struct sip_msg *msg, unsigned int *hash){	str* uri;	str key1;	str key2;			if(msg==NULL || hash == NULL)	{		LOG(L_ERR, "DISPATCHER:ds_hash_ruri: bad parameters\n");		return -1;	}	if (parse_sip_msg_uri(msg)<0){		LOG(L_ERR, "DISPATCHER: ds_hash_ruri: ERROR: bad request uri\n");		return -1;	}		uri=GET_RURI(msg);	if (get_uri_hash_keys(&key1, &key2, uri, &msg->parsed_uri, ds_flags)<0)		return -1;		*hash = ds_get_hash(&key1, &key2);	return 0;}static inline int ds_get_index(int group, int *index){	ds_setidx_p si = NULL;		if(index==NULL || group<0 || _ds_index==NULL)		return -1;		/* get the index of the set */	si = _ds_index;	while(si)	{		if(si->id == group)		{			*index = si->index;			break;		}		si = si->next;	}	if(si==NULL)	{		LOG(L_ERR,			"DISPATCHER:ds_get_index: destination set [%d] not found\n",group);		return -1;	}	return 0;}static inline int ds_update_dst(struct sip_msg *msg, str *uri, int mode){	struct action act;	switch(mode)	{		case 1:			act.type = SET_HOSTPORT_T;			act.p1_type = STRING_ST;			if(uri->len>4 					&& strncasecmp(uri->s,"sip:",4)==0)				act.p1.string = uri->s+4;			else				act.p1.string = uri->s;			act.next = 0;				if (do_action(&act, msg) < 0) {				LOG(L_ERR,					"DISPATCHER:dst_update_dst: Error while setting host\n");				return -1;			}			if(route_type==FAILURE_ROUTE)			{				if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, 0)!=1 )				{					LOG(L_ERR,						"DISPATCHER:dst_update_dst: append_branch action"						" failed\n");					return -1;				}			}		break;		default:			if(route_type==FAILURE_ROUTE)			{				if (append_branch(msg, 0, uri, 0, Q_UNSPECIFIED, 0, 0)!=1 )				{					LOG(L_ERR,						"DISPATCHER:dst_update_dst: append_branch action"						" failed\n");					return -1;				}			} else {				if (set_dst_uri(msg, uri) < 0) {					LOG(L_ERR,					"DISPATCHER:dst_update_dst: Error while setting dst_uri\n");					return -1;				}				}		break;	}	return 0;}/** * */int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode){	int idx, i, cnt;	unsigned int hash;	int_str avp_name, avp_val;	if(msg==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_select_dst: bad parameters\n");		return -1;	}		if(_ds_list==NULL || _ds_index==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_select_dst: no destination sets\n");		return -1;	}	if((mode==0) && (ds_force_dst==0)			&& (msg->dst_uri.s!=NULL || msg->dst_uri.len>0))	{		LOG(L_ERR,			"DISPATCHER:ds_select_dst: destination already set [%.*s]\n",			msg->dst_uri.len, msg->dst_uri.s);		return -1;	}		/* get the index of the set */	if(ds_get_index(set, &idx)!=0)	{		LOG(L_ERR,			"DISPATCHER:ds_select_dst: destination set [%d] not found\n",set);		return -1;	}		DBG("DISPATCHER:ds_select_dst: set index [%d->%d]\n", set, idx);	hash = 0;	switch(alg)	{		case 0:			if(ds_hash_callid(msg, &hash)!=0)			{				LOG(L_ERR,					"DISPATCHER:ds_select_dst: can't get callid hash\n");				return -1;			}		break;		case 1:			if(ds_hash_fromuri(msg, &hash)!=0)			{				LOG(L_ERR,					"DISPATCHER:ds_select_dst: can't get From uri hash\n");				return -1;			}		break;		case 2:			if(ds_hash_touri(msg, &hash)!=0)			{				LOG(L_ERR,					"DISPATCHER:ds_select_dst: can't get To uri hash\n");				return -1;			}		break;		case 3:			if (ds_hash_ruri(msg, &hash)!=0)			{				LOG(L_ERR,						"DISPATCHER:ds_select_dst: can't get ruri hash\n");				return -1;			}		break;		case 4:			hash = _ds_list[idx].last;			_ds_list[idx].last = (_ds_list[idx].last+1) % _ds_list[idx].nr;		break;		default:			LOG(L_WARN,					"WARNING: ds_select_dst: algo %d not implemented"					" - using first entry...\n", alg);			hash = 0;	}	DBG("DISPATCHER:ds_select_dst: alg hash [%u]\n", hash);	cnt = 0;	if(ds_use_default!=0)		hash = hash%(_ds_list[idx].nr-1);	else		hash = hash%_ds_list[idx].nr;	i=hash;	while(_ds_list[idx].dlist[i].flags & DS_INACTIVE_DST)	{		if(ds_use_default!=0)			i = (i+1)%(_ds_list[idx].nr-1);		else			i = (i+1)%_ds_list[idx].nr;		if(i==hash)		{			if(ds_use_default!=0)			{				i = _ds_list[idx].nr-1;			} else {				return -1;			}		}	}	hash = i;	if(ds_update_dst(msg, &_ds_list[idx].dlist[hash].uri, mode)!=0)	{		LOG(L_ERR, "DISPATCHER:ds_select_dst: cannot set dst addr\n");		return -1;	}		DBG("DISPATCHER:ds_select_dst: selected [%d-%d/%d/%d] <%.*s>\n",		alg, set, idx, hash, _ds_list[idx].dlist[hash].uri.len,		_ds_list[idx].dlist[hash].uri.s);	if(!(ds_flags&DS_FAILOVER_ON))		return 1;	if(ds_use_default!=0 && hash!=_ds_list[idx].nr-1)	{		avp_val.s = _ds_list[idx].dlist[_ds_list[idx].nr-1].uri;		avp_name.n = dst_avp_id;		if(add_avp(AVP_VAL_STR, avp_name, avp_val)!=0)			return -1;		cnt++;	}		/* add to avp */	for(i=hash-1; i>=0; i--)	{			if((_ds_list[idx].dlist[i].flags & DS_INACTIVE_DST)				|| (ds_use_default!=0 && i==(_ds_list[idx].nr-1)))			continue;		DBG("DISPATCHER:ds_select_dst: using entry [%d/%d]\n",				set, i);		avp_val.s = _ds_list[idx].dlist[i].uri;		avp_name.n = dst_avp_id;		if(add_avp(AVP_VAL_STR, avp_name, avp_val)!=0)			return -1;		cnt++;	}	for(i=_ds_list[idx].nr-1; i>hash; i--)	{			if((_ds_list[idx].dlist[i].flags & DS_INACTIVE_DST)				|| (ds_use_default!=0 && i==(_ds_list[idx].nr-1)))			continue;		DBG("DISPATCHER:ds_select_dst: using entry [%d/%d]\n",				set, i);		avp_val.s = _ds_list[idx].dlist[i].uri;		avp_name.n = dst_avp_id;		if(add_avp(AVP_VAL_STR, avp_name, avp_val)!=0)			return -1;		cnt++;	}	/* add to avp the first used dst */	avp_val.s = _ds_list[idx].dlist[hash].uri;	avp_name.n = dst_avp_id;	if(add_avp(AVP_VAL_STR, avp_name, avp_val)!=0)		return -1;	cnt++;		/* add to avp the group id */	avp_val.n = set;	avp_name.n = grp_avp_id;	if(add_avp(0, avp_name, avp_val)!=0)		return -1;		/* add to avp the number of dst */	avp_val.n = cnt;	avp_name.n = cnt_avp_id;	if(add_avp(0, avp_name, avp_val)!=0)		return -1;		return 1;}int ds_next_dst(struct sip_msg *msg, int mode){	struct usr_avp *avp;	struct usr_avp *prev_avp;	int_str avp_name;	int_str avp_value;		if(!(ds_flags&DS_FAILOVER_ON))	{		LOG(L_WARN, "DISPATCHER:ds_next_dst: failover support disabled\n");		return -1;	}	avp_name.n = dst_avp_id;	prev_avp = search_first_avp(0, avp_name, &avp_value, 0);	if(prev_avp==NULL)		return -1; /* used avp deleted -- strange */	avp = search_next_avp(prev_avp, &avp_value);	destroy_avp(prev_avp);	if(avp==NULL || !(avp->flags&AVP_VAL_STR))		return -1; /* no more avps or value is int */		if(ds_update_dst(msg, &avp_value.s, mode)!=0)	{		LOG(L_ERR, "DISPATCHER:ds_next_dst: cannot set dst addr\n");		return -1;	}	DBG("DISPATCHER:ds_next_dst: using [%.*s]\n",			avp_value.s.len, avp_value.s.s);		return 1;}int ds_mark_dst(struct sip_msg *msg, int mode){	int group, ret;	struct usr_avp *prev_avp;	int_str avp_name;	int_str avp_value;		if(!(ds_flags&DS_FAILOVER_ON))	{		LOG(L_WARN, "DISPATCHER:ds_mark_dst: failover support disabled\n");		return -1;	}	avp_name.n = grp_avp_id;	prev_avp = search_first_avp(0, avp_name, &avp_value, 0);		if(prev_avp==NULL || prev_avp->flags&AVP_VAL_STR)		return -1; /* grp avp deleted -- strange */	group = avp_value.n;		avp_name.n = dst_avp_id;	prev_avp = search_first_avp(0, avp_name, &avp_value, 0);		if(prev_avp==NULL || !(prev_avp->flags&AVP_VAL_STR))		return -1; /* dst avp deleted -- strange */		if(mode==1)		ret = ds_set_state(group, &avp_value.s, DS_INACTIVE_DST, 0);	else		ret = ds_set_state(group, &avp_value.s, DS_INACTIVE_DST, 1);	DBG("DISPATCHER:ds_mark_dst: mode [%d] grp [%d] dst [%.*s]\n",			mode, group, avp_value.s.len, avp_value.s.s);		return (ret==0)?1:-1;}int ds_set_state(int group, str *address, int state, int type){	int i=0, idx=0;	if(_ds_list==NULL)	{		LOG(L_ERR, "DISPATCHER:ds_set_state: the list is null\n");		return -1;	}		/* get the index of the set */	if(ds_get_index(group, &idx)!=0)	{		LOG(L_ERR,			"DISPATCHER:ds_set_state: destination set [%d] not found\n",group);		return -1;	}	while(i<_ds_list[idx].nr)	{		if(_ds_list[idx].dlist[i].uri.len==address->len 				&& strncasecmp(_ds_list[idx].dlist[i].uri.s, address->s,					address->len)==0)		{			if(type)				_ds_list[idx].dlist[i].flags |= state;			else				_ds_list[idx].dlist[i].flags &= ~state;							return 0;		}		i++;	}	return -1;}int ds_print_list(FILE *fout){	int i, j;		if(_ds_list==NULL || _ds_list_nr<=0)	{		LOG(L_ERR, "DISPATCHER:ds_print_list: the list is null\n");		return -1;	}		fprintf(fout, "\nnumber of destination sets: %d\n", _ds_list_nr);	for(i=0; i<_ds_list_nr; i++)	{		fprintf(fout, "\n set #%d\n", _ds_list[i].id);		for(j=0; j<_ds_list[i].nr; j++)		{			fprintf(fout, "    %c   %.*s\n",				(_ds_list[i].dlist[j].flags&DS_INACTIVE_DST)?'I':'A',				_ds_list[i].dlist[j].uri.len, _ds_list[i].dlist[j].uri.s);		}	}	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?