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 + -
显示快捷键?