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
... ...
@@ -2128,6 +2128,118 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
2128 2128
 }
2129 2129
 
2130 2130
 /**************************** RPC functions ******************************/
2131
+/*!
2132
+ * \brief Helper method that outputs a dialog in a file
2133
+ * \see rpc_dump_file_dlg
2134
+ * \param dlg printed dialog
2135
+ * \param output file descriptor
2136
+ * \return 0 on success, -1 on failure
2137
+ */
2138
+static inline void internal_rpc_dump_file_dlg(dlg_cell_t *dlg, FILE* dialogf)
2139
+{
2140
+	dlg_profile_link_t *pl;
2141
+	dlg_var_t *var;
2142
+	srjson_doc_t jdoc;
2143
+	srjson_t * jdoc_caller = NULL;
2144
+	srjson_t * jdoc_callee = NULL;
2145
+	srjson_t * jdoc_profiles = NULL;
2146
+	srjson_t * jdoc_variables = NULL;
2147
+
2148
+	srjson_InitDoc(&jdoc, NULL);
2149
+	jdoc.root = srjson_CreateObject(&jdoc);
2150
+	if (!jdoc.root) {
2151
+		LM_ERR("cannot create json\n");
2152
+		goto clear;
2153
+	}
2154
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "h_entry", dlg->h_entry);
2155
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "h_id", dlg->h_id);
2156
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "ref", dlg->ref);
2157
+	srjson_AddStrToObject(&jdoc, jdoc.root, "call_id", dlg->callid.s, dlg->callid.len);
2158
+	srjson_AddStrToObject(&jdoc, jdoc.root, "from_uri", dlg->from_uri.s, dlg->from_uri.len);
2159
+	srjson_AddStrToObject(&jdoc, jdoc.root, "to_uri", dlg->to_uri.s, dlg->to_uri.len);
2160
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "state", dlg->state);
2161
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "start_ts", dlg->start_ts);
2162
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "init_ts", dlg->init_ts);
2163
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "end_ts", dlg->end_ts);
2164
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "timeout", dlg->tl.timeout ? time(0) + dlg->tl.timeout - get_ticks() : 0);
2165
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "lifetime", dlg->lifetime);
2166
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "dflags", dlg->dflags);
2167
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "sflags", dlg->sflags);
2168
+	srjson_AddNumberToObject(&jdoc, jdoc.root, "iflags", dlg->iflags);
2169
+
2170
+	jdoc_caller = srjson_CreateObject(&jdoc);
2171
+	if (!jdoc_caller) {
2172
+		LM_ERR("cannot create json caller\n");
2173
+		goto clear;
2174
+	}
2175
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "tag", dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len);
2176
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "contact", dlg->contact[DLG_CALLER_LEG].s, dlg->contact[DLG_CALLER_LEG].len);
2177
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "cseq", dlg->cseq[DLG_CALLER_LEG].s, dlg->cseq[DLG_CALLER_LEG].len);
2178
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "route_set", dlg->route_set[DLG_CALLER_LEG].s, dlg->route_set[DLG_CALLER_LEG].len);
2179
+	srjson_AddStrToObject(&jdoc, jdoc_caller, "socket",
2180
+			dlg->bind_addr[DLG_CALLER_LEG] ? dlg->bind_addr[DLG_CALLER_LEG]->sock_str.s : empty_str.s,
2181
+			dlg->bind_addr[DLG_CALLER_LEG] ? dlg->bind_addr[DLG_CALLER_LEG]->sock_str.len : empty_str.len);
2182
+	srjson_AddItemToObject(&jdoc, jdoc.root, "caller", jdoc_caller);
2183
+
2184
+	jdoc_callee = srjson_CreateObject(&jdoc);
2185
+	if (!jdoc_callee) {
2186
+		LM_ERR("cannot create json callee\n");
2187
+		goto clear;
2188
+	}
2189
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "tag", dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len);
2190
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "contact", dlg->contact[DLG_CALLEE_LEG].s, dlg->contact[DLG_CALLEE_LEG].len);
2191
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "cseq", dlg->cseq[DLG_CALLEE_LEG].s, dlg->cseq[DLG_CALLEE_LEG].len);
2192
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "route_set", dlg->route_set[DLG_CALLEE_LEG].s, dlg->route_set[DLG_CALLEE_LEG].len);
2193
+	srjson_AddStrToObject(&jdoc, jdoc_callee, "socket",
2194
+			dlg->bind_addr[DLG_CALLEE_LEG] ? dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.s : empty_str.s,
2195
+			dlg->bind_addr[DLG_CALLEE_LEG] ? dlg->bind_addr[DLG_CALLEE_LEG]->sock_str.len : empty_str.len);
2196
+	srjson_AddItemToObject(&jdoc, jdoc.root, "callee", jdoc_callee);
2197
+
2198
+	// profiles section
2199
+	jdoc_profiles = srjson_CreateObject(&jdoc);
2200
+	if (!jdoc_profiles) {
2201
+		LM_ERR("cannot create json profiles\n");
2202
+		goto clear;
2203
+	}
2204
+	for (pl = dlg->profile_links ; pl && (dlg->state<DLG_STATE_DELETED) ; pl=pl->next) {
2205
+		if (pl->profile->has_value) {
2206
+			srjson_AddStrToObject(&jdoc, jdoc_profiles, pl->profile->name.s, pl->hash_linker.value.s, pl->hash_linker.value.len);
2207
+		} else {
2208
+			srjson_AddStrToObject(&jdoc, jdoc_profiles, pl->profile->name.s, empty_str.s, empty_str.len);
2209
+		}
2210
+	}
2211
+	srjson_AddItemToObject(&jdoc, jdoc.root, "profiles", jdoc_profiles);
2212
+
2213
+	// variables section
2214
+	jdoc_variables = srjson_CreateObject(&jdoc);
2215
+	if (!jdoc_variables) {
2216
+		LM_ERR("cannot create json variables\n");
2217
+		goto clear;
2218
+	}
2219
+	for (var=dlg->vars ; var && (dlg->state<DLG_STATE_DELETED) ; var=var->next) {
2220
+		srjson_AddStrToObject(&jdoc, jdoc_variables, var->key.s, var->value.s, var->value.len);
2221
+	}
2222
+	srjson_AddItemToObject(&jdoc, jdoc.root, "variables", jdoc_variables);
2223
+
2224
+	// serialize and print to file
2225
+	jdoc.buf.s = srjson_PrintUnformatted(&jdoc, jdoc.root);
2226
+	if (!jdoc.buf.s) {
2227
+		LM_ERR("unable to serialize data\n");
2228
+		goto clear;
2229
+	}
2230
+	jdoc.buf.len = strlen(jdoc.buf.s);
2231
+	LM_DBG("sending serialized data %.*s\n", jdoc.buf.len, jdoc.buf.s);
2232
+	fprintf(dialogf,"%s\n", jdoc.buf.s);
2233
+
2234
+clear:
2235
+	if (jdoc.buf.s) {
2236
+		jdoc.free_fn(jdoc.buf.s);
2237
+		jdoc.buf.s = NULL;
2238
+	}
2239
+	srjson_DestroyDoc(&jdoc);
2240
+	return;
2241
+}
2242
+
2131 2243
 /*!
2132 2244
  * \brief Helper method that outputs a dialog via the RPC interface
2133 2245
  * \see rpc_print_dlg
... ...
@@ -2208,6 +2320,38 @@ error:
2208 2320
 	return;
2209 2321
 }
2210 2322
 
2323
+/*!
2324
+ * \brief Helper function that outputs all dialogs via the RPC interface
2325
+ * \see rpc_dump_file_dlgs
2326
+ * \param rpc RPC node that should be filled
2327
+ * \param c RPC void pointer
2328
+ * \param with_context if 1 then the dialog context will be also printed
2329
+ */
2330
+static void internal_rpc_dump_file_dlgs(rpc_t *rpc, void *c, int with_context)
2331
+{
2332
+	dlg_cell_t *dlg;
2333
+	str output_file_name;
2334
+	FILE* dialogf;
2335
+	unsigned int i;
2336
+	if (rpc->scan(c, ".S", &output_file_name) < 1) return;
2337
+
2338
+	dialogf = fopen(output_file_name.s, "a+");
2339
+	if (!dialogf) {
2340
+		LM_ERR("failed to open output file: %s\n", output_file_name.s);
2341
+		return;
2342
+	}
2343
+
2344
+	for( i=0 ; i<d_table->size ; i++ ) {
2345
+		dlg_lock( d_table, &(d_table->entries[i]) );
2346
+
2347
+		for( dlg=d_table->entries[i].first ; dlg ; dlg=dlg->next ) {
2348
+			internal_rpc_dump_file_dlg(dlg, dialogf);
2349
+		}
2350
+		dlg_unlock( d_table, &(d_table->entries[i]) );
2351
+	}
2352
+	fclose(dialogf);
2353
+}
2354
+
2211 2355
 /*!
2212 2356
  * \brief Helper function that outputs all dialogs via the RPC interface
2213 2357
  * \see rpc_print_dlgs
... ...
@@ -2347,6 +2491,9 @@ static int w_dlg_set_ruri(sip_msg_t *msg, char *p1, char *p2)
2347 2491
 static const char *rpc_print_dlgs_doc[2] = {
2348 2492
 	"Print all dialogs", 0
2349 2493
 };
2494
+static const char *rpc_dump_file_dlgs_doc[2] = {
2495
+	"Print all dialogs to json file", 0
2496
+};
2350 2497
 static const char *rpc_print_dlgs_ctx_doc[2] = {
2351 2498
 	"Print all dialogs with associated context", 0
2352 2499
 };
... ...
@@ -2386,6 +2533,9 @@ static const char *rpc_dlg_is_alive_doc[2] = {
2386 2533
 static void rpc_print_dlgs(rpc_t *rpc, void *c) {
2387 2534
 	internal_rpc_print_dlgs(rpc, c, 0);
2388 2535
 }
2536
+static void rpc_dump_file_dlgs(rpc_t *rpc, void *c) {
2537
+	internal_rpc_dump_file_dlgs(rpc, c, 0);
2538
+}
2389 2539
 static void rpc_print_dlgs_ctx(rpc_t *rpc, void *c) {
2390 2540
 	internal_rpc_print_dlgs(rpc, c, 1);
2391 2541
 }
... ...
@@ -2770,6 +2920,7 @@ static void rpc_dlg_list_match_ctx(rpc_t *rpc, void *c)
2770 2920
 
2771 2921
 static rpc_export_t rpc_methods[] = {
2772 2922
 	{"dlg.list", rpc_print_dlgs, rpc_print_dlgs_doc, RET_ARRAY},
2923
+	{"dlg.dump_file", rpc_dump_file_dlgs, rpc_dump_file_dlgs_doc, 0},
2773 2924
 	{"dlg.list_ctx", rpc_print_dlgs_ctx, rpc_print_dlgs_ctx_doc, RET_ARRAY},
2774 2925
 	{"dlg.list_match", rpc_dlg_list_match, rpc_dlg_list_match_doc, RET_ARRAY},
2775 2926
 	{"dlg.list_match_ctx", rpc_dlg_list_match_ctx, rpc_dlg_list_match_ctx_doc, RET_ARRAY},
... ...
@@ -2495,6 +2495,24 @@ if(has_totag()) {
2495 2495
 		</programlisting>
2496 2496
 		</section>
2497 2497
 
2498
+		<section id="dlg.r.dump_file">
2499
+		<title>dlg.dump_file</title>
2500
+		<para>Dump all dialogs in a json file. (much faster than dlg.list)</para>
2501
+		<para>Name: <emphasis>dlg.dump_file</emphasis></para>
2502
+		<para>Parameters:</para>
2503
+		<itemizedlist>
2504
+			<listitem><para>
2505
+				<emphasis>file name</emphasis> output file name
2506
+			</para></listitem>
2507
+		</itemizedlist>
2508
+		<para>RPC Command Format:</para>
2509
+		<programlisting  format="linespecific">
2510
+...
2511
+&kamcmd; dlg.dump_file "/tmp/dlg.json"
2512
+...
2513
+		</programlisting>
2514
+		</section>
2515
+
2498 2516
 		<section id="dlg.r.dlg_list">
2499 2517
 		<title>dlg.dlg_list</title>
2500 2518
 		<para>