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; } if (dbmode == RLS_DB_ONLY) { *dialog = get_dialog_notify_rlsdb(callid,to_tag,from_tag); if(*dialog==NULL) { LM_INFO("record not retrieved from db [rlsubs_did]= %s\n", did); return; } } else { *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_INFO("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); return; } } if ((*dialog)->expires < (int)time(NULL)) (*dialog)->expires = 0; else (*dialog)->expires -= (int)time(NULL); if (dbmode != RLS_DB_ONLY) lock_release(&rls_table[*hash_code].lock); }
int rls_update_subs(struct sip_msg *msg, char *puri, char *pevent) { str uri; str event; struct sip_uri parsed_uri; event_t e; int i; if (fixup_get_svalue(msg, (gparam_p)puri, &uri) != 0) { LM_ERR("invalid uri parameter\n"); return -1; } if (fixup_get_svalue(msg, (gparam_p)pevent, &event) != 0) { LM_ERR("invalid event parameter\n"); return -1; } if (event_parser(event.s, event.len, &e) < 0) { LM_ERR("while parsing event: %.*s\n", event.len, event.s); return -1; } if (e.type & EVENT_OTHER) { LM_ERR("unrecognised event: %.*s\n", event.len, event.s); return -1; } if (!(e.type & rls_events)) { LM_ERR("event not supported by RLS: %.*s\n", event.len, event.s); return -1; } if (parse_uri(uri.s, uri.len, &parsed_uri) < 0) { LM_ERR("bad uri: %.*s\n", uri.len, uri.s); return -1; } LM_DBG("watcher username: %.*s, watcher domain: %.*s\n", parsed_uri.user.len, parsed_uri.user.s, parsed_uri.host.len, parsed_uri.host.s); if (dbmode==RLS_DB_ONLY) { int ret; lock_get(rls_update_subs_lock); ret = (update_all_subs_rlsdb(&parsed_uri.user, &parsed_uri.host, &event)); lock_release(rls_update_subs_lock); return ret; } if (rls_table == NULL) { LM_ERR("rls_table is NULL\n"); return -1; } /* Search through the entire subscription table for matches... */ for (i = 0; i < hash_size; i++) { subs_t *subs; lock_get(&rls_table[i].lock); subs = rls_table[i].entries->next; while (subs != NULL) { if (subs->watcher_user.len == parsed_uri.user.len && strncmp(subs->watcher_user.s, parsed_uri.user.s, parsed_uri.user.len) == 0 && subs->watcher_domain.len == parsed_uri.host.len && strncmp(subs->watcher_domain.s, parsed_uri.host.s, parsed_uri.host.len) == 0 && subs->event->evp->type == e.type) { subs_t *subs_copy = NULL; LM_DBG("found matching RLS subscription for: %.*s\n", subs->pres_uri.len, subs->pres_uri.s); if ((subs_copy = pres_copy_subs(subs, PKG_MEM_TYPE)) == NULL) { LM_ERR("subs_t copy failed\n"); lock_release(&rls_table[i].lock); return -1; } update_a_sub(subs_copy); } subs = subs->next; } lock_release(&rls_table[i].lock); } return 1; }
void timer_send_notify(unsigned int ticks,void *param) { db_key_t query_cols[2], update_cols[1], result_cols[7]; db_val_t query_vals[2], update_vals[1]; int did_col, resource_uri_col, auth_state_col, reason_col, body_col, ctype_col; int n_result_cols= 0, i; db_res_t *result= NULL; char* prev_did= NULL, * curr_did= NULL; db_row_t *row; db_val_t *row_vals; char* resource_uri; str body; 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; int contor= 0, auth_state_flag; str bstr= {0, 0}; str rlmi_cont= {0, 0}, multi_cont; subs_t* s, *dialog= NULL; char* rl_uri= NULL; char* str_aux = NULL; str ctype, cid; int add_len; query_cols[0]= &str_updated_col; query_vals[0].type = DB_INT; query_vals[0].nul = 0; query_vals[0].val.int_val= UPDATED_TYPE; result_cols[did_col= n_result_cols++]= &str_rlsubs_did_col; result_cols[resource_uri_col= n_result_cols++]= &str_resource_uri_col; result_cols[auth_state_col= n_result_cols++]= &str_auth_state_col; result_cols[ctype_col= n_result_cols++]= &str_content_type_col; result_cols[reason_col= n_result_cols++]= &str_reason_col; result_cols[body_col= n_result_cols++]= &str_presence_state_col; /* query in alfabetical 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"); goto done; } if(rls_dbf.query(rls_db, query_cols, 0, query_vals, result_cols, 1, n_result_cols, &str_rlsubs_did_col, &result)< 0) { LM_ERR("in sql query\n"); goto done; } if(result== NULL || result->n<= 0) goto done; /* update the rlpres table */ update_cols[0]= &str_updated_col; update_vals[0].type = DB_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) { LM_ERR("in sql update\n"); goto error; } /* generate the boundary string */ bstr.s= generate_string((int)time(NULL), BOUNDARY_STRING_LEN); if(bstr.s == NULL) { LM_ERR("failed to generate random string\n"); goto error; } bstr.len= strlen(bstr.s); /* for the multipart body , use here also an initial allocated * and reallocated on need buffer */ buf= pkg_malloc(size); 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; body.s= (char*)row_vals[body_col].val.string_val; body.len= strlen(body.s); ctype.s = (char*)row_vals[ctype_col].val.string_val; ctype.len = strlen(ctype.s); /* if all the info for one dialog have been collected -> send notify */ /* the 'dialog' variable must be filled with the dialog info */ /* 'buf' must contain the body */ if(prev_did!= NULL && strcmp(prev_did, curr_did)) { xmlDocDumpMemory(rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s, &rlmi_cont.len); multi_cont.s= buf; multi_cont.len= buf_len; if(agg_body_sendn_update(&dialog->pres_uri, bstr, &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; } /* for the new dialog -> search the dialog info and * fill the dialog structure and start a new rlmi document */ if(prev_did== NULL || strcmp(prev_did, curr_did)) { /* 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; } dialog->expires-= (int)time(NULL); 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; instance_node= xmlNewChild(resource_node, NULL, BAD_CAST "instance", NULL); if(instance_node== NULL) { LM_ERR("while adding instance child\n"); goto error; } str_aux = generate_string(contor, 8); if(str_aux == NULL) { LM_ERR("failed to create random string\n"); goto error; } xmlNewProp(instance_node, BAD_CAST "id", BAD_CAST str_aux); pkg_free(str_aux); 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)); cid.len = strlen(cid.s); 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) { APPEND_MULTIPART_BODY(); pkg_free(cid.s); cid.s = NULL; } i++; if(i== result->n) { i--; break; } row = &result->rows[i]; row_vals = ROW_VALUES(row); if(strncmp(row_vals[resource_uri_col].val.string_val,resource_uri, 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; body.s= (char*)row_vals[body_col].val.string_val; body.len = strlen(body.s); } prev_did= curr_did; } if(rlmi_doc) { xmlDocDumpMemory( rlmi_doc,(xmlChar**)(void*)&rlmi_cont.s, &rlmi_cont.len); multi_cont.s= buf; multi_cont.len= buf_len; if(agg_body_sendn_update(&dialog->pres_uri, bstr, &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; } 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; }