Browse code

dialog: adding dlg.dump

alternative command to output dialogs data to file, far much faster than
dlg.list

dialog: use core/srjson

Julien Chavanton authored on 31/03/2020 22:18:38
Showing 2 changed files
... ...
@@ -2196,6 +2196,118 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
2196 2196
 }
2197 2197
 
2198 2198
 /**************************** RPC functions ******************************/
2199
+/*!
2200
+ * \brief Helper method that outputs a dialog in a file
2201
+ * \see rpc_dump_file_dlg
2202
+ * \param dlg printed dialog
2203
+ * \param output file descriptor
2204
+ * \return 0 on success, -1 on failure
2205
+ */
2206
+static inline void internal_rpc_dump_file_dlg(dlg_cell_t *dlg, FILE* dialogf)
2207
+{
2208
+	dlg_profile_link_t *pl;
2209
+	dlg_var_t *var;
2210
+	srjson_doc_t jdoc;
2211
+	srjson_t * jdoc_caller = NULL;
2212
+	srjson_t * jdoc_callee = NULL;
2213
+	srjson_t * jdoc_profiles = NULL;
2214
+	srjson_t * jdoc_variables = NULL;
2215
+
2216
+	srjson_InitDoc(&jdoc, NULL);
2217
+	jdoc.root = srjson_CreateObject(&jdoc);
2218
+	if (!jdoc.root) {
2219
+		LM_ERR("cannot create json\n");
2220
+		goto clear;
2221
+	}
2222
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "h_entry", dlg->h_entry);
2223
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "h_id", dlg->h_id);
2224
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "ref", dlg->ref);
2225
+	srjson_AddStrToObject(&jdoc, jdoc.root, "call_id", dlg->callid.s, dlg->callid.len);
2226
+	srjson_AddStrToObject(&jdoc, jdoc.root, "from_uri", dlg->from_uri.s, dlg->from_uri.len);
2227
+	srjson_AddStrToObject(&jdoc, jdoc.root, "to_uri", dlg->to_uri.s, dlg->to_uri.len);
2228
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "state", dlg->state);
2229
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "start_ts", dlg->start_ts);
2230
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "init_ts", dlg->init_ts);
2231
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "end_ts", dlg->end_ts);
2232
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "timeout", dlg->tl.timeout ? time(0) + dlg->tl.timeout - get_ticks() : 0);
2233
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "lifetime", dlg->lifetime);
2234
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "dflags", dlg->dflags);
2235
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "sflags", dlg->sflags);
2236
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "iflags", dlg->iflags);
2237
+
2238
+	jdoc_caller = srjson_CreateObject(&jdoc);
2239
+	if (!jdoc_caller) {
2240
+		LM_ERR("cannot create json caller\n");
2241
+		goto clear;
2242
+	}
2243
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "tag", dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
2244
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "contact", dlg->contact[DLG_CALLER_LEG].s, dlg->contact[DLG_CALLER_LEG].len);
2245
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "cseq", dlg->cseq[DLG_CALLER_LEG].s, dlg->cseq[DLG_CALLER_LEG].len);
2246
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "route_set", dlg->route_set[DLG_CALLER_LEG].s, dlg->route_set[DLG_CALLER_LEG].len);
2247
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "socket",
2248
+			dlg->bind_addr[DLG_CALLER_LEG] ? dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s : empty_str.s,
2249
+			dlg->bind_addr[DLG_CALLER_LEG] ? dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len : empty_str.len);
2250
+	srjson_AddItemToObject(&jdoc, jdoc.root, "caller", jdoc_caller);
2251
+
2252
+	jdoc_callee = srjson_CreateObject(&jdoc);
2253
+	if (!jdoc_callee) {
2254
+		LM_ERR("cannot create json callee\n");
2255
+		goto clear;
2256
+	}
2257
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "tag", dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
2258
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "contact", dlg->contact[DLG_CALLEE_LEG].s, dlg->contact[DLG_CALLEE_LEG].len);
2259
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "cseq", dlg->cseq[DLG_CALLEE_LEG].s, dlg->cseq[DLG_CALLEE_LEG].len);
2260
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "route_set", dlg->route_set[DLG_CALLEE_LEG].s, dlg->route_set[DLG_CALLEE_LEG].len);
2261
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "socket",
2262
+			dlg->bind_addr[DLG_CALLEE_LEG] ? dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s : empty_str.s,
2263
+			dlg->bind_addr[DLG_CALLEE_LEG] ? dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len : empty_str.len);
2264
+	srjson_AddItemToObject(&jdoc, jdoc.root, "callee", jdoc_callee);
2265
+
2266
+	// profiles section
2267
+	jdoc_profiles = srjson_CreateObject(&jdoc);
2268
+	if (!jdoc_profiles) {
2269
+		LM_ERR("cannot create json profiles\n");
2270
+		goto clear;
2271
+	}
2272
+	for (pl = dlg->profile_links ; pl && (dlg->state<DLG_STATE_DELETED) ; pl=pl->next) {
2273
+		if (pl->profile->has_value) {
2274
+			srjson_AddStrToObject(&jdoc, jdoc_profiles, pl->profile->name.s, pl->hash_linker.value.s, pl->hash_linker.value.len);
2275
+		} else {
2276
+			srjson_AddStrToObject(&jdoc, jdoc_profiles, pl->profile->name.s, empty_str.s, empty_str.len);
2277
+		}
2278
+	}
2279
+	srjson_AddItemToObject(&jdoc, jdoc.root, "profiles", jdoc_profiles);
2280
+
2281
+	// variables section
2282
+	jdoc_variables = srjson_CreateObject(&jdoc);
2283
+	if (!jdoc_variables) {
2284
+		LM_ERR("cannot create json variables\n");
2285
+		goto clear;
2286
+	}
2287
+	for (var=dlg->vars ; var && (dlg->state<DLG_STATE_DELETED) ; var=var->next) {
2288
+		srjson_AddStrToObject(&jdoc, jdoc_variables, var->key.s, var->value.s, var->value.len);
2289
+	}
2290
+	srjson_AddItemToObject(&jdoc, jdoc.root, "variables", jdoc_variables);
2291
+
2292
+	// serialize and print to file
2293
+	jdoc.buf.s = srjson_PrintUnformatted(&jdoc, jdoc.root);
2294
+	if (!jdoc.buf.s) {
2295
+		LM_ERR("unable to serialize data\n");
2296
+		goto clear;
2297
+	}
2298
+	jdoc.buf.len = strlen(jdoc.buf.s);
2299
+	LM_DBG("sending serialized data %.*s\n", jdoc.buf.len, jdoc.buf.s);
2300
+	fprintf(dialogf,"%s\n", jdoc.buf.s);
2301
+
2302
+clear:
2303
+	if (jdoc.buf.s) {
2304
+		jdoc.free_fn(jdoc.buf.s);
2305
+		jdoc.buf.s = NULL;
2306
+	}
2307
+	srjson_DestroyDoc(&jdoc);
2308
+	return;
2309
+}
2310
+
2199 2311
 /*!
2200 2312
  * \brief Helper method that outputs a dialog via the RPC interface
2201 2313
  * \see rpc_print_dlg
... ...
@@ -2276,6 +2388,38 @@ error:
2276 2388
 	return;
2277 2389
 }
2278 2390
 
2391
+/*!
2392
+ * \brief Helper function that outputs all dialogs via the RPC interface
2393
+ * \see rpc_dump_file_dlgs
2394
+ * \param rpc RPC node that should be filled
2395
+ * \param c RPC void pointer
2396
+ * \param with_context if 1 then the dialog context will be also printed
2397
+ */
2398
+static void internal_rpc_dump_file_dlgs(rpc_t *rpc, void *c, int with_context)
2399
+{
2400
+	dlg_cell_t *dlg;
2401
+	str output_file_name;
2402
+	FILE* dialogf;
2403
+	unsigned int i;
2404
+	if (rpc->scan(c, ".S", &output_file_name) < 1) return;
2405
+
2406
+	dialogf = fopen(output_file_name.s, "a+");
2407
+	if (!dialogf) {
2408
+		LM_ERR("failed to open output file: %s\n", output_file_name.s);
2409
+		return;
2410
+	}
2411
+
2412
+	for( i=0 ; i<d_table->size ; i++ ) {
2413
+		dlg_lock( d_table, &(d_table->entries[i]) );
2414
+
2415
+		for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
2416
+			internal_rpc_dump_file_dlg(dlg, dialogf);
2417
+		}
2418
+		dlg_unlock( d_table, &(d_table->entries[i]) );
2419
+	}
2420
+	fclose(dialogf);
2421
+}
2422
+
2279 2423
 /*!
2280 2424
  * \brief Helper function that outputs all dialogs via the RPC interface
2281 2425
  * \see rpc_print_dlgs
... ...
@@ -2415,6 +2559,9 @@ static int w_dlg_set_ruri(sip_msg_t *msg, char *p1, char *p2)
2415 2559
 static const char *rpc_print_dlgs_doc[2] = {
2416 2560
 	"Print all dialogs", 0
2417 2561
 };
2562
+static const char *rpc_dump_file_dlgs_doc[2] = {
2563
+	"Print all dialogs to json file", 0
2564
+};
2418 2565
 static const char *rpc_print_dlgs_ctx_doc[2] = {
2419 2566
 	"Print all dialogs with associated context", 0
2420 2567
 };
... ...
@@ -2459,6 +2606,9 @@ static const char *rpc_dlg_is_alive_doc[2] = {
2459 2606
 static void rpc_print_dlgs(rpc_t *rpc, void *c) {
2460 2607
 	internal_rpc_print_dlgs(rpc, c, 0);
2461 2608
 }
2609
+static void rpc_dump_file_dlgs(rpc_t *rpc, void *c) {
2610
+	internal_rpc_dump_file_dlgs(rpc, c, 0);
2611
+}
2462 2612
 static void rpc_print_dlgs_ctx(rpc_t *rpc, void *c) {
2463 2613
 	internal_rpc_print_dlgs(rpc, c, 1);
2464 2614
 }
... ...
@@ -2946,6 +3096,7 @@ static void rpc_dlg_briefing(rpc_t *rpc, void *c)
2946 3096
 static rpc_export_t rpc_methods[] = {
2947 3097
 	{"dlg.briefing", rpc_dlg_briefing, rpc_dlg_briefing_doc, RET_ARRAY},
2948 3098
 	{"dlg.list", rpc_print_dlgs, rpc_print_dlgs_doc, RET_ARRAY},
3099
+	{"dlg.dump_file", rpc_dump_file_dlgs, rpc_dump_file_dlgs_doc, 0},
2949 3100
 	{"dlg.list_ctx", rpc_print_dlgs_ctx, rpc_print_dlgs_ctx_doc, RET_ARRAY},
2950 3101
 	{"dlg.list_match", rpc_dlg_list_match, rpc_dlg_list_match_doc, RET_ARRAY},
2951 3102
 	{"dlg.list_match_ctx", rpc_dlg_list_match_ctx, rpc_dlg_list_match_ctx_doc, RET_ARRAY},
... ...
@@ -2537,6 +2537,24 @@ dlg_reset_property("timeout-noreset");
2537 2537
 		</programlisting>
2538 2538
 		</section>
2539 2539
 
2540
+		<section id="dlg.r.dump_file">
2541
+		<title>dlg.dump_file</title>
2542
+		<para>Dump all dialogs in a json file. (much faster than dlg.list)</para>
2543
+		<para>Name: <emphasis>dlg.dump_file</emphasis></para>
2544
+		<para>Parameters:</para>
2545
+		<itemizedlist>
2546
+			<listitem><para>
2547
+				<emphasis>file name</emphasis> output file name
2548
+			</para></listitem>
2549
+		</itemizedlist>
2550
+		<para>RPC Command Format:</para>
2551
+		<programlisting  format="linespecific">
2552
+...
2553
+&kamcmd; dlg.dump_file "/tmp/dlg.json"
2554
+...
2555
+		</programlisting>
2556
+		</section>
2557
+
2540 2558
 		<section id="dlg.r.dlg_list">
2541 2559
 		<title>dlg.dlg_list</title>
2542 2560
 		<para>