Esempio n. 1
0
status tm_hremove(struct tm_hash_t *hashtable, char *key){
	unsigned hash;
	struct tm_hash_entry_t *entry, *tmpentry;

	hash = tm_hash(key, hashtable->size - 1);
	entry = hashtable->table[hash];

	if(entry && strcmp(entry->key, key) == 0){
		tmpentry = entry->next;
		free(entry);
		hashtable->table[hash] = tmpentry;
		return OK;
	}else{
		while(entry){
			if(entry->next && strcmp(entry->next->key, key) == 0){
				tmpentry = entry->next;
				entry->next = entry->next->next;
				free(tmpentry);
				return OK;
			}
			entry = entry->next;
		}
	}
	return ERROR;
}
Esempio n. 2
0
struct tm_hinsert(struct tm_hash_t *hashtable, char *key, char *data, unsigned length, unsigned lifetime, short mode ){
	unsigned hash;
	struct tm_hash_entry_t *entry, *tmpentry;
	time_t currtime;

	hash = tm_hash(key, hashtable->size - 1);

	if(hash < 0 || hash >= hashtable->size){
		return ERROR;
	}

	if(tm_hfind(hashtable, key) != NULL){
		if(mode == MODE_ADD){
			return SUCCESS;
		}else{
			tm_hremove(hashtable, key);
		}
	}
	if((entry = malloc( sizeof(struct tm_hash_entry_t))) == NULL){
		return ERROR;
	}

	currtime = time( (time_t *)NULL);

	entry->key = key;
	entry->data = data;
	entry->length = length;
	entry->created = currtime;
	entry->expired = currtime + lifetime;
	entry->next = hashtable->table[hash] != NULL ? hashtable->table[hash] : NULL;
	hashtable->table[hash] = entry;
	return OK;
}
Esempio n. 3
0
/* Return a case-sensitive hash of string contents. */
unsigned int tm_string_hash(tm_string *in_string, unsigned int table_size)
{
	ASSERT(in_string);
	ASSERT(in_string->contents);

	return(tm_hash(in_string->contents, table_size));
}
Esempio n. 4
0
static inline unsigned int dlg2hash( dlg_t* dlg )
{
	str cseq_nr;
	unsigned int hashid;

	cseq_nr.s=int2str(dlg->loc_seq.value, &cseq_nr.len);
	hashid = tm_hash(dlg->id.call_id, cseq_nr);
	LM_DBG("%d\n", hashid);
	return hashid;
}
Esempio n. 5
0
struct tm_hash_entry_t  *tm_hfind(struct tm_hash_t *hashtable, char *key){
	unsigned hash;
	struct tm_hash_entry_t *entry;

	hash = tm_hash(key, hashtable->size - 1);

	if(hash < 0 || hash >= hashtable->size){
		return NULL;
	}

	for(entry = hashtable->table[hash]; entry != NULL; entry = entry->next){
		if(strcmp(entry->key, key) == 0){
			return entry;
		}
	}
	return NULL;
}
Esempio n. 6
0
File: tm.c Progetto: Deni90/opensips
inline static int t_check_trans(struct sip_msg* msg)
{
	struct cell *trans;

	if (msg->REQ_METHOD==METHOD_CANCEL) {
		/* parse needed hdrs*/
		if (check_transaction_quadruple(msg)==0) {
			LM_ERR("too few headers\n");
			return 0; /*drop request!*/
		}
		if (!msg->hash_index)
			msg->hash_index = tm_hash(msg->callid->body,get_cseq(msg)->number);
		/* performe lookup */
		trans = t_lookupOriginalT(  msg );
		return trans?1:-1;
	} else {
		trans = get_t();
		if (trans==NULL)
			return -1;
		if (trans!=T_UNDEFINED)
			return 1;
		switch ( t_lookup_request( msg , 0) ) {
			case 1:
				/* transaction found -> is it local ACK? */
				if (msg->REQ_METHOD==METHOD_ACK)
					return 1;
				/* .... else -> retransmission */
				trans = get_t();
				t_retransmit_reply(trans);
				UNREF(trans);
				set_t(0);
				return 0;
			case -2:
				/* e2e ACK found */
				return 1;
			default:
				/* notfound */
				return -1;
		}
	}
}
Esempio n. 7
0
int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
{
	struct cell         *p_cell;
	unsigned int       isACK;
	struct sip_msg  *t_msg;
	struct via_param *branch;
	int match_status;

	isACK = p_msg->REQ_METHOD==METHOD_ACK;

	if (isACK) {
		if (e2eack_T==NULL)
			return -1;
		if (e2eack_T!=T_UNDEFINED)
			return -2;
	}

	/* parse all*/
	if (check_transaction_quadruple(p_msg)==0) {
		LM_ERR("too few headers\n");
		set_t(0);
		/* stop processing */
		return 0;
	}

	/* start searching into the table */
	if (!p_msg->hash_index)
		p_msg->hash_index=tm_hash( p_msg->callid->body ,
			get_cseq(p_msg)->number ) ;
	LM_DBG("start searching: hash=%d, isACK=%d\n",
		p_msg->hash_index,isACK);


	/* 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) {
		LM_ERR("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(p_msg->hash_index);
		match_status=matching_3261(p_msg,&p_cell,
				/* skip transactions with different method; otherwise CANCEL
				 * would match the previous INVITE trans.  */
				isACK ? ~METHOD_INVITE: ~p_msg->REQ_METHOD);
		switch(match_status) {
				case 0:	goto notfound;	/* no match */
				case 1:	goto found; 	/* match */
				case 2:	goto e2e_ack;	/* e2e proxy ACK */
		}
	}

	/* ok -- it's ugly old-fashioned transaction matching -- it is
	 * a bit simplified to be fast -- we don't do all the comparisons
	 * of parsed uri, which was simply too bloated */
	LM_DBG("proceeding to pre-RFC3261 transaction matching\n");

	/* lock the whole entry*/
	LOCK_HASH(p_msg->hash_index);

	/* all the transactions from the entry are compared */
	for ( p_cell = get_tm_table()->entrys[p_msg->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 */

		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 ! */
			LM_DBG("non-ACK matched\n");
			goto found;
		} else { /* it's an ACK request*/
			/* ACK's relate only to INVITEs - and we look only for 2 types of
			 * INVITEs : (a) negative INVITEs or (b) pozitive UAS INVITEs */
			if ( t_msg->REQ_METHOD!=METHOD_INVITE || !(p_cell->uas.status>=300
			|| (p_cell->nr_of_outgoings==0 && p_cell->uas.status>=200)) )
				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;

			if (p_cell->uas.status<300) {
				/* it's a 2xx local UAS transaction */
				if (dlg_matching(p_cell, p_msg))
					goto e2e_ack;
				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! */
			LM_DBG("non-2xx ACK matched\n");
			goto found;
		} /* ACK */
	} /* synonym loop */

notfound:
	/* no transaction found */
	set_t(0);
	e2eack_T = NULL;
	if (!leave_new_locked || isACK) {
		UNLOCK_HASH(p_msg->hash_index);
	}
	LM_DBG("no transaction found\n");
	return -1;

e2e_ack:
	REF_UNSAFE( p_cell );
	UNLOCK_HASH(p_msg->hash_index);
	e2eack_T = p_cell;
	set_t(0);
	LM_DBG("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 );
	LM_DBG("transaction found (T=%p)\n",T);
	if (has_tran_tmcbs( T, TMCB_MSG_MATCHED_IN) )
		run_trans_callbacks( TMCB_MSG_MATCHED_IN, T, p_msg, 0,0);
	return 1;
}
Esempio n. 8
0
/* lookup a transaction by callid and cseq, parameters are pure
 * header field content only, e.g. "[email protected]" and "11"
 */
int t_lookup_callid(struct cell ** trans, str callid, str cseq) {
	struct cell* p_cell;
	unsigned int hash_index;

	/* I use MAX_HEADER, not sure if this is a good choice... */
	char callid_header[MAX_HEADER];
	char cseq_header[MAX_HEADER];
	/* save return value of print_* functions here */
	char* endpos;
	UNUSED(endpos);

	/* need method, which is always INVITE in our case */
	/* CANCEL is only useful after INVITE */
	str invite_method;
	char* invite_string = INVITE;

	invite_method.s = invite_string;
	invite_method.len = INVITE_LEN;

	/* lookup the hash index where the transaction is stored */
	hash_index=tm_hash(callid, cseq);

	if(hash_index >= TM_TABLE_ENTRIES){
		LM_ERR("invalid hash_index=%u\n",hash_index);
		return -1;
	}

	/* create header fields the same way tm does itself, then compare headers */
	endpos = print_callid_mini(callid_header, callid);
	LM_DBG("created comparable call_id header field: >%.*s<\n",
			(int)(endpos - callid_header), callid_header);

	endpos = print_cseq_mini(cseq_header, &cseq, &invite_method);
	LM_DBG("created comparable cseq header field: >%.*s<\n",
			(int)(endpos - cseq_header), cseq_header);

	LOCK_HASH(hash_index);

	/* all the transactions from the entry are compared */
	p_cell = get_tm_table()->entrys[hash_index].first_cell;
	for ( ; p_cell; p_cell = p_cell->next_cell ) {

		/* compare complete header fields, casecmp to make sure invite=INVITE */
		LM_DBG(" <%.*s>  <%.*s>\n", p_cell->callid.len, p_cell->callid.s,
			p_cell->cseq_n.len,p_cell->cseq_n.s);
		if ( (strncmp(callid_header, p_cell->callid.s, p_cell->callid.len) == 0)
			&& (strncasecmp(cseq_header, p_cell->cseq_n.s, p_cell->cseq_n.len) == 0) ) {
			LM_DBG("we have a match: callid=>>%.*s<< cseq=>>%.*s<<\n",
				p_cell->callid.len,p_cell->callid.s, p_cell->cseq_n.len,
				p_cell->cseq_n.s);
			REF_UNSAFE(p_cell);
			UNLOCK_HASH(hash_index);
			set_t(p_cell);
			*trans=p_cell;
			LM_DBG("transaction found.\n");
			return 1;
		}
		LM_DBG("NO match: callid=%.*s cseq=%.*s\n",
			p_cell->callid.len, p_cell->callid.s,
			p_cell->cseq_n.len, p_cell->cseq_n.s);
	}

	UNLOCK_HASH(hash_index);
	LM_DBG("transaction not found.\n");

	return -1;
}