Add dumpchan application (bug #2678)
[asterisk/asterisk.git] / apps / app_dumpchan.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Application to dump channel variables
5  * 
6  * Copyright (C) 2004, Anthony Minessale II.
7  *
8  * Anthony Minessale <anthmct@yahoo.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License (and disclaimed to Digium)
12  */
13
14 #include <asterisk/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/pbx.h>
18 #include <asterisk/module.h>
19 #include <asterisk/options.h>
20 #include <asterisk/utils.h>
21 #include <asterisk/lock.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25
26 static char *tdesc = "Dump Info About The Calling Channel";
27 static char *app = "DumpChan";
28 static char *synopsis = "Dump Info About The Calling Channel";
29 static char *desc = "Usage: exten => 1,1,DumpChan([<min_verbose_level>])\n\n"
30 "If optional min_verbose_level is specified, only dump data when that verbose level is set.\n\n";
31
32 STANDARD_LOCAL_USER;
33
34 LOCAL_USER_DECL;
35
36 static int ast_serialize_showchan(struct ast_channel *c, char *buf, size_t size)
37 {
38         struct timeval now;
39         long elapsed_seconds=0;
40         int hour=0, min=0, sec=0;
41         gettimeofday(&now, NULL);
42         memset(buf,0,size);
43         if (!c)
44                 return 0;
45
46         if (c->cdr) {
47                 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
48                 hour = elapsed_seconds / 3600;
49                 min = (elapsed_seconds % 3600) / 60;
50                 sec = elapsed_seconds % 60;
51         }
52
53         snprintf(buf,size, 
54                          "Name=%s\n"
55                          "Type=%s\n"
56                          "UniqueID=%s\n"
57                          "CallerID=%s\n"
58                          "CallerIDName=%s\n"
59                          "DNIDDigits=%s\n"
60                          "State=%s(%d)\n"
61                          "Rings=%d\n"
62                          "NativeFormat=%d\n"
63                          "WriteFormat=%d\n"
64                          "ReadFormat=%d\n"
65                          "1stFileDescriptor=%d\n"
66                          "Framesin=%d%s\n"
67                          "Framesout=%d%s\n"
68                          "TimetoHangup=%ld\n"
69                          "ElapsedTime=%dh%dm%ds\n"
70                          "Context=%s\n"
71                          "Extension=%s\n"
72                          "Priority=%d\n"
73                          "CallGroup=%d\n"
74                          "PickupGroup=%d\n"
75                          "Application=%s\n"
76                          "Data=%s\n"
77                          "Stack=%d\n"
78                          "Blocking_in=%s\n",
79                          c->name,
80                          c->type,
81                          c->uniqueid,
82                          (c->cid.cid_num ? c->cid.cid_num : "(N/A)"),
83                          (c->cid.cid_name ? c->cid.cid_name : "(N/A)"),
84                          (c->cid.cid_dnid ? c->cid.cid_dnid : "(N/A)" ),
85                          ast_state2str(c->_state),
86                          c->_state,
87                          c->rings,
88                          c->nativeformats,
89                          c->writeformat,
90                          c->readformat,
91                          c->fds[0], c->fin & 0x7fffffff, (c->fin & 0x80000000) ? " (DEBUGGED)" : "",
92                          c->fout & 0x7fffffff, (c->fout & 0x80000000) ? " (DEBUGGED)" : "", (long)c->whentohangup,
93                          hour,
94                          min,
95                          sec,
96                          c->context,
97                          c->exten,
98                          c->priority,
99                          c->callgroup,
100                          c->pickupgroup,
101                          ( c->appl ? c->appl : "(N/A)" ),
102                          ( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"),
103                          c->stack,
104                          (c->blocking ? c->blockproc : "(Not Blocking)"));
105
106         return 1;
107 }
108
109 static int dumpchan_exec(struct ast_channel *chan, void *data)
110 {
111         int res=0;
112         struct localuser *u;
113         char vars[1024];
114         char info[1024];
115         int level = 0;
116         static char *line = "================================================================================";
117         LOCAL_USER_ADD(u);
118
119         if (data) {
120                 level = atoi(data);
121         }
122
123         pbx_builtin_serialize_variables(chan, vars, sizeof(vars));
124         ast_serialize_showchan(chan, info, sizeof(info));
125         if (option_verbose >= level)
126                 ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n",chan->name,line,info,vars,line);
127
128         LOCAL_USER_REMOVE(u);
129         return res;
130 }
131
132 int unload_module(void)
133 {
134         STANDARD_HANGUP_LOCALUSERS;
135         return ast_unregister_application(app);
136 }
137
138 int load_module(void)
139 {
140         return ast_register_application(app, dumpchan_exec, synopsis, desc);
141 }
142
143 char *description(void)
144 {
145         return tdesc;
146 }
147
148 int usecount(void)
149 {
150         int res;
151         STANDARD_USECOUNT(res);
152         return res;
153 }
154
155 char *key()
156 {
157         return ASTERISK_GPL_KEY;
158 }
159