static void find_and_delete_record(ua_pres_t *dialog, int hash_code) { ua_pres_t *presentity; if (dbmode == PUA_DB_ONLY) { delete_record_puadb(dialog); } else { lock_get(&HashT->p_records[hash_code].lock); presentity = search_htable(dialog, hash_code); if (presentity == NULL) { LM_DBG("Record found in table and deleted\n"); lock_release(&HashT->p_records[hash_code].lock); return; } delete_htable(presentity, hash_code); lock_release(&HashT->p_records[hash_code].lock); } }
static int find_and_update_record(ua_pres_t *dialog, int hash_code, int lexpire, str *etag) { ua_pres_t *presentity; if(dbmode==PUA_DB_ONLY) { return update_record_puadb(dialog, lexpire, etag); } else { lock_get(&HashT->p_records[hash_code].lock); presentity = search_htable(dialog, hash_code); if (presentity == NULL) { LM_DBG("Record found in table and deleted\n"); lock_release(&HashT->p_records[hash_code].lock); return 0; } update_htable(presentity, dialog->desired_expires, lexpire, etag, hash_code, NULL); lock_release(&HashT->p_records[hash_code].lock); return 1; } }
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; }
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= 0; unsigned int hash_index; ua_pres_t* hentity= NULL, pres; int expires; int flag; int result; print_subs(subs); flag= subs->source_flag; if(subs->source_flag & XMPP_INITIAL_SUBS) subs->source_flag= XMPP_SUBSCRIBE; if(subs->expires< 0) subs->expires = default_expires; else if(subs->expires!= 0 && subs->expires < min_expires) subs->expires = min_expires; expires = subs->expires; if(subs->extra_headers) LM_DBG("received extra_headers = %.*s\n", subs->extra_headers->len, subs->extra_headers->s); 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; } memset(&pres, 0, sizeof(ua_pres_t)); pres.pres_uri = subs->pres_uri; pres.watcher_uri= subs->watcher_uri; if(subs->to_uri.s) pres.to_uri = subs->to_uri; else { pres.to_uri.s = subs->pres_uri->s; pres.to_uri.len = subs->pres_uri->len; } pres.flag = subs->source_flag; pres.id = subs->id; pres.event = subs->event; hash_index=core_hash(&pres.to_uri, pres.watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_index].lock); if(subs->flag != INSERT_TYPE) presentity= search_htable(&pres, hash_index); if(presentity== NULL ) { lock_release(&HashT->p_records[hash_index].lock); if(subs->flag & UPDATE_TYPE) { /* LM_ERR("request for a subscription" " with update type and no record found\n"); ret= -1; goto done; commented this because of the strange type parameter in usrloc callback functions */ 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"); ret= -1; goto done; } hentity->hash_index = hash_index; hentity->flag= flag; result= tmb.t_request (&met, /* Type of the message */ pres.pres_uri, /* Request-URI*/ &pres.to_uri, /* To */ pres.watcher_uri, /* From */ str_hdr, /* Optional headers including CRLF */ 0, /* Message body */ subs->outbound_proxy, /* Outbound_proxy */ subs_cback_func, /* Callback function */ (void*)hentity, /* Callback parameter */ 0 ); if(result< 0) { LM_ERR("while sending request with t_request\n"); shm_free(hentity); goto done; } } else { /* if(presentity->desired_expires== 0) { if(subs->expires< 0) { LM_DBG("Found previous request for unlimited subscribe-" " do not send subscribe\n"); if (subs->event & PWINFO_EVENT) { presentity->watcher_count++; } lock_release(&HashT->p_records[hash_index].lock); goto done; } if(subs->event & PWINFO_EVENT) { if(subs->expires== 0) { presentity->watcher_count--; if( presentity->watcher_count> 0) { lock_release(&HashT->p_records[hash_index].lock); goto done; } } else { presentity->watcher_count++; if(presentity->watcher_count> 1) { lock_release(&HashT->p_records[hash_index].lock); goto done; } } } } */ dlg_t* td= NULL; if (subs->internal_update_flag) { LM_DBG("attempting to re-SUBSCRIBE on internal dialog update - skipping\n"); lock_release(&HashT->p_records[hash_index].lock); goto done; } if (presentity->to_tag.len == 0) { LM_WARN("attempting to re-SUBSCRIBE to temporary (non-established) dialog - skipping\n"); lock_release(&HashT->p_records[hash_index].lock); goto done; } td= pua_build_dlg_t(presentity); if(td== NULL) { LM_ERR("while building tm dlg_t structure"); ret= -1; lock_release(&HashT->p_records[hash_index].lock); goto done; } hentity= subs_cbparam_indlg(presentity, expires, REQ_OTHER); if(hentity== NULL) { LM_ERR("while building callback param\n"); lock_release(&HashT->p_records[hash_index].lock); ret= -1; pkg_free(td); goto done; } presentity->desired_expires = hentity->desired_expires; lock_release(&HashT->p_records[hash_index].lock); // hentity->flag= flag; LM_DBG("event parameter: %d\n", hentity->event); result= tmb.t_request_within (&met, str_hdr, 0, td, subs_cback_func, (void*)hentity, 0 ); if(result< 0) { shm_free(hentity); hentity= NULL; LM_ERR("while sending request with t_request\n"); goto done; } if(td->route_set) free_rr(&td->route_set); pkg_free(td); td= NULL; } done: pkg_free(str_hdr); return ret; }
int send_publish( publ_info_t* publ ) { ua_pres_t* presentity= NULL; ua_pres_t pres; unsigned int hash_code; pua_event_t* ev= NULL; publ_t **last; LM_DBG("pres_uri=%.*s\n", publ->pres_uri->len, publ->pres_uri->s ); /* get event from list */ ev= get_event(publ->event); if(ev== NULL) { LM_ERR("event not found in list\n"); return -1; } 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); LM_DBG("Try to get hash lock [%d]\n", hash_code); lock_get(&HashT->p_records[hash_code].lock); LM_DBG("Got hash lock %d\n", hash_code); if(publ->flag != INSERT_TYPE) presentity= search_htable(&pres, hash_code); if(publ->etag && presentity== NULL) { LM_DBG("Etag restriction and no record found\n"); lock_release(&HashT->p_records[hash_code].lock); return 418; } if(presentity) { /* handle extra headers */ if(presentity->extra_headers.s) shm_free(presentity->extra_headers.s); presentity->extra_headers.len= 0; if(publ->extra_headers && publ->extra_headers->s && publ->extra_headers->len) { presentity->extra_headers.s= (char*)shm_malloc(publ->extra_headers->len); if(presentity->extra_headers.s == NULL) { LM_ERR("while processing extra_headers\n"); lock_release(&HashT->p_records[hash_code].lock); return -1; } memcpy(presentity->extra_headers.s, publ->extra_headers->s, publ->extra_headers->len); presentity->extra_headers.len= publ->extra_headers->len; } if(presentity->db_flag == NO_UPDATEDB_FLAG) presentity->db_flag= UPDATEDB_FLAG; if (presentity->waiting_reply) { LM_DBG("Presentity is waiting for reply, queue this PUBLISH\n"); last = &presentity->pending_publ; while (*last) last = &((*last)->next); *last = build_pending_publ(publ); if(! *last) { LM_ERR("Failed to create pending publ record\n"); lock_release(&HashT->p_records[hash_code].lock); return -1; } lock_release(&HashT->p_records[hash_code].lock); return 0; } } return send_publish_int(presentity, publ, ev, hash_code); }