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