Example #1
0
static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array)
{
	subs_t* s, *ps, *cs;
	int i= 0;

	LM_DBG("start\n");

	if (subs_dbmode == DB_ONLY) return(update_pw_dialogs_dbonlymode(subs, subs_array));

	lock_get(&subs_htable[hash_code].lock);

	ps= subs_htable[hash_code].entries;

	while(ps && ps->next)
	{
		s= ps->next;

		if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len &&
				s->watcher_user.len== subs->watcher_user.len &&
				s->watcher_domain.len==subs->watcher_domain.len &&
				presence_sip_uri_match(&s->pres_uri, &subs->pres_uri)== 0 &&
				presence_sip_uri_match(&s->watcher_user, &subs->watcher_user)== 0 &&
				presence_sip_uri_match(&s->watcher_domain, &subs->watcher_domain)==0)
		{
			i++;
			s->status= subs->status;
			s->reason= subs->reason;
			s->db_flag= UPDATEDB_FLAG;

			cs= mem_copy_subs(s, PKG_MEM_TYPE);
			if(cs== NULL)
			{
				LM_ERR( "copying subs_t stucture\n");
				lock_release(&subs_htable[hash_code].lock);
				return -1;
			}
			cs->local_cseq++;
			cs->expires-= (int)time(NULL);
			cs->next= (*subs_array);
			(*subs_array)= cs;
			if(subs->status== TERMINATED_STATUS)
			{
				ps->next= s->next;
				shm_free(s->contact.s);
				shm_free(s);
				LM_DBG(" deleted terminated dialog from hash table\n");
			}
			else
				ps= s;

			printf_subs(cs);
		}
		else
			ps= s;
	}

	LM_DBG("found %d matching dialogs\n", i);
	lock_release(&subs_htable[hash_code].lock);

	return 0;
}
Example #2
0
void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps)
{
	struct hdr_field* hdr= NULL;
	struct sip_msg* msg= NULL;
	ua_pres_t* presentity= NULL;
	ua_pres_t* db_presentity= NULL; 
	ua_pres_t* hentity= NULL;
	int found = 0;
	int size= 0;
	unsigned int lexpire= 0;
	str etag;
	unsigned int hash_code;
	db1_res_t *res=NULL;
	ua_pres_t dbpres;
	str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0};
	int end_transaction = 1;

	memset(&dbpres, 0, sizeof(dbpres));
	dbpres.pres_uri = &pres_uri;
	dbpres.watcher_uri = &watcher_uri;
	dbpres.extra_headers = &extra_headers;

	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
	{
		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto error;
		}
	}

	if(ps->param== NULL|| *ps->param== NULL)
	{
		LM_ERR("NULL callback parameter\n");
		goto error;
	}
	hentity= (ua_pres_t*)(*ps->param);

	msg= ps->rpl;
	if(msg == NULL)
	{
		LM_ERR("no reply message found\n ");
		goto error;
	}
	

	if(msg== FAKED_REPLY)
	{
		LM_DBG("FAKED_REPLY\n");
		goto done;
	}

	hash_code= core_hash(hentity->pres_uri, NULL, HASH_SIZE);

	if( ps->code>= 300 )
	{
		find_and_delete_record(hentity, hash_code);

		if(ps->code== 412 && hentity->body && hentity->flag!= MI_PUBLISH
				&& hentity->flag!= MI_ASYN_PUBLISH)
		{
			/* sent a PUBLISH within a dialog that no longer exists
			 * send again an intial PUBLISH */
			LM_DBG("received a 412 reply- try again to send PUBLISH\n");
			publ_info_t publ;
			memset(&publ, 0, sizeof(publ_info_t));
			publ.pres_uri= hentity->pres_uri; 
			publ.body= hentity->body;
			
			if(hentity->desired_expires== 0)
				publ.expires= -1;
			else
			if(hentity->desired_expires<= (int)time(NULL))
				publ.expires= 0;
			else
				publ.expires= hentity->desired_expires- (int)time(NULL)+ 3;

			publ.source_flag|= hentity->flag;
			publ.event|= hentity->event;
			publ.content_type= hentity->content_type;	
			publ.id= hentity->id;
			publ.extra_headers= hentity->extra_headers;
			publ.outbound_proxy = hentity->outbound_proxy;
			publ.cb_param= hentity->cb_param;

			if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction)
			{
				if (pua_dbf.end_transaction(pua_db) < 0)
				{
					LM_ERR("in end_transaction\n");
					goto error;
				}
			}

			end_transaction = 0;

			if(send_publish(&publ)< 0)
			{
				LM_ERR("when trying to send PUBLISH\n");
				goto error;
			}
		}
		goto done;
	} /* code >= 300 */
	
	if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		goto error;
	}	
	if(msg->expires== NULL || msg->expires->body.len<= 0)
	{
			LM_ERR("No Expires header found\n");
			goto error;
	}	
	
	if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
	{
		LM_ERR("cannot parse Expires header\n");
		goto error;
	}
	lexpire = ((exp_body_t*)msg->expires->parsed)->val;
	LM_DBG("lexpire= %u\n", lexpire);
		
	hdr = msg->headers;
	while (hdr!= NULL)
	{
		if(cmp_hdrname_strzn(&hdr->name, "SIP-ETag",8)==0 )
		{
			found = 1;
			break;
		}
		hdr = hdr->next;
	}
	if(found== 0) /* must find SIP-Etag header field in 200 OK msg*/
	{	
		LM_ERR("no SIP-ETag header field found\n");
		goto error;
	}
	etag= hdr->body;
		
	LM_DBG("completed with status %d [contact:%.*s]\n",
	       ps->code, hentity->pres_uri->len, hentity->pres_uri->s);

	if (lexpire == 0)
	{
		find_and_delete_record(hentity, hash_code);
		goto done;
	}

	if (hentity->etag.s) {
		if (pua_dbf.affected_rows != NULL || dbmode != PUA_DB_ONLY) {
			if (find_and_update_record(hentity, hash_code,
						   lexpire, &etag) > 0)
				goto done;
		}
		else if ((db_presentity =
			  get_record_puadb(hentity->id, &hentity->etag,
					   &dbpres, &res)) != NULL)
		{
			update_record_puadb(hentity, lexpire, &etag);
			goto done;
		}
	}

	size= sizeof(ua_pres_t)+ sizeof(str)+ 
		(hentity->pres_uri->len+ hentity->tuple_id.len + 
		 hentity->id.len)* sizeof(char);
	if(hentity->extra_headers)
		size+= sizeof(str)+ hentity->extra_headers->len* sizeof(char);

	presentity= (ua_pres_t*)shm_malloc(size);
	if(presentity== NULL)
	{
		LM_ERR("no more share memory\n");
		goto error;
	}	
	memset(presentity, 0, size);

	size= sizeof(ua_pres_t);
	presentity->pres_uri= (str*)((char*)presentity+ size);
	size+= sizeof(str);

	presentity->pres_uri->s= (char*)presentity+ size;
	memcpy(presentity->pres_uri->s, hentity->pres_uri->s, 
			hentity->pres_uri->len);
	presentity->pres_uri->len= hentity->pres_uri->len;
	size+= hentity->pres_uri->len;
	
	presentity->tuple_id.s= (char*)presentity+ size;
	memcpy(presentity->tuple_id.s, hentity->tuple_id.s,
			hentity->tuple_id.len);
	presentity->tuple_id.len= hentity->tuple_id.len;
	size+= presentity->tuple_id.len;

	presentity->id.s=(char*)presentity+ size;
	memcpy(presentity->id.s, hentity->id.s, 
			hentity->id.len);
	presentity->id.len= hentity->id.len; 
	size+= presentity->id.len;
		
	if(hentity->extra_headers)
	{
		presentity->extra_headers= (str*)((char*)presentity+ size);
		size+= sizeof(str);
		presentity->extra_headers->s= (char*)presentity+ size;
		memcpy(presentity->extra_headers->s, hentity->extra_headers->s, 
				hentity->extra_headers->len);
		presentity->extra_headers->len= hentity->extra_headers->len;
		size+= hentity->extra_headers->len;
	}

	presentity->desired_expires= hentity->desired_expires;
	presentity->expires= lexpire+ (int)time(NULL);
	presentity->flag|= hentity->flag;
	presentity->event|= hentity->event;

	presentity->etag.s= (char*)shm_malloc(etag.len* sizeof(char));
	if(presentity->etag.s== NULL)
	{
		LM_ERR("No more share memory\n");
		goto error;
	}
	memcpy(presentity->etag.s, etag.s, etag.len);
	presentity->etag.len= etag.len;

	if (dbmode==PUA_DB_ONLY)
	{
		insert_record_puadb(presentity);
	}
	else
 	{
		lock_get(&HashT->p_records[hash_code].lock);
		insert_htable(presentity, hash_code);
		lock_release(&HashT->p_records[hash_code].lock);
	}
	LM_DBG("Inserted record\n");

done:
	if(hentity->ua_flag == REQ_OTHER)
	{
		run_pua_callbacks(hentity, msg);
	}
	if(*ps->param)
	{
		shm_free(*ps->param);
		*ps->param= NULL;
	}
	if(dbmode==PUA_DB_ONLY && presentity)
	{
		shm_free(presentity->etag.s);
		shm_free(presentity);
	}

	if (res) free_results_puadb(res);

	if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction && end_transaction)
	{
		if (pua_dbf.end_transaction(pua_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto error;
		}
	}

	return;

error:
	if(*ps->param)
	{
		shm_free(*ps->param);
		*ps->param= NULL;
	}
	if(presentity) shm_free(presentity);

	if (res) free_results_puadb(res);

	if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction)
	{
		if (pua_dbf.abort_transaction(pua_db) < 0)
			LM_ERR("in abort_transaction\n");
	}

	return;
}	
Example #3
0
void async_cdp_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) {
    struct cell *t = 0;
    pcontact_t* pcontact;
    unsigned int cdp_result;
    struct pcontact_info ci;
    udomain_t* domain_t;
    int finalReply = 0;
    int result = CSCF_RETURN_ERROR;

    LM_DBG("Received AAR callback\n");
    saved_transaction_local_t* local_data = (saved_transaction_local_t*) param;
    saved_transaction_t* data = local_data->global_data;
    domain_t = data->domain;

    int is_rereg = local_data->is_rereg;

    //before we do anything else, lets decrement the reference counter on replies
    lock_get(data->lock);
    data->answers_not_received--;
    if (data->answers_not_received <= 0) {
        finalReply = 1;
    }
    if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory
        free_saved_transaction_data(local_data);
        if (finalReply) {
            free_saved_transaction_global_data(data);
        }
        return;
    }
    lock_release(data->lock);

    LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed);

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        goto error;
    }
    //we have T, lets restore our state (esp. for AVPs)
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    if (is_timeout != 0) {
        LM_ERR("Error timeout when sending AAR message via CDP\n");
        update_stat(stat_aar_timeouts, 1);
        goto error;
    }
    if (!aaa) {
        LM_ERR("Error sending message via CDP\n");
        goto error;
    }

    update_stat(aar_replies_received, 1);
    update_stat(aar_replies_response_time, elapsed_msecs);

    /* Process the response to AAR, retrieving result code and associated Rx session ID */
    if (rx_process_aaa(aaa, &cdp_result) < 0) {
        LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s);
        goto error;
    }

    if (cdp_result >= 2000 && cdp_result < 3000) {
    	if (is_rereg) {
    		LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n");
    		result = CSCF_RETURN_TRUE;
    		create_return_code(result);
    		goto done;
    	}
        LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n",
                cdp_result, local_data->contact.len, local_data->contact.s,
                local_data->auth_session_id.len, local_data->auth_session_id.s);
        LM_DBG("Registering for Usrloc callbacks on DELETE\n");

        ul.lock_udomain(domain_t, &local_data->contact);
        if (ul.get_pcontact(domain_t, &local_data->contact, &pcontact) != 0) {
            LM_ERR("Shouldn't get here, can find contact....\n");
            ul.unlock_udomain(domain_t, &local_data->contact);
            goto error;
        }

        //at this point we have the contact
        /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again
         * for the duration of the registration.
         * */
        if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) {
            LM_ERR("unable to update pcontact......\n");
            ul.unlock_udomain(domain_t, &local_data->contact);
            goto error;
        }
        memset(&ci, 0, sizeof(struct pcontact_info));
        ci.reg_state = PCONTACT_REG_PENDING_AAR;
        ci.num_service_routes = 0;
        ci.num_public_ids = 0;
        LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s);
        ul.update_pcontact(domain_t, &ci, pcontact);
        //register for callbacks on contact
        ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE,
                callback_pcscf_contact_cb, NULL);
        ul.unlock_udomain(domain_t, &local_data->contact);
        result = CSCF_RETURN_TRUE;
    } else {
        LM_ERR("Received negative reply from PCRF for AAR Request\n");
        result = CSCF_RETURN_FALSE;
        goto error;
    }

    //set success response code AVP
    create_return_code(result);
    goto done;

error:
    //set failure response code
    create_return_code(result);

done:
    if (t) tmb.unref_cell(t);
    //free memory
    if (aaa)
        cdpb.AAAFreeMessage(&aaa);

    if (finalReply) {
        tmb.t_continue(data->tindex, data->tlabel, data->act);
        free_saved_transaction_global_data(data);
    }
    free_saved_transaction_data(local_data);
}
Example #4
0
static void rpc_delete(rpc_t* rpc, void* c)
{
	str sd;
	unsigned int dhash;
	int hash_entry;
	pd_t *it;
	pd_op_t *ito, *tmp;
	db_key_t db_keys[1] = {domain_column};
	db_val_t db_vals[1];
	db_op_t  db_ops[1] = {OP_EQ};

	if(_dhash==NULL) {
		LOG(L_ERR, "PDT:pdt_fifo_delete: strange situation\n");
		rpc->fault(c, 500, "Server Error");
		return;
	}

	     /* Use s to make sure the string is zero terminated */
	if (rpc->scan(c, "s", &sd.s) < 1) {
		rpc->fault(c, 400, "Parameter Missing");
		return;
	}
	sd.len = strlen(sd.s);

	if(*sd.s=='\0') {
		LOG(L_INFO, "PDT:pdt_fifo_delete: empty domain\n");
		rpc->fault(c, 400, "Empty Parameter");
		return;
	}

	dhash = pdt_compute_hash(sd.s);
	hash_entry = get_hash_entry(dhash, _dhash->hash_size);

	lock_get(&_dhash->diff_lock);

	lock_get(&_dhash->dhash[hash_entry].lock);

	it = _dhash->dhash[hash_entry].e;
	while(it!=NULL && it->dhash<=dhash) {
		if(it->dhash==dhash && it->domain.len==sd.len
		   && strncasecmp(it->domain.s, sd.s, sd.len)==0)
			break;
		it = it->n;
	}

	if(it!=NULL) {
		if(it->p!=NULL)
			(it->p)->n = it->n;
		else
			_dhash->dhash[hash_entry].e = it->n;
		if(it->n)
			(it->n)->p = it->p;
	}
	lock_release(&_dhash->dhash[hash_entry].lock);

	if(it!=NULL) {
		tmp = new_pd_op(it, 0, PDT_DELETE);
		if(tmp==NULL) {
			LOG(L_ERR, "PDT:pdt_fifo_delete: no more shm!\n");
			rpc->fault(c, 431, "No Shared Memory Left");
			lock_release(&_dhash->diff_lock);
			return;
		}

		_dhash->max_id++;
		tmp->id = _dhash->max_id;
		if(_dhash->diff==NULL) {
			_dhash->diff = tmp;
			DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op);
			goto done;
		}
		ito = _dhash->diff;
		while(ito->n!=NULL)
			ito = ito->n;

		ito->n = tmp;
		tmp->p = ito;
		DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op);
		dhash = 1;
	} else {
		dhash = 0;
	}

 done:
	lock_release(&_dhash->diff_lock);
	if(dhash==0) {
		DBG("PDT:pdt_fifo_delete: prefix for domain [%s] not found\n", sd.s);
		rpc->fault(c, 404, "Domain Not Found");
	} else {
		db_vals[0].type = DB_STR;
		db_vals[0].nul = 0;
		db_vals[0].val.str_val.s = sd.s;
		db_vals[0].val.str_val.len = sd.len;
		if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 1)<0)
			{
				LOG(L_ERR,"PDT:pdt_fifo_delete: database/cache are inconsistent\n");
				rpc->fault(c, 502, "Database And Cache Are Inconsistent");
			}
	}
}
Example #5
0
static inline int mi_print_b2be_dlg(struct mi_node *rpl, b2b_table htable, unsigned int hsize)
{
	int i, len;
	char* p;
	b2b_dlg_t* dlg;
	dlg_leg_t* leg;
	struct mi_node *node=NULL, *node1=NULL;
	struct mi_attr* attr;

	for(i = 0; i< hsize; i++)
	{
		lock_get(&htable[i].lock);
		dlg = htable[i].first;
		while(dlg)
		{
			p = int2str((unsigned long)(dlg->id), &len);
			node = add_mi_node_child(rpl, MI_DUP_VALUE, "dlg", 3, p, len);
			if(node == NULL) goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "param", 5,
					dlg->param.s, dlg->param.len);
			if(attr == NULL) goto error;
			p = int2str((unsigned long)(dlg->state), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "state", 5, p, len);
			if(attr == NULL) goto error;
			p = int2str((unsigned long)(dlg->last_invite_cseq), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "last_invite_cseq", 16, p, len);
			if(attr == NULL) goto error;
			p = int2str((unsigned long)(dlg->last_method), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "last_method", 11, p, len);
			if(attr == NULL) goto error;
			if (dlg->last_reply_code)
			{
				p = int2str((unsigned long)(dlg->last_reply_code), &len);
				attr = add_mi_attr(node,MI_DUP_VALUE,"last_reply_code",15,p,len);
				if(attr == NULL) goto error;
			}
			p = int2str((unsigned long)(dlg->db_flag), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "db_flag", 7, p, len);
			if(attr == NULL) goto error;

			if (dlg->ruri.len)
			{
				node1 = add_mi_node_child(node, MI_DUP_VALUE, "ruri", 4,
						dlg->ruri.s, dlg->ruri.len);
				if(node1 == NULL) goto error;
			}

			node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6,
					dlg->callid.s, dlg->callid.len);
			if(node1 == NULL) goto error;

			node1 = add_mi_node_child(node, MI_DUP_VALUE, "from", 4,
					dlg->from_dname.s, dlg->from_dname.len);
			if(node1 == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "uri", 3,
					dlg->from_uri.s, dlg->from_uri.len);
			if(attr == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3,
					dlg->tag[0].s, dlg->tag[0].len);
			if(attr == NULL) goto error;

			node1 = add_mi_node_child(node, MI_DUP_VALUE, "to", 2,
					dlg->to_dname.s, dlg->to_dname.len);
			if(node1 == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "uri", 3,
					dlg->to_uri.s, dlg->to_uri.len);
			if(attr == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3,
					dlg->tag[1].s, dlg->tag[1].len);
			if(attr == NULL) goto error;

			node1 = add_mi_node_child(node, MI_DUP_VALUE, "cseq", 4, NULL, 0);
			if(node1 == NULL) goto error;
			p = int2str((unsigned long)(dlg->cseq[0]), &len);
			attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6, p, len);
			if(attr == NULL) goto error;
			p = int2str((unsigned long)(dlg->cseq[1]), &len);
			attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6, p, len);
			if(attr == NULL) goto error;

			if (dlg->route_set[0].len||dlg->route_set[1].len)
			{
				node1 = add_mi_node_child(node,MI_DUP_VALUE,"route_set",9,NULL,0);
				if(node1 == NULL) goto error;
				if (dlg->route_set[0].len)
				{
					attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6,
							dlg->route_set[0].s, dlg->route_set[0].len);
					if(attr == NULL) goto error;
				}
				if (dlg->route_set[1].len)
				{
					attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6,
							dlg->route_set[1].s, dlg->route_set[1].len);
					if(attr == NULL) goto error;
				}
			}

			node1 = add_mi_node_child(node, MI_DUP_VALUE, "contact", 7, NULL, 0);
			if(node1 == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6,
					dlg->contact[0].s, dlg->contact[0].len);
			if(attr == NULL) goto error;
			attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6,
					dlg->contact[1].s, dlg->contact[1].len);
			if(attr == NULL) goto error;

			if (dlg->send_sock)
			{
				node1 = add_mi_node_child(node, MI_DUP_VALUE, "send_sock", 9,
					dlg->send_sock->name.s, dlg->send_sock->name.len);
				if(node1 == NULL) goto error;
			}

			if(dlg->uac_tran||dlg->uas_tran||dlg->update_tran||dlg->cancel_tm_tran)
			{
				node1 = add_mi_node_child(node, MI_DUP_VALUE, "tm_tran", 7, NULL, 0);
				if(node1 == NULL) goto error;
				if(dlg->uac_tran)
					attr = add_mi_attr(node1,MI_DUP_VALUE,"uac",3,NULL,0);
					if(attr == NULL) goto error;
				if(dlg->uas_tran)
					attr = add_mi_attr(node1,MI_DUP_VALUE,"uas",3,NULL,0);
					if(attr == NULL) goto error;
				if(dlg->update_tran)
					attr = add_mi_attr(node1,MI_DUP_VALUE,"update",6,NULL,0);
					if(attr == NULL) goto error;
				if(dlg->cancel_tm_tran)
					attr = add_mi_attr(node1,MI_DUP_VALUE,"cancel_tm",9,NULL,0);
					if(attr == NULL) goto error;
			}

			leg=dlg->legs;
			while(leg)
			{
				p = int2str((unsigned long)(leg->id), &len);
				node1 = add_mi_node_child(node, MI_DUP_VALUE, "leg", 3, p, len);
				if(node1 == NULL) goto error;
				attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3,
						leg->tag.s, leg->tag.len);
				if(attr == NULL) goto error;
				p = int2str((unsigned long)(leg->cseq), &len);
				attr = add_mi_attr(node1, MI_DUP_VALUE, "cseq", 4, p, len);
				if(attr == NULL) goto error;
				attr = add_mi_attr(node1, MI_DUP_VALUE, "contact", 7,
						leg->contact.s, leg->contact.len);
				if(attr == NULL) goto error;
				if(leg->route_set.len)
				{
					attr = add_mi_attr(node1, MI_DUP_VALUE, "route_set", 8,
						leg->route_set.s, leg->route_set.len);
					if(attr == NULL) goto error;
				}

				leg=leg->next;
			}

			dlg = dlg->next;
		}
		lock_release(&htable[i].lock);
	}
	return 0;
error:
	lock_release(&htable[i].lock);
	LM_ERR("failed to add node\n");
	return -1;
}
Example #6
0
static void rpc_uac_reg_info(rpc_t* rpc, void* ctx)
{
	int i;
	reg_item_t *reg = NULL;
	void* th;
	str none = {"none", 4};
	time_t tn;
	str attr = {0};
	str val = {0};
	str *rval;

	if(_reg_htable==NULL)
	{
		rpc->fault(ctx, 500, "Not enabled");
		return;
	}

	if(rpc->scan(ctx, "S.S", &attr, &val)<2)
	{
		rpc->fault(ctx, 500, "Invalid Parameters");
		return;
	}
	if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
	{
		LM_ERR("bad parameter values\n");
		rpc->fault(ctx, 500, "Invalid Parameter Values");
		return;
	}

	tn = time(NULL);

	for(i=0; i<_reg_htable->htsize; i++)
	{
		/* walk through entries */
		lock_get(&_reg_htable->entries[i].lock);
		reg = _reg_htable->entries[i].byuuid;
		while(reg)
		{
			if(attr.len==10 && strncmp(attr.s, "l_username", 10)==0) {
				rval = &reg->r->l_username;
			} else if(attr.len==10 && strncmp(attr.s, "r_username", 10)==0) {
				rval = &reg->r->r_username;
			} else if(attr.len==6 && strncmp(attr.s, "l_uuid", 6)==0) {
				rval = &reg->r->l_uuid;
			} else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) {
				rval = &reg->r->auth_username;
			} else {
				lock_release(&_reg_htable->entries[i].lock);
				LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s);
				rpc->fault(ctx, 500, "Unsupported Filter Attribtue");
				return;
			}

			if(rval->len==val.len && strncmp(val.s, rval->s, val.len)==0) {
				/* add entry node */
				if (rpc->add(ctx, "{", &th) < 0)
				{
					rpc->fault(ctx, 500, "Internal error creating rpc");
					return;
				}
				if(rpc->struct_add(th, "SSSSSSSSSdddd",
							"l_uuid",        &reg->r->l_uuid,
							"l_username",    &reg->r->l_username,
							"l_domain",      &reg->r->l_domain,
							"r_username",    &reg->r->r_username,
							"r_domain",      &reg->r->r_domain,
							"realm",         &reg->r->realm,
							"auth_username", &reg->r->auth_username,
							"auth_password", &reg->r->auth_password,
							"auth_proxy",    (reg->r->auth_proxy.len)?
							&reg->r->auth_proxy:&none,
							"expires",       (int)reg->r->expires,
							"flags",         (int)reg->r->flags,
							"diff_expires",  (int)(reg->r->timer_expires - tn),
							"timer_expires", (int)reg->r->timer_expires
							)<0)
				{
					lock_release(&_reg_htable->entries[i].lock);
					rpc->fault(ctx, 500, "Internal error adding item");
					return;
				}
				lock_release(&_reg_htable->entries[i].lock);
				return;
			}
			reg = reg->next;
		}
		lock_release(&_reg_htable->entries[i].lock);
	}
}
Example #7
0
int uac_reg_free_ht(void)
{
	int i;
	reg_item_t *it = NULL;
	reg_item_t *it0 = NULL;

	if(_reg_htable_gc_lock != NULL)
	{
		lock_destroy(_reg_htable_gc_lock);
		shm_free((void*)_reg_htable_gc_lock);
		_reg_htable_gc_lock = NULL;
	}
	if(_reg_htable_gc!=NULL)
	{
		for(i=0; i<_reg_htable_gc->htsize; i++)
		{
			it = _reg_htable_gc->entries[i].byuuid;
			while(it)
			{
				it0 = it;
				it = it->next;
				shm_free(it0);
			}
			it = _reg_htable_gc->entries[i].byuser;
			while(it)
			{
				it0 = it;
				it = it->next;
				shm_free(it0->r);
				shm_free(it0);
			}
		}
		shm_free(_reg_htable_gc->entries);
		shm_free(_reg_htable_gc);
		_reg_htable_gc = NULL;
	}

	if(_reg_htable==NULL)
	{
		LM_DBG("no hash table\n");
		return -1;
	}
	for(i=0; i<_reg_htable->htsize; i++)
	{
		lock_get(&_reg_htable->entries[i].lock);
		/* free entries */
		it = _reg_htable->entries[i].byuuid;
		while(it)
		{
			it0 = it;
			it = it->next;
			shm_free(it0);
		}
		it = _reg_htable->entries[i].byuser;
		while(it)
		{
			it0 = it;
			it = it->next;
			shm_free(it0->r);
			shm_free(it0);
		}
		lock_destroy(&_reg_htable->entries[i].lock);
	}
	shm_free(_reg_htable->entries);
	shm_free(_reg_htable);
	_reg_htable = NULL;
	return 0;
}
Example #8
0
/*
 * Update a row in table
 */
int dbt_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v,
	      db_key_t* _uk, db_val_t* _uv, int _n, int _un)
{
	tbl_cache_p _tbc = NULL;
	dbt_table_p _dtp = NULL;
	dbt_row_p _drp = NULL;
	int i;	
	str stbl;
	int *lkey=NULL, *lres=NULL;

	if (!_h || !CON_TABLE(_h) || !_uk || !_uv || _un <= 0)
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:dbt_update: Invalid parameter value\n");
#endif
		return -1;
	}
	
	stbl.s = (char*)CON_TABLE(_h);
	stbl.len = strlen(CON_TABLE(_h));

	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl);
	if(!_tbc)
	{
		DBG("DBT:dbt_update: table does not exist!\n");
		return -1;
	}

	lock_get(&_tbc->sem);
	_dtp = _tbc->dtp;

	if(!_dtp || _dtp->nrcols < _un)
	{
		DBG("DBT:dbt_update: table not loaded or more values"
			" to update than columns!\n");
		goto error;
	}
	if(_k)
	{
		lkey = dbt_get_refs(_dtp, _k, _n);
		if(!lkey)
			goto error;
	}
	lres = dbt_get_refs(_dtp, _uk, _un);
	if(!lres)
		goto error;
	DBG("DBT:dbt_update: ---- \n");
	_drp = _dtp->rows;
	while(_drp)
	{
		if(dbt_row_match(_dtp, _drp, lkey, _o, _v, _n))
		{ // update fields
			for(i=0; i<_un; i++)
			{
				if(dbt_is_neq_type(_dtp->colv[lres[i]]->type, _uv[i].type))
				{
					DBG("DBT:dbt_update: incompatible types!\n");
					goto error;
				}
				
				if(dbt_row_update_val(_drp, &(_uv[i]), _uv[i].type, lres[i]))
				{
					DBG("DBT:dbt_update: cannot set v[%d] in c[%d]!\n",
							i, lres[i]);
					goto error;
				}
			}
		}
		_drp = _drp->next;
	}

	dbt_table_update_flags(_dtp, DBT_TBFL_MODI, DBT_FL_SET, 1);
	
#ifdef DBT_EXTRA_DEBUG
	dbt_print_table(_dtp, NULL);
#endif
	
	lock_release(&_tbc->sem);

	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);

    return 0;

error:
	lock_release(&_tbc->sem);
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	
	DBG("DBT:dbt_update: error while updating table!\n");
    
	return -1;
}
Example #9
0
File: prog.c Project: EmisFR/burp
int real_main(int argc, char *argv[])
{
	int ret=1;
	int option=0;
	int daemon=1;
	int forking=1;
	int strip=0;
	int randomise=0;
	struct lock *lock=NULL;
	struct conf **confs=NULL;
	int forceoverwrite=0;
	enum action act=ACTION_LIST;
	const char *backup=NULL;
	const char *backup2=NULL;
	char *restoreprefix=NULL;
	const char *regex=NULL;
	const char *browsefile=NULL;
	char *browsedir=NULL;
	const char *conffile=get_conf_path();
	const char *orig_client=NULL;
	const char *logfile=NULL;
	// The orig_client is the original client that the normal client
	// would like to restore from.
#ifndef HAVE_WIN32
	int generate_ca_only=0;
#endif
	int vss_restore=1;
	int test_confs=0;
	enum burp_mode mode;

	log_init(argv[0]);
#ifndef HAVE_WIN32
	if(!strcmp(prog, "bedup"))
		return run_bedup(argc, argv);
	if(!strcmp(prog, "bsigs"))
		return run_bsigs(argc, argv);
#endif

	while((option=getopt(argc, argv, "a:b:c:C:d:fFghil:nq:r:s:tvxjz:?"))!=-1)
	{
		switch(option)
		{
			case 'a':
				if(parse_action(&act, optarg)) goto end;
				break;
			case 'b':
				// The diff command may have two backups
				// specified.
				if(!backup2 && backup) backup2=optarg;
				if(!backup) backup=optarg;
				break;
			case 'c':
				conffile=optarg;
				break;
			case 'C':
				orig_client=optarg;
				break;
			case 'd':
				restoreprefix=optarg; // for restores
				browsedir=optarg; // for lists
				break;
			case 'f':
				forceoverwrite=1;
				break;
			case 'F':
				daemon=0;
				break;
			case 'g':
#ifndef HAVE_WIN32
				generate_ca_only=1;
#endif
				break;
			case 'i':
				cmd_print_all();
				ret=0;
				goto end;
			case 'l':
				logfile=optarg;
				break;
			case 'n':
				forking=0;
				break;
			case 'q':
				randomise=atoi(optarg);
				break;
			case 'r':
				regex=optarg;
				break;
			case 's':
				strip=atoi(optarg);
				break;
			case 'v':
				printf("%s-%s\n", progname(), VERSION);
				ret=0;
				goto end;
			case 'x':
				vss_restore=0;
				break;
			case 't':
				test_confs=1;
				break;
			case 'z':
				browsefile=optarg;
				break;
			case 'h':
			case '?':
			default:
				usage();
				goto end;
		}
	}
	if(optind<argc)
	{
		usage();
		goto end;
	}

	if(act==ACTION_MONITOR)
	{
		// Try to output everything in JSON.
		log_set_json(1);
#ifndef HAVE_WIN32
		// Need to do this so that processes reading stdout get the
		// result of the printfs of logp straight away.
		setlinebuf(stdout);
#endif
	}

	if(!(confs=confs_alloc()))
		goto end;

	if(reload(confs, conffile,
	  1 /* first time */,
	  0 /* no oldmax_children setting */,
	  0 /* no oldmax_status_children setting */))
		goto end;

	// Dry run to test config file syntax.
	if(test_confs)
	{
		ret=run_test_confs(confs, orig_client, conffile);
		goto end;
	}

	if(!backup) switch(act)
	{
		case ACTION_DELETE:
			logp("No backup specified for deletion.\n");
			goto end;
		case ACTION_RESTORE:
		case ACTION_VERIFY:
		case ACTION_DIFF:
		case ACTION_DIFF_LONG:
			logp("No backup specified. Using the most recent.\n");
			backup="0";
		default:
			break;
	}
	if(!backup2) switch(act)
	{
		case ACTION_DIFF:
		case ACTION_DIFF_LONG:
			logp("No second backup specified. Using file system scan.\n");
			backup2="n"; // For 'next'.
		default:
			break;
	}

	// The logfile option is only used for the status client stuff.
	if(logfile
	  && (act!=ACTION_STATUS
		&& act!=ACTION_STATUS_SNAPSHOT))
			logp("-l <logfile> option obsoleted\n");

	if(orig_client
	  && *orig_client
	  && set_string(confs[OPT_ORIG_CLIENT], orig_client))
		goto end;

	// The random delay needs to happen before the lock is got, otherwise
	// you would never be able to use burp by hand.
	if(randomise) set_int(confs[OPT_RANDOMISE], randomise);
	mode=get_e_burp_mode(confs[OPT_BURP_MODE]);
	if(mode==BURP_MODE_CLIENT
	  && (act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK))
		random_delay(confs);

	if(mode==BURP_MODE_SERVER
	  && act==ACTION_CHAMP_CHOOSER)
	{
		// These server modes need to run without getting the lock.
	}
	else if(mode==BURP_MODE_CLIENT
	  && (act==ACTION_LIST
		|| act==ACTION_LIST_LONG
		|| act==ACTION_DIFF
		|| act==ACTION_DIFF_LONG
		|| act==ACTION_STATUS
		|| act==ACTION_STATUS_SNAPSHOT
		|| act==ACTION_MONITOR))
	{
		// These client modes need to run without getting the lock.
	}
	else
	{
		const char *lockfile=confs_get_lockfile(confs);
		if(!(lock=lock_alloc_and_init(lockfile)))
			goto end;
		lock_get(lock);
		switch(lock->status)
		{
			case GET_LOCK_GOT: break;
			case GET_LOCK_NOT_GOT:
				logp("Could not get lockfile.\n");
				logp("Another process is probably running,\n");
				goto end;
			case GET_LOCK_ERROR:
			default:
				logp("Could not get lockfile.\n");
				logp("Maybe you do not have permissions to write to %s.\n", lockfile);
				goto end;
		}
	}

	set_int(confs[OPT_OVERWRITE], forceoverwrite);
	set_int(confs[OPT_STRIP], strip);
	set_int(confs[OPT_FORK], forking);
	set_int(confs[OPT_DAEMON], daemon);

	strip_trailing_slashes(&restoreprefix);
	strip_trailing_slashes(&browsedir);
	if(replace_conf_str(confs[OPT_BACKUP], backup)
	  || replace_conf_str(confs[OPT_BACKUP2], backup2)
	  || replace_conf_str(confs[OPT_RESTOREPREFIX], restoreprefix)
	  || replace_conf_str(confs[OPT_REGEX], regex)
	  || replace_conf_str(confs[OPT_BROWSEFILE], browsefile)
	  || replace_conf_str(confs[OPT_BROWSEDIR], browsedir)
	  || replace_conf_str(confs[OPT_MONITOR_LOGFILE], logfile))
		goto end;

	base64_init();
	hexmap_init();

	if(mode==BURP_MODE_SERVER)
	{
#ifdef HAVE_WIN32
		logp("Sorry, server mode is not implemented for Windows.\n");
#else
		ret=server_modes(act,
			conffile, lock, generate_ca_only, confs);
#endif
	}
	else
	{
		ret=client(confs, act, vss_restore);
	}

end:
	lock_release(lock);
	lock_free(&lock);
	confs_free(&confs);
	return ret;
}
Example #10
0
/*
 * Insert a row into table
 */
int dbt_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n)
{
	tbl_cache_p _tbc = NULL;
	dbt_table_p _dtp = NULL;
	dbt_row_p _drp = NULL;
	
	str stbl;
	int *lkey=NULL, i, j;
	
	if (!_h || !CON_TABLE(_h))
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:dbt_insert: Invalid parameter value\n");
#endif
		return -1;
	}
	if(!_k || !_v || _n<=0)
	{
#ifdef DBT_EXTRA_DEBUG
		DBG("DBT:dbt_insert: no key-value to insert\n");
#endif
		return -1;
	}
	
	stbl.s = (char*)CON_TABLE(_h);
	stbl.len = strlen(CON_TABLE(_h));

	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl);
	if(!_tbc)
	{
		DBG("DBT:db_insert: table does not exist!\n");
		return -1;
	}

	lock_get(&_tbc->sem);
	
	_dtp = _tbc->dtp;
	if(!_dtp)
	{
		DBG("DBT:db_insert: table does not exist!!\n");
		goto error;
	}
	
	if(_dtp->nrcols<_n)
	{
		DBG("DBT:db_insert: more values than columns!!\n");
		goto error;
	}
	
	if(_k)
	{
		lkey = dbt_get_refs(_dtp, _k, _n);
		if(!lkey)
			goto error;
	}
	_drp = dbt_row_new(_dtp->nrcols);
	if(!_drp)
	{
		DBG("DBT:db_insert: no memory for a new row!!\n");
		goto error;
	}
	
	for(i=0; i<_n; i++)
	{
		j = (lkey)?lkey[i]:i;
		if(dbt_is_neq_type(_dtp->colv[j]->type, _v[i].type))
		{
			DBG("DBT:db_insert: incompatible types v[%d] - c[%d]!\n", i, j);
			goto clean;
		}
		if(dbt_row_set_val(_drp, &(_v[i]), _v[i].type, j))
		{
			DBG("DBT:db_insert: cannot set v[%d] in c[%d]!\n", i, j);
			goto clean;
		}
		
	}

	if(dbt_table_add_row(_dtp, _drp))
	{
		DBG("DBT:db_insert: cannot insert the new row!!\n");
		goto clean;
	}

#ifdef DBT_EXTRA_DEBUG
	dbt_print_table(_dtp, NULL);
#endif
	
	lock_release(&_tbc->sem);

	if(lkey)
		pkg_free(lkey);

	DBG("DBT:db_insert: done!\n");

    return 0;
	
error:
	lock_release(&_tbc->sem);
	if(lkey)
		pkg_free(lkey);
	DBG("DBT:db_insert: error inserting row in table!\n");
    return -1;
	
clean:
	lock_release(&_tbc->sem);
	if(lkey)
		pkg_free(lkey);
	
	if(_drp) // free row
		dbt_row_free(_dtp, _drp);
	
	DBG("DBT:db_insert: make clean!\n");
    return -1;
}
Example #11
0
/*
 * Delete a row from table
 */
int dbt_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n)
{
	tbl_cache_p _tbc = NULL;
	dbt_table_p _dtp = NULL;
	dbt_row_p _drp = NULL, _drp0 = NULL;
	int *lkey = NULL;
	str stbl;

	if (!_h || !CON_TABLE(_h))
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:dbt_delete: Invalid parameter value\n");
#endif
		return -1;
	}
	stbl.s = (char*)CON_TABLE(_h);
	stbl.len = strlen(CON_TABLE(_h));

	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl);
	if(!_tbc)
	{
		DBG("DBT:dbt_delete: error loading table <%s>!\n", CON_TABLE(_h));
		return -1;
	}

	lock_get(&_tbc->sem);
	_dtp = _tbc->dtp;

	if(!_dtp)
	{
		DBG("DBT:dbt_delete: table does not exist!!\n");
		goto error;
	}
	
	if(!_k || !_v || _n<=0)
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:dbt_delete: delete all values\n");
#endif
		dbt_table_free_rows(_dtp);
		lock_release(&_tbc->sem);
		return 0;
	}

	lkey = dbt_get_refs(_dtp, _k, _n);
	if(!lkey)
		goto error;
	
	_drp = _dtp->rows;
	while(_drp)
	{
		_drp0 = _drp->next;
		if(dbt_row_match(_dtp, _drp, lkey, _o, _v, _n))
		{
			// delete row
			DBG("DBT:dbt_delete: deleting a row!\n");
			if(_drp->prev)
				(_drp->prev)->next = _drp->next;
			else
				_dtp->rows = _drp->next;
			if(_drp->next)
				(_drp->next)->prev = _drp->prev;
			_dtp->nrrows--;
			// free row
			dbt_row_free(_dtp, _drp);
		}
		_drp = _drp0;
	}

	dbt_table_update_flags(_dtp, DBT_TBFL_MODI, DBT_FL_SET, 1);
	
#ifdef DBT_EXTRA_DEBUG
	dbt_print_table(_dtp, NULL);
#endif
	
	lock_release(&_tbc->sem);
	
	if(lkey)
		pkg_free(lkey);
	
	return 0;
	
error:
	lock_release(&_tbc->sem);
	DBG("DBT:dbt_delete: error deleting from table!\n");
    
	return -1;
}
Example #12
0
int dbt_query(db_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, db_res_t** _r)
{
	tbl_cache_p _tbc = NULL;
	dbt_table_p _dtp = NULL;
	dbt_row_p _drp = NULL;
	dbt_result_p _dres = NULL;
	
	str stbl;
	int *lkey=NULL, *lres=NULL;
	
	if ((!_h) || (!_r) || !CON_TABLE(_h))
	{
#ifdef DBT_EXTRA_DEBUG
		LOG(L_ERR, "DBT:dbt_query: Invalid parameter value\n");
#endif
		return -1;
	}
	
	stbl.s = (char*)CON_TABLE(_h);
	stbl.len = strlen(CON_TABLE(_h));

	_tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl);
	if(!_tbc)
	{
		DBG("DBT:dbt_query: table does not exist!\n");
		return -1;
	}

	lock_get(&_tbc->sem);
	_dtp = _tbc->dtp;

	if(!_dtp || _dtp->nrcols < _nc)
	{
		DBG("DBT:dbt_query: table not loaded!\n");
		goto error;
	}
	if(_k)
	{
		lkey = dbt_get_refs(_dtp, _k, _n);
		if(!lkey)
			goto error;
	}
	if(_c)
	{
		lres = dbt_get_refs(_dtp, _c, _nc);
		if(!lres)
			goto error;
	}

	DBG("DBT:dbt_query: new res with %d cols\n", _nc);
	_dres = dbt_result_new(_dtp, lres, _nc);
	
	if(!_dres)
		goto error;
	
	_drp = _dtp->rows;
	while(_drp)
	{
		if(dbt_row_match(_dtp, _drp, lkey, _op, _v, _n))
		{
			if(dbt_result_extract_fields(_dtp, _drp, lres, _dres))
			{
				DBG("DBT:dbt_query: error extracting result fields!\n");
				goto clean;
			}
		}
		_drp = _drp->next;
	}

	dbt_table_update_flags(_dtp, DBT_TBFL_ZERO, DBT_FL_IGN, 1);
	
	lock_release(&_tbc->sem);

#ifdef DBT_EXTRA_DEBUG
	dbt_result_print(_dres);
#endif
	
	DBT_CON_RESULT(_h) = _dres;
	
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);

	return dbt_get_result(_h, _r);

error:
	lock_release(&_tbc->sem);
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	DBG("DBT:dbt_query: error while querying table!\n");
    
	return -1;

clean:
	lock_release(&_tbc->sem);
	if(lkey)
		pkg_free(lkey);
	if(lres)
		pkg_free(lres);
	if(_dres)
		dbt_result_free(_dres);
	DBG("DBT:dbt_query: make clean\n");

	return -1;
}
Example #13
0
int notify_ebr_subscriptions( ebr_event *ev, evi_params_t *params)
{
	ebr_subscription *sub, *sub_next, *sub_prev;
	ebr_filter *filter;
	ebr_ipc_job *job;
	evi_param_t *e_param;
	int matches;
	char *s;
	struct usr_avp *avps=(void*)-1;
	unsigned int my_time;

	LM_DBG("notification received for event %.*s, checking subscriptions\n",
		ev->event_name.len, ev->event_name.s);

	my_time = get_ticks();

	lock_get( &(ev->lock) );

	/* check the EBR subscription on this event and apply the filters */
	sub_prev = NULL;
	for ( sub=ev->subs ; sub ; sub_prev=sub,
								sub=sub_next?sub_next:(sub?sub->next:NULL) ) {

		/* discard expired NOTIFY subscriptions */
		if (sub->flags&EBR_SUBS_TYPE_NOTY && sub->expire<my_time) {
			LM_DBG("subscription type [NOTIFY]from process %d(pid %d) on "
				"event <%.*s> expired at %d\n",
				sub->proc_no, pt[sub->proc_no].pid,
				sub->event->event_name.len, sub->event->event_name.s,
				sub->expire );
			/* remove the subscription */
			sub_next = sub->next;
			/* unlink it */
			if (sub_prev) sub_prev->next = sub_next;
			else ev->subs = sub_next;
			/* free it */
			free_ebr_subscription(sub);
			/* do not count us as prev, as we are removed */
			sub = sub_prev;
			continue;
		}

		/* run the filters */
		matches = 1;
		sub_next = NULL;
		for ( filter=sub->filters ; matches && filter ; filter=filter->next ) {

			/* look for the evi param with the same name */
			for ( e_param=params->first ; e_param ; e_param=e_param->next ) {

				if (e_param->name.len==filter->key.len &&
				strncasecmp(e_param->name.s,filter->key.s,filter->key.len)==0){

					/* name matches, let's see the value */
					LM_DBG("key <%.*s> found, checking value \n",
						filter->key.len, filter->key.s);

					if (filter->val.len==0) {
						/* a "no value" matches anything */
					} else {
						if (e_param->flags&EVI_INT_VAL) {
							s=int2str((unsigned long)e_param->val.n, NULL);
							if (s==NULL) {
								LM_ERR("failed to covert int EVI param to "
									"string, EBR filter failed\n");
								matches = 0;
							} else {
								/* the output of int2str is NULL terminated */
								if (fnmatch( filter->val.s, s, 0)!=0)
									matches = 0;
							}
						} else
						if (e_param->flags&EVI_STR_VAL) {
							s=(char*)pkg_malloc(e_param->val.s.len+1);
							if (s==NULL) {
								LM_ERR("failed to allocate PKG fnmatch "
									"buffer, EBR filter failed\n");
								matches = 0;
							} else {
								memcpy(s,e_param->val.s.s,e_param->val.s.len);
								s[e_param->val.s.len] = 0;
								if (fnmatch( filter->val.s, s, 0)!=0)
									matches = 0;
								pkg_free(s);
							}
						} else {
							LM_ERR("non-string EVI params are not supported "
								"yet\n");
							matches = 0;
						}
					}
					break;

				}
				/* a filter not matching any EVI params is simply ignored */

			} /* end EVI param iterator */

		} /* end EBR filter iterator */

		/* did the EVI event match the EBR filters for this subscription ? */
		if (matches) {

			LM_DBG("subscription type [%s]from process %d(pid %d) matched "
				"event, generating notification via IPC\n",
				(sub->flags&EBR_SUBS_TYPE_WAIT)?"WAIT":"NOTIFY",
				sub->proc_no, pt[sub->proc_no].pid);

			/* convert the EVI params into AVP (only once) */
			if (avps==(void*)-1) {
				avps = pack_evi_params_as_avp_list(params);
			}

			/* pack the EVI params to be attached to the IPC job */
			job =(ebr_ipc_job*)shm_malloc( sizeof(ebr_ipc_job) );
			if (job==NULL) {
				LM_ERR("failed to allocated new IPC job, skipping..\n");
				continue; /* with the next subscription */
			}
			job->ev = ev;
			job->avps = clone_avp_list( avps );
			job->data = sub->data;
			job->flags = sub->flags;
			job->tm = sub->tm;

			if (sub->flags&EBR_SUBS_TYPE_NOTY) {
				/* dispatch the event notification via IPC to the right 
				 * process. Key question - which one is the "right" process ?
				 *   - the current processs
				 *   - the process which performed the subscription
				 * Let's give it to ourselves for the moment */
				if (ipc_send_job( process_no, ebr_ipc_type , (void*)job)<0) {
					LM_ERR("failed to send job via IPC, skipping...\n");
					shm_free(job);
				}
			} else {
				/* sent the event notification via IPC to resume on the
				 * subscribing process */
				if (ipc_send_job( sub->proc_no, ebr_ipc_type , (void*)job)<0) {
					LM_ERR("failed to send job via IPC, skipping...\n");
					shm_free(job);
				}
				/* remove the subscription, as it can be triggered only 
				 * one time */
				sub_next = sub->next;
				/* unlink it */
				if (sub_prev) sub_prev->next = sub_next;
				else ev->subs = sub_next;
				/* free it */
				free_ebr_subscription(sub);
				/* do not count us as prev, as we are removed */
				sub = sub_prev;
			}

		}

	} /* end EBR subscription iterator */

	lock_release( &(ev->lock) );

	if (avps!=(void*)-1)
		destroy_avp_list( &avps );

	return 0;
}
Example #14
0
/*! \brief
 *  handle io routine, based on the fd_map type
 * (it will be called from reactor_main_loop )
 * params:  fm  - pointer to a fd hash entry
 *          idx - index in the fd_array (or -1 if not known)
 * return: -1 on error, or when we are not interested any more on reads
 *            from this fd (e.g.: we are closing it )
 *          0 on EAGAIN or when by some other way it is known that no more
 *            io events are queued on the fd (the receive buffer is empty).
 *            Usefull to detect when there are no more io events queued for
 *            sigio_rt, epoll_et, kqueue.
 *         >0 on successfull read from the fd (when there might be more io
 *            queued -- the receive buffer might still be non-empty)
 */
inline static int handle_io(struct fd_map* fm, int idx,int event_type)
{
	int ret=0;
	int n;
	struct tcp_connection* con;
	int s,rw;
	long resp;
	long response[2];

	switch(fm->type){
		case F_TIMER_JOB:
			handle_timer_job();
			break;
		case F_SCRIPT_ASYNC:
			async_resume_f( &fm->fd, fm->data);
			return 0;
		case F_TCPMAIN:
again:
			ret=n=receive_fd(fm->fd, response, sizeof(response), &s, 0);
			if (n<0){
				if (errno == EWOULDBLOCK || errno == EAGAIN){
					ret=0;
					break;
				}else if (errno == EINTR) goto again;
				else{
					LM_CRIT("read_fd: %s \n", strerror(errno));
						abort(); /* big error*/
				}
			}
			if (n==0){
				LM_WARN("0 bytes read\n");
				break;
			}
			con = (struct tcp_connection *)response[0];
			rw = (int)response[1];

			if (con==0){
					LM_CRIT("null pointer\n");
					break;
			}
			if (s==-1) {
				LM_BUG("read_fd:no fd read\n");
				/* FIXME? */
				return -1;
			}
			if (con==tcp_conn_lst){
				LM_CRIT("duplicate"
							" connection received: %p, id %d, fd %d, refcnt %d"
							" state %d (n=%d)\n", con, con->id, con->fd,
							con->refcnt, con->state, n);
				tcpconn_release(con, CONN_ERROR,0);
				break; /* try to recover */
			}

			LM_DBG("We have received conn %p with rw %d on fd %d\n",con,rw,s);
			if (rw & IO_WATCH_READ) {
				/* 0 attempts so far for this SIP MSG */
				con->msg_attempts = 0;

				/* must be before reactor_add, as the add might catch some
				 * already existing events => might call handle_io and
				 * handle_io might decide to del. the new connection =>
				 * must be in the list */
				tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev);
				con->timeout = con->lifetime;
				if (reactor_add_reader( s, F_TCPCONN, RCT_PRIO_NET, con )<0) {
					LM_CRIT("failed to add new socket to the fd list\n");
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					goto con_error;
				}

				/* mark that the connection is currently in our process
				future writes to this con won't have to acquire FD */
				con->proc_id = process_no;
				/* save FD which is valid in context of this TCP worker */
				con->fd=s;
			} else if (rw & IO_WATCH_WRITE) {
				LM_DBG("Received con for async write %p ref = %d\n",con,con->refcnt);
				lock_get(&con->write_lock);
				resp = protos[con->type].net.write( (void*)con, s );
				lock_release(&con->write_lock);
				if (resp<0) {
					ret=-1; /* some error occured */
					con->state=S_CONN_BAD;
					tcpconn_release(con, CONN_ERROR,1);
					break;
				} else if (resp==1) {
					tcpconn_release(con, ASYNC_WRITE,1);
				} else {
					tcpconn_release(con, CONN_RELEASE,1);
				}
				ret = 0;
				/* we always close the socket received for writing */
				close(s);
			}
			break;
		case F_TCPCONN:
			if (event_type & IO_WATCH_READ) {
				con=(struct tcp_connection*)fm->data;
				resp = protos[con->type].net.read( (void*)con, &ret );
				if (resp<0) {
					ret=-1; /* some error occured */
					con->state=S_CONN_BAD;
					reactor_del_all( con->fd, idx, IO_FD_CLOSING );
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					con->proc_id = -1;
					if (con->fd!=-1) { close(con->fd); con->fd = -1; }
					tcpconn_release(con, CONN_ERROR,0);
				} else if (con->state==S_CONN_EOF) {
					reactor_del_all( con->fd, idx, IO_FD_CLOSING );
					tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev);
					con->proc_id = -1;
					if (con->fd!=-1) { close(con->fd); con->fd = -1; }
					tcpconn_release(con, CONN_EOF,0);
				} else {
					//tcpconn_release(con, CONN_RELEASE);
					/* keep the connection for now */
					break;
				}
			}
			break;
		case F_NONE:
			LM_CRIT("empty fd map %p: "
						"{%d, %d, %p}\n", fm,
						fm->fd, fm->type, fm->data);
			goto error;
		default:
			LM_CRIT("uknown fd type %d\n", fm->type);
			goto error;
	}

	return ret;
con_error:
	con->state=S_CONN_BAD;
	tcpconn_release(con, CONN_ERROR,0);
	return ret;
error:
	return -1;
}
Example #15
0
dlg_t * build_dlg_t(struct dlg_cell * cell, int dir) {

    dlg_t* td = NULL;
    str cseq;
    unsigned int loc_seq;
    str route_set;
    str contact;

    struct dlg_cell_out *dlg_out = 0;
    struct dlg_entry_out* dlg_entry_out = 0;

    /* if trying to send by to callee we need to get the corresponding dlg_out cell */
    lock_get(cell->dlg_out_entries_lock);
    dlg_entry_out = &cell->dlg_entry_out;

    dlg_out = dlg_entry_out->first;
    //must be concurrent call - lets choose - TODO - ie. check if there is more

    if (!dlg_out) {
        LM_ERR("Trying to send BYE for dialog with no callee leg\n");
        lock_release(cell->dlg_out_entries_lock);
        return NULL;
    }

    td = (dlg_t*) pkg_malloc(sizeof (dlg_t));
    if (!td) {

        LM_ERR("out of pkg memory\n");
        lock_release(cell->dlg_out_entries_lock);
        return NULL;
    }
    memset(td, 0, sizeof (dlg_t));

    if (dir == DLG_CALLER_LEG) {
        cseq = cell->first_req_cseq;
        route_set = cell->caller_route_set;
        contact = cell->caller_contact;
        td->rem_uri = cell->from_uri;
        td->loc_uri = dlg_out->to_uri;
        td->id.rem_tag = cell->from_tag;
        td->id.loc_tag = dlg_out->to_tag;
        td->send_sock = cell->caller_bind_addr;
    } else {
        cseq = dlg_out->callee_cseq;
        route_set = dlg_out->callee_route_set;
        contact = dlg_out->callee_contact;
        td->rem_uri = dlg_out->to_uri;
        td->loc_uri = cell->from_uri;
        td->id.rem_tag = dlg_out->to_tag;
        td->id.loc_tag = cell->from_tag;
        td->send_sock = dlg_out->callee_bind_addr;
    }

    if (str2int(&cseq, &loc_seq) != 0) {
        LM_ERR("invalid cseq\n");
        goto error;
    }

    /*we don not increase here the cseq as this will be done by TM*/
    td->loc_seq.value = loc_seq;
    td->loc_seq.is_set = 1;

    /*route set*/
    if (route_set.s && route_set.len) {

        if (parse_rr_body(route_set.s, route_set.len, &td->route_set) != 0) {
            LM_ERR("failed to parse route set\n");
            goto error;
        }
    }

    if (contact.s == 0 || contact.len == 0) {

        LM_ERR("no contact available\n");
        goto error;
    }

    td->id.call_id = cell->callid;
    td->rem_target = contact;
    td->state = DLG_CONFIRMED;

    lock_release(cell->dlg_out_entries_lock);
    return td;

error:
    lock_release(cell->dlg_out_entries_lock);
    free_tm_dlg(td);
    return NULL;
}
Example #16
0
void sipwatch_lock(void)
{
  lock_get(&siplua_watch->lock);
}
Example #17
0
int uac_reg_db_refresh(str *pl_uuid)
{
	db1_con_t *reg_db_con = NULL;
	db_func_t reg_dbf;
	reg_uac_t reg;
	db_key_t db_cols[12] = {
		&l_uuid_column,
		&l_username_column,
		&l_domain_column,
		&r_username_column,
		&r_domain_column,
		&realm_column,
		&auth_username_column,
		&auth_password_column,
		&auth_proxy_column,
		&expires_column,
		&flags_column,
		&reg_delay_column
	};
	db_key_t db_keys[1] = {&l_uuid_column};
	db_val_t db_vals[1];

	db1_res_t* db_res = NULL;
	int i, ret;

	/* binding to db module */
	if(reg_db_url.s==NULL)
	{
		LM_ERR("no db url\n");
		return -1;
	}

	if(db_bind_mod(&reg_db_url, &reg_dbf))
	{
		LM_ERR("database module not found\n");
		return -1;
	}

	if (!DB_CAPABILITY(reg_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 */
	reg_db_con = reg_dbf.init(&reg_db_url);
	if(reg_db_con==NULL)
	{
		LM_ERR("failed to connect to the database\n");
		return -1;
	}
	if (reg_dbf.use_table(reg_db_con, &reg_db_table) < 0)
	{
		LM_ERR("failed to use_table\n");
		return -1;
	}

	db_vals[0].type = DB1_STR;
	db_vals[0].nul = 0;
	db_vals[0].val.str_val.s = pl_uuid->s;
	db_vals[0].val.str_val.len = pl_uuid->len;

	if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols,
					1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0
			|| RES_ROW_N(db_res)<=0 )
	{
		reg_dbf.free_result(reg_db_con, db_res);
		if( ret==0)
		{
			return 0;
		} else {
			goto error;
		}
	}

	memset(&reg, 0, sizeof(reg_uac_t));;
	i = 0;
	/* check for NULL values ?!?! */
	reg_db_set_attr(l_uuid, 0);
	reg_db_set_attr(l_username, 1);
	reg_db_set_attr(l_domain, 2);
	reg_db_set_attr(r_username, 3);
	reg_db_set_attr(r_domain, 4);
	/* realm may be empty */
	if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) {
		reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val);
		reg.realm.len = strlen(reg.realm.s);
	}
	reg_db_set_attr(auth_username, 6);
	reg_db_set_attr(auth_password, 7);
	reg_db_set_attr(auth_proxy, 8);
	reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val;
	reg.h_uuid = reg_compute_hash(&reg.l_uuid);
	reg.h_user = reg_compute_hash(&reg.l_username);
	reg.flags = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val;
	reg.reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val;

	lock_get(_reg_htable_gc_lock);
	if(reg_ht_get_byuuid(pl_uuid)!=NULL)
	{
		if(reg_ht_update_attrs(&reg)<0)
		{
			lock_release(_reg_htable_gc_lock);
			LM_ERR("Error updating reg to htable\n");
			goto error;
		}
	} else {
		if(reg_ht_add(&reg)<0)
		{
			lock_release(_reg_htable_gc_lock);
			LM_ERR("Error adding reg to htable\n");
			goto error;
		}
	}
	lock_release(_reg_htable_gc_lock);

	reg_dbf.free_result(reg_db_con, db_res);
	reg_dbf.close(reg_db_con);

	return 0;

error:
	if (reg_db_con) {
		reg_dbf.free_result(reg_db_con, db_res);
		reg_dbf.close(reg_db_con);
	}
	return -1;
}
Example #18
0
/**
 * Print the contents of an ims_subscription structure.
 * @param log_level - level to log on
 * @param s - the ims_subscription to be printed
 */
void print_user_data(int log_level,ims_subscription *s)
{
	int i,j,k;
	LOG(log_level,"INF:"M_NAME":IMSSubscription:\n");
	if (!s) return;
	lock_get(s->lock);
	LOG(log_level,"INF:"M_NAME":\tPrivate Identity: <%.*s>\n",s->private_identity.len,s->private_identity.s);
	for(i=0;i<s->service_profiles_cnt;i++){
		LOG(log_level,"INF:"M_NAME":\tService Profile:\n");
		for(j=0;j<s->service_profiles[i].public_identities_cnt;j++){	
			LOG(log_level,"INF:"M_NAME":\t\tPublic Identity: Barring [%d] <%.*s> \n",
				s->service_profiles[i].public_identities[j].barring,
				s->service_profiles[i].public_identities[j].public_identity.len,
				s->service_profiles[i].public_identities[j].public_identity.s);			
		}
		for(j=0;j<s->service_profiles[i].filter_criteria_cnt;j++){	
			LOG(log_level,"INF:"M_NAME":\t\tFilter Criteria: Priority [%d]ProfilePartInd [%d]\n",
				s->service_profiles[i].filter_criteria[j].priority,
				s->service_profiles[i].filter_criteria[j].profile_part_indicator?
				 *(s->service_profiles[i].filter_criteria[j].profile_part_indicator):-1 );				
			if (s->service_profiles[i].filter_criteria[j].trigger_point){
				LOG(log_level,"INF:"M_NAME":\t\t\tTrigger Point: CNF [%c] %s\n",
					s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?'X':' ',
					s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?"(_|_)&(_|_)":"(_&_)|(_&_)"
					);											
				for(k=0;k<s->service_profiles[i].filter_criteria[j].trigger_point->spt_cnt;k++){	
					LOG(log_level,"INF:"M_NAME":\t\t\t\tSPT: Grp[%d] NOT[%c] RegType[%d]\n",
						s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].group,
						s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].condition_negated?'X':' ',
						s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].registration_type
					);																
					switch(s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].type){
						case 1:
							LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Request-URI == <%.*s>\n",
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.s);
							break;
						case 2:
							LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Method == <%.*s>\n",
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.s);
							break;
						case 3:
							LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Hdr(%.*s(%d)) == <%.*s>\n",
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.s,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.type,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.s);
							break;
						case 4:
							LOG(log_level,"INF:"M_NAME":\t\t\t\t\t SessionCase [%d]\n",
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_case);
							break;
						case 5:
							LOG(log_level,"INF:"M_NAME":\t\t\t\t\t SDP(%.*s) == <%.*s>\n",
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.s,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.len,
								s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.s);
							break;							
					}
				}					
			}	 		
			LOG(log_level,"INF:"M_NAME":\t\t\tAS: <%.*s> Handling [%d] SrvInfo: <%.*s>\n",
				s->service_profiles[i].filter_criteria[j].application_server.server_name.len,
				s->service_profiles[i].filter_criteria[j].application_server.server_name.s,
				s->service_profiles[i].filter_criteria[j].application_server.default_handling,
				s->service_profiles[i].filter_criteria[j].application_server.service_info.len,				
				s->service_profiles[i].filter_criteria[j].application_server.service_info.s);							
		}
		if (s->service_profiles[i].cn_service_auth){
			LOG(log_level,"INF:"M_NAME":\t\tCN Serv Auth: Subs Media Profile ID [%d]\n",
				s->service_profiles[i].cn_service_auth->subscribed_media_profile_id);			
		}		
		for(j=0;j<s->service_profiles[i].shared_ifc_set_cnt;j++){	
			LOG(log_level,"INF:"M_NAME":\t\tShared IFC Set: [%d]\n",
				s->service_profiles[i].shared_ifc_set[j]);			
		}		
	}
	lock_release(s->lock);
}
Example #19
0
static void rpc_uac_reg_update_flag(rpc_t* rpc, void* ctx, int mode, int fval)
{
	int i;
	reg_item_t *reg = NULL;
	str attr = {0};
	str val = {0};
	str *rval;

	if(_reg_htable==NULL)
	{
		rpc->fault(ctx, 500, "Not enabled");
		return;
	}

	if(rpc->scan(ctx, "S.S", &attr, &val)<2)
	{
		rpc->fault(ctx, 500, "Invalid Parameters");
		return;
	}
	if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
	{
		LM_ERR("bad parameter values\n");
		rpc->fault(ctx, 500, "Invalid Parameter Values");
		return;
	}

	for(i=0; i<_reg_htable->htsize; i++)
	{
		lock_get(&_reg_htable->entries[i].lock);
		/* walk through entries */
		reg = _reg_htable->entries[i].byuuid;
		while(reg)
		{
			if(attr.len==10 && strncmp(attr.s, "l_username", 10)==0) {
				rval = &reg->r->l_username;
			} else if(attr.len==10 && strncmp(attr.s, "r_username", 10)==0) {
				rval = &reg->r->r_username;
			} else if(attr.len==6 && strncmp(attr.s, "l_uuid", 6)==0) {
				rval = &reg->r->l_uuid;
			} else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) {
				rval = &reg->r->auth_username;
			} else {
				lock_release(&_reg_htable->entries[i].lock);
				LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s);
				rpc->fault(ctx, 500, "Unsupported Filter Attribtue");
				return;
			}

			if(rval->len==val.len && strncmp(val.s, rval->s, val.len)==0) {
				/* found */
				if(mode==1) {
					reg->r->flags |= fval;
				} else {
					reg->r->flags &= ~fval;
				}
				reg->r->timer_expires = time(NULL) + 1;
				lock_release(&_reg_htable->entries[i].lock);
				return;
			}
			reg = reg->next;
		}
		lock_release(&_reg_htable->entries[i].lock);
	}
}
Example #20
0
int w_rl_check_3(struct sip_msg *_m, char *_n, char *_l, char *_a)
{
	str name;
	int limit = 0, ret = 1, should_update = 0;
	str algorithm;
	unsigned int hash_idx;
	rl_pipe_t **pipe;

	rl_algo_t algo = -1;

	/* retrieve and check parameters */
	if (!_n || !_l) {
		LM_ERR("invalid parameters\n");
		goto end;
	}
	if (fixup_get_svalue(_m, (gparam_p)_n, &name) < 0) {
		LM_ERR("cannot retrieve identifier\n");
		goto end;
	}
	if (fixup_get_ivalue(_m, (gparam_p)_l, &limit) < 0) {
		LM_ERR("cannot retrieve limit\n");
		goto end;
	}
	algorithm.s = 0;
	if (!_a || fixup_get_svalue(_m, (gparam_p)_a, &algorithm) < 0 ||
			(algo = get_rl_algo(algorithm)) < 0) {
		algo = PIPE_ALGO_NOP;
	}

	/* get limit for FEEDBACK algorithm */
	if (algo == PIPE_ALGO_FEEDBACK) {
		lock_get(rl_lock);
		if (*rl_feedback_limit) {
			if (*rl_feedback_limit != limit) {
				LM_WARN("FEEDBACK limit should be the same for all pipes, but"
						" new limit %d differs - setting to %d\n",
						limit, *rl_feedback_limit);
				limit = *rl_feedback_limit;
			}
		} else {
			if (limit <= 0 || limit >= 100) {
				LM_ERR("invalid limit for FEEDBACK algorithm "
					"(must be between 0 and 100)\n");
				lock_release(rl_lock);
				goto end;
			}
			*rl_feedback_limit = limit;
			pid_setpoint_limit(limit);
		}
		lock_release(rl_lock);
	}

	hash_idx = RL_GET_INDEX(name);
	RL_GET_LOCK(hash_idx);

	/* try to get the value */
	pipe = RL_GET_PIPE(hash_idx, name);
	if (!pipe) {
		LM_ERR("cannot get the index\n");
		goto release;
	}

	if (!*pipe) {
		/* allocate new pipe */
		*pipe = shm_malloc(sizeof(rl_pipe_t));
		if (!*pipe) {
			LM_ERR("no more shm memory\n");
			goto release;
		}
		memset(*pipe, 0, sizeof(rl_pipe_t));
		LM_DBG("Pipe %.*s doens't exist, but was created %p\n",
				name.len, name.s, *pipe);
		if (algo == PIPE_ALGO_NETWORK)
			should_update = 1;
		(*pipe)->algo = (algo == PIPE_ALGO_NOP) ? rl_default_algo : algo;
	} else {
		LM_DBG("Pipe %.*s found: %p - last used %lu\n",
				name.len, name.s, *pipe, (*pipe)->last_used);
		if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) {
			LM_WARN("algorithm %d different from the initial one %d for pipe "
					"%.*s", algo, (*pipe)->algo, name.len, name.s);
		}
	}

	/* set/update the limit */
	(*pipe)->limit = limit;

	/* set the last used time */
	(*pipe)->last_used = time(0);
	if (RL_USE_CDB(*pipe)) {
		/* release the counter for a while */
		if (rl_change_counter(&name, *pipe, 1) < 0) {
			LM_ERR("cannot increase counter\n");
			goto end;
		}
	} else {
		(*pipe)->counter++;
	}

	ret = rl_pipe_check(*pipe);
	LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n",
			name.len, name.s, (*pipe)->counter, (*pipe)->load,
			(*pipe)->limit, ret == 1? "NOT " : "", *pipe);


release:
	RL_RELEASE_LOCK(hash_idx);
	if (should_update) {
		lock_get(rl_lock);
		(*rl_network_count)++;
		lock_release(rl_lock);
	}
end:
	return ret;
}
Example #21
0
static void rpc_add(rpc_t* rpc, void* c)
{
	db_key_t db_keys[NR_KEYS] = {prefix_column, domain_column};
	db_val_t db_vals[NR_KEYS];
	db_op_t  db_ops[NR_KEYS] = {OP_EQ, OP_EQ};

	pd_t* cell;
	pd_op_t *ito, *tmp;
	str sd, sp;
	char* t;

	if(_dhash==NULL) {
		LOG(L_ERR, "PDT:pdt_fifo_add: strange situation\n");
		rpc->fault(c, 500, "Server Error");
		return;
	}

	     /* Use 's' to make sure strings are zero terminated */
	if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) {
		rpc->fault(c, 400, "Invalid Parameter Value");
		return;
	}
	sp.len = strlen(sp.s);
	sd.len = strlen(sd.s);

	t = sp.s;
	while(t!=NULL && *t!='\0') {
		if(*t < '0' || *t > '9') {
			LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s);
			rpc->fault(c, 400, "Bad Prefix");
			return;
		}
		t++;
	}

	if(pdt_check_pd(_dhash, &sp, &sd)!=0) {
		LOG(L_ERR, "PDT:pdt_fifo_add: prefix or domain exists\n");
		rpc->fault(c, 400, "Prefix Or Domain Exists");
		return;
	}

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

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

	DBG("PDT:pdt_fifo_add: [%.*s] <%.*s>\n", sp.len, sp.s, sd.len, sd.s);

	     /* insert a new domain into database */
	if(pdt_dbf.insert(db_con, db_keys, db_vals, NR_KEYS)<0) {
		LOG(L_ERR, "PDT:pdt_fifo_add: error storing new prefix/domain\n");
		rpc->fault(c, 430, "Cannot Store Prefix/domain");
		return;
	}

	     /* insert the new domain into hashtables, too */
	cell = new_cell(&sp, &sd);
	if(cell==NULL) {
		LOG(L_ERR, "PDT:pdt_fifo_add: no more shm\n");
		rpc->fault(c, 431, "Out Of Shared Memory");
		goto error1;
	}
	tmp = new_pd_op(cell, 0, PDT_ADD);
	if(tmp==NULL) {
		LOG(L_ERR, "PDT:pdt_fifo_add: no more shm!\n");
		rpc->fault(c, 431, "Out Of Shared Memory");
		goto error2;
	}

	lock_get(&_dhash->diff_lock);

	if(pdt_add_to_hash(_dhash, &sp, &sd)!=0) {
		LOG(L_ERR, "PDT:pdt_fifo_add: could not add to cache\n");
		rpc->fault(c, 431, "Could Not Add To Cache");
		goto error3;
	}

	_dhash->max_id++;
	tmp->id = _dhash->max_id;
	if(_dhash->diff==NULL) {
		_dhash->diff = tmp;
		goto done;
	}
	ito = _dhash->diff;
	while(ito->n!=NULL)
		ito = ito->n;

	ito->n = tmp;
	tmp->p = ito;

 done:
	DBG("PDT:pdt_fifo_add: op[%d]=%d...\n", tmp->id, tmp->op);
	lock_release(&_dhash->diff_lock);
	return;

 error3:
	lock_release(&_dhash->diff_lock);
	free_pd_op(tmp);
 error2:
	free_cell(cell);
 error1:
	if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, NR_KEYS)<0)
		LOG(L_ERR,"PDT:pdt_fifo_add: database/cache are inconsistent\n");
}
Example #22
0
/* timer housekeeping, invoked each timer interval to reset counters */
void rl_timer(unsigned int ticks, void *param)
{
	unsigned int i = 0;
	map_iterator_t it, del;
	rl_pipe_t **pipe;
	str *key;
	void *value;
	unsigned long now = time(0);

	/* get CPU load */
	if (get_cpuload() < 0) {
		LM_ERR("cannot update CPU load\n");
		i = 1;
	}

	lock_get(rl_lock);
	/* if CPU was successfully loaded */
	if (!i)
		do_update_load();


	/* update network if needed */
	if (*rl_network_count)
		*rl_network_load = get_total_bytes_waiting(PROTO_NONE);
	lock_release(rl_lock);

	/* iterate through each map */
	for (i = 0; i < rl_htable.size; i++) {
		RL_GET_LOCK(i);
		/* iterate through all the entries */
		if (map_first(rl_htable.maps[i], &it) < 0) {
			LM_ERR("map doesn't exist\n");
			goto next_map;
		}
		for (; iterator_is_valid(&it);) {
			pipe = (rl_pipe_t **)iterator_val(&it);
			if (!pipe || !*pipe) {
				LM_ERR("[BUG] bogus map[%d] state\n", i);
				goto next_pipe;
			}
			key = iterator_key(&it);
			if (!key) {
				LM_ERR("cannot retrieve pipe key\n");
				goto next_pipe;
			}
			/* check to see if it is expired */
			if ((*pipe)->last_used + rl_expire_time < now) {
				/* this pipe is engaged in a transaction */
				del = it;
				if (iterator_next(&it) < 0)
					LM_DBG("cannot find next iterator\n");
				if ((*pipe)->algo == PIPE_ALGO_NETWORK) {
					lock_get(rl_lock);
					(*rl_network_count)--;
					lock_release(rl_lock);
				}
				LM_DBG("Deleting ratelimit pipe key \"%.*s\"\n",
						key->len, key->s);
				value = iterator_delete(&del);
				/* free resources */
				if (value)
					shm_free(value);
				continue;
			} else {
				/* leave the lock if a cachedb query should be done*/
				if (RL_USE_CDB(*pipe)) {
					if (rl_get_counter(key, *pipe) < 0) {
						LM_ERR("cannot get pipe counter\n");
						goto next_pipe;
					}
				}
				switch ((*pipe)->algo) {
					case PIPE_ALGO_NETWORK:
						/* handle network algo */
						(*pipe)->load =
							(*rl_network_load > (*pipe)->limit) ? -1 : 1;
						break;

					case PIPE_ALGO_RED:
						if ((*pipe)->limit && rl_timer_interval)
							(*pipe)->load = (*pipe)->counter /
								((*pipe)->limit * rl_timer_interval);
						break;
					default:
						break;
				}
				(*pipe)->last_counter = rl_get_all_counters(*pipe);
				if (RL_USE_CDB(*pipe)) {
					if (rl_change_counter(key, *pipe, 0) < 0) {
						LM_ERR("cannot reset counter\n");
					}
				} else {
					(*pipe)->counter = 0;
				}
			}
next_pipe:
			if (iterator_next(&it) < 0)
				break;
			}
next_map:
		RL_RELEASE_LOCK(i);
	}
}
Example #23
0
/**
 *      Fifo command example:
 *
 *      ---
 *       :pdt_list:[response_file]\n
 *       prefix\n
 *       domain\n
 *       \n
 *      --
 *
 *      - '.' (dot) means NULL value for [prefix] and [domain]
 *      - if both [prefix] and [domain] are NULL, all prefix-domain pairs are listed
 *      - the comparison operation is 'START WITH' -- if domain is 'a' then
 *        all domains starting with 'a' are listed
 */
static void rpc_list(rpc_t* rpc, void* c)
{
	str sd, sp;
	pd_t *it;
	int i;
	char* buf1, *buf2, *t;

	if(_dhash==NULL) {
		LOG(L_ERR, "PDT:pdt_fifo_list: strange situation\n");
		rpc->fault(c, 500, "Server Error");
		return;
	}

	if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) {
		rpc->fault(c, 400, "Invalid parameter value");
		return;
	}
	sp.len = strlen(sp.s);
	sd.len = strlen(sd.s);

	t = sp.s;
	if(*t!='\0' && *t!='.') {
		while(t!=NULL && *t!='\0') {
			if(*t < '0' || *t > '9') {
				LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s);
				rpc->fault(c, 400, "Bad Prefix");
				return;
			}
			t++;
		}
	} else {
		sp.s   = NULL;
		sp.len = 0;
	}

	if(*sd.s=='\0' || *sd.s=='.') {
		sd.s   = NULL;
		sd.len = 0;
	}

	lock_get(&_dhash->diff_lock);

	for(i=0; i<_dhash->hash_size; i++) {
		lock_get(&_dhash->dhash[i].lock);

		it = _dhash->dhash[i].e;
		for (it = _dhash->dhash[i].e; it; it = it->n) {
			if((sp.s==NULL && sd.s==NULL)
			   || (sp.s!=NULL && it->prefix.len>=sp.len &&
			       strncmp(it->prefix.s, sp.s, sp.len)==0)
			   || (sd.s!=NULL && it->domain.len>=sd.len &&
			       strncasecmp(it->domain.s, sd.s, sd.len)==0)) {

				buf1 = pkg_malloc(it->prefix.len + 1);
				if (!buf1) continue;
				memcpy(buf1, it->prefix.s, it->prefix.len);
				buf1[it->prefix.len] = '\0';

				buf2 = pkg_malloc(it->domain.len + 1);
				if (!buf2) {
					pkg_free(buf1);
					continue;
				}
				memcpy(buf2, it->domain.s, it->domain.len);
				buf2[it->domain.len] = '\0';

				rpc->add(c, "ss", buf1, buf2);
				pkg_free(buf1);
				pkg_free(buf2);
			}
		}

		lock_release(&_dhash->dhash[i].lock);
	}

	lock_release(&_dhash->diff_lock);
}
Example #24
0
int is_nonce_index_valid(int index)
{
    /* if greater than MAX_NONCE_INDEX ->error */

    if(index>= MAX_NONCE_INDEX )
    {
        LM_ERR("index greater than buffer length\n");
        return 0;
    }

    lock_get(nonce_lock);

    /* if in the first 30 seconds */
    if(sec_monit[*second]== -1)
    {
        if(index>= *next_index)
        {
            LM_DBG("index out of range\n");
            lock_release(nonce_lock);
            return 0;
        }
        else
        {
            set_buf_bit(index);
            lock_release(nonce_lock);
            return 1;
        }
    }

    /* check if right interval */
    if(*next_index < sec_monit[*second])
    {
        if(!(index>= sec_monit[*second] || index<= *next_index))
        {
            LM_DBG("index out of the permitted interval\n");
            goto error;
        }
    }
    else
    {
        if(!(index >= sec_monit[*second] && index<=*next_index))
        {
            LM_DBG("index out of the permitted interval\n");
            goto error;
        }
    }

    /* check if the first time used */
    if(check_buf_bit(index))
    {
        LM_DBG("nonce already used\n");
        goto error;
    }

    set_buf_bit(index);
    lock_release(nonce_lock);
    return 1;

error:
    lock_release(nonce_lock);
    return 0;

}
Example #25
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) {
    struct dlg_cell *dlg;
    struct dlg_cell_out *dlg_out = 0;

    int new_state, old_state, unref, event;
    str to_tag, to_uri;
    struct sip_msg *req = param->req;
    struct sip_msg *rpl = param->rpl;
    struct dlg_entry_out* dlg_entry_out = 0;

    if (t && t->fwded_totags)
        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s);
    else
        LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type);

    dlg = (struct dlg_cell *) (*param->param);
    if (shutdown_done || dlg == 0)
        return;

    if (t) {
        dlg->transaction = t;
    }

    LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);

    if (type == TMCB_RESPONSE_FWDED) {
        // The state does not change, but the msg is mutable in this callback
        LM_DBG("TMCB_RESPONSE_FWDED from TM received");
        run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
        return;
    }

    if (type == TMCB_RESPONSE_READY) {
        LM_DBG("TMCB_RESPONSE_READY\n");
        return;
    }

    if (type == TMCB_RESPONSE_OUT) {
        if (rpl == FAKED_REPLY) {
            LM_DBG("Faked reply\n");
            return;
        }

        // get to tag
        LM_DBG("Extracting to-tag from reply");
        if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) {
            LM_ERR("bad reply or missing TO hdr :-/\n");
            to_tag.s = 0;
            to_tag.len = 0;
        } else {
            //populate to uri for this branch.
            to_uri = get_to(rpl)->uri;

            to_tag = get_to(rpl)->tag_value;
            if (to_tag.s == 0 || to_tag.len == 0) {
                LM_ERR("missing TAG param in TO hdr :-/\n");
                to_tag.s = 0;
                to_tag.len = 0;
                //Here we assume that the transaction module timer will remove any early dialogs
                return;
            }
        }

        LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s);
    }

    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;

    LM_DBG("Calling next_state_dlg and event is %i\n", event);
    next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag);

    if (type == TMCB_RESPONSE_OUT) {
        LM_DBG("Checking if there is an existing dialog_out entry with same to-tag");

        dlg_entry_out = &dlg->dlg_entry_out;

        lock_get(dlg->dlg_out_entries_lock);
        dlg_out = dlg_entry_out->first;

        LM_DBG("Scanning dlg_entry_out list for dlg_out");
        while (dlg_out) {
            //Check if there is an already dialog_out entry with same To-tag
            if (dlg_out->to_tag.len == to_tag.len &&
                    memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) {
                //Found a dialog_out entry with same to_tag!
                LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s);
                break;
            }
            dlg_out = dlg_out->next;
        }
        lock_release(dlg->dlg_out_entries_lock);

        if (!dlg_out) {
            LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg);
            dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag);

            link_dlg_out(dlg, dlg_out, 0);

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

            if (!dlg_out) {
                LM_ERR("failed to create new dialog out structure\n");
                //TODO do something on this error!

            }
        } else {
            //This dlg_out already exists, update cseq and contact if present

            LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s);

            if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq ||
                    !rpl->cseq->parsed) {
                LM_ERR("bad sip message or missing CSeq hdr :-/\n");
            }
            dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag));


            /* extract the contact address to update if present*/
            if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) {
                LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n");
            }
            else if (parse_contact(rpl->contact) < 0 ||
                    ((contact_body_t *) rpl->contact->parsed)->contacts == NULL ||
                    ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) {
                LM_ERR("Can not update callee contact: bad Contact HDR\n");
            }
            else
            {
                str contact;
                contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri;
                dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag));
            }

        }
    }

    if (new_state == DLG_STATE_EARLY) {
        run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
        return;
    }

    LM_DBG("new state is %i and old state is %i\n", new_state, old_state);

    if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) {
        LM_DBG("dialog %p confirmed \n", dlg);
        //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction
        //(not before in order to absorb late in-early-dialog requests).

        //remove all other dlg_out objects
        if (dlg_out) {
            if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) {
                LM_ERR("failed to register deletion delay function\n");
                LM_DBG("Removing all other DLGs");
                dlg_remove_dlg_out(dlg_out, dlg, 0);
            } else {
                //mark the outs for deletion
                dlg_remove_dlg_out(dlg_out, dlg, 1);

            }
        } else {
            LM_ERR("There is no dlg_out structure - this is bad\n");
            //TODO: add error handling here
        }

        /* 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 (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' \n",
                    dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
                    dlg->callid.len, dlg->callid.s,
                    dlg->from_tag.len, dlg->from_tag.s);

        } else {
            ref_dlg(dlg, 1);
        }

        run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);

        if (unref) unref_dlg(dlg, unref);
        return;
    }

    if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) {
        //This is a concurrently confirmed call
        LM_DBG("This is a concurrently confirmed call.");
        //Create a new Dialog ID token “X”
        //Not sure how to do this so just going to use existing Did and add an X character to it
        str new_did;
        create_concurrent_did(dlg, &new_did);

        //assign new did to the created or updated dialog_out entry.
        update_dlg_out_did(dlg_out, &new_did);

        //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did
        //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires

        struct dlg_cell *new_dlg = 0;
        new_dlg = build_new_dlg(&(dlg->callid) /*callid*/,
                &(dlg->from_uri) /*from uri*/,
                &(dlg->from_tag)/*from_tag*/,
                &(dlg->req_uri) /*r-uri*/);

        //assign new did to dlg_in
        update_dlg_did(new_dlg, &new_did);

        if (new_dlg == 0) {
            LM_ERR("failed to create new dialog\n");
            return;
        }

        //link the new_dlg with dlg_out object
        link_dlg_out(new_dlg, dlg_out, 0);

    }

    if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) {
        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);
        /* do unref */
        if (unref)
            unref_dlg(dlg, unref);

        return;
    }

    if (unref) unref_dlg(dlg, unref);

    return;
}
Example #26
0
int reserve_nonce_index(void)
{
    unsigned int curr_sec;
    int index;
    int i;


    curr_sec =  get_ticks()%(nonce_expire+1);

    lock_get(nonce_lock);

    /* update last index for the previous seconds */
    if(*next_index== -1) /* for the first request */
        *next_index= 0;
    else
    {
		/* if the portion with still alive nonces is not yet reached */
        if(*second!= curr_sec)
        {
            /* get the index for the next nonce */
			index= (*next_index==MAX_NONCE_INDEX)?MAX_NONCE_INDEX-1:*next_index -1;

			/* set the interval in sec_monit vector */
            if(curr_sec> *second)
            {
                for (i= *second; i< curr_sec; i++)
                    sec_monit[i]= index;
            }
            else
            {
                for (i= *second; i<= nonce_expire; i++)
                    sec_monit[i]= index;

                for (i= 0; i< curr_sec; i++)
                    sec_monit[i]= index;
            }
        }
    }
    *second= curr_sec;

    if(sec_monit[curr_sec]== -1) /* if in the first second*/
    {
        if(*next_index == MAX_NONCE_INDEX)
        {
            lock_release(nonce_lock);
            return -1;
        }

        goto done;
    }

    if(*next_index> sec_monit[curr_sec]) /* if at the end of the buffer */
    {
        /* if at the end of the buffer */
        if(*next_index == MAX_NONCE_INDEX)
        {
            *next_index = 0;
            goto index_smaller;
        }
        goto done;
    }

index_smaller:
    if(*next_index== sec_monit[curr_sec])  /* no more space -> return error */
    {
        lock_release(nonce_lock);
        LM_INFO("no more indexes available\n");
        return -1;
    }

done:
	unset_buf_bit(*next_index);
    index= *next_index;
    *next_index = *next_index + 1;
    LM_DBG("second= %d, sec_monit= %d,  index= %d\n", *second, sec_monit[curr_sec], index);
    lock_release(nonce_lock);
    return index;
}
Example #27
0
int send_publish( publ_info_t* publ )
{
	str met = {"PUBLISH", 7};
	str* str_hdr = NULL;
	ua_pres_t* presentity= NULL;
	str* body= NULL;
	str* tuple_id= NULL;
	ua_pres_t* cb_param= NULL;
	unsigned int hash_code=0;
	str etag= {0, 0};
	int ver= 0;
	int result;
	int ret_code= 0;
	pua_event_t* ev= NULL;
	uac_req_t uac_r;
	db1_res_t *res=NULL;
	ua_pres_t dbpres; 
	str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0};
	int ret = -1;

	LM_DBG("pres_uri=%.*s\n", publ->pres_uri->len, publ->pres_uri->s );
	
	if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction)
	{
		if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto error;
		}
	}

	/* get event from list */
	ev= get_event(publ->event);
	if(ev== NULL)
	{
		LM_ERR("event not found in list\n");
		goto error;
	}	

	if (dbmode==PUA_DB_ONLY)
	{
		if (publ->etag) {
			memset(&dbpres, 0, sizeof(dbpres));
			dbpres.pres_uri = &pres_uri;
			dbpres.watcher_uri = &watcher_uri;
			dbpres.extra_headers = &extra_headers;
			presentity = get_record_puadb(publ->id, publ->etag,
						      &dbpres, &res);
		}
	}
	else
	{
		ua_pres_t pres;

		memset(&pres, 0, sizeof(ua_pres_t));
		pres.pres_uri = publ->pres_uri;
		pres.flag = publ->source_flag;
		pres.id = publ->id;
		pres.event = publ->event;
		if(publ->etag)
			pres.etag = *publ->etag;

		hash_code= core_hash(publ->pres_uri, NULL, HASH_SIZE);
		lock_get(&HashT->p_records[hash_code].lock);
		presentity= search_htable(&pres, hash_code);
	}

	if(publ->etag && presentity== NULL)
	{
		if (dbmode!=PUA_DB_ONLY) 
			lock_release(&HashT->p_records[hash_code].lock);
		ret = 418;
		goto error;
	}

	if(publ->flag & INSERT_TYPE)
	{
		LM_DBG("Insert flag set\n");
		goto insert;
	}
	
	if(presentity== NULL)
	{
insert:	
		if (dbmode!=PUA_DB_ONLY) 
			lock_release(&HashT->p_records[hash_code].lock);
		LM_DBG("insert type\n"); 
		
		if(publ->flag & UPDATE_TYPE )
		{
			LM_DBG("UPDATE_TYPE and no record found \n");
			publ->flag= INSERT_TYPE;
		}
		if(publ->expires== 0)
		{
			LM_DBG("request for a publish with expires 0 and"
					" no record found\n");
			goto done;
			
		}
		if(publ->body== NULL)
		{
			LM_ERR("New PUBLISH and no body found- invalid request\n");
			ret = ERR_PUBLISH_NO_BODY;
			goto error;
		}
	}
	else
	{
		LM_DBG("record found\n");
		publ->flag= UPDATE_TYPE;
		etag.s= (char*)pkg_malloc(presentity->etag.len* sizeof(char));
		if(etag.s== NULL)
		{
			LM_ERR("while allocating memory\n");
			if (dbmode!=PUA_DB_ONLY) 
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		memcpy(etag.s, presentity->etag.s, presentity->etag.len);
		etag.len= presentity->etag.len;

		if(presentity->tuple_id.s && presentity->tuple_id.len)
		{	
			/* get tuple_id*/
			tuple_id=(str*)pkg_malloc(sizeof(str));
			if(tuple_id== NULL)
			{
				LM_ERR("No more memory\n");
				if (dbmode!=PUA_DB_ONLY) 
					lock_release(&HashT->p_records[hash_code].lock);
				goto error;
			}	
			tuple_id->s= (char*)pkg_malloc(presentity->tuple_id.len* sizeof(char));
			if(tuple_id->s== NULL)
			{
				LM_ERR("No more memory\n");
				if (dbmode!=PUA_DB_ONLY) 
					lock_release(&HashT->p_records[hash_code].lock);
				goto error;
			}	
			memcpy(tuple_id->s, presentity->tuple_id.s, presentity->tuple_id.len);
			tuple_id->len= presentity->tuple_id.len;
		}

		if(publ->expires== 0)
		{
			LM_DBG("expires= 0- delete from hash table\n");
			if (dbmode!=PUA_DB_ONLY) 
				lock_release(&HashT->p_records[hash_code].lock);
			goto send_publish;
		}

		presentity->version++; 
		ver= presentity->version;

		if (dbmode==PUA_DB_ONLY)
		{ 
			update_version_puadb(presentity);
		}
		else
		{
			lock_release(&HashT->p_records[hash_code].lock);
		}
	}

	/* handle body */
	if(publ->body && publ->body->s)
	{
		ret_code= ev->process_body(publ, &body, ver, &tuple_id );
		if( ret_code< 0 || body== NULL)
		{
			LM_ERR("while processing body\n");
			if(body== NULL)
				LM_ERR("NULL body\n");
			goto error;
		}
	}
	if(tuple_id)
		LM_DBG("tuple_id= %.*s\n", tuple_id->len, tuple_id->s  );
	
send_publish:
	
	/* construct the callback parameter */
	if(etag.s && etag.len)
		publ->etag = &etag;

	cb_param= publish_cbparam(publ, body, tuple_id, REQ_OTHER);
	if(cb_param== NULL)
	{
		LM_ERR("constructing callback parameter\n");
		goto error;
	}

	if(publ->flag & UPDATE_TYPE)
		LM_DBG("etag:%.*s\n", etag.len, etag.s);
	str_hdr = publ_build_hdr((publ->expires< 0)?3600:publ->expires, ev, &publ->content_type, 
				(publ->flag & UPDATE_TYPE)?&etag:NULL, publ->extra_headers, (body)?1:0);

	if(str_hdr == NULL)
	{
		LM_ERR("while building extra_headers\n");
		goto error;
	}

	LM_DBG("publ->pres_uri:\n%.*s\n ", publ->pres_uri->len, publ->pres_uri->s);
	LM_DBG("str_hdr:\n%.*s %d\n ", str_hdr->len, str_hdr->s, str_hdr->len);
	if(body && body->len && body->s )
		LM_DBG("body:\n%.*s\n ", body->len, body->s);

	set_uac_req(&uac_r, &met, str_hdr, body, 0, TMCB_LOCAL_COMPLETED,
			publ_cback_func, (void*)cb_param);
	result= tmb.t_request(&uac_r,
			publ->pres_uri,			/*! Request-URI */
			publ->pres_uri,			/*! To */
 		        publ->pres_uri,			/*! From */
		        publ->outbound_proxy?
			      publ->outbound_proxy:&outbound_proxy /*! Outbound proxy*/
			);

	if(result< 0)
	{
		LM_ERR("in t_request tm module function\n");
		goto error;
	}

done:
	ret = 0;

	if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction)
	{
		if (pua_dbf.end_transaction(pua_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto error;
		}
	}
	goto finish;

error:
	if(cb_param)
		shm_free(cb_param);

	if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction)
	{
		if (pua_dbf.abort_transaction(pua_db) < 0)
			LM_ERR("in abort_transaction\n");
	}

finish:
	if(etag.s)
		pkg_free(etag.s);

	if(body && ret_code)
	{
		if(body->s)
			xmlFree(body->s);
		pkg_free(body);
	}	
	if(str_hdr)
		pkg_free(str_hdr);
	if(tuple_id)
	{
		if(tuple_id->s)
			pkg_free(tuple_id->s);
		pkg_free(tuple_id);
	}
	free_results_puadb(res);

	return ret;
}
Example #28
0
/*callback function to handle responses to the BYE request */
void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps) {

    struct dlg_cell* dlg;
    int event, old_state, new_state, unref, ret;
    struct dlg_cell_out *dlg_out = 0;

    if (ps->param == NULL || *ps->param == NULL) {
        LM_ERR("invalid parameter\n");
        return;
    }

    if (ps->code < 200) {
        LM_DBG("receiving a provisional reply\n");
        return;
    }

    LM_DBG("receiving a final reply %d\n", ps->code);

    dlg = (struct dlg_cell *) (*(ps->param));
    event = DLG_EVENT_REQBYE;

    //get the corresponding dlg out structure for this REQ
    struct dlg_entry_out *dlg_entry_out = &dlg->dlg_entry_out;
    lock_get(dlg->dlg_out_entries_lock);
    dlg_out = dlg_entry_out->first; //TODO check for concurrent call
    if (!dlg_out)
        return;

    next_state_dlg(dlg, event, &old_state, &new_state, &unref, &dlg_out->to_tag);

    lock_release(dlg->dlg_out_entries_lock);

    if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) {

        LM_DBG("removing dialog with h_entry %u and h_id %u\n",
                dlg->h_entry, dlg->h_id);

        /* 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'\n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s);
        } else if (ret > 0) {
            LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
                    "with clid '%.*s'\n",
                    dlg, dlg->h_entry, dlg->h_id,
                    dlg->callid.len, dlg->callid.s);
        } else {
            unref++;
        }
        /* dialog terminated (BYE) */
        run_dlg_callbacks(DLGCB_TERMINATED, dlg, ps->req, ps->rpl, DLG_DIR_NONE, 0);

        /* derefering the dialog */
        unref_dlg(dlg, unref + 1);
    }

    if (new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED) {
        /* trash the dialog from DB and memory */

        /* force delete from mem */
        unref_dlg(dlg, 1);
    }

}
Example #29
0
static struct mi_root* mi_cc_list_agents(struct mi_root *cmd_tree, void *param)
{
	struct cc_agent *agent;
	struct mi_root *rpl_tree;
	struct mi_node *node;
	struct mi_node *rpl;
	struct mi_attr *attr;
	str state;
	static str s_free={"free", 4};
	static str s_wrapup={"wrapup", 6};
	static str s_incall={"incall", 6};
	char *p;
	int len;
	int i;

	rpl_tree = init_mi_tree( 200, MI_SSTR("OK") );
	if ( rpl_tree==NULL)
		return NULL;
	rpl = &rpl_tree->node;

	/* block access to data */
	lock_get( data->lock );

	for(i=0; i< 2; i++) {
		for( agent=data->agents[i] ; agent ; agent=agent->next ) {
			node = add_mi_node_child( rpl, MI_DUP_VALUE, "Agent", 5,
					agent->id.s, agent->id.len );
			if (node==NULL)
					goto error;

			p = int2str( (unsigned long)(agent->ref_cnt), &len);
			attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Ref"), p, len);
			if (attr==NULL)
					goto error;

			if(!agent->loged_in)
				attr = add_mi_attr( node, MI_DUP_VALUE, "Loged in", 8, "NO", 2);
			else {
				attr = add_mi_attr( node, MI_DUP_VALUE, "Loged in", 8, "YES", 3);
				if (attr==NULL)
					goto error;
				
				switch ( agent->state ) {
					case CC_AGENT_FREE:   state = s_free;   break;
					case CC_AGENT_WRAPUP: state = s_wrapup; break;
					case CC_AGENT_INCALL: state = s_incall; break;
					default: state.s =0;  state.len = 0;
				}
				attr = add_mi_attr( node, MI_DUP_VALUE, "State", 5,
						state.s, state.len );
			
			}
			if (attr==NULL)
					goto error;
		}
	}
	lock_release( data->lock );

	return rpl_tree;

error:
	lock_release( data->lock );
	return 0;
}
Example #30
0
int update_contact(struct sip_msg* msg, char* str1, char* str2)
{
	ua_pres_t* p, hentity;
	str contact;
	struct to_body *pto = NULL, TO = {0}, *pfrom = NULL;
	unsigned int hash_code;

	if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("when parsing headers\n");
		return -1;
	}

	/* find the record */
	if( msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot parse callid header\n");
		return -1;
	}		
	
	if (!msg->from || !msg->from->body.s)
	{
		LM_ERR("cannot find 'from' header!\n");
		return -1;
	}
	if (msg->from->parsed == NULL)
	{
		if ( parse_from_header( msg )<0 ) 
		{
			LM_ERR("cannot parse From header\n");
			return -1;
		}
	}
	
	pfrom = (struct to_body*)msg->from->parsed;
	
	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		return -1;
	}		
	
	if( msg->to==NULL || msg->to->body.s==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return -1;
	}			
	
	if(msg->to->parsed != NULL)
	{
		pto = (struct to_body*)msg->to->parsed;
		LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
	}
	else
	{
		parse_to(msg->to->body.s,msg->to->body.s +
			msg->to->body.len + 1, &TO);
		if(TO.uri.len <= 0) 
		{
			LM_DBG("'To' header NOT parsed\n");
			goto error;
		}
		pto = &TO;
	}			
	if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		goto error;
	}
	hentity.watcher_uri= &pto->uri;
	hentity.pres_uri= &pfrom->uri; 
	hentity.call_id=  msg->callid->body;
	hentity.to_tag= pto->tag_value;
	hentity.from_tag= pfrom->tag_value;
	

	/* extract the contact */
	if(msg->contact== NULL || msg->contact->body.s== NULL)
	{
		LM_ERR("no contact header found in 200 OK reply");
		goto error;
	}
	contact= msg->contact->body;

	if (dbmode==PUA_DB_ONLY)
	{
		update_contact_puadb(&hentity, &contact );
		free_to_params(&TO);
		return(1);
	}

	hash_code= core_hash(hentity.pres_uri,hentity.watcher_uri,
				HASH_SIZE);

	lock_get(&HashT->p_records[hash_code].lock);

	p= get_dialog(&hentity, hash_code);
	if(p== NULL)
	{
		lock_release(&HashT->p_records[hash_code].lock);
		LM_ERR("no record for the dialog found in hash table\n");
		goto error;
	}

	shm_free(p->remote_contact.s);

	if(!(p->remote_contact.len== contact.len && 
				strncmp(p->remote_contact.s, contact.s, contact.len)==0))
	{
		/* update remote contact */
		shm_free(p->remote_contact.s);
		p->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char));
		if(p->remote_contact.s== NULL)
		{
			LM_ERR("no more shared memory\n");
			lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		memcpy(p->remote_contact.s, contact.s, contact.len);
		p->remote_contact.len= contact.len;
	}

	lock_release(&HashT->p_records[hash_code].lock);

	free_to_params(&TO);
	return 1;

error:
	free_to_params(&TO);
	return -1;
}