Wed Apr 6 11:29:38 2011

Asterisk developer's documentation


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

Generated on Wed Apr 6 11:29:38 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7