📄 t_lookup.c
字号:
{ t_msg = p_cell->uas.request; if (!t_msg) continue; /* skip UAC transactions */ if (!isACK) { /* compare lengths first */ if (!EQ_LEN(callid)) continue; if (!EQ_LEN(cseq)) continue; if (!EQ_LEN(from)) continue; if (!EQ_LEN(to)) continue; if (ruri_matching && !EQ_REQ_URI_LEN) continue; if (via1_matching && !EQ_VIA_LEN(via1)) continue; /* length ok -- move on */ if (!EQ_STR(callid)) continue; if (!EQ_STR(cseq)) continue; if (!EQ_STR(from)) continue; if (!EQ_STR(to)) continue; if (ruri_matching && !EQ_REQ_URI_STR) continue; if (via1_matching && !EQ_VIA_STR(via1)) continue; /* request matched ! */ DBG("DEBUG: non-ACK matched\n"); goto found; } else { /* it's an ACK request*/ /* ACK's relate only to INVITEs */ if (t_msg->REQ_METHOD!=METHOD_INVITE) continue; /* From|To URI , CallID, CSeq # must be always there */ /* compare lengths now */ if (!EQ_LEN(callid)) continue; /* CSeq only the number without method ! */ if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len) continue; if (! EQ_LEN(from)) continue; /* To only the uri -- to many UACs screw up tags */ if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len) continue; if (!EQ_STR(callid)) continue; if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s, get_cseq(p_msg)->number.len)!=0) continue; if (!EQ_STR(from)) continue; if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s, get_to(t_msg)->uri.len)!=0) continue; /* it is e2e ACK/200 */ if (p_cell->uas.status<300 && e2e_ack_trans==0) { /* all criteria for proxied ACK are ok */ if (p_cell->relaied_reply_branch!=-2) { e2e_ack_trans=p_cell; continue; } /* it's a local UAS transaction */ if (dlg_matching(p_cell, p_msg)) goto found; continue; } /* it is not an e2e ACK/200 -- perhaps it is * local negative case; in which case we will want * more elements to match: r-uri and via; allow * mismatching r-uri as an config option for broken * UACs */ if (ruri_matching && !EQ_REQ_URI_LEN ) continue; if (via1_matching && !EQ_VIA_LEN(via1)) continue; if (ruri_matching && !EQ_REQ_URI_STR) continue; if (via1_matching && !EQ_VIA_STR(via1)) continue; /* wow -- we survived all the check! we matched! */ DBG("DEBUG: non-2xx ACK matched\n"); goto found; } /* ACK */ } /* synonym loop */notfound: if (e2e_ack_trans) { p_cell=e2e_ack_trans; goto e2e_ack; } /* no transaction found */ set_t(0); if (!leave_new_locked) { UNLOCK_HASH(p_msg->hash_index); } DBG("DEBUG: t_lookup_request: no transaction found\n"); return -1;e2e_ack: t_ack=p_cell; /* e2e proxied ACK */ set_t(0); if (!leave_new_locked) { UNLOCK_HASH(p_msg->hash_index); } DBG("DEBUG: t_lookup_request: e2e proxy ACK found\n"); return -2;found: set_t(p_cell); REF_UNSAFE( T ); set_kr(REQ_EXIST); UNLOCK_HASH( p_msg->hash_index ); DBG("DEBUG: t_lookup_request: transaction found (T=%p)\n",T); return 1;}/* function lookups transaction being canceled by CANCEL in p_msg; * it returns: * 0 - transaction wasn't found * T - transaction found */struct cell* t_lookupOriginalT( struct sip_msg* p_msg ){ struct cell *p_cell; unsigned int hash_index; struct sip_msg *t_msg; struct via_param *branch; int ret; /* start searching in the table */ hash_index = p_msg->hash_index; DBG("DEBUG: t_lookupOriginalT: searching on hash entry %d\n",hash_index ); /* first of all, look if there is RFC3261 magic cookie in branch; if * so, we can do very quick matching and skip the old-RFC bizzar * comparison of many header fields */ if (!p_msg->via1) { LOG(L_ERR, "ERROR: t_lookupOriginalT: no via\n"); set_t(0); return 0; } branch=p_msg->via1->branch; if (branch && branch->value.s && branch->value.len>MCOOKIE_LEN && memcmp(branch->value.s,MCOOKIE,MCOOKIE_LEN)==0) { /* huhuhu! the cookie is there -- let's proceed fast */ LOCK_HASH(hash_index); ret=matching_3261(p_msg, &p_cell, /* we are seeking the original transaction -- * skip CANCEL transactions during search */ METHOD_CANCEL); if (ret==1) goto found; else goto notfound; } /* no cookies --proceed to old-fashioned pre-3261 t-matching */ LOCK_HASH(hash_index); /* all the transactions from the entry are compared */ for (p_cell=get_tm_table()->entrys[hash_index].first_cell; p_cell; p_cell = p_cell->next_cell ) { t_msg = p_cell->uas.request; if (!t_msg) continue; /* skip UAC transactions */ /* we don't cancel CANCELs ;-) */ if (t_msg->REQ_METHOD==METHOD_CANCEL) continue; /* check lengths now */ if (!EQ_LEN(callid)) continue; if (get_cseq(t_msg)->number.len!=get_cseq(p_msg)->number.len) continue; if (!EQ_LEN(from)) continue;#ifdef CANCEL_TAG if (!EQ_LEN(to)) continue;#else /* relaxed matching -- we don't care about to-tags anymore, * many broken UACs screw them up and ignoring them does not * actually hurt */ if (get_to(t_msg)->uri.len!=get_to(p_msg)->uri.len) continue;#endif if (ruri_matching && !EQ_REQ_URI_LEN) continue; if (via1_matching && !EQ_VIA_LEN(via1)) continue; /* check the content now */ if (!EQ_STR(callid)) continue; if (memcmp(get_cseq(t_msg)->number.s, get_cseq(p_msg)->number.s,get_cseq(p_msg)->number.len)!=0) continue; if (!EQ_STR(from)) continue;#ifdef CANCEL_TAG if (!EQ_STR(to)) continue;#else if (memcmp(get_to(t_msg)->uri.s, get_to(p_msg)->uri.s, get_to(t_msg)->uri.len)!=0) continue;#endif if (ruri_matching && !EQ_REQ_URI_STR) continue; if (via1_matching && !EQ_VIA_STR(via1)) continue; /* found */ goto found; }notfound: /* no transaction found */ DBG("DEBUG: t_lookupOriginalT: no CANCEL matching found! \n" ); UNLOCK_HASH(hash_index); DBG("DEBUG: t_lookupOriginalT completed\n"); return 0;found: DBG("DEBUG: t_lookupOriginalT: canceled transaction" " found (%p)! \n",p_cell ); REF_UNSAFE( p_cell ); UNLOCK_HASH(hash_index); DBG("DEBUG: t_lookupOriginalT completed\n"); return p_cell;}/* Returns 0 - nothing found * 1 - T found */int t_reply_matching( struct sip_msg *p_msg , int *p_branch ){ struct cell* p_cell; int hash_index = 0; int entry_label = 0; int branch_id = 0; char *hashi, *branchi, *p, *n; int hashl, branchl; int scan_space; str cseq_method; str req_method; char *loopi; int loopl; char *syni; int synl; short is_cancel; /* make compiler warnings happy */ loopi=0; loopl=0; syni=0; synl=0; /* split the branch into pieces: loop_detection_check(ignored), hash_table_id, synonym_id, branch_id */ if (!(p_msg->via1 && p_msg->via1->branch && p_msg->via1->branch->value.s)) goto nomatch2; /* we do RFC 3261 tid matching and want to see first if there is * magic cookie in branch */ if (p_msg->via1->branch->value.len<=MCOOKIE_LEN) goto nomatch2; if (memcmp(p_msg->via1->branch->value.s, MCOOKIE, MCOOKIE_LEN)!=0) goto nomatch2; p=p_msg->via1->branch->value.s+MCOOKIE_LEN; scan_space=p_msg->via1->branch->value.len-MCOOKIE_LEN; /* hash_id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); hashl=n-p; scan_space-=hashl; if (!hashl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; hashi=p; p=n+1;scan_space--; if (!syn_branch) { /* md5 value */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR ); loopl = n-p; scan_space-= loopl; if (n==p || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; loopi=p; p=n+1; scan_space--; } else { /* synonym id */ n=eat_token2_end( p, p+scan_space, BRANCH_SEPARATOR); synl=n-p; scan_space-=synl; if (!synl || scan_space<2 || *n!=BRANCH_SEPARATOR) goto nomatch2; syni=p; p=n+1;scan_space--; } /* branch id - should exceed the scan_space */ n=eat_token_end( p, p+scan_space ); branchl=n-p; if (!branchl ) goto nomatch2; branchi=p; /* sanity check */ if ((hash_index=reverse_hex2int(hashi, hashl))<0 ||hash_index>=TABLE_ENTRIES || (branch_id=reverse_hex2int(branchi, branchl))<0 ||branch_id>=MAX_BRANCHES || (syn_branch ? (entry_label=reverse_hex2int(syni, synl))<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 = 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, 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;}/* Determine current transaction * * Found Not Found Error (e.g. parsing) * Return Value 1 0 -1 * T ptr 0 T_UNDEFINED */int t_check( struct sip_msg* p_msg , int *param_branch ){ int local_branch; /* is T still up-to-date ? */ DBG("DEBUG: t_check: msg id=%d global id=%d T start=%p\n", p_msg->id,global_msg_id,T); if ( p_msg->id != global_msg_id || T==T_UNDEFINED ) { global_msg_id = p_msg->id; T = T_UNDEFINED; /* transaction lookup */ if ( p_msg->first_line.type==SIP_REQUEST ) { /* force parsing all the needed headers*/ if (parse_headers(p_msg, HDR_EOH, 0 )==-1) { LOG(L_ERR, "ERROR: t_check: parsing error\n"); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -