/** * Drops and deallocates a r_public. * \note Must be called with a lock on the domain to avoid races * \note When calling be sure that get_r_public(d,aor) returns p, * to avoid a bogus removal * @param c - the r_contact that this r_public is attached currently to * @param p - the r_public to remove */ void del_r_public(r_contact *c,r_public *p) { if (c->head == p) c->head = p->next; else p->prev->next = p->next; if (c->tail == p) c->tail = p->prev; else p->next->prev = p->prev; free_r_public(p); }
/** * Drops and deallocates a r_public. * \note Don't forget to release the lock on the !!OLD!! hash value (yes, the memory is * deallocated, so you can not do r_unlock(p->hash) because p does not exist anymore!) * \note When calling be sure that get_r_public(aor) returns p, to avoid a bogus removal * @param p - the r_public to remove */ void del_r_public(r_public *p) { S_drop_all_dialogs(p->aor); if (registrar[p->hash].head == p) registrar[p->hash].head = p->next; else p->prev->next = p->next; if (registrar[p->hash].tail == p) registrar[p->hash].tail = p->prev; else p->next->prev = p->prev; free_r_public(p); }
/** * Destroy the registrar */ void r_storage_destroy() { int i; r_public *p,*np; for(i=0;i<r_hash_size;i++){ r_lock(i); p = registrar[i].head; while(p){ np = p->next; free_r_public(p); p = np; } r_unlock(i); lock_dealloc(registrar[i].lock); } shm_free(registrar); }
/** * Frees memory taken by a r_contact structure * @param c - the r_contact to be deallocated */ void free_r_contact(r_contact *c) { r_public *p,*n; int i; if (!c) return; if (c->pinhole) shm_free(c->pinhole); if (c->host.s) shm_free(c->host.s); if (c->uri.s) shm_free(c->uri.s); if (c->service_route){ i=0; for(i=0;i<c->service_route_cnt;i++) if (c->service_route[i].s) shm_free(c->service_route[i].s); shm_free(c->service_route); } p = c->head; while(p){ n = p->next; free_r_public(p); p = n; } if (c->security_temp) free_r_security(c->security_temp); if (c->security) free_r_security(c->security); if (c->pcc_session_id.len) shm_free(c->pcc_session_id.s); if(c->si_pc) { if(c->si_pc->name.s) shm_free(c->si_pc->name.s); if(c->si_pc->address_str.s) shm_free(c->si_pc->address_str.s); if(c->si_pc->port_no_str.s) shm_free(c->si_pc->port_no_str.s); shm_free(c->si_pc); } if(c->si_ps) { if(c->si_ps->name.s) shm_free(c->si_ps->name.s); if(c->si_ps->address_str.s) shm_free(c->si_ps->address_str.s); if(c->si_ps->port_no_str.s) shm_free(c->si_ps->port_no_str.s); shm_free(c->si_ps); } shm_free(c); }
/** * Decode a r_contact from a binary data structure * @param x - binary data to decode from * @returns the r_contact* where the data has been decoded */ r_contact* bin_decode_r_contact(bin_data *x) { r_contact *c=0; r_public *p=0,*pn=0; int len,i; char k; unsigned short us; str st; len = sizeof(r_contact); c = (r_contact*) shm_malloc(len); if (!c) { LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error allocating %d bytes.\n",len); goto error; } memset(c,0,len); if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->host),&st)) goto error; if (!bin_decode_ushort(x,&c->port)) goto error; if (!bin_decode_char(x,&c->transport)) goto error; c->hash = get_contact_hash(c->host,c->port,c->transport,r_hash_size); if (!bin_decode_r_security(x,&(c->security_temp))) goto error; if (!bin_decode_r_security(x,&(c->security))) goto error; if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->uri),&st)) goto error; if (!bin_decode_char(x,&k)) goto error; c->reg_state = k; if (!bin_decode_time_t(x,&c->expires)) goto error; if (!bin_decode_ushort(x, &c->service_route_cnt)) goto error; len = sizeof(str)*c->service_route_cnt; c->service_route = (str*) shm_malloc(len); if (!c->service_route) { LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error allocating %d bytes.\n",len); goto error; } memset(c->service_route,0,len); for(i=0;i<c->service_route_cnt;i++) if (!bin_decode_str(x,&st)||!str_shm_dup(c->service_route+i,&st)) goto error; if (!bin_decode_pinhole(x,&(c->pinhole ))) goto error; if (!bin_decode_char(x,&k)) goto error; c->sos_flag = k; if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->pcc_session_id),&st)) goto error; if (!bin_decode_ushort(x,&us)) goto error; for(i=0;i<us;i++){ p = bin_decode_r_public(x); if (!p) goto error; p->prev = c->tail; p->next = 0; if (c->tail) c->tail->next = p; c->tail = p; if (!c->head) c->head = p; } return c; error: LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error while decoding (at %d (%04x)).\n",x->max,x->max); if (c) { if (c->host.s) shm_free(c->host.s); if (c->security_temp) free_r_security(c->security_temp); if (c->security) free_r_security(c->security); if (c->uri.s) shm_free(c->uri.s); if (c->pinhole) shm_free(c->pinhole); while(c->head){ p = c->head; pn = p->next; free_r_public(p); c->head = pn; } shm_free(c); } return 0; }
/** * Updates the r_public with the new reg_state and ims_subscription values. * If not found, it will be inserted. * \note Aquires the lock on the hash_slot on success, so release it when you are done. * @param aor - the address of record * @param reg_state - new registration state, NULL if no update necessary * @param s - the new subscription attached, NULL if no update necessary * @returns the update r_public or NULL on error */ r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s, str *ccf1, str *ccf2, str *ecf1, str *ecf2) { r_public *p=0; //LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s); if ((*s)->wpsi) { p = get_r_public_wpsi(aor); } else { p = get_r_public(aor); } if (!p){ //LOG(L_DBG,"updating a new r_public profile\n"); if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){ p = add_r_public(aor,*reg_state,*s); if (!p) return p; if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } //LOG(L_DBG,"update_r_public(): it was actually adding\n"); return p; } else return 0; }else{ //LOG(L_DBG,"updating a not so new r_public profile\n"); if (reg_state) p->reg_state = *reg_state; if (*s) { if (p->s){ lock_get(p->s->lock); if (p->s->ref_count==1){ free_user_data(p->s); }else{ p->s->ref_count--; lock_release(p->s->lock); } } p->s = *s; lock_get(p->s->lock); p->s->ref_count++; lock_release(p->s->lock); if ((*s)->wpsi) { p->s=NULL; if (p->prev) p->prev->next=p->next; else registrar[r_hash_size].head=p->next; if (p->next) p->next->prev=p->prev; else registrar[r_hash_size].tail=p->prev; free_r_public(p); r_unlock(r_hash_size); p=add_r_public(aor,0,*s); } } if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } //LOG(L_DBG,"update_r_public(): return normaly\n"); return p; } out_of_memory: return p; }