Pārlūkot izejas kodu

dialog: Send properly structured responses on RPC requests

Instead of dumping random blobs in structured protocols (json, xmlrpc),
return properly structured data.

Each dialog is a struct with named fields, a list of dialogs is an array
of structs. Variables and profiles are arrays in the dialog struct.

Dialog contexts still todo.
Alex Hermann 11 gadi atpakaļ
vecāks
revīzija
684afd9cde
2 mainītis faili ar 78 papildinājumiem un 91 dzēšanām
  1. 76 90
      modules/dialog/dialog.c
  2. 2 1
      modules/dialog/dlg_var.c

+ 76 - 90
modules/dialog/dialog.c

@@ -119,6 +119,7 @@ str dlg_bridge_contact = str_init("sip:[email protected]:5060");
 
 str ruri_pvar_param = str_init("$ru");
 pv_elem_t * ruri_param_model = NULL;
+str empty_str = STR_NULL;
 
 /* statistic variables */
 int dlg_enable_stats = 1;
@@ -1483,57 +1484,69 @@ static inline void internal_rpc_print_dlg(rpc_t *rpc, void *c, dlg_cell_t *dlg,
 		int with_context)
 {
 	rpc_cb_ctx_t rpc_cb;
-	time_t _start_ts, _stop_ts;
-	struct tm *_start_t, *_stop_t;
-	char _start_date_buf[RPC_DATE_BUF_LEN]="UNSPECIFIED";
-	char _stop_date_buf[RPC_DATE_BUF_LEN]="UNSPECIFIED";
-
-	_start_ts = (time_t)dlg->start_ts;
-	if (_start_ts) {
-		_start_t = localtime(&_start_ts);
-		strftime(_start_date_buf, RPC_DATE_BUF_LEN - 1,
-			"%Y-%m-%d %H:%M:%S", _start_t);
-		if (dlg->tl.timeout) {
-			_stop_ts = time(0) + dlg->tl.timeout - get_ticks();
-			_stop_t = localtime(&_stop_ts);
-			strftime(_stop_date_buf, RPC_DATE_BUF_LEN - 1,
-				"%Y-%m-%d %H:%M:%S", _stop_t);
+	void *h, *sh, *ssh;
+	dlg_profile_link_t *pl;
+	dlg_var_t *var;
+
+	if (rpc->add(c, "{", &h) < 0) goto error;
+
+	rpc->struct_add(h, "ddSSSdddddddd",
+		"h_entry", dlg->h_entry,
+		"h_id", dlg->h_id,
+		"call-id", &dlg->callid,
+		"from_uri", &dlg->from_uri,
+		"to_uri", &dlg->to_uri,
+		"state", dlg->state,
+		"start_ts", dlg->start_ts,
+		"init_ts", dlg->init_ts,
+		"timeout", dlg->tl.timeout ? time(0) + dlg->tl.timeout - get_ticks() : 0,
+		"lifetime", dlg->lifetime,
+		"dflags", dlg->dflags,
+		"sflags", dlg->sflags,
+		"iflags", dlg->iflags);
+
+	if (rpc->struct_add(h, "{", "caller", &sh) < 0) goto error;
+	rpc->struct_add(sh, "SSSSS",
+		"tag", &dlg->tag[DLG_CALLER_LEG],
+		"contact", &dlg->contact[DLG_CALLER_LEG],
+		"cseq", &dlg->cseq[DLG_CALLER_LEG],
+		"route_set", &dlg->route_set[DLG_CALLER_LEG],
+		"socket", dlg->bind_addr[DLG_CALLER_LEG] ? &dlg->bind_addr[DLG_CALLER_LEG]->sock_str : &empty_str);
+
+	if (rpc->struct_add(h, "{", "callee", &sh) < 0) goto error;
+	rpc->struct_add(sh, "SSSSS",
+		"tag", &dlg->tag[DLG_CALLEE_LEG],
+		"contact", &dlg->contact[DLG_CALLEE_LEG],
+		"cseq", &dlg->cseq[DLG_CALLEE_LEG],
+		"route_set", &dlg->route_set[DLG_CALLEE_LEG],
+		"socket", dlg->bind_addr[DLG_CALLEE_LEG] ? &dlg->bind_addr[DLG_CALLEE_LEG]->sock_str : &empty_str);
+
+	if (rpc->struct_add(h, "[", "profiles", &sh) < 0) goto error;
+	for (pl = dlg->profile_links ; pl ; pl=pl->next) {
+		if (pl->profile->has_value) {
+			rpc->array_add(sh, "{", &ssh);
+			rpc->struct_add(ssh, "S", pl->profile->name.s, &pl->hash_linker.value);
+		} else {
+			rpc->array_add(sh, "S", &pl->profile->name);
 		}
 	}
 
-	rpc->rpl_printf(c, "hash:%u:%u state:%u ref_count:%u "
-		"timestart:%u timeout:%u lifetime:%u datestart:%s datestop:%s",
-		dlg->h_entry, dlg->h_id, dlg->state, dlg->ref, _start_ts, dlg->tl.timeout, dlg->lifetime,
-		_start_date_buf, _stop_date_buf);
-	rpc->rpl_printf(c, "\tcallid:%.*s from_tag:%.*s to_tag:%.*s",
-		dlg->callid.len, dlg->callid.s,
-		dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
-		dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
-	rpc->rpl_printf(c, "\tfrom_uri:%.*s to_uri:%.*s",
-		dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len, dlg->to_uri.s);
-	rpc->rpl_printf(c, "\tcaller_contact:%.*s caller_cseq:%.*s",
-		dlg->contact[DLG_CALLER_LEG].len, dlg->contact[DLG_CALLER_LEG].s,
-		dlg->cseq[DLG_CALLER_LEG].len, dlg->cseq[DLG_CALLER_LEG].s);
-	rpc->rpl_printf(c, "\tcaller_route_set: %.*s",
-		dlg->route_set[DLG_CALLER_LEG].len, dlg->route_set[DLG_CALLER_LEG].s);
-	rpc->rpl_printf(c, "\tcallee_contact:%.*s callee_cseq:%.*s",
-		dlg->contact[DLG_CALLEE_LEG].len, dlg->contact[DLG_CALLEE_LEG].s,
-		dlg->cseq[DLG_CALLEE_LEG].len, dlg->cseq[DLG_CALLEE_LEG].s);
-	rpc->rpl_printf(c, "\tcallee_route_set: %.*s",
-		dlg->route_set[DLG_CALLEE_LEG].len, dlg->route_set[DLG_CALLEE_LEG].s);
-	if (dlg->bind_addr[DLG_CALLEE_LEG]) {
-		rpc->rpl_printf(c, "\tcaller_bind_addr:%.*s callee_bind_addr:%.*s",
-			dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s,
-			dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len, dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s);
-	} else {
-		rpc->rpl_printf(c, "\tcaller_bind_addr:%.*s callee_bind_addr:",
-			dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len, dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s);
+	if (rpc->struct_add(h, "[", "variables", &sh) < 0) goto error;
+	for(var=dlg->vars ; var ; var=var->next) {
+		rpc->array_add(sh, "{", &ssh);
+		rpc->struct_add(ssh, "S", var->key.s, &var->value);
 	}
+
 	if (with_context) {
 		rpc_cb.rpc = rpc;
-		rpc_cb.c = c;
+		rpc_cb.c = h;
 		run_dlg_callbacks( DLGCB_RPC_CONTEXT, dlg, NULL, NULL, DLG_DIR_NONE, (void *)&rpc_cb);
 	}
+
+	return;
+error:
+	LM_ERR("Failed to add item to RPC response\n");
+	return;
 }
 
 /*!
@@ -1600,23 +1613,12 @@ static void internal_rpc_profile_get_size(rpc_t *rpc, void *c, str *profile_name
 
 	profile = search_dlg_profile( profile_name );
 	if (!profile) {
-		rpc->rpl_printf(c, "Non existing profile:%.*s",
+		rpc->fault(c, 404, "Profile not found: %.*s",
 			profile_name->len, profile_name->s);
 		return;
 	}
 	size = get_profile_size(profile, value);
-	if (value) {
-		rpc->rpl_printf(c, "Profile:%.*s => profile:%.*s value:%.*s count:%u",
-			profile_name->len, profile_name->s,
-			profile->name.len, profile->name.s,
-			value->len, value->s, size);
-		return;
-	} else {
-		rpc->rpl_printf(c, "Profile:%.*s => profile:%.*s value: count:%u",
-			profile_name->len, profile_name->s,
-			profile->name.len, profile->name.s, size);
-		return;
-	}
+	rpc->add(c, "d", size);
 	return;
 }
 
@@ -1638,45 +1640,29 @@ static void internal_rpc_profile_print_dlgs(rpc_t *rpc, void *c, str *profile_na
 
 	profile = search_dlg_profile( profile_name );
 	if (!profile) {
-		rpc->rpl_printf(c, "Non existing profile:%.*s",
+		rpc->fault(c, 404, "Profile not found: %.*s",
 			profile_name->len, profile_name->s);
 		return;
 	}
 
 	/* go through the hash and print the dialogs */
-	if (profile->has_value==0 || value==NULL) {
-		/* no value */
-		lock_get( &profile->lock );
-		for ( i=0 ; i< profile->size ; i++ ) {
-			ph = profile->entries[i].first;
-			if(ph) {
-				do {
+	if (profile->has_value==0)
+		value=NULL;
+
+	lock_get( &profile->lock );
+	for ( i=0 ; i< profile->size ; i++ ) {
+		ph = profile->entries[i].first;
+		if(ph) {
+			do {
+				if (!value || (STR_EQ(*value, ph->value))) {
 					/* print dialog */
 					internal_rpc_print_dlg(rpc, c, ph->dlg, 0);
-					/* next */
-					ph=ph->next;
-				}while(ph!=profile->entries[i].first);
-			}
-			lock_release(&profile->lock);
-		}
-	} else {
-		/* check for value also */
-		lock_get( &profile->lock );
-		for ( i=0 ; i< profile->size ; i++ ) {
-			ph = profile->entries[i].first;
-			if(ph) {
-				do {
-					if ( value->len==ph->value.len &&
-						memcmp(value->s,ph->value.s,value->len)==0 ) {
-						/* print dialog */
-						internal_rpc_print_dlg(rpc, c, ph->dlg, 0);
-					}
-					/* next */
-					ph=ph->next;
-				}while(ph!=profile->entries[i].first);
-			}
-			lock_release(&profile->lock);
+				}
+				/* next */
+				ph=ph->next;
+			}while(ph!=profile->entries[i].first);
 		}
+		lock_release(&profile->lock);
 	}
 }
 
@@ -1809,13 +1795,13 @@ static void rpc_dlg_bridge(rpc_t *rpc, void *c) {
 }
 
 static rpc_export_t rpc_methods[] = {
-	{"dlg.list", rpc_print_dlgs, rpc_print_dlgs_doc, 0},
-	{"dlg.list_ctx", rpc_print_dlgs_ctx, rpc_print_dlgs_ctx_doc, 0},
+	{"dlg.list", rpc_print_dlgs, rpc_print_dlgs_doc, RET_ARRAY},
+	{"dlg.list_ctx", rpc_print_dlgs_ctx, rpc_print_dlgs_ctx_doc, RET_ARRAY},
 	{"dlg.dlg_list", rpc_print_dlg, rpc_print_dlg_doc, 0},
 	{"dlg.dlg_list_ctx", rpc_print_dlg_ctx, rpc_print_dlg_ctx_doc, 0},
 	{"dlg.end_dlg", rpc_end_dlg_entry_id, rpc_end_dlg_entry_id_doc, 0},
 	{"dlg.profile_get_size", rpc_profile_get_size, rpc_profile_get_size_doc, 0},
-	{"dlg.profile_list", rpc_profile_print_dlgs, rpc_profile_print_dlgs_doc, 0},
+	{"dlg.profile_list", rpc_profile_print_dlgs, rpc_profile_print_dlgs_doc, RET_ARRAY},
 	{"dlg.bridge_dlg", rpc_dlg_bridge, rpc_dlg_bridge_doc, 0},
 	{0, 0, 0, 0}
 };

+ 2 - 1
modules/dialog/dlg_var.c

@@ -76,13 +76,14 @@ static inline struct dlg_var *new_dlg_var(str *key, str *val)
 	var->vflags = DLG_FLAG_NEW;
 	/* set key */
 	var->key.len = key->len;
-	var->key.s = (char*)shm_malloc(var->key.len);
+	var->key.s = (char*)shm_malloc(var->key.len+1);
 	if (var->key.s==NULL) {
 		shm_free(var);			
 		LM_ERR("no more shm mem\n");
 		return NULL;
 	}
 	memcpy(var->key.s, key->s, key->len);
+	var->key.s[var->key.len] = '\0';
 	/* set value */
 	var->value.len = val->len;
 	var->value.s = (char*)shm_malloc(var->value.len);