Esempio n. 1
0
struct mi_root* mi_pua_subscribe(struct mi_root* cmd, void* param)
{
	int exp= 0;
	str pres_uri, watcher_uri, expires;
	struct mi_node* node= NULL;
	struct mi_root* rpl= NULL;
	struct sip_uri uri;
	subs_info_t subs;
	int sign= 1;
	str event;

	node = cmd->node.kids;
	if(node == NULL)
		return 0;

	pres_uri= node->value;
	if(pres_uri.s == NULL || pres_uri.s== 0)
	{
		return init_mi_tree(400, "Bad uri", 7);
	}
	if(parse_uri(pres_uri.s, pres_uri.len, &uri)<0 )
	{
		LM_ERR("bad uri\n");	
		return init_mi_tree(400, "Bad uri", 7);
	}

	node = node->next;
	if(node == NULL)
		return 0;

	watcher_uri= node->value;
	if(watcher_uri.s == NULL || watcher_uri.s== 0)
	{
		return init_mi_tree(400, "Bad uri", 7);
	}
	if(parse_uri(watcher_uri.s, watcher_uri.len, &uri)<0 )
	{
		LM_ERR("bad uri\n");	
		return init_mi_tree(400, "Bad uri", 7);
	}

	/* Get event */
	node = node->next;
	if(node == NULL)
		return 0;

	event= node->value;
	if(event.s== NULL || event.len== 0)
	{
		LM_ERR("empty event parameter\n");
		return init_mi_tree(400, "Empty event parameter", 21);
	}
	LM_DBG("event '%.*s'\n", event.len, event.s);

	node = node->next;
	if(node == NULL || node->next!=NULL)
	{
		LM_ERR("Too much or too many parameters\n");
		return 0;
	}

	expires= node->value;
	if(expires.s== NULL || expires.len== 0)
	{
		LM_ERR("Bad expires parameter\n");
		return init_mi_tree(400, "Bad expires", 11);
	}		
	if(expires.s[0]== '-')
	{
		sign= -1;
		expires.s++;
		expires.len--;
	}
	if( str2int(&expires, (unsigned int*) &exp)< 0)
	{
		LM_ERR("invalid expires parameter\n" );
		goto error;
	}
	
	exp= exp* sign;

	LM_DBG("expires '%d'\n", exp);
	
	memset(&subs, 0, sizeof(subs_info_t));
	
	subs.pres_uri= &pres_uri;

	subs.watcher_uri= &watcher_uri;

	subs.contact= &watcher_uri;
	
	subs.expires= exp;
	subs.source_flag |= MI_SUBSCRIBE;
	subs.event= get_event_flag(&event);
	if(subs.event< 0)
	{
		LM_ERR("unkown event\n");
		return init_mi_tree(400, "Unknown event", 13);
	}

	if(pua_send_subscribe(&subs)< 0)
	{
		LM_ERR("while sending subscribe\n");
		goto error;
	}
	
	rpl= init_mi_tree(202, "accepted", 8);
	if(rpl == NULL)
		return 0;
	
	return rpl;

error:

	return 0;

}
Esempio n. 2
0
struct mi_root* mi_pua_publish(struct mi_root* cmd, void* param)
{
	int exp;
	struct mi_node* node= NULL;
	str pres_uri, expires;
	str body= {0, 0};
	struct sip_uri uri;
	publ_info_t publ;
	str event;
	str content_type;
	str etag;
	int result;
	int sign= 1;

	LM_DBG("start\n");

	node = cmd->node.kids;
	if(node == NULL)
		return 0;

	/* Get presentity URI */
	pres_uri = node->value;
	if(pres_uri.s == NULL || pres_uri.s== 0)
	{
		LM_ERR("empty uri\n");
		return init_mi_tree(404, "Empty presentity URI", 20);
	}
	if(parse_uri(pres_uri.s, pres_uri.len, &uri)<0 )
	{
		LM_ERR("bad uri\n");
		return init_mi_tree(404, "Bad presentity URI", 18);
	}
	LM_DBG("pres_uri '%.*s'\n", pres_uri.len, pres_uri.s);

	node = node->next;
	if(node == NULL)
		return 0;

	/* Get expires */
	expires= node->value;
	if(expires.s== NULL || expires.len== 0)
	{
		LM_ERR("empty expires parameter\n");
		return init_mi_tree(400, "Empty expires parameter", 23);
	}
	if(expires.s[0]== '-')
	{
		sign= -1;
		expires.s++;
		expires.len--;
	}
	if( str2int(&expires, (unsigned int*) &exp)< 0)
	{
		LM_ERR("invalid expires parameter\n" );
		goto error;
	}
	
	exp= exp* sign;

	LM_DBG("expires '%d'\n", exp);

	node = node->next;
	if(node == NULL)
		return 0;

	/* Get event */
	event= node->value;
	if(event.s== NULL || event.len== 0)
	{
		LM_ERR("empty event parameter\n");
		return init_mi_tree(400, "Empty event parameter", 21);
	}
	LM_DBG("event '%.*s'\n",
	    event.len, event.s);

	node = node->next;
	if(node == NULL)
		return 0;

	/* Get content type */
	content_type= node->value;
	if(content_type.s== NULL || content_type.len== 0)
	{
		LM_ERR("empty content type\n");
		return init_mi_tree(400, "Empty content type parameter", 28);
	}
	LM_DBG("content type '%.*s'\n",
	    content_type.len, content_type.s);

	node = node->next;
	if(node == NULL)
		return 0;

	/* Get etag */
	etag= node->value;
	if(etag.s== NULL || etag.len== 0)
	{
		LM_ERR("empty etag parameter\n");
		return init_mi_tree(400, "Bad expires", 11);
	}
	LM_DBG("etag '%.*s'\n",
	    etag.len, etag.s);

	node = node->next;

	/* Get body */
	if(node == NULL )
	{
		body.s= NULL;
		body.len= 0;
	}
	else
	{
		if(node->next!=NULL)
			return init_mi_tree(400, "Too many parameters", 19);

		body= node->value;
		if(body.s == NULL || body.s== 0)
		{
			LM_ERR("empty body parameter\n");
			return init_mi_tree(400, "Empty body parameter", 20);
		}
	}
	LM_DBG("body '%.*s'\n",
	    body.len, body.s);

	/* Check that body is NULL iff content type is . */
	if(body.s== NULL && (content_type.len!= 1 || content_type.s[0]!= '.'))
	{
		LM_ERR("body is missing, but content type is not .\n");
		return init_mi_tree(400, "Body parameter is missing", 25);
	}

	/* Create the publ_info_t structure */
	memset(&publ, 0, sizeof(publ_info_t));
	
	publ.pres_uri= &pres_uri;
	if(body.s)
	{
		publ.body= &body;
	}
	
	publ.event= get_event_flag(&event);
	if(publ.event< 0)
	{
		LM_ERR("unkown event\n");
		return init_mi_tree(400, "Unknown event", 13);
	}
	if(content_type.len!= 1)
	{
		publ.content_type= content_type;
	}	
	
	if(! (etag.len== 1 && etag.s[0]== '.'))
	{
		publ.etag= &etag;
	}	
	publ.expires= exp;
	
	if (cmd->async_hdl!=NULL)
	{
		publ.source_flag= MI_ASYN_PUBLISH;
		publ.cb_param= (void*)cmd->async_hdl;
	}	
	else
		publ.source_flag|= MI_PUBLISH;

	LM_DBG("send publish\n");

	result= pua_send_publish(&publ);

	if(result< 0)
	{
		LM_ERR("sending publish failed\n");
		return init_mi_tree(500, "MI/PUBLISH failed", 17);
	}	
	if(result== 418)
		return init_mi_tree(418, "Wrong ETag", 10);
	
	if (cmd->async_hdl==NULL)
			return init_mi_tree( 202, "Accepted", 8);
	else
			return MI_ROOT_ASYNC_RPL;

error:

	return 0;
}
Esempio n. 3
0
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
{
	struct to_body *pto, TO = {0}, *pfrom = NULL;
	str body= {0, 0};
	ua_pres_t dialog;
	str* res_id= NULL;
	db_key_t query_cols[8];
	db_val_t query_vals[8];
	int n_query_cols= 0;
	str auth_state= {0, 0};
	int found= 0;
	str reason = {0, 0};
	int auth_flag;
	struct hdr_field* hdr= NULL;
	int expires= -1;
	str content_type= {0, 0};
	int reply_code = 500;
	str reply_str = pu_500_rpl;

	LM_DBG("start\n");
	/* extract the dialog information and check if an existing dialog*/	
	if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	if((!msg->event ) ||(msg->event->body.len<=0))
	{
		LM_ERR("Missing event header field value\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	if( msg->to==NULL || msg->to->body.s==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	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_ERR(" 'To' header NOT parsed\n");
			reply_code = 400;
			reply_str = pu_400_rpl;
			goto error;
		}
		pto = &TO;
	}
	memset(&dialog, 0, sizeof(ua_pres_t));
	dialog.watcher_uri= &pto->uri;
	if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
	{
		LM_ERR("to tag value not parsed\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	dialog.from_tag= pto->tag_value;
	if( msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot parse callid header\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	dialog.call_id = msg->callid->body;

	if (!msg->from || !msg->from->body.s)
	{
		LM_ERR("cannot find 'from' header!\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	if (msg->from->parsed == NULL)
	{
		LM_DBG("'From' header not parsed\n");
		/* parsing from header */
		if ( parse_from_header( msg )<0 ) 
		{
			LM_ERR("cannot parse From header\n");
			reply_code = 400;
			reply_str = pu_400_rpl;
			goto error;
		}
	}
	pfrom = (struct to_body*)msg->from->parsed;
	dialog.pres_uri= &pfrom->uri;

	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		reply_code = 400;
		reply_str = pu_400_rpl;
		goto error;
	}
	dialog.to_tag= pfrom->tag_value;
	dialog.flag|= RLS_SUBSCRIBE;

	dialog.event= get_event_flag(&msg->event->body);
	if(dialog.event< 0)
	{
		LM_ERR("unrecognized event package\n");
		reply_code = 489;
		reply_str = pu_489_rpl;
		goto error;
	}

	/* extract the subscription state */
	hdr = msg->headers;
	while (hdr!= NULL)
	{
		if(cmp_hdrname_strzn(&hdr->name, "Subscription-State", 18)==0)  
		{
			found = 1;
			break;
		}
		hdr = hdr->next;
	}
	if(found==0 )
	{
		LM_ERR("'Subscription-State' header not found\n");
		goto error;
	}
	auth_state = hdr->body;

	/* extract state and reason */
	auth_flag= parse_subs_state(auth_state, &reason, &expires);
	if(auth_flag< 0)
	{
		LM_ERR("while parsing 'Subscription-State' header\n");
		goto error;
	}
	if(pua_get_record_id(&dialog, &res_id)< 0) /* verify if within a stored dialog */
	{
		LM_ERR("occured when trying to get record id\n");
		goto error;
	}
	if(res_id==0)
	{
		LM_DBG("presence dialog record not found\n");
		/* if it is a NOTIFY for a terminated SUBSCRIBE dialog in RLS, then
		 * the module might not have the dialog structure anymore
		 * - just send 200ok, it is harmless
		 */
		if(auth_flag==TERMINATED_STATE)
			goto done;
		LM_INFO("no presence dialog record for non-TERMINATED state uri pres_uri = %.*s watcher_uri = %.*s\n",
                dialog.pres_uri->len, dialog.pres_uri->s, dialog.watcher_uri->len, dialog.watcher_uri->s);
		reply_code = 481;
		reply_str = pu_481_rpl;
		goto error;
	}
		
	if(msg->content_type== NULL || msg->content_type->body.s== NULL)
	{
		LM_DBG("cannot find content type header header\n");
	}
	else
		content_type= msg->content_type->body;
					
	/*constructing the xml body*/
	if(get_content_length(msg) == 0 )
	{	
		goto done;
	}	
	else
	{
		if(content_type.s== 0)
		{
			LM_ERR("content length != 0 and no content type header found\n");
			goto error;
		}
		body.s=get_body(msg);
		if (body.s== NULL) 
		{
			LM_ERR("cannot extract body from msg\n");
			goto error;
		}
		body.len = get_content_length( msg );

	}
	/* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/

	LM_DBG("body= %.*s\n", body.len, body.s);

	query_cols[n_query_cols]= &str_rlsubs_did_col;
	query_vals[n_query_cols].type = DB1_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= *res_id; 
	n_query_cols++;

	query_cols[n_query_cols]= &str_resource_uri_col;
	query_vals[n_query_cols].type = DB1_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= *dialog.pres_uri; 
	n_query_cols++;

	query_cols[n_query_cols]= &str_updated_col;
	query_vals[n_query_cols].type = DB1_INT;
	query_vals[n_query_cols].nul = 0;
	if (dbmode == RLS_DB_ONLY)
		query_vals[n_query_cols].val.int_val=
			core_hash(res_id, NULL, 0) %
				(waitn_time * rls_notifier_poll_rate
					* rls_notifier_processes);
	else
		query_vals[n_query_cols].val.int_val = UPDATED_TYPE;
	n_query_cols++;
		
	query_cols[n_query_cols]= &str_auth_state_col;
	query_vals[n_query_cols].type = DB1_INT;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.int_val= auth_flag; 
	n_query_cols++;

	query_cols[n_query_cols]= &str_reason_col;
	query_vals[n_query_cols].type = DB1_STR;
	query_vals[n_query_cols].nul = 0;
	if(reason.len > 0)
	{
		query_vals[n_query_cols].val.str_val.s= reason.s;
		query_vals[n_query_cols].val.str_val.len= reason.len;
	}	
	else
	{
		query_vals[n_query_cols].val.str_val.s = "";
		query_vals[n_query_cols].val.str_val.len = 0;
	}
	n_query_cols++;

	query_cols[n_query_cols]= &str_content_type_col;
	query_vals[n_query_cols].type = DB1_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= content_type;
	n_query_cols++;
			
	query_cols[n_query_cols]= &str_presence_state_col;
	query_vals[n_query_cols].type = DB1_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= body;
	n_query_cols++;
		
	query_cols[n_query_cols]= &str_expires_col;
	query_vals[n_query_cols].type = DB1_INT;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL);
	n_query_cols++;

	if (rlpres_dbf.use_table(rlpres_db, &rlpres_table) < 0) 
	{
		LM_ERR("in use_table\n");
		goto error;
	}

	if (dbmode == RLS_DB_ONLY && rlpres_dbf.start_transaction)
	{
		if (rlpres_dbf.start_transaction(rlpres_db) < 0)
		{
			LM_ERR("in start_transaction\n");
			goto error;
		}
	}

	if (rlpres_dbf.replace != NULL)
	{
		if(rlpres_dbf.replace(rlpres_db, query_cols, query_vals, n_query_cols,
					2, 0)< 0)
		{
			LM_ERR("in sql replace\n");
			goto error;
		}
		LM_DBG("Inserted/replace in database table new record\n");
	}
	else
	{
		if(rlpres_dbf.update(rlpres_db, query_cols, 0, query_vals, query_cols+2,
						query_vals+2, 2, n_query_cols-2)< 0)
		{
			LM_ERR("in sql update\n");
			goto error;
		}

		if (rlpres_dbf.affected_rows(rlpres_db) == 0)
		{
			if(rlpres_dbf.insert(rlpres_db, query_cols, query_vals, n_query_cols)< 0)
			{
				LM_ERR("in sql insert\n");
				goto error;
			}
			LM_DBG("Inserted in database table new record\n");
		}
	}

	if (dbmode == RLS_DB_ONLY && rlpres_dbf.end_transaction)
	{
		if (rlpres_dbf.end_transaction(rlpres_db) < 0)
		{
			LM_ERR("in end_transaction\n");
			goto error;
		}
	}

	LM_DBG("Updated rlpres_table\n");	
	/* reply 200OK */
done:
	if(slb.freply(msg, 200, &su_200_rpl) < 0)
	{
		LM_ERR("while sending reply\n");
		goto error;
	}

	if(res_id!=NULL)
	{
		pkg_free(res_id->s);
		pkg_free(res_id);
	}

	if (reason.s) pkg_free(reason.s);

	free_to_params(&TO);
	return 1;

error:
	if(slb.freply(msg, reply_code, &reply_str) < 0)
	{
		LM_ERR("failed sending reply\n");
	}
	if(res_id!=NULL)
	{
		pkg_free(res_id->s);
		pkg_free(res_id);
	}

	if (reason.s) pkg_free(reason.s);

	free_to_params(&TO);

	if (dbmode == RLS_DB_ONLY && rlpres_dbf.abort_transaction)
	{
		if (rlpres_dbf.abort_transaction(rlpres_db) < 0)
			LM_ERR("in abort_transaction\n");
	}

	return -1;
}
Esempio n. 4
0
int resource_subscriptions(subs_t* subs, xmlNodePtr rl_node)
{
	char* uri= NULL;
	subs_info_t s;
	str wuri= {0, 0};
	str did_str= {0, 0};
	str *tmp_str;
	int cont_no= 0;
	static str ehdr= {SUBS_EXTRA_HDRS, SUBS_EXTRA_HDRS_LEN};
	list_entry_t *rls_contact_list = NULL;
	list_entry_t *rls_subs_list = NULL;
	void* params[2] = {&s, &rls_contact_list};

	/* if is initial send an initial Subscribe 
	 * else search in hash table for a previous subscription */

	if(CONSTR_RLSUBS_DID(subs, &did_str)< 0)
	{
		LM_ERR("Failed to create did\n");
		return -1;
	}

	memset(&s, 0, sizeof(subs_info_t));

	if( uandd_to_uri(subs->from_user, subs->from_domain, &wuri)< 0)
	{
		LM_ERR("while constructing uri from user and domain\n");
		goto error;
	}
	s.id= did_str;
	s.watcher_uri= &wuri;
	s.to_uri.s=0;
	s.contact= &server_address;
	s.event= get_event_flag(&subs->event->name);
	if(presence_server.s)
		s.outbound_proxy= &presence_server;
	if(s.event< 0)
	{
		LM_ERR("not recognized event\n");
		goto error;
	}
	s.expires= subs->expires;
	s.source_flag= RLS_SUBSCRIBE;
	s.extra_headers= &ehdr;
	s.internal_update_flag = subs->internal_update_flag;

	if(process_list_and_exec(rl_node, subs->from_user, subs->from_domain,
	                        send_resource_subs, params, &cont_no) < 0)
	{
		LM_ERR("while processing list\n");
		goto error;
	}

	LM_INFO("Subscription from %.*s for resource list uri %.*s expanded to"
			" %d contacts\n", wuri.len, wuri.s, subs->pres_uri.len,
			subs->pres_uri.s, cont_no);

	if (s.internal_update_flag)
	{
		s.internal_update_flag = 0;

		rls_subs_list = pua_get_subs_list(&did_str);

		while ((tmp_str = list_pop(&rls_contact_list)) != NULL)
		{
			rls_subs_list = list_remove(*tmp_str, rls_subs_list);
			pkg_free(tmp_str->s);
			pkg_free(tmp_str);
		}

		while ((tmp_str = list_pop(&rls_subs_list)) != NULL)
		{
			LM_DBG("Removing subscription for %.*s\n", tmp_str->len, tmp_str->s);
			s.expires = 0;
			send_resource_subs(tmp_str->s, params);
			pkg_free(tmp_str->s);
			pkg_free(tmp_str);
		}
	}

	if (rls_contact_list != NULL)
        {
                list_free(&rls_contact_list);
        }

	pkg_free(wuri.s);
	pkg_free(did_str.s);

	return 0;

error:
	if(wuri.s)
		pkg_free(wuri.s);
	if(uri)
		xmlFree(uri);
	if(did_str.s)
		pkg_free(did_str.s);
	return -1;

}
Esempio n. 5
0
/**
 * send subscriptions to the list from XML node
 */
int resource_subscriptions(subs_t* subs, xmlNodePtr xmlnode)
{
	subs_info_t s;
	str wuri= {0, 0};
	str extra_headers;
	str did_str= {0, 0};
	str *tmp_str;
	list_entry_t *rls_contact_list = NULL;
	list_entry_t *rls_subs_list = NULL;
	void* params[2] = {&s, &rls_contact_list};
		
	/* if is initial send an initial Subscribe 
	 * else search in hash table for a previous subscription */

	if(CONSTR_RLSUBS_DID(subs, &did_str)<0)
	{
		LM_ERR("cannot build rls subs did\n");
		goto error;
	}

	memset(&s, 0, sizeof(subs_info_t));

	if(uandd_to_uri(subs->watcher_user, subs->watcher_domain, &wuri)<0)
	{
		LM_ERR("while constructing uri from user and domain\n");
		goto error;
	}
	s.id = did_str;
	s.watcher_uri = &wuri;
	s.contact = &rls_server_address;
	s.event = get_event_flag(&subs->event->name);
	if(s.event<0)
	{
		LM_ERR("not recognized event\n");
		goto error;
	}
	s.expires = subs->expires;
	s.source_flag = RLS_SUBSCRIBE;
	if(rls_outbound_proxy.s)
		s.outbound_proxy = &rls_outbound_proxy;
	extra_headers.s = "Supported: eventlist\r\n"
				"Accept: application/pidf+xml, application/rlmi+xml,"
					" application/watcherinfo+xml,"
					" multipart/related\r\n";
	extra_headers.len = strlen(extra_headers.s);

	s.extra_headers = &extra_headers;

	s.internal_update_flag = subs->internal_update_flag;

	counter = 0;
	
	if(process_list_and_exec(xmlnode, subs->watcher_user, subs->watcher_domain,
			send_resource_subs, params)<0)
	{
		LM_ERR("while processing list\n");
		goto error;
	}

	if (rls_max_backend_subs > 0 && counter > rls_max_backend_subs)
		LM_WARN("%.*s has too many contacts.  Max: %d, has: %d\n",
			wuri.len, wuri.s, rls_max_backend_subs, counter);

	if (s.internal_update_flag == INTERNAL_UPDATE_TRUE)
	{
		counter = 0;
		s.internal_update_flag = 0;

		rls_subs_list = pua_get_subs_list(&did_str);

		while ((tmp_str = list_pop(&rls_contact_list)) != NULL)
		{
			LM_DBG("Finding and removing %.*s from subscription list\n", tmp_str->len, tmp_str->s);
			rls_subs_list = list_remove(*tmp_str, rls_subs_list);
			pkg_free(tmp_str->s);
			pkg_free(tmp_str);
		}

		while ((tmp_str = list_pop(&rls_subs_list)) != NULL)
		{
			LM_DBG("Removing subscription for %.*s\n", tmp_str->len, tmp_str->s);
			s.expires = 0;
			send_resource_subs(tmp_str->s, params);
			pkg_free(tmp_str->s);
			pkg_free(tmp_str);
		}
	}
	if (rls_contact_list != NULL)
		list_free(&rls_contact_list);

	pkg_free(wuri.s);
	pkg_free(did_str.s);

	return 0;

error:
	if(wuri.s)
		pkg_free(wuri.s);
	if(did_str.s)
		pkg_free(did_str.s);
	if(rls_contact_list)
		list_free(&rls_contact_list);
	return -1;

}
Esempio n. 6
0
static void pua_rpc_publish(rpc_t* rpc, void* c)
{
	str pres_uri, expires, event, content_type, id, etag,
		outbound_proxy, extra_headers, body;
	rpc_delayed_ctx_t* dctx;
	int exp, sign, ret, err_ret, sip_error;
	char err_buf[MAX_REASON_LEN];
	struct sip_uri uri;
	publ_info_t publ;

	body.s = 0;
	body.len = 0;
	dctx = 0;

	LM_DBG("rpc publishing ...\n");

	if ((rpc->capabilities == 0) ||
	    !(rpc->capabilities(c) & RPC_DELAYED_REPLY)) {
		rpc->fault(c, 600, "Reply wait/async mode not supported"
			   " by this rpc transport");
		return;
	}

	ret = rpc->scan(c, "SSSSSSSS*S", &pres_uri, &expires, &event,
			&content_type, &id, &etag, &outbound_proxy,
			&extra_headers, &body);
	if (ret < 8) {
		rpc->fault(c, 400, "Too few or wrong type of parameters (%d)",
			   ret);
		return;
	}

	if (parse_uri(pres_uri.s, pres_uri.len, &uri) <0) {
		LM_ERR("bad resentity uri\n");
		rpc->fault(c, 400, "Invalid presentity uri '%s'", pres_uri.s);
		return;
	}
	LM_DBG("presentity uri '%.*s'\n", pres_uri.len, pres_uri.s);

	if (expires.s[0]== '-') {
		sign= -1;
		expires.s++;
		expires.len--;
	} else {
		sign = 1;
	}
	if (str2int(&expires, (unsigned int*)&exp) < 0) {
		LM_ERR("invalid expires parameter\n" );
		rpc->fault(c, 400, "Invalid expires value '%s'", expires.s);
		return;
	}
	exp = exp * sign;
	LM_DBG("expires '%d'\n", exp);

	LM_DBG("event '%.*s'\n", event.len, event.s);

	LM_DBG("content type '%.*s'\n", content_type.len, content_type.s);

	LM_DBG("id '%.*s'\n", id.len, id.s);

	LM_DBG("ETag '%.*s'\n", etag.len, etag.s);

	LM_DBG("outbound_proxy '%.*s'\n", outbound_proxy.len, outbound_proxy.s);

	LM_DBG("extra headers '%.*s'\n", extra_headers.len, extra_headers.s);

	if (body.len > 0) LM_DBG("body '%.*s'\n", body.len, body.s);

	if ((body.s == 0) &&
	    (content_type.len != 1 || content_type.s[0] != '.')) {
		LM_ERR("body is missing, but content type is not .\n");
		rpc->fault(c, 400, "Body is missing");
		return;
	}

	memset(&publ, 0, sizeof(publ_info_t));

	publ.pres_uri= &pres_uri;

	publ.expires= exp;

	publ.event= get_event_flag(&event);
	if (publ.event < 0) {
		LM_ERR("unknown event '%.*s'\n", event.len, event.s);
		rpc->fault(c, 400, "Unknown event");
		return;
	}

	if (content_type.len != 1) {
		publ.content_type= content_type;
	}

	if (!((id.len == 1) && (id.s[0]== '.'))) {
		publ.id= id;
	}

	if (!((etag.len== 1) && (etag.s[0]== '.'))) {
		publ.etag= &etag;
	}

	if (!((outbound_proxy.len == 1) && (outbound_proxy.s[0] == '.'))) {
		publ.outbound_proxy = &outbound_proxy;
	}

	if (!((extra_headers.len == 1) && (extra_headers.s[0] == '.'))) {
		publ.extra_headers = &extra_headers;
	}

	if (body.s != 0) {
		publ.body= &body;
	}

	dctx = rpc->delayed_ctx_new(c);
	if (dctx == 0) {
		LM_ERR("internal error: failed to create context\n");
		rpc->fault(c, 500, "Internal error: failed to create context");
		return;
	}
	publ.cb_param = dctx;
	publ.source_flag = MI_ASYN_PUBLISH;

	ret = pua_rpc_api.send_publish(&publ);
	LM_DBG("pua send_publish returned %d\n", ret);

	if (dctx->reply_ctx != 0) {
		/* callback was not executed or its execution failed */
		rpc = &dctx->rpc;
		c = dctx->reply_ctx;
	} else {
		return;
	}

	if (ret < 0) {
		LM_ERR("pua send_publish failed\n");
		err_ret = err2reason_phrase(ret, &sip_error, err_buf,
					    sizeof(err_buf), "RPC/PUBLISH") ;
		if (err_ret > 0 ) {
			rpc->fault(c, sip_error, "%s", err_buf);
		} else {
			rpc->fault(c, 500, "RPC/PUBLISH error");
		}
		rpc->delayed_ctx_close(dctx);
	}

	if (ret == 418) {
		rpc->fault(c, 500, "Wrong ETag");
		rpc->delayed_ctx_close(dctx);
	}


	return;
}
Esempio n. 7
0
int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
{
	struct to_body *pto, *pfrom= NULL;
	str body= {0, 0};
	ua_pres_t dialog;
	str* res_id= NULL;
	db_key_t query_cols[9], result_cols[1];
	db_val_t query_vals[9];
	db_res_t* result= NULL;
	int n_query_cols= 0;
	str auth_state= {0, 0};
	str* reason= NULL;
	int auth_flag;
	struct hdr_field* hdr= NULL;
	int n, expires= -1;
	str ctype= {0, 0};
	int err_ret = -1;

	LM_DBG("start\n");
	/* extract the dialog information and check if an existing dialog*/	
	if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
	{
		LM_ERR("parsing headers\n");
		return -1;
	}
	if((!msg->event ) ||(msg->event->body.len<=0))
	{
		LM_ERR("Missing event header field value\n");
		return -1;
	}
	if( msg->to==NULL || msg->to->body.s==NULL)
	{
		LM_ERR("cannot parse TO header\n");
		return -1;
	}

	pto = get_to(msg);
	if (pto == NULL || pto->error != PARSE_OK) {
		LM_ERR("failed to parse TO header\n");
		return -1;
	}

	memset(&dialog, 0, sizeof(ua_pres_t));
	dialog.watcher_uri= &pto->uri;
    if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
	{  
		LM_ERR("to tag value not parsed\n");
		goto error;
	}

	dialog.from_tag= pto->tag_value;
	if( msg->callid==NULL || msg->callid->body.s==NULL)
	{
		LM_ERR("cannot parse callid header\n");
		goto error;
	}
	dialog.call_id = msg->callid->body;

	if (!msg->from || !msg->from->body.s)
	{
		LM_ERR("cannot find 'from' header!\n");
		goto error;
	}
	if (msg->from->parsed == NULL)
	{
		LM_DBG("'From' header not parsed\n");
		/* parsing from header */
		if ( parse_from_header( msg )<0 ) 
		{
			LM_ERR("cannot parse From header\n");
			goto error;
		}
	}
	pfrom = (struct to_body*)msg->from->parsed;
	dialog.pres_uri= &pfrom->uri;
		
	if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
	{
		LM_ERR("no from tag value present\n");
		goto error;
	}
	dialog.to_tag= pfrom->tag_value;
	dialog.flag|= RLS_SUBSCRIBE;

	dialog.event= get_event_flag(&msg->event->body);
	if(dialog.event< 0)
	{
		LM_ERR("unrecognized event package\n");
		goto error;
	}
	if(pua_get_record_id(&dialog, &res_id)< 0) // verify if within a stored dialog
	{
		LM_ERR("error occured while trying to get dialog record id\n");
		goto error;
	}
	if(res_id== 0)
	{
		LM_DBG("no dialog match found in hash table\n");
		err_ret = 2;
		goto error;
	}

	/* extract the subscription state */
	hdr = get_header_by_static_name( msg, "Subscription-State");
	if( hdr==NULL )
	{
		LM_ERR("'Subscription-State' header not found\n");
		goto error;
	}
	auth_state = hdr->body;

	/* extract state and reason */
	auth_flag= parse_subs_state(auth_state, &reason, &expires);
	if(auth_flag< 0)
	{
		LM_ERR("while parsing 'Subscription-State' header\n");
		goto error;
	}
	if(msg->content_type== NULL || msg->content_type->body.s== NULL)
	{
		LM_DBG("cannot find content type header\n");
	}
	else
		ctype= msg->content_type->body;

	LM_DBG("NOTIFY for [user]= %.*s\n",dialog.pres_uri->len,
			dialog.pres_uri->s);
	/*constructing the xml body*/
	if(get_content_length(msg) == 0 )
	{
		LM_DBG("null body\n");
		goto done;
	}	
	else
	{
		if(ctype.s== 0)
		{
			LM_ERR("content length != 0 and no content type header found\n");
			goto error;
		}
		if ( get_body(msg,&body)!=0 || body.len==0)
		{
			LM_ERR("cannot extract body from msg\n");
			goto error;
		}
		LM_DBG("[body]= %.*s\n", body.len, body.s);
	}
	
	/* update in rlpres_table where rlsusb_did= res_id and resource_uri= from_uri*/

	query_cols[n_query_cols]= &str_rlsubs_did_col;
	query_vals[n_query_cols].type = DB_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= *res_id; 
	n_query_cols++;
	
	query_cols[n_query_cols]= &str_resource_uri_col;
	query_vals[n_query_cols].type = DB_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= *dialog.pres_uri; 
	n_query_cols++;

	query_cols[n_query_cols]= &str_updated_col;
	query_vals[n_query_cols].type = DB_INT;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.int_val= UPDATED_TYPE; 
	n_query_cols++;

	query_cols[n_query_cols]= &str_auth_state_col;
	query_vals[n_query_cols].type = DB_INT;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.int_val= auth_flag; 
	n_query_cols++;

	if(reason)
	{
		query_cols[n_query_cols]= &str_reason_col;
		query_vals[n_query_cols].type = DB_STR;
		query_vals[n_query_cols].nul = 0;
		query_vals[n_query_cols].val.str_val= *reason;
		n_query_cols++;
	}
	query_cols[n_query_cols]= &str_content_type_col;
	query_vals[n_query_cols].type = DB_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= ctype;
	n_query_cols++;

	query_cols[n_query_cols]= &str_presence_state_col;
	query_vals[n_query_cols].type = DB_STR;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.str_val= body;
	n_query_cols++;
	
	query_cols[n_query_cols]= &str_expires_col;
	query_vals[n_query_cols].type = DB_INT;
	query_vals[n_query_cols].nul = 0;
	query_vals[n_query_cols].val.int_val= expires+ (int)time(NULL);
	n_query_cols++;

	if (rls_dbf.use_table(rls_db, &rlpres_table) < 0) 
	{
		LM_ERR("in use_table\n");
		goto error;
	}
	/* query-> if not present insert // else update */
	result_cols[0]= &str_updated_col;

	if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols,
					2, 1, 0, &result)< 0)
	{
		LM_ERR("in sql query\n");
		if(result)
			rls_dbf.free_result(rls_db, result);
		goto error;
	}
	if(result== NULL)
		goto error;
	n= result->n;
	rls_dbf.free_result(rls_db, result);

	if(n<= 0)
	{
		if(rls_dbf.insert(rls_db, query_cols, query_vals, n_query_cols)< 0)
		{
			LM_ERR("in sql insert\n");
			goto error;
		}
	}
	else
	{
		if(expires!= 0)
		{
			if(rls_dbf.update(rls_db, query_cols, 0, query_vals, query_cols+2,
						query_vals+2, 2, n_query_cols-2)< 0)
			{
				LM_ERR("in sql update\n");
				goto error;
			}
		}
		else  /* if terminated - delete from rls_presentity table */
		{
			if(rls_dbf.delete(rls_db, query_cols, 0, query_vals, 2)< 0)
			{
				LM_ERR("sql delete failed\n");
				goto error;
			}

		}
	}
	
done:
	if( rls_sigb.reply(msg, 200, &su_200_rpl, 0) < 0)
	{
		LM_ERR("failed to send SIP reply\n");
		goto error;
	}	
	pkg_free(res_id->s);
	pkg_free(res_id);

	return 1;

error:
	if(res_id)
	{
		pkg_free(res_id->s);
		pkg_free(res_id);
	}

	return err_ret;
}