/** * @brief Get a subscription from the subscription list based on the IMPI * NB - does not return with a lock on the subscription but does increment ref count * @param impu string of impu to search for * @param s ims_subscription to be returned if found * @param leave_slot_locked if no subscription is found return with the slot locked (in case we want to add) * @return 0 on success */ int get_subscription(str* impi_s, ims_subscription** s, int leave_slot_locked) { int subscription_hash, sl; ims_subscription* ptr; subscription_hash = core_hash(impi_s, 0, 0); sl = subscription_hash & (subs_hash_size - 1); lock_subscription_slot(sl); ptr = ims_subscription_list->slot[sl].first; while (ptr) { if ((impi_s->len == ptr->private_identity.len) && (memcmp(impi_s->s, ptr->private_identity.s, impi_s->len) == 0)) { LM_DBG("found an existing subscription for IMPI [%.*s]\n", impi_s->len, impi_s->s); (*s) = ptr; lock_subscription(ptr); ref_subscription_unsafe(ptr); unlock_subscription(ptr); unlock_subscription_slot(sl); return 0; } ptr = ptr->next; } if (!leave_slot_locked) unlock_subscription_slot(sl); return 1; }
/* * get all IMPUs as string from a subscription related to an impurecord. apply filter for barring (assumed to be called with lock on impurec) * barring-1 get all barred * barring-0 get all unbarred * barring-(-1) get all records * NB. Remember to free the block of memory pointed to by impus (pkg_malloc) */ int get_impus_from_subscription_as_string(udomain_t* _d, impurecord_t* impu_rec, int barring, str** impus, int* num_impus) { int i, j, count; *num_impus = 0; *impus = 0; ims_public_identity* impi; int bytes_needed = 0; int len = 0; LM_DBG("getting IMPU subscription set\n"); if (!impu_rec) { LM_ERR("no impu record provided\n"); return 1; } if (!impu_rec->s) { LM_DBG("no subscription associated with impu\n"); return 0; } lock_subscription(impu_rec->s); for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) { for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) { impi = &(impu_rec->s->service_profiles[i].public_identities[j]); if (barring < 0) { //get all records bytes_needed += impi->public_identity.len; (*num_impus)++; } else { if (impi->barring == barring) { //add the record to the list bytes_needed += impi->public_identity.len; (*num_impus)++; } } } } LM_DBG("num of records returned is %d and we need %d bytes\n", *num_impus, bytes_needed); len = (sizeof (str)*(*num_impus)) + bytes_needed; *impus = (str*) pkg_malloc(len); if (*impus == 0) { LM_ERR("no more pkg_mem\n"); return 0; } char* ptr = (char*) (*impus + *num_impus); //now populate the data count = 0; for (i = 0; i < impu_rec->s->service_profiles_cnt; i++) { for (j = 0; j < impu_rec->s->service_profiles[i].public_identities_cnt; j++) { impi = &(impu_rec->s->service_profiles[i].public_identities[j]); if (barring < 0) { //get all records (*impus)[count].s = ptr; memcpy(ptr, impi->public_identity.s, impi->public_identity.len); (*impus)[count].len = impi->public_identity.len; ptr += impi->public_identity.len; count++; } else { if (impi->barring == barring) { //add the record to the list (*impus)[count].s = ptr; memcpy(ptr, impi->public_identity.s, impi->public_identity.len); (*impus)[count].len = impi->public_identity.len; ptr += impi->public_identity.len; count++; } } } } if (ptr != ((char*) *impus + len)) { LM_CRIT("buffer overflow\n"); return 1; } unlock_subscription(impu_rec->s); return 0; }
static void ul_rpc_show_impu(rpc_t* rpc, void* ctx) { int i, j; str impu; int res; udomain_t* domain; struct impurecord* impu_rec; ucontact_t* contact; void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi; char numstr[21 + 16]; //enough for all numbers up to 64bits + longest length of field name (16) if (rpc->scan(ctx, "S", &impu) < 1) { rpc->fault(ctx, 400, "required IMPU argument"); return; } LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s); res = get_udomain("location", &domain); if (res != 0) { LM_ERR("Failed to get domain\n"); return; } lock_udomain(domain, &impu); res = get_impurecord(domain, &impu, &impu_rec); if (res != 0) { unlock_udomain(domain, &impu); return; } //now print the data for this IMPU record if (rpc->add(ctx, "{", &ah) < 0) { rpc->fault(ctx, 500, "Internal error creating IMPU struct"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "SsdSSSS", "impu", &impu, "state", get_impu_regstate_as_string(impu_rec->reg_state), "barring", impu_rec->barring, "ccf1", &impu_rec->ccf1, "ccf2", &impu_rec->ccf2, "ecf1", &impu_rec->ecf1, "ecf2", &impu_rec->ecf2 ) < 0) { rpc->fault(ctx, 500, "Internal error adding impu data"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); unlock_udomain(domain, &impu); return; } ims_subscription* subscription = impu_rec->s; lock_subscription(subscription); //add subscription data if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); unlock_subscription(subscription); unlock_udomain(domain, &impu); return; } //add subscription detail information for (i = 0; i < subscription->service_profiles_cnt; i++) { sprintf(numstr, "%d", i + 1); if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); unlock_subscription(subscription); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); unlock_subscription(subscription); unlock_udomain(domain, &impu); return; } for (j = 0; j < subscription->service_profiles[i].public_identities_cnt; j++) { sprintf(numstr, "%d", j + 1); if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); unlock_subscription(subscription); unlock_udomain(domain, &impu); return; } } } unlock_subscription(subscription); //add contact data if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } i = 0; if (impu_rec->num_contacts > 0 && impu_rec->newcontacts[0]) { while (i < MAX_CONTACTS_PER_IMPU && (contact = impu_rec->newcontacts[i++])) { //contact is not null terminated so we need to create a null terminated version if (!contact_buf.s || (contact_buf.len <= contact->c.len)) { if (contact_buf.s && contact_buf.len <= contact->c.len) { pkg_free(contact_buf.s); } contact_buflen = contact->c.len + 1; contact_buf.s = (char*) pkg_malloc(contact_buflen); if (!contact_buf.s) { LM_ERR("no more pkg memory"); rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } } memcpy(contact_buf.s, contact->c.s, contact->c.len); contact_buf.s[contact->c.len] = '\0'; contact_buf.len = contact->c.len; LM_DBG("contact is %s\n", contact_buf.s); if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(cdh, "dS", "expires", contact->expires - time(NULL), "client", &contact->user_agent) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } contact = contact->next; } } unlock_udomain(domain, &impu); }