backup
[lcr.git] / trace.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** trace functions                                                           **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 struct trace trace[MAX_NESTED_TRACES];
15 int trace_current = -1;
16 char trace_string[MX_TRACE_ELEMENTS * 100 + 400];
17
18 static char *spaces[11] = {
19         "          ",
20         "         ",
21         "        ",
22         "       ",
23         "      ",
24         "     ",
25         "    ",
26         "   ",
27         "  ",
28         " ",
29         "",
30 };
31
32 /*
33  * initializes a new trace
34  * all values will be reset
35  */
36 void start_trace(int port, char *interface, char *caller, char *dialing, int direction, char *category, char *name);
37 {
38         if (++trace_current == MAX_NESTED_TRACES)
39         {
40                 PERROR("maximum nesting level of traces exceeding: %d, exitting!\n", MAX_NESTED_TRACES);
41                 PERROR("last trace=%s\n", trace[MAX_NESTED_TRACE-1].name);
42                 exit(-1);
43         }
44         memset(trace[trace_current], 0, sizeof(struct trace));
45         trace[trace_current].port = port;
46         if (interface) if (interface[0])
47                 SCPY(trace[trace_current].interface, interface);
48         if (caller) if (caller[0])
49                 SCPY(trace[trace_current].caller, caller);
50         if (dialing) if (dialing[0])
51                 SCPY(trace[trace_current].dialing, dialing);
52         trace[trace_current].direction = direction;
53         if (category) if (category[0])
54                 SCPY(trace[trace_current].category, category);
55         if (name) if (name[0])
56                 SCPY(trace[trace_current].name, name);
57         trace[trace_current].sec = now_tv.tv_sec;
58         trace[trace_current].usec = now_tv.tv_usec;
59 }
60
61
62 /*
63  * adds a new element to the trace
64  * if subelement is given, element will also contain a subelement
65  * if multiple subelements belong to same element, name must be equal for all subelements
66  */
67 void add_trace(char *name, char *sub, const char *fmt, ...);
68 {
69         va_list args;
70
71         /* check nesting */
72         if (trace_current < 0)
73         {
74                 PERROR("add_trace called without start_trace, exitting.\n");
75                 exit(0);
76         }
77         
78         /* check for space */
79         if (trace[trace_current].elements == MAX_TRACE_ELEMENTS)
80         {
81                 PERROR("trace with name=%s exceeds the maximum number of elements (%d)\n", trace.name, MAX_TRACE_ELEMENTS);
82                 return;
83         }
84         
85         /* check for required name value */
86         if (!name)
87                 goto nostring;
88         if (!name[0])
89         {
90                 nostring:
91                 PERROR("trace with name=%s gets element with no string\n", trace->name);
92                 return;
93         }
94         
95         /* write name, sub and value */
96         SCPY(trace[trace_current].element[trace[trace_current].elements].name, name);
97         if (sub) if (sub[0])
98                 SCPY(trace[trace_current].element[trace[trace_current].elements].sub, sub);
99         if (fmt) if (fmt[0])
100         {
101                 va_start(args, fmt);
102                 VUNPRINT(trace[trace_current].element[trace[trace_current].element].value, sizeof(trace[trace_current].element[trace[trace_current].elements].value)-1, fmt, args);
103                 va_end(args);
104         }
105
106         /* increment elements */
107         trace[trace_current].elements++;
108 }
109
110
111 /*
112  * trace ends
113  * this function will put the trace to sockets and logfile, if requested
114  */
115 void end_trace(void);
116 {
117         /* check nesting */
118         if (trace_current < 0)
119         {
120                 PERROR("end_trace called without start_trace, exitting.\n");
121                 exit(0);
122         }
123         
124         /* process log file */
125         if (options.log[0])
126         {
127                 string = print_trace(1, 0, NULL, NULL, NULL, -1, "AP", NULL);
128                 fwrite(string, strlen(string), 1, fp);
129         }
130
131         /* reduce nesting level */
132         trace_current--;
133 }
134
135
136 /*
137  * prints trace to socket or log
138  * detail: 1 = brief, 2=short, 3=long
139  */
140 static char *print_trace(int detail, int port, char *interface, char *caller, char *dialing, int direction, char *category);
141 {
142         trace_string[0] = '\0';
143         char buffer[256];
144         struct tm *tm;
145
146         if (detail < 1)
147                 return;
148
149         /* filter trace */
150         if (port && trace.port)
151                 if (port != trace.port) return;
152         if (interface && interface[0] && trace.interface[0])
153                 if (!!strcasecmp(interface, trace.interface)) return;
154         if (caller && caller[0] && trace.caller[0])
155                 if (!!strcasecmp(caller, trace.caller)) return;
156         if (dialing && dialing[0] && trace.dialing[0])
157                 if (!!strcasecmp(dialing, trace.dialing)) return;
158         if (direction && trace.direction)
159                 if (direction != trace.direction) return;
160         if (category && category[0] && trace.category[0])
161                 if (!!strcasecmp(category, trace.category)) return;
162
163         /* head */
164         if (detail >= 3)
165         {
166                 /* "Port: 1 (BRI PTMP TE)" */
167                 if (port)
168                 {
169                         mISDNport = mISDNport_first;
170                         while(mISDNport)
171                         {
172                                 if (mISDNport->number == trace.port)
173                                         break;
174                                 mISDNport = mISDNport->next;
175                         }
176                         if (mISDNport)
177                                 SPRINT(buffer, "Port: %d (%s %s %s)", port, (mISDNport->pri)?"PRI":"BRI", (mISDNport->ptp)?"PTP":"PTMP", (mISDNport->nt)?"NT":"TE");
178                         else
179                                 SPRINT(buffer, "Port: %d (does not exist}\n", port);
180                         SCAT(trace_string, buffer);
181                 } else
182                         SCAT(trace_string, "Port: ---");
183
184                 if (trace.interface[0])
185                 {
186                         /* "  Interface: 'Ext'" */
187                         SPRINT(buffer, "  Interface: '%s'", trace.interface);
188                         SCAT(trace_string, buffer);
189                 } else
190                         SCAT(trace_string, "  Interface: ---");
191                         
192                 if (trace.caller[0])
193                 {
194                         /* "  Caller: '021256493'" */
195                         SPRINT(buffer, "  Caller: '%s'\n", trace.caller);
196                         SCAT(trace_string, buffer);
197                 } else
198                         SCAT(trace_string, "  Caller: ---\n");
199
200                 /* "Time: 25.08.73 05:14:39.282" */
201                 tm = localtime(&trace.sec);
202                 SPRINT(buffer, "Time: %02d.%02d.%02d %02d:%02d:%02d.%03d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec, trace->usec/1000);
203                 SCAT(trace_string, buffer);
204
205                 if (trace.direction)
206                 {
207                         /* "  Direction: out" */
208                         SPRINT(buffer, "  Direction: %s", (trace.direction==DIRECTION_OUT)?"OUT":"IN");
209                         SCAT(trace_string, buffer);
210                 } else
211                         SCAT(trace_string, "  Direction: ---");
212
213                 if (trace.dialing[0])
214                 {
215                         /* "  Dialing: '57077'" */
216                         SPRINT(buffer, "  Dialing: '%s'\n", trace.dialing);
217                         SCAT(trace_string, buffer);
218                 } else
219                         SCAT(trace_string, "  Dialing: ---\n");
220
221                 SCAT(trace_string, "------------------------------------------------------------------------------\n");
222         }
223
224         /* "L3: CC_SETUP (net->user)" */
225         SPRINT(buffer, "%s: %s", trace.category[0]?trace.category:"--", trace.name[0]?trace.name:"<unknown>");
226         SCAT(trace_string, buffer);
227
228         /* elements */
229         switch(detail)
230         {
231                 case 1: /* brief */
232                 i = 0;
233                 while(i < trace.elements)
234                 {
235                         SPRINT(buffer, "  %s", trace.element[i].name);
236                         if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
237                                 buffer[0] = '\0';
238                         SCAT(trace_string, buffer);
239                         if (trace.element[i].sub[0])
240                                 SPRINT(buffer, " %s=%s", trace.element[i].sub, value);
241                         else
242                                 SPRINT(buffer, " %s", value);
243                         SCAT(trace_string, buffer);
244                         i++;
245                 }
246                 SCAT(trace_string, "\n");
247                 break;
248
249                 case 2: /* short */
250                 case 3: /* long */
251                 SCAT(trace_string, "\n");
252                 i = 0;
253                 while(i < trace.elements)
254                 {
255                         SPRINT(buffer, " %s%s", trace.element[i].name, spaces[strlen(trace.element[i].name)]);
256                         if (i) if (!strcmp(trace.element[i].name, trace.element[i-1].name))
257                                 SPRINT(buffer, "           ");
258                         SCAT(trace_string, buffer);
259                         if (trace.element[i].sub[0])
260                                 SPRINT(buffer, " : %s%s = %s\n", trace.element[i].sub, spaces[strlen(trace.element[i].sub)], value);
261                         else
262                                 SPRINT(buffer, " :              %s\n", value);
263                         SCAT(trace_string, buffer);
264                         i++;
265                 }
266                 break;
267         }
268
269         /* end */
270         if (detail >= 3)
271                 SCAT(trace_string, "\n");
272 }
273
274
275
276 ^todo:
277 socket
278 file open
279
280