Пример #1
0
static struct mi_root* mi_cc_list_flows(struct mi_root *cmd, void *param)
{
	struct cc_flow *flow;
	struct mi_root *rpl_tree;
	struct mi_node *node;
	struct mi_node *rpl;
	struct mi_attr *attr;
	int len;
	char *p;

	rpl_tree = init_mi_tree( 200, MI_SSTR("OK") );
	if ( rpl_tree==NULL)
		return NULL;
	rpl = &rpl_tree->node;

	/* block access to data */
	lock_get( data->lock );

	for( flow=data->flows; flow ; flow=flow->next ) {

		node = add_mi_node_child( rpl, MI_DUP_VALUE, MI_SSTR("Flow"),
				flow->id.s, flow->id.len );
		if (node==NULL)
				goto error;

		p = int2str( (unsigned long)(flow->avg_call_duration), &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Avg Call Duration"), p, len);
		if (attr==NULL)
				goto error;

		p = int2str( (unsigned long)(flow->processed_calls), &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Processed Calls"), p, len);
		if (attr==NULL)
				goto error;

		p = int2str( (unsigned long)(flow->logged_agents), &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Logged Agents"), p, len);
		if (attr==NULL)
				goto error;

		p = int2str( (unsigned long)(flow->ongoing_calls), &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Ongoing Calls"), p, len);
		if (attr==NULL)
				goto error;

		p = int2str( (unsigned long)(flow->ref_cnt), &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Ref"), p, len);
		if (attr==NULL)
				goto error;

	}

	lock_release( data->lock );

	return rpl_tree;

error:
	lock_release( data->lock );
	return 0;
}
Пример #2
0
struct mi_root* mt_mi_summary(struct mi_root* cmd_tree, void* param)
{
	m_tree_t *pt;
	struct mi_root* rpl_tree = NULL;
	struct mi_node* node = NULL;
	struct mi_attr* attr= NULL;
	str val;

	if(!mt_defined_trees())
	{
		LM_ERR("empty tree list\n");
		return init_mi_tree( 500, "No trees", 8);
	}

	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
	if(rpl_tree == NULL)
		return 0;

	pt = mt_get_first_tree();

	while(pt!=NULL)
	{
		node = add_mi_node_child(&rpl_tree->node, 0, "MT", 2, 0, 0);
		if(node == NULL)
			goto error;
		attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
				pt->tname.s, pt->tname.len);
		if(attr == NULL)
			goto error;
		val.s = int2str(pt->type, &val.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "TTYPE", 5,
				val.s, val.len);
		if(attr == NULL)
			goto error;
		val.s = int2str(pt->memsize, &val.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "MEMSIZE", 7,
				val.s, val.len);
		if(attr == NULL)
			goto error;
		val.s = int2str(pt->nrnodes, &val.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "NRNODES", 7,
				val.s, val.len);
		if(attr == NULL)
			goto error;
		val.s = int2str(pt->nritems, &val.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "NRITEMS", 7,
				val.s, val.len);
		if(attr == NULL)
			goto error;

		pt = pt->next;
	}

	return rpl_tree;
error:
	free_mi_tree(rpl_tree);
	return 0;
}
Пример #3
0
int add_mi_session_nodes(struct mi_node* node, int index, sdp_session_cell_t* session)
{
	struct mi_node* node1;
	struct mi_attr* attr;
	sdp_stream_cell_t* stream;
	char* p;
	int i, len;

	switch (index) {
		case 0:
			node1 = add_mi_node_child( node, MI_IS_ARRAY|MI_DUP_VALUE,
				"session", 7, "caller", 6);
			if (node1==NULL)
				return 1;
			break;
		case 1:
			node1 = add_mi_node_child( node,  MI_IS_ARRAY|MI_DUP_VALUE,
				"session", 7, "callee", 6);
			if (node1==NULL)
				return 1;
			break;
		default:
			return 1;
	}

	attr = add_mi_attr(node1, MI_DUP_VALUE, "cnt_disp", 8, session->cnt_disp.s, session->cnt_disp.len);
	if(attr == NULL)
		return 1;

	attr = add_mi_attr(node1, MI_DUP_VALUE, "bw_type", 7, session->bw_type.s, session->bw_type.len);
	if(attr == NULL)
		return 1;

	attr = add_mi_attr(node1, MI_DUP_VALUE, "bw_width", 8, session->bw_width.s, session->bw_width.len);
	if(attr == NULL)
		return 1;

	p = int2str((unsigned long)(session->streams_num), &len);
	attr = add_mi_attr(node1, MI_DUP_VALUE, "streams", 7, p, len);
	if(attr == NULL)
		return 1;

	stream = session->streams;
	for(i=session->streams_num-1;i>=0;i--){
		if (!stream) {
			LM_ERR("got NULL stream\n");
			return 1;
		}
		if (0!=add_mi_stream_nodes(node1, i, stream)){
			return 1;
		}
		stream = stream->next;
	}

	return 0;
}
Пример #4
0
static int rl_map_print(void *param, str key, void *value)
{
	struct mi_attr* attr;
	char* p;
	int len;
	rl_pipe_t *pipe = (rl_pipe_t *)value;
	struct mi_node * rpl = (struct mi_node *)param;
	struct mi_node * node;
	str *alg;

	if (!pipe) {
		LM_ERR("invalid pipe value\n");
		return -1;
	}

	if (!rpl) {
		LM_ERR("no reply node\n");
		return -1;
	}

	if (!key.len || !key.s) {
		LM_ERR("no key found\n");
		return -1;
	}
	LM_DBG("Algorithm is %d (%p)\n", pipe->algo, pipe);

	/* skip if no algo */
	if (pipe->algo == PIPE_ALGO_NOP)
		return 0;

	if (!(node = add_mi_node_child(rpl, 0, "PIPE", 4, 0, 0)))
		return -1;

	if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "id", 2, key.s, key.len)))
		return -1;

	if (!(alg = get_rl_algo_name(pipe->algo))) {
		LM_ERR("[BUG] unknown algorithm %d\n", pipe->algo);
		return -1;
	}

	if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "algorithm", 9,
					alg->s, alg->len)))
		return -1;


	p = int2str((unsigned long)(pipe->limit), &len);
	if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "limit", 5, p, len)))
		return -1;

	p = int2str((unsigned long)(pipe->last_counter), &len);
	if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "counter", 7, p, len)))
		return -1;

	return 0;
}
Пример #5
0
int pdt_print_mi_node(pdt_node_t *pt, struct mi_node* rpl, char *code,
		int len, str *sdomain, str *sd, str *sp)
{
	int i;
	struct mi_node* node = NULL;
	struct mi_attr* attr= NULL;
	str *cl;

	if(pt==NULL || len>=PDT_MAX_DEPTH)
		return 0;
	
	cl = pdt_get_char_list();

	for(i=0; i<cl->len; i++)
	{
		code[len]=cl->s[i];
		if(pt[i].domain.s!=NULL)
		{
			if((sp->s==NULL && sd->s==NULL)
				|| (sp->s==NULL && (sd->s!=NULL && pt[i].domain.len==sd->len
						&& strncasecmp(pt[i].domain.s, sd->s, sd->len)==0)) 
				|| (sd->s==NULL && (len+1>=sp->len
						&& strncmp(code, sp->s, sp->len)==0))
				|| ((sp->s!=NULL && len+1>=sp->len
						&& strncmp(code, sp->s, sp->len)==0)
						&& (sd->s!=NULL && pt[i].domain.len>=sd->len
						&& strncasecmp(pt[i].domain.s, sd->s, sd->len)==0)))
			{
				node = add_mi_node_child(rpl, 0, "PDT", 3, 0, 0);
				if(node == NULL)
					goto error;

				attr = add_mi_attr(node, MI_DUP_VALUE, "SDOMAIN", 7,
						sdomain->s, sdomain->len);
				if(attr == NULL)
					goto error;
				attr = add_mi_attr(node, MI_DUP_VALUE, "PREFIX", 6,
							code, len+1);
				if(attr == NULL)
					goto error;
						
				attr = add_mi_attr(node, MI_DUP_VALUE,"DOMAIN", 6,
							pt[i].domain.s, pt[i].domain.len);
				if(attr == NULL)
					goto error;
			}
		}
		if(pdt_print_mi_node(pt[i].child, rpl, code, len+1, sdomain, sd, sp)<0)
			goto error;
	}
	return 0;
error:
	return -1;
}
Пример #6
0
/************************* MI ***********************/
static struct mi_root* imc_mi_list_rooms(struct mi_root* cmd_tree, void* param)
{
	int i, len;
	struct mi_root* rpl_tree= NULL;
	struct mi_node* rpl= NULL;
	struct mi_node* node= NULL;
	struct mi_attr* attr= NULL;
	imc_room_p irp = NULL;
	char* p = NULL;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if(rpl_tree == NULL)
		return 0;
	rpl = &rpl_tree->node;
	rpl->flags |= MI_IS_ARRAY;

	for(i=0; i<imc_hash_size; i++)
	{
		lock_get(&_imc_htable[i].lock);
		irp = _imc_htable[i].rooms;
			while(irp){
				node = add_mi_node_child(rpl, 0, "ROOM", 4, 0, 0);
				if( node == NULL)
					goto error;

				attr= add_mi_attr(node, MI_DUP_VALUE, "URI", 3, irp->uri.s,
					irp->uri.len);
				if(attr == NULL)
					goto error;

				p = int2str(irp->nr_of_members, &len);
				attr= add_mi_attr(node, 0, "MEMBERS", 7,p, len );
				if(attr == NULL)
					goto error;

				attr= add_mi_attr(node, MI_DUP_VALUE, "OWNER", 5,
						irp->members->uri.s, irp->members->uri.len);
				if(attr == NULL)
					goto error;

				irp = irp->next;
			}
		lock_release(&_imc_htable[i].lock);
	}

	return rpl_tree;

error:
	lock_release(&_imc_htable[i].lock);
	free_mi_tree(rpl_tree);
	return 0;

}
Пример #7
0
int mt_print_mi_node(m_tree_t *tree, mt_node_t *pt, struct mi_node* rpl,
		char *code, int len)
{
	int i;
	struct mi_node* node = NULL;
	struct mi_attr* attr= NULL;
	mt_is_t *tvalues;
	str val;

	if(pt==NULL || len>=MT_MAX_DEPTH)
		return 0;

	for(i=0; i<MT_NODE_SIZE; i++)
	{
		code[len]=mt_char_list.s[i];
		tvalues = pt[i].tvalues;
		if (tvalues != NULL)
		{
			node = add_mi_node_child(rpl, 0, "MT", 2, 0, 0);
			if(node == NULL)
				goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
					tree->tname.s, tree->tname.len);
			if(attr == NULL)
				goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "TPREFIX", 7,
					code, len+1);
			if(attr == NULL)
				goto error;

			while (tvalues != NULL) {
				if (tree->type == MT_TREE_IVAL) {
					val.s = int2str(tvalues->tvalue.n, &val.len);
					attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
							val.s, val.len);
				} else {
					attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
							tvalues->tvalue.s.s,
							tvalues->tvalue.s.len);
				}
				if(attr == NULL)
					goto error;
				tvalues = tvalues->next;
			}
		}
		if(mt_print_mi_node(tree, pt[i].child, rpl, code, len+1)<0)
			goto error;
	}
	return 0;
error:
	return -1;
}
Пример #8
0
struct mi_root* mi_get_pipes(struct mi_root* cmd_tree, void* param)
{
	struct mi_root *rpl_tree;
	struct mi_node *node=NULL, *rpl=NULL;
	struct mi_attr* attr;
	str algo;
	char* p;
	int i, len;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;

	LOCK_GET(rl_lock);
	for (i=0; i<MAX_PIPES; i++) {
		if (*pipes[i].algo != PIPE_ALGO_NOP) {
			node = add_mi_node_child(rpl, 0, "PIPE", 4, 0, 0);
			if(node == NULL)
				goto error;

			p = int2str((unsigned long)(i), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "id" , 2, p, len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*pipes[i].algo), &len);
			if (str_map_int(algo_names, *pipes[i].algo, &algo))
				goto error;
			attr = add_mi_attr(node, 0, "algorithm", 9, algo.s, algo.len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*pipes[i].limit), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "limit", 5, p, len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*pipes[i].counter), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "counter", 7, p, len);
			if(attr == NULL)
				goto error;
		}
	}
	LOCK_RELEASE(rl_lock);
	return rpl_tree;
error:
	LOCK_RELEASE(rl_lock);
	LM_ERR("Unable to create reply\n");
	free_mi_tree(rpl_tree); 
	return 0;
}
Пример #9
0
int add_mi_sdp_nodes(struct mi_node* node, qos_sdp_t* qos_sdp)
{
	struct mi_node* node1;
	struct mi_attr* attr;
	char* p;
	int i, len;
	sdp_session_cell_t* session;

	if ( qos_sdp->prev != NULL ) LM_ERR("got qos_sdp->prev=%p\n", qos_sdp->prev);

	while (qos_sdp) {
		node1 = add_mi_node_child( node, MI_DUP_VALUE, "sdp", 3, NULL, 0);
		if (node1==NULL)
			return 1;

		p = int2str((unsigned long)(qos_sdp->method_dir), &len);
		attr = add_mi_attr(node1, MI_DUP_VALUE, "m_dir", 5, p, len);
		if(attr == NULL)
			return 1;

		p = int2str((unsigned long)(qos_sdp->method_id), &len);
		attr = add_mi_attr(node1, MI_DUP_VALUE, "m_id", 4, p, len);
		if(attr == NULL)
			return 1;

		attr = add_mi_attr(node1, MI_DUP_VALUE, "method", 6, qos_sdp->method.s, qos_sdp->method.len);
		if(attr == NULL)
			return 1;

		attr = add_mi_attr(node1, MI_DUP_VALUE, "cseq", 4, qos_sdp->cseq.s, qos_sdp->cseq.len);
		if(attr == NULL)
			return 1;

		p = int2str((unsigned long)(qos_sdp->negotiation), &len);
		attr = add_mi_attr(node1, MI_DUP_VALUE, "negotiation", 11, p, len);
		if(attr == NULL)
			return 1;

		for (i=1;i>=0;i--){
			session = qos_sdp->sdp_session[i];
			if (session) {
				if (0 != add_mi_session_nodes(node1, i, session))
					return 1;
			}
		}

		qos_sdp = qos_sdp->next;
	}
	return 0;
}
Пример #10
0
/* mi function implementations */
struct mi_root* mi_stats(struct mi_root* cmd_tree, void* param)
{
	struct mi_root *rpl_tree;
	struct mi_node *node=NULL, *rpl=NULL;
	struct mi_attr* attr;
	char* p;
	int i, len;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;

	LOCK_GET(rl_lock);
	for (i=0; i<MAX_PIPES; i++) {
		if (*pipes[i].algo != PIPE_ALGO_NOP) {
			node = add_mi_node_child(rpl, 0, "PIPE", 4, 0, 0);
			if(node == NULL)
				goto error;

			p = int2str((unsigned long)(i), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "id", 2, p, len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*pipes[i].load), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "load", 4, p, len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*pipes[i].last_counter), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "counter", 7, p, len);
			if(attr == NULL)
				goto error;
		}
	}

	p = int2str((unsigned long)(*drop_rate), &len);
	node = add_mi_node_child(rpl, MI_DUP_VALUE, "DROP_RATE", 9, p, len);

	LOCK_RELEASE(rl_lock);
	return rpl_tree;
error:
	LOCK_RELEASE(rl_lock);
	LM_ERR("Unable to create reply\n");
	free_mi_tree(rpl_tree); 
	return 0;
}
Пример #11
0
int rl_bin_status(struct mi_root *rpl_tree)
{
	int index = 0;
	struct mi_node *node;
	char* p;
	int len;

	for (index = 0; index < rl_dests_nr; index++) {
		if (!(node = add_mi_node_child(&rpl_tree->node, 0, "Instance", 8,
					rl_dests[index].dst.s, rl_dests[index].dst.len))) {
			LM_ERR("cannot add a new instance\n");
			return -1;
		}

		if (*rl_dests[index].last_msg) {
			p = int2str((unsigned long)(*rl_dests[index].last_msg), &len);
		} else {
			p = "never";
			len = 5;
		}
		if (!add_mi_attr(node, MI_DUP_VALUE, "timestamp", 9, p, len)) {
			LM_ERR("cannot add last update\n");
			return -1;
		}

	}
	return 0;
}
Пример #12
0
static struct mi_root* mi_list_root_path(struct mi_root* cmd, void* param)
{
	struct mi_root *rpl_tree;
	struct mi_node *node, *rpl;
	struct mi_attr* attr;
	struct httpd_cb *cb = httpd_cb_list;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==NULL) return NULL;
	rpl = &rpl_tree->node;
	rpl->flags |= MI_IS_ARRAY;
	while(cb) {
		node = add_mi_node_child(rpl, 0, "http_root", 9,
				cb->http_root->s, cb->http_root->len);
		if(node == NULL) goto error;
		attr = add_mi_attr(node, 0, "module", 6,
				(char*)cb->module, strlen(cb->module));
		if(attr == NULL) goto error;

		cb = cb->next;
	}

	return rpl_tree;
error:
	LM_ERR("Unable to create reply\n");
	free_mi_tree(rpl_tree);
	return NULL;
}
Пример #13
0
static struct mi_root * mi_show_partition(struct mi_root *cmd_tree, void *param)
{
	struct mi_node *node = NULL;
	struct mi_root *rpl_tree = NULL;
	struct mi_node* root= NULL;
	struct mi_attr* attr;
	dp_connection_list_t *el;


	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==NULL) return NULL;

	if (cmd_tree) node = cmd_tree->node.kids;
	if (node == NULL) {
		el = dp_get_connections();
		root = &rpl_tree->node;
		while (el) {
			node = add_mi_node_child(root, 0, "Partition", 9, el->partition.s, el->partition.len);
			if( node == NULL) goto error;
			attr = add_mi_attr(node, 0, "table", 5, el->table_name.s, el->table_name.len);
			if(attr == NULL) goto error;
			db_get_url(&el->db_url);
			if(database_url.len == 0) goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "db_url", 6, database_url.s, database_url.len);
			if(attr == NULL) goto error;
			el = el->next;
		}
	} else {
		el = dp_get_connection(&node->value);
		if (!el) goto error;
		root = &rpl_tree->node;
		node = add_mi_node_child(root, 0, "Partition", 9, el->partition.s, el->partition.len);
		if( node == NULL) goto error;
		attr = add_mi_attr(node, 0, "table", 5, el->table_name.s, el->table_name.len);
		if(attr == NULL) goto error;
		db_get_url(&el->db_url);
		if(database_url.len == 0) goto error;
		attr = add_mi_attr(node, MI_DUP_VALUE, "db_url", 6, database_url.s, database_url.len);
		if(attr == NULL) goto error;
	}

	return rpl_tree;

error:
	if(rpl_tree) free_mi_tree(rpl_tree);
	return NULL;
}
Пример #14
0
static struct mi_root *mi_ps(struct mi_root *cmd, void *param)
{
	struct mi_root *rpl_tree;
	struct mi_node *rpl;
	struct mi_node *node;
	struct mi_attr *attr;
	char *p;
	int len;
	int i,threads_no;
	struct thread_info *threads_table;

	rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;

	get_threads_info( &threads_table, &threads_no);

	for ( i=0 ; i<threads_no ; i++ ) {
		node = add_mi_node_child(rpl, 0, MI_SSTR("Thread"), 0, 0 );
		if (node==0)
			goto error;

		p = int2str((unsigned long)i, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("ID"), p, len);
		if (attr==0)
			goto error;

		p = int2str((unsigned long)threads_table[i].id, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("TID"), p, len);
		if (attr==0)
			goto error;

		attr = add_mi_attr( node, 0, MI_SSTR("Type"),
			threads_table[i].name, strlen(threads_table[i].name));
		if (attr==0)
			goto error;
	}

	return rpl_tree;
error:
	LM_ERR("failed to add node\n");
	free_mi_tree(rpl_tree);
	return 0;
}
Пример #15
0
struct mi_root* mi_get_queues(struct mi_root* cmd_tree, void* param)
{
	struct mi_root *rpl_tree;
	struct mi_node *node=NULL, *rpl=NULL;
	struct mi_attr* attr;
	char* p;
	int i, len;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;

	LOCK_GET(rl_lock);
	for (i=0; i<MAX_QUEUES; i++) {
		if (queues[i].pipe) {
			node = add_mi_node_child(rpl, 0, "QUEUE", 5, 0, 0);
			if(node == NULL)
				goto error;

			p = int2str((unsigned long)(i), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "id" , 2, p, len);
			if(attr == NULL)
				goto error;

			p = int2str((unsigned long)(*queues[i].pipe), &len);
			attr = add_mi_attr(node, MI_DUP_VALUE, "pipe" , 4, p, len);
			if(attr == NULL)
				goto error;

			attr = add_mi_attr(node, 0, "method", 6,
				(*queues[i].method).s, (*queues[i].method).len);
			if(attr == NULL)
				goto error;
		}
	}
	LOCK_RELEASE(rl_lock);

	return rpl_tree;
error:
	LOCK_RELEASE(rl_lock);
	LM_ERR("Unable to create reply\n");
	free_mi_tree(rpl_tree); 
	return 0;
}
Пример #16
0
int add_mi_stream_nodes(struct mi_node* node, int index, sdp_stream_cell_t* stream)
{
	struct mi_node* node1;
	struct mi_attr* attr;
	sdp_payload_attr_t* sdp_payload;
	char* p;
	int i, len;

	p = int2str((unsigned long)(index), &len);
	node1 = add_mi_node_child( node, MI_DUP_VALUE, "stream", 6, p, len);
	if (node1==NULL)
		return 1;
	
	attr = add_mi_attr(node1, MI_DUP_VALUE, "media", 5, stream->media.s, stream->media.len);
	if(attr == NULL) 
		return 1; 

	attr = add_mi_attr(node1, MI_DUP_VALUE, "IP", 2, stream->ip_addr.s, stream->ip_addr.len);
	if(attr == NULL) 
		return 1;

	attr = add_mi_attr(node1, MI_DUP_VALUE, "port", 4, stream->port.s, stream->port.len);
	if(attr == NULL)
		return 1;

	attr = add_mi_attr(node1, MI_DUP_VALUE, "transport", 9, stream->transport.s, stream->transport.len);
	if(attr == NULL)
		return 1;

	if (stream->sendrecv_mode.s!=NULL && stream->sendrecv_mode.len!=0) {
		attr = add_mi_attr(node1, MI_DUP_VALUE, "sendrecv", 8, stream->sendrecv_mode.s, stream->sendrecv_mode.len);
		if(attr == NULL)
			return 1;
	}

	if (stream->ptime.s!=NULL && stream->ptime.len!=0) {
		attr = add_mi_attr(node1, MI_DUP_VALUE, "ptime", 5, stream->ptime.s, stream->ptime.len);
		if(attr == NULL)
			return 1;
	}

	p = int2str((unsigned long)(stream->payloads_num), &len);
	attr = add_mi_attr(node1, MI_DUP_VALUE, "payloads_num", 12, p, len);
	if(attr == NULL)
		return 1;

	sdp_payload = stream->payload_attr;
	for(i=stream->payloads_num-1;i>=0;i--){
		if (!sdp_payload) {
			LM_ERR("got NULL sdp_payload\n");
			return 1;
		}
		if (0!=add_mi_sdp_payload_nodes(node1, i, sdp_payload)){
			return 1;
		}
		sdp_payload = sdp_payload->next;
	}

	return 0;
}
Пример #17
0
static struct mi_root *mi_ps(struct mi_root *cmd, void *param)
{
	struct mi_root *rpl_tree;
	struct mi_node *rpl;
	struct mi_node *node;
	struct mi_attr *attr;
	char *p;
	int len;
	int i;

	rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;
	rpl->flags |= MI_IS_ARRAY;

	for ( i=0 ; i<counted_processes ; i++ ) {
		node = add_mi_node_child(rpl, 0, MI_SSTR("Process"), 0, 0 );
		if (node==0)
			goto error;

		p = int2str((unsigned long)i, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("ID"), p, len);
		if (attr==0)
			goto error;

		p = int2str((unsigned long)pt[i].pid, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("PID"), p, len);
		if (attr==0)
			goto error;

		attr = add_mi_attr( node, 0, MI_SSTR("Type"),
			pt[i].desc, strlen(pt[i].desc));
		if (attr==0)
			goto error;
	}

	return rpl_tree;
error:
	LM_ERR("failed to add node\n");
	free_mi_tree(rpl_tree);
	return 0;
}
Пример #18
0
static int evi_print_subscriber(struct mi_node *rpl, evi_subs_p subs)
{
	evi_reply_sock *sock = subs->reply_sock;
	struct mi_node *node = NULL;
	str socket;

	if (!subs || !subs->trans_mod || !subs->trans_mod->print) {
		LM_ERR("subscriber does not have a print method exported\n");
		return -1;
	}
	node = add_mi_node_child(rpl, 0, "Subscriber", 10, 0, 0);
	if(node == NULL)
		return -1;

	if (!sock) {
		LM_DBG("no socket specified\n");
		if (!add_mi_attr(node, 0, "protocol", 8,
				subs->trans_mod->proto.s, subs->trans_mod->proto.len))
			return -1;
		return 0;
	}

	socket = subs->trans_mod->print(sock);
	LM_DBG("print subscriber socket <%.*s> %d\n",
			socket.len, socket.s, socket.len);
	if (!addf_mi_attr(node, MI_DUP_VALUE, "socket", 6, "%.*s:%.*s",
			subs->trans_mod->proto.len, subs->trans_mod->proto.s,
			socket.len, socket.s))
		return -1;

	if (sock->flags & EVI_EXPIRE) {
		if (!addf_mi_attr(node, 0, "expire", 6, "%d", sock->expire))
			return -1;
	} else {
		if (!add_mi_attr(node, 0, "expire", 6, "never", 5))
			return -1;
	}
	/* XXX - does subscription time make sense? */

	return 0;
}
Пример #19
0
int mt_print_mi_node(m_tree_t *tree, mt_node_t *pt, struct mi_node* rpl,
		char *code, int len)
{
	int i;
	struct mi_node* node = NULL;
	struct mi_attr* attr= NULL;

	if(pt==NULL || len>=MT_MAX_DEPTH)
		return 0;
	
	for(i=0; i<MT_NODE_SIZE; i++)
	{
		code[len]=mt_char_list.s[i];
		if(pt[i].tvalue.s!=NULL)
		{
			node = add_mi_node_child(rpl, 0, "MT", 2, 0, 0);
			if(node == NULL)
				goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "TNAME", 5,
					tree->tname.s, tree->tname.len);
			if(attr == NULL)
				goto error;
			attr = add_mi_attr(node, MI_DUP_VALUE, "TPREFIX", 7,
						code, len+1);
			if(attr == NULL)
				goto error;
					
			attr = add_mi_attr(node, MI_DUP_VALUE, "TVALUE", 6,
						pt[i].tvalue.s, pt[i].tvalue.len);
			if(attr == NULL)
				goto error;
		}
		if(mt_print_mi_node(tree, pt[i].child, rpl, code, len+1)<0)
			goto error;
	}
	return 0;
error:
	return -1;
}
Пример #20
0
/**
 * The dialog mi helper function.
 */
void sst_dialog_mi_context_CB(struct dlg_cell* did, int type, struct dlg_cb_params * params)
{
	struct mi_node* parent_node = (struct mi_node*)(params->dlg_data);
	struct mi_node* node;
	struct mi_attr* attr;
	sst_info_t* sst_info = (sst_info_t*)*(params->param);
	char* p;
	int len;

	node = add_mi_node_child(parent_node, 0, "sst", 3, NULL, 0);
	if (node==NULL) {
		LM_ERR("oom\n");
		return;
	}

	p = int2str((unsigned long)(sst_info->requester), &len);
	attr = add_mi_attr(node, MI_DUP_VALUE, "requester_flags", 15, p, len);
	if(attr == NULL) {
		LM_ERR("oom requester_flags\n");
		return;
	}

	p = int2str((unsigned long)(sst_info->supported), &len);
	attr = add_mi_attr(node, MI_DUP_VALUE, "supported_flags", 15, p, len);
	if(attr == NULL) {
		LM_ERR("oom supported_flags\n");
		return;
	}

	p = int2str((unsigned long)(sst_info->interval), &len);
	attr = add_mi_attr(node, MI_DUP_VALUE, "interval", 8, p, len);
	if(attr == NULL) {
		LM_ERR("oom interval\n");
		return;
	}

	return;
}
Пример #21
0
static struct mi_root * clusterer_list_cap(struct mi_root *cmd_tree, void *param)
{
	cluster_info_t *cl;
	struct local_cap *cap;
	struct mi_root *rpl_tree = NULL;
	struct mi_node *node = NULL;
	struct mi_node *node_s = NULL;
	struct mi_attr* attr;
	str val;
	static str str_ok = str_init("Ok");
	static str str_not_synced = str_init("not synced");

	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
	if (!rpl_tree)
		return NULL;
	rpl_tree->node.flags |= MI_IS_ARRAY;

	lock_start_read(cl_list_lock);

	for (cl = *cluster_list; cl; cl = cl->next) {
		val.s = int2str(cl->cluster_id, &val.len);
		node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE|MI_IS_ARRAY,
			MI_SSTR("Cluster"), val.s, val.len);
		if (!node) goto error;

		for (cap = cl->capabilities; cap; cap = cap->next) {
			val.s = cap->reg.name.s;
			val.len = cap->reg.name.len;
			node_s = add_mi_node_child(node, MI_DUP_VALUE|MI_IS_ARRAY,
			   MI_SSTR("Capability"), val.s, val.len);
			if (!node_s) goto error;

			lock_get(cl->lock);
			val.s = int2str((cap->flags & CAP_STATE_OK) ? 1 : 0, &val.len);
			lock_release(cl->lock);
			attr = add_mi_attr(node_s, MI_DUP_VALUE, MI_SSTR("State"),
				(cap->flags & CAP_STATE_OK) ? str_ok.s : str_not_synced.s,
				(cap->flags & CAP_STATE_OK) ? str_ok.len : str_not_synced.len);
			if (!attr) goto error;
	   }
	}

	lock_stop_read(cl_list_lock);
	return rpl_tree;

error:
	lock_stop_read(cl_list_lock);
	if (rpl_tree) free_mi_tree(rpl_tree);
	return NULL;
}
Пример #22
0
int add_mi_sdp_payload_nodes(struct mi_node* node, int index, sdp_payload_attr_t* sdp_payload)
{
	struct mi_node* node1;
	struct mi_attr* attr;
	char* p;
	int len;

	p = int2str((unsigned long)(index), &len);
	node1 = add_mi_node_child( node, MI_DUP_VALUE, "payload", 7, p, len);
	if (node1==NULL)
		return 1;

	attr = add_mi_attr(node1, MI_DUP_VALUE, "rtpmap", 6, sdp_payload->rtp_payload.s, sdp_payload->rtp_payload.len);
	if (attr==NULL)
		return 1;

	if (sdp_payload->rtp_enc.s!=NULL && sdp_payload->rtp_enc.len!=0) {
		attr = add_mi_attr(node1, MI_DUP_VALUE, "codec", 5, sdp_payload->rtp_enc.s, sdp_payload->rtp_enc.len);
		if(attr == NULL)
			return 1;
	}

	return 0;
}
Пример #23
0
int ds_print_mi_list(struct mi_node* rpl)
{
	int len, j;
	char* p;
	char c;
	ds_set_p list;
	struct mi_node* node = NULL;
	struct mi_node* set_node = NULL;
	struct mi_attr* attr = NULL;
	
	if(_ds_list==NULL || _ds_list_nr<=0)
	{
		LM_DBG("empty destination sets\n");
		return  0;
	}

	p= int2str(_ds_list_nr, &len); 
	node = add_mi_node_child(rpl, MI_DUP_VALUE, "SET_NO",6, p, len);
	if(node== NULL)
		return -1;

	for(list = _ds_list; list!= NULL; list= list->next)
	{
		p = int2str(list->id, &len);
		set_node= add_mi_node_child(rpl, MI_DUP_VALUE,"SET", 3, p, len);
		if(set_node == NULL)
			return -1;

		for(j=0; j<list->nr; j++)
  		{
  			node= add_mi_node_child(set_node, 0, "URI", 3,
  					list->dlist[j].uri.s, list->dlist[j].uri.len);
  			if(node == NULL)
  				return -1;
  
  			if (list->dlist[j].flags & DS_INACTIVE_DST) c = 'I';
  			else if (list->dlist[j].flags & DS_PROBING_DST) c = 'P';
  			else c = 'A';
  
  			attr = add_mi_attr (node, MI_DUP_VALUE, "flag",4, &c, 1);
  			if(attr == 0)
  				return -1;
  
 		}
	}

	return 0;
}
Пример #24
0
static int bin_status_aux(struct mi_node *root, clusterer_node_t *nodes, int type, int cluster_id)
{
	clusterer_node_t *d;
	struct mi_node *node = NULL;
	struct mi_attr* attr;
	str cluster_id_s;
	str machine_id_s;
	str state;

	for (d = nodes; d; d = d->next) {
		cluster_id_s.s = int2str(cluster_id, &cluster_id_s.len);
		node = add_mi_node_child(root, MI_DUP_VALUE, "Cluster ID", 10,
			cluster_id_s.s, cluster_id_s.len);
		if (node == NULL) goto error;

		machine_id_s.s = int2str(d->machine_id, &machine_id_s.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "Machine ID", 10,
			machine_id_s.s, machine_id_s.len);
		if (attr == NULL) goto error;

		state.s = int2str(d->state, &state.len);
		attr = add_mi_attr(node, MI_DUP_VALUE, "STATE", 5,
			state.s, state.len);
		if (attr == NULL) goto error;

		if (d->description.s)
			attr = add_mi_attr(node, MI_DUP_VALUE, "DESCRIPTION", 11,
			d->description.s, d->description.len);
		else
			attr = add_mi_attr(node, MI_DUP_VALUE, "DESCRIPTION", 11,
			"none", 4);
		if (attr == NULL) goto error;

		if (type)
			attr = add_mi_attr(node, MI_DUP_VALUE, "TYPE", 4,
			"server", 6);
		else
			attr = add_mi_attr(node, MI_DUP_VALUE, "TYPE", 4,
			"client", 6);
		if (attr == NULL) goto error;
	}

	return 0;
error:
	return -1;
}
Пример #25
0
/* mi function implementations */
struct mi_root* mi_stats(struct mi_root* cmd_tree, void* param)
{
	struct mi_root *rpl_tree;
	struct mi_node *node=NULL, *rpl=NULL;
	struct mi_attr *attr;
	int len;
	char * p;

	node = cmd_tree->node.kids;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==0)
		return 0;
	rpl = &rpl_tree->node;
	rpl->flags |= MI_IS_ARRAY;

	if (rl_stats(rpl_tree, &node->value)) {
		LM_ERR("cannot mi print values\n");
		goto free;
	}

	if (!(node = add_mi_node_child(rpl, 0, "PIPE", 4, NULL, 0)))
		goto free;

	LOCK_GET(rl_lock);
	p = int2str((unsigned long)(*drop_rate), &len);
	if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "drop_rate", 9, p, len))) {
		LOCK_RELEASE(rl_lock);
		goto free;
	}

	LOCK_RELEASE(rl_lock);
	return rpl_tree;
free:
	free_mi_tree(rpl_tree);
	return 0;
}
Пример #26
0
struct mi_root *mi_list_sharing_tags(struct mi_root *cmd_tree, void *param)
{
    struct mi_root *rpl_tree= NULL;
    struct mi_node *node, *rpl = NULL;
    struct mi_attr *attr;
    struct dlg_sharing_tag *tag;
    str val;

    if (!dialog_repl_cluster)
		return init_mi_tree(400, MI_SSTR("Dialog replication disabled"));

    rpl_tree = init_mi_tree(200, MI_SSTR(MI_OK));
    if (rpl_tree==0)
        return NULL;
    rpl = &rpl_tree->node;
    rpl->flags |= MI_IS_ARRAY;

    lock_start_read(shtags_lock);
    for (tag = *shtags_list; tag; tag = tag->next) {
        node = add_mi_node_child(rpl, MI_DUP_VALUE,
            MI_SSTR("Tag"), tag->name.s, tag->name.len);
        if (!node) goto error;

        val.s = int2str(tag->state, &val.len);
        attr = add_mi_attr(node, MI_DUP_VALUE,
            MI_SSTR("State"), val.s, val.len);
        if (!attr) goto error;
    }
    lock_stop_read(shtags_lock);

    return rpl_tree;

error:
    lock_stop_read(shtags_lock);
    if (rpl_tree) free_mi_tree(rpl_tree);
    return NULL;
}
Пример #27
0
static struct mi_root *mq_mi_get_size(struct mi_root *cmd_tree, 
				      void *param)
{
	static struct mi_node	*node = NULL, *rpl = NULL;
	static struct mi_root	*rpl_tree = NULL;
	static struct mi_attr	*attr = NULL;
	str			mqueue_name;
	int			mqueue_sz = 0;
	char			*p = NULL;
	int			len = 0;

	if((node = cmd_tree->node.kids) == NULL) {
		return init_mi_tree(400, MI_MISSING_PARM_S, 
					 MI_MISSING_PARM_LEN);
	}

	mqueue_name = node->value;

	if(mqueue_name.len <= 0 || mqueue_name.s == NULL) {
		LM_ERR("bad mqueue name\n");
		return init_mi_tree(500, MI_SSTR("bad mqueue name"));
	}

	mqueue_sz = _mq_get_csize(&mqueue_name);

	if(mqueue_sz < 0) {
		LM_ERR("no such mqueue\n");
		return init_mi_tree(404, MI_SSTR("no such mqueue"));
	}

	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);

	if(rpl_tree == NULL) 
		return 0;

	rpl = &rpl_tree->node;

	node = add_mi_node_child(rpl, MI_DUP_VALUE, "mqueue", strlen("mqueue"),
				 NULL, 0);

	if(node == NULL) {
		free_mi_tree(rpl_tree);
		return NULL;
	}

	attr = add_mi_attr(node, MI_DUP_VALUE, "name", strlen("name"),
			   mqueue_name.s, mqueue_name.len);

	if(attr == NULL) goto error;

	p = int2str((unsigned long) mqueue_sz, &len);	

	attr = add_mi_attr(node, MI_DUP_VALUE, "size", strlen("size"), 
			   p, len);

	if(attr == NULL) goto error;

	return rpl_tree;

error:
	free_mi_tree(rpl_tree);
	return NULL;
}
Пример #28
0
static struct mi_root* mi_lb_list(struct mi_root *cmd_tree, void *param)
{
	struct mi_root *rpl_tree;
	struct mi_node *dst_node;
	struct mi_node *node, *node1;
	struct mi_attr *attr;
	struct lb_dst *dst;
	char *p;
	int len;
	int i;

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==NULL)
		return NULL;
	rpl_tree->node.flags |= MI_IS_ARRAY;

	lock_start_read( ref_lock );

	/* go through all destination */
	for( dst=(*curr_data)->dsts ; dst ; dst=dst->next) {
		/* add a destination node */
		dst_node = add_mi_node_child( &rpl_tree->node, 0, "Destination", 11,
					dst->uri.s, dst->uri.len);
		if (dst_node==0)
			goto error;

		/* add some attributes to the destination node */
		p= int2str((unsigned long)dst->id, &len);
		attr = add_mi_attr( dst_node, MI_DUP_VALUE, "id", 2, p, len);
		if (attr==0)
			goto error;

		p= int2str((unsigned long)dst->group, &len);
		attr = add_mi_attr( dst_node, MI_DUP_VALUE, "group", 5, p, len);
		if (attr==0)
			goto error;

		if (dst->flags&LB_DST_STAT_DSBL_FLAG) {
			attr = add_mi_attr( dst_node, 0, "enabled", 7, "no", 2);
		} else {
			attr = add_mi_attr( dst_node, 0, "enabled", 7, "yes", 3);
		}
		if (attr==0)
			goto error;

		if (dst->flags&LB_DST_STAT_NOEN_FLAG) {
			attr = add_mi_attr( dst_node, 0, "auto-reenable", 13, "off", 3);
		} else {
			attr = add_mi_attr( dst_node, 0, "auto-reenable", 13, "on", 2);
		}
		if (attr==0)
			goto error;

		node = add_mi_node_child( dst_node, MI_IS_ARRAY, "Resources", 9, NULL, 0);
		if (node==0)
			goto error;

		/* go through all resources */
		for( i=0 ; i<dst->rmap_no ; i++) {
		/* add a resource node */
			node1 = add_mi_node_child( node, 0, "Resource", 8,
				dst->rmap[i].resource->name.s,dst->rmap[i].resource->name.len);
			if (node1==0)
				goto error;

			/* add some attributes to the destination node */
			p= int2str((unsigned long)dst->rmap[i].max_load, &len);
			attr = add_mi_attr( node1, MI_DUP_VALUE, "max", 3, p, len);
			if (attr==0)
				goto error;

			p= int2str((unsigned long)lb_dlg_binds.get_profile_size
				(dst->rmap[i].resource->profile, &dst->profile_id), &len);
			attr = add_mi_attr( node1, MI_DUP_VALUE, "load", 4, p, len);
			if (attr==0)
				goto error;
		}
	}

	lock_stop_read( ref_lock );
	return rpl_tree;
error:
	lock_stop_read( ref_lock );
	free_mi_tree(rpl_tree);
	return 0;
}
Пример #29
0
/* lists the clusters' topology as viewed by the current node*/
static struct mi_root * clusterer_list_topology(struct mi_root *cmd_tree, void *param)
{
	cluster_info_t *cl;
	node_info_t *n_info;
	struct mi_root *rpl_tree = NULL;
	struct mi_node *node = NULL;
	struct mi_node *node_s = NULL;
	struct mi_attr* attr;
	str val;
	char neigh_list[512];
	struct neighbour *neigh;

	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
	if (!rpl_tree)
		return NULL;
	rpl_tree->node.flags |= MI_IS_ARRAY;

	lock_start_read(cl_list_lock);

	/* iterate through clusters */
	for (cl = *cluster_list; cl; cl = cl->next) {

		val.s = int2str(cl->cluster_id, &val.len);
		node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE|MI_IS_ARRAY,
			MI_SSTR("Cluster"), val.s, val.len);
		if (!node) goto error;

		val.s = int2str(current_id, &val.len);
		node_s = add_mi_node_child(node, MI_DUP_VALUE,
			MI_SSTR("Node"), val.s, val.len);
		if (!node_s) goto error;

		memset(neigh_list, 0, 500);
		for (neigh = cl->current_node->neighbour_list; neigh; neigh = neigh->next) {
			sprintf(neigh_list + strlen(neigh_list), "%d ", neigh->node->node_id);
		}
		val.s = neigh_list;
		val.len = strlen(neigh_list);

		attr = add_mi_attr(node_s, MI_DUP_VALUE,
			MI_SSTR("Neighbours"), val.s, val.len);
		if (!attr) goto error;

		for (n_info = cl->node_list; n_info; n_info = n_info->next) {

			val.s = int2str(n_info->node_id, &val.len);
			node_s = add_mi_node_child(node, MI_DUP_VALUE,
				MI_SSTR("Node"), val.s, val.len);
			if (!node_s) goto error;

			memset(neigh_list, 0, 500);

			lock_get(n_info->lock);

			for (neigh = n_info->neighbour_list; neigh; neigh = neigh->next) {
				sprintf(neigh_list + strlen(neigh_list), "%d ", neigh->node->node_id);
			}
			if (n_info->link_state == LS_UP)
				sprintf(neigh_list + strlen(neigh_list), "%d ", current_id);

			lock_release(n_info->lock);

			val.s = neigh_list;
			val.len = strlen(neigh_list);

			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("Neighbours"), val.s, val.len);
			if (!attr) goto error;
		}
	}

	lock_stop_read(cl_list_lock);
	return rpl_tree;
error:
	lock_stop_read(cl_list_lock);
	if (rpl_tree) free_mi_tree(rpl_tree);
	return NULL;
}
Пример #30
0
static struct mi_root * clusterer_list(struct mi_root *cmd_tree, void *param)
{
	cluster_info_t *cl;
	node_info_t *n_info;
	struct mi_root *rpl_tree = NULL;
	struct mi_node *node = NULL;
	struct mi_node *node_s = NULL;
	struct mi_attr* attr;
	str val;
	static str str_up   = 	str_init("Up     ");
	static str str_prob = 	str_init("Probe  ");
	static str str_down = 	str_init("Down   ");
	static str str_none = 	str_init("none");
	int n_hop;

	rpl_tree = init_mi_tree(200, MI_OK_S, MI_OK_LEN);
	if (!rpl_tree)
		return NULL;
	rpl_tree->node.flags |= MI_IS_ARRAY;

	lock_start_read(cl_list_lock);

	/* iterate through clusters */
	for (cl = *cluster_list; cl; cl = cl->next) {

		val.s = int2str(cl->cluster_id, &val.len);
		node = add_mi_node_child(&rpl_tree->node, MI_DUP_VALUE|MI_IS_ARRAY,
			MI_SSTR("Cluster"), val.s, val.len);
		if (!node) goto error;

		/* iterate through servers */
		for (n_info = cl->node_list; n_info; n_info = n_info->next) {

			val.s = int2str(n_info->node_id, &val.len);
			node_s = add_mi_node_child(node, MI_DUP_VALUE,
				MI_SSTR("Node"), val.s, val.len);
			if (!node) goto error;

			val.s = sint2str(n_info->id, &val.len);
			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("DB_ID"), val.s, val.len);
			if (!attr) goto error;

			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("URL"), n_info->url.s, n_info->url.len);
			if (!attr) goto error;

			lock_get(n_info->lock);

			val.s = int2str(n_info->flags & NODE_STATE_ENABLED ? 1 : 0, &val.len);
			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("Enabled"), val.s, val.len);
			if (!attr) {
				lock_release(n_info->lock);
				goto error;
			}

			if (n_info->link_state == LS_UP)
				val = str_up;
			else if (n_info->link_state == LS_DOWN)
				val = str_down;
			else
				val = str_prob;
			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("Link_state"), val.s, val.len);
			if (!attr) {
				lock_release(n_info->lock);
				goto error;
			}

			lock_release(n_info->lock);

			n_hop = get_next_hop(n_info); 
			if (n_hop <= 0)
				val = str_none;
			else
				val.s = int2str(n_hop, &val.len);
			attr = add_mi_attr(node_s, MI_DUP_VALUE,
				MI_SSTR("Next_hop"), val.s, val.len);
			if (!attr)
				goto error;

			if (n_info->description.s)
				attr = add_mi_attr(node_s, MI_DUP_VALUE,
					MI_SSTR("Description"),
					n_info->description.s, n_info->description.len);
			else
				attr = add_mi_attr(node_s, MI_DUP_VALUE,
					MI_SSTR("Description"),
					"none", 4);
			if (!attr) goto error;
		}
	}

	lock_stop_read(cl_list_lock);
	return rpl_tree;
error:
	lock_stop_read(cl_list_lock);
	if (rpl_tree) free_mi_tree(rpl_tree);
	return NULL;
}