Beispiel #1
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;
}
int send_subscribe(subs_info_t* subs)
{
	ua_pres_t* presentity= NULL;
	str met= {"SUBSCRIBE", 9};
	str* str_hdr= NULL;
	int ret= -1;
	unsigned int hash_code=0;
	ua_pres_t* hentity= NULL;
	int expires;
	int flag;
	int result;
	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};
	dlg_t* td= NULL;


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

	print_subs(subs);

	flag= subs->source_flag;
	if(subs->source_flag & XMPP_INITIAL_SUBS)
		subs->source_flag= XMPP_SUBSCRIBE;

	if(subs->expires< 0)
		expires= 3600;
	else
		expires= subs->expires;

	str_hdr= subs_build_hdr(subs->contact, expires, subs->event, 
			subs->extra_headers);
	if(str_hdr== NULL || str_hdr->s== NULL)
	{
		LM_ERR("while building extra headers\n");
		return -1;
	}

	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;
		}
	}

	/* generation of hash and getting lock moved from here to further down */

	if (dbmode==PUA_DB_ONLY)
	{
		presentity = get_dialog_puadb(subs->id, subs->pres_uri, &dbpres, &res);
	}
	else
	{
		ua_pres_t pres;

		memset(&pres, 0, sizeof(ua_pres_t));
		pres.pres_uri = subs->pres_uri;
		pres.watcher_uri = subs->watcher_uri;
		pres.flag = subs->source_flag;
		pres.id = subs->id;
		pres.event = subs->event;
		if (subs->remote_target)
			pres.remote_contact = *subs->remote_target;

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

	/* if flag == INSERT_TYPE insert no matter what the search result is */
	if(subs->flag & INSERT_TYPE)
	{
		LM_DBG("A subscription request with insert type\n");
		goto insert;
	}
	
	if(presentity== NULL )
	{
		int size;
insert:
	
		if (subs->expires == 0)
		{
			/* Don't create a new dialog when expires == 0 */
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		if(subs->flag & UPDATE_TYPE)
		{
			LM_DBG("request for a subscription with update type"
					" and no record found\n");
			subs->flag= INSERT_TYPE;
		}	
		hentity= subscribe_cbparam(subs, REQ_OTHER);
		if(hentity== NULL)
		{
			LM_ERR("while building callback"
					" param\n");
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		hentity->flag= flag;

		set_uac_req(&uac_r, &met, str_hdr, 0, 0, TMCB_LOCAL_COMPLETED,
				subs_cback_func, (void*)hentity);
		result= tmb.t_request_outside
			(&uac_r,						  /* Type of the message */
		subs->remote_target?subs->remote_target:subs->pres_uri,/* Request-URI*/
			subs->pres_uri,				  /* To */
			subs->watcher_uri,			  /* From */
			subs->outbound_proxy		  /* Outbound_proxy */	
			);
		if(result< 0)
		{
			LM_ERR("while sending request with t_request\n");
			if (uac_r.dialog != NULL)
			{
				uac_r.dialog->rem_target.s = 0;
				uac_r.dialog->dst_uri.s = 0;
				tmb.free_dlg(uac_r.dialog);
				uac_r.dialog = 0;
			}
			shm_free(hentity);
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);

			/* Although this is an error must not return -1 as the
			   calling function must continue processing. */
			ret = 0;
			goto error;
		}

		/* Now create a temporary hash table entry.
		   This is needed to deal with the race-hazard when NOTIFYs
		   arrive before the 2xx response to the SUBSCRIBE. */
		size = sizeof(ua_pres_t)+ 2 * sizeof(str) + (
			subs->pres_uri->len +
			subs->watcher_uri->len +
			uac_r.dialog->id.loc_tag.len +
			uac_r.dialog->id.call_id.len +
			subs->id.len) * sizeof(char);

		presentity= (ua_pres_t*)shm_malloc(size);
		if(presentity== NULL)
		{
			LM_ERR("no more share memory\n");
       			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			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, subs->pres_uri->s, subs->pres_uri->len);
		presentity->pres_uri->len= subs->pres_uri->len;
		size+= subs->pres_uri->len;

		presentity->watcher_uri= (str *) ((char *) presentity + size);
		size += sizeof(str);
		presentity->watcher_uri->s= (char *) presentity + size;
		memcpy(presentity->watcher_uri->s, subs->watcher_uri->s, subs->watcher_uri->len);
		presentity->watcher_uri->len = subs->watcher_uri->len;
		size += subs->watcher_uri->len;

		presentity->call_id.s = (char *) presentity + size;
		memcpy(presentity->call_id.s, uac_r.dialog->id.call_id.s, uac_r.dialog->id.call_id.len);
		presentity->call_id.len = uac_r.dialog->id.call_id.len;
		size += uac_r.dialog->id.call_id.len;

		presentity->from_tag.s = (char *) presentity + size;
		memcpy(presentity->from_tag.s, uac_r.dialog->id.loc_tag.s, uac_r.dialog->id.loc_tag.len);
		presentity->from_tag.len= uac_r.dialog->id.loc_tag.len;
		size += uac_r.dialog->id.loc_tag.len;

		presentity->id.s = (char *) presentity+ size;
		memcpy(presentity->id.s, subs->id.s, subs->id.len);
		presentity->id.len = subs->id.len;
		size += subs->id.len;

		presentity->event = subs->event;
		presentity->flag = subs->source_flag;
		presentity->cseq = uac_r.dialog->loc_seq.value;

		/* Set the temporary record expiry for 2 * 64T1 seconds from now */
		presentity->expires= (int)time(NULL) + 64;
		presentity->desired_expires= presentity->expires;

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

		uac_r.dialog->rem_target.s = 0;
		uac_r.dialog->dst_uri.s = 0;
		tmb.free_dlg(uac_r.dialog);
		uac_r.dialog = 0;
	}
	else
	{
		if (subs->internal_update_flag == INTERNAL_UPDATE_TRUE)
		{
			LM_INFO("attempting to re-SUBSCRIBE on internal (rls_update_subs()) update - skipping\n");
			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		if (presentity->to_tag.len == 0)
		{
			if (subs->expires > 0)
				LM_WARN("attempting to re-SUBSCRIBE to a temporary (non-established) dialog - skipping\n");
			else
			{
				LM_WARN("attempting to un-SUBSCRIBE from a temporary (non-established) dialog - skipping and deleting dialog\n");
				if (dbmode==PUA_DB_ONLY)
					delete_dialog_puadb(presentity);
				else
					delete_htable(presentity, hash_code);
			}

			if (dbmode != PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto done;
		}

		td= pua_build_dlg_t(presentity);
		if(td== NULL)
		{
			LM_ERR("while building tm dlg_t structure");
			if (dbmode!=PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
				
		hentity= subs_cbparam_indlg(presentity, expires, REQ_OTHER);
		if(hentity== NULL)
		{
			LM_ERR("while building callback param\n");
			if (dbmode!=PUA_DB_ONLY)
				lock_release(&HashT->p_records[hash_code].lock);
			goto error;
		}
		if (dbmode!=PUA_DB_ONLY)
			lock_release(&HashT->p_records[hash_code].lock);

		LM_DBG("event parameter: %d\n", hentity->event);	

		set_uac_req(&uac_r, &met, str_hdr, 0, td, TMCB_LOCAL_COMPLETED,
				subs_cback_func, (void*)hentity);
		result= tmb.t_request_within(&uac_r);
		if(result< 0)
		{
			shm_free(hentity);
			hentity= NULL;
			LM_ERR("while sending request with t_request\n");
			goto error;
		}
	}


done:
	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;
		}
	}

	ret = 0;

error:
	pua_free_tm_dlg(td);
	pkg_free(str_hdr);
	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 ret;
}
Beispiel #3
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 && *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;
}