Thanks to the fine work of Russell Bryant and Dancho Lazarov, we now have autoconf...
[asterisk/asterisk.git] / apps / app_osplookup.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Open Settlement Protocol Applications
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * 
25  * \ingroup applications
26  */
27
28 /*** MODULEINFO
29         <depend>libosptk</depend>
30         <depend>ssl</depend>
31  ***/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <ctype.h>
38
39 #include "asterisk.h"
40
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
42
43 #include "asterisk/lock.h"
44 #include "asterisk/file.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/options.h"
49 #include "asterisk/config.h"
50 #include "asterisk/module.h"
51 #include "asterisk/utils.h"
52 #include "asterisk/causes.h"
53 #include "asterisk/astosp.h"
54 #include "asterisk/app.h"
55 #include "asterisk/options.h"
56
57 static char *app1= "OSPAuth";
58 static char *synopsis1 = "OSP authentication";
59 static char *descrip1 = 
60 "  OSPAuth([provider[|options]]):  Authenticate a SIP INVITE by OSP and sets\n"
61 "the variables:\n"
62 " ${OSPINHANDLE}:  The in_bound call transaction handle\n"
63 " ${OSPINTIMELIMIT}:  The in_bound call duration limit in seconds\n"
64 "\n"
65 "The option string may contain the following character:\n"
66 "       'j' -- jump to n+101 priority if the authentication was NOT successful\n"
67 "This application sets the following channel variable upon completion:\n"
68 "       OSPAUTHSTATUS   The status of the OSP Auth attempt as a text string, one of\n"
69 "               SUCCESS | FAILED | ERROR\n";
70
71 static char *app2= "OSPLookup";
72 static char *synopsis2 = "Lookup destination by OSP";
73 static char *descrip2 = 
74 "  OSPLookup(exten[|provider[|options]]):  Looks up an extension via OSP and sets\n"
75 "the variables, where 'n' is the number of the result beginning with 1:\n"
76 " ${OSPOUTHANDLE}:  The OSP Handle for anything remaining\n"
77 " ${OSPTECH}:  The technology to use for the call\n"
78 " ${OSPDEST}:  The destination to use for the call\n"
79 " ${OSPCALLING}:  The calling number to use for the call\n"
80 " ${OSPOUTTOKEN}:  The actual OSP token as a string\n"
81 " ${OSPOUTTIMELIMIT}:  The out_bound call duration limit in seconds\n"
82 " ${OSPRESULTS}:  The number of OSP results total remaining\n"
83 "\n"
84 "The option string may contain the following character:\n"
85 "       'j' -- jump to n+101 priority if the lookup was NOT successful\n"
86 "This application sets the following channel variable upon completion:\n"
87 "       OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
88 "               SUCCESS | FAILED | ERROR\n";
89
90 static char *app3 = "OSPNext";
91 static char *synopsis3 = "Lookup next destination by OSP";
92 static char *descrip3 = 
93 "  OSPNext(cause[|options]):  Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
94 "See OSPLookup for more information\n"
95 "\n"
96 "The option string may contain the following character:\n"
97 "       'j' -- jump to n+101 priority if the lookup was NOT successful\n"
98 "This application sets the following channel variable upon completion:\n"
99 "       OSPNEXTSTATUS   The status of the OSP Next attempt as a text string, one of\n"
100 "               SUCCESS | FAILED |ERROR\n";
101
102 static char *app4 = "OSPFinish";
103 static char *synopsis4 = "Record OSP entry";
104 static char *descrip4 = 
105 "  OSPFinish([status[|options]]):  Records call state for ${OSPINHANDLE}, according to\n"
106 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
107 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
108 "\n"
109 "The option string may contain the following character:\n"
110 "       'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
111 "This application sets the following channel variable upon completion:\n"
112 "       OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
113 "               SUCCESS | FAILED |ERROR \n";
114
115 LOCAL_USER_DECL;
116
117 static int ospauth_exec(struct ast_channel *chan, void *data)
118 {
119         int res = 0;
120         struct localuser* u;
121         char* provider = OSP_DEF_PROVIDER;
122         int priority_jump = 0;
123         struct varshead* headp;
124         struct ast_var_t* current;
125         const char* source = "";
126         const char* token = "";
127         int handle;
128         unsigned int timelimit;
129         char* tmp;
130         char buffer[OSP_INTSTR_SIZE];
131         char* status;
132
133         AST_DECLARE_APP_ARGS(args,
134                 AST_APP_ARG(provider);
135                 AST_APP_ARG(options);
136         );
137
138         LOCAL_USER_ADD(u);
139
140         if (!(tmp = ast_strdupa(data))) {
141                 ast_log(LOG_ERROR, "Out of memory\n");
142                 LOCAL_USER_REMOVE(u);
143                 return(-1);
144         }
145
146         AST_STANDARD_APP_ARGS(args, tmp);
147
148         if (!ast_strlen_zero(args.provider)) {
149                 provider = args.provider;
150         }
151         ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
152
153         if (args.options) {
154                 if (strchr(args.options, 'j')) {
155                         priority_jump = 1;
156                 }
157         }
158         ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
159
160         headp = &chan->varshead;
161         AST_LIST_TRAVERSE(headp, current, entries) {
162                 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
163                         source = ast_var_value(current);
164                 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
165                         token = ast_var_value(current);
166                 }
167         }
168         ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
169         ast_log(LOG_DEBUG, "OSPAuth: token size '%d'\n", strlen(token));
170
171         res = ast_osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit);
172         if (res > 0) {
173                 status = OSP_APP_SUCCESS;
174         } else {
175                 timelimit = OSP_DEF_TIMELIMIT;
176                 if (!res) {
177                         status = OSP_APP_FAILED;
178                 } else {
179                         handle = OSP_INVALID_HANDLE;
180                         status = OSP_APP_ERROR;
181                 }
182         }
183
184         snprintf(buffer, sizeof(buffer), "%d", handle);
185         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
186         ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
187         snprintf(buffer, sizeof(buffer), "%d", timelimit);
188         pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
189         ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
190         pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
191         ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
192
193         if(!res) {
194                 if (priority_jump || ast_opt_priority_jumping) {
195                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
196                 } else {
197                         res = -1;
198                 }
199         } else if (res > 0) {
200                 res = 0;
201         }
202
203         LOCAL_USER_REMOVE(u);
204
205         return(res);
206 }
207
208 static int osplookup_exec(struct ast_channel *chan, void *data)
209 {
210         int res = 0;
211         struct localuser* u;
212         char* provider = OSP_DEF_PROVIDER;
213         int priority_jump = 0;
214         struct varshead* headp;
215         struct ast_var_t* current;
216         const char* srcdev = "";
217         char* tmp;
218         char buffer[OSP_TOKSTR_SIZE];
219         struct ast_osp_result result;
220         char* status;
221
222         AST_DECLARE_APP_ARGS(args,
223                 AST_APP_ARG(exten);
224                 AST_APP_ARG(provider);
225                 AST_APP_ARG(options);
226         );
227         
228         if (ast_strlen_zero(data)) {
229                 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
230                 return(-1);
231         }
232
233         LOCAL_USER_ADD(u);
234
235         if (!(tmp = ast_strdupa(data))) {
236                 ast_log(LOG_ERROR, "Out of memory\n");
237                 LOCAL_USER_REMOVE(u);
238                 return(-1);
239         }
240
241         AST_STANDARD_APP_ARGS(args, tmp);
242
243         ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
244
245         if (!ast_strlen_zero(args.provider)) {
246                 provider = args.provider;
247         }
248         ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
249
250         if (args.options) {
251                 if (strchr(args.options, 'j')) {
252                         priority_jump = 1;
253                 }
254         }
255         ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
256
257         result.inhandle = OSP_INVALID_HANDLE;
258
259         headp = &chan->varshead;
260         AST_LIST_TRAVERSE(headp, current, entries) {
261                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
262                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
263                                 result.inhandle = OSP_INVALID_HANDLE;
264                         }
265                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
266                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
267                                 result.intimelimit = OSP_DEF_TIMELIMIT;
268                         }
269                 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
270                         srcdev = ast_var_value(current);
271                 }
272         }
273         ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
274         ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
275         ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
276
277         res = ast_osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result);
278         if (res > 0) {
279                 status = OSP_APP_SUCCESS;
280         } else {
281                 result.tech[0] = '\0';
282                 result.dest[0] = '\0';
283                 result.calling[0] = '\0';
284                 result.token[0] = '\0'; 
285                 result.numresults = 0;
286                 result.outtimelimit = OSP_DEF_TIMELIMIT;
287                 if (!res) {
288                         status = OSP_APP_FAILED;
289                 } else {
290                         result.outhandle = OSP_INVALID_HANDLE;
291                         status = OSP_APP_ERROR;
292                 }
293         }
294
295         snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
296         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
297         ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
298         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
299         ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
300         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
301         ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
302         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
303         ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
304         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
305         ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%d'\n", strlen(result.token));
306         if (!ast_strlen_zero(result.token)) {
307                 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
308                 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
309                 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%d'\n", strlen(buffer));
310         }
311         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
312         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
313         ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
314         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
315         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
316         ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
317         pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
318         ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
319
320         if(!res) {
321                 if (priority_jump || ast_opt_priority_jumping) {
322                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
323                 } else {
324                         res = -1;
325                 }
326         } else if (res > 0) {
327                 res = 0;
328         }
329
330         LOCAL_USER_REMOVE(u);
331
332         return(res);
333 }
334
335 static int str2cause(char *str)
336 {
337         int cause = AST_CAUSE_NORMAL;
338
339         if (ast_strlen_zero(str)) {
340                 cause = AST_CAUSE_NOTDEFINED;
341         } else if (!strcasecmp(str, "BUSY")) {
342                 cause = AST_CAUSE_BUSY;
343         } else if (!strcasecmp(str, "CONGESTION")) {
344                 cause = AST_CAUSE_CONGESTION;
345         } else if (!strcasecmp(str, "ANSWER")) {
346                 cause = AST_CAUSE_NORMAL;
347         } else if (!strcasecmp(str, "CANCEL")) {
348                 cause = AST_CAUSE_NORMAL;
349         } else if (!strcasecmp(str, "NOANSWER")) {
350                 cause = AST_CAUSE_NOANSWER;
351         } else if (!strcasecmp(str, "NOCHANAVAIL")) {
352                 cause = AST_CAUSE_CONGESTION;
353         } else {
354                 ast_log(LOG_WARNING, "OSP: Unknown cause '%s', using NORMAL\n", str);
355         }
356
357         return(cause);
358 }
359
360 static int ospnext_exec(struct ast_channel *chan, void *data)
361 {
362         int res=0;
363         struct localuser *u;
364         int priority_jump = 0;
365         int cause;
366         struct varshead* headp;
367         struct ast_var_t* current;
368         struct ast_osp_result result;
369         char *tmp;
370         char buffer[OSP_TOKSTR_SIZE];
371         char* status;
372
373         AST_DECLARE_APP_ARGS(args,
374                 AST_APP_ARG(cause);
375                 AST_APP_ARG(options);
376         );
377         
378         if (ast_strlen_zero(data)) {
379                 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n");
380                 return(-1);
381         }
382
383         LOCAL_USER_ADD(u);
384
385         if (!(tmp = ast_strdupa(data))) {
386                 ast_log(LOG_ERROR, "Out of memory\n");
387                 LOCAL_USER_REMOVE(u);
388                 return(-1);
389         }
390
391         AST_STANDARD_APP_ARGS(args, tmp);
392
393         cause = str2cause(args.cause);
394         ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
395
396         if (args.options) {
397                 if (strchr(args.options, 'j'))
398                         priority_jump = 1;
399         }
400         ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
401
402         result.inhandle = OSP_INVALID_HANDLE;
403         result.outhandle = OSP_INVALID_HANDLE;
404         result.numresults = 0;
405
406         headp = &chan->varshead;
407         AST_LIST_TRAVERSE(headp, current, entries) {
408                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
409                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
410                                 result.inhandle = OSP_INVALID_HANDLE;
411                         }
412                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
413                         if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
414                                 result.outhandle = OSP_INVALID_HANDLE;
415                         }
416                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMEOUT")) {
417                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
418                                 result.intimelimit = OSP_DEF_TIMELIMIT;
419                         }
420                 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
421                         if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
422                                 result.numresults = 0;
423                         }
424                 }
425         }
426         ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
427         ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
428         ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
429         ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
430
431         if ((res = ast_osp_next(cause, &result)) > 0) {
432                 status = OSP_APP_SUCCESS;
433         } else {
434                 result.tech[0] = '\0';
435                 result.dest[0] = '\0';
436                 result.calling[0] = '\0';
437                 result.token[0] = '\0'; 
438                 result.numresults = 0;
439                 result.outtimelimit = OSP_DEF_TIMELIMIT;
440                 if (!res) {
441                         status = OSP_APP_FAILED;
442                 } else {
443                         result.outhandle = OSP_INVALID_HANDLE;
444                         status = OSP_APP_ERROR;
445                 }
446         }
447
448         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
449         ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
450         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
451         ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
452         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
453         ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
454         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
455         ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%d'\n", strlen(result.token));
456         if (!ast_strlen_zero(result.token)) {
457                 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
458                 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
459                 ast_log(LOG_DEBUG, "OSPNext: SIPADDHEADER size '%d'\n", strlen(buffer));
460         }
461         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
462         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
463         ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
464         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
465         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
466         ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
467         pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
468         ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
469
470         if(!res) {
471                 if (priority_jump || ast_opt_priority_jumping) {
472                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
473                 } else {
474                         res = -1;
475                 }
476         } else if (res > 0) {
477                 res = 0;
478         }
479
480         LOCAL_USER_REMOVE(u);
481
482         return(res);
483 }
484
485 static int ospfinished_exec(struct ast_channel *chan, void *data)
486 {
487         int res = 1;
488         struct localuser* u;
489         int priority_jump = 0;
490         int cause;
491         struct varshead* headp;
492         struct ast_var_t* current;
493         int inhandle = OSP_INVALID_HANDLE;
494         int outhandle = OSP_INVALID_HANDLE;
495         int recorded = 0;
496         time_t start, connect, end;
497         char* tmp;
498         char* str = "";
499         char buffer[OSP_INTSTR_SIZE];
500         char* status;
501
502         AST_DECLARE_APP_ARGS(args,
503                 AST_APP_ARG(status);
504                 AST_APP_ARG(options);
505         );
506         
507         LOCAL_USER_ADD(u);
508
509         if (!(tmp = ast_strdupa(data))) {
510                 ast_log(LOG_ERROR, "Out of memory\n");
511                 LOCAL_USER_REMOVE(u);
512                 return(-1);
513         }
514
515         AST_STANDARD_APP_ARGS(args, tmp);
516
517         if (args.options) {
518                 if (strchr(args.options, 'j'))
519                         priority_jump = 1;
520         }
521         ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
522
523         headp = &chan->varshead;
524         AST_LIST_TRAVERSE(headp, current, entries) {
525                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
526                         if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
527                                 inhandle = OSP_INVALID_HANDLE;
528                         }
529                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
530                         if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
531                                 outhandle = OSP_INVALID_HANDLE;
532                         }
533                 } else if (!recorded &&
534                         (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
535                         !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") || 
536                         !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS"))) 
537                 {
538                         if (strcasecmp(ast_var_value(current), OSP_APP_SUCCESS)) {
539                                 recorded = 1;
540                         }
541                 }
542         }
543         ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
544         ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
545         ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
546
547         if (!recorded) {
548                 str = args.status;
549         }
550         cause = str2cause(str);
551         ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
552
553         if (chan->cdr) {
554                 start = chan->cdr->start.tv_sec;
555                 connect = chan->cdr->answer.tv_sec;
556                 if (connect) {
557                         end = time(NULL);
558                 } else {
559                         end = connect;
560                 }
561         } else {
562                 start = 0;
563                 connect = 0;
564                 end = 0;
565         }
566         ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
567         ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
568         ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
569
570         if (ast_osp_finish(outhandle, cause, start, connect, end) <= 0) {
571                 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for out_bound call\n");
572         }
573         if (ast_osp_finish(inhandle, cause, start, connect, end) <= 0) {
574                 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for in_bound call\n");
575         }
576         snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
577         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
578         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
579
580         if (res > 0) {
581                 status = OSP_APP_SUCCESS;
582         } else if (!res) {
583                 status = OSP_APP_FAILED;
584         } else {
585                 status = OSP_APP_ERROR;
586         }
587         pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
588
589         if(!res) {
590                 if (priority_jump || ast_opt_priority_jumping) {
591                         ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
592                 } else {
593                         res = -1;
594                 }
595         } else if (res > 0) {
596                 res = 0;
597         }
598
599         LOCAL_USER_REMOVE(u);
600
601         return(res);
602 }
603
604 static int load_module(void *mod)
605 {
606         int res;
607         
608         ast_osp_adduse();
609
610         res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
611         res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
612         res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
613         res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
614
615         return(res);
616 }
617
618 static int unload_module(void *mod)
619 {
620         int res;
621         
622         res = ast_unregister_application(app4);
623         res |= ast_unregister_application(app3);
624         res |= ast_unregister_application(app2);
625         res |= ast_unregister_application(app1);
626
627         STANDARD_HANGUP_LOCALUSERS;
628
629         ast_osp_deluse();
630
631         return(res);
632 }
633
634 static const char *description(void)
635 {
636         return "Open Settlement Protocol Applications";
637 }
638
639 static const char *key(void)
640 {
641         return(ASTERISK_GPL_KEY);
642 }
643
644 STD_MOD1;
645
646