/** * Frees memory taken by a r_public aor structure * @param p - the r_public to be deallocated */ void free_r_public(r_public *p) { r_contact *c,*n; r_subscriber *s,*m; if (!p) return; if (p->aor.s) shm_free(p->aor.s); if (p->early_ims_ip.s) shm_free(p->early_ims_ip.s); if (p->s) { lock_get(p->s->lock); p->s->ref_count--; if (p->s->ref_count<=0) { free_user_data(p->s); }else lock_release(p->s->lock); } c = p->head; while(c){ n = c->next; free_r_contact(c); c = n; } s = p->shead; while(s){ m = s->next; free_r_subscriber(s); s = m; } shm_free(p); }
/** * Drops and deallocates a r_contact. * \note When calling be sure that get_r_contact(p,uri) returns c, to avoid a bogus removal * @param p - the r_public record to look into * @param c - the r_contact to remove */ void del_r_contact(r_public *p,r_contact *c) { if (p->head == c) p->head = c->next; else c->prev->next = c->next; if (p->tail == c) p->tail = c->prev; else c->next->prev = c->prev; free_r_contact(c); }
/** * Destroy the registrar */ void r_storage_destroy() { int i; r_contact *c,*nc; for(i=0;i<r_hash_size;i++){ r_lock(i); c = registrar[i].head; while(c){ nc = c->next; free_r_contact(c); c = nc; } r_unlock(i); lock_dealloc(registrar[i].lock); } shm_free(registrar); }
/** * Drops and deallocates a r_contact. * \note Don't forget to release the lock on the !!OLD!! hash value * @param c - the r_contact to remove */ void del_r_contact(r_contact *c) { AAASession *auth; P_drop_all_dialogs(c->host,c->port,c->transport); if (c->pcc_session_id.len) { auth = cdpb.AAAGetAuthSession(c->pcc_session_id); if (auth) cdpb.AAATerminateAuthSession(auth); shm_free(c->pcc_session_id.s); c->pcc_session_id.len=0; c->pcc_session_id.s=0; } if (registrar[c->hash].head == c) registrar[c->hash].head = c->next; else c->prev->next = c->next; if (registrar[c->hash].tail == c) registrar[c->hash].tail = c->prev; else c->next->prev = c->prev; free_r_contact(c); }
/** * Creates a registrar contact * This does not insert it in the registrar * @param host - the host part of the contact, in string * @param port - the port number of the contact * @param transport - the transport of the contact * @param uri - URI of the contact * @param reg_state - Registration state * @param expires - expires in * @param service_route - array of service routes * @param service_route_cnt - the size of the array above * @returns the new r_contact* or NULL on error */ r_contact* new_r_contact(str host,int port,int transport,str uri,enum Reg_States reg_state,int expires, str *service_route,int service_route_cnt, r_reg_type sos_flag) { r_contact *c; int i; c = shm_malloc(sizeof(r_contact)); if (!c) { LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n", sizeof(r_contact)); goto error; } memset(c,0,sizeof(r_contact)); STR_SHM_DUP(c->host,host,"new_r_contact"); c->port = port; c->transport = transport; c->hash = get_contact_hash(host,port,transport,r_hash_size); STR_SHM_DUP(c->uri,uri,"new_r_contact"); c->reg_state = reg_state; c->expires = expires; c->sos_flag = sos_flag; if (service_route_cnt && service_route){ c->service_route = shm_malloc(service_route_cnt*sizeof(str)); if (!c->service_route){ LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n", service_route_cnt*sizeof(str)); goto error; } for(i=0;i<service_route_cnt;i++) STR_SHM_DUP(c->service_route[i],service_route[i],"new_r_contact"); c->service_route_cnt = service_route_cnt; } return c; error: out_of_memory: if (c){ free_r_contact(c); } return 0; }
/** * Decode a r_public from a binary data structure * @param x - binary data to decode from * @returns the r_public* where the data has been decoded */ r_public* bin_decode_r_public(bin_data *x) { r_public *p=0; r_contact *c=0,*cn=0; r_subscriber *s,*sn=0; int len,i; unsigned short k; char ch; str st; len = sizeof(r_public); p = (r_public*) shm_malloc(len); if (!p) { LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_public: Error allocating %d bytes.\n",len); goto error; } memset(p,0,len); if (!bin_decode_str(x,&st)||!str_shm_dup(&(p->aor),&st)) goto error; if (!bin_decode_str(x,&st)||!str_shm_dup(&(p->early_ims_ip),&st)) goto error; p->hash = get_aor_hash(p->aor,r_hash_size); if (!bin_decode_char(x,&ch)) goto error; p->reg_state = ch; p->s = bin_decode_ims_subscription(x); if (!p->s) goto error; if (!bin_decode_ushort(x,&k)) goto error; for(i=0;i<k;i++){ c = bin_decode_r_contact(x); if (!c) goto error; c->prev = p->tail; c->next = 0; if (!p->head) p->head = c; if (p->tail) p->tail->next = c; p->tail = c; } if (!bin_decode_ushort(x,&k)) goto error; for(i=0;i<k;i++){ s = bin_decode_r_subscriber(x); if (!s) goto error; s->prev = p->stail; s->next = 0; if (!p->shead) p->shead = s; if (p->stail) p->stail->next = s; p->stail = s; } return p; error: LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_public: Error while decoding (at %d (%04x)).\n",x->max,x->max); if (p) { if (p->aor.s) shm_free(p->aor.s); while(p->head){ c = p->head; cn = c->next; free_r_contact(c); p->head = cn; } while(p->shead){ s = p->shead; sn = s->next; free_r_subscriber(s); p->shead = sn; } shm_free(p); } return 0; }