示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
/* 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;

	}
}
示例#4
0
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;
}
示例#5
0
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);
		}
	}
}
示例#6
0
// 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;
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
0
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
}
示例#10
0
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();
}
示例#11
0
/* 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);
	}
}
示例#12
0
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
}
示例#13
0
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);
}
示例#14
0
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;
}
示例#15
0
文件: dlist.c 项目: iamroger/voip
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;
}