static command_status_t fetch_domains(domain_set_t *ds, bool force, error_t **error) { if (!ds->uptodate || force) { request_t *req; bool request_success; json_document_t *doc; req = request_new(REQUEST_FLAG_SIGN, HTTP_GET, NULL, error, API_BASE_URL "/domain"); request_success = request_execute(req, RESPONSE_JSON, (void **) &doc, error); request_destroy(req); if (request_success) { Iterator it; json_value_t root; root = json_document_get_root(doc); hashtable_clear(ds->domains); json_array_to_iterator(&it, root); for (iterator_first(&it); iterator_is_valid(&it); iterator_next(&it)) { json_value_t v; v = (json_value_t) iterator_current(&it, NULL); hashtable_put(ds->domains, 0, json_get_string(v), domain_new(), NULL); // ds->domains has strdup as key_duper, don't need to strdup it ourself } iterator_close(&it); ds->uptodate = TRUE; json_document_destroy(doc); } else { return COMMAND_FAILURE; } } return COMMAND_SUCCESS; }
static bool complete_records(void *parsed_arguments, const char *current_argument, size_t current_argument_len, DPtrArray *possibilities, void *UNUSED(data)) { domain_t *d; bool request_success; domain_record_argument_t *args; args = (domain_record_argument_t *) parsed_arguments; assert(NULL != args->domain); if ((request_success = (COMMAND_SUCCESS == get_domain_records(args->domain, &d, FALSE, NULL)))) { Iterator it; hashtable_to_iterator(&it, d->records); for (iterator_first(&it); iterator_is_valid(&it); iterator_next(&it)) { record_t *r; r = iterator_current(&it, NULL); if (0 == strncmp(r->name, current_argument, current_argument_len)) { dptrarray_push(possibilities, (void *) r->name); } } iterator_close(&it); } return request_success; }
/* get name functions */ static inline str* __get_avp_name(int id, map_t m) { map_iterator_t it; int **idp; if (map_first(m, &it) < 0) { LM_ERR("map doesn't exist\n"); return NULL; } for (;;) { if (!iterator_is_valid(&it)) return NULL; idp = (int**)iterator_val(&it); if (!idp) { LM_ERR("[BUG] while getting avp name\n"); return NULL; } if (p2int(*idp) == id) return iterator_key(&it); if (iterator_next(&it) < 0) return NULL; } }
static command_status_t domain_check(COMMAND_ARGS) { bool success; domain_set_t *ds; USED(arg); USED(mainopts); FETCH_ACCOUNT_DOMAINS(ds); // populate if ((success = (COMMAND_SUCCESS == fetch_domains(ds, FALSE, error)))) { time_t now; Iterator it; now = time(NULL); hashtable_to_iterator(&it, ds->domains); for (iterator_first(&it); success && iterator_is_valid(&it); iterator_next(&it)) { request_t *req; json_document_t *doc; const char *domain_name; iterator_current(&it, (void **) &domain_name); // request req = request_new(REQUEST_FLAG_SIGN, HTTP_GET, NULL, error, API_BASE_URL "/domain/%s/serviceInfos", domain_name); success = request_execute(req, RESPONSE_JSON, (void **) &doc, error); request_destroy(req); // response if (success) { time_t domain_expiration; json_value_t root, expiration; root = json_document_get_root(doc); if (json_object_get_property(root, "expiration", &expiration)) { if (date_parse_to_timestamp(json_get_string(expiration), NULL, &domain_expiration)) { int diff_days; diff_days = date_diff_in_days(domain_expiration, now); if (diff_days > 0 && diff_days < 3000) { printf("%s expires in %d days\n", domain_name, diff_days); } } } json_document_destroy(doc); } } iterator_close(&it); } return success ? COMMAND_SUCCESS : COMMAND_FAILURE; }
static void clean_profiles(unsigned int ticks, void *param) { map_iterator_t it, del; unsigned int count; struct dlg_profile_table *profile; prof_value_info_t *rp; void **dst; int i; for (profile = profiles; profile; profile = profile->next) { if (!profile->has_value || profile->repl_type != REPL_PROTOBIN) continue; for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); if (map_first(profile->entries[i], &it) < 0) { LM_ERR("map does not exist\n"); goto next_entry; } while (iterator_is_valid(&it)) { dst = iterator_val(&it); if (!dst || !*dst) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_val; } count = prof_val_get_count(dst); if (!count) { del = it; if (iterator_next(&it) < 0) LM_DBG("cannot find next iterator\n"); rp = (prof_value_info_t *) iterator_delete(&del); if (rp) { free_profile_val_t(rp); /*if (rp->noval) shm_free(rp->noval); shm_free(rp);*/ } continue; } next_val: if (iterator_next(&it) < 0) break; } next_entry: lock_set_release(profile->locks, i); } } }
// TODO: optionnal arguments fieldType and subDomain in query string static command_status_t record_list(COMMAND_ARGS) { domain_t *d; Iterator it; command_status_t ret; domain_record_argument_t *args; USED(mainopts); args = (domain_record_argument_t *) arg; assert(NULL != args->domain); if (COMMAND_SUCCESS == (ret = get_domain_records(args->domain, &d, args->nocache, error))) { // display table_t *t; t = table_new( #ifdef PRINT_OVH_ID 5, _("id"), TABLE_TYPE_INT, #else 4, #endif /* PRINT_OVH_ID */ _("subdomain"), TABLE_TYPE_STRING, _("type"), TABLE_TYPE_ENUM, domain_record_types, _("TTL"), TABLE_TYPE_INT, _("target"), TABLE_TYPE_STRING ); hashtable_to_iterator(&it, d->records); for (iterator_first(&it); iterator_is_valid(&it); iterator_next(&it)) { record_t *r; r = iterator_current(&it, NULL); if (0 == args->type || r->type == args->type) { table_store(t, #ifdef PRINT_OVH_ID r->id, #endif /* PRINT_OVH_ID */ r->name, r->type, r->ttl, r->target ); } } iterator_close(&it); table_display(t, TABLE_FLAG_NONE); table_destroy(t); } return ret; }
static bool get_domain_records(const char *domain, domain_t **d, bool force, error_t **error) { domain_set_t *ds; bool request_success; *d = NULL; FETCH_ACCOUNT_DOMAINS(ds); request_success = TRUE; // TODO: hashtable_clear((*d)->records) if force if (!hashtable_get(ds->domains, domain, d) || !(*d)->uptodate || force) { request_t *req; json_document_t *doc; if (NULL == *d) { *d = domain_new(); hashtable_put(ds->domains, 0, domain, *d, NULL); } req = request_new(REQUEST_FLAG_SIGN, HTTP_GET, NULL, error, API_BASE_URL "/domain/zone/%s/record", domain); request_success = request_execute(req, RESPONSE_JSON, (void **) &doc, error); request_destroy(req); // result if (request_success) { Iterator it; json_value_t root; root = json_document_get_root(doc); json_array_to_iterator(&it, root); for (iterator_first(&it); request_success && iterator_is_valid(&it); iterator_next(&it)) { json_value_t v; json_document_t *doc; v = (json_value_t) iterator_current(&it, NULL); req = request_new(REQUEST_FLAG_SIGN, HTTP_GET, NULL, error, API_BASE_URL "/domain/zone/%s/record/%u", domain, json_get_integer(v)); request_success = request_execute(req, RESPONSE_JSON, (void **) &doc, error); request_destroy(req); // result parse_record((*d)->records, doc); } iterator_close(&it); json_document_destroy(doc); (*d)->uptodate = TRUE; } } return request_success ? COMMAND_SUCCESS : COMMAND_FAILURE; }
static size_t find_record(HashTable *records, const char *name, record_t **match) { Iterator it; size_t matches; matches = 0; hashtable_to_iterator(&it, records); for (iterator_first(&it); iterator_is_valid(&it); iterator_next(&it)) { record_t *r; r = iterator_current(&it, NULL); if (r->name[0] == name[0] && 0 == strcmp(r->name, name)) { // TODO: strcmp_l? type? ++matches; *match = r; } } iterator_close(&it); return matches; }
static void broadcast_profiles(utime_t ticks, void *param) { #define REPL_PROF_TRYSEND() \ do { \ nr++; \ if (ret > repl_prof_buffer_th) { \ /* send the buffer */ \ if (nr) \ dlg_replicate_profiles(&packet); \ bin_reset_back_pointer(&packet); \ nr = 0; \ } \ } while (0) struct dlg_profile_table *profile; map_iterator_t it; unsigned int count; int i; int nr = 0; int ret; void **dst; str *value; bin_packet_t packet; if (bin_init(&packet, &prof_repl_cap, REPLICATION_DLG_PROFILE, BIN_VERSION, 0) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } for (profile = profiles; profile; profile = profile->next) { if (!(profile->repl_type&REPL_PROTOBIN)) continue; count = 0; if (!profile->has_value) { count = noval_get_local_count(profile); if ((ret = repl_prof_add(&packet, &profile->name, 0, NULL, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); } else { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); if (map_first(profile->entries[i], &it) < 0) { LM_ERR("map does not exist\n"); goto next_entry; } while (iterator_is_valid(&it)) { dst = iterator_val(&it); if (!dst || !*dst) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_val; } value = iterator_key(&it); if (!value) { LM_ERR("cannot retrieve profile's key\n"); goto next_val; } count = prof_val_get_local_count(dst); if ((ret = repl_prof_add(&packet, &profile->name, 1, value, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); next_val: if (iterator_next(&it) < 0) break; } next_entry: lock_set_release(profile->locks, i); } } } goto done; error: LM_ERR("cannot add any more profiles in buffer\n"); bin_free_packet(&packet); done: /* check if there is anything else left to replicate */ if (nr) dlg_replicate_profiles(&packet); bin_free_packet(&packet); #undef REPL_PROF_TRYSEND }
void rl_timer_repl(utime_t ticks, void *param) { static str module_name = str_init("ratelimit"); unsigned int i = 0; map_iterator_t it; rl_pipe_t **pipe; str *key; int nr = 0; int ret; if (bin_init(&module_name, RL_PIPE_COUNTER) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } /* iterate through each map */ for (i = 0; i < rl_htable.size; i++) { RL_GET_LOCK(i); /* iterate through all the entries */ if (map_first(rl_htable.maps[i], &it) < 0) { LM_ERR("map doesn't exist\n"); goto next_map; } for (; iterator_is_valid(&it);) { pipe = (rl_pipe_t **)iterator_val(&it); if (!pipe || !*pipe) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_pipe; } /* ignore cachedb replicated stuff */ if (RL_USE_CDB(*pipe)) goto next_pipe; key = iterator_key(&it); if (!key) { LM_ERR("cannot retrieve pipe key\n"); goto next_pipe; } if (bin_push_str(key) < 0) goto error; if (bin_push_int((*pipe)->algo) < 0) goto error; if (bin_push_int((*pipe)->limit) < 0) goto error; if ((ret = bin_push_int((*pipe)->counter)) < 0) goto error; nr++; if (ret > rl_buffer_th) { /* send the buffer */ if (nr) rl_replicate(); if (bin_init(&module_name, RL_PIPE_COUNTER) < 0) { LM_ERR("cannot initiate bin buffer\n"); RL_RELEASE_LOCK(i); return; } nr = 0; } next_pipe: if (iterator_next(&it) < 0) break; } next_map: RL_RELEASE_LOCK(i); } /* if there is anything else to send, do it now */ if (nr) rl_replicate(); return; error: LM_ERR("cannot add pipe info in buffer\n"); RL_RELEASE_LOCK(i); if (nr) rl_replicate(); }
/* timer housekeeping, invoked each timer interval to reset counters */ void rl_timer(unsigned int ticks, void *param) { unsigned int i = 0; map_iterator_t it, del; rl_pipe_t **pipe; str *key; void *value; unsigned long now = time(0); /* get CPU load */ if (get_cpuload() < 0) { LM_ERR("cannot update CPU load\n"); i = 1; } lock_get(rl_lock); /* if CPU was successfully loaded */ if (!i) do_update_load(); /* update network if needed */ if (*rl_network_count) *rl_network_load = get_total_bytes_waiting(PROTO_NONE); lock_release(rl_lock); /* iterate through each map */ for (i = 0; i < rl_htable.size; i++) { RL_GET_LOCK(i); /* iterate through all the entries */ if (map_first(rl_htable.maps[i], &it) < 0) { LM_ERR("map doesn't exist\n"); goto next_map; } for (; iterator_is_valid(&it);) { pipe = (rl_pipe_t **)iterator_val(&it); if (!pipe || !*pipe) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_pipe; } key = iterator_key(&it); if (!key) { LM_ERR("cannot retrieve pipe key\n"); goto next_pipe; } /* check to see if it is expired */ if ((*pipe)->last_used + rl_expire_time < now) { /* this pipe is engaged in a transaction */ del = it; if (iterator_next(&it) < 0) LM_DBG("cannot find next iterator\n"); if ((*pipe)->algo == PIPE_ALGO_NETWORK) { lock_get(rl_lock); (*rl_network_count)--; lock_release(rl_lock); } LM_DBG("Deleting ratelimit pipe key \"%.*s\"\n", key->len, key->s); value = iterator_delete(&del); /* free resources */ if (value) shm_free(value); continue; } else { /* leave the lock if a cachedb query should be done*/ if (RL_USE_CDB(*pipe)) { if (rl_get_counter(key, *pipe) < 0) { LM_ERR("cannot get pipe counter\n"); goto next_pipe; } } switch ((*pipe)->algo) { case PIPE_ALGO_NETWORK: /* handle network algo */ (*pipe)->load = (*rl_network_load > (*pipe)->limit) ? -1 : 1; break; case PIPE_ALGO_RED: if ((*pipe)->limit && rl_timer_interval) (*pipe)->load = (*pipe)->counter / ((*pipe)->limit * rl_timer_interval); break; default: break; } (*pipe)->last_counter = rl_get_all_counters(*pipe); if (RL_USE_CDB(*pipe)) { if (rl_change_counter(key, *pipe, 0) < 0) { LM_ERR("cannot reset counter\n"); } } else { (*pipe)->counter = 0; } } next_pipe: if (iterator_next(&it) < 0) break; } next_map: RL_RELEASE_LOCK(i); } }
static void repl_prof_utimer_f(utime_t ticks, void *param) { #define REPL_PROF_TRYSEND() \ do { \ nr++; \ if (ret > repl_prof_buffer_th) { \ /* send the buffer */ \ if (nr) { \ dlg_replicate_profiles(); \ LM_DBG("sent %d records\n", nr); \ } \ if (bin_init(&module_name, REPLICATION_DLG_PROFILE, BIN_VERSION) < 0) { \ LM_ERR("cannot initiate bin buffer\n"); \ return; \ } \ nr = 0; \ } \ } while (0) struct dlg_profile_table *profile; static str module_name = str_init("dialog"); map_iterator_t it; unsigned int count; int i; int nr = 0; int ret; void **dst; str *value; if (bin_init(&module_name, REPLICATION_DLG_PROFILE, BIN_VERSION) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } for (profile = profiles; profile; profile = profile->next) { count = 0; if (!profile->has_value) { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); count += profile->counts[i]; lock_set_release(profile->locks, i); } if ((ret = repl_prof_add(&profile->name, 0, NULL, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); } else { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); if (map_first(profile->entries[i], &it) < 0) { LM_ERR("map does not exist\n"); goto next_entry; } while (iterator_is_valid(&it)) { dst = iterator_val(&it); if (!dst || !*dst) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_val; } value = iterator_key(&it); if (!value) { LM_ERR("cannot retrieve profile's key\n"); goto next_val; } count = repl_prof_get(dst); if ((ret = repl_prof_add(&profile->name, 1, value, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); next_val: if (iterator_next(&it) < 0) break; } next_entry: lock_set_release(profile->locks, i); } } } goto done; error: LM_ERR("cannot add any more profiles in buffer\n"); done: /* check if there is anything else left to replicate */ LM_DBG("sent %d records\n", nr); if (nr) dlg_replicate_profiles(); #undef REPL_PROF_TRYSEND }
void rl_timer_repl(utime_t ticks, void *param) { unsigned int i = 0; map_iterator_t it; rl_pipe_t **pipe; str *key; int nr = 0; int ret; bin_packet_t packet; if (bin_init(&packet, &pipe_repl_cap, RL_PIPE_COUNTER, BIN_VERSION, 0) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } /* iterate through each map */ for (i = 0; i < rl_htable.size; i++) { RL_GET_LOCK(i); /* iterate through all the entries */ if (map_first(rl_htable.maps[i], &it) < 0) { LM_ERR("map doesn't exist\n"); goto next_map; } for (; iterator_is_valid(&it);) { pipe = (rl_pipe_t **) iterator_val(&it); if (!pipe || !*pipe) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_pipe; } /* ignore cachedb replicated stuff */ if (RL_USE_CDB(*pipe)) goto next_pipe; key = iterator_key(&it); if (!key) { LM_ERR("cannot retrieve pipe key\n"); goto next_pipe; } if (bin_push_str(&packet, key) < 0) goto error; if (bin_push_int(&packet, (*pipe)->algo) < 0) goto error; if (bin_push_int(&packet, (*pipe)->limit) < 0) goto error; /* * for the SBT algorithm it is safe to replicate the current * counter, since it is always updating according to the window */ if ((ret = bin_push_int(&packet, ((*pipe)->algo == PIPE_ALGO_HISTORY ? (*pipe)->counter : (*pipe)->my_last_counter))) < 0) goto error; nr++; if (ret > rl_buffer_th) { /* send the buffer */ if (nr) rl_replicate(&packet); bin_reset_back_pointer(&packet); nr = 0; } next_pipe: if (iterator_next(&it) < 0) break; } next_map: RL_RELEASE_LOCK(i); } /* if there is anything else to send, do it now */ if (nr) rl_replicate(&packet); bin_free_packet(&packet); return; error: LM_ERR("cannot add pipe info in buffer\n"); RL_RELEASE_LOCK(i); if (nr) rl_replicate(&packet); bin_free_packet(&packet); }
static int receive_sync_request(int node_id) { bin_packet_t *sync_packet; dlist_t *dl; udomain_t *dom; map_iterator_t it; struct urecord *r; ucontact_t* c; str st; void **p; int i; for (dl = root; dl; dl = dl->next) { dom = dl->d; for(i = 0; i < dom->size; i++) { lock_ulslot(dom, i); for (map_first(dom->table[i].records, &it); iterator_is_valid(&it); iterator_next(&it)) { p = iterator_val(&it); if (p == NULL) goto error_unlock; r = (urecord_t *)*p; sync_packet = clusterer_api.sync_chunk_start(&contact_repl_cap, location_cluster, node_id); if (!sync_packet) goto error_unlock; /* urecord in this chunk */ bin_push_int(sync_packet, 0); bin_push_str(sync_packet, r->domain); bin_push_str(sync_packet, &r->aor); for (c = r->contacts; c; c = c->next) { sync_packet = clusterer_api.sync_chunk_start(&contact_repl_cap, location_cluster, node_id); if (!sync_packet) goto error_unlock; /* contact in this chunk */ bin_push_int(sync_packet, 1); bin_push_str(sync_packet, r->domain); bin_push_str(sync_packet, &r->aor); bin_push_str(sync_packet, &c->c); bin_push_str(sync_packet, &c->callid); bin_push_str(sync_packet, &c->user_agent); bin_push_str(sync_packet, &c->path); bin_push_str(sync_packet, &c->attr); bin_push_str(sync_packet, &c->received); bin_push_str(sync_packet, &c->instance); st.s = (char *)&c->expires; st.len = sizeof c->expires; bin_push_str(sync_packet, &st); st.s = (char *)&c->q; st.len = sizeof c->q; bin_push_str(sync_packet, &st); bin_push_str(sync_packet, c->sock?&c->sock->sock_str:NULL); bin_push_int(sync_packet, c->cseq); bin_push_int(sync_packet, c->flags); bin_push_int(sync_packet, c->cflags); bin_push_int(sync_packet, c->methods); st.s = (char *)&c->last_modified; st.len = sizeof c->last_modified; bin_push_str(sync_packet, &st); } } unlock_ulslot(dom, i); } } return 0; error_unlock: unlock_ulslot(dom, i); return -1; }
static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags, unsigned int part_idx, unsigned int part_max) { dlist_t *p; urecord_t *r; ucontact_t *c; void *cp; void **dest; map_iterator_t it; int shortage; int needed; int count; int i = 0; cp = buf; shortage = 0; /* Reserve space for terminating 0000 */ len -= sizeof(c->c.len); for (p = root; p != NULL; p = p->next) { for(i=0; i<p->d->size; i++) { if ( (i % part_max) != part_idx ) continue; lock_ulslot( p->d, i); count = map_size(p->d->table[i].records); if( count <= 0 ) { unlock_ulslot(p->d, i); continue; } for ( map_first( p->d->table[i].records, &it); iterator_is_valid(&it); iterator_next(&it) ) { dest = iterator_val(&it); if( dest == NULL ) { unlock_ulslot(p->d, i); return -1; } r =( urecord_t * ) *dest; for (c = r->contacts; c != NULL; c = c->next) { if (c->c.len <= 0) continue; /* * List only contacts that have all requested * flags set */ if ((c->cflags & flags) != flags) continue; if (c->received.s) { needed = (int)(sizeof(c->received.len) + c->received.len + sizeof(c->sock) + sizeof(c->cflags) + sizeof(c->path.len) + c->path.len); if (len >= needed) { memcpy(cp,&c->received.len,sizeof(c->received.len)); cp = (char*)cp + sizeof(c->received.len); memcpy(cp, c->received.s, c->received.len); cp = (char*)cp + c->received.len; memcpy(cp, &c->sock, sizeof(c->sock)); cp = (char*)cp + sizeof(c->sock); memcpy(cp, &c->cflags, sizeof(c->cflags)); cp = (char*)cp + sizeof(c->cflags); memcpy(cp, &c->path.len, sizeof(c->path.len)); cp = (char*)cp + sizeof(c->path.len); memcpy(cp, c->path.s, c->path.len); cp = (char*)cp + c->path.len; len -= needed; } else { shortage += needed; } } else { needed = (int)(sizeof(c->c.len) + c->c.len + sizeof(c->sock) + sizeof(c->cflags) + sizeof(c->path.len) + c->path.len); if (len >= needed) { memcpy(cp, &c->c.len, sizeof(c->c.len)); cp = (char*)cp + sizeof(c->c.len); memcpy(cp, c->c.s, c->c.len); cp = (char*)cp + c->c.len; memcpy(cp, &c->sock, sizeof(c->sock)); cp = (char*)cp + sizeof(c->sock); memcpy(cp, &c->cflags, sizeof(c->cflags)); cp = (char*)cp + sizeof(c->cflags); memcpy(cp, &c->path.len, sizeof(c->path.len)); cp = (char*)cp + sizeof(c->path.len); memcpy(cp, c->path.s, c->path.len); cp = (char*)cp + c->path.len; len -= needed; } else { shortage += needed; } } } } unlock_ulslot(p->d, i); } } /* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */ if (len >= 0) memset(cp, 0, sizeof(c->c.len)); /* Shouldn't happen */ if (shortage > 0 && len > shortage) { abort(); } shortage -= len; return shortage > 0 ? shortage : 0; }