app_queue: Cleanup queue_ref / queue_unref routines.
[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         FILE *f;
334         if (ast_channel_state(chan) != AST_STATE_UP)
335                 res = ast_answer(chan);
336         /* Read version */
337         ast_debug(1, "Read client version\n");
338         if (!res)
339                 res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
340         if (res > 0)
341                 res = 0;
342
343         ast_debug(1, "client version: %s\n", testid);
344         ast_debug(1, "Transmit server version\n");
345
346         res = ast_safe_sleep(chan, 1000);
347         if (!res)
348                 res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0);
349         if (res > 0)
350                 res = 0;
351
352         if (!res)
353                 res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
354         ast_debug(1, "read test identifier: %s\n", testid);
355         /* Check for sneakyness */
356         if (strchr(testid, '/'))
357                 res = -1;
358         if ((res >=0) && (!ast_strlen_zero(testid))) {
359                 char fn[PATH_MAX];
360
361                 /* Got a Test ID!  Whoo hoo! */
362                 /* Make the directory to hold the test results in case it's not there */
363                 snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
364                 ast_mkdir(fn, 0777);
365                 snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
366                 if ((f = fopen(fn, "w+"))) {
367                         setlinebuf(f);
368                         fprintf(f, "SERVERCHAN:    %s\n", ast_channel_name(chan));
369                         fprintf(f, "SERVERTEST ID: %s\n", testid);
370                         fprintf(f, "ANSWER:        PASS\n");
371                         ast_debug(1, "Processing Test ID '%s'\n", testid);
372                         res = ast_safe_sleep(chan, 1000);
373                         if (!res) {
374                                 /* Step 1: Send "1" */
375                                 ast_debug(1, "TestServer: 1.  Send DTMF 1\n");
376                                 res = ast_dtmf_stream(chan, NULL, "1", 0,0 );
377                                 fprintf(f, "SEND DTMF 1:   %s\n", (res < 0) ? "FAIL" : "PASS");
378                                 if (res > 0)
379                                         res = 0;
380                         }
381                         if (!res) {
382                                 /* Step 2: Wait for "2" */
383                                 ast_debug(1, "TestServer: 2.  Wait DTMF 2\n");
384                                 res = ast_waitfordigit(chan, 3000);
385                                 fprintf(f, "WAIT DTMF 2:   %s\n", (res != '2') ? "FAIL" : "PASS");
386                                 if (res == '2')
387                                         res = 0;
388                                 else
389                                         res = -1;
390                         }
391                         if (!res) {
392                                 /* Step 3: Measure noise */
393                                 ast_debug(1, "TestServer: 3.  Measure noise\n");
394                                 res = measurenoise(chan, 6000, "TestServer");
395                                 fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
396                                 if (res > 0)
397                                         res = 0;
398                         }
399                         if (!res) {
400                                 /* Step 4: Send "4" */
401                                 ast_debug(1, "TestServer: 4.  Send DTMF 4\n");
402                                 res = ast_dtmf_stream(chan, NULL, "4", 0, 0);
403                                 fprintf(f, "SEND DTMF 4:   %s\n", (res < 0) ? "FAIL" : "PASS");
404                                 if (res > 0)
405                                         res = 0;
406                         }
407                         if (!res) {
408                                 /* Step 5: Wait one second */
409                                 ast_debug(1, "TestServer: 5.  Wait one second\n");
410                                 res = ast_safe_sleep(chan, 1000);
411                                 fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
412                                 if (res > 0)
413                                         res = 0;
414                         }
415                         if (!res) {
416                                 /* Step 6: Measure noise */
417                                 ast_debug(1, "TestServer: 6.  Measure tone\n");
418                                 res = measurenoise(chan, 4000, "TestServer");
419                                 fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
420                                 if (res > 0)
421                                         res = 0;
422                         }
423                         if (!res) {
424                                 /* Step 7: Send "5" */
425                                 ast_debug(1, "TestServer: 7.  Send DTMF 5\n");
426                                 res = ast_dtmf_stream(chan, NULL, "5", 0, 0);
427                                 fprintf(f, "SEND DTMF 5:   %s\n", (res < 0) ? "FAIL" : "PASS");
428                                 if (res > 0)
429                                         res = 0;
430                         }
431                         if (!res) {
432                                 /* Step 8: Transmit tone noise */
433                                 ast_debug(1, "TestServer: 8.  Transmit tone\n");
434                                 res = sendnoise(chan, 6000);
435                                 fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
436                         }
437
438                         if (!res || (res == '7')) {
439                                 /* Step 9: Wait for "7" */
440                                 ast_debug(1, "TestServer: 9.  Wait DTMF 7\n");
441                                 if (!res)
442                                         res = ast_waitfordigit(chan, 3000);
443                                 fprintf(f, "WAIT DTMF 7:   %s\n", (res != '7') ? "FAIL" : "PASS");
444                                 if (res == '7')
445                                         res = 0;
446                                 else
447                                         res = -1;
448                         }
449                         if (!res) {
450                                 res = ast_safe_sleep(chan, 1000);
451                         }
452                         if (!res) {
453                                 /* Step 10: Send "8" */
454                                 ast_debug(1, "TestServer: 10.  Send DTMF 8\n");
455                                 res = ast_dtmf_stream(chan, NULL, "8", 0, 0);
456                                 fprintf(f, "SEND DTMF 8:   %s\n", (res < 0) ? "FAIL" : "PASS");
457                                 if (res > 0)
458                                         res = 0;
459                         }
460                         if (!res) {
461                                 /* Step 11: Wait for hangup to arrive! */
462                                 ast_debug(1, "TestServer: 11.  Waiting for hangup\n");
463                                 res = ast_safe_sleep(chan, 10000);
464                                 fprintf(f, "WAIT HANGUP:   %s\n", (res < 0) ? "PASS" : "FAIL");
465                         }
466
467                         ast_log(LOG_NOTICE, "-- TEST COMPLETE--\n");
468                         fprintf(f, "-- END TEST--\n");
469                         fclose(f);
470                         res = -1;
471                 } else
472                         res = -1;
473         } else {
474                 ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", ast_channel_name(chan));
475                 res = -1;
476         }
477         return res;
478 }
479
480 static int unload_module(void)
481 {
482         int res;
483
484         res = ast_unregister_application(testc_app);
485         res |= ast_unregister_application(tests_app);
486
487         return res;
488 }
489
490 static int load_module(void)
491 {
492         int res;
493
494         res = ast_register_application_xml(testc_app, testclient_exec);
495         res |= ast_register_application_xml(tests_app, testserver_exec);
496
497         return res;
498 }
499
500 AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Interface Test Application");