int w_is_first_hop(sip_msg_t *msg, char *p1, char *p2)
{
int ret;
rr_t* r = NULL;
sip_uri_t puri;
struct ip_addr *ip;
if(msg==NULL)
return -1;
if(msg->first_line.type == SIP_REQUEST) {
if (parse_headers( msg, HDR_VIA2_F, 0 )<0
|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
{
/* sip request: if more than one via, then not first hop */
/* no second via or error */
LM_DBG("no 2nd via found - first hop\n");
return 1;
}
return -1;
} else if(msg->first_line.type == SIP_REPLY) {
/* sip reply: if top record-route is myself
* and not received from myself (loop), then is first hop */
if (parse_headers( msg, HDR_EOH_F, 0 )<0) {
LM_DBG("error parsing headers\n");
return -1;
}
if(msg->record_route==NULL) {
LM_DBG("no record-route header - first hop\n");
return 1;
}
if(parse_rr(msg->record_route)<0) {
LM_DBG("failed to parse first record-route header\n");
return -1;
}
r = (rr_t*)msg->record_route->parsed;
if(parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &puri)<0) {
LM_DBG("failed to parse uri in first record-route header\n");
return -1;
}
if (((ip = str2ip(&(puri.host))) == NULL)
&& ((ip = str2ip6(&(puri.host))) == NULL)) {
LM_DBG("uri host is not an ip address\n");
return -1;
}
ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
(puri.transport_val.s)?puri.proto:0);
if(ret!=1) {
LM_DBG("top record route uri is not myself\n");
return -1;
}
if (ip_addr_cmp(ip, &(msg->rcv.src_ip))
&& ((msg->rcv.src_port == puri.port_no)
|| ((puri.port.len == 0) && (msg->rcv.src_port == 5060)))
&& (puri.proto==msg->rcv.proto
|| (puri.proto==0 && msg->rcv.proto==PROTO_UDP)) ) {
LM_DBG("source address matches top record route uri - loop\n");
return -1;
}
/* todo - check spirals */
return 1;
} else {
return -1;
}
}
//.........这里部分代码省略.........
/* sanity check */
if (reverse_hex2int(hashi, hashl, &hash_index)<0
||hash_index>=TABLE_ENTRIES
|| reverse_hex2int(branchi, branchl, &branch_id)<0
||branch_id>=MAX_BRANCHES
|| (syn_branch ? (reverse_hex2int(syni, synl, &entry_label))<0
: loopl!=MD5_LEN )
) {
DBG("DEBUG: t_reply_matching: poor reply labels %d label %d "
"branch %d\n", hash_index, entry_label, branch_id );
goto nomatch2;
}
DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
hash_index, entry_label, branch_id );
/* search the hash table list at entry 'hash_index'; lock the
entry first
*/
cseq_method=get_cseq(p_msg)->method;
is_cancel=cseq_method.len==CANCEL_LEN
&& memcmp(cseq_method.s, CANCEL, CANCEL_LEN)==0;
LOCK_HASH(hash_index);
for (p_cell = get_tm_table()->entrys[hash_index].first_cell; p_cell;
p_cell=p_cell->next_cell) {
/* first look if branch matches */
if (syn_branch) {
if (p_cell->label != entry_label)
continue;
} else {
if ( memcmp(p_cell->md5, loopi,MD5_LEN)!=0)
continue;
}
/* sanity check ... too high branch ? */
if ( branch_id>=p_cell->nr_of_outgoings )
continue;
/* does method match ? (remember -- CANCELs have the same branch
as canceled transactions) */
req_method=p_cell->method;
if ( /* method match */
! ((cseq_method.len==req_method.len
&& memcmp( cseq_method.s, req_method.s, cseq_method.len )==0)
/* or it is a local cancel */
|| (is_cancel && is_invite(p_cell)
/* commented out -- should_cancel_branch set it to
BUSY_BUFFER to avoid collisions with replies;
thus, we test here by buffer size
*/
/* && p_cell->uac[branch_id].local_cancel.buffer ))) */
&& p_cell->uac[branch_id].local_cancel.buffer_len )))
continue;
/* we passed all disqualifying factors .... the transaction has been
matched !
*/
set_t(p_cell);
*p_branch =(int) branch_id;
REF_UNSAFE( T );
UNLOCK_HASH(hash_index);
DBG("DEBUG: t_reply_matching: reply matched (T=%p)!\n",T);
/* if this is a 200 for INVITE, we will wish to store to-tags to be
* able to distinguish retransmissions later and not to call
* TMCB_RESPONSE_OUT uselessly; we do it only if callbacks are
* enabled -- except callback customers, nobody cares about
* retransmissions of multiple 200/INV or ACK/200s
*/
if (is_invite(p_cell) && p_msg->REPLY_STATUS>=200
&& p_msg->REPLY_STATUS<300
&& ( (!is_local(p_cell) &&
has_tran_tmcbs(p_cell,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) )
|| (is_local(p_cell)&&has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED))
)) {
if (parse_headers(p_msg, HDR_TO_F, 0)==-1) {
LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n");
}
}
if (!is_local(p_cell)) {
run_trans_callbacks( TMCB_RESPONSE_IN, T, T->uas.request, p_msg,
p_msg->REPLY_STATUS);
}
return 1;
} /* for cycle */
/* nothing found */
UNLOCK_HASH(hash_index);
DBG("DEBUG: t_reply_matching: no matching transaction exists\n");
nomatch2:
DBG("DEBUG: t_reply_matching: failure to match a transaction\n");
*p_branch = -1;
set_t(0);
return -1;
}
//#define DEBUG
int
encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
{
contact_body_t *cb;
contact_t *c;
str uri;
str newUri;
int res;
char separator;
/*
* I have a list of contacts in contact->parsed which is of type contact_body_t
* inside i have a contact->parsed->contact which is the head of the list of contacts
* inside it is a
* str uri;
* struct contact *next;
* I just have to visit each uri and encode each uri according to a scheme
*/
if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
(msg->contact == NULL) ))
{
LM_ERR("no Contact header present\n");
return -1;
}
separator = DEFAULT_SEPARATOR[0];
if (contact_flds_separator != NULL)
if (strlen(contact_flds_separator)>=1)
separator = contact_flds_separator[0];
if (msg->contact->parsed == NULL) parse_contact (msg->contact);
if (msg->contact->parsed != NULL)
{
cb = (contact_body_t *) msg->contact->parsed;
c = cb->contacts;
/* we visit each contact */
if (c != NULL)
{
uri = c->uri;
res = encode_uri (uri, encoding_prefix, public_ip,separator, &newUri);
if (res != 0)
{
LM_ERR("failed encoding contact.Code %d\n", res);
#ifdef STRICT_CHECK
return res;
#endif
}
else
if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
{
LM_ERR("lumping failed in mangling port \n");
return -2;
}
/* encoding next contacts too?*/
#ifdef ENCODE_ALL_CONTACTS
while (c->next != NULL)
{
c = c->next;
uri = c->uri;
res = encode_uri (uri, encoding_prefix,public_ip,separator,&newUri);
if (res != 0)
{
LM_ERR("failed encode_uri.Code %d\n",res);
#ifdef STRICT_CHECK
return res;
#endif
}
else
if (patch (msg, uri.s, uri.len, newUri.s, newUri.len)< 0)
{
LM_ERR("lumping failed in mangling port \n");
return -3;
}
} /* while */
#endif /* ENCODE_ALL_CONTACTS */
} /* if c != NULL */
} /* end if */
else /* after parsing still NULL */
{
LM_ERR("unable to parse Contact header\n");
return -4;
}
return 1;
}
/*! \brief removes first via & sends msg to the second */
int forward_reply(struct sip_msg* msg)
{
char* new_buf;
union sockaddr_union* to;
unsigned int new_len;
struct sr_module *mod;
int proto;
int id; /* used only by tcp*/
struct socket_info *send_sock;
#ifdef USE_TCP
char* s;
int len;
#endif
to=0;
id=0;
new_buf=0;
/*check if first via host = us */
if (check_via){
if (check_self(&msg->via1->host,
msg->via1->port?msg->via1->port:SIP_PORT,
msg->via1->proto)!=1){
LM_ERR("host in first via!=me : %.*s:%d\n",
msg->via1->host.len, msg->via1->host.s, msg->via1->port);
/* send error msg back? */
goto error;
}
}
/* quick hack, slower for multiple modules*/
for (mod=modules;mod;mod=mod->next){
if ((mod->exports) && (mod->exports->response_f)){
LM_DBG("found module %s, passing reply to it\n",
mod->exports->name);
if (mod->exports->response_f(msg)==0) goto skip;
}
}
/* if stateless fwd was disabled, we cannot have stateless replies here*/
if (sl_fwd_disabled)
goto skip;
/* we have to forward the reply stateless, so we need second via -bogdan*/
if (parse_headers( msg, HDR_VIA2_F, 0 )==-1
|| (msg->via2==0) || (msg->via2->error!=PARSE_OK))
{
/* no second via => error */
LM_ERR("no 2nd via found in reply from %s:%d <%.*s>\n",
ip_addr2a(&msg->rcv.src_ip),msg->rcv.src_port, msg->len,msg->buf );
goto error;
}
to=(union sockaddr_union*)pkg_malloc(sizeof(union sockaddr_union));
if (to==0){
LM_ERR("out of pkg memory\n");
goto error;
}
proto=msg->via2->proto;
if (update_sock_struct_from_via( to, msg, msg->via2 )==-1) goto error;
#ifdef USE_TCP
if (proto==PROTO_TCP
#ifdef USE_TLS
|| proto==PROTO_TLS
#endif
){
/* find id in i param if it exists */
if (msg->via1->i&&msg->via1->i->value.s){
s=msg->via1->i->value.s;
len=msg->via1->i->value.len;
id=reverse_hex2int(s, len);
}
}
#endif
send_sock = get_send_socket(msg, to, proto);
new_buf = build_res_buf_from_sip_res( msg, &new_len, send_sock);
if (!new_buf){
LM_ERR("failed to build rpl from req failed\n");
goto error;
}
if (msg_send(send_sock, proto, to, id, new_buf, new_len)<0) {
update_stat( drp_rpls, 1);
goto error0;
}
update_stat( fwd_rpls, 1);
/*
* If no port is specified in the second via, then this
* message output a wrong port number - zero. Despite that
* the correct port is choosen in update_sock_struct_from_via,
* as its visible with su_getport(to); .
*/
LM_DBG("reply forwarded to %.*s:%d\n", msg->via2->host.len,
msg->via2->host.s, (unsigned short) msg->via2->port);
pkg_free(new_buf);
pkg_free(to);
//.........这里部分代码省略.........
开发者ID:iamroger,项目名称:voip,代码行数:101,代码来源:forward.c
示例14: select_anyheader
int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
{
struct hdr_field *hf, *hf0;
int hi;
char c;
struct hdr_field hdr;
if(msg==NULL) {
if (res!=NULL) return -1;
/* "fixup" call, res & msg are NULL */
if (s->n <3) return -1;
if (s->params[2].type==SEL_PARAM_STR) {
/* replace _ with - (for P-xxx headers) */
for (hi=s->params[2].v.s.len-1; hi>0; hi--)
if (s->params[2].v.s.s[hi]=='_')
s->params[2].v.s.s[hi]='-';
/* if header name is parseable, parse it and set SEL_PARAM_DIV */
c=s->params[2].v.s.s[s->params[2].v.s.len];
s->params[2].v.s.s[s->params[2].v.s.len]=':';
if (parse_hname2(s->params[2].v.s.s,s->params[2].v.s.s+(s->params[2].v.s.len<3?4:s->params[2].v.s.len+1),
&hdr)==0) {
ERR("select_anyhdr:fixup_call:parse error\n");
return -1;
}
s->params[2].v.s.s[s->params[2].v.s.len]=c;
if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) {
/* pkg_free(s->params[1].v.s.s); */
/* don't free it (the mem can leak only once at startup)
* the parsed string can live inside larger string block
* e.g. when xlog's select is parsed
*/
s->params[2].type = SEL_PARAM_DIV;
s->params[2].v.i = hdr.type;
}
}
return 1;
}
hf0 = NULL;
/* extract header index if present */
if (s->param_offset[s->lvl+1] == 4) {
if (s->params[3].type == SEL_PARAM_INT) {
hi = s->params[3].v.i;
} else {
hi = -1;
}
} else {
hi = 1;
}
/* we need to be sure we have parsed all headers */
if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
ERR("bad msg while parsing to EOH \n");
return -1;
}
for (hf=msg->headers; hf; hf=hf->next) {
if(s->params[2].type==SEL_PARAM_DIV) {
if (s->params[2].v.i!=hf->type) continue;
} else if(s->params[2].type==SEL_PARAM_STR) {
if (s->params[2].v.s.len!=hf->name.len) continue;
if (strncasecmp(s->params[2].v.s.s, hf->name.s, hf->name.len)!=0) continue;
}
hf0 = hf;
hi--;
if (!hi) break;
}
if(hf0==NULL || hi>0)
return 1;
res->s = hf0->body.s;
res->len = hf0->body.len;
trim(res);
return 0;
}
请发表评论