Пример #1
0
/**
 * init module function
 */
static int mod_init(void)
{
	LM_INFO("initializing...\n");

	init_db_url( db_url , 0 /*cannot be null*/);
	db_table.len = strlen(db_table.s);
	sdomain_column.len = strlen(sdomain_column.s);
	prefix_column.len = strlen(prefix_column.s);
	domain_column.len = strlen(domain_column.s);
	prefix.len = strlen(prefix.s);

	pdt_char_list.len = strlen(pdt_char_list.s);
	if(pdt_char_list.len<=0)
	{
		LM_ERR("invalid pdt char list\n");
		return -1;
	}
	LM_INFO("pdt_char_list=%s \n",pdt_char_list.s);

	/* binding to mysql module */
	if(db_bind_mod(&db_url, &pdt_dbf))
	{
		LM_ERR("database module not found\n");
		return -1;
	}

	if (!DB_CAPABILITY(pdt_dbf, DB_CAP_ALL))
	{
		LM_ERR("database module does not "
		    "implement all functions needed by the module\n");
		return -1;
	}

	/* open a connection with the database */
	db_con = pdt_dbf.init(&db_url);
	if(db_con==NULL)
	{
		LM_ERR("failed to connect to the database\n");        
		return -1;
	}
	
	if (pdt_dbf.use_table(db_con, &db_table) < 0)
	{
		LM_ERR("failed to use_table\n");
		goto error1;
	}
	LM_DBG("database connection opened successfully\n");
	
	/* create & init lock */
	if ((pdt_lock = lock_init_rw()) == NULL) {
		LM_CRIT("failed to init lock\n");
		goto error1;
	}
	
	/* tree pointer in shm */
	_ptree = (pdt_tree_t**)shm_malloc( sizeof(pdt_tree_t*) );
	if (_ptree==0) {
		LM_ERR("out of shm mem for pdtree\n");
		goto error1;
	}
	*_ptree=0;

	/* loading all information from database */
	if(pdt_load_db()!=0)
	{
		LM_ERR("cannot load info from database\n");	
		goto error1;
	}
		
	pdt_dbf.close(db_con);
	db_con = 0;

#if 0
	pdt_print_tree(*_ptree);
#endif

	/* success code */
	return 0;

error1:
	if (pdt_lock)
	{
		lock_destroy_rw( pdt_lock );
		pdt_lock = 0;
	}
	if(_ptree!=0)
		shm_free(_ptree);

	if(db_con!=NULL)
	{
		pdt_dbf.close(db_con);
		db_con = 0;
	}
	return -1;
}
Пример #2
0
/*
 * Record destination status
 * param code Destination status
 * param dest Destination
 */
static void ospRecordCode(
    int code,
    osp_dest* dest)
{
    struct usr_avp* destmediaavp = NULL;
    int_str destmediaval;

    LM_DBG("code '%d'\n", code);
    dest->lastcode = code;

    switch (code) {
        case 100:
            if (!dest->time100) {
                dest->time100 = time(NULL);
            } else {
                LM_DBG("100 already recorded\n");
            }
            break;
        case 180:
        case 181:
        case 182:
        case 183:
            if (!dest->time180) {
                dest->time180 = time(NULL);

                if (!dest->endtime) {
                    dest->endtime = time(NULL);
                } else {
                    LM_DBG("180, 181, 182 or 183 end allready recorded\n");
                }
            } else {
                LM_DBG("180, 181, 182 or 183 allready recorded\n");
            }
            break;
        case 200:
        case 202:
            if (!dest->time200) {
                dest->time200 = time(NULL);

                if ((_osp_destmedia_avpid >= 0) &&
                    ((destmediaavp = search_first_avp(_osp_destmedia_avptype, _osp_destmedia_avpid, &destmediaval, 0)) != NULL) &&
                    (destmediaavp->flags & AVP_VAL_STR) && (destmediaval.s.s && destmediaval.s.len))
                {
                    snprintf(dest->destmedia, sizeof(dest->destmedia), "%.*s", destmediaval.s.len, destmediaval.s.s);
                } else {
                    dest->destmedia[0] = '\0';
                }
            } else {
                LM_DBG("200 or 202 allready recorded\n");
            }
            break;
        case 408:
        case 487:
            if (!dest->endtime) {
                dest->endtime = time(NULL);
            } else {
                LM_DBG("408 or 487 end allready recorded\n");
            }
            break;
        default:
            /* It may overwrite existing end time, it is the expected behavior */
            if ((code >= 400) && (code <= 699)) {
                dest->endtime = time(NULL);
            }
    }
}
Пример #3
0
/*
 * Delete a row from table
 */
int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
{
	dbt_table_p _tbc = NULL;
	dbt_row_p _drp = NULL, _drp0 = NULL;
	int *lkey = NULL;

	if (!_h || !CON_TABLE(_h))
	{
		LM_ERR("invalid parameters\n");
		return -1;
	}

	/* lock database */
	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
	if(!_tbc)
	{
		LM_ERR("failed to load table <%.*s>!\n", CON_TABLE(_h)->len,
				CON_TABLE(_h)->s);
		return -1;
	}

	if(!_k || !_v || _n<=0)
	{
		LM_DBG("deleting all records\n");
		dbt_table_free_rows(_tbc);
		/* unlock databse */
		dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
		return 0;
	}

	lkey = dbt_get_refs(_tbc, _k, _n);
	if(!lkey)
		goto error;
	
	_drp = _tbc->rows;
	while(_drp)
	{
		_drp0 = _drp->next;
		if(dbt_row_match(_tbc, _drp, lkey, _o, _v, _n))
		{
			// delete row
			if(_drp->prev)
				(_drp->prev)->next = _drp->next;
			else
				_tbc->rows = _drp->next;
			if(_drp->next)
				(_drp->next)->prev = _drp->prev;
			_tbc->nrrows--;
			// free row
			dbt_row_free(_tbc, _drp);
		}
		_drp = _drp0;
	}

	dbt_table_update_flags(_tbc, DBT_TBFL_MODI, DBT_FL_SET, 1);
	
	/* dbt_print_table(_tbc, NULL); */
	
	/* unlock database */
	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));

	if(lkey)
		pkg_free(lkey);
	
	return 0;
	
error:
	/* unlock database */
	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));

	LM_ERR("failed to delete from table!\n");
	return -1;
}
Пример #4
0
static inline int oma_match_identity_condition(xmlNodePtr condition, subs_t *subs, str *w_uri)
{
        int r = 0, many_match = 0;
        char *domain = NULL;
        str uri;
        str *normalized_uri;
        xmlNodePtr node = NULL, except_node = NULL;

        for(node = condition->children; node; node = node->next)
        {
                if(xmlStrcasecmp(node->name, (unsigned char*)"one") == 0)
                {
			uri.s = xmlNodeGetAttrContentByName(node, "id");
			if(uri.s == NULL)
			{
				LM_ERR("when extracting entry attribute\n");
				continue;
			}
                        uri.len = strlen(uri.s);

                        normalized_uri = normalizeSipUri(&uri);
                        if (normalized_uri->s == NULL || normalized_uri->len == 0)
                        {
                                LM_ERR("normalizing URI\n");
                                xmlFree(uri.s);
                                continue;
                        }
                        xmlFree(uri.s);

                        if (normalized_uri->len == w_uri->len && strncmp(normalized_uri->s, w_uri->s, w_uri->len) == 0)
                        {
                                r = 1;
                                break;
                        }
                }
                else if(xmlStrcasecmp(node->name, (unsigned char*)"many") == 0)
                {
                        domain = xmlNodeGetAttrContentByName(node, "domain");
                        if(domain == NULL)
                        {
                                LM_DBG("No domain attribute in identity many\n");
                        }
                        else
                        {
                                LM_DBG("<many domain= %s>\n", domain);
                                if(!(strlen(domain) == subs->from_domain.len &&
                                    strncmp(domain, subs->from_domain.s, subs->from_domain.len) == 0))
                                {
                                        xmlFree(domain);
                                        continue;
                                }
                                xmlFree(domain);
                        }

                        many_match = 1;
                        for(except_node = node->children; except_node; except_node= except_node->next)
                        {
                                if(xmlStrcasecmp(except_node->name, (unsigned char*)"except"))
                                        continue;

                                uri.s = xmlNodeGetAttrContentByName(except_node, "id");
                                if(uri.s != NULL)
                                {
                                    uri.len = strlen(uri.s);
                                    normalized_uri = normalizeSipUri(&uri);
                                    if (normalized_uri->s == NULL || normalized_uri->len == 0)
                                    {
                                            LM_ERR("normalizing URI\n");
                                            xmlFree(uri.s);
                                            continue;
                                    }
                                    xmlFree(uri.s);

                                    if (normalized_uri->len == w_uri->len && strncmp(normalized_uri->s, w_uri->s, w_uri->len) == 0)
                                    {
                                            many_match = 0;
                                            break;
                                    }
                                }
                                else
                                {
                                        domain = NULL;
                                        domain = xmlNodeGetAttrContentByName(except_node, "domain");
                                        if(domain != NULL)
                                        {
                                                LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n", domain, (int)strlen(domain));
                                                if(strlen(domain)==subs->from_domain.len &&
                                                    (strncmp(domain,subs->from_domain.s , subs->from_domain.len)==0))
                                                {
                                                        LM_DBG("except domain match\n");
                                                        xmlFree(domain);
                                                        many_match = 0;
                                                        break;
                                                }
                                                xmlFree(domain);
                                        }

                                }
                        }

                        if(many_match)
                        {
                                r = 1;
                                break;
                        }
                }

        }

        return r;

}
Пример #5
0
static void ietf_get_rules(subs_t* subs, xmlDocPtr xcap_tree, xcap_rule_t **rules)
{
	str w_uri= {0, 0};
	char* id = NULL, *domain = NULL, *time_cont= NULL;
	int apply_rule = -1;
	xmlNodePtr ruleset_node = NULL, node1= NULL, node2= NULL;
	xmlNodePtr cond_node = NULL, except_node = NULL;
	xmlNodePtr identity_node = NULL, sphere_node = NULL;
	xmlNodePtr iden_child;
	xmlNodePtr validity_node, time_node;
	time_t t_init, t_fin, t;
	int valid= 0;
	xcap_rule_t *rule = NULL;

        *rules = NULL;

	uandd_to_uri(subs->from_user, subs->from_domain, &w_uri);
	if(w_uri.s == NULL)
	{
		LM_ERR("while creating uri\n");
		return;
	}
	ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL);
	if(ruleset_node == NULL)
	{
		LM_DBG("ruleset_node NULL\n");
		goto error;

	}
	for(node1 = ruleset_node->children ; node1; node1 = node1->next)
	{
		if(xmlStrcasecmp(node1->name, (unsigned char*)"text")==0 )
				continue;

		/* process conditions */
		LM_DBG("node1->name= %s\n", node1->name);

		cond_node = xmlNodeGetChildByName(node1, "conditions");
		if(cond_node == NULL)
		{
			LM_DBG("cond node NULL\n");
			goto error;
		}
		LM_DBG("cond_node->name= %s\n", cond_node->name);

		validity_node = xmlNodeGetChildByName(cond_node, "validity");
		if(validity_node !=NULL)
		{
			LM_DBG("found validity tag\n");

			t= time(NULL);

			/* search all from-until pair */
			for(time_node= validity_node->children; time_node;
					time_node= time_node->next)
			{
				if(xmlStrcasecmp(time_node->name, (unsigned char*)"from")!= 0)
				{
					continue;
				}
				time_cont= (char*)xmlNodeGetContent(time_node);
				t_init= xml_parse_dateTime(time_cont);
				xmlFree(time_cont);
				if(t_init< 0)
				{
					LM_ERR("failed to parse xml dateTime\n");
					goto error;
				}

				if(t< t_init)
				{
					LM_DBG("the lower time limit is not respected\n");
					continue;
				}

				time_node= time_node->next;
				while(1)
				{
					if(time_node== NULL)
					{
						LM_ERR("bad formatted xml doc:until child not found in"
								" validity pair\n");
						goto error;
					}
					if( xmlStrcasecmp(time_node->name,
								(unsigned char*)"until")== 0)
						break;
					time_node= time_node->next;
				}

				time_cont= (char*)xmlNodeGetContent(time_node);
				t_fin= xml_parse_dateTime(time_cont);
				xmlFree(time_cont);

				if(t_fin< 0)
				{
					LM_ERR("failed to parse xml dateTime\n");
					goto error;
				}

				if(t <= t_fin)
				{
					LM_DBG("the rule is active at this time\n");
					valid= 1;
				}

			}

			if(!valid)
			{
				LM_DBG("the rule is not active at this time\n");
				continue;
			}

		}

		sphere_node = xmlNodeGetChildByName(cond_node, "sphere");
		if(sphere_node!= NULL)
		{
			/* check to see if matches presentity current sphere */
			/* ask presence for sphere information */

			char* sphere= pres_get_sphere(&subs->pres_uri);
			if(sphere)
			{
				char* attr= (char*)xmlNodeGetContent(sphere_node);
				if(xmlStrcasecmp((unsigned char*)attr, (unsigned char*)sphere)!= 0)
				{
					LM_DBG("sphere condition not respected\n");
					pkg_free(sphere);
					xmlFree(attr);
					continue;
				}
				pkg_free(sphere);
				xmlFree(attr);

			}
			else
			{
				LM_DBG("Noo sphere definition found\n");
				continue;
			}
			/* if the user has not define a sphere
			 *						consider the condition false*/
		}

		identity_node = xmlNodeGetChildByName(cond_node, "identity");
		if(identity_node == NULL)
		{
			LM_ERR("didn't find identity tag\n");
			goto error;
		}

		iden_child= xmlNodeGetChildByName(identity_node, "one");
		if(iden_child)
		{
			for(node2 = identity_node->children; node2; node2 = node2->next)
			{
				if(xmlStrcasecmp(node2->name, (unsigned char*)"one")!= 0)
					continue;

				id = xmlNodeGetAttrContentByName(node2, "id");
				if(id== NULL)
				{
					LM_ERR("while extracting attribute\n");
					goto error;
				}
				if((strlen(id)== w_uri.len &&
							(strncmp(id, w_uri.s, w_uri.len)==0)))
				{
					apply_rule = 1;
					xmlFree(id);
					break;
				}
				xmlFree(id);
			}
		}

		/* search for many node*/
		iden_child= xmlNodeGetChildByName(identity_node, "many");
		if(iden_child)
		{
			domain = NULL;
			for(node2 = identity_node->children; node2; node2 = node2->next)
			{
				if(xmlStrcasecmp(node2->name, (unsigned char*)"many")!= 0)
					continue;

				domain = xmlNodeGetAttrContentByName(node2, "domain");
				if(domain == NULL)
				{
					LM_DBG("No domain attribute to many\n");
				}
				else
				{
					LM_DBG("<many domain= %s>\n", domain);
					if((strlen(domain)!= subs->from_domain.len &&
								strncmp(domain, subs->from_domain.s,
									subs->from_domain.len) ))
					{
						xmlFree(domain);
						continue;
					}
				}
				xmlFree(domain);
				apply_rule = 1;
				if(node2->children == NULL)       /* there is no exception */
					break;

				for(except_node = node2->children; except_node;
						except_node= except_node->next)
				{
					if(xmlStrcasecmp(except_node->name, (unsigned char*)"except"))
						continue;

					id = xmlNodeGetAttrContentByName(except_node, "id");
					if(id!=NULL)
					{
						if((strlen(id)- 1== w_uri.len &&
								(strncmp(id, w_uri.s, w_uri.len)==0)))
						{
							xmlFree(id);
							apply_rule = 0;
							break;
						}
						xmlFree(id);
					}
					else
					{
						domain = NULL;
						domain = xmlNodeGetAttrContentByName(except_node, "domain");
						if(domain!=NULL)
						{
							LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n",
									domain, (int)strlen(domain));
							if(strlen(domain)==subs->from_domain.len &&
								(strncmp(domain,subs->from_domain.s , subs->from_domain.len)==0))
							{
								LM_DBG("except domain match\n");
								xmlFree(domain);
								apply_rule = 0;
								break;
							}
							xmlFree(domain);
						}

					}
				}
				if(apply_rule== 1)  /* if a match was found no need to keep searching*/
					break;

			}
		}
		if(apply_rule ==1)
			break;
	}

	LM_DBG("apply_rule= %d\n", apply_rule);
	if(w_uri.s!=NULL)
		pkg_free(w_uri.s);

	if( !apply_rule || !node1)
		return;

	rule = (xcap_rule_t *)pkg_malloc(sizeof(*rule));
	if (rule == NULL)
	{
		LM_ERR("cannot allocate pkg_mem\n");
		return;
	}

	/* TODO: in IETF mode only the first matching rule is returned */
	rule->node = node1;
	rule->next = NULL;
	*rules = rule;

	return;
error:
	if(w_uri.s)
		pkg_free(w_uri.s);
}
Пример #6
0
static int _bm_register_timer(char *tname, int mode, unsigned int *id)
{
	benchmark_timer_t *bmt = 0;
	benchmark_timer_t **tidx = 0;

	if(tname==NULL || id==NULL || bm_mycfg==NULL || strlen(tname)==0
			|| strlen(tname)>BM_NAME_LEN-1)
		return -1;

	bmt = bm_mycfg->timers;
	while(bmt)
	{
		if(strcmp(bmt->name, tname)==0)
		{
			*id = bmt->id;
			return 0;
		}
		bmt = bmt->next;
	}
	if(mode==0)
		return -1;

	bmt = (benchmark_timer_t*)shm_malloc(sizeof(benchmark_timer_t));

	if(bmt==0)
	{
		LM_ERR("no more shm\n");
		return -1;
	}
	memset(bmt, 0, sizeof(benchmark_timer_t));

	bmt->lock = lock_alloc();
	if(bmt->lock == NULL) {
		shm_free(bmt);
		LM_ERR("no more shm\n");
		return -1;
	}

	if (!lock_init(bmt->lock)) {
		lock_dealloc(bmt->lock);
		shm_free(bmt);
		LM_ERR("failed to init lock\n");
		return -1;
	}

	/* private memory, otherwise we have races */
	bmt->start = (bm_timeval_t*)pkg_malloc(sizeof(bm_timeval_t)); 
	if(bmt->start == NULL)
	{
		lock_dealloc(bmt->lock);
		shm_free(bmt);
		LM_ERR("no more pkg\n");
		return -1;
	}
	memset(bmt->start, 0, sizeof(bm_timeval_t)); 

	strcpy(bmt->name, tname);
	if(bm_mycfg->timers==0)
	{
		bmt->id = 0;
		bm_mycfg->timers = bmt;
	} else {
		bmt->id = bm_mycfg->timers->id+1;
		bmt->next = bm_mycfg->timers;
		bm_mycfg->timers = bmt;
	}

	/* do the indexing */
	if(bmt->id%10==0)
	{
		if(bm_mycfg->tindex!=NULL)
			tidx = bm_mycfg->tindex;
		bm_mycfg->tindex = (benchmark_timer_t**)shm_malloc((10+bmt->id)*
								sizeof(benchmark_timer_t*));
		if(bm_mycfg->tindex==0)
		{
			LM_ERR("no more share memory\n");
			if(tidx!=0)
				shm_free(tidx);
			return -1;
		}
		memset(bm_mycfg->tindex, 0, (10+bmt->id)*sizeof(benchmark_timer_t*));
		if(tidx!=0)
		{
			memcpy(bm_mycfg->tindex, tidx, bmt->id*sizeof(benchmark_timer_t*));
			shm_free(tidx);
		}
	}
	bm_mycfg->tindex[bmt->id] = bmt;
	bm_mycfg->nrtimers = bmt->id + 1;
	reset_timer(bmt->id);
	*id = bmt->id;
	LM_DBG("timer [%s] added with index <%u>\n", bmt->name, bmt->id);

	return 0;
}
Пример #7
0
/* first time it will called for a CALLER leg - at that time there will
   be no leg allocated, so automatically CALLER gets the first position, while
   the CALLEE legs will follow into the array in the same order they came */
int dlg_add_leg_info(struct dlg_cell *dlg, str* tag, str *rr,
		str *contact,str *cseq, struct socket_info *sock,
		str *mangled_from,str *mangled_to,str *sdp)
{
	struct dlg_leg* leg,*new_legs;
	rr_t *head = NULL, *rrp;

	if ( (dlg->legs_no[DLG_LEGS_ALLOCED]-dlg->legs_no[DLG_LEGS_USED])==0) {
		new_legs = (struct dlg_leg*)shm_realloc(dlg->legs,
			(dlg->legs_no[DLG_LEGS_ALLOCED]+2)*sizeof(struct dlg_leg));
		if (new_legs==NULL) {
			LM_ERR("Failed to resize legs array\n");
			return -1;
		}
		dlg->legs=new_legs;
		dlg->legs_no[DLG_LEGS_ALLOCED] += 2;
		memset( dlg->legs+dlg->legs_no[DLG_LEGS_ALLOCED]-2, 0,
			2*sizeof(struct dlg_leg));
	}
	leg = &dlg->legs[ dlg->legs_no[DLG_LEGS_USED] ];

	leg->tag.s = (char*)shm_malloc(tag->len);
	leg->r_cseq.s = (char*)shm_malloc( cseq->len );
	if ( leg->tag.s==NULL || leg->r_cseq.s==NULL) {
		LM_ERR("no more shm mem\n");
		if (leg->tag.s) shm_free(leg->tag.s);
		if (leg->r_cseq.s) shm_free(leg->r_cseq.s);
		return -1;
	}

	if (dlg->legs_no[DLG_LEGS_USED] == 0) {
		/* first leg = caller. also store inv cseq */
		leg->inv_cseq.s = (char *)shm_malloc( cseq->len);
		if (leg->inv_cseq.s == NULL) {
			LM_ERR("no more shm mem\n");
			shm_free(leg->tag.s);
			shm_free(leg->r_cseq.s);
			return -1;
		}
	}

	if (contact->len) {
		/* contact */
		leg->contact.s = shm_malloc(rr->len + contact->len);
		if (leg->contact.s==NULL) {
			LM_ERR("no more shm mem\n");
			shm_free(leg->tag.s);
			shm_free(leg->r_cseq.s);
			return -1;
		}
		leg->contact.len = contact->len;
		memcpy( leg->contact.s, contact->s, contact->len);
		/* rr */
		if (rr->len) {
			leg->route_set.s = leg->contact.s + contact->len;
			leg->route_set.len = rr->len;
			memcpy( leg->route_set.s, rr->s, rr->len);

			if (parse_rr_body(leg->route_set.s,leg->route_set.len,&head) != 0) {
				LM_ERR("failed parsing route set\n");
				shm_free(leg->tag.s);
				shm_free(leg->r_cseq.s);
				shm_free(leg->contact.s);
				return -1;
			}
			rrp = head;
			leg->nr_uris = 0;
			while (rrp) {
				leg->route_uris[leg->nr_uris++] = rrp->nameaddr.uri;
				rrp = rrp->next;
			}
			free_rr(&head);
		}
	}

	/* save mangled from URI, if any */
	if (mangled_from && mangled_from->s && mangled_from->len) {
		leg->from_uri.s = shm_malloc(mangled_from->len);
		if (!leg->from_uri.s) {
			LM_ERR("no more shm\n");
			shm_free(leg->tag.s);
			shm_free(leg->r_cseq.s);
			if (leg->contact.s)
				shm_free(leg->contact.s);
			return -1;
		}

		leg->from_uri.len = mangled_from->len;
		memcpy(leg->from_uri.s,mangled_from->s,mangled_from->len);
	}

	if (mangled_to && mangled_to->s && mangled_to->len) {
		leg->to_uri.s = shm_malloc(mangled_to->len);
		if (!leg->to_uri.s) {
			LM_ERR("no more shm\n");
			shm_free(leg->tag.s);
			shm_free(leg->r_cseq.s);
			if (leg->contact.s)
				shm_free(leg->contact.s);
			if (leg->from_uri.s)
				shm_free(leg->from_uri.s);
			return -1;
		}

		leg->to_uri.len = mangled_to->len;
		memcpy(leg->to_uri.s,mangled_to->s,mangled_to->len);
	}

	/* TODO - consider late negociation here and when handling the first ACK */
	if (dlg->legs_no[DLG_LEGS_USED] == 0 && sdp && sdp->s && sdp->len) {
		/* save this just for the caller leg here, for the callee leg we'll have to update anyway */
		leg->sdp.s = shm_malloc(sdp->len);
		if (!leg->sdp.s) {
			LM_ERR("no more shm\n");
			shm_free(leg->tag.s);
			shm_free(leg->r_cseq.s);
			if (leg->contact.s)
				shm_free(leg->contact.s);
			if (leg->from_uri.s)
				shm_free(leg->from_uri.s);
			return -1;
		}

		leg->sdp.len = sdp->len;
		memcpy(leg->sdp.s,sdp->s,sdp->len);
	}

	/* tag */
	leg->tag.len = tag->len;
	memcpy( leg->tag.s, tag->s, tag->len);

	/* socket */
	leg->bind_addr = sock;

	if (dlg->legs_no[DLG_LEGS_USED] == 0)
	{
		/* first leg = caller . store inv cseq */
		leg->inv_cseq.len = cseq->len;
		memcpy(leg->inv_cseq.s,cseq->s,cseq->len);

		/* set cseq for caller to 0
		 * future requests to the caller leg will update this
		 * needed for proper validation of in-dialog requests
		 *
		 * TM also increases this value by one, if dialog
		 * is terminated from the middle, so 0 is ok*/
		leg->r_cseq.len = 1;
		leg->r_cseq.s[0]='0';
	} else {
		/* cseq */
		leg->r_cseq.len = cseq->len;
		memcpy( leg->r_cseq.s, cseq->s, cseq->len);
	}

	/* make leg visible for searchers */
	dlg->legs_no[DLG_LEGS_USED]++;

	LM_DBG("set leg %d for %p: tag=<%.*s> rcseq=<%.*s>\n",
		dlg->legs_no[DLG_LEGS_USED]-1, dlg,
		leg->tag.len,leg->tag.s,
		leg->r_cseq.len,leg->r_cseq.s );

	return 0;
}
/**
 * Initialize the database module.
 * No function should be called before this
 * \param _url URL used for initialization
 * \return zero on success, negative value on failure
 */
db1_con_t* erlang_srdb1_init(const str* _url)
{
	LM_DBG("erlang_srdb1_init %.*s \n", _url->len, _url->s);
	return db_do_init(_url, (void *)erlang_srdb1_new_connection);
}
//temporary
void erlang_srdb1_free_connection(struct erlang_connection* con) {
	LM_DBG("erlang_free_connection %p \n",con);
	free_db_id(con->hdr.id);
	pkg_free(con);
	return;
}
/**
 * Query a table for specified rows.
 * \param _h structure representing database connection
 * \param _k key names
 * \param _op operators
 *\param  _v values of the keys that must match
 * \param _c column names to return
 * \param _n number of key=values pairs to compare
 * \param _nc number of columns to return
 * \param _o order by the specified column
 * \param _r pointer to a structure representing the result
 * \return zero on success, negative value on failure
 */
int erlang_srdb1_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op,
	     const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc,
	     const db_key_t _o, db1_res_t** _r) {
	ei_x_buff argbuf,retbuf;
	int retcode,i,j,x;
	int n_cols,n_rows,len;
	db1_res_t *res;
	db_row_t *rows = NULL, *row;
	db_val_t *val;
	char atom[MAXATOMLEN], *p;
	ei_term term;
	int ei_type,size;
	str *sname;

	if (!_h || !_r) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}
	*_r=NULL;
	LM_DBG("erlang_srdb1_query table %.*s\n",CON_TABLE(_h)->len, CON_TABLE(_h)->s);
	ei_x_new(&argbuf);
	//encode tuple {db_op, table, [cols], [params]}
	ei_x_encode_tuple_header(&argbuf, 5);
	ei_x_encode_atom(&argbuf,"select");
	ei_x_encode_atom_len(&argbuf,CON_TABLE(_h)->s,CON_TABLE(_h)->len);

	srdb1_encode_c(_c, _nc, &argbuf);
	srdb1_encode_k(_k, _op, _v, _n, &argbuf);
//	ei_x_encode_atom_len(&argbuf,_o->s,_o->len);
	ei_x_encode_list_header(&argbuf, 0);

	retcode=erl_bind.do_erlang_call(&(CON_ERLANG(_h)->con),&(CON_ERLANG(_h)->regname), &argbuf, &retbuf);
	ei_x_free(&argbuf);
	if (retcode<0) {
		if(retbuf.buff) shm_free(retbuf.buff);
		return retcode;
	}
	// we have a tuple there:
	ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &i);
	x=retbuf.index;
	ei_skip_term(retbuf.buff, &x);
	LM_DBG("erlang_srdb1_query: position of end of field list should be %d\n",x);
	//first is list of 5-element tuples containing name and type of field
	ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_cols);
	LM_DBG("erlang_srdb1_query: length -f field_list is %d\n",n_cols);
	res=db_new_result();
	if (db_allocate_columns(res, n_cols) != 0) {
		LM_ERR("erlang_srdb1_query: db_allocate_columns failed\n");
		goto error;
	}
	RES_COL_N(res) = n_cols;
	for(i=0; i < n_cols; i++) {
		x=retbuf.index;
		ei_skip_term(retbuf.buff, &x);
		LM_DBG("erlang_srdb1_query: position of end of this field should be %d\n",x);
		ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j);
		if( j!=5) LM_ERR("erlang_srdb1_query name&type list element tuple is not 5\n");
		ei_decode_atom(retbuf.buff, &(retbuf.index), atom);  //1  name
		len=strlen(atom);
		sname = (str*)pkg_malloc(sizeof(str)+len+1);
		if (!sname) {
			LM_ERR("no private memory left\n");
			goto error;
		}
		sname->len = len;
		sname->s = (char*)sname + sizeof(str);
		memcpy(sname->s, atom, len);
		sname->s[len] = '\0';
		RES_NAMES(res)[i] = sname;
		LM_DBG("decoded header %d, fieled 1: %s\n",i,atom);
		ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //2 type atom
		if(strcmp("int",atom)==0) { RES_TYPES(res)[i]=DB1_INT; }
		if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_STRING; }
		if(strcmp("float",atom)==0) { RES_TYPES(res)[i]=DB1_DOUBLE; }
		if(strcmp("datetime",atom)==0) { RES_TYPES(res)[i]=DB1_DATETIME; }
//		if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_BLOB; }
		ei_skip_term(retbuf.buff, &(retbuf.index));  //3 size (ignored)
		ei_skip_term(retbuf.buff, &(retbuf.index));  //4 default value (ignored)
		ei_skip_term(retbuf.buff, &(retbuf.index));  //3 null status (ignored)
		LM_DBG("end of %d record: %d\n",i,retbuf.index);
	}
	ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail,
	LM_DBG("erlang_srdb1_query: position after scanning is %d\n",retbuf.index);
	//now rows, list of tuples
	ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_rows);
	LM_DBG("erlang_srdb1_query values list size is %d\n",n_rows);
	if (n_rows<=0) {
		LM_DBG("erlang_srdb1_query no rows returned\n");
		RES_ROWS(res) = NULL;
		RES_NUM_ROWS(res)=0;
		*_r=res;
		return 0;
	}
	RES_NUM_ROWS(res)=n_rows;
	rows = pkg_realloc(rows, sizeof(db_row_t) * n_rows);
	if (rows == NULL) {
		LM_ERR("erlang_srdb1_query: pkg_realloc rows failed\n");
		goto error;
	}
	RES_ROWS(res) = rows;
	for(i=0; i < n_rows; i++) {
		RES_ROW_N(res)=i+1;
		row = &RES_ROWS(res)[i];
		if (db_allocate_row(res, row) != 0) {
			LM_ERR("erlang_srdb1_query: db_allocate_row failed for row %d\n",i);
			goto error;
		}
		ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j);
		if(j!=n_cols) {
			LM_ERR("erlang_srdb1_query: mismatch:values list element tuple size is %d n_cols from header was %d\n",j, n_cols);
		}
		for (j = 0, val = ROW_VALUES(row); j < RES_COL_N(res); j++, val++) {
			VAL_TYPE(val) = RES_TYPES(res)[j];
			VAL_NULL(val) = 0;
			VAL_FREE(val) = 0;
			retcode=ei_get_type_internal(retbuf.buff, &(retbuf.index), &ei_type, &size);
			if (retcode < 0) {
				LM_ERR("erlang_srdb1_query: error getting type for element %d %d\n",i,j);
				goto error;
			}
			LM_DBG("erlang_srdb1_query: element %d %d ei_type=%d size=%d\n",i,j,ei_type, size);
			switch(ei_type) {
				case ERL_SMALL_INTEGER_EXT:
				case ERL_INTEGER_EXT:
					retcode=ei_decode_long(retbuf.buff, &(retbuf.index), &VAL_INT(val));
					if(retcode < 0) goto error;
					LM_DBG("decoded interger %d\n",VAL_INT(val));
					break;
				case ERL_FLOAT_EXT:
				case NEW_FLOAT_EXT:
					retcode=ei_decode_double(retbuf.buff, &(retbuf.index), &VAL_DOUBLE(val));
					if(retcode < 0) goto error;
					LM_DBG("decoded float %f\n",VAL_DOUBLE(val));
					break;
				case ERL_ATOM_EXT:
				case ERL_SMALL_ATOM_EXT:
				case ERL_ATOM_UTF8_EXT:
				case ERL_SMALL_ATOM_UTF8_EXT:
					p=pkg_malloc(size+1);
					if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; }
					retcode=ei_decode_atom(retbuf.buff, &(retbuf.index), p);
					if(retcode < 0) {
						pkg_free(p);
						goto error;
					}
					LM_DBG("decoded small_atom_utf %s\n",p);
					VAL_STRING(val)=p;
					VAL_FREE(val)=1;
					break;
				case ERL_STRING_EXT:
					p=pkg_malloc(size+1);
					if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; }
					retcode=ei_decode_string(retbuf.buff, &(retbuf.index), p);
					if(retcode < 0) {
						pkg_free(p);
						goto error;
					}
					LM_DBG("decoded string %s\n",p);
					VAL_STRING(val)=p;
					VAL_FREE(val)=1;
					break;
				case ERL_SMALL_TUPLE_EXT:
				case ERL_LARGE_TUPLE_EXT:
					LM_DBG("got tuple)\n");
					if (VAL_TYPE(val)==DB1_DATETIME) {
					    struct tm tm;
					    LM_DBG("and col type is datetime\n");
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_year);tm.tm_year -=1900;
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mon); tm.tm_mon -=1;
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mday);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_hour);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_min);
					    if(retcode < 0) goto error;
					    retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_sec);
					    if(retcode < 0) goto error;
					    VAL_TIME(val)=mktime(&tm);
					    break;
					}
					LM_ERR("erlang_srdb1_query: got tuple but valtype is not datetime element %d in row %d in response\n",j,i);
					break;
				case ERL_REFERENCE_EXT:
				case ERL_NEW_REFERENCE_EXT:
				case ERL_PORT_EXT:
				case ERL_PID_EXT:
				case ERL_NIL_EXT:
				case ERL_LIST_EXT:
				case ERL_BINARY_EXT:
				case ERL_SMALL_BIG_EXT:
				case ERL_LARGE_BIG_EXT:
				case ERL_NEW_FUN_EXT:
				case ERL_FUN_EXT:
				default:
				    LM_ERR("erlang_srdb1_query: don't know how to handle element %d in row %d in response\n",j,i);
			}
		}
	}
	ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail,
	*_r=res;
	return 0;
error:
	if (res)
		db_free_result(res);
	LM_ERR("erlang_srdb1_query: Failed\n");
	return -1;
}
/**
 * Store the name of table that will be used by subsequent database functions
 * \param _h database handle
 * \param _t table name
 * \return zero on success, negative value on failure
 */
int erlang_srdb1_use_table(db1_con_t* _h, const str* _t)
{
	LM_DBG("erlang_srdb1_use_table %.*s\n", _t->len, _t->s);
	return db_use_table(_h, _t);
}
Пример #12
0
/**
 * "pdt_delete" syntax:
 *    sdomain
 *    domain
 */
struct mi_root* pdt_mi_delete(struct mi_root* cmd_tree, void* param)
{
	str sd, sdomain;
	struct mi_node* node= NULL;
	db_key_t db_keys[2] = {&sdomain_column, &domain_column};
	db_val_t db_vals[2];
	db_op_t  db_ops[2] = {OP_EQ, OP_EQ};

	/* read sdomain */
	node = cmd_tree->node.kids;
	if(node == NULL)
		goto error;

	sdomain = node->value;
	if(sdomain.s == NULL || sdomain.len== 0)
		return init_mi_tree( 404, "domain not found", 16);

	if( *sdomain.s=='.' )
		 return init_mi_tree( 400, "400 empty param",11);

	/* read domain */
	node= node->next;
	if(node == NULL || node->next!=NULL)
		goto error;

	sd= node->value;
	if(sd.s== NULL || sd.len==0)
	{
		LM_ERR("could not read domain\n");
		return init_mi_tree(404, "domain not found", 16);
	}

	if(*sd.s=='.')
		 return init_mi_tree( 400, "empty param", 11);


	db_vals[0].type = DB_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = sdomain.s;
	db_vals[0].val.str_val.len = sdomain.len;
	
	db_vals[1].type = DB_STR;
	db_vals[1].nul = 0;
	db_vals[1].val.str_val.s = sd.s;
	db_vals[1].val.str_val.len = sd.len;

	if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 2)<0)
	{
		LM_ERR("database/cache are inconsistent\n");
		return init_mi_tree( 500, "database/cache are inconsistent", 31 );
	} 
	/* re-loading all information from database */
	if(pdt_load_db()!=0)
	{
		LM_ERR("cannot re-load info from database\n");	
		return init_mi_tree( 500, "cannot reload", 13 );
	}

	LM_DBG("prefix for sdomain [%.*s] domain [%.*s] "
			"removed\n", sdomain.len, sdomain.s, sd.len, sd.s);
	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
error:
	return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);
}
Пример #13
0
/**
 * "pdt_add" syntax :
 *   sdomain
 *   prefix
 *   domain
 */
struct mi_root* pdt_mi_add(struct mi_root* cmd_tree, void* param)
{
	db_key_t db_keys[NR_KEYS] = {&sdomain_column, &prefix_column, &domain_column};
	db_val_t db_vals[NR_KEYS];
	db_op_t  db_ops[NR_KEYS] = {OP_EQ, OP_EQ};
	int i= 0;
	str sd, sp, sdomain;
	struct mi_node* node= NULL;

	if(_ptree==NULL)
	{
		LM_ERR("strange situation\n");
		return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
	}

	/* read sdomain */
	node = cmd_tree->node.kids;
	if(node == NULL)
		goto error1;

	sdomain = node->value;
	if(sdomain.s == NULL || sdomain.len== 0)
		return init_mi_tree( 404, "domain not found", 16);

	if(*sdomain.s=='.' )
		 return init_mi_tree( 400, "empty param",11);

	/* read prefix */
	node = node->next;
	if(node == NULL)
		goto error1;

	sp= node->value;
	if(sp.s== NULL || sp.len==0)
	{
		LM_ERR("could not read prefix\n");
		return init_mi_tree( 404, "prefix not found", 16);
	}

	if(*sp.s=='.')
		 return init_mi_tree(400, "empty param", 11);

	while(i< sp.len)
	{
		if(strpos(pdt_char_list.s,sp.s[i]) < 0) 
			return init_mi_tree(400, "bad prefix", 10);
		i++;
	}

	/* read domain */
	node= node->next;
	if(node == NULL || node->next!=NULL)
		goto error1;

	sd= node->value;
	if(sd.s== NULL || sd.len==0)
	{
		LM_ERR("could not read domain\n");
		return init_mi_tree( 400, "domain not found", 16);
	}

	if(*sd.s=='.')
		 return init_mi_tree(400, "empty param", 11);

	
	if(pdt_check_domain!=0 && *_ptree!=NULL
			&& pdt_check_pd(*_ptree, &sdomain, &sp, &sd)==1)
	{
		LM_ERR("(sdomain,prefix,domain) exists\n");
		return init_mi_tree(400,
				"(sdomain,prefix,domain) exists already", 38);
	}
	db_vals[0].type = DB_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = sdomain.s;
	db_vals[0].val.str_val.len = sdomain.len;

	db_vals[1].type = DB_STR;
	db_vals[1].nul = 0;
	db_vals[1].val.str_val.s = sp.s;
	db_vals[1].val.str_val.len = sp.len;

	db_vals[2].type = DB_STR;
	db_vals[2].nul = 0;
	db_vals[2].val.str_val.s = sd.s;
	db_vals[2].val.str_val.len = sd.len;
	
	/* insert a new domain into database */
	if(pdt_dbf.insert(db_con, db_keys, db_vals, NR_KEYS)<0)
	{
		LM_ERR("failed to store new prefix/domain\n");
		return init_mi_tree( 500,"Cannot store prefix/domain", 26);
	}

	/* re-loading all information from database */
	if(pdt_load_db()!=0)
	{
		LM_ERR("cannot re-load info from database\n");	
		goto error;
	}
	
	LM_DBG("new prefix added %.*s-%.*s => %.*s\n",
			sdomain.len, sdomain.s, sp.len, sp.s, sd.len, sd.s);
	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);

	
error:
	if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, NR_KEYS)<0)
		LM_ERR("database/cache are inconsistent\n");
	return init_mi_tree( 500, "could not add to cache", 23 );

error1:
	return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

}
Пример #14
0
/* change the r-uri if it is a PSTN format */
static int prefix2domain(struct sip_msg* msg, int mode, int sd_en)
{
	str *d, p, all={"*",1};
	int plen;
	struct sip_uri uri;
	
	if(msg==NULL)
	{
		LM_ERR("received null msg\n");
		return -1;
	}
	
	/* parse the uri, if not yet */
	if(msg->parsed_uri_ok==0)
		if(parse_sip_msg_uri(msg)<0)
		{
			LM_ERR("failed to parse the R-URI\n");
			return -1;
		}

    /* if the user part begin with the prefix for PSTN users, extract the code*/
	if (msg->parsed_uri.user.len<=0)
	{
		LM_DBG("user part of the message is empty\n");
		return -1;
	}   
    
	if(prefix.len>0)
	{
		if (msg->parsed_uri.user.len<=prefix.len)
		{
			LM_DBG("user part is less than prefix\n");
			return -1;
		}   
		if(strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)
		{
			LM_DBG("PSTN prefix did not matched\n");
			return -1;
		}
	}   
	
	if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len
			&& strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0)
	{
		LM_DBG("PSTN prefix did not matched\n");
		return -1;
			
	}

	p.s   = msg->parsed_uri.user.s + prefix.len;
	p.len = msg->parsed_uri.user.len - prefix.len;

	lock_start_read( pdt_lock );

	if(sd_en==2)
	{	
		/* take the domain from  FROM uri as sdomain */
		if(parse_from_header(msg)<0 ||  msg->from == NULL 
				|| get_from(msg)==NULL)
		{
			LM_ERR("cannot parse FROM header\n");
			goto error;
		}	
		
		memset(&uri, 0, sizeof(struct sip_uri));
		if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0)
		{
			LM_ERR("failed to parse From uri\n");
			goto error;
		}
	
		/* find the domain that corresponds to this prefix */
		plen = 0;
		if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL)
		{
			plen = 0;
			if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL)
			{
				LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
				goto error;
			}
		}
	} else if(sd_en==1) {	
		/* take the domain from  FROM uri as sdomain */
		if(parse_from_header(msg)<0 ||  msg->from == NULL
				|| get_from(msg)==NULL)
		{
			LM_ERR("ERROR cannot parse FROM header\n");
			goto error;
		}	
		
		memset(&uri, 0, sizeof(struct sip_uri));
		if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0)
		{
			LM_ERR("failed to parse From uri\n");
			goto error;
		}
	
		/* find the domain that corresponds to this prefix */
		plen = 0;
		if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL)
		{
			LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
			goto error;
		}
	} else {
		/* find the domain that corresponds to this prefix */
		plen = 0;
		if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL)
		{
			LM_INFO("no prefix found in [%.*s]\n", p.len, p.s);
			goto error;
		}
	}
	
	/* update the new uri */
	if(update_new_uri(msg, plen, d, mode)<0)
	{
		LM_ERR("new_uri cannot be updated\n");
		goto error;
	}

	lock_stop_read( pdt_lock );
	return 1;

error:
	lock_stop_read( pdt_lock );
	return -1;
}
Пример #15
0
/*!
 * \brief Function that is registered as TM callback and called on replies
 *
 * Function that is registered as TM callback and called on replies. It
 * parses the reply and set the appropriate event. This is then used to
 * update the dialog state, run eventual dialog callbacks and save or
 * update the necessary informations about the dialog.
 * \see next_state_dlg
 * \param t transaction, unused
 * \param type type of the entered callback
 * \param param saved dialog structure in the callback
 */
static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
{
    dlg_cell_t *dlg = NULL;
	dlg_iuid_t *iuid = NULL;
    int new_state, old_state, unref, event;
    str tag;
    sip_msg_t *req = param->req;
	sip_msg_t *rpl = param->rpl;

	if (shutdown_done)
		return;
	iuid = (dlg_iuid_t*)(*param->param);
	dlg = dlg_get_by_iuid(iuid);
	if(dlg==0)
		return;

	unref = 0;
	if (type & (TMCB_RESPONSE_IN|TMCB_ON_FAILURE)) {
		/* Set the dialog context so it is available in onreply_route and failure_route*/
		set_current_dialog(req, dlg);
		dlg_set_ctx_iuid(dlg);
		goto done;
	}

	if (type==TMCB_RESPONSE_FWDED) {
		/* The state does not change, but the msg is mutable in this callback*/
		run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		goto done;
	}

	if (type==TMCB_DESTROY)
		event = DLG_EVENT_TDEL;
	else if (param->code<200)
		event = DLG_EVENT_RPL1xx;
	else if (param->code<300)
		event = DLG_EVENT_RPL2xx;
	else
		event = DLG_EVENT_RPL3xx;

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);
	dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state);

	if (new_state==DLG_STATE_EARLY) {
		run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if (old_state!=DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, 1);
		goto done;
	}

	if (new_state==DLG_STATE_CONFIRMED_NA &&
	old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
		LM_DBG("dialog %p confirmed (ACK pending)\n",dlg);

		 if (rpl != FAKED_REPLY) {
			/* get to tag*/
			if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
						|| !rpl->to) ) {
				LM_ERR("bad reply or missing TO hdr :-/\n");
				tag.s = 0;
				tag.len = 0;
			} else {
				tag = get_to(rpl)->tag_value;
				if (tag.s==0 || tag.len==0) {
					LM_ERR("missing TAG param in TO hdr :-/\n");
					tag.s = 0;
					tag.len = 0;
				}
			}

			/* save callee's tag, cseq, contact and record route*/
			if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
				LM_ERR("could not add further info to the dialog\n");
			}
		 } else {
			 LM_ERR("Faked reply!\n");
		 }

		/* set start time */
		dlg->start_ts = (unsigned int)(time(0));

		/* save the settings to the database,
		 * if realtime saving mode configured- save dialog now
		 * else: the next time the timer will fire the update*/
		dlg->dflags |= DLG_FLAG_NEW;
		if ( dlg_db_mode==DB_MODE_REALTIME )
			update_dialog_dbinfo(dlg);

		if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
			LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* dialog pointer inserted in timer list */
			dlg_ref(dlg, 1);
		}

		/* dialog confirmed (ACK pending) */
		run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);

		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if (unref) dlg_unref(dlg, unref);
		if_update_stat(dlg_enable_stats, active_dlgs, 1);
		goto done;
	}

	if(new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
		/* set end time */
		dlg->end_ts = (unsigned int)(time(0));
	}

	if ( new_state==DLG_STATE_DELETED
				&& (old_state==DLG_STATE_UNCONFIRMED
					|| old_state==DLG_STATE_EARLY) ) {
		LM_DBG("dialog %p failed (negative reply)\n", dlg);
		/* dialog setup not completed (3456XX) */
		run_dlg_callbacks( DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
		if(dlg_wait_ack==1)
			dlg_set_tm_waitack(t, dlg);
		/* do unref */
		if (unref)
			dlg_unref(dlg, unref);
		if (old_state==DLG_STATE_EARLY)
			if_update_stat(dlg_enable_stats, early_dlgs, -1);

		if_update_stat(dlg_enable_stats, failed_dlgs, 1);

		goto done;
	}

	if (unref) dlg_unref(dlg, unref);

done:
	/* unref due to dlg_get_by_iuid() */
	dlg_release(dlg);
	return;
}
/**
 * Shut down the database module.
 * No function should be called after this
 * \param _h handle to the closed connection
 * \return zero on success, negative value on failure
 */
void erlang_srdb1_close(db1_con_t* _h)
{
	LM_DBG("erlang_erlang_srdb1_close %p \n",_h);
	db_do_close(_h, erlang_srdb1_free_connection);
}
Пример #17
0
/*!
 * \brief Create a new dialog from a sip message
 *
 * Create a new dialog from a SIP message, register a callback
 * to keep track of the dialog with help of the tm module.
 * This function is either called from the request callback, or
 * from the dlg_manage function in the configuration script.
 * \see dlg_onreq
 * \see w_dlg_manage
 * \param req SIP message
 * \param t transaction
 * \param run_initial_cbs if set zero, initial callbacks are not executed
 * \return 0 on success, -1 on failure
 */ 
int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
{
	dlg_cell_t *dlg;
	str s;
	str callid;
    str ftag;
    str ttag;
    str req_uri;
    unsigned int dir;

	dlg = dlg_get_ctx_dialog();
    if(dlg != NULL) {
		dlg_release(dlg);
        return -1;
	}

	if(req->first_line.u.request.method_value != METHOD_INVITE)
		return -1;

    if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
        LM_WARN("pre-matching failed\n");
        return -1;
    }

    if(ttag.s!=0 && ttag.len!=0)
        return -1;

    if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
        LM_ERR("error - cannot print the r-uri format\n");
        return -1;
    }
    trim(&req_uri);

	dir = DLG_DIR_NONE;
	/* search dialog by SIP attributes
	 * - hash table slot is left locked  */
	dlg = dlg_search(&callid, &ftag, &ttag, &dir);
	if(dlg) {
		if (detect_spirals) {
			if (spiral_detected == 1) {
				dlg_hash_release(&callid);
				return 0;
			}

			if ( dlg->state != DLG_STATE_DELETED ) {
				LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
					callid.len, callid.s);
				spiral_detected = 1;

				if (run_initial_cbs)
					run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
							DLG_DIR_DOWNSTREAM, 0);
				/* set ctx dlg id shortcuts */
				_dlg_ctx.iuid.h_entry = dlg->h_entry;
				_dlg_ctx.iuid.h_id = dlg->h_id;
				/* search_dlg() has incremented the ref count by 1 */
				dlg_release(dlg);
				dlg_hash_release(&callid);
				return 0;
			}
			dlg_release(dlg);
		}
    }
    spiral_detected = 0;

    dlg = build_new_dlg (&callid /*callid*/,
                         &(get_from(req)->uri) /*from uri*/,
                         &(get_to(req)->uri) /*to uri*/,
                         &ftag/*from_tag*/,
                         &req_uri /*r-uri*/ );

	if (dlg==0) {
		dlg_hash_release(&callid);
		LM_ERR("failed to create new dialog\n");
		return -1;
	}

	/* save caller's tag, cseq, contact and record route*/
	if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
			&(get_from(req)->tag_value)) !=0) {
		dlg_hash_release(&callid);
		LM_ERR("could not add further info to the dialog\n");
		shm_free(dlg);
		return -1;
	}

	/* Populate initial varlist: */
	dlg->vars = get_local_varlist_pointer(req, 1);

	/* after dlg_search() slot was kept locked */
	link_dlg(dlg, 0, 1);
	/* unlock after dlg_search() */
	dlg_hash_release(&callid);

	dlg->lifetime = get_dlg_timeout(req);
	s.s   = _dlg_ctx.to_route_name;
	s.len = strlen(s.s);
	dlg_set_toroute(dlg, &s);
	dlg->sflags |= _dlg_ctx.flags;
	dlg->iflags |= _dlg_ctx.iflags;

	if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
		dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;

    if (run_initial_cbs)  run_create_callbacks( dlg, req);

	/* first INVITE seen (dialog created, unconfirmed) */
	if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
			add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
		LM_ERR("failed to add RR param\n");
		goto error;
	}

    if_update_stat( dlg_enable_stats, processed_dlgs, 1);

	_dlg_ctx.cpid = my_pid();
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;
    set_current_dialog(req, dlg);

	return 0;

error:
	if (!spiral_detected)
		dlg_unref(dlg, 1);               // undo ref regarding linking
	return -1;
}
Пример #18
0
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state, char service_routes[][MAXROUTESIZE], int num_service_routes) {
	ppublic_t * p;
	contact_body_t *b = 0;
	contact_t *ct;
	pcontact_info_t search_ci;
	str received_host = {0, 0};
	char srcip[50];
	struct via_body *vb;
	unsigned short port, proto;
	str host;
	sip_uri_t contact_uri;
	int mustRetryViaSearch = 0;
	int mustRetryReceivedSearch = 0;

	LM_DBG("number of service routes to look for is %d\n", num_service_routes);
    b = cscf_parse_contacts(_m);

    if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) {
		mustRetryViaSearch = 1;
		mustRetryReceivedSearch = 1;
        LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n");
        ct = b->contacts;
        host = ct->uri;
        if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) {
            LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s);
            return NULL;
        }
        host = contact_uri.host;
        port = contact_uri.port_no ? contact_uri.port_no : 5060;
        proto = contact_uri.proto;
        if (proto == 0) {
            LM_DBG("Contact protocol not specified - using received\n");
            proto = _m->rcv.proto;
        }
    } else {
        if (_m->first_line.type == SIP_REPLY)
            LM_DBG("This is a reply but we are forced to use the via header\n");
        else
            LM_DBG("This is a request - using first via to find contact\n");

        vb = cscf_get_ue_via(_m);
        host = vb->host;
        port = vb->port ? vb->port : 5060;
        proto = vb->proto;
    }

    LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port);

    received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip));
    received_host.s = srcip;

//    if (_m->id != current_msg_id) {
        current_msg_id = _m->id;
        c = NULL;
	//search_ci.reg_state = PCONTACT_REGISTERED;          //we can do this because this function is always called expecting a REGISTERED contact
	memset(&search_ci, 0, sizeof(struct pcontact_info));
    search_ci.reg_state = reg_state;
	search_ci.received_host.s = received_host.s;
	search_ci.received_host.len = received_host.len;
	search_ci.received_port = _m->rcv.src_port;
	search_ci.received_proto = _m->rcv.proto;
	search_ci.searchflag = SEARCH_RECEIVED;
	search_ci.num_service_routes = 0;
	if (is_registered_fallback2ip == 1) {
		search_ci.searchflag = SEARCH_NORMAL;
	} 
	search_ci.via_host = host;
	search_ci.via_port = port;
	search_ci.via_prot = proto;
	search_ci.aor.s = 0;
	search_ci.aor.len = 0;
	
	int size = num_service_routes==0?1:num_service_routes;
	str s_service_routes[size];
	int i;
	for (i=0;i<num_service_routes;i++) {
		s_service_routes[i].s = service_routes[i];
		s_service_routes[i].len = strlen(service_routes[i]);
		LM_DBG("Setting service routes str for pos %d to %.*s", i, s_service_routes[i].len, s_service_routes[i].s);
	}
	if (num_service_routes > 0) {
		LM_DBG("asked to search for specific service routes...\n");
		search_ci.service_routes = s_service_routes;
		search_ci.num_service_routes = num_service_routes;
		search_ci.extra_search_criteria = SEARCH_SERVICE_ROUTES;
	}

//	b = cscf_parse_contacts(_m);
tryagain:
	if (b && b->contacts) {
		for (ct = b->contacts; ct; ct = ct->next) {
			search_ci.aor = ct->uri;
			if (ul.get_pcontact(_d, &search_ci, &c) == 0) {
				if (checkcontact(_m, c) != 0) {
					c = NULL;
				} else {
					break;
				}
			}
		}
	} else {
		LM_WARN("No contact-header found...\n");
	}

	if ((c == NULL) && (is_registered_fallback2ip == 1)) {
		LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n");
		//			received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
		//			received_host.s = srcip;
		search_ci.searchflag = SEARCH_RECEIVED;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
			LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto);
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	if ((c == NULL) && (is_registered_fallback2ip == 2)) {
		LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n");
		search_ci.searchflag = SEARCH_NORMAL;
		if (ul.get_pcontact(_d, &search_ci, &c) == 1) {
		} else {
			if (checkcontact(_m, c) != 0) {
				c = NULL;
			}
		}
	}

	asserted_identity = NULL;
	registration_contact = NULL;
	if (c) {
                LM_DBG("Trying to set asserted identity field");
		registration_contact = &c->contact_user;
		p = c->head;
		while (p) {
                        LM_DBG("Checking through contact users");
			if (p->is_default == 1) {
                            LM_DBG("Found default contact user so setting asserted identity");
                            asserted_identity = &p->public_identity;
                        }
			p = p->next;
		}
	}
        if (asserted_identity != NULL && asserted_identity->len > 0) {
            LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s);
        } else {
            LM_DBG("Asserted identity not set");
        }
            
    
//    LM_DBG("pcontact flag is [%d]\n", c->flags);
//    if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) {
//        LM_DBG("we have a contact that was read fresh from the DB....\n");
//    }
	if (!c && mustRetryViaSearch) {
		LM_DBG("This is a reply so we will search using the last via once more...\n");
		vb = cscf_get_ue_via(_m);
		search_ci.via_host = vb->host;
		search_ci.via_port = vb->port ? vb->port : 5060;
		search_ci.via_prot = vb->proto;
		mustRetryViaSearch = 0;
		goto tryagain;
	}
	
	if (!c && mustRetryReceivedSearch) {
		LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n");
		search_ci.via_host = received_host;
		search_ci.via_port = _m->rcv.src_port;
		search_ci.via_prot = _m->rcv.proto;
		mustRetryReceivedSearch = 0;
		goto tryagain;
	}

    return c;
}
Пример #19
0
/*
 * IMPORTANT: if a dialog reference is returned, the dialog hash entry will
   be kept locked when this function returns
   NOTE: if a reply tree is returned, no dialog reference is returned.
 */
static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree,
			struct dlg_cell **dlg_p, unsigned int *idx, unsigned int *cnt)
{
	struct mi_node* node;
	struct dlg_entry *d_entry;
	struct dlg_cell *dlg;
	str *p1;
	str *p2;
	unsigned int h_entry;

	node = cmd_tree->node.kids;
	if (node == NULL) {
		/* no parameters at all */
		*dlg_p = NULL;
		*idx = *cnt = 0;
		return NULL;
	}

	/* we have params -> get p1 and p2 */
	p1 = &node->value;
	LM_DBG("p1='%.*s'\n", p1->len, p1->s);

	node = node->next;
	if ( !node || !node->value.s || !node->value.len) {
		p2 = NULL;
	} else {
		p2 = &node->value;
		LM_DBG("p2='%.*s'\n", p2->len, p2->s);
		if ( node->next!=NULL )
			return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
	}

	/* check the params */
	if (p2 && str2int(p1,idx)==0 && str2int(p2,cnt)==0) {
		/* 2 numerical params -> index and counter */
		*dlg_p = NULL;
		return NULL;
	}

	*idx = *cnt = 0;

        if (!p1->s)
                return init_mi_tree( 400, "Invalid Call-ID specified", 25);

	h_entry = dlg_hash( p1/*callid*/ );

	d_entry = &(d_table->entries[h_entry]);
	dlg_lock( d_table, d_entry);

	for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) {
		if (match_downstream_dialog( dlg, p1/*callid*/, p2/*from_tag*/)==1) {
			if (dlg->state==DLG_STATE_DELETED) {
				*dlg_p = NULL;
				break;
			} else {
				*dlg_p = dlg;
				return 0;
			}
		}
	}
	dlg_unlock( d_table, d_entry);

	return init_mi_tree( 404, MI_SSTR("No such dialog"));
}
Пример #20
0
/**
 * Check, if a user-agent follows the indicated service-routes
 */
int check_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct sip_uri uri;
	int i;
	struct hdr_field *hdr;
	rr_t *r;
	char routes[MAXROUTES][MAXROUTESIZE];
	unsigned int num_routes = 0;
	
	struct via_body * vb;
	unsigned short port;
	unsigned short proto;
	/* Contact not found => not following service-routes */
//	if (c == NULL) return -1;

	/* Search for the first Route-Header: */
	if (find_first_route(_m) < 0) return -1;

//	LM_DBG("Got %i Route-Headers.\n", c->num_service_routes);

	vb = cscf_get_ue_via(_m);
	port = vb->port?vb->port:5060;
	proto = vb->proto;
	
	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &vb->host, port, proto);
    
	if (_m->route) {
		hdr = _m->route;
		r = (rr_t*)hdr->parsed;
		//get rid of ourselves from route header
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) 
					r = NULL;
				else 
					r = (rr_t*)hdr->parsed;
				
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			
			int i = 0;
			while (r) {
				memset(routes[i],0,MAXROUTESIZE);
				memcpy(routes[i], r->nameaddr.uri.s, r->nameaddr.uri.len);
				
				if (find_next_route(_m, &hdr) != 0) 
					r = NULL;
				else 
					r = (rr_t*)hdr->parsed;
				
				i += 1;
				num_routes += 1;
			}
			
			LM_DBG("num_routes is %d\n", num_routes);
			for (i=0; i<num_routes; i++) {
				LM_DBG("route %d for checking is %s\n", i, routes[i]);
			}
			pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, routes, num_routes);
			if (!c) {
				LM_DBG("no contact found in usrloc when checking for service route\n");
				goto error;
			}
			
			LM_DBG("we have a contact which satisifes the routes...\n");
			ul.unlock_udomain(_d, &vb->host, port, proto);
			return 1;
		}
	} else {
		LM_DBG("Request doesn't have any route headers to check service-route...ignoring\n");
		goto error;
	}
	
	pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, 0, 0);
	if (!c) {
		LM_DBG("no contact found in usrloc when checking for service route\n");
		goto error;
	}

	/* Check the route-set: */
	if (_m->route) {
		hdr = _m->route;
		LM_DBG("hdr is %p\n", hdr);
		/* Check, if the first host is ourself: */
		r = (rr_t*)hdr->parsed;
		if (r) {
			LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			/* Skip first headers containing myself: */
			while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0)
			  && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) {
				LM_DBG("Self\n");
				/* Check for more headers and fail, if it was the last one
				   Check, if service-routes are indicated.
				   If yes, request is not following service-routes */
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;

				if (!r && (c->num_service_routes > 0)) {
					LM_DBG("Not enough route-headers in Message\n");
					goto error;
				}
				LM_DBG("hdr is %p\n", hdr);
				LM_DBG("r is %p\n", r);
				if (r)
					LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
			}
			LM_DBG("We have %d service-routes\n", c->num_service_routes);
			/* Then check the following headers: */
			for (i=0; i< c->num_service_routes; i++) {
				LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s);

				/* No more Route-Headers? Not following service-routes */
				if (!r) {
					LM_DBG("No more route headers in message.\n");
					 goto error;
				}
				
				LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s);
 				
				/* Check length: */
				if (r->nameaddr.uri.len != c->service_routes[i].len) {
					LM_DBG("Length does not match.\n");
					 goto error;
				}
				/* Check contents: */
				if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) {
					LM_DBG("String comparison failed.\n");
					 goto error;
				}
				if (find_next_route(_m, &hdr) != 0) r = NULL;
				else r = (rr_t*)hdr->parsed;
			}

			/* Check, if it was the last route-header in the message: */
			if (r) {
				LM_DBG("Too many route headers in message.\n");
				 goto error;
			}
		} else {
			LM_WARN("Strange: Route-Header is present, but not parsed?!?");
			if (c->num_service_routes > 0) goto error;
		}
	} else {
		LM_DBG("No route header in Message.\n");
		/* No route-header? Check, if service-routes are indicated.
		   If yes, request is not following service-routes */
		if (c->num_service_routes > 0) goto error;
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return -1;
}
Пример #21
0
void next_state_dlg(struct dlg_cell *dlg, int event, int dir, int *old_state,
		int *new_state, int *unref, int last_dst_leg, char is_replicated)
{
	struct dlg_entry *d_entry;

	d_entry = &(d_table->entries[dlg->h_entry]);
	*unref = 0;

	dlg_lock( d_table, d_entry);

	*old_state = dlg->state;

	switch (event) {
		case DLG_EVENT_TDEL:
			switch (dlg->state) {
				case DLG_STATE_UNCONFIRMED:
				case DLG_STATE_EARLY:
					dlg->state = DLG_STATE_DELETED;
					unref_dlg_unsafe(dlg,1,d_entry); /* unref from TM CBs*/
					*unref = 1; /* unref from hash -> t failed */
					break;
				case DLG_STATE_CONFIRMED_NA:
				case DLG_STATE_CONFIRMED:
					unref_dlg_unsafe(dlg,1,d_entry); /* unref from TM CBs*/
					break;
				case DLG_STATE_DELETED:
					/* as the dialog aleady is in DELETE state, it is
					dangerous to directly unref it from here as it might
					be last ref -> dialog will be destroied and we will end up
					with a dangling pointer :D - bogdan */
					*unref = 1; /* unref from TM CBs*/
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_RPL1xx:
			switch (dlg->state) {
				case DLG_STATE_UNCONFIRMED:
				case DLG_STATE_EARLY:
					dlg->state = DLG_STATE_EARLY;
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_RPL3xx:
			switch (dlg->state) {
				case DLG_STATE_UNCONFIRMED:
				case DLG_STATE_EARLY:
					dlg->state = DLG_STATE_DELETED;
					*unref = 1; /* unref from hash -> t failed */
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_RPL2xx:
			switch (dlg->state) {
				case DLG_STATE_DELETED:
					if (dlg->flags&DLG_FLAG_HASBYE) {
						log_next_state_dlg(event, dlg);
						break;
					}
					ref_dlg_unsafe(dlg,1); /* back in hash */
				case DLG_STATE_UNCONFIRMED:
				case DLG_STATE_EARLY:
					dlg->state = DLG_STATE_CONFIRMED_NA;
					break;
				case DLG_STATE_CONFIRMED_NA:
				case DLG_STATE_CONFIRMED:
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_REQACK:
			switch (dlg->state) {
				case DLG_STATE_CONFIRMED_NA:
					dlg->state = DLG_STATE_CONFIRMED;
					break;
				case DLG_STATE_CONFIRMED:
					break;
				case DLG_STATE_DELETED:
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_REQBYE:
			switch (dlg->state) {
				case DLG_STATE_CONFIRMED_NA:
				case DLG_STATE_CONFIRMED:
					if (dir == DLG_DIR_DOWNSTREAM &&
					last_dst_leg!=dlg->legs_no[DLG_LEG_200OK] )
						/* to end the call, the BYE must be received
						 * on the same leg as the 200 OK for INVITE */
						break;
					dlg->flags |= DLG_FLAG_HASBYE;
					dlg->state = DLG_STATE_DELETED;
					*unref = 1; /* unref from hash -> dialog ended */
					break;
				case DLG_STATE_DELETED:
					break;
				default:
					/* only case for BYEs in early or unconfirmed states
					 * is for requests generate by caller or callee.
					 * We never internally generate BYEs for early dialogs
					 *
					 * RFC says caller may send BYEs for early dialogs,
					 * while the callee side MUST not send such requests*/
					if (last_dst_leg == 0)
						log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_REQPRACK:
			switch (dlg->state) {
				case DLG_STATE_EARLY:
				case DLG_STATE_CONFIRMED_NA:
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		case DLG_EVENT_REQ:
			switch (dlg->state) {
				case DLG_STATE_EARLY:
				case DLG_STATE_CONFIRMED_NA:
				case DLG_STATE_CONFIRMED:
					break;
				default:
					log_next_state_dlg(event, dlg);
			}
			break;
		default:
			LM_INFO("unknown event %d in state %d "
				"for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n",
				event, dlg->state, dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg_leg_print_info( dlg, DLG_CALLER_LEG, tag),
				dlg_leg_print_info( dlg, callee_idx(dlg), tag));
	}
	*new_state = dlg->state;

	dlg_unlock( d_table, d_entry);

	if (*old_state != *new_state)
		raise_state_changed_event(  dlg->h_entry, dlg->h_id,
			(unsigned int)(*old_state), (unsigned int)(*new_state) );

	 if ( !is_replicated && dialog_replicate_cluster &&
	(*old_state==DLG_STATE_CONFIRMED_NA || *old_state==DLG_STATE_CONFIRMED) &&
	dlg->state==DLG_STATE_DELETED )
		replicate_dialog_deleted(dlg);


	LM_DBG("dialog %p changed from state %d to "
		"state %d, due event %d\n",dlg,*old_state,*new_state,event);
}
Пример #22
0
/**
 * Force Service routes (upon request)
 */
int force_service_routes(struct sip_msg* _m, udomain_t* _d) {
	struct hdr_field *it;
	int i;
	str new_route_header;
	struct lump* lmp = NULL;
	char * buf;
	pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED,0 ,0);
//	char srcip[20];
//	str received_host;
        struct via_body* vb;
        unsigned short port;
        unsigned short proto;
	
	// Contact not found => not following service-routes
	if (c == NULL) return -1;

	/* we need to be sure we have seen all HFs */
	parse_headers(_m, HDR_EOH_F, 0);

        vb = cscf_get_ue_via(_m);
        port = vb->port?vb->port:5060;
        proto = vb->proto;
        
	/* Save current buffer */
	buf = _m->buf;

	// Delete old Route headers:
	if (_m->route) {
		for (it = _m->route; it; it = it->next) {
			if (it->type == HDR_ROUTE_T) {
				if ((lmp = del_lump(_m, it->name.s - buf, it->len, HDR_ROUTE_T)) == 0) {
					LM_ERR("del_lump failed \n");
					return -1;
				}
			}
		}
	}

	/* Reset dst_uri if previously set either by loose route or manually */
	if (_m->dst_uri.s && _m->dst_uri.len) {
		pkg_free(_m->dst_uri.s);
		_m->dst_uri.s = NULL;
		_m->dst_uri.len = 0;
	}
	
//	received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip));
//	received_host.s = srcip;

	/* Lock this record while working with the data: */
	ul.lock_udomain(_d, &vb->host, port, proto);

	if (c->num_service_routes > 0) {
		/* Create anchor for new Route-Header: */
		lmp = anchor_lump(_m, _m->headers->name.s - buf,0,0);
		if (lmp == 0) {
			LM_ERR("Failed to get anchor lump\n");
			goto error;
		}	
		/* Calculate the length: */
		new_route_header.len = route_start.len +
			route_end.len + (c->num_service_routes-1) * route_sep.len;

		for(i=0; i< c->num_service_routes; i++)
			new_route_header.len+=c->service_routes[i].len;		
		/* Allocate the memory for this new header: */
		new_route_header.s = pkg_malloc(new_route_header.len);
		if (!new_route_header.s) {
			LM_ERR("Error allocating %d bytes\n", new_route_header.len);
			goto error;
		}
		
		/* Construct new header */
		new_route_header.len = 0;
		STR_APPEND(new_route_header, route_start);
		for(i=0; i < c->num_service_routes; i++) {
			if (i) STR_APPEND(new_route_header, route_sep);
			STR_APPEND(new_route_header, c->service_routes[i]);
		}
		STR_APPEND(new_route_header, route_end);

		LM_DBG("Setting route header to <%.*s> \n", new_route_header.len, new_route_header.s);

		if ((lmp = insert_new_lump_after(lmp, new_route_header.s, new_route_header.len, HDR_ROUTE_T)) == 0) {
			LM_ERR("Error inserting new route set\n");
			pkg_free(new_route_header.s);
			goto error;
		}

		LM_DBG("Setting dst_uri to <%.*s> \n", c->service_routes[0].len,
			c->service_routes[0].s);

		if (set_dst_uri(_m, &c->service_routes[0]) !=0 ) {
			LM_ERR("Error setting new dst uri\n");
			goto error;
		}
	}
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return 1;
error:
	/* Unlock domain */
	ul.unlock_udomain(_d, &vb->host, port, proto);
	return -1;
	
    return 1;
}
Пример #23
0
static inline int get_resource_list(str *username, str *domain, str *filename, str *selector,
                                    xmlNodePtr *rl_node, xmlDocPtr *xmldoc)
{
        static char path_buf[MAX_PATH_LEN+1];

        int checked = 0;
        str path;
        str *doc = NULL;
        str *etag = NULL;
	xmlXPathContextPtr xpathCtx = NULL;
	xmlXPathObjectPtr xpathObj = NULL;

	if (filename==NULL || username==NULL || domain==NULL)
	{
		LM_ERR("invalid parameters\n");
		return -1;
	}

        if (xcapDbGetDoc(username, domain, RESOURCE_LISTS, filename, NULL, &doc, &etag) < 0)
        {
		LM_DBG("No rl document found\n");
                return -1;
        }
	LM_DBG("rl document:\n%.*s\n", doc->len, doc->s);

	path.s = path_buf;
	path.len = 0;
	if (selector->s) {
            while (checked < selector->len && path.len <= MAX_PATH_LEN)
            {
                    if (selector->s[checked] == '/')
                    {
                            memcpy(path.s+path.len, "/xmlns:", 7);
                            path.len += 7;
                    }
                    else
                    {
                            path.s[path.len++] = selector->s[checked];
                    }
                    checked++;
            }
            path.s[path.len] = '\0';
            LM_DBG("path: %.*s", path.len, path.s);
        }

	*xmldoc = xmlParseMemory(doc->s, doc->len);
	if (*xmldoc == NULL)
	{
		LM_ERR("while parsing XML memory\n");
		goto error;
	}

	if(path.len == 0)
	{
		LM_ERR("no path specified\n");
		goto error;
	}

        /* TODO: move this to xcap module? */
        xpathCtx = xmlXPathNewContext(*xmldoc);
        if (xpathCtx == NULL)
        {
                LM_ERR("unable to create new XPath context");
                goto error;
        }

        if (xmlXPathRegisterNs(xpathCtx, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:resource-lists") != 0)
        {
                LM_ERR("unable to register xmlns\n");
                goto error;
        }

        xpathObj = xmlXPathEvalExpression(BAD_CAST path.s, xpathCtx);
        if (xpathObj == NULL)
        {
                LM_ERR("unable to evaluate path\n");
                goto error;
        }

        if (xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr <= 0)
        {
                LM_ERR("no nodes found\n");
                goto error;
        }
        if (xpathObj->nodesetval->nodeTab[0] != NULL && xpathObj->nodesetval->nodeTab[0]->type != XML_ELEMENT_NODE)
        {
                LM_ERR("no nodes of the correct type found\n");
                goto error;

        }

        *rl_node = xpathObj->nodesetval->nodeTab[0];

        xmlXPathFreeObject(xpathObj);
        xmlXPathFreeContext(xpathCtx);

        pkg_free(doc->s);
        pkg_free(doc);
        pkg_free(etag->s);
        pkg_free(etag);

        return 0;

error:
        if (doc != NULL)
        {
                if (doc->s != NULL)
                        pkg_free(doc->s);
                pkg_free(doc);
        }
        if (etag != NULL)
        {
                if (etag->s != NULL)
                        pkg_free(etag->s);
                pkg_free(etag);
        }
	if (xpathObj)
		xmlXPathFreeObject(xpathObj);
	if (xpathCtx)
		xmlXPathFreeContext(xpathCtx);
	if (*xmldoc)
		xmlFreeDoc(*xmldoc);
	return -1;
}
Пример #24
0
/*!
 * \brief Function that is registered as RR callback for dialog tracking
 *
 * Function that is registered as RR callback for dialog tracking. It
 * sets the appropriate events after the SIP method and run the state
 * machine to update the dialog state. It updates then the saved
 * dialogs and also the statistics.
 * \param req SIP request
 * \param route_params record-route parameter
 * \param param unused
 */
void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
{
	dlg_cell_t *dlg;
	dlg_iuid_t *iuid;
	str val, callid, ftag, ttag;
	int h_entry, h_id, new_state, old_state, unref, event, timeout, reset;
	unsigned int dir;
	int ret = 0;

	dlg = dlg_get_ctx_dialog();
	if (dlg!=NULL) {
		dlg_release(dlg);
		return;
	}

	/* skip initial requests - they may end up here because of the
	 * preloaded route */
	if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
		LM_ERR("bad request or missing TO hdr :-/\n");
		return;
	}
	if ( get_to(req)->tag_value.len==0 )
		return;

	dlg = 0;
	dir = DLG_DIR_NONE;

	if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
		if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
			LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
			if (seq_match_mode==SEQ_MATCH_STRICT_ID )
				return;
		} else {
			LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);

			if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
				return;

			dlg = dlg_lookup(h_entry, h_id);
			if (dlg==0) {
				LM_WARN("unable to find dialog for %.*s "
					"with route param '%.*s' [%u:%u]\n",
					req->first_line.u.request.method.len,
					req->first_line.u.request.method.s,
					val.len,val.s, h_entry, h_id);
				if (seq_match_mode==SEQ_MATCH_STRICT_ID )
					return;
			} else {
				if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);
					return;
				}
				if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
					LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
							"ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
							req->first_line.u.request.method.len,
							req->first_line.u.request.method.s,
							callid.len, callid.s, callid.len,
							ftag.len, ftag.s, ftag.len,
							ttag.len, ttag.s, ttag.len, dir);
					LM_WARN("dialog identification elements are callid='%.*s'/%d, "
							"caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
							dlg->callid.len, dlg->callid.s, dlg->callid.len,
							dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
							dlg->tag[DLG_CALLER_LEG].len,
							dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
							dlg->tag[DLG_CALLEE_LEG].len);
					// lookup_dlg has incremented the ref count by 1
					dlg_release(dlg);

					// Reset variables in order to do a lookup based on SIP-Elements.
					dlg = 0;
					dir = DLG_DIR_NONE;

					if (seq_match_mode==SEQ_MATCH_STRICT_ID )
						return;
				}
			}
		}
	}

	if (dlg==0) {
		if (pre_match_parse(req, &callid, &ftag, &ttag, 1)<0)
			return;
		/* TODO - try to use the RR dir detection to speed up here the
		 * search -bogdan */
		dlg = get_dlg(&callid, &ftag, &ttag, &dir);
		if (dlg==0){
			LM_DBG("Callid '%.*s' not found\n",
				req->callid->body.len, req->callid->body.s);
			return;
		}
	}

    /* set current dialog - re-use ref increment from dlg_get() above */
    set_current_dialog( req, dlg);
    _dlg_ctx.iuid.h_entry = dlg->h_entry;
    _dlg_ctx.iuid.h_id = dlg->h_id;

	if(dlg->iflags & DLG_IFLAG_CSEQ_DIFF) {
		if(dlg_cseq_refresh(req, dlg, dir)<0) {
			LM_ERR("failed to refresh cseq update\n");
		}
	}

	if (req->first_line.u.request.method_value != METHOD_ACK) {
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL)
		{
			/* register callback for the replies of this request */
			if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_IN|TMCB_ON_FAILURE,
					dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register TMCB (3)\n");
				shm_free(iuid);
			}
			iuid = NULL;
		}
	}

	/* run state machine */
	switch ( req->first_line.u.request.method_value ) {
		case METHOD_PRACK:
			event = DLG_EVENT_REQPRACK; break;
		case METHOD_ACK:
			event = DLG_EVENT_REQACK; break;
		case METHOD_BYE:
			event = DLG_EVENT_REQBYE; break;
		default:
			event = DLG_EVENT_REQ;
	}

	next_state_dlg( dlg, event, &old_state, &new_state, &unref);

	CURR_DLG_ID = req->id;
	CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
	CURR_DLG_STATUS = new_state;

	dlg_run_event_route(dlg, req, old_state, new_state);

	/* delay deletion of dialog until transaction has died off in order
	 * to absorb in-air messages */
	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
		/* set end time */
		dlg->end_ts = (unsigned int)(time(0));
		iuid = dlg_get_iuid_shm_clone(dlg);
		if(iuid!=NULL) {
			if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
					unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) {
				LM_ERR("failed to register deletion delay function\n");
				shm_free(iuid);
			} else {
				dlg_ref(dlg, 1);
			}
		}
	}

	if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED)
		dlg_ka_add(dlg);

	/* run actions for the transition */
	if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
	old_state!=DLG_STATE_DELETED) {
		LM_DBG("BYE successfully processed\n");
		/* remove from timer */
		ret = remove_dialog_timer(&dlg->tl);
		if (ret < 0) {
			LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else if (ret > 0) {
			LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
				"with clid '%.*s' and tags '%.*s' '%.*s'\n",
				dlg, dlg->h_entry, dlg->h_id,
				dlg->callid.len, dlg->callid.s,
				dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
				dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
		} else {
			/* one extra unref due to removal from timer list */
			unref++;
		}
		/* dialog terminated (BYE) */
        dlg_terminated( req, dlg, dir);

		dlg_unref(dlg, unref);

		_dlg_ctx.cpid = my_pid();
		_dlg_ctx.expect_t = 1;
		dlg_set_ctx_iuid(dlg);

		if_update_stat( dlg_enable_stats, active_dlgs, -1);
		goto done;
	}

	if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
	&& (new_state==DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {

		timeout = get_dlg_timeout(req);
		if (timeout!=default_timeout) {
			dlg->lifetime = timeout;
		}
		reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset);

		if ((new_state!=DLG_STATE_EARLY) && (old_state!=DLG_STATE_CONFIRMED || reset)) {
			if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
				LM_ERR("failed to update dialog lifetime\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(event != DLG_EVENT_REQACK) {
			if(dlg_refresh_contacts(dlg, req, dir)!=0) {
				LM_ERR("contacts update failed\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
			if(update_cseqs(dlg, req, dir)!=0) {
				LM_ERR("cseqs update failed\n");
			} else {
				dlg->dflags |= DLG_FLAG_CHANGED;
			}
		}
		if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
			update_dialog_dbinfo(dlg);
		}

		if (old_state==DLG_STATE_CONFIRMED_NA) {
			LM_DBG("confirming ACK successfully processed\n");

			/* confirming ACK request */
			run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
		} else {
			LM_DBG("sequential request successfully processed\n");

			/* within dialog request */
			run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);
			if (add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
				LM_ERR("failed to add RR param\n");
				goto done;
			}

			if ( (event!=DLG_EVENT_REQACK) &&
					(dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
				iuid = dlg_get_iuid_shm_clone(dlg);
				if(iuid!=NULL)
				{
					/* register callback for the replies of this request */
					if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
							(dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:
														dlg_seq_up_onreply,
							(void*)iuid, dlg_iuid_sfree)<0 ) {
						LM_ERR("failed to register TMCB (2)\n");
						shm_free(iuid);
					}
				}
			}
		}
	}

	if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
		dlg->dflags |= DLG_FLAG_CHANGED;
		if(dlg_db_mode == DB_MODE_REALTIME)
			update_dialog_dbinfo(dlg);
	}

done:
	dlg_release(dlg);
	return;
}
Пример #25
0
static void oma_get_rules(subs_t* subs, xmlDocPtr xcap_tree, xcap_rule_t **rules)
{
	int apply_rule = 0, current_node_type = -1;
	str w_uri = {0, 0};
	xmlNodePtr ruleset_node = NULL, cond_node = NULL;
	xmlNodePtr node1 = NULL, node2 = NULL, current_node = NULL;
	xcap_rule_t *tmp_rule = NULL;
	xcap_rule_t *identity_rules = NULL, *external_rules = NULL, *anonymous_rules = NULL, *other_identity_rules = NULL;
	xcap_rule_t *identity_tail = NULL, *external_tail = NULL, *anonymous_tail = NULL, *other_identity_tail = NULL;

        *rules = NULL;

	uandd_to_uri(subs->from_user, subs->from_domain, &w_uri);
	if(w_uri.s == NULL)
	{
		LM_ERR("while creating uri\n");
		return;
	}

	ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL);
	if(ruleset_node == NULL)
	{
		LM_ERR("ruleset_node not found\n");
		pkg_free(w_uri.s);
	        return;
	}

	for(node1 = ruleset_node->children; node1; node1 = node1->next)
	{
		if(xmlStrcasecmp(node1->name, (unsigned char*)"text")==0)
		        continue;

		cond_node = xmlNodeGetChildByName(node1, "conditions");
		if(cond_node == NULL)
		{
			LM_WARN("condition node not found\n");
			continue;
		}

                apply_rule = 0;
                current_node = node1;
                current_node_type = -1;

                for(node2 = cond_node->children; node2; node2 = node2->next)
                {
                        if(xmlStrcasecmp(node2->name, (unsigned char*)"identity") == 0)
                        {
                                current_node_type = IDENTITY_RULE;
                                apply_rule = oma_match_identity_condition(node2, subs, &w_uri);
                                break;
                        }
                        else if(xmlStrcasecmp(node2->name, (unsigned char*)"external-list") == 0)
                        {
                                current_node_type = EXTERNAL_LIST_RULE;
                                apply_rule = oma_match_external_list_condition(node2, subs, &w_uri);
                                break;
                        }
                        else if(xmlStrcasecmp(node2->name, (unsigned char*)"anonymous-request") == 0)
                        {
                                current_node_type = ANONYMOUS_REQUEST_RULE;
                                apply_rule = oma_match_anonymous_condition(node2, subs, &w_uri);
                                break;
                        }
                        else if(xmlStrcasecmp(node2->name, (unsigned char*)"other-identity") == 0)
                        {
                                current_node_type = OTHER_IDENTITY_RULE;
                                apply_rule = 1;
                                break;
                        }
                        else
                        {
                                /* unknown condition */
                                continue;
                        }

                }

                /* finished scanning all conditions for a given rule */
                if (apply_rule)
                {
                        tmp_rule = (xcap_rule_t *)pkg_malloc(sizeof(*tmp_rule));
                        if (tmp_rule == NULL)
                        {
                                LM_ERR("pkg mem\n");
                                goto error;
                        }
                        tmp_rule->node = current_node;
                        tmp_rule->next = NULL;
                        switch (current_node_type)
                        {
                                case IDENTITY_RULE:
                                        if(identity_rules == NULL)
                                                identity_rules = tmp_rule;
                                        else
                                                identity_tail->next = tmp_rule;
                                        identity_tail = tmp_rule;
                                        break;
                                case EXTERNAL_LIST_RULE:
                                        if(external_rules == NULL)
                                                external_rules = tmp_rule;
                                        else
                                                external_tail->next = tmp_rule;
                                        external_tail = tmp_rule;
                                        break;
                                case ANONYMOUS_REQUEST_RULE:
                                        if(anonymous_rules == NULL)
                                                anonymous_rules = tmp_rule;
                                        else
                                                anonymous_tail->next = tmp_rule;
                                        anonymous_tail = tmp_rule;
                                        break;
                                case OTHER_IDENTITY_RULE:
                                        if(other_identity_rules == NULL)
                                                other_identity_rules = tmp_rule;
                                        else
                                                other_identity_tail->next = tmp_rule;
                                        other_identity_tail = tmp_rule;
                                        break;
                                default:
                                        /* this will never happen */
                                        break;
                        }
                }
	}

        if (anonymous_rules)
        {
                *rules = anonymous_rules;
                free_rules(identity_rules);
                free_rules(external_rules);
                free_rules(other_identity_rules);
        }
        else if (identity_rules)
        {
                *rules = identity_rules;
                free_rules(external_rules);
                free_rules(anonymous_rules);
                free_rules(other_identity_rules);
        }
        else if (external_rules)
        {
                *rules = external_rules;
                free_rules(identity_rules);
                free_rules(anonymous_rules);
                free_rules(other_identity_rules);
        }
        else if (other_identity_rules)
        {
                *rules = other_identity_rules;
                free_rules(identity_rules);
                free_rules(external_rules);
                free_rules(anonymous_rules);
        }
        else
        {
                *rules = NULL;
                LM_DBG("no matching rules found\n");
        }

        pkg_free(w_uri.s);
        return;

error:
        if (w_uri.s)
                pkg_free(w_uri.s);
        free_rules(identity_rules);
        free_rules(external_rules);
        free_rules(anonymous_rules);
        free_rules(other_identity_rules);
}
Пример #26
0
/*!
 * \brief Timer function that removes expired dialogs, run timeout route
 * \param tl dialog timer list
 */
void dlg_ontimeout(struct dlg_tl *tl)
{
	dlg_cell_t *dlg;
	int new_state, old_state, unref;
	sip_msg_t *fmsg;
	void* timeout_cb = 0;

	/* get the dialog tl payload */
	dlg = ((struct dlg_cell*)((char *)(tl) -
			(unsigned long)(&((struct dlg_cell*)0)->tl)));

	/* mark dialog as expired */
	dlg->dflags |= DLG_FLAG_EXPIRED;

	if(dlg->state==DLG_STATE_CONFIRMED_NA
				|| dlg->state==DLG_STATE_CONFIRMED)
	{
		if(dlg->toroute>0 && dlg->toroute<main_rt.entries
			&& main_rt.rlist[dlg->toroute]!=NULL)
		{
			fmsg = faked_msg_next();
			if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
			{
				dlg_ref(dlg, 1);
				dlg_set_ctx_iuid(dlg);
				LM_DBG("executing route %d on timeout\n", dlg->toroute);
				set_route_type(REQUEST_ROUTE);
				run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0);
				dlg_reset_ctx_iuid();
				exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
				dlg_unref(dlg, 1);
			}
		}

		if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE)
		{
			/* set the dialog context so that it's available in
			 * tm:local-request event route */
			dlg_set_ctx_iuid(dlg);
			if(dlg_bye_all(dlg, NULL)<0)
				dlg_unref(dlg, 1);
			dlg_reset_ctx_iuid();

			dlg_unref(dlg, 1);
			if_update_stat(dlg_enable_stats, expired_dlgs, 1);
			return;
		}
	}

	next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
    /* used for computing duration for timed out acknowledged dialog */
	if (DLG_STATE_CONFIRMED == old_state) {
		timeout_cb = (void *)CONFIRMED_DIALOG_STATE;
	}

	dlg_run_event_route(dlg, NULL, old_state, new_state);

	if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
		LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
			dlg->callid.len, dlg->callid.s,
			dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
			dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);

		/* set end time */
		dlg->end_ts = (unsigned int)(time(0));

		/* dialog timeout */
		run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb);

		dlg_unref(dlg, unref+1);

		if_update_stat( dlg_enable_stats, expired_dlgs, 1);
		if_update_stat( dlg_enable_stats, active_dlgs, -1);
	} else {
		dlg_unref(dlg, 1);
	}

	return;
}
Пример #27
0
int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, 
			db_key_t* _c, int _n, int _nc, db_key_t _o, db1_res_t** _r)
{
	dbt_table_p _tbc = NULL;
	dbt_row_p _drp = NULL;
	dbt_result_p _dres = NULL;
	int result = 0;
	
	int *lkey=NULL, *lres=NULL;
	
	db_key_t *_o_k=NULL;    /* columns in order-by */
	char *_o_op=NULL;       /* operators for oder-by */
	int _o_n;               /* no of elements in order-by */
	int *_o_l=NULL;         /* column selection for order-by */
	int _o_nc;              /* no of elements in _o_l but not lres */

	if ((!_h) || (!_r) || !CON_TABLE(_h))
	{
		LM_ERR("invalid parameters\n");
		return -1;
	}
	*_r = NULL;
	

	if (_o)
	{
		if (dbt_parse_orderbyclause(&_o_k, &_o_op, &_o_n, _o) < 0)
			return -1;
	}

	/* lock database */
	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
	if(!_tbc)
	{
		LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s);
		return -1;
	}


	if(!_tbc || _tbc->nrcols < _nc)
	{
		LM_ERR("table %s not loaded! (too few columns)\n", CON_TABLE(_h)->s);
		goto error;
	}
	if(_k)
	{
		lkey = dbt_get_refs(_tbc, _k, _n);
		if(!lkey)
			goto error;
	}
	if(_c)
	{
		lres = dbt_get_refs(_tbc, _c, _nc);
		if(!lres)
			goto error;
	}
	if(_o_k)
	{
		_o_l = dbt_get_refs(_tbc, _o_k, _o_n);
		if (!_o_l)
			goto error;
		/* enlarge select-columns lres by all order-by columns, _o_nc is how many */
		if (dbt_mangle_columnselection(&lres, &_nc, &_o_nc, _o_l, _o_n) < 0)
			goto error;
	}

	LM_DBG("new res with %d cols\n", _nc);
	_dres = dbt_result_new(_tbc, lres, _nc);
	
	if(!_dres)
		goto error;
	
	_drp = _tbc->rows;
	while(_drp)
	{
		if(dbt_row_match(_tbc, _drp, lkey, _op, _v, _n))
		{
			if(dbt_result_extract_fields(_tbc, _drp, lres, _dres))
			{
				LM_ERR("failed to extract result fields!\n");
				goto clean;
			}
		}
		_drp = _drp->next;
	}

	dbt_table_update_flags(_tbc, DBT_TBFL_ZERO, DBT_FL_IGN, 1);
	
	/* unlock database */
	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));

	if (_o_l)
	{
		if (_dres->nrrows > 1)
		{
			if (dbt_sort_result(_dres, _o_l, _o_op, _o_n, lres, _nc) < 0)
				goto error_nounlock;
		}

		/* last but not least, remove surplus columns */
		if (_o_nc)
			dbt_project_result(_dres, _o_nc);
	}


	/* dbt_result_print(_dres); */
	
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	if(_o_k)
 		pkg_free(_o_k);
 	if(_o_op)
 		pkg_free(_o_op);
 	if(_o_l)
 		pkg_free(_o_l);

	result = dbt_get_result(_r, _dres);
	if(result != 0)
		dbt_result_free(_dres);

	return result;

error:
	/* unlock database */
	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
error_nounlock:
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	if(_o_k)
		pkg_free(_o_k);
	if(_o_op)
		pkg_free(_o_op);
	if(_o_l)
		pkg_free(_o_l);
	if(_dres)
		dbt_result_free(_dres);
	LM_ERR("failed to query the table!\n");

	return -1;

clean:
	/* unlock database */
	dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h));
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	if(_o_k)
		pkg_free(_o_k);
	if(_o_op)
		pkg_free(_o_op);
	if(_o_l)
		pkg_free(_o_l);
	if(_dres)
		dbt_result_free(_dres);

	return -1;
}
Пример #28
0
/*!
 * \brief Parse SIP message and populate leg informations
 *
 * Parse SIP message and populate leg informations. 
 * \param dlg the dialog to add cseq, contact & record_route
 * \param msg sip message
 * \param t transaction
 * \param leg type of the call leg
 * \param tag SIP To tag
 * \return 0 on success, -1 on failure
 * \note for a request: get record route in normal order, for a reply get
 * in reverse order, skipping the ones from the request and the proxies' own
 */
int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
	struct cell* t, unsigned int leg, str *tag)
{
	unsigned int skip_recs;
	str cseq;
	str contact;
	str rr_set;

	dlg->bind_addr[leg] = msg->rcv.bind_address;

	/* extract the cseq number as string */
	if (leg==DLG_CALLER_LEG) {
		if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
			|| !msg->cseq->parsed){
			LM_ERR("bad sip message or missing CSeq hdr :-/\n");
			goto error0;
		}
		cseq = (get_cseq(msg))->number;
	} else {
		/* use the same as in request */
		cseq = dlg->cseq[DLG_CALLEE_LEG];
	}

	/* extract the contact address */
	if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
		LM_ERR("bad sip message or missing Contact hdr\n");
		goto error0;
	}
	if ( parse_contact(msg->contact)<0 ||
	((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
	((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
		LM_ERR("bad Contact HDR\n");
		goto error0;
	}
	contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;

	/* extract the RR parts */
	if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0)  ){
		LM_ERR("failed to parse record route header\n");
		goto error0;
	}

	if (leg==DLG_CALLER_LEG) {
		skip_recs = 0;
	} else {
		/* was the 200 OK received or local generated */
		skip_recs = dlg->from_rr_nb +
			((t->relayed_reply_branch>=0)?
				((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
				 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
				:0);
	}

	if(msg->record_route){
		if( print_rr_body(msg->record_route, &rr_set, leg,
							&skip_recs) != 0 ){
			LM_ERR("failed to print route records \n");
			goto error0;
		}
	} else {
		rr_set.s = 0;
		rr_set.len = 0;
	}

	if(leg==DLG_CALLER_LEG)
		dlg->from_rr_nb = skip_recs;

	LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
		rr_set.len, rr_set.s, contact.len, contact.s,
		cseq.len, cseq.s,
		msg->rcv.bind_address->sock_str.len,
		msg->rcv.bind_address->sock_str.s);

	if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
		LM_ERR("dlg_set_leg_info failed\n");
		if (rr_set.s) pkg_free(rr_set.s);
		goto error0;
	}

	if (rr_set.s) pkg_free(rr_set.s);

	return 0;
error0:
	return -1;
}
Пример #29
0
/**
 * run keep-alive list
 *
 */
int dlg_ka_run(ticks_t ti)
{
	dlg_ka_t *dka;
	dlg_cell_t *dlg;

	if(dlg_ka_interval<=0)
		return 0;

	while(1) {
		/* get head item */
		lock_get(dlg_ka_list_lock);
		if(*dlg_ka_list_head==NULL) {
			lock_release(dlg_ka_list_lock);
			return 0;
		}
		dka = *dlg_ka_list_head;
#if 0
		LM_DBG("dlg ka timer at %lu for"
				" dlg[%u,%u] on %lu\n", (unsigned long)ti,
				dka->iuid.h_entry, dka->iuid.h_id,
				(unsigned long)dka->katime);
#endif
		if(dka->katime>ti) {
			lock_release(dlg_ka_list_lock);
			return 0;
		}
		if(*dlg_ka_list_head == *dlg_ka_list_tail) {
			*dlg_ka_list_head = NULL;
			*dlg_ka_list_tail = NULL;
		}
		*dlg_ka_list_head = dka->next;
		lock_release(dlg_ka_list_lock);

		/* send keep-alive for dka */
		dlg = dlg_get_by_iuid(&dka->iuid);
		if(dlg==NULL) {
			shm_free(dka);
			dka = NULL;
		} else {
			if(dka->iflags & DLG_IFLAG_KA_SRC)
				dlg_send_ka(dlg, DLG_CALLER_LEG);
			if(dka->iflags & DLG_IFLAG_KA_DST)
				dlg_send_ka(dlg, DLG_CALLEE_LEG);
			dlg_release(dlg);
		}
		/* append to tail */
		if(dka!=NULL)
		{
			dka->katime = ti + dlg_ka_interval;
			lock_get(dlg_ka_list_lock);
			if(*dlg_ka_list_tail!=NULL)
				(*dlg_ka_list_tail)->next = dka;
			if(*dlg_ka_list_head==NULL)
				*dlg_ka_list_head = dka;
			*dlg_ka_list_tail = dka;
			lock_release(dlg_ka_list_lock);
		}
	}

	return 0;
}
Пример #30
0
int update_phtable(presentity_t* presentity, str pres_uri, str body)
{
	char* sphere= NULL;
	unsigned int hash_code;
	pres_entry_t* p;
	int ret= 0;
	str* xcap_doc= NULL;

	/* get new sphere */
	sphere= extract_sphere(body);
	if(sphere==NULL)
	{
		LM_DBG("no sphere defined in new body\n");
		return 0;
	}

	/* search for record in hash table */
	hash_code= core_hash(&pres_uri, NULL, phtable_size);

	lock_get(&pres_htable[hash_code].lock);

	p= search_phtable(&pres_uri, presentity->event->evp->parsed, hash_code);
	if(p== NULL)
	{
		lock_release(&pres_htable[hash_code].lock);
		goto done;
	}

	if(p->sphere)
	{
		if(strcmp(p->sphere, sphere)!= 0)
		{
			/* new sphere definition */
			shm_free(p->sphere);
		}
		else
		{
			/* no change in sphere definition */
			lock_release(&pres_htable[hash_code].lock);
			pkg_free(sphere);
			return 0;
		}

	}


	p->sphere= (char*)shm_malloc(strlen(sphere)+ 1);
	if(p->sphere== NULL)
	{
		lock_release(&pres_htable[hash_code].lock);
		ret= -1;
		goto done;
	}
	strcpy(p->sphere, sphere);

	lock_release(&pres_htable[hash_code].lock);

	/* call for watchers status update */

	if(presentity->event->get_rules_doc(&presentity->user, &presentity->domain,
				&xcap_doc)< 0)
	{
		LM_ERR("failed to retreive xcap document\n");
		ret= -1;
		goto done;
	}

	update_watchers_status(pres_uri, presentity->event, xcap_doc);


done:

	if(xcap_doc)
	{
		if(xcap_doc->s)
			pkg_free(xcap_doc->s);
		pkg_free(xcap_doc);
	}

	if(sphere)
		pkg_free(sphere);
	return ret;
}