app_osplookup.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*!
00020  * \file
00021  * \brief Open Settlement Protocol (OSP) Applications
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * \extref The OSP Toolkit: http://www.transnexus.com
00026  * \extref OpenSSL http://www.openssl.org
00027  *
00028  * \ingroup applications
00029  */
00030 
00031 /*** MODULEINFO
00032    <depend>osptk</depend>
00033    <depend>openssl</depend>
00034    <support_level>extended</support_level>
00035  ***/
00036 
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 429683 $")
00040 
00041 #include <osp/osp.h>
00042 #include <osp/osputils.h>
00043 #include <osp/ospb64.h>
00044 
00045 #include "asterisk/paths.h"
00046 #include "asterisk/lock.h"
00047 #include "asterisk/config.h"
00048 #include "asterisk/utils.h"
00049 #include "asterisk/causes.h"
00050 #include "asterisk/channel.h"
00051 #include "asterisk/app.h"
00052 #include "asterisk/module.h"
00053 #include "asterisk/pbx.h"
00054 #include "asterisk/cli.h"
00055 #include "asterisk/astosp.h"
00056 
00057 /*** DOCUMENTATION
00058    <application name="OSPAuth" language="en_US">
00059       <synopsis>
00060          OSP Authentication.
00061       </synopsis>
00062       <syntax>
00063          <parameter name="provider">
00064             <para>The name of the provider that authenticates the call.</para>
00065          </parameter>
00066          <parameter name="options">
00067             <para>Reserverd.</para>
00068          </parameter>
00069       </syntax>
00070       <description>
00071          <para>Authenticate a call by OSP.</para>
00072          <para>Input variables:</para>
00073          <variablelist>
00074             <variable name="OSPINPEERIP">
00075                <para>The last hop IP address.</para>
00076             </variable>
00077             <variable name="OSPINTOKEN">
00078                <para>The inbound OSP token.</para>
00079             </variable>
00080          </variablelist>
00081          <para>Output variables:</para>
00082          <variablelist>
00083             <variable name="OSPINHANDLE">
00084                <para>The inbound call OSP transaction handle.</para>
00085             </variable>
00086             <variable name="OSPINTIMELIMIT">
00087                <para>The inbound call duration limit in seconds.</para>
00088             </variable>
00089          </variablelist>
00090          <para>This application sets the following channel variable upon completion:</para>
00091          <variablelist>
00092             <variable name="OSPAUTHSTATUS">
00093                <para>The status of OSPAuth attempt as a text string, one of</para>
00094                <value name="SUCCESS" />
00095                <value name="FAILED" />
00096                <value name="ERROR" />
00097             </variable>
00098          </variablelist>
00099       </description>
00100       <see-also>
00101          <ref type="application">OSPLookup</ref>
00102          <ref type="application">OSPNext</ref>
00103          <ref type="application">OSPFinish</ref>
00104       </see-also>
00105    </application>
00106    <application name="OSPLookup" language="en_US">
00107       <synopsis>
00108          Lookup destination by OSP.
00109       </synopsis>
00110       <syntax>
00111          <parameter name="exten" required="true">
00112             <para>The exten of the call.</para>
00113          </parameter>
00114          <parameter name="provider">
00115             <para>The name of the provider that is used to route the call.</para>
00116          </parameter>
00117          <parameter name="options">
00118             <enumlist>
00119                <enum name="h">
00120                   <para>generate H323 call id for the outbound call</para>
00121                </enum>
00122                <enum name="s">
00123                   <para>generate SIP call id for the outbound call. Have not been implemented</para>
00124                </enum>
00125                <enum name="i">
00126                   <para>generate IAX call id for the outbound call. Have not been implemented</para>
00127                </enum>
00128             </enumlist>
00129          </parameter>
00130       </syntax>
00131       <description>
00132          <para>Looks up destination via OSP.</para>
00133          <para>Input variables:</para>
00134          <variablelist>
00135             <variable name="OSPINACTUALSRC">
00136                <para>The actual source device IP address in indirect mode.</para>
00137             </variable>
00138             <variable name="OSPINPEERIP">
00139                <para>The last hop IP address.</para>
00140             </variable>
00141             <variable name="OSPINTECH">
00142                <para>The inbound channel technology for the call.</para>
00143             </variable>
00144             <variable name="OSPINHANDLE">
00145                <para>The inbound call OSP transaction handle.</para>
00146             </variable>
00147             <variable name="OSPINTIMELIMIT">
00148                <para>The inbound call duration limit in seconds.</para>
00149             </variable>
00150             <variable name="OSPINNETWORKID">
00151                <para>The inbound source network ID.</para>
00152             </variable>
00153             <variable name="OSPINNPRN">
00154                <para>The inbound routing number.</para>
00155             </variable>
00156             <variable name="OSPINNPCIC">
00157                <para>The inbound carrier identification code.</para>
00158             </variable>
00159             <variable name="OSPINNPDI">
00160                <para>The inbound number portability database dip indicator.</para>
00161             </variable>
00162             <variable name="OSPINSPID">
00163                <para>The inbound service provider identity.</para>
00164             </variable>
00165             <variable name="OSPINOCN">
00166                <para>The inbound operator company number.</para>
00167             </variable>
00168             <variable name="OSPINSPN">
00169                <para>The inbound service provider name.</para>
00170             </variable>
00171             <variable name="OSPINALTSPN">
00172                <para>The inbound alternate service provider name.</para>
00173             </variable>
00174             <variable name="OSPINMCC">
00175                <para>The inbound mobile country code.</para>
00176             </variable>
00177             <variable name="OSPINMNC">
00178                <para>The inbound mobile network code.</para>
00179             </variable>
00180             <variable name="OSPINTOHOST">
00181                <para>The inbound To header host part.</para>
00182             </variable>
00183             <variable name="OSPINRPIDUSER">
00184                <para>The inbound Remote-Party-ID header user part.</para>
00185             </variable>
00186             <variable name="OSPINPAIUSER">
00187                <para>The inbound P-Asserted-Identify header user part.</para>
00188             </variable>
00189             <variable name="OSPINDIVUSER">
00190                <para>The inbound Diversion header user part.</para>
00191             </variable>
00192             <variable name="OSPINDIVHOST">
00193                <para>The inbound Diversion header host part.</para>
00194             </variable>
00195             <variable name="OSPINPCIUSER">
00196                <para>The inbound P-Charge-Info header user part.</para>
00197             </variable>
00198             <variable name="OSPINCUSTOMINFOn">
00199                <para>The inbound custom information, where <literal>n</literal> is the index beginning with <literal>1</literal>
00200                upto <literal>8</literal>.</para>
00201             </variable>
00202          </variablelist>
00203          <para>Output variables:</para>
00204          <variablelist>
00205             <variable name="OSPOUTHANDLE">
00206                <para>The outbound call OSP transaction handle.</para>
00207             </variable>
00208             <variable name="OSPOUTTECH">
00209                <para>The outbound channel technology for the call.</para>
00210             </variable>
00211             <variable name="OSPDESTINATION">
00212                <para>The outbound destination IP address.</para>
00213             </variable>
00214             <variable name="OSPOUTCALLING">
00215                <para>The outbound calling number.</para>
00216             </variable>
00217             <variable name="OSPOUTCALLED">
00218                <para>The outbound called number.</para>
00219             </variable>
00220             <variable name="OSPOUTNETWORKID">
00221                <para>The outbound destination network ID.</para>
00222             </variable>
00223             <variable name="OSPOUTNPRN">
00224                <para>The outbound routing number.</para>
00225             </variable>
00226             <variable name="OSPOUTNPCIC">
00227                <para>The outbound carrier identification code.</para>
00228             </variable>
00229             <variable name="OSPOUTNPDI">
00230                <para>The outbound number portability database dip indicator.</para>
00231             </variable>
00232             <variable name="OSPOUTSPID">
00233                <para>The outbound service provider identity.</para>
00234             </variable>
00235             <variable name="OSPOUTOCN">
00236                <para>The outbound operator company number.</para>
00237             </variable>
00238             <variable name="OSPOUTSPN">
00239                <para>The outbound service provider name.</para>
00240             </variable>
00241             <variable name="OSPOUTALTSPN">
00242                <para>The outbound alternate service provider name.</para>
00243             </variable>
00244             <variable name="OSPOUTMCC">
00245                <para>The outbound mobile country code.</para>
00246             </variable>
00247             <variable name="OSPOUTMNC">
00248                <para>The outbound mobile network code.</para>
00249             </variable>
00250             <variable name="OSPOUTTOKEN">
00251                <para>The outbound OSP token.</para>
00252             </variable>
00253             <variable name="OSPDESTREMAILS">
00254                <para>The number of remained destinations.</para>
00255             </variable>
00256             <variable name="OSPOUTTIMELIMIT">
00257                <para>The outbound call duration limit in seconds.</para>
00258             </variable>
00259             <variable name="OSPOUTCALLIDTYPES">
00260                <para>The outbound Call-ID types.</para>
00261             </variable>
00262             <variable name="OSPOUTCALLID">
00263                <para>The outbound Call-ID. Only for H.323.</para>
00264             </variable>
00265             <variable name="OSPDIALSTR">
00266                <para>The outbound Dial command string.</para>
00267             </variable>
00268          </variablelist>
00269          <para>This application sets the following channel variable upon completion:</para>
00270          <variablelist>
00271             <variable name="OSPLOOKUPSTATUS">
00272                <para>The status of OSPLookup attempt as a text string, one of</para>
00273                <value name="SUCCESS" />
00274                <value name="FAILED" />
00275                <value name="ERROR" />
00276             </variable>
00277          </variablelist>
00278       </description>
00279       <see-also>
00280          <ref type="application">OSPAuth</ref>
00281          <ref type="application">OSPNext</ref>
00282          <ref type="application">OSPFinish</ref>
00283       </see-also>
00284    </application>
00285    <application name="OSPNext" language="en_US">
00286       <synopsis>
00287          Lookup next destination by OSP.
00288       </synopsis>
00289       <description>
00290          <para>Looks up the next destination via OSP.</para>
00291          <para>Input variables:</para>
00292          <variablelist>
00293             <variable name="OSPINHANDLE">
00294                <para>The inbound call OSP transaction handle.</para>
00295             </variable>
00296             <variable name="OSPOUTHANDLE">
00297                <para>The outbound call OSP transaction handle.</para>
00298             </variable>
00299             <variable name="OSPINTIMELIMIT">
00300                <para>The inbound call duration limit in seconds.</para>
00301             </variable>
00302             <variable name="OSPOUTCALLIDTYPES">
00303                <para>The outbound Call-ID types.</para>
00304             </variable>
00305             <variable name="OSPDESTREMAILS">
00306                <para>The number of remained destinations.</para>
00307             </variable>
00308          </variablelist>
00309          <para>Output variables:</para>
00310          <variablelist>
00311             <variable name="OSPOUTTECH">
00312                <para>The outbound channel technology.</para>
00313             </variable>
00314             <variable name="OSPDESTINATION">
00315                <para>The destination IP address.</para>
00316             </variable>
00317             <variable name="OSPOUTCALLING">
00318                <para>The outbound calling number.</para>
00319             </variable>
00320             <variable name="OSPOUTCALLED">
00321                <para>The outbound called number.</para>
00322             </variable>
00323             <variable name="OSPOUTNETWORKID">
00324                <para>The outbound destination network ID.</para>
00325             </variable>
00326             <variable name="OSPOUTNPRN">
00327                <para>The outbound routing number.</para>
00328             </variable>
00329             <variable name="OSPOUTNPCIC">
00330                <para>The outbound carrier identification code.</para>
00331             </variable>
00332             <variable name="OSPOUTNPDI">
00333                <para>The outbound number portability database dip indicator.</para>
00334             </variable>
00335             <variable name="OSPOUTSPID">
00336                <para>The outbound service provider identity.</para>
00337             </variable>
00338             <variable name="OSPOUTOCN">
00339                <para>The outbound operator company number.</para>
00340             </variable>
00341             <variable name="OSPOUTSPN">
00342                <para>The outbound service provider name.</para>
00343             </variable>
00344             <variable name="OSPOUTALTSPN">
00345                <para>The outbound alternate service provider name.</para>
00346             </variable>
00347             <variable name="OSPOUTMCC">
00348                <para>The outbound mobile country code.</para>
00349             </variable>
00350             <variable name="OSPOUTMNC">
00351                <para>The outbound mobile network code.</para>
00352             </variable>
00353             <variable name="OSPOUTTOKEN">
00354                <para>The outbound OSP token.</para>
00355             </variable>
00356             <variable name="OSPDESTREMAILS">
00357                <para>The number of remained destinations.</para>
00358             </variable>
00359             <variable name="OSPOUTTIMELIMIT">
00360                <para>The outbound call duration limit in seconds.</para>
00361             </variable>
00362             <variable name="OSPOUTCALLID">
00363                <para>The outbound Call-ID. Only for H.323.</para>
00364             </variable>
00365             <variable name="OSPDIALSTR">
00366                <para>The outbound Dial command string.</para>
00367             </variable>
00368          </variablelist>
00369          <para>This application sets the following channel variable upon completion:</para>
00370          <variablelist>
00371             <variable name="OSPNEXTSTATUS">
00372                <para>The status of the OSPNext attempt as a text string, one of</para>
00373                <value name="SUCCESS" />
00374                <value name="FAILED" />
00375                <value name="ERROR" />
00376             </variable>
00377          </variablelist>
00378       </description>
00379       <see-also>
00380          <ref type="application">OSPAuth</ref>
00381          <ref type="application">OSPLookup</ref>
00382          <ref type="application">OSPFinish</ref>
00383       </see-also>
00384    </application>
00385    <application name="OSPFinish" language="en_US">
00386       <synopsis>
00387          Report OSP entry.
00388       </synopsis>
00389       <syntax>
00390          <parameter name="cause">
00391             <para>Hangup cause.</para>
00392          </parameter>
00393          <parameter name="options">
00394             <para>Reserved.</para>
00395          </parameter>
00396       </syntax>
00397       <description>
00398          <para>Report call state.</para>
00399          <para>Input variables:</para>
00400          <variablelist>
00401             <variable name="OSPINHANDLE">
00402                <para>The inbound call OSP transaction handle.</para>
00403             </variable>
00404             <variable name="OSPOUTHANDLE">
00405                <para>The outbound call OSP transaction handle.</para>
00406             </variable>
00407             <variable name="OSPAUTHSTATUS">
00408                <para>The OSPAuth status.</para>
00409             </variable>
00410             <variable name="OSPLOOKUPSTATUS">
00411                <para>The OSPLookup status.</para>
00412             </variable>
00413             <variable name="OSPNEXTSTATUS">
00414                <para>The OSPNext status.</para>
00415             </variable>
00416             <variable name="OSPINAUDIOQOS">
00417                <para>The inbound call leg audio QoS string.</para>
00418             </variable>
00419             <variable name="OSPOUTAUDIOQOS">
00420                <para>The outbound call leg audio QoS string.</para>
00421             </variable>
00422          </variablelist>
00423          <para>This application sets the following channel variable upon completion:</para>
00424          <variablelist>
00425             <variable name="OSPFINISHSTATUS">
00426                <para>The status of the OSPFinish attempt as a text string, one of</para>
00427                <value name="SUCCESS" />
00428                <value name="FAILED" />
00429                <value name="ERROR" />
00430             </variable>
00431          </variablelist>
00432       </description>
00433       <see-also>
00434          <ref type="application">OSPAuth</ref>
00435          <ref type="application">OSPLookup</ref>
00436          <ref type="application">OSPNext</ref>
00437       </see-also>
00438    </application>
00439  ***/
00440 
00441 /* OSP Buffer Sizes */
00442 #define OSP_SIZE_INTSTR    ((unsigned int)16)         /* OSP signed/unsigned int string buffer size */
00443 #define OSP_SIZE_NORSTR    ((unsigned int)256)        /* OSP normal string buffer size */
00444 #define OSP_SIZE_KEYSTR    ((unsigned int)1024)    /* OSP certificate string buffer size */
00445 #define OSP_SIZE_TOKSTR    ((unsigned int)4096)    /* OSP token string buffer size */
00446 #define OSP_SIZE_TECHSTR   ((unsigned int)32)         /* OSP signed/unsigned int string buffer size */
00447 #define OSP_SIZE_UUID      ((unsigned int)16)         /* UUID size */
00448 #define OSP_SIZE_UUIDSTR   ((unsigned int)36)         /* UUID string size */
00449 #define OSP_SIZE_QOSSTR    ((unsigned int)1024)    /* QoS string buffer size */
00450 
00451 /* Call ID Type*/
00452 #define OSP_CALLID_UNDEF   ((unsigned int)0)       /* Undefined */
00453 #define OSP_CALLID_SIP     ((unsigned int)(1 << 0))   /* SIP */
00454 #define OSP_CALLID_H323    ((unsigned int)(1 << 1))   /* H.323 */
00455 #define OSP_CALLID_IAX     ((unsigned int)(1 << 2))   /* IAX2 */
00456 #define OSP_CALLID_MAXNUM  ((unsigned int)3)       /* Max number of call ID types */
00457 
00458 /* OSP Supported Destination Protocols */
00459 #define OSP_PROT_SIP    ((const char*)"SIP")    /* SIP protocol name */
00460 #define OSP_PROT_H323      ((const char*)"H323")      /* H.323 Q.931 protocol name*/
00461 #define OSP_PROT_IAX    ((const char*)"IAX")    /* IAX2 protocol name */
00462 #define OSP_PROT_SKYPE     ((const char*)"SKYPE")     /* Skype protocol name */
00463 
00464 /* OSP supported Destination Tech */
00465 #define OSP_TECH_SIP    ((const char*)"SIP")    /* SIP tech name */
00466 #define OSP_TECH_H323      ((const char*)"H323")      /* OH323 tech name */
00467 #define OSP_TECH_IAX    ((const char*)"IAX2")      /* IAX2 tech name */
00468 #define OSP_TECH_SKYPE     ((const char*)"SKYPE")     /* Skype tech name */
00469 
00470 /* SIP OSP header field name */
00471 #define OSP_SIP_HEADER     ((const char*)"P-OSP-Auth-Token")
00472 
00473 /* OSP Authentication Policy */
00474 enum osp_authpolicy {
00475    OSP_AUTH_NO = 0,  /* Accept any call */
00476    OSP_AUTH_YES,     /* Accept call with valid OSP token or without OSP token */
00477    OSP_AUTH_EXC      /* Only accept call with valid OSP token */
00478 };
00479 
00480 /* OSP Work Mode */
00481 enum osp_workmode {
00482    OSP_MODE_DIRECT= 0,  /* Direct */
00483    OSP_MODE_INDIRECT /* Indirect */
00484 };
00485 
00486 /* OSP Service Type */
00487 enum osp_srvtype {
00488    OSP_SRV_VOICE = 0,   /* Normal voice service */
00489    OSP_SRV_NPQUERY      /* Ported number query service */
00490 };
00491 
00492 /* OSP Constants */
00493 #define OSP_OK             ((int)1)             /* OSP function call successful */
00494 #define OSP_FAILED            ((int)0)             /* OSP function call failed */
00495 #define OSP_ERROR          ((int)-1)               /* OSP function call error */
00496 #define OSP_AST_OK            ((int)0)             /* Asterisk function call successful */
00497 #define OSP_AST_ERROR         ((int)-1)               /* Asterisk function call error */
00498 #define OSP_INVALID_HANDLE    ((int)-1)               /* Invalid OSP handle, provider, transaction etc. */
00499 #define OSP_CONFIG_FILE       ((const char*)"osp.conf")  /* OSP configuration file name */
00500 #define OSP_GENERAL_CAT       ((const char*)"general")   /* OSP global configuration context name */
00501 #define OSP_DEF_PROVIDER      ((const char*)"default")   /* OSP default provider context name */
00502 #define OSP_MAX_CERTS         ((unsigned int)10)         /* OSP max number of cacerts */
00503 #define OSP_MAX_SPOINTS       ((unsigned int)10)         /* OSP max number of service points */
00504 #define OSP_DEF_MAXCONNECT    ((unsigned int)20)         /* OSP default max_connections */
00505 #define OSP_MIN_MAXCONNECT    ((unsigned int)1)       /* OSP min max_connections */
00506 #define OSP_MAX_MAXCONNECT    ((unsigned int)1000)    /* OSP max max_connections */
00507 #define OSP_DEF_RETRYDELAY    ((unsigned int)0)       /* OSP default retry delay */
00508 #define OSP_MIN_RETRYDELAY    ((unsigned int)0)       /* OSP min retry delay */
00509 #define OSP_MAX_RETRYDELAY    ((unsigned int)10)         /* OSP max retry delay */
00510 #define OSP_DEF_RETRYLIMIT    ((unsigned int)2)       /* OSP default retry times */
00511 #define OSP_MIN_RETRYLIMIT    ((unsigned int)0)       /* OSP min retry times */
00512 #define OSP_MAX_RETRYLIMIT    ((unsigned int)100)        /* OSP max retry times */
00513 #define OSP_DEF_TIMEOUT       ((unsigned int)500)        /* OSP default timeout in ms */
00514 #define OSP_MIN_TIMEOUT       ((unsigned int)200)        /* OSP min timeout in ms */
00515 #define OSP_MAX_TIMEOUT       ((unsigned int)10000)      /* OSP max timeout in ms */
00516 #define OSP_DEF_AUTHPOLICY    OSP_AUTH_YES            /* OSP default auth policy, yes */
00517 #define OSP_AUDIT_URL         ((const char*)"localhost") /* OSP default Audit URL */
00518 #define OSP_LOCAL_VALIDATION  ((int)1)             /* Validate OSP token locally */
00519 #define OSP_SSL_LIFETIME      ((unsigned int)300)        /* SSL life time, in seconds */
00520 #define OSP_HTTP_PERSISTENCE  ((int)1)             /* In seconds */
00521 #define OSP_CUSTOMER_ID       ((const char*)"")       /* OSP customer ID */
00522 #define OSP_DEVICE_ID         ((const char*)"")       /* OSP device ID */
00523 #define OSP_DEF_MAXDESTS      ((unsigned int)12)         /* OSP default max number of destinations */
00524 #define OSP_DEF_TIMELIMIT     ((unsigned int)0)       /* OSP default duration limit, no limit */
00525 #define OSP_DEF_PROTOCOL      OSP_PROT_SIP            /* OSP default signaling protocol, SIP */
00526 #define OSP_DEF_WORKMODE      OSP_MODE_DIRECT            /* OSP default work mode, direct */
00527 #define OSP_DEF_SRVTYPE       OSP_SRV_VOICE           /* OSP default service type, voice */
00528 #define OSP_MAX_CUSTOMINFO    ((unsigned int)8)       /* OSP max number of custom info */
00529 #define OSP_DEF_INTSTATS      ((int)-1)               /* OSP default int statistic */
00530 #define OSP_DEF_FLOATSTATS    ((float)-1)             /* OSP default float statistic */
00531 
00532 /* OSP Provider */
00533 struct osp_provider {
00534    OSPTPROVHANDLE handle;                    /* OSP provider handle */
00535    char name[OSP_SIZE_NORSTR];                  /* OSP provider context name */
00536    char privatekey[OSP_SIZE_NORSTR];            /* OSP private key file name */
00537    char localcert[OSP_SIZE_NORSTR];          /* OSP local cert file name */
00538    unsigned int canum;                       /* Number of cacerts */
00539    char cacerts[OSP_MAX_CERTS][OSP_SIZE_NORSTR];   /* Cacert file names */
00540    unsigned int spnum;                       /* Number of service points */
00541    char spoints[OSP_MAX_SPOINTS][OSP_SIZE_NORSTR]; /* Service point URLs */
00542    unsigned int maxconnect;                  /* Max number of connections */
00543    unsigned int retrydelay;                  /* Retry delay */
00544    unsigned int retrylimit;                  /* Retry limit */
00545    unsigned int timeout;                     /* Timeout in ms */
00546    char source[OSP_SIZE_NORSTR];             /* IP of self */
00547    enum osp_authpolicy authpolicy;              /* OSP authentication policy */
00548    const char* defprotocol;                  /* OSP default signaling protocol */
00549    enum osp_workmode workmode;                  /* OSP work mode */
00550    enum osp_srvtype srvtype;                 /* OSP service type */
00551    struct osp_provider* next;                /* Pointer to next OSP provider */
00552 };
00553 
00554 /* Call ID */
00555 struct osp_callid {
00556    unsigned char buf[OSP_SIZE_NORSTR];    /* Call ID string */
00557    unsigned int len;                /* Call ID length */
00558 };
00559 
00560 /* Number Portability Data */
00561 struct osp_npdata {
00562    const char* rn;                     /* Rounding Number */
00563    const char* cic;                 /* Carrier Identification Code */
00564    int npdi;                        /* NP Database Dip Indicator */
00565    const char* opname[OSPC_OPNAME_NUMBER];   /* Operator Names */
00566 };
00567 
00568 /* SIP Header Parameters */
00569 struct osp_headers {
00570    const char* rpiduser;               /* Remote-Party-ID header user info */
00571    const char* paiuser;             /* P-Asserted-Identity header user info */
00572    const char* divuser;             /* Diversion header user info */
00573    const char* divhost;             /* Diversion header host info */
00574    const char* pciuser;             /* P-Charge-Info header user info */
00575 };
00576 
00577 /* OSP Application In/Output Results */
00578 struct osp_results {
00579    int inhandle;                             /* Inbound transaction handle */
00580    int outhandle;                            /* Outbound transaction handle */
00581    unsigned int intimelimit;                    /* Inbound duration limit */
00582    unsigned int outtimelimit;                   /* Outbound duration limit */
00583    char intech[OSP_SIZE_TECHSTR];                  /* Inbound Asterisk TECH string */
00584    char outtech[OSP_SIZE_TECHSTR];                 /* Outbound Asterisk TECH string */
00585    char dest[OSP_SIZE_NORSTR];                     /* Outbound destination IP address */
00586    char calling[OSP_SIZE_NORSTR];                  /* Outbound calling number, may be translated */
00587    char called[OSP_SIZE_NORSTR];                /* Outbound called number, may be translated */
00588    char token[OSP_SIZE_TOKSTR];                 /* Outbound OSP token */
00589    char networkid[OSP_SIZE_NORSTR];             /* Outbound network ID */
00590    char nprn[OSP_SIZE_NORSTR];                     /* Outbound NP routing number */
00591    char npcic[OSP_SIZE_NORSTR];                 /* Outbound NP carrier identification code */
00592    int npdi;                                 /* Outbound NP database dip indicator */
00593    char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR];  /* Outbound Operator names */
00594    unsigned int numdests;                       /* Number of remain outbound destinations */
00595    struct osp_callid outcallid;                 /* Outbound call ID */
00596 };
00597 
00598 /* OSP Call Leg */
00599 enum osp_callleg {
00600    OSP_CALL_INBOUND, /* Inbound call leg */
00601    OSP_CALL_OUTBOUND /* Outbound call leg */
00602 };
00603 
00604 /* OSP Media Stream Direction */
00605 enum osp_direction {
00606    OSP_DIR_RX = 0,      /* Receive */
00607    OSP_DIR_TX,       /* Send */
00608    OSP_DIR_NUMBER    /* Number of directions */
00609 };
00610 
00611 /* OSP Metrics */
00612 struct osp_metrics {
00613    int value;        /* Value */
00614    float min;        /* Minimum */
00615    float max;        /* Maximum */
00616    float avg;        /* Average */
00617    float sdev;       /* Standard deviation */
00618 };
00619 
00620 /* OSP Module Global Variables */
00621 AST_MUTEX_DEFINE_STATIC(osp_lock);                    /* Lock of OSP provider list */
00622 static int osp_initialized = 0;                       /* Init flag */
00623 static int osp_hardware = 0;                       /* Hardware acceleration flag */
00624 static int osp_security = 0;                       /* Using security features flag */
00625 static struct osp_provider* osp_providers = NULL;        /* OSP provider list */
00626 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
00627 
00628 /* OSP default certificates */
00629 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
00630 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
00631 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
00632 
00633 /* OSP Client Wrapper APIs */
00634 
00635 /*!
00636  * \brief Create OSP provider handle according to configuration
00637  * \param cfg OSP configuration
00638  * \param name OSP provider context name
00639  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
00640  */
00641 static int osp_create_provider(
00642    struct ast_config* cfg,
00643    const char* name)
00644 {
00645    int res = OSP_FAILED;
00646    struct ast_variable* var;
00647    struct osp_provider* provider;
00648    OSPTPRIVATEKEY privatekey;
00649    OSPT_CERT localcert;
00650    OSPT_CERT cacerts[OSP_MAX_CERTS];
00651    const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
00652    const char* pspoints[OSP_MAX_SPOINTS];
00653    unsigned char privatekeydata[OSP_SIZE_KEYSTR];
00654    unsigned char localcertdata[OSP_SIZE_KEYSTR];
00655    unsigned char cacertdata[OSP_SIZE_KEYSTR];
00656    int i, num, error = OSPC_ERR_NO_ERROR;
00657 
00658    if (!(provider = ast_calloc(1, sizeof(*provider)))) {
00659       ast_log(LOG_ERROR, "Out of memory\n");
00660       return OSP_ERROR;
00661    }
00662 
00663    /* ast_calloc has set 0 in provider */
00664    provider->handle = OSP_INVALID_HANDLE;
00665    ast_copy_string(provider->name, name, sizeof(provider->name));
00666    snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, name);
00667    snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, name);
00668    snprintf(provider->cacerts[0], sizeof(provider->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, name);
00669    provider->maxconnect = OSP_DEF_MAXCONNECT;
00670    provider->retrydelay = OSP_DEF_RETRYDELAY;
00671    provider->retrylimit = OSP_DEF_RETRYLIMIT;
00672    provider->timeout = OSP_DEF_TIMEOUT;
00673    provider->authpolicy = OSP_DEF_AUTHPOLICY;
00674    provider->defprotocol = OSP_DEF_PROTOCOL;
00675    provider->workmode = OSP_DEF_WORKMODE;
00676    provider->srvtype = OSP_DEF_SRVTYPE;
00677 
00678    for (var = ast_variable_browse(cfg, name); var != NULL; var = var->next) {
00679       if (!strcasecmp(var->name, "privatekey")) {
00680          if (osp_security) {
00681             if (var->value[0] == '/') {
00682                ast_copy_string(provider->privatekey, var->value, sizeof(provider->privatekey));
00683             } else {
00684                snprintf(provider->privatekey, sizeof(provider->privatekey), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00685             }
00686             ast_debug(1, "OSP: privatekey '%s'\n", provider->privatekey);
00687          }
00688       } else if (!strcasecmp(var->name, "localcert")) {
00689          if (osp_security) {
00690             if (var->value[0] == '/') {
00691                ast_copy_string(provider->localcert, var->value, sizeof(provider->localcert));
00692             } else {
00693                snprintf(provider->localcert, sizeof(provider->localcert), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00694             }
00695             ast_debug(1, "OSP: localcert '%s'\n", provider->localcert);
00696          }
00697       } else if (!strcasecmp(var->name, "cacert")) {
00698          if (osp_security) {
00699             if (provider->canum < OSP_MAX_CERTS) {
00700                if (var->value[0] == '/') {
00701                   ast_copy_string(provider->cacerts[provider->canum], var->value, sizeof(provider->cacerts[provider->canum]));
00702                } else {
00703                   snprintf(provider->cacerts[provider->canum], sizeof(provider->cacerts[provider->canum]), "%s/%s", ast_config_AST_KEY_DIR, var->value);
00704                }
00705                ast_debug(1, "OSP: cacerts[%d]: '%s'\n", provider->canum, provider->cacerts[provider->canum]);
00706                provider->canum++;
00707             } else {
00708                ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", var->lineno);
00709             }
00710          }
00711       } else if (!strcasecmp(var->name, "servicepoint")) {
00712          if (provider->spnum < OSP_MAX_SPOINTS) {
00713             ast_copy_string(provider->spoints[provider->spnum], var->value, sizeof(provider->spoints[provider->spnum]));
00714             ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", provider->spnum, provider->spoints[provider->spnum]);
00715             provider->spnum++;
00716          } else {
00717             ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", var->lineno);
00718          }
00719       } else if (!strcasecmp(var->name, "maxconnect")) {
00720          if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_MAXCONNECT) && (num <= OSP_MAX_MAXCONNECT)) {
00721             provider->maxconnect = num;
00722             ast_debug(1, "OSP: maxconnect '%d'\n", num);
00723          } else {
00724             ast_log(LOG_WARNING, "OSP: maxconnect should be an integer from %d to %d, not '%s' at line %d\n",
00725                OSP_MIN_MAXCONNECT, OSP_MAX_MAXCONNECT, var->value, var->lineno);
00726          }
00727       } else if (!strcasecmp(var->name, "retrydelay")) {
00728          if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYDELAY) && (num <= OSP_MAX_RETRYDELAY)) {
00729             provider->retrydelay = num;
00730             ast_debug(1, "OSP: retrydelay '%d'\n", num);
00731          } else {
00732             ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
00733                OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, var->value, var->lineno);
00734          }
00735       } else if (!strcasecmp(var->name, "retrylimit")) {
00736          if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_RETRYLIMIT) && (num <= OSP_MAX_RETRYLIMIT)) {
00737             provider->retrylimit = num;
00738             ast_debug(1, "OSP: retrylimit '%d'\n", num);
00739          } else {
00740             ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
00741                OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, var->value, var->lineno);
00742          }
00743       } else if (!strcasecmp(var->name, "timeout")) {
00744          if ((sscanf(var->value, "%30d", &num) == 1) && (num >= OSP_MIN_TIMEOUT) && (num <= OSP_MAX_TIMEOUT)) {
00745             provider->timeout = num;
00746             ast_debug(1, "OSP: timeout '%d'\n", num);
00747          } else {
00748             ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
00749                OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, var->value, var->lineno);
00750          }
00751       } else if (!strcasecmp(var->name, "source")) {
00752          ast_copy_string(provider->source, var->value, sizeof(provider->source));
00753          ast_debug(1, "OSP: source '%s'\n", provider->source);
00754       } else if (!strcasecmp(var->name, "authpolicy")) {
00755          if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_AUTH_NO) || (num == OSP_AUTH_YES) || (num == OSP_AUTH_EXC))) {
00756             provider->authpolicy = num;
00757             ast_debug(1, "OSP: authpolicy '%d'\n", num);
00758          } else {
00759             ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
00760                OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXC, var->value, var->lineno);
00761          }
00762       } else if (!strcasecmp(var->name, "defprotocol")) {
00763          if (!strcasecmp(var->value, OSP_PROT_SIP)) {
00764             provider->defprotocol = OSP_PROT_SIP;
00765             ast_debug(1, "OSP: default protocol SIP\n");
00766          } else if (!strcasecmp(var->value, OSP_PROT_H323)) {
00767             provider->defprotocol = OSP_PROT_H323;
00768             ast_debug(1, "OSP: default protocol H.323\n");
00769          } else if (!strcasecmp(var->value, OSP_PROT_IAX)) {
00770             provider->defprotocol = OSP_PROT_IAX;
00771             ast_debug(1, "OSP: default protocol IAX\n");
00772          } else if (!strcasecmp(var->value, OSP_PROT_SKYPE)) {
00773             provider->defprotocol = OSP_PROT_SKYPE;
00774             ast_debug(1, "OSP: default protocol Skype\n");
00775          } else {
00776             ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s or %s not '%s' at line %d\n",
00777                OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_SKYPE, var->value, var->lineno);
00778          }
00779       } else if (!strcasecmp(var->name, "workmode")) {
00780          if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_MODE_DIRECT) || (num == OSP_MODE_INDIRECT))) {
00781             provider->workmode = num;
00782             ast_debug(1, "OSP: workmode '%d'\n", num);
00783          } else {
00784             ast_log(LOG_WARNING, "OSP: workmode should be %d or %d, not '%s' at line %d\n",
00785                OSP_MODE_DIRECT, OSP_MODE_INDIRECT, var->value, var->lineno);
00786          }
00787       } else if (!strcasecmp(var->name, "servicetype")) {
00788          if ((sscanf(var->value, "%30d", &num) == 1) && ((num == OSP_SRV_VOICE) || (num == OSP_SRV_NPQUERY))) {
00789             provider->srvtype = num;
00790             ast_debug(1, "OSP: servicetype '%d'\n", num);
00791          } else {
00792             ast_log(LOG_WARNING, "OSP: servicetype should be %d or %d, not '%s' at line %d\n",
00793                OSP_SRV_VOICE, OSP_SRV_NPQUERY, var->value, var->lineno);
00794          }
00795       }
00796    }
00797 
00798    if (provider->canum == 0) {
00799       provider->canum = 1;
00800    }
00801 
00802    for (i = 0; i < provider->spnum; i++) {
00803       pspoints[i] = provider->spoints[i];
00804    }
00805 
00806    if (osp_security) {
00807       privatekey.PrivateKeyData = NULL;
00808       privatekey.PrivateKeyLength = 0;
00809 
00810       localcert.CertData = NULL;
00811       localcert.CertDataLength = 0;
00812 
00813       for (i = 0; i < provider->canum; i++) {
00814          cacerts[i].CertData = NULL;
00815          cacerts[i].CertDataLength = 0;
00816       }
00817 
00818       if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)provider->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
00819          ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", provider->privatekey, error);
00820       } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
00821          ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", provider->localcert, error);
00822       } else {
00823          for (i = 0; i < provider->canum; i++) {
00824             if ((error = OSPPUtilLoadPEMCert((unsigned char*)provider->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
00825                ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", provider->cacerts[i], error);
00826                break;
00827             } else {
00828                pcacerts[i] = &cacerts[i];
00829             }
00830          }
00831       }
00832    } else {
00833       privatekey.PrivateKeyData = privatekeydata;
00834       privatekey.PrivateKeyLength = sizeof(privatekeydata);
00835 
00836       localcert.CertData = localcertdata;
00837       localcert.CertDataLength = sizeof(localcertdata);
00838 
00839       cacerts[0].CertData = cacertdata;
00840       cacerts[0].CertDataLength = sizeof(cacertdata);
00841       pcacerts[0] = &cacerts[0];
00842 
00843       if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
00844          ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
00845       } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
00846          ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
00847       } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
00848          ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
00849       }
00850    }
00851 
00852    if (error == OSPC_ERR_NO_ERROR) {
00853       error = OSPPProviderNew(provider->spnum,
00854          pspoints,
00855          NULL,
00856          OSP_AUDIT_URL,
00857          &privatekey,
00858          &localcert,
00859          provider->canum,
00860          pcacerts,
00861          OSP_LOCAL_VALIDATION,
00862          OSP_SSL_LIFETIME,
00863          provider->maxconnect,
00864          OSP_HTTP_PERSISTENCE,
00865          provider->retrydelay,
00866          provider->retrylimit,
00867          provider->timeout,
00868          OSP_CUSTOMER_ID,
00869          OSP_DEVICE_ID,
00870          &provider->handle);
00871       if (error != OSPC_ERR_NO_ERROR) {
00872          ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", name, error);
00873          res = OSP_ERROR;
00874       } else {
00875          ast_debug(1, "OSP: provider '%s'\n", name);
00876          ast_mutex_lock(&osp_lock);
00877          provider->next = osp_providers;
00878          osp_providers = provider;
00879          ast_mutex_unlock(&osp_lock);
00880          res = OSP_OK;
00881       }
00882    }
00883 
00884    if (osp_security) {
00885       for (i = 0; i < provider->canum; i++) {
00886          if (cacerts[i].CertData) {
00887             ast_free(cacerts[i].CertData);
00888          }
00889       }
00890       if (localcert.CertData) {
00891          ast_free(localcert.CertData);
00892       }
00893       if (privatekey.PrivateKeyData) {
00894          ast_free(privatekey.PrivateKeyData);
00895       }
00896    }
00897 
00898    if (res != OSP_OK) {
00899       ast_free(provider);
00900    }
00901 
00902    return res;
00903 }
00904 
00905 /*!
00906  * \brief Get OSP provider by name
00907  * \param name OSP provider context name
00908  * \param provider OSP provider structure
00909  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
00910  */
00911 static int osp_get_provider(
00912    const char* name,
00913    struct osp_provider** provider)
00914 {
00915    int res = OSP_FAILED;
00916    struct osp_provider* p;
00917 
00918    *provider = NULL;
00919 
00920    ast_mutex_lock(&osp_lock);
00921    for (p = osp_providers; p != NULL; p = p->next) {
00922       if (!strcasecmp(p->name, name)) {
00923          *provider = p;
00924          ast_debug(1, "OSP: find provider '%s'\n", name);
00925          res = OSP_OK;
00926          break;
00927       }
00928    }
00929    ast_mutex_unlock(&osp_lock);
00930 
00931    return res;
00932 }
00933 
00934 /*!
00935  * \brief Create OSP transaction handle
00936  * \param name OSP provider context name
00937  * \param trans OSP transaction handle, output
00938  * \param source Source of provider, output
00939  * \param srcsize Size of source buffer, in
00940  * \return OSK_OK Success, OSK_FAILED Failed, OSP_ERROR Error
00941  */
00942 static int osp_create_transaction(
00943    const char* name,
00944    int* trans,
00945    char* source,
00946    unsigned int srcsize)
00947 {
00948    int res = OSP_FAILED;
00949    struct osp_provider* provider;
00950    int error;
00951 
00952    if ((trans == NULL) || (source == NULL) || (srcsize <= 0)) {
00953       ast_log(LOG_ERROR, "Invalid parameters\n");
00954       return OSP_ERROR;
00955    }
00956 
00957    *trans = OSP_INVALID_HANDLE;
00958    *source = '\0';
00959 
00960    ast_mutex_lock(&osp_lock);
00961    for (provider = osp_providers; provider; provider = provider->next) {
00962       if (!strcasecmp(provider->name, name)) {
00963          error = OSPPTransactionNew(provider->handle, trans);
00964          if (error == OSPC_ERR_NO_ERROR) {
00965             ast_debug(1, "OSP: transaction '%d'\n", *trans);
00966             ast_copy_string(source, provider->source, srcsize);
00967             ast_debug(1, "OSP: source '%s'\n", source);
00968             res = OSP_OK;
00969          } else {
00970             *trans = OSP_INVALID_HANDLE;
00971             ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
00972             *source = '\0';
00973             res = OSP_ERROR;
00974          }
00975          break;
00976       }
00977    }
00978    ast_mutex_unlock(&osp_lock);
00979 
00980    return res;
00981 }
00982 
00983 /*!
00984  * \brief Convert "address:port" to "[x.x.x.x]:port" or "hostname:port" format
00985  * \param src Source address string
00986  * \param dest Destination address string
00987  * \param destsize Size of dest buffer
00988  */
00989 static void osp_convert_inout(
00990    const char* src,
00991    char* dest,
00992    unsigned int destsize)
00993 {
00994    struct in_addr inp;
00995    char buffer[OSP_SIZE_NORSTR];
00996    char* port;
00997 
00998    if ((dest != NULL) && (destsize > 0)) {
00999       if (!ast_strlen_zero(src)) {
01000          ast_copy_string(buffer, src, sizeof(buffer));
01001 
01002          if((port = strchr(buffer, ':')) != NULL) {
01003             *port = '\0';
01004             port++;
01005          }
01006 
01007          if (inet_pton(AF_INET, buffer, &inp) == 1) {
01008             if (port != NULL) {
01009                snprintf(dest, destsize, "[%s]:%s", buffer, port);
01010             } else {
01011                snprintf(dest, destsize, "[%s]", buffer);
01012             }
01013             dest[destsize - 1] = '\0';
01014          } else {
01015             ast_copy_string(dest, src, destsize);
01016          }
01017       } else {
01018          *dest = '\0';
01019       }
01020    }
01021 }
01022 
01023 /*!
01024  * \brief Convert "[x.x.x.x]:port" or "hostname:prot" to "address:port" format
01025  * \param src Source address string
01026  * \param dest Destination address string
01027  * \param destsize Size of dest buffer
01028  */
01029 static void osp_convert_outin(
01030    const char* src,
01031    char* dest,
01032    unsigned int destsize)
01033 {
01034    char buffer[OSP_SIZE_NORSTR];
01035    char* end;
01036    char* port;
01037 
01038    if ((dest != NULL) && (destsize > 0)) {
01039       if (!ast_strlen_zero(src)) {
01040          ast_copy_string(buffer, src, sizeof(buffer));
01041 
01042          if (buffer[0] == '[') {
01043             if((port = strchr(buffer + 1, ':')) != NULL) {
01044                *port = '\0';
01045                port++;
01046             }
01047 
01048             if ((end = strchr(buffer + 1, ']')) != NULL) {
01049                *end = '\0';
01050             }
01051 
01052             if (port != NULL) {
01053                snprintf(dest, destsize, "%s:%s", buffer + 1, port);
01054                dest[destsize - 1] = '\0';
01055             } else {
01056                ast_copy_string(dest, buffer + 1, destsize);
01057             }
01058          } else {
01059             ast_copy_string(dest, src, destsize);
01060          }
01061       } else {
01062          *dest = '\0';
01063       }
01064    }
01065 }
01066 
01067 /*!
01068  * \brief Validate OSP token of inbound call
01069  * \param trans OSP transaction handle
01070  * \param source Source of inbound call
01071  * \param destination Destination of inbound call
01072  * \param calling Calling number
01073  * \param called Called number
01074  * \param token OSP token, may be empty
01075  * \param timelimit Call duration limit, output
01076  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
01077  */
01078 static int osp_validate_token(
01079    int trans,
01080    const char* source,
01081    const char* destination,
01082    const char* calling,
01083    const char* called,
01084    const char* token,
01085    unsigned int* timelimit)
01086 {
01087    int res;
01088    int tokenlen;
01089    unsigned char tokenstr[OSP_SIZE_TOKSTR];
01090    char src[OSP_SIZE_NORSTR];
01091    char dest[OSP_SIZE_NORSTR];
01092    unsigned int authorised;
01093    unsigned int dummy = 0;
01094    int error;
01095 
01096    if (timelimit == NULL) {
01097       ast_log(LOG_ERROR, "Invalid parameters\n");
01098       return OSP_ERROR;
01099    }
01100 
01101    tokenlen = ast_base64decode(tokenstr, token, strlen(token));
01102    osp_convert_inout(source, src, sizeof(src));
01103    osp_convert_inout(destination, dest, sizeof(dest));
01104    error = OSPPTransactionValidateAuthorisation(trans,
01105       src,
01106       dest,
01107       NULL,
01108       NULL,
01109       calling ? calling : "",
01110       OSPC_NFORMAT_E164,
01111       called,
01112       OSPC_NFORMAT_E164,
01113       0,
01114       NULL,
01115       tokenlen,
01116       (char*)tokenstr,
01117       &authorised,
01118       timelimit,
01119       &dummy,
01120       NULL,
01121       osp_tokenformat);
01122    if (error != OSPC_ERR_NO_ERROR) {
01123       ast_log(LOG_WARNING, "OSP: Unable to validate inbound token, error '%d'\n", error);
01124       *timelimit = 0;
01125       res = OSP_ERROR;
01126    } else if (authorised) {
01127       ast_debug(1, "OSP: Authorised\n");
01128       res = OSP_OK;
01129    } else {
01130       ast_debug(1, "OSP: Unauthorised\n");
01131       res = OSP_FAILED;
01132    }
01133 
01134    return res;
01135 }
01136 
01137 /*!
01138  * \brief Choose min duration limit
01139  * \param in Inbound duration limit
01140  * \param out Outbound duration limit
01141  * \return min duration limit
01142  */
01143 static unsigned int osp_choose_timelimit(
01144    unsigned int in,
01145    unsigned int out)
01146 {
01147    if (in == OSP_DEF_TIMELIMIT) {
01148       return out;
01149    } else if (out == OSP_DEF_TIMELIMIT) {
01150       return in;
01151    } else {
01152       return in < out ? in : out;
01153    }
01154 }
01155 
01156 /*!
01157  * \brief Choose min duration limit
01158  * \param provider OSP provider
01159  * \param calling Calling number
01160  * \param called Called number
01161  * \param destination Destination IP in '[x.x.x.x]' format
01162  * \param tokenlen OSP token length
01163  * \param token OSP token
01164  * \param reason Failure reason, output
01165  * \param results OSP lookup results, in/output
01166  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
01167  */
01168 static int osp_check_destination(
01169    struct osp_provider* provider,
01170    const char* calling,
01171    const char* called,
01172    const char* destination,
01173    unsigned int tokenlen,
01174    const char* token,
01175    OSPEFAILREASON* reason,
01176    struct osp_results* results)
01177 {
01178    int res;
01179    OSPE_DEST_OSPENABLED enabled;
01180    OSPE_PROTOCOL_NAME protocol;
01181    char dest[OSP_SIZE_NORSTR];
01182    OSPE_OPERATOR_NAME type;
01183    int error;
01184 
01185    if ((provider == NULL) || (reason == NULL) || (results == NULL)) {
01186       ast_log(LOG_ERROR, "Invalid parameters\n");
01187       return OSP_ERROR;
01188    }
01189 
01190    if ((error = OSPPTransactionIsDestOSPEnabled(results->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
01191       ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
01192       *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
01193       return OSP_ERROR;
01194    }
01195 
01196    if (enabled == OSPC_DOSP_FALSE) {
01197       results->token[0] = '\0';
01198    } else {
01199       ast_base64encode(results->token, (const unsigned char*)token, tokenlen, sizeof(results->token) - 1);
01200    }
01201 
01202    if ((error = OSPPTransactionGetDestinationNetworkId(results->outhandle, sizeof(results->networkid), results->networkid)) != OSPC_ERR_NO_ERROR) {
01203       ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
01204       results->networkid[0] = '\0';
01205    }
01206 
01207    error = OSPPTransactionGetNumberPortabilityParameters(results->outhandle,
01208       sizeof(results->nprn),
01209       results->nprn,
01210       sizeof(results->npcic),
01211       results->npcic,
01212       &results->npdi);
01213    if (error != OSPC_ERR_NO_ERROR) {
01214       ast_debug(1, "OSP: Unable to get number portability parameters, error '%d'\n", error);
01215       results->nprn[0] = '\0';
01216       results->npcic[0] = '\0';
01217       results->npdi = 0;
01218    }
01219 
01220    for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01221       error = OSPPTransactionGetOperatorName(results->outhandle, type, sizeof(results->opname[type]), results->opname[type]);
01222       if (error != OSPC_ERR_NO_ERROR) {
01223          ast_debug(1, "OSP: Unable to get operator name of type '%d', error '%d'\n", type, error);
01224          results->opname[type][0] = '\0';
01225       }
01226    }
01227 
01228    if ((error = OSPPTransactionGetDestProtocol(results->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
01229       ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
01230       *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
01231       results->token[0] = '\0';
01232       results->networkid[0] = '\0';
01233       results->nprn[0] = '\0';
01234       results->npcic[0] = '\0';
01235       results->npdi = 0;
01236       for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01237          results->opname[type][0] = '\0';
01238       }
01239       return OSP_ERROR;
01240    }
01241 
01242    res = OSP_OK;
01243    osp_convert_outin(destination, dest, sizeof(dest));
01244    switch(protocol) {
01245    case OSPC_PROTNAME_SIP:
01246       ast_debug(1, "OSP: protocol SIP\n");
01247       ast_copy_string(results->outtech, OSP_TECH_SIP, sizeof(results->outtech));
01248       ast_copy_string(results->dest, dest, sizeof(results->dest));
01249       ast_copy_string(results->calling, calling, sizeof(results->calling));
01250       ast_copy_string(results->called, called, sizeof(results->called));
01251       break;
01252    case OSPC_PROTNAME_Q931:
01253       ast_debug(1, "OSP: protocol Q.931\n");
01254       ast_copy_string(results->outtech, OSP_TECH_H323, sizeof(results->outtech));
01255       ast_copy_string(results->dest, dest, sizeof(results->dest));
01256       ast_copy_string(results->calling, calling, sizeof(results->calling));
01257       ast_copy_string(results->called, called, sizeof(results->called));
01258       break;
01259    case OSPC_PROTNAME_IAX:
01260       ast_debug(1, "OSP: protocol IAX\n");
01261       ast_copy_string(results->outtech, OSP_TECH_IAX, sizeof(results->outtech));
01262       ast_copy_string(results->dest, dest, sizeof(results->dest));
01263       ast_copy_string(results->calling, calling, sizeof(results->calling));
01264       ast_copy_string(results->called, called, sizeof(results->called));
01265       break;
01266    case OSPC_PROTNAME_SKYPE:
01267       ast_debug(1, "OSP: protocol Skype\n");
01268       ast_copy_string(results->outtech, OSP_TECH_SKYPE, sizeof(results->outtech));
01269       ast_copy_string(results->dest, dest, sizeof(results->dest));
01270       ast_copy_string(results->calling, calling, sizeof(results->calling));
01271       ast_copy_string(results->called, called, sizeof(results->called));
01272       break;
01273    case OSPC_PROTNAME_UNDEFINED:
01274    case OSPC_PROTNAME_UNKNOWN:
01275       ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
01276       ast_debug(1, "OSP: use default protocol '%s'\n", provider->defprotocol);
01277       ast_copy_string(results->outtech, provider->defprotocol, sizeof(results->outtech));
01278       ast_copy_string(results->dest, dest, sizeof(results->dest));
01279       ast_copy_string(results->calling, calling, sizeof(results->calling));
01280       ast_copy_string(results->called, called, sizeof(results->called));
01281       break;
01282    case OSPC_PROTNAME_LRQ:
01283    case OSPC_PROTNAME_T37:
01284    case OSPC_PROTNAME_T38:
01285    case OSPC_PROTNAME_SMPP:
01286    case OSPC_PROTNAME_XMPP:
01287    default:
01288       ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
01289       *reason = OSPC_FAIL_PROTOCOL_ERROR;
01290       results->token[0] = '\0';
01291       results->networkid[0] = '\0';
01292       results->nprn[0] = '\0';
01293       results->npcic[0] = '\0';
01294       results->npdi = 0;
01295       for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01296          results->opname[type][0] = '\0';
01297       }
01298       res = OSP_FAILED;
01299       break;
01300    }
01301 
01302    return res;
01303 }
01304 
01305 /*!
01306  * \brief Convert Asterisk status to TC code
01307  * \param cause Asterisk hangup cause
01308  * \return OSP TC code
01309  */
01310 static OSPEFAILREASON asterisk2osp(
01311    int cause)
01312 {
01313    return (OSPEFAILREASON)cause;
01314 }
01315 
01316 /*!
01317  * \brief OSP Authentication function
01318  * \param name OSP provider context name
01319  * \param trans OSP transaction handle, output
01320  * \param source Source of inbound call
01321  * \param calling Calling number
01322  * \param called Called number
01323  * \param token OSP token, may be empty
01324  * \param timelimit Call duration limit, output
01325  * \return OSP_OK Authenricated, OSP_FAILED Unauthenticated, OSP_ERROR Error
01326  */
01327 static int osp_auth(
01328    const char* name,
01329    int* trans,
01330    const char* source,
01331    const char* calling,
01332    const char* called,
01333    const char* token,
01334    unsigned int* timelimit)
01335 {
01336    int res;
01337    struct osp_provider* provider = NULL;
01338    char dest[OSP_SIZE_NORSTR];
01339 
01340    if ((trans == NULL) || (timelimit == NULL)) {
01341       ast_log(LOG_ERROR, "Invalid parameters\n");
01342       return OSP_ERROR;
01343    }
01344 
01345    *trans = OSP_INVALID_HANDLE;
01346    *timelimit = OSP_DEF_TIMELIMIT;
01347 
01348    if ((res = osp_get_provider(name, &provider)) <= 0) {
01349       ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01350       return res;
01351    }
01352 
01353    switch (provider->authpolicy) {
01354    case OSP_AUTH_NO:
01355       res = OSP_OK;
01356       break;
01357    case OSP_AUTH_EXC:
01358       if (ast_strlen_zero(token)) {
01359          res = OSP_FAILED;
01360       } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
01361          ast_debug(1, "OSP: Unable to generate transaction handle\n");
01362          *trans = OSP_INVALID_HANDLE;
01363          res = OSP_FAILED;
01364       } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
01365          OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
01366       }
01367       break;
01368    case OSP_AUTH_YES:
01369    default:
01370       if (ast_strlen_zero(token)) {
01371          res = OSP_OK;
01372       } else if ((res = osp_create_transaction(name, trans, dest, sizeof(dest))) <= 0) {
01373          ast_debug(1, "OSP: Unable to generate transaction handle\n");
01374          *trans = OSP_INVALID_HANDLE;
01375          res = OSP_FAILED;
01376       } else if((res = osp_validate_token(*trans, source, dest, calling, called, token, timelimit)) <= 0) {
01377          OSPPTransactionRecordFailure(*trans, OSPC_FAIL_CALL_REJECTED);
01378       }
01379       break;
01380    }
01381 
01382    return res;
01383 }
01384 
01385 /*!
01386  * \brief Create a UUID
01387  * \param uuid UUID buffer
01388  * \param bufsize UUID buffer size
01389  * \return OSK_OK Created, OSP_ERROR Error
01390  */
01391 static int osp_create_uuid(
01392    unsigned char* uuid,
01393    unsigned int* bufsize)
01394 {
01395    int i, res;
01396    long int tmp[OSP_SIZE_UUID / sizeof(long int)];
01397 
01398    if ((uuid != NULL) && (*bufsize >= OSP_SIZE_UUID)) {
01399       for (i = 0; i < OSP_SIZE_UUID / sizeof(long int); i++) {
01400          tmp[i] = ast_random();
01401       }
01402       memcpy(uuid, tmp, OSP_SIZE_UUID);
01403       *bufsize = OSP_SIZE_UUID;
01404       res = OSP_OK;
01405    } else {
01406       ast_log(LOG_ERROR, "Invalid parameters\n");
01407       res = OSP_ERROR;
01408    }
01409 
01410    return res;
01411 }
01412 
01413 /*!
01414  * \brief UUID to string
01415  * \param uuid UUID
01416  * \param buffer String buffer
01417  * \param bufsize String buffer size
01418  * \return OSP_OK Successed, OSP_ERROR Error
01419  */
01420 static int osp_uuid2str(
01421    unsigned char* uuid,
01422    char* buffer,
01423    unsigned int bufsize)
01424 {
01425    int res;
01426 
01427    if ((uuid != NULL) && (bufsize > OSP_SIZE_UUIDSTR)) {
01428       snprintf(buffer, bufsize, "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-"
01429                  "%02hhx%02hhx-%02hhx%02hhx-"
01430                  "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
01431          uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
01432          uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
01433       res = OSP_OK;
01434    } else {
01435       ast_log(LOG_ERROR, "Invalid parameters\n");
01436       res = OSP_ERROR;
01437    }
01438 
01439    return res;
01440 }
01441 
01442 /*!
01443  * \brief Create a call ID according to the type
01444  * \param type Call ID type
01445  * \param callid Call ID buffer
01446  * \return OSK_OK Created, OSP_FAILED Not create, OSP_ERROR Error
01447  */
01448 static int osp_create_callid(
01449    unsigned int type,
01450    struct osp_callid* callid)
01451 {
01452    int res;
01453 
01454    if (callid == NULL) {
01455       ast_log(LOG_ERROR, "Invalid parameters\n");
01456       return OSP_ERROR;
01457    }
01458 
01459    callid->len = sizeof(callid->buf);
01460    switch (type) {
01461    case OSP_CALLID_H323:
01462       res = osp_create_uuid(callid->buf, &callid->len);
01463       break;
01464    case OSP_CALLID_SIP:
01465    case OSP_CALLID_IAX:
01466       res = OSP_FAILED;
01467       break;
01468    default:
01469       res = OSP_ERROR;
01470       break;
01471    }
01472 
01473    if ((res != OSP_OK) && (callid->len != 0)) {
01474       callid->buf[0] = '\0';
01475       callid->len = 0;
01476    }
01477 
01478    return res;
01479 }
01480 
01481 /*!
01482  * \brief OSP Lookup function
01483  * \param name OSP provider context name
01484  * \param callidtypes Call ID types
01485  * \param actualsrc Actual source device in indirect mode
01486  * \param srcdev Source device of outbound call
01487  * \param calling Calling number
01488  * \param called Called number
01489  * \param snetid Source network ID
01490  * \param np NP parameters
01491  * \param headers SIP header parameters
01492  * \param cinfo Custom info
01493  * \param results Lookup results
01494  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
01495  */
01496 static int osp_lookup(
01497    const char* name,
01498    unsigned int callidtypes,
01499    const char* actualsrc,
01500    const char* srcdev,
01501    const char* calling,
01502    const char* called,
01503    const char* snetid,
01504    struct osp_npdata* np,
01505    struct osp_headers* headers,
01506    const char* cinfo[],
01507    struct osp_results* results)
01508 {
01509    int res;
01510    struct osp_provider* provider = NULL;
01511    OSPE_PROTOCOL_NAME protocol;
01512    char source[OSP_SIZE_NORSTR];
01513    char callingnum[OSP_SIZE_NORSTR];
01514    char callednum[OSP_SIZE_NORSTR];
01515    char destination[OSP_SIZE_NORSTR];
01516    char* tmp;
01517    unsigned int tokenlen;
01518    char token[OSP_SIZE_TOKSTR];
01519    char src[OSP_SIZE_NORSTR];
01520    char dev[OSP_SIZE_NORSTR];
01521    char host[OSP_SIZE_NORSTR];
01522    unsigned int i, type;
01523    struct osp_callid callid;
01524    unsigned int callidnum;
01525    OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
01526    char dest[OSP_SIZE_NORSTR];
01527    const char* preferred[2] = { NULL };
01528    unsigned int dummy = 0;
01529    OSPEFAILREASON reason;
01530    int error;
01531 
01532    if (results == NULL) {
01533       ast_log(LOG_ERROR, "Invalid parameters\n");
01534       return OSP_ERROR;
01535    }
01536 
01537    osp_convert_inout(results->dest, dest, sizeof(dest));
01538 
01539    results->outhandle = OSP_INVALID_HANDLE;
01540    results->outtech[0] = '\0';
01541    results->calling[0] = '\0';
01542    results->called[0] = '\0';
01543    results->token[0] = '\0';
01544    results->networkid[0] = '\0';
01545    results->nprn[0] = '\0';
01546    results->npcic[0] = '\0';
01547    results->npdi = 0;
01548    for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01549       results->opname[type][0] = '\0';
01550    }
01551    results->numdests = 0;
01552    results->outtimelimit = OSP_DEF_TIMELIMIT;
01553 
01554    if ((res = osp_get_provider(name, &provider)) <= 0) {
01555       ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01556       return res;
01557    }
01558 
01559    if ((res = osp_create_transaction(name, &results->outhandle, source, sizeof(source))) <= 0) {
01560       ast_debug(1, "OSP: Unable to generate transaction handle\n");
01561       results->outhandle = OSP_INVALID_HANDLE;
01562       if (results->inhandle != OSP_INVALID_HANDLE) {
01563          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01564       }
01565       return OSP_ERROR;
01566    }
01567 
01568    if (!strcasecmp(results->intech, OSP_TECH_SIP)) {
01569       protocol = OSPC_PROTNAME_SIP;
01570    } else if (!strcasecmp(results->intech, OSP_TECH_H323)) {
01571       protocol = OSPC_PROTNAME_Q931;
01572    } else if (!strcasecmp(results->intech, OSP_TECH_IAX)) {
01573       protocol = OSPC_PROTNAME_IAX;
01574    } else if (!strcasecmp(results->intech, OSP_TECH_SKYPE)) {
01575       protocol = OSPC_PROTNAME_SKYPE;
01576    } else {
01577       protocol = OSPC_PROTNAME_SIP;
01578    }
01579    OSPPTransactionSetProtocol(results->outhandle, OSPC_PROTTYPE_SOURCE, protocol);
01580 
01581    if (!ast_strlen_zero(snetid)) {
01582       OSPPTransactionSetNetworkIds(results->outhandle, snetid, "");
01583    }
01584 
01585    OSPPTransactionSetNumberPortability(results->outhandle, np->rn, np->cic, np->npdi);
01586 
01587    for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01588       OSPPTransactionSetOperatorName(results->outhandle, type, np->opname[type]);
01589    }
01590 
01591     OSPPTransactionSetRemotePartyId(results->outhandle, OSPC_NFORMAT_E164, headers->rpiduser);
01592     OSPPTransactionSetAssertedId(results->outhandle, OSPC_NFORMAT_E164, headers->paiuser);
01593    osp_convert_inout(headers->divhost, host, sizeof(host));
01594    OSPPTransactionSetDiversion(results->outhandle, headers->divuser, host);
01595     OSPPTransactionSetChargeInfo(results->outhandle, OSPC_NFORMAT_E164, headers->pciuser);
01596 
01597    if (cinfo != NULL) {
01598       for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
01599          if (!ast_strlen_zero(cinfo[i])) {
01600             OSPPTransactionSetCustomInfo(results->outhandle, i, cinfo[i]);
01601          }
01602       }
01603    }
01604 
01605    ast_copy_string(callednum, called, sizeof(callednum));
01606    if((tmp = strchr(callednum, ';')) != NULL) {
01607       *tmp = '\0';
01608    }
01609 
01610    callidnum = 0;
01611    callids[0] = NULL;
01612    for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
01613       type = 1 << i;
01614       if (callidtypes & type) {
01615          error = osp_create_callid(type, &callid);
01616          if (error == 1) {
01617             callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
01618             callidnum++;
01619          }
01620       }
01621    }
01622 
01623    if (provider->workmode == OSP_MODE_INDIRECT) {
01624       osp_convert_inout(srcdev, src, sizeof(src));
01625       if (ast_strlen_zero(actualsrc)) {
01626          osp_convert_inout(srcdev, dev, sizeof(dev));
01627       } else {
01628          osp_convert_inout(actualsrc, dev, sizeof(dev));
01629       }
01630    } else {
01631       osp_convert_inout(source, src, sizeof(src));
01632       osp_convert_inout(srcdev, dev, sizeof(dev));
01633    }
01634 
01635    if (provider->srvtype == OSP_SRV_NPQUERY) {
01636       OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_NPQUERY);
01637       if (!ast_strlen_zero(dest)) {
01638          preferred[0] = dest;
01639       }
01640       results->numdests = 1;
01641    } else {
01642       OSPPTransactionSetServiceType(results->outhandle, OSPC_SERVICE_VOICE);
01643       results->numdests = OSP_DEF_MAXDESTS;
01644    }
01645 
01646    error = OSPPTransactionRequestAuthorisation(results->outhandle,
01647       src,
01648       dev,
01649       calling ? calling : "",
01650       OSPC_NFORMAT_E164,
01651       callednum,
01652       OSPC_NFORMAT_E164,
01653       NULL,
01654       callidnum,
01655       callids,
01656       preferred,
01657       &results->numdests,
01658       &dummy,
01659       NULL);
01660 
01661    for (i = 0; i < callidnum; i++) {
01662       OSPPCallIdDelete(&callids[i]);
01663    }
01664 
01665    if (error != OSPC_ERR_NO_ERROR) {
01666       ast_log(LOG_WARNING, "OSP: Unable to request authorization, error '%d'\n", error);
01667       results->numdests = 0;
01668       if (results->inhandle != OSP_INVALID_HANDLE) {
01669          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01670       }
01671       return OSP_ERROR;
01672    }
01673 
01674    if (!results->numdests) {
01675       ast_debug(1, "OSP: No more destination\n");
01676       if (results->inhandle != OSP_INVALID_HANDLE) {
01677          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01678       }
01679       return OSP_FAILED;
01680    }
01681 
01682    results->outcallid.len = sizeof(results->outcallid.buf);
01683    tokenlen = sizeof(token);
01684    error = OSPPTransactionGetFirstDestination(results->outhandle,
01685       0,
01686       NULL,
01687       NULL,
01688       &results->outtimelimit,
01689       &results->outcallid.len,
01690       results->outcallid.buf,
01691       sizeof(callednum),
01692       callednum,
01693       sizeof(callingnum),
01694       callingnum,
01695       sizeof(destination),
01696       destination,
01697       0,
01698       NULL,
01699       &tokenlen,
01700       token);
01701    if (error != OSPC_ERR_NO_ERROR) {
01702       ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
01703       results->numdests = 0;
01704       results->outtimelimit = OSP_DEF_TIMELIMIT;
01705       if (results->inhandle != OSP_INVALID_HANDLE) {
01706          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01707       }
01708       return OSP_ERROR;
01709    }
01710 
01711    results->numdests--;
01712    results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01713    ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01714    ast_debug(1, "OSP: calling '%s'\n", callingnum);
01715    ast_debug(1, "OSP: called '%s'\n", callednum);
01716    ast_debug(1, "OSP: destination '%s'\n", destination);
01717    ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01718 
01719    if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
01720       return OSP_OK;
01721    }
01722 
01723    if (!results->numdests) {
01724       ast_debug(1, "OSP: No more destination\n");
01725       results->outtimelimit = OSP_DEF_TIMELIMIT;
01726       OSPPTransactionRecordFailure(results->outhandle, reason);
01727       if (results->inhandle != OSP_INVALID_HANDLE) {
01728          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01729       }
01730       return OSP_FAILED;
01731    }
01732 
01733    while(results->numdests) {
01734       results->outcallid.len = sizeof(results->outcallid.buf);
01735       tokenlen = sizeof(token);
01736       error = OSPPTransactionGetNextDestination(results->outhandle,
01737          reason,
01738          0,
01739          NULL,
01740          NULL,
01741          &results->outtimelimit,
01742          &results->outcallid.len,
01743          results->outcallid.buf,
01744          sizeof(callednum),
01745          callednum,
01746          sizeof(callingnum),
01747          callingnum,
01748          sizeof(destination),
01749          destination,
01750          0,
01751          NULL,
01752          &tokenlen,
01753          token);
01754       if (error == OSPC_ERR_NO_ERROR) {
01755          results->numdests--;
01756          results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01757          ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01758          ast_debug(1, "OSP: calling '%s'\n", callingnum);
01759          ast_debug(1, "OSP: called '%s'\n", callednum);
01760          ast_debug(1, "OSP: destination '%s'\n", destination);
01761          ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01762 
01763          if ((res = osp_check_destination(provider, callingnum, callednum, destination, tokenlen, token, &reason, results)) > 0) {
01764             break;
01765          } else if (!results->numdests) {
01766             ast_debug(1, "OSP: No more destination\n");
01767             OSPPTransactionRecordFailure(results->outhandle, reason);
01768             if (results->inhandle != OSP_INVALID_HANDLE) {
01769                OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01770             }
01771             res = OSP_FAILED;
01772             break;
01773          }
01774       } else {
01775          ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01776          results->numdests = 0;
01777          results->outtimelimit = OSP_DEF_TIMELIMIT;
01778          if (results->inhandle != OSP_INVALID_HANDLE) {
01779             OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01780          }
01781          res = OSP_ERROR;
01782          break;
01783       }
01784    }
01785 
01786    return res;
01787 }
01788 
01789 /*!
01790  * \brief OSP Lookup Next function
01791  * \param name OSP provider name
01792  * \param cause Asterisk hangup cause
01793  * \param results Lookup results, in/output
01794  * \return OSP_OK Found , OSP_FAILED No route, OSP_ERROR Error
01795  */
01796 static int osp_next(
01797    const char* name,
01798    int cause,
01799    struct osp_results* results)
01800 {
01801    int res;
01802    struct osp_provider* provider = NULL;
01803    char calling[OSP_SIZE_NORSTR];
01804    char called[OSP_SIZE_NORSTR];
01805    char dest[OSP_SIZE_NORSTR];
01806    unsigned int tokenlen;
01807    char token[OSP_SIZE_TOKSTR];
01808    OSPEFAILREASON reason;
01809    OSPE_OPERATOR_NAME type;
01810    int error;
01811 
01812    if (results == NULL) {
01813       ast_log(LOG_ERROR, "Invalid parameters\n");
01814       return OSP_ERROR;
01815    }
01816 
01817    results->outtech[0] = '\0';
01818    results->dest[0] = '\0';
01819    results->calling[0] = '\0';
01820    results->called[0] = '\0';
01821    results->token[0] = '\0';
01822    results->networkid[0] = '\0';
01823    results->nprn[0] = '\0';
01824    results->npcic[0] = '\0';
01825    results->npdi = 0;
01826    for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
01827       results->opname[type][0] = '\0';
01828    }
01829    results->outtimelimit = OSP_DEF_TIMELIMIT;
01830 
01831    if ((res = osp_get_provider(name, &provider)) <= 0) {
01832       ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", name);
01833       return res;
01834    }
01835 
01836    if (results->outhandle == OSP_INVALID_HANDLE) {
01837       ast_debug(1, "OSP: Transaction handle undefined\n");
01838       results->numdests = 0;
01839       if (results->inhandle != OSP_INVALID_HANDLE) {
01840          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01841       }
01842       return OSP_ERROR;
01843    }
01844 
01845    reason = asterisk2osp(cause);
01846 
01847    if (!results->numdests) {
01848       ast_debug(1, "OSP: No more destination\n");
01849       OSPPTransactionRecordFailure(results->outhandle, reason);
01850       if (results->inhandle != OSP_INVALID_HANDLE) {
01851          OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01852       }
01853       return OSP_FAILED;
01854    }
01855 
01856    while(results->numdests) {
01857       results->outcallid.len = sizeof(results->outcallid.buf);
01858       tokenlen = sizeof(token);
01859       error = OSPPTransactionGetNextDestination(
01860          results->outhandle,
01861          reason,
01862          0,
01863          NULL,
01864          NULL,
01865          &results->outtimelimit,
01866          &results->outcallid.len,
01867          results->outcallid.buf,
01868          sizeof(called),
01869          called,
01870          sizeof(calling),
01871          calling,
01872          sizeof(dest),
01873          dest,
01874          0,
01875          NULL,
01876          &tokenlen,
01877          token);
01878       if (error == OSPC_ERR_NO_ERROR) {
01879          results->numdests--;
01880          results->outtimelimit = osp_choose_timelimit(results->intimelimit, results->outtimelimit);
01881          ast_debug(1, "OSP: outtimelimit '%d'\n", results->outtimelimit);
01882          ast_debug(1, "OSP: calling '%s'\n", calling);
01883          ast_debug(1, "OSP: called '%s'\n", called);
01884          ast_debug(1, "OSP: destination '%s'\n", dest);
01885          ast_debug(1, "OSP: token size '%d'\n", tokenlen);
01886 
01887          if ((res = osp_check_destination(provider, calling, called, dest, tokenlen, token, &reason, results)) > 0) {
01888             res = OSP_OK;
01889             break;
01890          } else if (!results->numdests) {
01891             ast_debug(1, "OSP: No more destination\n");
01892             OSPPTransactionRecordFailure(results->outhandle, reason);
01893             if (results->inhandle != OSP_INVALID_HANDLE) {
01894                OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
01895             }
01896             res = OSP_FAILED;
01897             break;
01898          }
01899       } else {
01900          ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
01901          results->token[0] = '\0';
01902          results->numdests = 0;
01903          results->outtimelimit = OSP_DEF_TIMELIMIT;
01904          if (results->inhandle != OSP_INVALID_HANDLE) {
01905             OSPPTransactionRecordFailure(results->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
01906          }
01907          res = OSP_ERROR;
01908          break;
01909       }
01910    }
01911 
01912    return res;
01913 }
01914 
01915 /*!
01916  * \brief Get integer from variable string
01917  * \param vstr Variable string
01918  * \return OSP_DEF_INTSTATS Error
01919  */
01920 static int osp_get_varint(
01921    const char* vstr)
01922 {
01923    char* tmp;
01924    int value = OSP_DEF_INTSTATS;
01925 
01926    if (!ast_strlen_zero(vstr)) {
01927       if ((tmp = strchr(vstr, '=')) != NULL) {
01928          tmp++;
01929          if (sscanf(tmp, "%30d", &value) != 1) {
01930             value = OSP_DEF_INTSTATS;
01931          }
01932       }
01933    }
01934 
01935    return value;
01936 }
01937 
01938 /*!
01939  * \brief Get float from variable string
01940  * \param vstr Variable string
01941  * \return OSP_DEF_FLOATSTATS Error
01942  */
01943 static float osp_get_varfloat(
01944    const char* vstr)
01945 {
01946    char* tmp;
01947    float value = OSP_DEF_FLOATSTATS;
01948 
01949    if (!ast_strlen_zero(vstr)) {
01950       if ((tmp = strchr(vstr, '=')) != NULL) {
01951          tmp++;
01952          if (sscanf(tmp, "%30f", &value) != 1) {
01953             value = OSP_DEF_FLOATSTATS;
01954          }
01955       }
01956    }
01957 
01958    return value;
01959 }
01960 
01961 /*!
01962  * \brief Report QoS
01963  * \param trans OSP in/outbound transaction handle
01964  * \param leg Inbound/outbound
01965  * \param qos QoS string
01966  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
01967  */
01968 static int osp_report_qos(
01969    int trans,
01970    enum osp_callleg leg,
01971    const char* qos)
01972 {
01973    int res = OSP_FAILED;
01974    enum osp_direction dir;
01975    char buffer[OSP_SIZE_NORSTR];
01976    char* tmp;
01977    char* item;
01978    int totalpackets[OSP_DIR_NUMBER];
01979    struct osp_metrics lost[OSP_DIR_NUMBER];
01980    struct osp_metrics jitter[OSP_DIR_NUMBER];
01981    struct osp_metrics rtt;
01982    int value;
01983 
01984    if (!ast_strlen_zero(qos)) {
01985       for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01986          totalpackets[dir] = OSP_DEF_INTSTATS;
01987       }
01988 
01989       for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01990          lost[dir].value = OSP_DEF_INTSTATS;
01991          lost[dir].min = OSP_DEF_FLOATSTATS;
01992          lost[dir].max = OSP_DEF_FLOATSTATS;
01993          lost[dir].avg = OSP_DEF_FLOATSTATS;
01994          lost[dir].sdev = OSP_DEF_FLOATSTATS;
01995       }
01996 
01997       for (dir = OSP_DIR_RX; dir < OSP_DIR_NUMBER; dir++) {
01998          jitter[dir].value = OSP_DEF_INTSTATS;
01999          jitter[dir].min = OSP_DEF_FLOATSTATS;
02000          jitter[dir].max = OSP_DEF_FLOATSTATS;
02001          jitter[dir].avg = OSP_DEF_FLOATSTATS;
02002          jitter[dir].sdev = OSP_DEF_FLOATSTATS;
02003       }
02004 
02005       rtt.value = OSP_DEF_INTSTATS;
02006       rtt.min = OSP_DEF_FLOATSTATS;
02007       rtt.max = OSP_DEF_FLOATSTATS;
02008       rtt.avg = OSP_DEF_FLOATSTATS;
02009       rtt.sdev = OSP_DEF_FLOATSTATS;
02010 
02011       ast_copy_string(buffer, qos, sizeof(buffer));
02012       for (item = strtok_r(buffer, ";", &tmp); item; item = strtok_r(NULL, ";", &tmp)) {
02013          if (!strncasecmp(item, "rxcount", strlen("rxcount"))) {
02014             totalpackets[OSP_DIR_RX] = osp_get_varint(item);
02015          } else if (!strncasecmp(item, "txcount", strlen("txcount"))) {
02016             totalpackets[OSP_DIR_TX] = osp_get_varint(item);
02017          } else if (!strncasecmp(item, "lp", strlen("lp"))) {
02018             lost[OSP_DIR_RX].value = osp_get_varint(item);
02019          } else if (!strncasecmp(item, "minrxlost", strlen("minrxlost"))) {
02020             lost[OSP_DIR_RX].min = osp_get_varfloat(item);
02021          } else if (!strncasecmp(item, "maxrxlost", strlen("maxrxlost"))) {
02022             lost[OSP_DIR_RX].max = osp_get_varfloat(item);
02023          } else if (!strncasecmp(item, "avgrxlost", strlen("avgrxlost"))) {
02024             lost[OSP_DIR_RX].avg = osp_get_varfloat(item);
02025          } else if (!strncasecmp(item, "stdevrxlost", strlen("stdevrxlost"))) {
02026             lost[OSP_DIR_RX].sdev = osp_get_varfloat(item);
02027          } else if (!strncasecmp(item, "rlp", strlen("rlp"))) {
02028             lost[OSP_DIR_TX].value = osp_get_varint(item);
02029          } else if (!strncasecmp(item, "reported_minlost", strlen("reported_minlost"))) {
02030             lost[OSP_DIR_TX].min = osp_get_varfloat(item);
02031          } else if (!strncasecmp(item, "reported_maxlost", strlen("reported_maxlost"))) {
02032             lost[OSP_DIR_TX].max = osp_get_varfloat(item);
02033          } else if (!strncasecmp(item, "reported_avglost", strlen("reported_avglost"))) {
02034             lost[OSP_DIR_TX].avg = osp_get_varfloat(item);
02035          } else if (!strncasecmp(item, "reported_stdevlost", strlen("reported_stdevlost"))) {
02036             lost[OSP_DIR_TX].sdev = osp_get_varfloat(item);
02037          } else if (!strncasecmp(item, "rxjitter", strlen("rxjitter"))) {
02038             jitter[OSP_DIR_RX].value = osp_get_varint(item);
02039          } else if (!strncasecmp(item, "minrxjitter", strlen("minrxjitter"))) {
02040             jitter[OSP_DIR_RX].min = osp_get_varfloat(item);
02041          } else if (!strncasecmp(item, "maxrxjitter", strlen("maxrxjitter"))) {
02042             jitter[OSP_DIR_RX].max = osp_get_varfloat(item);
02043          } else if (!strncasecmp(item, "avgrxjitter", strlen("avgjitter"))) {
02044             jitter[OSP_DIR_RX].avg = osp_get_varfloat(item);
02045          } else if (!strncasecmp(item, "stdevrxjitter", strlen("stdevjitter"))) {
02046             jitter[OSP_DIR_RX].sdev = osp_get_varfloat(item);
02047          } else if (!strncasecmp(item, "txjitter", strlen("txjitter"))) {
02048             jitter[OSP_DIR_TX].value = osp_get_varint(item);
02049          } else if (!strncasecmp(item, "reported_minjitter", strlen("reported_minjitter"))) {
02050             jitter[OSP_DIR_TX].min = osp_get_varfloat(item);
02051          } else if (!strncasecmp(item, "reported_maxjitter", strlen("reported_maxjitter"))) {
02052             jitter[OSP_DIR_TX].max = osp_get_varfloat(item);
02053          } else if (!strncasecmp(item, "reported_avgjitter", strlen("reported_avgjitter"))) {
02054             jitter[OSP_DIR_TX].avg = osp_get_varfloat(item);
02055          } else if (!strncasecmp(item, "reported_stdevjitter", strlen("reported_stdevjitter"))) {
02056             jitter[OSP_DIR_TX].sdev = osp_get_varfloat(item);
02057          } else if (!strncasecmp(item, "rtt", strlen("rtt"))) {
02058             rtt.value = osp_get_varint(item);
02059          } else if (!strncasecmp(item, "minrtt", strlen("minrtt"))) {
02060             rtt.min = osp_get_varfloat(item);
02061          } else if (!strncasecmp(item, "maxrtt", strlen("maxrtt"))) {
02062             rtt.max = osp_get_varfloat(item);
02063          } else if (!strncasecmp(item, "avgrtt", strlen("avgrtt"))) {
02064             rtt.avg = osp_get_varfloat(item);
02065          } else if (!strncasecmp(item, "stdevrtt", strlen("stdevrtt"))) {
02066             rtt.sdev = osp_get_varfloat(item);
02067          }
02068       }
02069 
02070       ast_debug(1, "OSP: call leg '%d'\n", leg);
02071       ast_debug(1, "OSP: rxcount '%d'\n", totalpackets[OSP_DIR_RX]);
02072       ast_debug(1, "OSP: txcount '%d'\n", totalpackets[OSP_DIR_TX]);
02073       ast_debug(1, "OSP: lp '%d'\n",lost[OSP_DIR_RX].value);
02074       ast_debug(1, "OSP: minrxlost '%f'\n", lost[OSP_DIR_RX].min);
02075       ast_debug(1, "OSP: maxrxlost '%f'\n", lost[OSP_DIR_RX].max);
02076       ast_debug(1, "OSP: avgrxlost '%f'\n", lost[OSP_DIR_RX].avg);
02077       ast_debug(1, "OSP: stdevrxlost '%f'\n", lost[OSP_DIR_RX].sdev);
02078       ast_debug(1, "OSP: rlp '%d'\n", lost[OSP_DIR_TX].value);
02079       ast_debug(1, "OSP: reported_minlost '%f'\n", lost[OSP_DIR_TX].min);
02080       ast_debug(1, "OSP: reported_maxlost '%f'\n", lost[OSP_DIR_TX].max);
02081       ast_debug(1, "OSP: reported_avglost '%f'\n", lost[OSP_DIR_TX].avg);
02082       ast_debug(1, "OSP: reported_stdevlost '%f'\n", lost[OSP_DIR_TX].sdev);
02083       ast_debug(1, "OSP: rxjitter '%d'\n", jitter[OSP_DIR_RX].value);
02084       ast_debug(1, "OSP: minrxjitter '%f'\n", jitter[OSP_DIR_RX].min);
02085       ast_debug(1, "OSP: maxrxjitter '%f'\n", jitter[OSP_DIR_RX].max);
02086       ast_debug(1, "OSP: avgrxjitter '%f'\n", jitter[OSP_DIR_RX].avg);
02087       ast_debug(1, "OSP: stdevrxjitter '%f'\n", jitter[OSP_DIR_RX].sdev);
02088       ast_debug(1, "OSP: txjitter '%d'\n", jitter[OSP_DIR_TX].value);
02089       ast_debug(1, "OSP: reported_minjitter '%f'\n", jitter[OSP_DIR_TX].min);
02090       ast_debug(1, "OSP: reported_maxjitter '%f'\n", jitter[OSP_DIR_TX].max);
02091       ast_debug(1, "OSP: reported_avgjitter '%f'\n", jitter[OSP_DIR_TX].avg);
02092       ast_debug(1, "OSP: reported_stdevjitter '%f'\n", jitter[OSP_DIR_TX].sdev);
02093       ast_debug(1, "OSP: rtt '%d'\n", rtt.value);
02094       ast_debug(1, "OSP: minrtt '%f'\n", rtt.min);
02095       ast_debug(1, "OSP: maxrtt '%f'\n", rtt.max);
02096       ast_debug(1, "OSP: avgrtt '%f'\n", rtt.avg);
02097       ast_debug(1, "OSP: stdevrtt '%f'\n", rtt.sdev);
02098 
02099       if (leg == OSP_CALL_INBOUND) {
02100          OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_RX]);
02101          OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_TX]);
02102          if (lost[OSP_DIR_RX].value >= 0) {
02103             value = lost[OSP_DIR_RX].value;
02104          } else {
02105             value = (int)lost[OSP_DIR_RX].avg;
02106          }
02107          OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, value, OSP_DEF_INTSTATS);
02108          if (lost[OSP_DIR_TX].value >= 0) {
02109             value = lost[OSP_DIR_TX].value;
02110          } else {
02111             value = (int)lost[OSP_DIR_TX].avg;
02112          }
02113          OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP, value, OSP_DEF_INTSTATS);
02114          if (jitter[OSP_DIR_RX].value >= 0) {
02115             value = jitter[OSP_DIR_RX].value;
02116          } else {
02117             value = (int)jitter[OSP_DIR_RX].avg;
02118          }
02119          OSPPTransactionSetJitter(trans,
02120             OSPC_SMETRIC_RTP,
02121             OSPC_SDIR_SRCREP,
02122             OSP_DEF_INTSTATS,
02123             (int)jitter[OSP_DIR_RX].min,
02124             (int)jitter[OSP_DIR_RX].max,
02125             value, jitter[OSP_DIR_RX].sdev);
02126          if (jitter[OSP_DIR_TX].value >= 0) {
02127             value = jitter[OSP_DIR_TX].value;
02128          } else {
02129             value = (int)jitter[OSP_DIR_TX].avg;
02130          }
02131          OSPPTransactionSetJitter(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_DESTREP,
02132             OSP_DEF_INTSTATS, (int)jitter[OSP_DIR_TX].min, (int)jitter[OSP_DIR_TX].max, value, jitter[OSP_DIR_TX].sdev);
02133       } else {
02134          OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, totalpackets[OSP_DIR_RX]);
02135          OSPPTransactionSetPackets(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, totalpackets[OSP_DIR_TX]);
02136          OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, lost[OSP_DIR_RX].value, OSP_DEF_INTSTATS);
02137          OSPPTransactionSetLost(trans, OSPC_SMETRIC_RTCP, OSPC_SDIR_SRCREP, lost[OSP_DIR_TX].value, OSP_DEF_INTSTATS);
02138          if (jitter[OSP_DIR_RX].value >= 0) {
02139             value = jitter[OSP_DIR_RX].value;
02140          } else {
02141             value = (int)jitter[OSP_DIR_RX].avg;
02142          }
02143          OSPPTransactionSetJitter(trans,
02144             OSPC_SMETRIC_RTP,
02145             OSPC_SDIR_DESTREP,
02146             OSP_DEF_INTSTATS,
02147             (int)jitter[OSP_DIR_RX].min,
02148             (int)jitter[OSP_DIR_RX].max,
02149             value,
02150             jitter[OSP_DIR_RX].sdev);
02151          if (jitter[OSP_DIR_TX].value >= 0) {
02152             value = jitter[OSP_DIR_TX].value;
02153          } else {
02154             value = (int)jitter[OSP_DIR_TX].avg;
02155          }
02156          OSPPTransactionSetJitter(trans,
02157             OSPC_SMETRIC_RTCP,
02158             OSPC_SDIR_SRCREP,
02159             OSP_DEF_INTSTATS,
02160             (int)jitter[OSP_DIR_TX].min,
02161             (int)jitter[OSP_DIR_TX].max,
02162             value,
02163             jitter[OSP_DIR_TX].sdev);
02164       }
02165 
02166       res = OSP_OK;
02167    }
02168 
02169    return res;
02170 }
02171 
02172 /*!
02173  * \brief OSP Finish function
02174  * \param trans OSP in/outbound transaction handle
02175  * \param recorded If failure reason has been recorded
02176  * \param cause Asterisk hangup cause
02177  * \param start Call start time
02178  * \param connect Call connect time
02179  * \param end Call end time
02180  * \param release Who release first, 0 source, 1 destination
02181  * \param inqos Inbound QoS string
02182  * \param outqos Outbound QoS string
02183  * \return OSP_OK Success, OSP_FAILED Failed, OSP_ERROR Error
02184  */
02185 static int osp_finish(
02186    int trans,
02187    int recorded,
02188    int cause,
02189    time_t start,
02190    time_t connect,
02191    time_t end,
02192    unsigned int release,
02193    const char* inqos,
02194    const char* outqos)
02195 {
02196    int res;
02197    OSPEFAILREASON reason;
02198    time_t alert = 0;
02199    unsigned isPddInfoPresent = 0;
02200    unsigned pdd = 0;
02201    unsigned int dummy = 0;
02202    int error;
02203 
02204    if (trans == OSP_INVALID_HANDLE) {
02205       return OSP_FAILED;
02206    }
02207 
02208    OSPPTransactionSetRoleInfo(trans, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_ASTERISK);
02209 
02210    if (!recorded) {
02211       reason = asterisk2osp(cause);
02212       OSPPTransactionRecordFailure(trans, reason);
02213    }
02214 
02215    osp_report_qos(trans, OSP_CALL_INBOUND, inqos);
02216    osp_report_qos(trans, OSP_CALL_OUTBOUND, outqos);
02217 
02218    error = OSPPTransactionReportUsage(trans,
02219       difftime(end, connect),
02220       start,
02221       end,
02222       alert,
02223       connect,
02224       isPddInfoPresent,
02225       pdd,
02226       release,
02227       NULL,
02228       OSP_DEF_INTSTATS,
02229       OSP_DEF_INTSTATS,
02230       OSP_DEF_INTSTATS,
02231       OSP_DEF_INTSTATS,
02232       &dummy,
02233       NULL);
02234    if (error == OSPC_ERR_NO_ERROR) {
02235       ast_debug(1, "OSP: Usage reported\n");
02236       res = OSP_OK;
02237    } else {
02238       ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
02239       res = OSP_ERROR;
02240    }
02241    OSPPTransactionDelete(trans);
02242 
02243    return res;
02244 }
02245 
02246 /* OSP Application APIs */
02247 
02248 /*!
02249  * \brief OSP Application OSPAuth
02250  * \param chan Channel
02251  * \param data Parameter
02252  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
02253  */
02254 static int ospauth_exec(
02255    struct ast_channel *chan,
02256    const char *data)
02257 {
02258    int res;
02259    const char* provider = OSP_DEF_PROVIDER;
02260    struct varshead* headp;
02261    struct ast_var_t* current;
02262    const char* source = "";
02263    const char* token = "";
02264    int handle;
02265    unsigned int timelimit;
02266    char buffer[OSP_SIZE_INTSTR];
02267    const char* status;
02268    char* tmp;
02269 
02270    AST_DECLARE_APP_ARGS(args,
02271       AST_APP_ARG(provider);
02272       AST_APP_ARG(options);
02273    );
02274 
02275    tmp = ast_strdupa(data);
02276 
02277    AST_STANDARD_APP_ARGS(args, tmp);
02278 
02279    if (!ast_strlen_zero(args.provider)) {
02280       provider = args.provider;
02281    }
02282    ast_debug(1, "OSPAuth: provider '%s'\n", provider);
02283 
02284    headp = ast_channel_varshead(chan);
02285    AST_LIST_TRAVERSE(headp, current, entries) {
02286       if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
02287          source = ast_var_value(current);
02288       } else if (!strcmp(ast_var_name(current), "OSPINTOKEN")) {
02289          token = ast_var_value(current);
02290       }
02291    }
02292 
02293    ast_debug(1, "OSPAuth: source '%s'\n", source);
02294    ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
02295 
02296    res = osp_auth(provider, &handle, source,
02297       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
02298       ast_channel_exten(chan), token, &timelimit);
02299    if (res > 0) {
02300       status = AST_OSP_SUCCESS;
02301    } else {
02302       timelimit = OSP_DEF_TIMELIMIT;
02303       if (!res) {
02304          status = AST_OSP_FAILED;
02305       } else {
02306          status = AST_OSP_ERROR;
02307       }
02308    }
02309 
02310    snprintf(buffer, sizeof(buffer), "%d", handle);
02311    pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02312    ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
02313    snprintf(buffer, sizeof(buffer), "%d", timelimit);
02314    pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
02315    ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
02316    pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
02317    ast_debug(1, "OSPAuth: %s\n", status);
02318 
02319    if(res != OSP_OK) {
02320       res = OSP_AST_ERROR;
02321    } else {
02322       res = OSP_AST_OK;
02323    }
02324 
02325    return res;
02326 }
02327 
02328 /*!
02329  * \brief OSP Application OSPLookup
02330  * \param chan Channel
02331  * \param data Parameter
02332  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
02333  */
02334 static int osplookup_exec(
02335    struct ast_channel* chan,
02336    const char * data)
02337 {
02338    int res;
02339    const char* provider = OSP_DEF_PROVIDER;
02340    unsigned int callidtypes = OSP_CALLID_UNDEF;
02341    struct varshead* headp;
02342    struct ast_var_t* current;
02343    const char* actualsrc = "";
02344    const char* srcdev = "";
02345    const char* snetid = "";
02346    struct osp_npdata np;
02347    OSPE_OPERATOR_NAME type;
02348    struct osp_headers headers;
02349    unsigned int i;
02350    const char* cinfo[OSP_MAX_CUSTOMINFO] = { NULL };
02351    char buffer[OSP_SIZE_TOKSTR];
02352    struct osp_results results;
02353    const char* status;
02354    char* tmp;
02355 
02356    AST_DECLARE_APP_ARGS(args,
02357       AST_APP_ARG(exten);
02358       AST_APP_ARG(provider);
02359       AST_APP_ARG(options);
02360    );
02361 
02362    if (ast_strlen_zero(data)) {
02363       ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[,provider[,options]])\n");
02364       return OSP_AST_ERROR;
02365    }
02366 
02367    tmp = ast_strdupa(data);
02368 
02369    AST_STANDARD_APP_ARGS(args, tmp);
02370 
02371    ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
02372 
02373    if (!ast_strlen_zero(args.provider)) {
02374       provider = args.provider;
02375    }
02376    ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02377 
02378    if (args.options) {
02379       if (strchr(args.options, 'h')) {
02380          callidtypes |= OSP_CALLID_H323;
02381       }
02382       if (strchr(args.options, 's')) {
02383          callidtypes |= OSP_CALLID_SIP;
02384       }
02385       if (strchr(args.options, 'i')) {
02386          callidtypes |= OSP_CALLID_IAX;
02387       }
02388    }
02389    ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
02390 
02391    results.inhandle = OSP_INVALID_HANDLE;
02392    results.intimelimit = OSP_DEF_TIMELIMIT;
02393    results.dest[0] = '\0';
02394 
02395    np.rn = "";
02396    np.cic = "";
02397    np.npdi = 0;
02398    for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02399       np.opname[type] = "";
02400    }
02401 
02402    headers.rpiduser = "";
02403    headers.paiuser = "";
02404    headers.divuser = "";
02405    headers.divhost = "";
02406    headers.pciuser = "";
02407 
02408    headp = ast_channel_varshead(chan);
02409    AST_LIST_TRAVERSE(headp, current, entries) {
02410       if (!strcmp(ast_var_name(current), "OSPINACTUALSRC")) {
02411          actualsrc = ast_var_value(current);
02412       } else if (!strcmp(ast_var_name(current), "OSPINPEERIP")) {
02413          srcdev = ast_var_value(current);
02414       } else if (!strcmp(ast_var_name(current), "OSPINTECH")) {
02415          ast_copy_string(results.intech, ast_var_value(current), sizeof(results.intech));
02416       } else if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
02417          if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02418             results.inhandle = OSP_INVALID_HANDLE;
02419          }
02420       } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02421          if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02422             results.intimelimit = OSP_DEF_TIMELIMIT;
02423          }
02424       } else if (!strcmp(ast_var_name(current), "OSPINNETWORKID")) {
02425          snetid = ast_var_value(current);
02426       } else if (!strcmp(ast_var_name(current), "OSPINNPRN")) {
02427          np.rn = ast_var_value(current);
02428       } else if (!strcmp(ast_var_name(current), "OSPINNPCIC")) {
02429          np.cic = ast_var_value(current);
02430       } else if (!strcmp(ast_var_name(current), "OSPINNPDI")) {
02431          if (ast_true(ast_var_value(current))) {
02432             np.npdi = 1;
02433          }
02434       } else if (!strcmp(ast_var_name(current), "OSPINSPID")) {
02435          np.opname[OSPC_OPNAME_SPID] = ast_var_value(current);
02436       } else if (!strcmp(ast_var_name(current), "OSPINOCN")) {
02437          np.opname[OSPC_OPNAME_OCN] = ast_var_value(current);
02438       } else if (!strcmp(ast_var_name(current), "OSPINSPN")) {
02439          np.opname[OSPC_OPNAME_SPN] = ast_var_value(current);
02440       } else if (!strcmp(ast_var_name(current), "OSPINALTSPN")) {
02441          np.opname[OSPC_OPNAME_ALTSPN] = ast_var_value(current);
02442       } else if (!strcmp(ast_var_name(current), "OSPINMCC")) {
02443          np.opname[OSPC_OPNAME_MCC] = ast_var_value(current);
02444       } else if (!strcmp(ast_var_name(current), "OSPINMNC")) {
02445          np.opname[OSPC_OPNAME_MNC] = ast_var_value(current);
02446       } else if (!strcmp(ast_var_name(current), "OSPINTOHOST")) {
02447          ast_copy_string(results.dest, ast_var_value(current), sizeof(results.dest));
02448       } else if (!strcmp(ast_var_name(current), "OSPINRPIDUSER")) {
02449          headers.rpiduser = ast_var_value(current);
02450       } else if (!strcmp(ast_var_name(current), "OSPINPAIUSER")) {
02451          headers.paiuser = ast_var_value(current);
02452       } else if (!strcmp(ast_var_name(current), "OSPINDIVUSER")) {
02453          headers.divuser = ast_var_value(current);
02454       } else if (!strcmp(ast_var_name(current), "OSPINDIVHOST")) {
02455          headers.divhost = ast_var_value(current);
02456       } else if (!strcmp(ast_var_name(current), "OSPINPCIUSER")) {
02457          headers.pciuser = ast_var_value(current);
02458       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO1")) {
02459          cinfo[0] = ast_var_value(current);
02460       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO2")) {
02461          cinfo[1] = ast_var_value(current);
02462       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO3")) {
02463          cinfo[2] = ast_var_value(current);
02464       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO4")) {
02465          cinfo[3] = ast_var_value(current);
02466       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO5")) {
02467          cinfo[4] = ast_var_value(current);
02468       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO6")) {
02469          cinfo[5] = ast_var_value(current);
02470       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO7")) {
02471          cinfo[6] = ast_var_value(current);
02472       } else if (!strcmp(ast_var_name(current), "OSPINCUSTOMINFO8")) {
02473          cinfo[7] = ast_var_value(current);
02474       }
02475    }
02476    ast_debug(1, "OSPLookup: actual source device '%s'\n", actualsrc);
02477    ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
02478    ast_debug(1, "OSPLookup: OSPINTECH '%s'\n", results.intech);
02479    ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", results.inhandle);
02480    ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02481    ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
02482    ast_debug(1, "OSPLookup: OSPINNPRN '%s'\n", np.rn);
02483    ast_debug(1, "OSPLookup: OSPINNPCIC '%s'\n", np.cic);
02484    ast_debug(1, "OSPLookup: OSPINNPDI '%d'\n", np.npdi);
02485    ast_debug(1, "OSPLookup: OSPINSPID '%s'\n", np.opname[OSPC_OPNAME_SPID]);
02486    ast_debug(1, "OSPLookup: OSPINOCN '%s'\n", np.opname[OSPC_OPNAME_OCN]);
02487    ast_debug(1, "OSPLookup: OSPINSPN '%s'\n", np.opname[OSPC_OPNAME_SPN]);
02488    ast_debug(1, "OSPLookup: OSPINALTSPN '%s'\n", np.opname[OSPC_OPNAME_ALTSPN]);
02489    ast_debug(1, "OSPLookup: OSPINMCC '%s'\n", np.opname[OSPC_OPNAME_MCC]);
02490    ast_debug(1, "OSPLookup: OSPINMNC '%s'\n", np.opname[OSPC_OPNAME_MNC]);
02491    ast_debug(1, "OSPLookup: OSPINTOHOST '%s'\n", results.dest);
02492    ast_debug(1, "OSPLookup: OSPINRPIDUSER '%s'\n", headers.rpiduser);
02493    ast_debug(1, "OSPLookup: OSPINPAIUSER '%s'\n", headers.paiuser);
02494    ast_debug(1, "OSPLookup: OSPINDIVUSER '%s'\n", headers.divuser);
02495    ast_debug(1, "OSPLookup: OSPINDIVHOST'%s'\n", headers.divhost);
02496    ast_debug(1, "OSPLookup: OSPINPCIUSER '%s'\n", headers.pciuser);
02497    for (i = 0; i < OSP_MAX_CUSTOMINFO; i++) {
02498       if (!ast_strlen_zero(cinfo[i])) {
02499          ast_debug(1, "OSPLookup: OSPINCUSTOMINFO%d '%s'\n", i, cinfo[i]);
02500       }
02501    }
02502 
02503    if (ast_autoservice_start(chan) < 0) {
02504       return OSP_AST_ERROR;
02505    }
02506 
02507    res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
02508       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
02509       args.exten, snetid, &np, &headers, cinfo, &results);
02510    if (res > 0) {
02511       status = AST_OSP_SUCCESS;
02512    } else {
02513       results.outtech[0] = '\0';
02514       results.dest[0] = '\0';
02515       results.calling[0] = '\0';
02516       results.called[0] = '\0';
02517       results.token[0] = '\0';
02518       results.networkid[0] = '\0';
02519       results.nprn[0] = '\0';
02520       results.npcic[0] = '\0';
02521       results.npdi = 0;
02522       for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02523          results.opname[type][0] = '\0';
02524       }
02525       results.numdests = 0;
02526       results.outtimelimit = OSP_DEF_TIMELIMIT;
02527       results.outcallid.buf[0] = '\0';
02528       results.outcallid.len = 0;
02529       if (!res) {
02530          status = AST_OSP_FAILED;
02531       } else {
02532          status = AST_OSP_ERROR;
02533       }
02534    }
02535 
02536    snprintf(buffer, sizeof(buffer), "%d", results.outhandle);
02537    pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02538    ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
02539    pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
02540    ast_debug(1, "OSPLookup: OSPOUTTECH '%s'\n", results.outtech);
02541    pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02542    ast_debug(1, "OSPLookup: OSPDESTINATION '%s'\n", results.dest);
02543    pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02544    ast_debug(1, "OSPLookup: OSPOUTCALLING '%s'\n", results.calling);
02545    pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02546    ast_debug(1, "OSPLookup: OSPOUTCALLED '%s'\n", results.called);
02547    pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02548    ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02549    pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02550    ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02551    pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02552    ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02553    snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02554    pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02555    ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02556    pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02557    ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02558    pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02559    ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02560    pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02561    ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02562    pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02563    ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02564    pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02565    ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02566    pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02567    ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02568    pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02569    ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02570    snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02571    pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02572    ast_debug(1, "OSPLookup: OSPDESTREMAILS '%s'\n", buffer);
02573    snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02574    pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02575    ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
02576    snprintf(buffer, sizeof(buffer), "%d", callidtypes);
02577    pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
02578    ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
02579    pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
02580    ast_debug(1, "OSPLookup: %s\n", status);
02581 
02582    if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
02583       snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
02584       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02585       if (!ast_strlen_zero(results.token)) {
02586          snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02587          pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02588          ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02589       }
02590    } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
02591       if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02592          osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02593       } else {
02594          buffer[0] = '\0';
02595       }
02596       pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02597       snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
02598       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02599    } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
02600       snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
02601       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02602    } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
02603       snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
02604       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02605    }
02606 
02607    if (ast_autoservice_stop(chan) < 0) {
02608       return OSP_AST_ERROR;
02609    }
02610 
02611    if(res != OSP_OK) {
02612       res = OSP_AST_ERROR;
02613    } else {
02614       res = OSP_AST_OK;
02615    }
02616 
02617    return res;
02618 }
02619 
02620 /*!
02621  * \brief OSP Application OSPNext
02622  * \param chan Channel
02623  * \param data Parameter
02624  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
02625  */
02626 static int ospnext_exec(
02627    struct ast_channel* chan,
02628    const char * data)
02629 {
02630    int res;
02631    const char* provider = OSP_DEF_PROVIDER;
02632    int cause = 0;
02633    struct varshead* headp;
02634    struct ast_var_t* current;
02635    struct osp_results results;
02636    OSPE_OPERATOR_NAME type;
02637    char buffer[OSP_SIZE_TOKSTR];
02638    unsigned int callidtypes = OSP_CALLID_UNDEF;
02639    const char* status;
02640    char* tmp;
02641 
02642    AST_DECLARE_APP_ARGS(args,
02643       AST_APP_ARG(cause);
02644       AST_APP_ARG(provider);
02645       AST_APP_ARG(options);
02646    );
02647 
02648    if (ast_strlen_zero(data)) {
02649       ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[,provider[,options]])\n");
02650       return OSP_AST_ERROR;
02651    }
02652 
02653    tmp = ast_strdupa(data);
02654 
02655    AST_STANDARD_APP_ARGS(args, tmp);
02656 
02657    if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02658       cause = 0;
02659    }
02660    ast_debug(1, "OSPNext: cause '%d'\n", cause);
02661 
02662    if (!ast_strlen_zero(args.provider)) {
02663       provider = args.provider;
02664    }
02665    ast_debug(1, "OSPlookup: provider '%s'\n", provider);
02666 
02667    results.inhandle = OSP_INVALID_HANDLE;
02668    results.outhandle = OSP_INVALID_HANDLE;
02669    results.intimelimit = OSP_DEF_TIMELIMIT;
02670    results.numdests = 0;
02671 
02672    headp = ast_channel_varshead(chan);
02673    AST_LIST_TRAVERSE(headp, current, entries) {
02674       if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
02675          if (sscanf(ast_var_value(current), "%30d", &results.inhandle) != 1) {
02676             results.inhandle = OSP_INVALID_HANDLE;
02677          }
02678       } else if (!strcmp(ast_var_name(current), "OSPOUTHANDLE")) {
02679          if (sscanf(ast_var_value(current), "%30d", &results.outhandle) != 1) {
02680             results.outhandle = OSP_INVALID_HANDLE;
02681          }
02682       } else if (!strcmp(ast_var_name(current), "OSPINTIMELIMIT")) {
02683          if (sscanf(ast_var_value(current), "%30d", &results.intimelimit) != 1) {
02684             results.intimelimit = OSP_DEF_TIMELIMIT;
02685          }
02686       } else if (!strcmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
02687          if (sscanf(ast_var_value(current), "%30d", &callidtypes) != 1) {
02688             callidtypes = OSP_CALLID_UNDEF;
02689          }
02690       } else if (!strcmp(ast_var_name(current), "OSPDESTREMAILS")) {
02691          if (sscanf(ast_var_value(current), "%30d", &results.numdests) != 1) {
02692             results.numdests = 0;
02693          }
02694       }
02695    }
02696    ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", results.inhandle);
02697    ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", results.outhandle);
02698    ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", results.intimelimit);
02699    ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
02700    ast_debug(1, "OSPNext: OSPDESTREMAILS '%d'\n", results.numdests);
02701 
02702    if ((res = osp_next(provider, cause, &results)) > 0) {
02703       status = AST_OSP_SUCCESS;
02704    } else {
02705       results.outtech[0] = '\0';
02706       results.dest[0] = '\0';
02707       results.calling[0] = '\0';
02708       results.called[0] = '\0';
02709       results.token[0] = '\0';
02710       results.networkid[0] = '\0';
02711       results.nprn[0] = '\0';
02712       results.npcic[0] = '\0';
02713       results.npdi = 0;
02714       for (type = OSPC_OPNAME_START; type < OSPC_OPNAME_NUMBER; type++) {
02715          results.opname[type][0] = '\0';
02716       }
02717       results.numdests = 0;
02718       results.outtimelimit = OSP_DEF_TIMELIMIT;
02719       results.outcallid.buf[0] = '\0';
02720       results.outcallid.len = 0;
02721       if (!res) {
02722          status = AST_OSP_FAILED;
02723       } else {
02724          status = AST_OSP_ERROR;
02725       }
02726    }
02727 
02728    pbx_builtin_setvar_helper(chan, "OSPOUTTECH", results.outtech);
02729    ast_debug(1, "OSPNext: OSPOUTTECH '%s'\n", results.outtech);
02730    pbx_builtin_setvar_helper(chan, "OSPDESTINATION", results.dest);
02731    ast_debug(1, "OSPNext: OSPDESTINATION '%s'\n", results.dest);
02732    pbx_builtin_setvar_helper(chan, "OSPOUTCALLING", results.calling);
02733    ast_debug(1, "OSPNext: OSPOUTCALLING '%s'\n", results.calling);
02734    pbx_builtin_setvar_helper(chan, "OSPOUTCALLED", results.called);
02735    ast_debug(1, "OSPNext: OSPOUTCALLED'%s'\n", results.called);
02736    pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", results.networkid);
02737    ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", results.networkid);
02738    pbx_builtin_setvar_helper(chan, "OSPOUTNPRN", results.nprn);
02739    ast_debug(1, "OSPLookup: OSPOUTNPRN '%s'\n", results.nprn);
02740    pbx_builtin_setvar_helper(chan, "OSPOUTNPCIC", results.npcic);
02741    ast_debug(1, "OSPLookup: OSPOUTNPCIC '%s'\n", results.npcic);
02742    snprintf(buffer, sizeof(buffer), "%d", results.npdi);
02743    pbx_builtin_setvar_helper(chan, "OSPOUTNPDI", buffer);
02744    ast_debug(1, "OSPLookup: OSPOUTNPDI'%s'\n", buffer);
02745    pbx_builtin_setvar_helper(chan, "OSPOUTSPID", results.opname[OSPC_OPNAME_SPID]);
02746    ast_debug(1, "OSPLookup: OSPOUTSPID '%s'\n", results.opname[OSPC_OPNAME_SPID]);
02747    pbx_builtin_setvar_helper(chan, "OSPOUTOCN", results.opname[OSPC_OPNAME_OCN]);
02748    ast_debug(1, "OSPLookup: OSPOUTOCN '%s'\n", results.opname[OSPC_OPNAME_OCN]);
02749    pbx_builtin_setvar_helper(chan, "OSPOUTSPN", results.opname[OSPC_OPNAME_SPN]);
02750    ast_debug(1, "OSPLookup: OSPOUTSPN '%s'\n", results.opname[OSPC_OPNAME_SPN]);
02751    pbx_builtin_setvar_helper(chan, "OSPOUTALTSPN", results.opname[OSPC_OPNAME_ALTSPN]);
02752    ast_debug(1, "OSPLookup: OSPOUTALTSPN '%s'\n", results.opname[OSPC_OPNAME_ALTSPN]);
02753    pbx_builtin_setvar_helper(chan, "OSPOUTMCC", results.opname[OSPC_OPNAME_MCC]);
02754    ast_debug(1, "OSPLookup: OSPOUTMCC '%s'\n", results.opname[OSPC_OPNAME_MCC]);
02755    pbx_builtin_setvar_helper(chan, "OSPOUTMNC", results.opname[OSPC_OPNAME_MNC]);
02756    ast_debug(1, "OSPLookup: OSPOUTMNC '%s'\n", results.opname[OSPC_OPNAME_MNC]);
02757    pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", results.token);
02758    ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(results.token));
02759    snprintf(buffer, sizeof(buffer), "%d", results.numdests);
02760    pbx_builtin_setvar_helper(chan, "OSPDESTREMAILS", buffer);
02761    ast_debug(1, "OSPNext: OSPDESTREMAILS '%s'\n", buffer);
02762    snprintf(buffer, sizeof(buffer), "%d", results.outtimelimit);
02763    pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
02764    ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
02765    pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
02766    ast_debug(1, "OSPNext: %s\n", status);
02767 
02768    if (!strcasecmp(results.outtech, OSP_TECH_SIP)) {
02769       snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
02770       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02771       if (!ast_strlen_zero(results.token)) {
02772          snprintf(buffer, sizeof(buffer), "%s: %s", OSP_SIP_HEADER, results.token);
02773          pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
02774          ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
02775       }
02776    } else if (!strcasecmp(results.outtech, OSP_TECH_H323)) {
02777       if ((callidtypes & OSP_CALLID_H323) && (results.outcallid.len != 0)) {
02778          osp_uuid2str(results.outcallid.buf, buffer, sizeof(buffer));
02779       } else {
02780          buffer[0] = '\0';
02781       }
02782       pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
02783       snprintf(buffer, sizeof(buffer), "%s/%s@%s", results.outtech, results.called, results.dest);
02784       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02785    } else if (!strcasecmp(results.outtech, OSP_TECH_IAX)) {
02786       snprintf(buffer, sizeof(buffer), "%s/%s/%s", results.outtech, results.dest, results.called);
02787       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02788    } else if (!strcasecmp(results.outtech, OSP_TECH_SKYPE)) {
02789       snprintf(buffer, sizeof(buffer), "%s/%s", results.outtech, results.called);
02790       pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
02791    }
02792 
02793    if(res != OSP_OK) {
02794       res = OSP_AST_ERROR;
02795    } else {
02796       res = OSP_AST_OK;
02797    }
02798 
02799    return res;
02800 }
02801 
02802 /*!
02803  * \brief OSP Application OSPFinish
02804  * \param chan Channel
02805  * \param data Parameter
02806  * \return OSP_AST_OK Success, OSP_AST_ERROR Error
02807  */
02808 static int ospfinished_exec(
02809    struct ast_channel* chan,
02810    const char * data)
02811 {
02812    int res = OSP_OK;
02813    int cause = 0;
02814    struct varshead* headp;
02815    struct ast_var_t* current;
02816    int inhandle = OSP_INVALID_HANDLE;
02817    int outhandle = OSP_INVALID_HANDLE;
02818    int recorded = 0;
02819    time_t start = 0, connect = 0, end = 0;
02820    unsigned int release;
02821    char buffer[OSP_SIZE_INTSTR];
02822    char inqos[OSP_SIZE_QOSSTR] = { 0 };
02823    char outqos[OSP_SIZE_QOSSTR] = { 0 };
02824    const char* status;
02825    char* tmp;
02826 
02827    AST_DECLARE_APP_ARGS(args,
02828       AST_APP_ARG(cause);
02829       AST_APP_ARG(options);
02830    );
02831 
02832    tmp = ast_strdupa(data);
02833 
02834    AST_STANDARD_APP_ARGS(args, tmp);
02835 
02836    headp = ast_channel_varshead(chan);
02837    AST_LIST_TRAVERSE(headp, current, entries) {
02838       if (!strcmp(ast_var_name(current), "OSPINHANDLE")) {
02839          if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
02840             inhandle = OSP_INVALID_HANDLE;
02841          }
02842       } else if (!strcmp(ast_var_name(current), "OSPOUTHANDLE")) {
02843          if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
02844             outhandle = OSP_INVALID_HANDLE;
02845          }
02846       } else if (!recorded &&
02847          (!strcmp(ast_var_name(current), "OSPAUTHSTATUS") ||
02848          !strcmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
02849          !strcmp(ast_var_name(current), "OSPNEXTSTATUS")))
02850       {
02851          if (strcmp(ast_var_value(current), AST_OSP_SUCCESS)) {
02852             recorded = 1;
02853          }
02854       } else if (!strcmp(ast_var_name(current), "OSPINAUDIOQOS")) {
02855          ast_copy_string(inqos, ast_var_value(current), sizeof(inqos));
02856       } else if (!strcmp(ast_var_name(current), "OSPOUTAUDIOQOS")) {
02857          ast_copy_string(outqos, ast_var_value(current), sizeof(outqos));
02858       }
02859    }
02860    ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
02861    ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
02862    ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
02863    ast_debug(1, "OSPFinish: OSPINAUDIOQOS '%s'\n", inqos);
02864    ast_debug(1, "OSPFinish: OSPOUTAUDIOQOS '%s'\n", outqos);
02865 
02866    if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
02867       cause = 0;
02868    }
02869    ast_debug(1, "OSPFinish: cause '%d'\n", cause);
02870 
02871    if (!ast_tvzero(ast_channel_creationtime(chan))) {
02872       start = ast_channel_creationtime(chan).tv_sec;
02873    }
02874    if (!ast_tvzero(ast_channel_answertime(chan))) {
02875       connect = ast_channel_answertime(chan).tv_sec;
02876    }
02877    if (connect) {
02878       end = time(NULL);
02879    } else {
02880       end = connect;
02881    }
02882 
02883    ast_debug(1, "OSPFinish: start '%ld'\n", start);
02884    ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
02885    ast_debug(1, "OSPFinish: end '%ld'\n", end);
02886 
02887    release = ast_check_hangup(chan) ? 0 : 1;
02888 
02889    if (osp_finish(outhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02890       ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
02891    }
02892    switch (cause) {
02893    case AST_CAUSE_NORMAL_CLEARING:
02894       break;
02895    default:
02896       cause = AST_CAUSE_NO_ROUTE_DESTINATION;
02897       break;
02898    }
02899    if (osp_finish(inhandle, recorded, cause, start, connect, end, release, inqos, outqos) <= 0) {
02900       ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
02901    }
02902    snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
02903    pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
02904    pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
02905 
02906    if (res > 0) {
02907       status = AST_OSP_SUCCESS;
02908    } else if (!res) {
02909       status = AST_OSP_FAILED;
02910    } else {
02911       status = AST_OSP_ERROR;
02912    }
02913    pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
02914 
02915    if(res != OSP_OK) {
02916       res = OSP_AST_ERROR;
02917    } else {
02918       res = OSP_AST_OK;
02919    }
02920 
02921    return res;
02922 }
02923 
02924 /* OSP Module APIs */
02925 
02926 static int osp_unload(void)
02927 {
02928    struct osp_provider* provider;
02929    struct osp_provider* next;
02930 
02931    if (osp_initialized) {
02932       ast_mutex_lock(&osp_lock);
02933       for (provider = osp_providers; provider; provider = next) {
02934          next = provider->next;
02935          OSPPProviderDelete(provider->handle, 0);
02936          ast_free(provider);
02937       }
02938       osp_providers = NULL;
02939       ast_mutex_unlock(&osp_lock);
02940 
02941       OSPPCleanup();
02942 
02943       osp_tokenformat = TOKEN_ALGO_SIGNED;
02944       osp_security = 0;
02945       osp_hardware = 0;
02946       osp_initialized = 0;
02947    }
02948 
02949    return 0;
02950 }
02951 
02952 static int osp_load(int reload)
02953 {
02954    const char* cvar;
02955    unsigned int ivar;
02956    struct ast_config* cfg;
02957    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02958    int error = OSPC_ERR_NO_ERROR;
02959 
02960    if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
02961       return 0;
02962    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
02963       ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", OSP_CONFIG_FILE);
02964       return 0;
02965    }
02966 
02967    if (cfg) {
02968       if (reload) {
02969          osp_unload();
02970       }
02971 
02972       if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate")) && ast_true(cvar)) {
02973          if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
02974             ast_log(LOG_WARNING, "OSP: Unable to enable hardware acceleration, error='%d'\n", error);
02975             OSPPInit(0);
02976          } else {
02977             osp_hardware = 1;
02978          }
02979       } else {
02980          OSPPInit(0);
02981       }
02982       ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
02983 
02984       if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures")) && ast_true(cvar)) {
02985          osp_security = 1;
02986       }
02987       ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
02988 
02989       if ((cvar = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat"))) {
02990          if ((sscanf(cvar, "%30d", &ivar) == 1) &&
02991             ((ivar == TOKEN_ALGO_SIGNED) || (ivar == TOKEN_ALGO_UNSIGNED) || (ivar == TOKEN_ALGO_BOTH)))
02992          {
02993             osp_tokenformat = ivar;
02994          } else {
02995             ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
02996                TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, cvar);
02997          }
02998       }
02999       ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
03000 
03001       for (cvar = ast_category_browse(cfg, NULL); cvar != NULL; cvar = ast_category_browse(cfg, cvar)) {
03002          if (strcasecmp(cvar, OSP_GENERAL_CAT)) {
03003             osp_create_provider(cfg, cvar);
03004          }
03005       }
03006 
03007       osp_initialized = 1;
03008 
03009       ast_config_destroy(cfg);
03010    } else {
03011       ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
03012       return 0;
03013    }
03014    ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
03015 
03016    return 1;
03017 }
03018 
03019 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03020 {
03021    int i;
03022    int found = 0;
03023    struct osp_provider* provider;
03024    const char* name = NULL;
03025    const char* tokenalgo;
03026 
03027    switch (cmd) {
03028    case CLI_INIT:
03029       e->command = "osp show";
03030       e->usage =
03031          "Usage: osp show\n"
03032          "       Displays information on Open Settlement Protocol support\n";
03033       return NULL;
03034    case CLI_GENERATE:
03035       return NULL;
03036    }
03037 
03038    if ((a->argc < 2) || (a->argc > 3)) {
03039       return CLI_SHOWUSAGE;
03040    }
03041 
03042    if (a->argc > 2) {
03043       name = a->argv[2];
03044    }
03045 
03046    if (!name) {
03047       switch (osp_tokenformat) {
03048       case TOKEN_ALGO_BOTH:
03049          tokenalgo = "Both";
03050          break;
03051       case TOKEN_ALGO_UNSIGNED:
03052          tokenalgo = "Unsigned";
03053          break;
03054       case TOKEN_ALGO_SIGNED:
03055       default:
03056          tokenalgo = "Signed";
03057          break;
03058       }
03059       ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
03060          osp_initialized ? "Initialized" : "Uninitialized",
03061          osp_hardware ? "Accelerated" : "Normal",
03062          osp_security ? "Enabled" : "Disabled",
03063          tokenalgo);
03064    }
03065 
03066    ast_mutex_lock(&osp_lock);
03067    for (provider = osp_providers; provider; provider = provider->next) {
03068       if (!name || !strcasecmp(provider->name, name)) {
03069          if (found) {
03070             ast_cli(a->fd, "\n");
03071          }
03072          ast_cli(a->fd, " == OSP Provider '%s' == \n", provider->name);
03073          if (osp_security) {
03074             ast_cli(a->fd, "Local Private Key: %s\n", provider->privatekey);
03075             ast_cli(a->fd, "Local Certificate: %s\n", provider->localcert);
03076             for (i = 0; i < provider->canum; i++) {
03077                ast_cli(a->fd, "CA Certificate %d:  %s\n", i + 1, provider->cacerts[i]);
03078             }
03079          }
03080          for (i = 0; i < provider->spnum; i++) {
03081             ast_cli(a->fd, "Service Point %d:   %s\n", i + 1, provider->spoints[i]);
03082          }
03083          ast_cli(a->fd, "Max Connections:   %d\n", provider->maxconnect);
03084          ast_cli(a->fd, "Retry Delay:       %d seconds\n", provider->retrydelay);
03085          ast_cli(a->fd, "Retry Limit:       %d\n", provider->retrylimit);
03086          ast_cli(a->fd, "Timeout:           %d milliseconds\n", provider->timeout);
03087          ast_cli(a->fd, "Source:            %s\n", strlen(provider->source) ? provider->source : "<unspecified>");
03088          ast_cli(a->fd, "Auth Policy        %d\n", provider->authpolicy);
03089          ast_cli(a->fd, "Default protocol   %s\n", provider->defprotocol);
03090          ast_cli(a->fd, "Work mode          %d\n", provider->workmode);
03091          ast_cli(a->fd, "Service type       %d\n", provider->srvtype);
03092          ast_cli(a->fd, "OSP Handle:        %d\n", provider->handle);
03093          found++;
03094       }
03095    }
03096    ast_mutex_unlock(&osp_lock);
03097 
03098    if (!found) {
03099       if (name) {
03100          ast_cli(a->fd, "Unable to find OSP provider '%s'\n", name);
03101       } else {
03102          ast_cli(a->fd, "No OSP providers configured\n");
03103       }
03104    }
03105 
03106    return CLI_SUCCESS;
03107 }
03108 
03109 /* OSPAuth() dialplan application */
03110 static const char app1[] = "OSPAuth";
03111 
03112 /* OSPLookup() dialplan application */
03113 static const char app2[] = "OSPLookup";
03114 
03115 /* OSPNext() dialplan application */
03116 static const char app3[] = "OSPNext";
03117 
03118 /* OSPFinish() dialplan application */
03119 static const char app4[] = "OSPFinish";
03120 
03121 static struct ast_cli_entry cli_osp[] = {
03122    AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
03123 };
03124 
03125 static int load_module(void)
03126 {
03127    int res;
03128 
03129    if (!osp_load(0))
03130       return AST_MODULE_LOAD_DECLINE;
03131 
03132    ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03133    res = ast_register_application_xml(app1, ospauth_exec);
03134    res |= ast_register_application_xml(app2, osplookup_exec);
03135    res |= ast_register_application_xml(app3, ospnext_exec);
03136    res |= ast_register_application_xml(app4, ospfinished_exec);
03137 
03138    return res;
03139 }
03140 
03141 static int unload_module(void)
03142 {
03143    int res;
03144 
03145    res = ast_unregister_application(app4);
03146    res |= ast_unregister_application(app3);
03147    res |= ast_unregister_application(app2);
03148    res |= ast_unregister_application(app1);
03149    ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
03150    osp_unload();
03151 
03152    return res;
03153 }
03154 
03155 static int reload(void)
03156 {
03157    osp_load(1);
03158 
03159    return 0;
03160 }
03161 
03162 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
03163    .support_level = AST_MODULE_SUPPORT_EXTENDED,
03164    .load = load_module,
03165    .unload = unload_module,
03166    .reload = reload,
03167 );

Generated on Thu Apr 16 06:27:11 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6