|
@@ -61,6 +61,385 @@ static str su_200_rpl = str_init("OK");
|
|
|
dest_len= source_len;\
|
|
|
size+= source_len;
|
|
|
|
|
|
+int parse_rlsubs_did(char* str_did, str* callid, str* from_tag, str* to_tag)
|
|
|
+{
|
|
|
+ char* smc= NULL;
|
|
|
+
|
|
|
+ smc= strstr(str_did, RLS_DID_SEP);
|
|
|
+ if(smc== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("bad format for resource list Subscribe dialog"
|
|
|
+ " indentifier[rlsubs did]= %s\n", str_did);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ callid->s= str_did;
|
|
|
+ callid->len= smc- str_did;
|
|
|
+
|
|
|
+ from_tag->s= smc+ RLS_DID_SEP_LEN;
|
|
|
+ smc= strstr(from_tag->s, RLS_DID_SEP);
|
|
|
+ if(smc== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("bad format for resource list Subscribe dialog"
|
|
|
+ " indentifier(rlsubs did)= %s\n", str_did);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ from_tag->len= smc- from_tag->s;
|
|
|
+
|
|
|
+ to_tag->s= smc+ RLS_DID_SEP_LEN;
|
|
|
+ to_tag->len= strlen(str_did)- 2* RLS_DID_SEP_LEN- callid->len- from_tag->len;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void get_dialog_from_did(char* did, subs_t **dialog, unsigned int *hash_code)
|
|
|
+{
|
|
|
+ str callid, to_tag, from_tag;
|
|
|
+ subs_t* s;
|
|
|
+
|
|
|
+ *dialog= NULL;
|
|
|
+
|
|
|
+ /* search the subscription in rlsubs_table*/
|
|
|
+ if( parse_rlsubs_did(did, &callid, &from_tag, &to_tag)< 0)
|
|
|
+ {
|
|
|
+ LM_ERR("bad format for "
|
|
|
+ "resource list Subscribe dialog indentifier(rlsubs did)\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ *hash_code= core_hash(&callid, &to_tag, hash_size);
|
|
|
+
|
|
|
+ lock_get(&rls_table[*hash_code].lock);
|
|
|
+ s= pres_search_shtable(rls_table,callid,to_tag,from_tag,*hash_code);
|
|
|
+ if(s== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("record not found in hash_table [rlsubs_did]= %s\n",
|
|
|
+ did);
|
|
|
+ lock_release(&rls_table[*hash_code].lock);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* save dialog info */
|
|
|
+ *dialog= pres_copy_subs(s, PKG_MEM_TYPE);
|
|
|
+ if(*dialog== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("while copying subs_t structure\n");
|
|
|
+ }
|
|
|
+ lock_release(&rls_table[*hash_code].lock);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+int send_notify(xmlDocPtr * rlmi_doc, char * buf, int buf_len,
|
|
|
+ const str bstr, subs_t * dialog, unsigned int hash_code)
|
|
|
+{
|
|
|
+ int result = 0;
|
|
|
+ str rlmi_cont= {0, 0}, multi_cont;
|
|
|
+
|
|
|
+ xmlDocDumpFormatMemory(*rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s,
|
|
|
+ &rlmi_cont.len, 0);
|
|
|
+
|
|
|
+ multi_cont.s= buf;
|
|
|
+ multi_cont.len= buf_len;
|
|
|
+
|
|
|
+ result =agg_body_sendn_update(&dialog->pres_uri, bstr.s, &rlmi_cont,
|
|
|
+ (buf_len==0)?NULL:&multi_cont, dialog, hash_code);
|
|
|
+ xmlFree(rlmi_cont.s);
|
|
|
+ xmlFreeDoc(*rlmi_doc);
|
|
|
+ *rlmi_doc= NULL;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void send_notifies(db1_res_t *result, int did_col, int resource_uri_col, int auth_state_col, int reason_col,
|
|
|
+ int pres_state_col, int content_type_col, subs_t* subscription, int external_hash)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ char* prev_did= NULL, * curr_did= NULL;
|
|
|
+ db_row_t *row;
|
|
|
+ db_val_t *row_vals;
|
|
|
+ char* resource_uri;
|
|
|
+ str pres_state = {0, 0};
|
|
|
+ xmlDocPtr rlmi_doc= NULL;
|
|
|
+ xmlNodePtr list_node= NULL, instance_node= NULL, resource_node;
|
|
|
+ unsigned int hash_code= 0;
|
|
|
+ int size= BUF_REALLOC_SIZE, buf_len= 0;
|
|
|
+ char* buf= NULL, *auth_state= NULL, *boundary_string= NULL;
|
|
|
+ str cid = {0,0};
|
|
|
+ str content_type= {0, 0};
|
|
|
+ int contor= 0, auth_state_flag;
|
|
|
+ int chunk_len=0;
|
|
|
+ str bstr= {0, 0};
|
|
|
+ subs_t* dialog= NULL;
|
|
|
+ int len_est = 0;
|
|
|
+ int resource_added = 0; /* Flag to indicate that we have added at least one resource */
|
|
|
+
|
|
|
+ /* generate the boundary string */
|
|
|
+ boundary_string= generate_string((int)time(NULL), BOUNDARY_STRING_LEN);
|
|
|
+ bstr.len= strlen(boundary_string);
|
|
|
+ bstr.s= (char*)pkg_malloc((bstr.len+ 1)* sizeof(char));
|
|
|
+ if(bstr.s== NULL)
|
|
|
+ {
|
|
|
+ ERR_MEM(PKG_MEM_STR);
|
|
|
+ }
|
|
|
+ memcpy(bstr.s, boundary_string, bstr.len);
|
|
|
+ bstr.s[bstr.len]= '\0';
|
|
|
+
|
|
|
+ /* Allocate an initial buffer for the multipart body.
|
|
|
+ * This buffer will be reallocated if neccessary */
|
|
|
+ buf= pkg_malloc(size* sizeof(char));
|
|
|
+ if(buf== NULL)
|
|
|
+ {
|
|
|
+ ERR_MEM(PKG_MEM_STR);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ dialog = subscription;
|
|
|
+ /* If we have been given a subscription to use
|
|
|
+ We should also have been given a hash value. */
|
|
|
+ hash_code = external_hash;
|
|
|
+ }
|
|
|
+
|
|
|
+ LM_DBG("found %d records with updated state\n", result->n);
|
|
|
+ for(i= 0; i< result->n; i++)
|
|
|
+ {
|
|
|
+ row = &result->rows[i];
|
|
|
+ row_vals = ROW_VALUES(row);
|
|
|
+
|
|
|
+ curr_did= (char*)row_vals[did_col].val.string_val;
|
|
|
+ resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
|
|
|
+ auth_state_flag= row_vals[auth_state_col].val.int_val;
|
|
|
+ pres_state.s= (char*)row_vals[pres_state_col].val.string_val;
|
|
|
+ pres_state.len = strlen(pres_state.s);
|
|
|
+ trim(&pres_state);
|
|
|
+
|
|
|
+ /* If we have moved onto a new resource list Subscribe dialog indentifier,
|
|
|
+ Send a NOTIFY for the previous ID and then drop the existing documents. */
|
|
|
+ if(prev_did!= NULL && strcmp(prev_did, curr_did))
|
|
|
+ {
|
|
|
+ if (send_notify(&rlmi_doc, buf, buf_len, bstr, dialog, hash_code))
|
|
|
+ {
|
|
|
+ LM_ERR("in send_notify\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ len_est = 0;
|
|
|
+
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ pkg_free(dialog);
|
|
|
+ dialog= NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*if first or different*/
|
|
|
+ if(prev_did==NULL || strcmp(prev_did, curr_did)!=0)
|
|
|
+ {
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ /* We have not been given a subscription
|
|
|
+ Work it out from the did. */
|
|
|
+ get_dialog_from_did(curr_did, &dialog, &hash_code);
|
|
|
+ if(dialog== NULL)
|
|
|
+ {
|
|
|
+ prev_did = NULL;
|
|
|
+ LM_ERR("Dialog is NULL\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ len_est = create_empty_rlmi_doc(&rlmi_doc, &list_node, &dialog->pres_uri, dialog->version, 0);
|
|
|
+ len_est += 2*strlen(boundary_string)+4+102+2+50+strlen(resource_uri)+20;
|
|
|
+ buf_len= 0;
|
|
|
+
|
|
|
+ /* !!!! for now I will include the auth state without checking if
|
|
|
+ * it has changed - > in future chech if it works */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* add a node in rlmi_doc and if any presence state registered add
|
|
|
+ * it in the buffer */
|
|
|
+
|
|
|
+ resource_node= xmlNewChild(list_node,NULL,BAD_CAST "resource", NULL);
|
|
|
+ if(resource_node== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("when adding resource child\n");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ xmlNewProp(resource_node, BAD_CAST "uri", BAD_CAST resource_uri);
|
|
|
+ len_est += strlen (resource_uri) + 35; /* <resource uri="[uri]"></resource>/r/n */
|
|
|
+
|
|
|
+ /* there might be more records with the same uri- more instances-
|
|
|
+ * search and add them all */
|
|
|
+
|
|
|
+ contor= 0;
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ contor++;
|
|
|
+ cid.s= NULL;
|
|
|
+ cid.len= 0;
|
|
|
+
|
|
|
+ auth_state= get_auth_string(auth_state_flag);
|
|
|
+ if(auth_state== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("bad authorization status flag\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ len_est += strlen(auth_state) + 38; /* <instance id="12345678" state="[auth_state]" />r/n */
|
|
|
+
|
|
|
+ if(auth_state_flag & ACTIVE_STATE)
|
|
|
+ {
|
|
|
+ cid.s= generate_cid(resource_uri, strlen(resource_uri));
|
|
|
+ cid.len = strlen(cid.s);
|
|
|
+ len_est += cid.len + 8; /* cid="[cid]" */
|
|
|
+ content_type.s = (char*)row_vals[content_type_col].val.string_val;
|
|
|
+ content_type.len = strlen(content_type.s);
|
|
|
+ chunk_len = 4 + bstr.len
|
|
|
+ + 35
|
|
|
+ + 16 + cid.len
|
|
|
+ + 18 + content_type.len
|
|
|
+ + 4 + pres_state.len + 8;
|
|
|
+ len_est += chunk_len;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if(auth_state_flag & TERMINATED_STATE)
|
|
|
+ {
|
|
|
+ len_est += strlen(row_vals[resource_uri_col].val.string_val) + 10; /* reason="[resaon]" */
|
|
|
+ }
|
|
|
+
|
|
|
+ if (rls_max_notify_body_len > 0 && len_est > rls_max_notify_body_len)
|
|
|
+ {
|
|
|
+ /* We have a limit on body length set, and we were about to exceed it */
|
|
|
+ if (resource_added == 1)
|
|
|
+ {
|
|
|
+ /* We added at least one resource. */
|
|
|
+ LM_ERR("timer_send_notify hit the size limit. len_est = %d\n", len_est);
|
|
|
+ if (send_notify(&rlmi_doc, buf, buf_len, bstr, dialog, hash_code))
|
|
|
+ {
|
|
|
+ LM_ERR("in send_notify\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+ i --;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LM_ERR("timer_send_notify hit the size limit. NO RESOURCE ADDED len_est = %d\n", len_est);
|
|
|
+ }
|
|
|
+ len_est = 0;
|
|
|
+
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ pkg_free(dialog);
|
|
|
+ dialog= NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ curr_did=NULL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* OK, we are happy this will fit */
|
|
|
+ instance_node= xmlNewChild(resource_node, NULL, BAD_CAST "instance", NULL);
|
|
|
+ if(instance_node== NULL)
|
|
|
+ {
|
|
|
+ LM_ERR("while adding instance child\n");
|
|
|
+ goto error;
|
|
|
+ }
|
|
|
+
|
|
|
+ xmlNewProp(instance_node, BAD_CAST "id",
|
|
|
+ BAD_CAST generate_string(contor, 8));
|
|
|
+ if(auth_state_flag & ACTIVE_STATE)
|
|
|
+ {
|
|
|
+ xmlNewProp(instance_node, BAD_CAST "state", BAD_CAST auth_state);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if(auth_state_flag & TERMINATED_STATE)
|
|
|
+ {
|
|
|
+ xmlNewProp(instance_node, BAD_CAST "reason",
|
|
|
+ BAD_CAST row_vals[resource_uri_col].val.string_val);
|
|
|
+ }
|
|
|
+ xmlNewProp(instance_node, BAD_CAST "cid", BAD_CAST cid.s);
|
|
|
+
|
|
|
+ /* add in the multipart buffer */
|
|
|
+ if(cid.s)
|
|
|
+ {
|
|
|
+
|
|
|
+ if(buf_len + chunk_len >= size)
|
|
|
+ {
|
|
|
+ REALLOC_BUF
|
|
|
+ }
|
|
|
+ buf_len+= sprintf(buf+ buf_len, "--%.*s\r\n", bstr.len,
|
|
|
+ bstr.s);
|
|
|
+ buf_len+= sprintf(buf+ buf_len,
|
|
|
+ "Content-Transfer-Encoding: binary\r\n");
|
|
|
+ buf_len+= sprintf(buf+ buf_len, "Content-ID: <%.*s>\r\n",
|
|
|
+ cid.len, cid.s);
|
|
|
+ buf_len+= sprintf(buf+ buf_len, "Content-Type: %.*s\r\n\r\n",
|
|
|
+ content_type.len, content_type.s);
|
|
|
+ buf_len+= sprintf(buf+buf_len,"%.*s\r\n\r\n", pres_state.len,
|
|
|
+ pres_state.s);
|
|
|
+ }
|
|
|
+
|
|
|
+ i++;
|
|
|
+ if(i== result->n)
|
|
|
+ {
|
|
|
+ i--;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ row = &result->rows[i];
|
|
|
+ row_vals = ROW_VALUES(row);
|
|
|
+
|
|
|
+ if(strncmp(resource_uri, row_vals[resource_uri_col].val.string_val,
|
|
|
+ strlen(resource_uri))
|
|
|
+ || strncmp(curr_did, row_vals[did_col].val.string_val,
|
|
|
+ strlen(curr_did)))
|
|
|
+ {
|
|
|
+ i--;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
|
|
|
+ auth_state_flag= row_vals[auth_state_col].val.int_val;
|
|
|
+ pres_state.s= (char*)row_vals[pres_state_col].val.string_val;
|
|
|
+ pres_state.len= strlen(pres_state.s);
|
|
|
+ trim(&pres_state);
|
|
|
+ }
|
|
|
+
|
|
|
+ prev_did= curr_did;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(rlmi_doc)
|
|
|
+ {
|
|
|
+ LM_ERR("timer_send_notify at end len_est = %d resource_added = %d\n", len_est, resource_added);
|
|
|
+ if (resource_added == 1)
|
|
|
+ {
|
|
|
+ send_notify(&rlmi_doc, buf, buf_len, bstr, dialog, hash_code);
|
|
|
+ }
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ /* We are using a derived subscription */
|
|
|
+ if(dialog)
|
|
|
+ {
|
|
|
+ pkg_free(dialog);
|
|
|
+ }
|
|
|
+ dialog= NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+error:
|
|
|
+done:
|
|
|
+ if(bstr.s)
|
|
|
+ pkg_free(bstr.s);
|
|
|
+
|
|
|
+ if(buf)
|
|
|
+ pkg_free(buf);
|
|
|
+ if (subscription == NULL)
|
|
|
+ {
|
|
|
+ /* We are using a derived subscription */
|
|
|
+ if(dialog)
|
|
|
+ pkg_free(dialog);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int parse_subs_state(str auth_state, str** reason, int* expires)
|
|
|
{
|
|
|
str str_exp;
|
|
@@ -87,10 +466,10 @@ int parse_subs_state(str auth_state, str** reason, int* expires)
|
|
|
{
|
|
|
LM_ERR("terminated state and no reason found");
|
|
|
return -1;
|
|
|
- }
|
|
|
+ }
|
|
|
res= (str*)pkg_malloc(sizeof(str));
|
|
|
if(res== NULL)
|
|
|
- {
|
|
|
+ {
|
|
|
ERR_MEM(PKG_MEM_STR);
|
|
|
}
|
|
|
len= auth_state.len- 10- 1- 7;
|
|
@@ -103,7 +482,7 @@ int parse_subs_state(str auth_state, str** reason, int* expires)
|
|
|
res->len= len;
|
|
|
return TERMINATED_STATE;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if(flag> 0)
|
|
|
{
|
|
|
smc= strchr(auth_state.s, ';');
|
|
@@ -111,7 +490,7 @@ int parse_subs_state(str auth_state, str** reason, int* expires)
|
|
|
{
|
|
|
LM_ERR("active or pending state and no expires parameter found");
|
|
|
return -1;
|
|
|
- }
|
|
|
+ }
|
|
|
if(strncmp(smc+1, "expires=", 8))
|
|
|
{
|
|
|
LM_ERR("active or pending state and no expires parameter found");
|
|
@@ -121,10 +500,10 @@ int parse_subs_state(str auth_state, str** reason, int* expires)
|
|
|
str_exp.len= auth_state.s+ auth_state.len- smc- 9;
|
|
|
|
|
|
if( str2int(&str_exp, (unsigned int*)expires)< 0)
|
|
|
- {
|
|
|
+ {
|
|
|
LM_ERR("while getting int from str\n");
|
|
|
return -1;
|
|
|
- }
|
|
|
+ }
|
|
|
return flag;
|
|
|
|
|
|
}
|
|
@@ -175,9 +554,9 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
{
|
|
|
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 );
|
|
@@ -190,13 +569,13 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
{
|
|
|
LM_ERR(" 'To' header NOT parsed\n");
|
|
|
return -1;
|
|
|
- }
|
|
|
+ }
|
|
|
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");
|
|
|
goto error;
|
|
|
}
|
|
@@ -220,12 +599,12 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
if ( parse_from_header( msg )<0 )
|
|
|
{
|
|
|
LM_ERR("cannot parse From header\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
+ 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");
|
|
@@ -256,7 +635,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
{
|
|
|
LM_ERR("'Subscription-State' header not found\n");
|
|
|
goto error;
|
|
|
- }
|
|
|
+ }
|
|
|
auth_state = hdr->body;
|
|
|
|
|
|
/* extract state and reason */
|
|
@@ -266,7 +645,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
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
|
|
|
+ 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;
|
|
@@ -280,22 +659,23 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
*/
|
|
|
if(auth_flag==TERMINATED_STATE)
|
|
|
goto done;
|
|
|
- LM_ERR("no presence dialog record for non-TERMINATED state\n");
|
|
|
+ LM_ERR("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);
|
|
|
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;
|
|
|
- }
|
|
|
+ {
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
else
|
|
|
{
|
|
|
if(content_type.s== 0)
|
|
@@ -313,7 +693,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
|
|
|
}
|
|
|
/* 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;
|
|
@@ -321,7 +701,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
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;
|
|
@@ -333,7 +713,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
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 = DB1_INT;
|
|
|
query_vals[n_query_cols].nul = 0;
|
|
@@ -353,13 +733,13 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
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;
|
|
@@ -373,7 +753,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
}
|
|
|
/* 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)
|
|
|
{
|
|
@@ -386,7 +766,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
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)
|
|
@@ -406,7 +786,7 @@ int rls_handle_notify(struct sip_msg* msg, char* c1, char* c2)
|
|
|
goto error;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
LM_DBG("Updated rlpres_table\n");
|
|
|
/* reply 200OK */
|
|
|
done:
|
|
@@ -414,7 +794,7 @@ done:
|
|
|
{
|
|
|
LM_ERR("while sending reply\n");
|
|
|
goto error;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
if(res_id!=NULL)
|
|
|
{
|
|
@@ -430,38 +810,8 @@ error:
|
|
|
pkg_free(res_id);
|
|
|
}
|
|
|
return -1;
|
|
|
-}
|
|
|
-/* callid, from_tag, to_tag parameters must be allocated */
|
|
|
-
|
|
|
-int parse_rlsubs_did(char* str_did, str* callid, str* from_tag, str* to_tag)
|
|
|
-{
|
|
|
- char* smc= NULL;
|
|
|
-
|
|
|
- smc= strstr(str_did, RLS_DID_SEP);
|
|
|
- if(smc== NULL)
|
|
|
- {
|
|
|
- LM_ERR("bad format for resource list Subscribe dialog"
|
|
|
- " indentifier[rlsubs did]= %s\n", str_did);
|
|
|
- return -1;
|
|
|
}
|
|
|
- callid->s= str_did;
|
|
|
- callid->len= smc- str_did;
|
|
|
-
|
|
|
- from_tag->s= smc+ RLS_DID_SEP_LEN;
|
|
|
- smc= strstr(from_tag->s, RLS_DID_SEP);
|
|
|
- if(smc== NULL)
|
|
|
- {
|
|
|
- LM_ERR("bad format for resource list Subscribe dialog"
|
|
|
- " indentifier(rlsubs did)= %s\n", str_did);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- from_tag->len= smc- from_tag->s;
|
|
|
-
|
|
|
- to_tag->s= smc+ RLS_DID_SEP_LEN;
|
|
|
- to_tag->len= strlen(str_did)- 2* RLS_DID_SEP_LEN- callid->len- from_tag->len;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
+/* callid, from_tag, to_tag parameters must be allocated */
|
|
|
|
|
|
void timer_send_notify(unsigned int ticks,void *param)
|
|
|
{
|
|
@@ -469,29 +819,9 @@ void timer_send_notify(unsigned int ticks,void *param)
|
|
|
db_val_t query_vals[2], update_vals[1];
|
|
|
int did_col, resource_uri_col, auth_state_col, reason_col,
|
|
|
pres_state_col, content_type_col;
|
|
|
- int n_result_cols= 0, i;
|
|
|
+ int n_result_cols= 0;
|
|
|
db1_res_t *result= NULL;
|
|
|
- char* prev_did= NULL, * curr_did= NULL;
|
|
|
- db_row_t *row;
|
|
|
- db_val_t *row_vals;
|
|
|
- char* resource_uri;
|
|
|
- str pres_state = {0, 0};
|
|
|
- str callid, to_tag, from_tag;
|
|
|
- xmlDocPtr rlmi_doc= NULL;
|
|
|
- xmlNodePtr list_node= NULL, instance_node= NULL, resource_node;
|
|
|
- unsigned int hash_code= 0;
|
|
|
- int len;
|
|
|
- int size= BUF_REALLOC_SIZE, buf_len= 0;
|
|
|
- char* buf= NULL, *auth_state= NULL, *boundary_string= NULL;
|
|
|
- str cid = {0,0};
|
|
|
- str content_type = {0,0};
|
|
|
- int contor= 0, auth_state_flag;
|
|
|
- int chunk_len;
|
|
|
- str bstr= {0, 0};
|
|
|
- str rlmi_cont= {0, 0}, multi_cont;
|
|
|
- subs_t* s, *dialog= NULL;
|
|
|
- char* rl_uri= NULL;
|
|
|
-
|
|
|
+
|
|
|
query_cols[0]= &str_updated_col;
|
|
|
query_vals[0].type = DB1_INT;
|
|
|
query_vals[0].nul = 0;
|
|
@@ -504,9 +834,14 @@ void timer_send_notify(unsigned int ticks,void *param)
|
|
|
result_cols[reason_col= n_result_cols++]= &str_reason_col;
|
|
|
result_cols[pres_state_col= n_result_cols++]= &str_presence_state_col;
|
|
|
|
|
|
- /* query in alfabetical order after rlsusbs_did
|
|
|
- * (resource list Subscribe dialog indentifier)*/
|
|
|
+ update_cols[0]= &str_updated_col;
|
|
|
+ update_vals[0].type = DB1_INT;
|
|
|
+ update_vals[0].nul = 0;
|
|
|
+ update_vals[0].val.int_val= NO_UPDATE_TYPE;
|
|
|
|
|
|
+ /* query in alphabetical order after rlsusbs_did
|
|
|
+ * (resource list Subscribe dialog indentifier)*/
|
|
|
+
|
|
|
if (rls_dbf.use_table(rls_db, &rlpres_table) < 0)
|
|
|
{
|
|
|
LM_ERR("in use_table\n");
|
|
@@ -523,16 +858,6 @@ void timer_send_notify(unsigned int ticks,void *param)
|
|
|
goto done;
|
|
|
|
|
|
/* update the rlpres table */
|
|
|
- update_cols[0]= &str_updated_col;
|
|
|
- update_vals[0].type = DB1_INT;
|
|
|
- update_vals[0].nul = 0;
|
|
|
- update_vals[0].val.int_val= NO_UPDATE_TYPE;
|
|
|
-
|
|
|
- if (rls_dbf.use_table(rls_db, &rlpres_table) < 0)
|
|
|
- {
|
|
|
- LM_ERR("in use_table\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
if(rls_dbf.update(rls_db, query_cols, 0, query_vals, update_cols,
|
|
|
update_vals, 1, 1)< 0)
|
|
|
{
|
|
@@ -540,279 +865,13 @@ void timer_send_notify(unsigned int ticks,void *param)
|
|
|
goto error;
|
|
|
}
|
|
|
|
|
|
- /* generate the boundary string */
|
|
|
-
|
|
|
- boundary_string= generate_string((int)time(NULL), BOUNDARY_STRING_LEN);
|
|
|
- bstr.len= strlen(boundary_string);
|
|
|
- bstr.s= (char*)pkg_malloc((bstr.len+ 1)* sizeof(char));
|
|
|
- if(bstr.s== NULL)
|
|
|
- {
|
|
|
- ERR_MEM(PKG_MEM_STR);
|
|
|
- }
|
|
|
- memcpy(bstr.s, boundary_string, bstr.len);
|
|
|
- bstr.s[bstr.len]= '\0';
|
|
|
-
|
|
|
- /* for the multipart body , use here also an initial allocated
|
|
|
- * and reallocated on need buffer */
|
|
|
- buf= pkg_malloc(size* sizeof(char));
|
|
|
- if(buf== NULL)
|
|
|
- {
|
|
|
- ERR_MEM(PKG_MEM_STR);
|
|
|
- }
|
|
|
-
|
|
|
- LM_DBG("found %d records with updated state\n", result->n);
|
|
|
- for(i= 0; i< result->n; i++)
|
|
|
- {
|
|
|
- row = &result->rows[i];
|
|
|
- row_vals = ROW_VALUES(row);
|
|
|
-
|
|
|
- curr_did= (char*)row_vals[did_col].val.string_val;
|
|
|
- resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
|
|
|
- auth_state_flag= row_vals[auth_state_col].val.int_val;
|
|
|
- pres_state.s= (char*)row_vals[pres_state_col].val.string_val;
|
|
|
- pres_state.len = strlen(pres_state.s);
|
|
|
- trim(&pres_state);
|
|
|
-
|
|
|
- if(prev_did!= NULL && strcmp(prev_did, curr_did))
|
|
|
- {
|
|
|
- xmlDocDumpFormatMemory(rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s,
|
|
|
- &rlmi_cont.len, 1);
|
|
|
-
|
|
|
- multi_cont.s= buf;
|
|
|
- multi_cont.len= buf_len;
|
|
|
-
|
|
|
- if(agg_body_sendn_update(&dialog->pres_uri, bstr.s, &rlmi_cont,
|
|
|
- (buf_len==0)?NULL:&multi_cont, dialog, hash_code)<0)
|
|
|
- {
|
|
|
- LM_ERR("in function agg_body_sendn_update\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- xmlFree(rlmi_cont.s);
|
|
|
- xmlFreeDoc(rlmi_doc);
|
|
|
- rlmi_doc= NULL;
|
|
|
- pkg_free(rl_uri);
|
|
|
- rl_uri= NULL;
|
|
|
- pkg_free(dialog);
|
|
|
- dialog= NULL;
|
|
|
- }
|
|
|
-
|
|
|
- /*if first or different*/
|
|
|
- if(prev_did==NULL || strcmp(prev_did, curr_did)!=0)
|
|
|
- {
|
|
|
- /* search the subscription in rlsubs_table*/
|
|
|
- if( parse_rlsubs_did(curr_did, &callid, &from_tag, &to_tag)< 0)
|
|
|
- {
|
|
|
- LM_ERR("bad format for "
|
|
|
- "resource list Subscribe dialog indentifier(rlsubs did)\n");
|
|
|
- prev_did = NULL;
|
|
|
- continue;
|
|
|
-
|
|
|
- }
|
|
|
- hash_code= core_hash(&callid, &to_tag, hash_size);
|
|
|
-
|
|
|
- lock_get(&rls_table[hash_code].lock);
|
|
|
- s= pres_search_shtable(rls_table,callid,to_tag,from_tag,hash_code);
|
|
|
- if(s== NULL)
|
|
|
- {
|
|
|
- LM_DBG("record not found in hash_table [rlsubs_did]= %s\n",
|
|
|
- curr_did);
|
|
|
- LM_DBG("callid= %.*s\tfrom_tag= %.*s\tto_tag= %.*s\n",
|
|
|
- callid.len, callid.s,from_tag.len,from_tag.s,
|
|
|
- to_tag.len,to_tag.s);
|
|
|
- lock_release(&rls_table[hash_code].lock);
|
|
|
- prev_did = NULL;
|
|
|
- continue;
|
|
|
- }
|
|
|
- LM_DBG("Found rl-subs record in hash table\n");
|
|
|
-
|
|
|
- /* save dialog info and rl_uri*/
|
|
|
- dialog= pres_copy_subs(s, PKG_MEM_TYPE);
|
|
|
- if(dialog== NULL)
|
|
|
- {
|
|
|
- LM_ERR("while copying subs_t structure\n");
|
|
|
- lock_release(&rls_table[hash_code].lock);
|
|
|
- goto done;
|
|
|
- }
|
|
|
- lock_release(&rls_table[hash_code].lock);
|
|
|
-
|
|
|
- /* make new rlmi and multipart documents */
|
|
|
- rlmi_doc= xmlNewDoc(BAD_CAST "1.0");
|
|
|
- if(rlmi_doc== NULL)
|
|
|
- {
|
|
|
- LM_ERR("when creating new xml doc\n");
|
|
|
- goto done;
|
|
|
- }
|
|
|
- list_node= xmlNewNode(NULL, BAD_CAST "list");
|
|
|
- if(list_node== NULL)
|
|
|
- {
|
|
|
- LM_ERR("while creating new xml node\n");
|
|
|
- goto done;
|
|
|
- }
|
|
|
- rl_uri= (char*)pkg_malloc((dialog->pres_uri.len+ 1)* sizeof(char));
|
|
|
- if(rl_uri== NULL)
|
|
|
- {
|
|
|
- ERR_MEM(PKG_MEM_STR);
|
|
|
- }
|
|
|
- memcpy(rl_uri, dialog->pres_uri.s, dialog->pres_uri.len);
|
|
|
- rl_uri[dialog->pres_uri.len]= '\0';
|
|
|
-
|
|
|
- xmlNewProp(list_node, BAD_CAST "uri", BAD_CAST rl_uri);
|
|
|
- xmlNewProp(list_node, BAD_CAST "xmlns",
|
|
|
- BAD_CAST "urn:ietf:params:xml:ns:rlmi");
|
|
|
- xmlNewProp(list_node, BAD_CAST "version",
|
|
|
- BAD_CAST int2str(dialog->version, &len));
|
|
|
- xmlNewProp(list_node, BAD_CAST "fullState", BAD_CAST "false");
|
|
|
-
|
|
|
- xmlDocSetRootElement(rlmi_doc, list_node);
|
|
|
- buf_len= 0;
|
|
|
-
|
|
|
- /* !!!! for now I will include the auth state without checking if
|
|
|
- * it has changed - > in future chech if it works */
|
|
|
- }
|
|
|
-
|
|
|
- /* add a node in rlmi_doc and if any presence state registered add
|
|
|
- * it in the buffer */
|
|
|
-
|
|
|
- resource_node= xmlNewChild(list_node,NULL,BAD_CAST "resource", NULL);
|
|
|
- if(resource_node== NULL)
|
|
|
- {
|
|
|
- LM_ERR("when adding resource child\n");
|
|
|
- goto done;
|
|
|
- }
|
|
|
- xmlNewProp(resource_node, BAD_CAST "uri", BAD_CAST resource_uri);
|
|
|
-
|
|
|
- /* there might be more records with the same uri- more instances-
|
|
|
- * search and add them all */
|
|
|
-
|
|
|
- contor= 0;
|
|
|
- while(1)
|
|
|
- {
|
|
|
- contor++;
|
|
|
- cid.s= NULL;
|
|
|
- cid.len= 0;
|
|
|
- instance_node= xmlNewChild(resource_node, NULL,
|
|
|
- BAD_CAST "instance", NULL);
|
|
|
- if(instance_node== NULL)
|
|
|
- {
|
|
|
- LM_ERR("while adding instance child\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- xmlNewProp(instance_node, BAD_CAST "id",
|
|
|
- BAD_CAST generate_string(contor, 8));
|
|
|
-
|
|
|
- auth_state= get_auth_string(auth_state_flag);
|
|
|
- if(auth_state== NULL)
|
|
|
- {
|
|
|
- LM_ERR("bad authorization status flag\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- xmlNewProp(instance_node, BAD_CAST "state", BAD_CAST auth_state);
|
|
|
-
|
|
|
- if(auth_state_flag & ACTIVE_STATE)
|
|
|
- {
|
|
|
- cid.s= generate_cid(resource_uri, strlen(resource_uri));
|
|
|
- xmlNewProp(instance_node, BAD_CAST "cid", BAD_CAST cid.s);
|
|
|
- }
|
|
|
- else
|
|
|
- if(auth_state_flag & TERMINATED_STATE)
|
|
|
- {
|
|
|
- xmlNewProp(instance_node, BAD_CAST "reason",
|
|
|
- BAD_CAST row_vals[resource_uri_col].val.string_val);
|
|
|
- }
|
|
|
-
|
|
|
- /* add in the multipart buffer */
|
|
|
- if(cid.s)
|
|
|
- {
|
|
|
- cid.len = strlen(cid.s);
|
|
|
- content_type.s = (char*)row_vals[content_type_col].val.string_val;
|
|
|
- content_type.len = strlen(content_type.s);
|
|
|
- chunk_len = 4 + bstr.len
|
|
|
- + 35
|
|
|
- + 16 + cid.len
|
|
|
- + 18 + content_type.len
|
|
|
- + 4 + pres_state.len + 8;
|
|
|
- if(buf_len + chunk_len >= size)
|
|
|
- {
|
|
|
- REALLOC_BUF
|
|
|
- }
|
|
|
- buf_len+= sprintf(buf+ buf_len, "--%.*s\r\n", bstr.len,
|
|
|
- bstr.s);
|
|
|
- buf_len+= sprintf(buf+ buf_len,
|
|
|
- "Content-Transfer-Encoding: binary\r\n");
|
|
|
- buf_len+= sprintf(buf+ buf_len, "Content-ID: <%.*s>\r\n",
|
|
|
- cid.len, cid.s);
|
|
|
- buf_len+= sprintf(buf+ buf_len, "Content-Type: %.*s\r\n\r\n",
|
|
|
- content_type.len, content_type.s);
|
|
|
- buf_len+= sprintf(buf+buf_len,"%.*s\r\n\r\n", pres_state.len,
|
|
|
- pres_state.s);
|
|
|
- }
|
|
|
-
|
|
|
- i++;
|
|
|
- if(i== result->n)
|
|
|
- {
|
|
|
- i--;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- row = &result->rows[i];
|
|
|
- row_vals = ROW_VALUES(row);
|
|
|
-
|
|
|
- if(strncmp(resource_uri, row_vals[resource_uri_col].val.string_val,
|
|
|
- strlen(resource_uri))
|
|
|
- || strncmp(curr_did, row_vals[did_col].val.string_val,
|
|
|
- strlen(curr_did)))
|
|
|
- {
|
|
|
- i--;
|
|
|
- break;
|
|
|
- }
|
|
|
- resource_uri= (char*)row_vals[resource_uri_col].val.string_val;
|
|
|
- auth_state_flag= row_vals[auth_state_col].val.int_val;
|
|
|
- pres_state.s= (char*)row_vals[pres_state_col].val.string_val;
|
|
|
- pres_state.len= strlen(pres_state.s);
|
|
|
- trim(&pres_state);
|
|
|
- }
|
|
|
-
|
|
|
- prev_did= curr_did;
|
|
|
- }
|
|
|
-
|
|
|
- if(rlmi_doc)
|
|
|
- {
|
|
|
- xmlDocDumpFormatMemory( rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s,
|
|
|
- &rlmi_cont.len, 1);
|
|
|
-
|
|
|
- multi_cont.s= buf;
|
|
|
- multi_cont.len= buf_len;
|
|
|
-
|
|
|
- if(agg_body_sendn_update(&dialog->pres_uri, bstr.s, &rlmi_cont,
|
|
|
- (buf_len==0)?NULL:&multi_cont, dialog, hash_code)<0)
|
|
|
- {
|
|
|
- LM_ERR("in function agg_body_sendn_update\n");
|
|
|
- goto error;
|
|
|
- }
|
|
|
- xmlFree(rlmi_cont.s);
|
|
|
- pkg_free(rl_uri);
|
|
|
- rl_uri= NULL;
|
|
|
- pkg_free(dialog);
|
|
|
- dialog= NULL;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+ send_notifies(result, did_col, resource_uri_col, auth_state_col, reason_col,
|
|
|
+ pres_state_col, content_type_col,
|
|
|
+ NULL, 0); /* Work out the subscription */
|
|
|
error:
|
|
|
done:
|
|
|
if(result)
|
|
|
rls_dbf.free_result(rls_db, result);
|
|
|
- if(rlmi_doc)
|
|
|
- xmlFreeDoc(rlmi_doc);
|
|
|
- if(rl_uri)
|
|
|
- pkg_free(rl_uri);
|
|
|
- if(bstr.s)
|
|
|
- pkg_free(bstr.s);
|
|
|
-
|
|
|
- if(buf)
|
|
|
- pkg_free(buf);
|
|
|
- if(dialog)
|
|
|
- pkg_free(dialog);
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
|