the last round of file version tags
[asterisk/asterisk.git] / apps / app_test.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Applications to test connection and produce report in text file
5  * 
6  * Copyright (C) 2004 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  * Russell Bryant <russelb@clemson.edu>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU General Public License
13  */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21
22 #include "asterisk.h"
23
24 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
25
26 #include "asterisk/channel.h"
27 #include "asterisk/options.h"
28 #include "asterisk/module.h"
29 #include "asterisk/logger.h"
30 #include "asterisk/lock.h"
31 #include "asterisk/app.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/utils.h"
34
35 static char *tdesc = "Interface Test Application";
36
37 static char *tests_descrip = 
38          "TestServer(): Perform test server function and write call report.\n"
39          "Results stored in /var/log/asterisk/testreports/<testid>-server.txt";
40 static char *tests_app = "TestServer";
41 static char *tests_synopsis = "Execute Interface Test Server";
42
43 static char *testc_descrip = 
44          "TestClient(testid): Executes test client with given testid.\n"
45          "Results stored in /var/log/asterisk/testreports/<testid>-client.txt";
46
47 static char *testc_app = "TestClient";
48 static char *testc_synopsis = "Execute Interface Test Client";
49
50 static int measurenoise(struct ast_channel *chan, int ms, char *who)
51 {
52         int res=0;
53         int mssofar;
54         int noise=0;
55         int samples=0;
56         int x;
57         short *foo;
58         struct timeval start, tv;
59         struct ast_frame *f;
60         int rformat;
61         rformat = chan->readformat;
62         if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
63                 ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
64                 return -1;
65         }
66         gettimeofday(&start, NULL);
67         for(;;) {
68                 gettimeofday(&tv, NULL);
69                 mssofar = (tv.tv_sec - start.tv_sec) * 1000;
70                 mssofar += (tv.tv_usec - start.tv_usec) / 1000;
71                 if (mssofar > ms)
72                         break;
73                 res = ast_waitfor(chan, ms - mssofar);
74                 if (res < 1)
75                         break;
76                 f = ast_read(chan);
77                 if (!f) {
78                         res = -1;
79                         break;
80                 }
81                 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
82                         foo = (short *)f->data;
83                         for (x=0;x<f->samples;x++) {
84                                 noise += abs(foo[x]);
85                                 samples++;
86                         }
87                 }
88         }
89
90         if (rformat) {
91                 if (ast_set_read_format(chan, rformat)) {
92                         ast_log(LOG_NOTICE, "Unable to restore original format!\n");
93                         return -1;
94                 }
95         }
96         if (res < 0)
97                 return res;
98         if (!samples) {
99                 ast_log(LOG_NOTICE, "No samples were received from the other side!\n");
100                 return -1;
101         }
102         ast_log(LOG_DEBUG, "%s: Noise: %d, samples: %d, avg: %d\n", who, noise, samples, noise / samples);
103         return (noise / samples);
104 }
105
106 static int sendnoise(struct ast_channel *chan, int ms) 
107 {
108         int res;
109         res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
110         if (!res) {
111                 res = ast_waitfordigit(chan, ms);
112                 ast_tonepair_stop(chan);
113         }
114         return res;     
115 }
116
117 STANDARD_LOCAL_USER;
118
119 LOCAL_USER_DECL;
120
121 static int testclient_exec(struct ast_channel *chan, void *data)
122 {
123         struct localuser *u;
124         int res = 0;
125         char *testid=data;
126         char fn[80];
127         char serverver[80];
128         FILE *f;
129         LOCAL_USER_ADD(u);
130         
131         /* Check for test id */
132         if (!testid || ast_strlen_zero(testid)) {
133                 ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
134                 return -1;
135         }
136         
137         if (chan->_state != AST_STATE_UP)
138                 res = ast_answer(chan);
139         
140         /* Wait a few just to be sure things get started */
141         res = ast_safe_sleep(chan, 3000);
142         /* Transmit client version */
143         if (!res)
144                 res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
145         if (option_debug)
146                 ast_log(LOG_DEBUG, "Transmit client version\n");
147         
148         /* Read server version */
149         if (option_debug)
150                 ast_log(LOG_DEBUG, "Read server version\n");
151         if (!res) 
152                 res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
153         if (res > 0)
154                 res = 0;
155         if (option_debug)
156                 ast_log(LOG_DEBUG, "server version: %s\n", serverver);
157                 
158         if (res > 0)
159                 res = 0;
160
161         if (!res)
162                 res = ast_safe_sleep(chan, 1000);
163         /* Send test id */
164         if (!res) 
165                 res = ast_dtmf_stream(chan, NULL, testid, 0);           
166         if (!res) 
167                 res = ast_dtmf_stream(chan, NULL, "#", 0);              
168         if (option_debug)
169                 ast_log(LOG_DEBUG, "send test identifier: %s\n", testid);
170
171         if ((res >=0) && (!ast_strlen_zero(testid))) {
172                 /* Make the directory to hold the test results in case it's not there */
173                 snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
174                 mkdir(fn, 0777);
175                 snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
176                 if ((f = fopen(fn, "w+"))) {
177                         setlinebuf(f);
178                         fprintf(f, "CLIENTCHAN:    %s\n", chan->name);
179                         fprintf(f, "CLIENTTEST ID: %s\n", testid);
180                         fprintf(f, "ANSWER:        PASS\n");
181                         res = 0;
182                         
183                         if (!res) {
184                                 /* Step 1: Wait for "1" */
185                                 if (option_debug)
186                                         ast_log(LOG_DEBUG, "TestClient: 2.  Wait DTMF 1\n");
187                                 res = ast_waitfordigit(chan, 3000);
188                                 fprintf(f, "WAIT DTMF 1:   %s\n", (res != '1') ? "FAIL" : "PASS");
189                                 if (res == '1')
190                                         res = 0;
191                                 else
192                                         res = -1;
193                         }
194                         if (!res)
195                                 res = ast_safe_sleep(chan, 1000);
196                         if (!res) {
197                                 /* Step 2: Send "2" */
198                                 if (option_debug)
199                                         ast_log(LOG_DEBUG, "TestClient: 2.  Send DTMF 2\n");
200                                 res = ast_dtmf_stream(chan, NULL, "2", 0);
201                                 fprintf(f, "SEND DTMF 2:   %s\n", (res < 0) ? "FAIL" : "PASS");
202                                 if (res > 0)
203                                         res = 0;
204                         }
205                         if (!res) {
206                                 /* Step 3: Wait one second */
207                                 if (option_debug)
208                                         ast_log(LOG_DEBUG, "TestClient: 3.  Wait one second\n");
209                                 res = ast_safe_sleep(chan, 1000);
210                                 fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
211                                 if (res > 0)
212                                         res = 0;
213                         }                       
214                         if (!res) {
215                                 /* Step 4: Measure noise */
216                                 if (option_debug)
217                                         ast_log(LOG_DEBUG, "TestClient: 4.  Measure noise\n");
218                                 res = measurenoise(chan, 5000, "TestClient");
219                                 fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
220                                 if (res > 0)
221                                         res = 0;
222                         }
223                         if (!res) {
224                                 /* Step 5: Wait for "4" */
225                                 if (option_debug)
226                                         ast_log(LOG_DEBUG, "TestClient: 5.  Wait DTMF 4\n");
227                                 res = ast_waitfordigit(chan, 3000);
228                                 fprintf(f, "WAIT DTMF 4:   %s\n", (res != '4') ? "FAIL" : "PASS");
229                                 if (res == '4')
230                                         res = 0;
231                                 else
232                                         res = -1;
233                         }
234                         if (!res) {
235                                 /* Step 6: Transmit tone noise */
236                                 if (option_debug)
237                                         ast_log(LOG_DEBUG, "TestClient: 6.  Transmit tone\n");
238                                 res = sendnoise(chan, 6000);
239                                 fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
240                         }
241                         if (!res || (res == '5')) {
242                                 /* Step 7: Wait for "5" */
243                                 if (option_debug)
244                                         ast_log(LOG_DEBUG, "TestClient: 7.  Wait DTMF 5\n");
245                                 if (!res)
246                                         res = ast_waitfordigit(chan, 3000);
247                                 fprintf(f, "WAIT DTMF 5:   %s\n", (res != '5') ? "FAIL" : "PASS");
248                                 if (res == '5')
249                                         res = 0;
250                                 else
251                                         res = -1;
252                         }
253                         if (!res) {
254                                 /* Step 8: Wait one second */
255                                 if (option_debug)
256                                         ast_log(LOG_DEBUG, "TestClient: 8.  Wait one second\n");
257                                 res = ast_safe_sleep(chan, 1000);
258                                 fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
259                                 if (res > 0)
260                                         res = 0;
261                         }
262                         if (!res) {
263                                 /* Step 9: Measure noise */
264                                 if (option_debug)
265                                         ast_log(LOG_DEBUG, "TestClient: 6.  Measure tone\n");
266                                 res = measurenoise(chan, 4000, "TestClient");
267                                 fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
268                                 if (res > 0)
269                                         res = 0;
270                         }
271                         if (!res) {
272                                 /* Step 10: Send "7" */
273                                 if (option_debug)
274                                         ast_log(LOG_DEBUG, "TestClient: 7.  Send DTMF 7\n");
275                                 res = ast_dtmf_stream(chan, NULL, "7", 0);
276                                 fprintf(f, "SEND DTMF 7:   %s\n", (res < 0) ? "FAIL" : "PASS");
277                                 if (res > 0)
278                                         res =0;
279                         }
280                         if (!res) {
281                                 /* Step 11: Wait for "8" */
282                                 if (option_debug)
283                                         ast_log(LOG_DEBUG, "TestClient: 11.  Wait DTMF 8\n");
284                                 res = ast_waitfordigit(chan, 3000);
285                                 fprintf(f, "WAIT DTMF 8:   %s\n", (res != '8') ? "FAIL" : "PASS");
286                                 if (res == '8')
287                                         res = 0;
288                                 else
289                                         res = -1;
290                         }
291                         if (option_debug && !res ) {
292                                 /* Step 12: Hangup! */
293                                 ast_log(LOG_DEBUG, "TestClient: 12.  Hangup\n");
294                         }
295
296                         if (option_debug)
297                                 ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
298                         fprintf(f, "-- END TEST--\n");
299                         fclose(f);
300                         res = -1;
301                 } else
302                         res = -1;
303         } else {
304                 ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
305                 res = -1;
306         }
307         LOCAL_USER_REMOVE(u);
308         return res;
309 }
310
311 static int testserver_exec(struct ast_channel *chan, void *data)
312 {
313         struct localuser *u;
314         int res = 0;
315         char testid[80]="";
316         char fn[80];
317         FILE *f;
318         LOCAL_USER_ADD(u);
319         if (chan->_state != AST_STATE_UP)
320                 res = ast_answer(chan);
321         /* Read version */
322         if (option_debug)
323                 ast_log(LOG_DEBUG, "Read client version\n");
324         if (!res) 
325                 res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
326         if (res > 0)
327                 res = 0;
328         if (option_debug) {
329                 ast_log(LOG_DEBUG, "client version: %s\n", testid);
330                 ast_log(LOG_DEBUG, "Transmit server version\n");
331         }
332         res = ast_safe_sleep(chan, 1000);
333         if (!res)
334                 res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
335         if (res > 0)
336                 res = 0;
337
338         if (!res) 
339                 res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);               
340         if (option_debug) 
341                 ast_log(LOG_DEBUG, "read test identifier: %s\n", testid);
342         /* Check for sneakyness */
343         if (strchr(testid, '/'))
344                 res = -1;
345         if ((res >=0) && (!ast_strlen_zero(testid))) {
346                 /* Got a Test ID!  Whoo hoo! */
347                 /* Make the directory to hold the test results in case it's not there */
348                 snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
349                 mkdir(fn, 0777);
350                 snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
351                 if ((f = fopen(fn, "w+"))) {
352                         setlinebuf(f);
353                         fprintf(f, "SERVERCHAN:    %s\n", chan->name);
354                         fprintf(f, "SERVERTEST ID: %s\n", testid);
355                         fprintf(f, "ANSWER:        PASS\n");
356                         ast_log(LOG_DEBUG, "Processing Test ID '%s'\n", testid);
357                         res = ast_safe_sleep(chan, 1000);
358                         if (!res) {
359                                 /* Step 1: Send "1" */
360                                 if (option_debug) 
361                                         ast_log(LOG_DEBUG, "TestServer: 1.  Send DTMF 1\n");
362                                 res = ast_dtmf_stream(chan, NULL, "1", 0);
363                                 fprintf(f, "SEND DTMF 1:   %s\n", (res < 0) ? "FAIL" : "PASS");
364                                 if (res > 0)
365                                         res = 0;
366                         }
367                         if (!res) {
368                                 /* Step 2: Wait for "2" */
369                                 if (option_debug) 
370                                         ast_log(LOG_DEBUG, "TestServer: 2.  Wait DTMF 2\n");
371                                 res = ast_waitfordigit(chan, 3000);
372                                 fprintf(f, "WAIT DTMF 2:   %s\n", (res != '2') ? "FAIL" : "PASS");
373                                 if (res == '2')
374                                         res = 0;
375                                 else
376                                         res = -1;
377                         }
378                         if (!res) {
379                                 /* Step 3: Measure noise */
380                                 if (option_debug) 
381                                         ast_log(LOG_DEBUG, "TestServer: 3.  Measure noise\n");
382                                 res = measurenoise(chan, 6000, "TestServer");
383                                 fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
384                                 if (res > 0)
385                                         res = 0;
386                         }
387                         if (!res) {
388                                 /* Step 4: Send "4" */
389                                 if (option_debug) 
390                                         ast_log(LOG_DEBUG, "TestServer: 4.  Send DTMF 4\n");
391                                 res = ast_dtmf_stream(chan, NULL, "4", 0);
392                                 fprintf(f, "SEND DTMF 4:   %s\n", (res < 0) ? "FAIL" : "PASS");
393                                 if (res > 0)
394                                         res = 0;
395                         }
396                 
397                         if (!res) {
398                                 /* Step 5: Wait one second */
399                                 if (option_debug) 
400                                         ast_log(LOG_DEBUG, "TestServer: 5.  Wait one second\n");
401                                 res = ast_safe_sleep(chan, 1000);
402                                 fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
403                                 if (res > 0)
404                                         res = 0;
405                         }
406                 
407                         if (!res) {
408                                 /* Step 6: Measure noise */
409                                 if (option_debug) 
410                                         ast_log(LOG_DEBUG, "TestServer: 6.  Measure tone\n");
411                                 res = measurenoise(chan, 4000, "TestServer");
412                                 fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
413                                 if (res > 0)
414                                         res = 0;
415                         }
416
417                         if (!res) {
418                                 /* Step 7: Send "5" */
419                                 if (option_debug) 
420                                         ast_log(LOG_DEBUG, "TestServer: 7.  Send DTMF 5\n");
421                                 res = ast_dtmf_stream(chan, NULL, "5", 0);
422                                 fprintf(f, "SEND DTMF 5:   %s\n", (res < 0) ? "FAIL" : "PASS");
423                                 if (res > 0)
424                                         res = 0;
425                         }
426
427                         if (!res) {
428                                 /* Step 8: Transmit tone noise */
429                                 if (option_debug) 
430                                         ast_log(LOG_DEBUG, "TestServer: 8.  Transmit tone\n");
431                                 res = sendnoise(chan, 6000);
432                                 fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
433                         }
434                 
435                         if (!res || (res == '7')) {
436                                 /* Step 9: Wait for "7" */
437                                 if (option_debug) 
438                                         ast_log(LOG_DEBUG, "TestServer: 9.  Wait DTMF 7\n");
439                                 if (!res)
440                                         res = ast_waitfordigit(chan, 3000);
441                                 fprintf(f, "WAIT DTMF 7:   %s\n", (res != '7') ? "FAIL" : "PASS");
442                                 if (res == '7')
443                                         res = 0;
444                                 else
445                                         res = -1;
446                         }
447                         if (!res)
448                                 res = ast_safe_sleep(chan, 1000);
449                         if (!res) {
450                                 /* Step 10: Send "8" */
451                                 if (option_debug) 
452                                         ast_log(LOG_DEBUG, "TestServer: 10.  Send DTMF 8\n");
453                                 res = ast_dtmf_stream(chan, NULL, "8", 0);
454                                 fprintf(f, "SEND DTMF 8:   %s\n", (res < 0) ? "FAIL" : "PASS");
455                                 if (res > 0)
456                                         res = 0;
457                         }
458                         if (!res) {
459                                 /* Step 11: Wait for hangup to arrive! */
460                                 if (option_debug) 
461                                         ast_log(LOG_DEBUG, "TestServer: 11.  Waiting for hangup\n");
462                                 res = ast_safe_sleep(chan, 10000);
463                                 fprintf(f, "WAIT HANGUP:   %s\n", (res < 0) ? "PASS" : "FAIL");
464                         }
465
466                         ast_log(LOG_NOTICE, "-- TEST COMPLETE--\n");
467                         fprintf(f, "-- END TEST--\n");
468                         fclose(f);
469                         res = -1;
470                 } else
471                         res = -1;
472         } else {
473                 ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
474                 res = -1;
475         }
476         LOCAL_USER_REMOVE(u);
477         return res;
478 }
479
480 int unload_module(void)
481 {
482         STANDARD_HANGUP_LOCALUSERS;
483         ast_unregister_application(testc_app);
484         return ast_unregister_application(tests_app);
485 }
486
487 int load_module(void)
488 {
489         ast_register_application(testc_app, testclient_exec, testc_synopsis, testc_descrip);
490         return ast_register_application(tests_app, testserver_exec, tests_synopsis, tests_descrip);
491 }
492
493 char *description(void)
494 {
495         return tdesc;
496 }
497
498 int usecount(void)
499 {
500         int res;
501         STANDARD_USECOUNT(res);
502         return res;
503 }
504
505 char *key(void)
506 {
507         return ASTERISK_GPL_KEY;
508 }