Review Board 1.7.16


res_pjsip_history: A debugging module for busy systems

Review Request #4053 - Created Oct. 8, 2014 and updated

Matt Jordan
trunk
Reviewers
asterisk-dev
Asterisk
While debugging things at SIPit, I found that the capabilities afforded by res_pjsip_logger to be inadequate for tracing SIP messages on the CLI. Often, so many requests/responses were received -- often with very large SDPs -- in a short period of time that after a single call scenario, the initial requests/responses had already been expunged from the CLI buffer. Furthermore, displaying every single SIP request/response was often counterproductive - OPTIONS, SUBSCRIBE, and even REGISTER requests were often interleaved in the call scenarios, making it difficult to find or trace portions of a call.

This isn't the fault of res_pjsip_logger: it was doing exactly what it was designed to do. And res_pjsip_logger is absolutely necessary for getting full logs when a problem occurs. However, it isn't designed for debugging things on the CLI. Hence, this module.

res_pjsip_history records every request/response received/transmitted through the PJSIP stack, but does not bother dumping them to the CLI. Instead, it provides a few CLI comamnds to access the recorded messages:

* pjsip set history {on|off} - enable/disable the history
* pjsip show history [min [max]] - display the entire history, or segments of the history.
* pjsip show entry {num} - display a particular history entry

Because we store all received/transmitted requests/responses, the module is only suitable for debugging purposes. Leaving it permanently odd is a bad idea, for obvious reasons. When the history is turned off, all messages are purged and the history reset.

As an example, we can record some history and display all of the messages:

*CLI> pjsip show history
No.  Timestamp      Rx/Tx Address        Call-ID              SIP Message
==== ============== ==================== ==================== ============
0000 1412775534.791 RX: 127.0.0.1:22428  d56324c8f042034aae29 OPTIONS sip:127.0.0.1 SIP/2.0
0001 1412775534.792 TX: 127.0.0.1:22428  d56324c8f042034aae29 SIP/2.0 200 OK
0002 1412775540.277 RX: 127.0.0.1:22428  86cd74e458e76b79e267 OPTIONS sip:127.0.0.1 SIP/2.0
0003 1412775540.277 TX: 127.0.0.1:22428  86cd74e458e76b79e267 SIP/2.0 200 OK
0004 1412775541.763 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc INVITE sip:200@127.0.0.1 SIP/2.0
0005 1412775541.765 TX: 127.0.0.1:22428  f4c0050f5b604fc52ecc SIP/2.0 200 OK
0006 1412775541.766 TX: 127.0.0.1:22428  f4c0050f5b604fc52ecc SIP/2.0 200 OK
0007 1412775541.780 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc ACK sip:127.0.0.1:5060 SIP/2.0
0008 1412775543.767 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc BYE sip:127.0.0.1:5060 SIP/2.0
0009 1412775543.768 TX: 127.0.0.1:22428  f4c0050f5b604fc52ecc SIP/2.0 200 OK
0010 1412775547.823 RX: 127.0.0.1:22428  ab6fc9f37aa1dc5ed038 SUBSCRIBE sip:1000@127.0.0.1 SIP/2.0
0011 1412775547.824 TX: 127.0.0.1:22428  ab6fc9f37aa1dc5ed038 SIP/2.0 481 Call/Transaction Does Not Exist
0012 1412775547.826 RX: 127.0.0.1:22428  ba4ed4625cbb3282b34c REGISTER sip:127.0.0.1 SIP/2.0
0013 1412775547.841 TX: 127.0.0.1:22428  ba4ed4625cbb3282b34c SIP/2.0 200 OK
0014 1412775549.854 RX: 127.0.0.1:34899  ca022bf6e5a31b306bfd REGISTER sip:127.0.0.1 SIP/2.0
0015 1412775549.870 TX: 127.0.0.1:34899  ca022bf6e5a31b306bfd SIP/2.0 200 OK
0016 1412775549.876 RX: 127.0.0.1:34899  d92c91d540a36d2cbca1 SUBSCRIBE sip:1000@127.0.0.1 SIP/2.0
0017 1412775549.876 TX: 127.0.0.1:34899  d92c91d540a36d2cbca1 SIP/2.0 200 OK
0018 1412775549.877 TX: 127.0.0.1:34899  d92c91d540a36d2cbca1 NOTIFY sip:1000@127.0.0.1:34899;transport=udp;registering_acc=127_0_0_1 SIP/2.0
0019 1412775549.877 RX: 127.0.0.1:34899  32cca4f61cbba6cbe47f OPTIONS sip:127.0.0.1 SIP/2.0
0020 1412775549.877 TX: 127.0.0.1:34899  32cca4f61cbba6cbe47f SIP/2.0 200 OK
0021 1412775549.889 RX: 127.0.0.1:34899  d92c91d540a36d2cbca1 SIP/2.0 200 OK
0022 1412775555.376 RX: 127.0.0.1:34899  f65c7ea06475be757d2c INVITE sip:1000@127.0.0.1 SIP/2.0
0023 1412775555.377 TX: 127.0.0.1:34899  f65c7ea06475be757d2c SIP/2.0 487 Request Terminated
0024 1412775555.382 TX: 127.0.0.1:34899  6ddb9f94-9c20-4f83-8 INVITE sip:1000@127.0.0.1:34899;transport=udp;registering_acc=127_0_0_1 SIP/2.0
0025 1412775555.383 TX: 127.0.0.1:34899  f65c7ea06475be757d2c SIP/2.0 487 Request Terminated
0026 1412775560.135 RX: 127.0.0.1:34899  f65c7ea06475be757d2c CANCEL sip:1000@127.0.0.1 SIP/2.0
0027 1412775560.135 TX: 127.0.0.1:34899  f65c7ea06475be757d2c SIP/2.0 200 OK
0028 1412775560.135 TX: 127.0.0.1:34899  f65c7ea06475be757d2c SIP/2.0 487 Request Terminated
0029 1412775560.146 RX: 127.0.0.1:34899  f65c7ea06475be757d2c ACK sip:1000@127.0.0.1 SIP/2.0

Alternatively, we can display on a subset of the messages:

*CLI> pjsip show history 4 9
No.  Timestamp      Rx/Tx Address        Call-ID              SIP Message
==== ============== ==================== ==================== ============
0004 1412775541.763 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc INVITE sip:200@127.0.0.1 SIP/2.0
0005 1412775541.765 TX: 127.0.0.1:22428  f4c0050f5b604fc52ecc SIP/2.0 200 OK
0006 1412775541.766 TX: 127.0.0.1:22428  f4c0050f5b604fc52ecc SIP/2.0 200 OK
0007 1412775541.780 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc ACK sip:127.0.0.1:5060 SIP/2.0
0008 1412775543.767 RX: 127.0.0.1:22428  f4c0050f5b604fc52ecc BYE sip:127.0.0.1:5060 SIP/2.0
*CLI> 

We can narrow down things further by displaying only a specific entry in the history:

*CLI> pjsip show entry 4
INVITE sip:200@127.0.0.1 SIP/2.0
Call-ID: f4c0050f5b604fc52ecca628a9393d3f@0:0:0:0:0:0:0:0
CSeq: 1 INVITE
From: "1000" <sip:1000@127.0.0.1>;tag=aece8db8
To: <sip:200@127.0.0.1>
Via: SIP/2.0/UDP 127.0.0.1:22428;branch=z9hG4bK-3833-5f28322b65a22d22475a18c1b3cb8260
Max-Forwards: 70
Contact: "1000" <sip:1000@127.0.0.1:22428;transport=udp;registering_acc=127_0_0_1>
User-Agent: Jitsi2.4.4997Linux
Content-Type: application/sdp
Content-Length: 783

v=0
o=1000 0 0 IN IP4 127.0.0.1
s=-
c=IN IP4 127.0.0.1
t=0 0
m=audio 5012 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101
a=rtpmap:96 opus/48000/2
a=fmtp:96 usedtx=1
a=rtpmap:97 SILK/24000
a=rtpmap:98 SILK/16000
a=rtpmap:9 G722/8000
a=rtpmap:100 speex/32000
a=rtpmap:102 speex/16000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:103 iLBC/8000
a=rtpmap:3 GSM/8000
a=rtpmap:104 speex/8000
a=rtpmap:101 telephone-event/8000
a=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level
m=video 5014 RTP/AVP 105 99
a=recvonly
a=rtpmap:105 H264/90000
a=fmtp:105 profile-level-id=4DE01f;packetization-mode=1
a=imageattr:105 send * recv [x=[0-1360],y=[0-768]]
a=rtpmap:99 H264/90000
a=fmtp:99 profile-level-id=4DE01f
a=imageattr:99 send * recv [x=[0-1360],y=[0-768]]

*CLI> 


Because we cache the actual PJSIP tdata/rdata structures, this module could be taken further in the future by adding filtering mechanisms. Ideally, someone could filter the history on particular call-ids, message types, etc. However, at the sake of having something (and not going too crazy with this on an initial patch), the initial functionality provided in this module should be fairly useful.

 

Diff revision 1 (Latest)

  1. /trunk/res/res_pjsip_history.c: Loading...
/trunk/res/res_pjsip_history.c
New File

    
   
1
/*

    
   
2
 * Asterisk -- An open source telephony toolkit.

    
   
3
 *

    
   
4
 * Copyright (C) 2014, Digium, Inc.

    
   
5
 *

    
   
6
 * Matt Jordan <mjordan@digium.com>

    
   
7
 *

    
   
8
 * See http://www.asterisk.org for more information about

    
   
9
 * the Asterisk project. Please do not directly contact

    
   
10
 * any of the maintainers of this project for assistance;

    
   
11
 * the project provides a web site, mailing lists and IRC

    
   
12
 * channels for your use.

    
   
13
 *

    
   
14
 * This program is free software, distributed under the terms of

    
   
15
 * the GNU General Public License Version 2. See the LICENSE file

    
   
16
 * at the top of the source tree.

    
   
17
 */

    
   
18

   

    
   
19
/*** MODULEINFO

    
   
20
	<depend>pjproject</depend>

    
   
21
	<depend>res_pjsip</depend>

    
   
22
	<defaultenabled>yes</defaultenabled>

    
   
23
	<support_level>core</support_level>

    
   
24
 ***/

    
   
25

   

    
   
26
#include "asterisk.h"

    
   
27

   

    
   
28
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")

    
   
29

   

    
   
30
#include <pjsip.h>

    
   
31

   

    
   
32
#include "asterisk/res_pjsip.h"

    
   
33
#include "asterisk/module.h"

    
   
34
#include "asterisk/logger.h"

    
   
35
#include "asterisk/cli.h"

    
   
36
#include "asterisk/netsock2.h"

    
   
37
#include "asterisk/vector.h"

    
   
38
#include "asterisk/lock.h"

    
   
39

   

    
   
40
/*! \brief An entry in the PJSIP history */

    
   
41
struct pjsip_history_entry {

    
   
42
	/*! When the history entry was made */

    
   
43
	struct timeval timestamp;

    
   
44
	/*! Transmitted request/response */

    
   
45
	pjsip_tx_data *tdata;

    
   
46
	/*! Received request/response */

    
   
47
	pjsip_rx_data *rdata;

    
   
48
};

    
   
49

   

    
   
50
/*! \brief Mutex that protects \ref vector_history and \ref enabled */

    
   
51
AST_MUTEX_DEFINE_STATIC(history_lock);

    
   
52

   

    
   
53
/*! \brief The vector of \ref pjsip_history_entry entries */

    
   
54
static AST_VECTOR(, struct pjsip_history_entry *) vector_history;

    
   
55

   

    
   
56
/*! \brief Whether or not the history is enabled */

    
   
57
static int enabled;

    
   
58

   

    
   
59
static void pjsip_history_entry_dtor(void *obj)

    
   
60
{

    
   
61
	struct pjsip_history_entry *entry = obj;

    
   
62

   

    
   
63
	if (entry->tdata) {

    
   
64
		pjsip_tx_data_dec_ref(entry->tdata);

    
   
65
	}

    
   
66
	if (entry->rdata) {

    
   
67
		pjsip_rx_data_free_cloned(entry->rdata);

    
   
68
	}

    
   
69
}

    
   
70

   

    
   
71
static struct pjsip_history_entry *pjsip_history_entry_alloc(void)

    
   
72
{

    
   
73
	struct pjsip_history_entry *entry;

    
   
74

   

    
   
75
	entry = ao2_alloc(sizeof(*entry), pjsip_history_entry_dtor);

    
   
76
	if (!entry) {

    
   
77
		return NULL;

    
   
78
	}

    
   
79
	entry->timestamp = ast_tvnow();

    
   
80

   

    
   
81
	return entry;

    
   
82
}

    
   
83

   

    
   
84
static pj_status_t history_on_tx_msg(pjsip_tx_data *tdata)

    
   
85
{

    
   
86
	struct pjsip_history_entry *entry;

    
   
87
	SCOPED_MUTEX(lock, &history_lock);

    
   
88

   

    
   
89
	if (!enabled) {

    
   
90
		return PJ_SUCCESS;

    
   
91
	}

    
   
92

   

    
   
93
	entry = pjsip_history_entry_alloc();

    
   
94
	if (!entry) {

    
   
95
		return PJ_SUCCESS;

    
   
96
	}

    
   
97
	pjsip_tx_data_add_ref(tdata);

    
   
98
	entry->tdata = tdata;

    
   
99

   

    
   
100
	AST_VECTOR_APPEND(&vector_history, entry);

    
   
101

   

    
   
102
	return PJ_SUCCESS;

    
   
103
}

    
   
104

   

    
   
105
static pj_bool_t history_on_rx_msg(pjsip_rx_data *rdata)

    
   
106
{

    
   
107
	struct pjsip_history_entry *entry;

    
   
108
	SCOPED_MUTEX(lock, &history_lock);

    
   
109

   

    
   
110
	if (!enabled) {

    
   
111
		return PJ_FALSE;

    
   
112
	}

    
   
113

   

    
   
114
	if (!rdata->msg_info.msg) {

    
   
115
		return PJ_FALSE;

    
   
116
	}

    
   
117

   

    
   
118
	entry = pjsip_history_entry_alloc();

    
   
119
	if (!entry) {

    
   
120
		return PJ_FALSE;

    
   
121
	}

    
   
122
	pjsip_rx_data_clone(rdata, 0, &entry->rdata);

    
   
123

   

    
   
124
	AST_VECTOR_APPEND(&vector_history, entry);

    
   
125

   

    
   
126
	return PJ_FALSE;

    
   
127
}

    
   
128

   

    
   
129
static pjsip_module history_module = {

    
   
130
	.name = { "History Module", 14 },

    
   
131
	.priority = 0,

    
   
132
	.on_rx_request = history_on_rx_msg,

    
   
133
	.on_rx_response = history_on_rx_msg,

    
   
134
	.on_tx_request = history_on_tx_msg,

    
   
135
	.on_tx_response = history_on_tx_msg,

    
   
136
};

    
   
137

   

    
   
138
static char *pjsip_show_entry(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

    
   
139
{

    
   
140
	int entry_index;

    
   
141
	struct pjsip_history_entry *entry;

    
   
142

   

    
   
143
	if (cmd == CLI_INIT) {

    
   
144
		e->command = "pjsip show entry";

    
   
145
		e->usage =

    
   
146
			"Usage: pjsip show entry {num}\n"

    
   
147
			"       Display a full transmitted or received request/response\n"

    
   
148
			"       from the history.\n";

    
   
149
		return NULL;

    
   
150
	} else if (cmd == CLI_GENERATE) {

    
   
151
		return NULL;

    
   
152
	}

    
   
153

   

    
   
154
	if (a->argc != 4) {

    
   
155
		return CLI_SHOWUSAGE;

    
   
156
	}

    
   
157

   

    
   
158
	{

    
   
159
		SCOPED_MUTEX(lock, &history_lock);

    
   
160

   

    
   
161
		if (!enabled) {

    
   
162
			ast_cli(a->fd, "PJSIP History not enabled.\n");

    
   
163
			return CLI_SUCCESS;

    
   
164
		}

    
   
165

   

    
   
166
		if (!AST_VECTOR_SIZE(&vector_history)) {

    
   
167
			ast_cli(a->fd, "No entries in PJSIP History!\n");

    
   
168
			return CLI_SUCCESS;

    
   
169
		}

    
   
170

   

    
   
171
		sscanf(a->argv[3], "%30d", &entry_index);

    
   
172
		if (entry_index < 0 || entry_index > AST_VECTOR_SIZE(&vector_history)) {

    
   
173
			ast_cli(a->fd, "Entry '%d' not in PJSIP History\n", entry_index);

    
   
174
			return CLI_SUCCESS;

    
   
175
		}

    
   
176

   

    
   
177
		entry = AST_VECTOR_GET(&vector_history, entry_index);

    
   
178

   

    
   
179
		if (entry->rdata) {

    
   
180
			ast_cli(a->fd, "%s\n", entry->rdata->pkt_info.packet);

    
   
181
		} else {

    
   
182
			ast_cli(a->fd, "%.*s\n",

    
   
183
				(int)(entry->tdata->buf.end - entry->tdata->buf.start),

    
   
184
				entry->tdata->buf.start);

    
   
185
		}

    
   
186
	}

    
   
187

   

    
   
188
	return CLI_SUCCESS;

    
   
189
}

    
   
190

   

    
   
191
static char *pjsip_show_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

    
   
192
{

    
   
193
	char address[128];

    
   
194
	int min;

    
   
195
	int max;

    
   
196
	int i;

    
   
197

   

    
   
198
	if (cmd == CLI_INIT) {

    
   
199
		e->command = "pjsip show history";

    
   
200
		e->usage =

    
   
201
		    "Usage: pjsip show history [min [max]]\n"

    
   
202
		    "       Display the history entries collected. Optionally, if [min]\n"

    
   
203
		    "       is specified, start displaying entries at that point. If\n"

    
   
204
		    "       [max] is also specified, display received entries up to\n"

    
   
205
		    "       that point.\n";

    
   
206
		return NULL;

    
   
207
	} else if (cmd == CLI_GENERATE) {

    
   
208
		if (a->n < a->pos && (a->pos == 3 || a->pos == 4)) {

    
   
209
			char *str_max;

    
   
210
			int vec_min;

    
   
211
			size_t vec_size;

    
   
212

   

    
   
213
			ast_mutex_lock(&history_lock);

    
   
214
			vec_size = AST_VECTOR_SIZE(&vector_history);

    
   
215
			ast_mutex_unlock(&history_lock);

    
   
216

   

    
   
217
			if (vec_size) {

    
   
218
				vec_min = vec_size - 1;

    
   
219
			} else {

    
   
220
				vec_min = vec_size;

    
   
221
			}

    
   
222
			ast_asprintf(&str_max, "%zu", a->pos == 3 ? vec_min : vec_size);

    
   
223
			return str_max;

    
   
224
		}

    
   
225
		return NULL;

    
   
226
	}

    
   
227

   

    
   
228
	if (a->argc < 3 || a->argc > 5) {

    
   
229
		return CLI_SHOWUSAGE;

    
   
230
	}

    
   
231

   

    
   
232
	ast_mutex_lock(&history_lock);

    
   
233

   

    
   
234
	if (!enabled) {

    
   
235
		ast_mutex_unlock(&history_lock);

    
   
236
		ast_cli(a->fd, "PJSIP History not enabled.\n");

    
   
237
		return CLI_SUCCESS;

    
   
238
	}

    
   
239

   

    
   
240
	min = 0;

    
   
241
	max = AST_VECTOR_SIZE(&vector_history);

    
   
242
	if (a->argc > 3) {

    
   
243
		sscanf(a->argv[3], "%30d", &min);

    
   
244
	}

    
   
245
	if (a->argc > 4) {

    
   
246
		sscanf(a->argv[4], "%30d", &max);

    
   
247
	}

    
   
248

   

    
   
249
	ast_cli(a->fd, "%-4.4s %-14.14s %-20.20s %-20.20s %s\n",

    
   
250
		"No.",

    
   
251
		"Timestamp",

    
   
252
		"Rx/Tx Address",

    
   
253
		"Call-ID",

    
   
254
		"SIP Message");

    
   
255
	ast_cli(a->fd, "==== ============== ==================== ==================== ============\n");

    
   
256
	for (i = min; i < max; i++) {

    
   
257
		struct pjsip_history_entry *entry = AST_VECTOR_GET(&vector_history, i);

    
   
258
		char *call_id;

    
   
259
		const pj_str_t *cid_str;

    
   
260

   

    
   
261
		if (entry->tdata) {

    
   
262
			pjsip_cid_hdr *cid_hdr;

    
   
263

   

    
   
264
			cid_hdr = PJSIP_MSG_CID_HDR(entry->tdata->msg);

    
   
265
			cid_str = &cid_hdr->id;

    
   
266
			pj_sockaddr_print(&entry->tdata->tp_info.dst_addr,

    
   
267
			                  address, sizeof(address), 3);

    
   
268
		} else {

    
   
269

   

    
   
270
			cid_str = &entry->rdata->msg_info.cid->id;

    
   
271
			if (entry->rdata->pkt_info.src_addr_len) {

    
   
272
				pj_sockaddr_print(&entry->rdata->pkt_info.src_addr,

    
   
273
				                  address, sizeof(address), 3);

    
   
274
			} else {

    
   
275
				strcpy(address, "[Unknown]");

    
   
276
			}

    
   
277
		}

    
   
278

   

    
   
279
		call_id = ast_malloc(pj_strlen(cid_str) + 1);

    
   
280
		if (!call_id) {

    
   
281
			return CLI_FAILURE;

    
   
282
		}

    
   
283
		ast_copy_pj_str(call_id, cid_str, pj_strlen(cid_str) + 1);

    
   
284

   

    
   
285
		ast_cli(a->fd, "%-4.04d %-10.10ld.%-3.3ld %s %-16.16s %-20.20s %.*s\n",

    
   
286
			i,

    
   
287
			entry->timestamp.tv_sec,

    
   
288
			entry->timestamp.tv_usec / 1000,

    
   
289
			entry->rdata ? "RX:" : "TX:",

    
   
290
			address,

    
   
291
			call_id,

    
   
292
			entry->rdata ? (int)(strchr(entry->rdata->pkt_info.packet, '\n')

    
   
293
			                            - entry->rdata->pkt_info.packet)

    
   
294
			             : (int)(strchr(entry->tdata->buf.start, '\n')

    
   
295
			                            - entry->tdata->buf.start),

    
   
296
			entry->rdata ? entry->rdata->pkt_info.packet

    
   
297
			             : entry->tdata->buf.start);

    
   
298

   

    
   
299
		ast_free(call_id);

    
   
300
	}

    
   
301
	ast_mutex_unlock(&history_lock);

    
   
302

   

    
   
303
	return CLI_SUCCESS;

    
   
304
}

    
   
305

   

    
   
306
static void enable_history(void)

    
   
307
{

    
   
308
	ast_mutex_lock(&history_lock);

    
   
309
	if (!enabled) {

    
   
310
		AST_VECTOR_INIT(&vector_history, 256);

    
   
311
		enabled = 1;

    
   
312
	}

    
   
313
	ast_mutex_unlock(&history_lock);

    
   
314
}

    
   
315

   

    
   
316
static void disable_history(void)

    
   
317
{

    
   
318
	int i;

    
   
319

   

    
   
320
	ast_mutex_lock(&history_lock);

    
   
321
	if (enabled) {

    
   
322
		enabled = 0;

    
   
323

   

    
   
324
		for (i = 0; i < AST_VECTOR_SIZE(&vector_history); i++) {

    
   
325
			ao2_ref(AST_VECTOR_GET(&vector_history, i), -1);

    
   
326
		}

    
   
327
		AST_VECTOR_FREE(&vector_history);

    
   
328
	}

    
   
329
	ast_mutex_unlock(&history_lock);

    
   
330
}

    
   
331

   

    
   
332
static char *pjsip_set_history(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

    
   
333
{

    
   
334
	const char *what;

    
   
335

   

    
   
336
	if (cmd == CLI_INIT) {

    
   
337
		e->command = "pjsip set history {on|off}";

    
   
338
		e->usage =

    
   
339
			"Usage: pjsip set history {on|off}\n"

    
   
340
			"       Enable or disable the PJSIP history. As the PJSIP history\n"

    
   
341
			"       maintains all received and transmitted requests/responses,\n"

    
   
342
			"       this command should only be used for debugging purposes.\n"

    
   
343
			"       Note:\n"

    
   
344
			"         The history buffer is reset whenever the PJSIP history\n"

    
   
345
			"         is disabled.\n";

    
   
346
		return NULL;

    
   
347
	} else if (cmd == CLI_GENERATE) {

    
   
348
		return NULL;

    
   
349
	}

    
   
350

   

    
   
351
	what = a->argv[e->args - 1];     /* Guaranteed to exist */

    
   
352

   

    
   
353
	if (a->argc == e->args) {

    
   
354
		if (!strcasecmp(what, "on")) {

    
   
355
			enable_history();

    
   
356
			ast_cli(a->fd, "PJSIP History enabled\n");

    
   
357
			return CLI_SUCCESS;

    
   
358
		} else if (!strcasecmp(what, "off")) {

    
   
359
			disable_history();

    
   
360
			ast_cli(a->fd, "PJSIP History disabled\n");

    
   
361
			return CLI_SUCCESS;

    
   
362
		}

    
   
363
	}

    
   
364

   

    
   
365
	return CLI_SHOWUSAGE;

    
   
366
}

    
   
367

   

    
   
368
static struct ast_cli_entry cli_pjsip[] = {

    
   
369
	AST_CLI_DEFINE(pjsip_set_history, "Enable/Disable PJSIP History"),

    
   
370
	AST_CLI_DEFINE(pjsip_show_history, "Display the PJSIP History"),

    
   
371
	AST_CLI_DEFINE(pjsip_show_entry, "Display an entry in the PJSIP History"),

    
   
372
};

    
   
373

   

    
   
374
static int load_module(void)

    
   
375
{

    
   
376
	ast_sip_register_service(&history_module);

    
   
377
	ast_cli_register_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));

    
   
378

   

    
   
379
	return AST_MODULE_LOAD_SUCCESS;

    
   
380
}

    
   
381

   

    
   
382
static int unload_module(void)

    
   
383
{

    
   
384
	ast_cli_unregister_multiple(cli_pjsip, ARRAY_LEN(cli_pjsip));

    
   
385
	ast_sip_unregister_service(&history_module);

    
   
386

   

    
   
387
	disable_history();

    
   
388

   

    
   
389
	return 0;

    
   
390
}

    
   
391

   

    
   
392
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP History",

    
   
393
		.support_level = AST_MODULE_SUPPORT_CORE,

    
   
394
		.load = load_module,

    
   
395
		.unload = unload_module,

    
   
396
		.load_pri = AST_MODPRI_APP_DEPEND,

    
   
397
	       );
  1. /trunk/res/res_pjsip_history.c: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.