Thu Oct 11 06:41:59 2012

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  * \ingroup applications
00026  */
00027 
00028 /*** MODULEINFO
00029    <depend>osptk</depend>
00030    <depend>ssl</depend>
00031  ***/
00032 
00033 #include "asterisk.h"
00034 
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211528 $")
00036 
00037 #include <sys/types.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042 #include <osp/osp.h>
00043 #include <osp/osputils.h>
00044 
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/options.h"
00054 #include "asterisk/cli.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/astosp.h"
00057 
00058 /* OSP Buffer Sizes */
00059 #define OSP_INTSTR_SIZE       ((unsigned int)16)         /* OSP signed/unsigned int string buffer size */
00060 #define OSP_NORSTR_SIZE       ((unsigned int)256)        /* OSP normal string buffer size */
00061 #define OSP_TOKSTR_SIZE       ((unsigned int)4096)       /* OSP token string buffer size */
00062 
00063 /* OSP Constants */
00064 #define OSP_INVALID_HANDLE    ((int)-1)            /* Invalid OSP handle, provider, transaction etc. */
00065 #define OSP_CONFIG_FILE       ((const char*)"osp.conf")     /* OSP configuration file name */
00066 #define OSP_GENERAL_CAT       ((const char*)"general")      /* OSP global configuration context name */
00067 #define OSP_DEF_PROVIDER      ((const char*)"default")      /* OSP default provider context name */
00068 #define OSP_MAX_CERTS         ((unsigned int)10)         /* OSP max number of cacerts */
00069 #define OSP_MAX_SRVS       ((unsigned int)10)         /* OSP max number of service points */
00070 #define OSP_DEF_MAXCONNECTIONS      ((unsigned int)20)         /* OSP default max_connections */
00071 #define OSP_MIN_MAXCONNECTIONS      ((unsigned int)1)       /* OSP min max_connections */
00072 #define OSP_MAX_MAXCONNECTIONS      ((unsigned int)1000)       /* OSP max max_connections */
00073 #define OSP_DEF_RETRYDELAY    ((unsigned int)0)       /* OSP default retry delay */
00074 #define OSP_MIN_RETRYDELAY    ((unsigned int)0)       /* OSP min retry delay */
00075 #define OSP_MAX_RETRYDELAY    ((unsigned int)10)         /* OSP max retry delay */
00076 #define OSP_DEF_RETRYLIMIT    ((unsigned int)2)       /* OSP default retry times */
00077 #define OSP_MIN_RETRYLIMIT    ((unsigned int)0)       /* OSP min retry times */
00078 #define OSP_MAX_RETRYLIMIT    ((unsigned int)100)        /* OSP max retry times */
00079 #define OSP_DEF_TIMEOUT       ((unsigned int)500)        /* OSP default timeout in ms */
00080 #define OSP_MIN_TIMEOUT       ((unsigned int)200)        /* OSP min timeout in ms */
00081 #define OSP_MAX_TIMEOUT       ((unsigned int)10000)         /* OSP max timeout in ms */
00082 #define OSP_DEF_AUTHPOLICY    ((enum osp_authpolicy)OSP_AUTH_YES)
00083 #define OSP_AUDIT_URL         ((const char*)"localhost")    /* OSP default Audit URL */
00084 #define OSP_LOCAL_VALIDATION     ((int)1)          /* Validate OSP token locally */
00085 #define OSP_SSL_LIFETIME      ((unsigned int)300)        /* SSL life time, in seconds */
00086 #define OSP_HTTP_PERSISTENCE     ((int)1)          /* In seconds */
00087 #define OSP_CUSTOMER_ID       ((const char*)"")       /* OSP customer ID */
00088 #define OSP_DEVICE_ID         ((const char*)"")       /* OSP device ID */
00089 #define OSP_DEF_DESTINATIONS     ((unsigned int)5)       /* OSP default max number of destinations */
00090 #define OSP_DEF_TIMELIMIT     ((unsigned int)0)       /* OSP default duration limit, no limit */
00091 
00092 /* OSP Authentication Policy */
00093 enum osp_authpolicy {
00094    OSP_AUTH_NO,      /* Accept any call */
00095    OSP_AUTH_YES,     /* Accept call with valid OSP token or without OSP token */
00096    OSP_AUTH_EXCLUSIVE   /* Only accept call with valid OSP token */
00097 };
00098 
00099 /* OSP Provider */
00100 struct osp_provider {
00101    char name[OSP_NORSTR_SIZE];            /* OSP provider context name */
00102    char privatekey[OSP_NORSTR_SIZE];         /* OSP private key file name */
00103    char localcert[OSP_NORSTR_SIZE];       /* OSP local cert file name */
00104    unsigned int cacount;               /* Number of cacerts */
00105    char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];      /* Cacert file names */
00106    unsigned int spcount;               /* Number of service points */
00107    char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];     /* Service point URLs */
00108    int maxconnections;              /* Max number of connections */
00109    int retrydelay;                  /* Retry delay */
00110    int retrylimit;                  /* Retry limit */
00111    int timeout;                  /* Timeout in ms */
00112    char source[OSP_NORSTR_SIZE];          /* IP of self */
00113    enum osp_authpolicy authpolicy;           /* OSP authentication policy */
00114    OSPTPROVHANDLE handle;              /* OSP provider handle */
00115    struct osp_provider* next;          /* Pointer to next OSP provider */
00116 };
00117 
00118 /* OSP Application In/Output Results */
00119 struct osp_result {
00120    int inhandle;                 /* Inbound transaction handle */
00121    int outhandle;                /* Outbound transaction handle */
00122    unsigned int intimelimit;           /* Inbound duration limit */
00123    unsigned int outtimelimit;          /* Outbound duration limit */
00124    char tech[20];                /* Asterisk TECH string */
00125    char dest[OSP_NORSTR_SIZE];            /* Destination in called@IP format */
00126    char calling[OSP_NORSTR_SIZE];            /* Calling number, may be translated */
00127    char token[OSP_TOKSTR_SIZE];           /* Outbound OSP token */
00128    unsigned int numresults;            /* Number of remain destinations */
00129 };
00130 
00131 /* OSP Module Global Variables */
00132 AST_MUTEX_DEFINE_STATIC(osplock);            /* Lock of OSP provider list */
00133 static int osp_initialized = 0;              /* Init flag */
00134 static int osp_hardware = 0;              /* Hardware accelleration flag */
00135 static struct osp_provider* ospproviders = NULL;      /* OSP provider list */
00136 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED; /* Token format supported */
00137 
00138 /* OSP Client Wrapper APIs */
00139 
00140 /*!
00141  * \brief Create OSP provider handle according to configuration
00142  * \param cfg OSP configuration
00143  * \param provider OSP provider context name
00144  * \return 1 Success, 0 Failed, -1 Error
00145  */
00146 static int osp_create_provider(struct ast_config* cfg, const char* provider)
00147 {
00148    int res;
00149    unsigned int t, i, j;
00150    struct osp_provider* p;
00151    struct ast_variable* v;
00152    OSPTPRIVATEKEY privatekey;
00153    OSPTCERT localcert;
00154    const char* psrvpoints[OSP_MAX_SRVS];
00155    OSPTCERT cacerts[OSP_MAX_CERTS];
00156    const OSPTCERT* pcacerts[OSP_MAX_CERTS];
00157    int error = OSPC_ERR_NO_ERROR;
00158 
00159    if (!(p = ast_calloc(1, sizeof(*p)))) {
00160       ast_log(LOG_ERROR, "Out of memory\n");
00161       return -1;
00162    }
00163 
00164    ast_copy_string(p->name, provider, sizeof(p->name));
00165    snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
00166    snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
00167    p->maxconnections = OSP_DEF_MAXCONNECTIONS;
00168    p->retrydelay = OSP_DEF_RETRYDELAY;
00169    p->retrylimit = OSP_DEF_RETRYLIMIT;
00170    p->timeout = OSP_DEF_TIMEOUT;
00171    p->authpolicy = OSP_DEF_AUTHPOLICY;
00172    p->handle = OSP_INVALID_HANDLE;
00173 
00174    v = ast_variable_browse(cfg, provider);
00175    while(v) {
00176       if (!strcasecmp(v->name, "privatekey")) {
00177          if (v->value[0] == '/') {
00178             ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
00179          } else {
00180             snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00181          }
00182          ast_log(LOG_DEBUG, "OSP: privatekey '%s'\n", p->privatekey);
00183       } else if (!strcasecmp(v->name, "localcert")) {
00184          if (v->value[0] == '/') {
00185             ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
00186          } else {
00187             snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00188          }
00189          ast_log(LOG_DEBUG, "OSP: localcert '%s'\n", p->localcert);
00190       } else if (!strcasecmp(v->name, "cacert")) {
00191          if (p->cacount < OSP_MAX_CERTS) {
00192             if (v->value[0] == '/') {
00193                ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
00194             } else {
00195                snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00196             }
00197             ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00198             p->cacount++;
00199          } else {
00200             ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
00201          }
00202       } else if (!strcasecmp(v->name, "servicepoint")) {
00203          if (p->spcount < OSP_MAX_SRVS) {
00204             ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
00205             ast_log(LOG_DEBUG, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
00206             p->spcount++;
00207          } else {
00208             ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
00209          }
00210       } else if (!strcasecmp(v->name, "maxconnections")) {
00211          if ((sscanf(v->value, "%30d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
00212             p->maxconnections = t;
00213             ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t);
00214          } else {
00215             ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n", 
00216                OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
00217          }
00218       } else if (!strcasecmp(v->name, "retrydelay")) {
00219          if ((sscanf(v->value, "%30d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
00220             p->retrydelay = t;
00221             ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t);
00222          } else {
00223             ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n", 
00224                OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
00225          }
00226       } else if (!strcasecmp(v->name, "retrylimit")) {
00227          if ((sscanf(v->value, "%30d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
00228             p->retrylimit = t;
00229             ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t);
00230          } else {
00231             ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n", 
00232                OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
00233          }
00234       } else if (!strcasecmp(v->name, "timeout")) {
00235          if ((sscanf(v->value, "%30d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
00236             p->timeout = t;
00237             ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t);
00238          } else {
00239             ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n", 
00240                OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
00241          }
00242       } else if (!strcasecmp(v->name, "source")) {
00243          ast_copy_string(p->source, v->value, sizeof(p->source));
00244          ast_log(LOG_DEBUG, "OSP: source '%s'\n", p->source);
00245       } else if (!strcasecmp(v->name, "authpolicy")) {
00246          if ((sscanf(v->value, "%30d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
00247             p->authpolicy = t;
00248             ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t);
00249          } else {
00250             ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n", 
00251                OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
00252          }
00253       }
00254       v = v->next;
00255    }
00256 
00257    error = OSPPUtilLoadPEMPrivateKey((unsigned char *) p->privatekey, &privatekey);
00258    if (error != OSPC_ERR_NO_ERROR) {
00259       ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
00260       free(p);
00261       return 0;
00262    }
00263 
00264    error = OSPPUtilLoadPEMCert((unsigned char *) p->localcert, &localcert);
00265    if (error != OSPC_ERR_NO_ERROR) {
00266       ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
00267       if (privatekey.PrivateKeyData) {
00268          free(privatekey.PrivateKeyData);
00269       }
00270       free(p);
00271       return 0;
00272    }
00273 
00274    if (p->cacount < 1) {
00275       snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
00276       ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00277       p->cacount++;
00278    }
00279    for (i = 0; i < p->cacount; i++) {
00280       error = OSPPUtilLoadPEMCert((unsigned char *) p->cacerts[i], &cacerts[i]);
00281       if (error != OSPC_ERR_NO_ERROR) {
00282          ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
00283          for (j = 0; j < i; j++) {
00284             if (cacerts[j].CertData) {
00285                free(cacerts[j].CertData);
00286             }
00287          }
00288          if (localcert.CertData) {
00289             free(localcert.CertData);
00290          }
00291          if (privatekey.PrivateKeyData) {
00292             free(privatekey.PrivateKeyData);
00293          }
00294          free(p);
00295          return 0;
00296       }
00297       pcacerts[i] = &cacerts[i];
00298    }
00299    
00300    for (i = 0; i < p->spcount; i++) {
00301       psrvpoints[i] = p->srvpoints[i];
00302    }
00303 
00304    error = OSPPProviderNew(p->spcount, psrvpoints, NULL, OSP_AUDIT_URL, &privatekey, &localcert, p->cacount, pcacerts, OSP_LOCAL_VALIDATION,
00305             OSP_SSL_LIFETIME, p->maxconnections, OSP_HTTP_PERSISTENCE, p->retrydelay, p->retrylimit,p->timeout, OSP_CUSTOMER_ID,
00306             OSP_DEVICE_ID, &p->handle);
00307    if (error != OSPC_ERR_NO_ERROR) {
00308       ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
00309       free(p);
00310       res = -1;
00311    } else {
00312       ast_log(LOG_DEBUG, "OSP: provider '%s'\n", provider);
00313       ast_mutex_lock(&osplock);
00314       p->next = ospproviders;
00315       ospproviders = p;
00316       ast_mutex_unlock(&osplock);   
00317       res = 1;
00318    }
00319 
00320    for (i = 0; i < p->cacount; i++) {
00321       if (cacerts[i].CertData) {
00322          free(cacerts[i].CertData);
00323       }
00324    }
00325    if (localcert.CertData) {
00326       free(localcert.CertData);
00327    }
00328    if (privatekey.PrivateKeyData) {
00329       free(privatekey.PrivateKeyData);
00330    }
00331 
00332    return res;
00333 }
00334 
00335 /*!
00336  * \brief Get OSP authenticiation policy of provider
00337  * \param provider OSP provider context name
00338  * \param policy OSP authentication policy, output
00339  * \return 1 Success, 0 Failed, -1 Error
00340  */
00341 static int osp_get_policy(const char* provider, int* policy)
00342 {
00343    int res = 0;
00344    struct osp_provider* p;
00345 
00346    ast_mutex_lock(&osplock);
00347    p = ospproviders;
00348    while(p) {
00349       if (!strcasecmp(p->name, provider)) {
00350          *policy = p->authpolicy;
00351          ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", *policy);
00352          res = 1;
00353          break;
00354       }
00355       p = p->next;
00356    }
00357    ast_mutex_unlock(&osplock);
00358 
00359    return res;
00360 }
00361 
00362 /*!
00363  * \brief Create OSP transaction handle
00364  * \param provider OSP provider context name
00365  * \param transaction OSP transaction handle, output
00366  * \param sourcesize Size of source buffer, in/output
00367  * \param source Source of provider, output
00368  * \return 1 Success, 0 Failed, -1 Error
00369  */
00370 static int osp_create_transaction(const char* provider, int* transaction, unsigned int sourcesize, char* source)
00371 {
00372    int res = 0;
00373    struct osp_provider* p;
00374    int error;
00375 
00376    ast_mutex_lock(&osplock);
00377    p = ospproviders;
00378    while(p) {
00379       if (!strcasecmp(p->name, provider)) {
00380          error = OSPPTransactionNew(p->handle, transaction);
00381          if (error == OSPC_ERR_NO_ERROR) {
00382             ast_log(LOG_DEBUG, "OSP: transaction '%d'\n", *transaction);
00383             ast_copy_string(source, p->source, sourcesize);
00384             ast_log(LOG_DEBUG, "OSP: source '%s'\n", source);
00385             res = 1;
00386          } else {
00387             *transaction = OSP_INVALID_HANDLE;
00388             ast_log(LOG_DEBUG, "OSP: Unable to create transaction handle, error '%d'\n", error);
00389             res = -1;
00390          }
00391          break;
00392       }
00393       p = p->next;
00394    }
00395    ast_mutex_unlock(&osplock);
00396 
00397    return res;
00398 }
00399 
00400 /*!
00401  * \brief Convert address to "[x.x.x.x]" or "host.domain" format
00402  * \param src Source address string
00403  * \param dst Destination address string
00404  * \param buffersize Size of dst buffer
00405  */
00406 static void osp_convert_address(
00407    const char* src,
00408    char* dst,
00409    int buffersize)
00410 {
00411    struct in_addr inp;
00412 
00413    if (inet_aton(src, &inp) != 0) {
00414       snprintf(dst, buffersize, "[%s]", src);
00415    } else {
00416       snprintf(dst, buffersize, "%s", src);
00417    }
00418 }
00419 
00420 /*!
00421  * \brief Validate OSP token of inbound call
00422  * \param transaction OSP transaction handle
00423  * \param source Source of inbound call
00424  * \param dest Destination of inbound call
00425  * \param calling Calling number
00426  * \param called Called number
00427  * \param token OSP token, may be empty
00428  * \param timelimit Call duration limit, output
00429  * \return 1 Success, 0 Failed, -1 Error
00430  */
00431 static int osp_validate_token(int transaction, const char* source, const char* dest, const char* calling, const char* called, const char* token, unsigned int* timelimit)
00432 {
00433    int res;
00434    int tokenlen;
00435    unsigned char tokenstr[OSP_TOKSTR_SIZE];
00436    char src[OSP_NORSTR_SIZE];
00437    char dst[OSP_NORSTR_SIZE];
00438    unsigned int authorised;
00439    unsigned int dummy = 0;
00440    int error;
00441 
00442    tokenlen = ast_base64decode(tokenstr, token, strlen(token));
00443    osp_convert_address(source, src, sizeof(src));
00444    osp_convert_address(dest, dst, sizeof(dst));
00445    error = OSPPTransactionValidateAuthorisation(
00446       transaction, 
00447       src, dst, NULL, NULL,
00448       calling ? calling : "", OSPC_E164, 
00449       called, OSPC_E164, 
00450       0, NULL,
00451       tokenlen, (char *) tokenstr, 
00452       &authorised, 
00453       timelimit, 
00454       &dummy, NULL, 
00455       osp_tokenformat); 
00456    if (error != OSPC_ERR_NO_ERROR) {
00457       ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n");
00458       res = -1;
00459    } else if (authorised) {
00460       ast_log(LOG_DEBUG, "OSP: Authorised\n");
00461       res = 1;
00462    } else {
00463       ast_log(LOG_DEBUG, "OSP: Unauthorised\n");
00464       res = 0;
00465    }
00466    
00467    return res;
00468 }
00469 
00470 /*!
00471  * \brief Choose min duration limit
00472  * \param in Inbound duration limit
00473  * \param out Outbound duration limit
00474  * \return min duration limit
00475  */
00476 static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out)
00477 {
00478    if (in == OSP_DEF_TIMELIMIT) {
00479       return out;
00480    } else if (out == OSP_DEF_TIMELIMIT) {
00481       return in;
00482    } else {
00483       return in < out ? in : out;
00484    }
00485 }
00486 
00487 /*!
00488  * \brief Choose min duration limit
00489  * \param called Called number
00490  * \param calling Calling number
00491  * \param destination Destination IP in '[x.x.x.x]' format
00492  * \param tokenlen OSP token length
00493  * \param token OSP token
00494  * \param reason Failure reason, output
00495  * \param result OSP lookup results, in/output
00496  * \return 1 Success, 0 Failed, -1 Error
00497  */
00498 static int osp_check_destination(const char* called, const char* calling, char* destination, unsigned int tokenlen, const char* token, enum OSPEFAILREASON* reason, struct osp_result* result)
00499 {
00500    int res;
00501    OSPE_DEST_OSP_ENABLED enabled;
00502    OSPE_DEST_PROT protocol;
00503    int error;
00504 
00505    if (strlen(destination) <= 2) {
00506       ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination);
00507       *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00508       return -1;
00509    } 
00510 
00511    if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
00512       ast_log(LOG_DEBUG, "OSP: Unable to get destination OSP version, error '%d'\n", error);
00513       *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00514       return -1;
00515    }
00516 
00517    if (enabled == OSPE_OSP_FALSE) {
00518       result->token[0] = '\0';
00519    } else {
00520       ast_base64encode(result->token, (const unsigned char *) token, tokenlen, sizeof(result->token) - 1);
00521    }
00522 
00523    if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
00524       ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error);
00525       *reason = OSPC_FAIL_NORMAL_UNSPECIFIED; 
00526       result->token[0] = '\0';
00527       return -1;
00528    } 
00529 
00530    res = 1;
00531    /* Strip leading and trailing brackets */
00532    destination[strlen(destination) - 1] = '\0';
00533    switch(protocol) {
00534       case OSPE_DEST_PROT_H323_SETUP:
00535          ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00536          ast_copy_string(result->tech, "H323", sizeof(result->tech));
00537          snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00538          ast_copy_string(result->calling, calling, sizeof(result->calling));
00539          break;
00540       case OSPE_DEST_PROT_SIP:
00541          ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00542          ast_copy_string(result->tech, "SIP", sizeof(result->tech));
00543          snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00544          ast_copy_string(result->calling, calling, sizeof(result->calling));
00545          break;
00546       case OSPE_DEST_PROT_IAX:
00547          ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00548          ast_copy_string(result->tech, "IAX", sizeof(result->tech));
00549          snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00550          ast_copy_string(result->calling, calling, sizeof(result->calling));
00551          break;
00552       default:
00553          ast_log(LOG_DEBUG, "OSP: Unknown protocol '%d'\n", protocol);
00554          *reason = OSPC_FAIL_PROTOCOL_ERROR; 
00555          result->token[0] = '\0';
00556          res = 0;
00557    }
00558 
00559    return res;
00560 }
00561 
00562 /*!
00563  * \brief Convert Asterisk status to TC code
00564  * \param cause Asterisk hangup cause
00565  * \return OSP TC code
00566  */
00567 static enum OSPEFAILREASON asterisk2osp(int cause)
00568 {
00569    return (enum OSPEFAILREASON)cause;
00570 }
00571 
00572 /*!
00573  * \brief OSP Authentication function
00574  * \param provider OSP provider context name
00575  * \param transaction OSP transaction handle, output
00576  * \param source Source of inbound call
00577  * \param calling Calling number
00578  * \param called Called number
00579  * \param token OSP token, may be empty
00580  * \param timelimit Call duration limit, output
00581  * \return 1 Authenricated, 0 Unauthenticated, -1 Error
00582  */
00583 static int osp_auth(const char* provider, int* transaction, const char* source, const char* calling, const char* called, const char* token, unsigned int* timelimit)
00584 {
00585    int res;
00586    int policy = OSP_AUTH_YES;
00587    char dest[OSP_NORSTR_SIZE];
00588 
00589    *transaction = OSP_INVALID_HANDLE;
00590    *timelimit = OSP_DEF_TIMELIMIT;
00591    res = osp_get_policy(provider, &policy);
00592    if (!res) {
00593       ast_log(LOG_DEBUG, "OSP: Unabe to find OSP authentication policy\n");
00594       return res;
00595    }
00596 
00597    switch (policy) {
00598       case OSP_AUTH_NO:
00599          res = 1;
00600          break;
00601       case OSP_AUTH_EXCLUSIVE:
00602          if (ast_strlen_zero(token)) {
00603             res = 0;
00604          } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00605             ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00606             *transaction = OSP_INVALID_HANDLE;
00607             res = 0;
00608          } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00609             OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00610          }
00611          break;
00612       case OSP_AUTH_YES:
00613       default:
00614          if (ast_strlen_zero(token)) {
00615             res = 1;
00616          } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00617             ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00618             *transaction = OSP_INVALID_HANDLE;
00619             res = 0;
00620          } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00621             OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00622          }
00623          break;
00624    }
00625 
00626    return res;
00627 }
00628 
00629 /*!
00630  * \brief OSP Lookup function
00631  * \param provider OSP provider context name
00632  * \param srcdev Source device of outbound call
00633  * \param calling Calling number
00634  * \param called Called number
00635  * \param result Lookup results
00636  * \return 1 Found , 0 No route, -1 Error
00637  */
00638 static int osp_lookup(const char* provider, const char* srcdev, const char* calling, const char* called, struct osp_result* result)
00639 {
00640    int res;
00641    char source[OSP_NORSTR_SIZE];
00642    unsigned int callidlen;
00643    char callid[OSPC_CALLID_MAXSIZE];
00644    char callingnum[OSP_NORSTR_SIZE];
00645    char callednum[OSP_NORSTR_SIZE];
00646    char destination[OSP_NORSTR_SIZE];
00647    unsigned int tokenlen;
00648    char token[OSP_TOKSTR_SIZE];
00649    char src[OSP_NORSTR_SIZE];
00650    char dev[OSP_NORSTR_SIZE];
00651    unsigned int dummy = 0;
00652    enum OSPEFAILREASON reason;
00653    int error;
00654 
00655    result->outhandle = OSP_INVALID_HANDLE;
00656    result->tech[0] = '\0';
00657    result->dest[0] = '\0';
00658    result->calling[0] = '\0';
00659    result->token[0] = '\0';
00660    result->numresults = 0;
00661    result->outtimelimit = OSP_DEF_TIMELIMIT;
00662 
00663    if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
00664       ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00665       result->outhandle = OSP_INVALID_HANDLE;
00666       if (result->inhandle != OSP_INVALID_HANDLE) {
00667          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00668       }
00669       return -1;
00670    }
00671 
00672    osp_convert_address(source, src, sizeof(src));
00673    osp_convert_address(srcdev, dev, sizeof(dev));
00674    result->numresults = OSP_DEF_DESTINATIONS;
00675    error = OSPPTransactionRequestAuthorisation(result->outhandle, src, dev, calling ? calling : "",
00676          OSPC_E164, called, OSPC_E164, NULL, 0, NULL, NULL, &result->numresults, &dummy, NULL);
00677    if (error != OSPC_ERR_NO_ERROR) {
00678       ast_log(LOG_DEBUG, "OSP: Unable to request authorization\n");
00679       result->numresults = 0;
00680       if (result->inhandle != OSP_INVALID_HANDLE) {
00681          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00682       }
00683       return -1;
00684    }
00685 
00686    if (!result->numresults) {
00687       ast_log(LOG_DEBUG, "OSP: No more destination\n");
00688       if (result->inhandle != OSP_INVALID_HANDLE) {
00689          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00690       }
00691       return 0;
00692    }
00693 
00694    callidlen = sizeof(callid);
00695    tokenlen = sizeof(token);
00696    error = OSPPTransactionGetFirstDestination(result->outhandle, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00697          sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00698    if (error != OSPC_ERR_NO_ERROR) {
00699       ast_log(LOG_DEBUG, "OSP: Unable to get first route\n");
00700       result->numresults = 0;
00701       result->outtimelimit = OSP_DEF_TIMELIMIT;
00702       if (result->inhandle != OSP_INVALID_HANDLE) {
00703          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00704       }
00705       return -1;
00706    }
00707 
00708    result->numresults--;
00709    result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00710    ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00711    ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00712    ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00713    ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00714    ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00715 
00716    if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00717       return 1;
00718    }
00719 
00720    if (!result->numresults) {
00721       ast_log(LOG_DEBUG, "OSP: No more destination\n");
00722       result->outtimelimit = OSP_DEF_TIMELIMIT;
00723       OSPPTransactionRecordFailure(result->outhandle, reason);
00724       if (result->inhandle != OSP_INVALID_HANDLE) {
00725          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00726       }
00727       return 0;
00728    }
00729 
00730    while(result->numresults) {
00731       callidlen = sizeof(callid);
00732       tokenlen = sizeof(token);
00733       error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00734             sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00735       if (error == OSPC_ERR_NO_ERROR) {
00736          result->numresults--;
00737          result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00738          ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00739          ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00740          ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00741          ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00742          ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00743          if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00744             break;
00745          } else if (!result->numresults) {
00746             ast_log(LOG_DEBUG, "OSP: No more destination\n");
00747             OSPPTransactionRecordFailure(result->outhandle, reason);
00748             if (result->inhandle != OSP_INVALID_HANDLE) {
00749                OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00750             }
00751             res = 0;
00752             break;
00753          }
00754       } else {
00755          ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00756          result->numresults = 0;
00757          result->outtimelimit = OSP_DEF_TIMELIMIT;
00758          if (result->inhandle != OSP_INVALID_HANDLE) {
00759             OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00760          }
00761          res = -1;
00762          break;
00763       }
00764    }
00765    return res;
00766 }
00767 
00768 /*!
00769  * \brief OSP Lookup Next function
00770  * \param cause Asterisk hangup cuase
00771  * \param result Lookup results, in/output
00772  * \return 1 Found , 0 No route, -1 Error
00773  */
00774 static int osp_next(int cause, struct osp_result* result)
00775 {
00776    int res;
00777    unsigned int callidlen;
00778    char callid[OSPC_CALLID_MAXSIZE];
00779    char callingnum[OSP_NORSTR_SIZE];
00780    char callednum[OSP_NORSTR_SIZE];
00781    char destination[OSP_NORSTR_SIZE];
00782    unsigned int tokenlen;
00783    char token[OSP_TOKSTR_SIZE];
00784    enum OSPEFAILREASON reason;
00785    int error;
00786 
00787    result->tech[0] = '\0';
00788    result->dest[0] = '\0';
00789    result->calling[0] = '\0';
00790    result->token[0] = '\0';
00791    result->outtimelimit = OSP_DEF_TIMELIMIT;
00792 
00793    if (result->outhandle == OSP_INVALID_HANDLE) {
00794       ast_log(LOG_DEBUG, "OSP: Transaction handle undefined\n");
00795       result->numresults = 0;
00796       if (result->inhandle != OSP_INVALID_HANDLE) {
00797          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00798       }
00799       return -1;
00800    }
00801 
00802    reason = asterisk2osp(cause);
00803 
00804    if (!result->numresults) {
00805       ast_log(LOG_DEBUG, "OSP: No more destination\n");
00806       OSPPTransactionRecordFailure(result->outhandle, reason);
00807       if (result->inhandle != OSP_INVALID_HANDLE) {
00808          OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00809       }
00810       return 0;
00811    }
00812 
00813    while(result->numresults) {
00814       callidlen = sizeof(callid);
00815       tokenlen = sizeof(token);
00816       error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen,
00817             callid, sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00818       if (error == OSPC_ERR_NO_ERROR) {
00819          result->numresults--;
00820          result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00821          ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00822          ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00823          ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00824          ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00825          ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00826          if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00827             res = 1;
00828             break;
00829          } else if (!result->numresults) {
00830             ast_log(LOG_DEBUG, "OSP: No more destination\n");
00831             OSPPTransactionRecordFailure(result->outhandle, reason);
00832             if (result->inhandle != OSP_INVALID_HANDLE) {
00833                OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00834             }
00835             res = 0;
00836             break;
00837          }
00838       } else {
00839          ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00840          result->token[0] = '\0';
00841          result->numresults = 0;
00842          result->outtimelimit = OSP_DEF_TIMELIMIT;
00843          if (result->inhandle != OSP_INVALID_HANDLE) {
00844             OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00845          }
00846          res = -1;
00847          break;
00848       }
00849    }
00850 
00851    return res;
00852 }
00853 
00854 /*!
00855  * \brief OSP Finish function
00856  * \param handle OSP in/outbound transaction handle
00857  * \param recorded If failure reason has been recorded
00858  * \param cause Asterisk hangup cause
00859  * \param start Call start time
00860  * \param connect Call connect time
00861  * \param end Call end time
00862  * \param release Who release first, 0 source, 1 destination
00863  * \return 1 Success, 0 Failed, -1 Error
00864  */
00865 static int osp_finish(int handle, int recorded, int cause, time_t start, time_t connect, time_t end, unsigned int release)
00866 {
00867    int res;
00868    enum OSPEFAILREASON reason;
00869    time_t alert = 0;
00870    unsigned isPddInfoPresent = 0;
00871    unsigned pdd = 0;
00872    unsigned int dummy = 0;
00873    int error;
00874    
00875    if (handle == OSP_INVALID_HANDLE) {
00876       return 0;
00877    }
00878 
00879    if (!recorded) {
00880       reason = asterisk2osp(cause);
00881       OSPPTransactionRecordFailure(handle, reason);
00882    }
00883 
00884    error = OSPPTransactionReportUsage(handle, difftime(end, connect), start, end, alert, connect, isPddInfoPresent, pdd,
00885                   release, (unsigned char *) "", 0, 0, 0, 0, &dummy, NULL);
00886    if (error == OSPC_ERR_NO_ERROR) {
00887       ast_log(LOG_DEBUG, "OSP: Usage reported\n");
00888       res = 1;
00889    } else {
00890       ast_log(LOG_DEBUG, "OSP: Unable to report usage, error '%d'\n", error);
00891       res = -1;
00892    }
00893    OSPPTransactionDelete(handle);
00894 
00895    return res;
00896 }
00897 
00898 /* OSP Application APIs */
00899 
00900 /*!
00901  * \brief OSP Application OSPAuth
00902  * \param chan Channel
00903  * \param data Parameter
00904  * \return 0 Success, -1 Failed
00905  */
00906 static int ospauth_exec(struct ast_channel* chan, void* data)
00907 {
00908    int res;
00909    struct ast_module_user *u;
00910    const char* provider = OSP_DEF_PROVIDER;
00911    int priority_jump = 0;
00912    struct varshead *headp;
00913    struct ast_var_t *current;
00914    const char *source = "";
00915    const char *token = "";
00916    int handle;
00917    unsigned int timelimit;
00918    char buffer[OSP_INTSTR_SIZE];
00919    const char *status;
00920    char *tmp;
00921 
00922    AST_DECLARE_APP_ARGS(args,
00923       AST_APP_ARG(provider);
00924       AST_APP_ARG(options);
00925    );
00926 
00927    u = ast_module_user_add(chan);
00928 
00929    if (!(tmp = ast_strdupa(data))) {
00930       ast_log(LOG_ERROR, "Out of memory\n");
00931       ast_module_user_remove(u);
00932       return -1;
00933    }
00934 
00935    AST_STANDARD_APP_ARGS(args, tmp);
00936 
00937    if (!ast_strlen_zero(args.provider)) {
00938       provider = args.provider;
00939    }
00940    ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
00941 
00942    if ((args.options) && (strchr(args.options, 'j'))) {
00943       priority_jump = 1;
00944    }
00945    ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
00946 
00947    headp = &chan->varshead;
00948    AST_LIST_TRAVERSE(headp, current, entries) {
00949       if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
00950          source = ast_var_value(current);
00951       } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
00952          token = ast_var_value(current);
00953       }
00954    }
00955    ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
00956    ast_log(LOG_DEBUG, "OSPAuth: token size '%zd'\n", strlen(token));
00957 
00958    
00959    if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
00960       status = AST_OSP_SUCCESS;
00961    } else {
00962       timelimit = OSP_DEF_TIMELIMIT;
00963       if (!res) {
00964          status = AST_OSP_FAILED;
00965       } else {
00966          status = AST_OSP_ERROR;
00967       }
00968    }
00969 
00970    snprintf(buffer, sizeof(buffer), "%d", handle);
00971    pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
00972    ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
00973    snprintf(buffer, sizeof(buffer), "%d", timelimit);
00974    pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
00975    ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
00976    pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
00977    ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
00978 
00979    if(res <= 0) {
00980       if (priority_jump || ast_opt_priority_jumping) {
00981          ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
00982          res = 0;
00983       } else {
00984          res = -1;
00985       }
00986    } else {
00987       res = 0;
00988    }
00989 
00990    ast_module_user_remove(u);
00991 
00992    return res;
00993 }
00994 
00995 /*!
00996  * \brief OSP Application OSPLookup
00997  * \param chan Channel
00998  * \param data Parameter
00999  * \return 0 Success, -1 Failed
01000  */
01001 static int osplookup_exec(struct ast_channel* chan, void* data)
01002 {
01003    int res, cres;
01004    struct ast_module_user *u;
01005    const char *provider = OSP_DEF_PROVIDER;
01006    int priority_jump = 0;
01007    struct varshead *headp;
01008    struct ast_var_t* current;
01009    const char *srcdev = "";
01010    char buffer[OSP_TOKSTR_SIZE];
01011    struct osp_result result;
01012    const char *status;
01013    char *tmp;
01014 
01015    AST_DECLARE_APP_ARGS(args,
01016       AST_APP_ARG(exten);
01017       AST_APP_ARG(provider);
01018       AST_APP_ARG(options);
01019    );
01020    
01021    if (ast_strlen_zero(data)) {
01022       ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
01023       return -1;
01024    }
01025 
01026    u = ast_module_user_add(chan);
01027 
01028    if (!(tmp = ast_strdupa(data))) {
01029       ast_log(LOG_ERROR, "Out of memory\n");
01030       ast_module_user_remove(u);
01031       return -1;
01032    }
01033 
01034    AST_STANDARD_APP_ARGS(args, tmp);
01035 
01036    ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
01037 
01038    if (!ast_strlen_zero(args.provider)) {
01039       provider = args.provider;
01040    }
01041    ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
01042 
01043    if ((args.options) && (strchr(args.options, 'j'))) {
01044       priority_jump = 1;
01045    }
01046    ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
01047 
01048    result.inhandle = OSP_INVALID_HANDLE;
01049    result.intimelimit = OSP_DEF_TIMELIMIT;
01050 
01051    headp = &chan->varshead;
01052    AST_LIST_TRAVERSE(headp, current, entries) {
01053       if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01054          if (sscanf(ast_var_value(current), "%30d", &result.inhandle) != 1) {
01055             result.inhandle = OSP_INVALID_HANDLE;
01056          }
01057       } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01058          if (sscanf(ast_var_value(current), "%30d", &result.intimelimit) != 1) {
01059             result.intimelimit = OSP_DEF_TIMELIMIT;
01060          }
01061       } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
01062          srcdev = ast_var_value(current);
01063       }
01064    }
01065    ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
01066    ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01067    ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
01068    
01069    if ((cres = ast_autoservice_start(chan)) < 0) {
01070       ast_module_user_remove(u);
01071       return -1;
01072    }
01073 
01074    if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result)) > 0) {
01075       status = AST_OSP_SUCCESS;
01076    } else {
01077       result.tech[0] = '\0';
01078       result.dest[0] = '\0';
01079       result.calling[0] = '\0';
01080       result.token[0] = '\0'; 
01081       result.numresults = 0;
01082       result.outtimelimit = OSP_DEF_TIMELIMIT;
01083       if (!res) {
01084          status = AST_OSP_FAILED;
01085       } else {
01086          status = AST_OSP_ERROR;
01087       }
01088    }
01089 
01090    snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
01091    pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01092    ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
01093    pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01094    ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
01095    pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01096    ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
01097    pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01098    ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
01099    pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01100    ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01101    snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01102    pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01103    ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
01104    snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01105    pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01106    ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
01107    pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
01108    ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
01109 
01110    if (!strcasecmp(result.tech, "SIP")) {
01111       if (!ast_strlen_zero(result.token)) {
01112          snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01113          pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01114          ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01115       }
01116    } else if (!strcasecmp(result.tech, "H323")) {
01117    } else if (!strcasecmp(result.tech, "IAX")) {
01118    }
01119 
01120    if ((cres = ast_autoservice_stop(chan)) < 0) {
01121       ast_module_user_remove(u);
01122       return -1;
01123    }
01124 
01125    if(res <= 0) {
01126       if (priority_jump || ast_opt_priority_jumping) {
01127          ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01128          res = 0;
01129       } else {
01130          res = -1;
01131       }
01132    } else {
01133       res = 0;
01134    }
01135 
01136    ast_module_user_remove(u);
01137 
01138    return res;
01139 }
01140 
01141 /*!
01142  * \brief OSP Application OSPNext
01143  * \param chan Channel
01144  * \param data Parameter
01145  * \return 0 Success, -1 Failed
01146  */
01147 static int ospnext_exec(struct ast_channel* chan, void* data)
01148 {
01149    int res;
01150    struct ast_module_user *u;
01151    int priority_jump = 0;
01152    int cause = 0;
01153    struct varshead* headp;
01154    struct ast_var_t* current;
01155    struct osp_result result;
01156    char buffer[OSP_TOKSTR_SIZE];
01157    const char* status;
01158    char* tmp;
01159 
01160    AST_DECLARE_APP_ARGS(args,
01161       AST_APP_ARG(cause);
01162       AST_APP_ARG(options);
01163    );
01164    
01165    if (ast_strlen_zero(data)) {
01166       ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n");
01167       return -1;
01168    }
01169 
01170    u = ast_module_user_add(chan);
01171 
01172    if (!(tmp = ast_strdupa(data))) {
01173       ast_log(LOG_ERROR, "Out of memory\n");
01174       ast_module_user_remove(u);
01175       return -1;
01176    }
01177 
01178    AST_STANDARD_APP_ARGS(args, tmp);
01179 
01180    if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
01181       cause = 0;
01182    }
01183    ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
01184 
01185    if ((args.options) && (strchr(args.options, 'j'))) {
01186       priority_jump = 1;
01187    }
01188    ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
01189 
01190    result.inhandle = OSP_INVALID_HANDLE;
01191    result.outhandle = OSP_INVALID_HANDLE;
01192    result.intimelimit = OSP_DEF_TIMELIMIT;
01193    result.numresults = 0;
01194 
01195    headp = &chan->varshead;
01196    AST_LIST_TRAVERSE(headp, current, entries) {
01197       if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01198          if (sscanf(ast_var_value(current), "%30d", &result.inhandle) != 1) {
01199             result.inhandle = OSP_INVALID_HANDLE;
01200          }
01201       } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01202          if (sscanf(ast_var_value(current), "%30d", &result.outhandle) != 1) {
01203             result.outhandle = OSP_INVALID_HANDLE;
01204          }
01205       } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01206          if (sscanf(ast_var_value(current), "%30d", &result.intimelimit) != 1) {
01207             result.intimelimit = OSP_DEF_TIMELIMIT;
01208          }
01209       } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
01210          if (sscanf(ast_var_value(current), "%30d", &result.numresults) != 1) {
01211             result.numresults = 0;
01212          }
01213       }
01214    }
01215    ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
01216    ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
01217    ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01218    ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
01219 
01220    if ((res = osp_next(cause, &result)) > 0) {
01221       status = AST_OSP_SUCCESS;
01222    } else {
01223       result.tech[0] = '\0';
01224       result.dest[0] = '\0';
01225       result.calling[0] = '\0';
01226       result.token[0] = '\0'; 
01227       result.numresults = 0;
01228       result.outtimelimit = OSP_DEF_TIMELIMIT;
01229       if (!res) {
01230          status = AST_OSP_FAILED;
01231       } else {
01232          status = AST_OSP_ERROR;
01233       }
01234    }
01235 
01236    pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01237    ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
01238    pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01239    ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
01240    pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01241    ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
01242    pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01243    ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01244    snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01245    pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01246    ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
01247    snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01248    pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01249    ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
01250    pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
01251    ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
01252 
01253    if (!strcasecmp(result.tech, "SIP")) {
01254       if (!ast_strlen_zero(result.token)) {
01255          snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01256          pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01257          ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01258       }
01259    } else if (!strcasecmp(result.tech, "H323")) {
01260    } else if (!strcasecmp(result.tech, "IAX")) {
01261    }
01262 
01263    if(res <= 0) {
01264       if (priority_jump || ast_opt_priority_jumping) {
01265          ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01266          res = 0;
01267       } else {
01268          res = -1;
01269       }
01270    } else {
01271       res = 0;
01272    }
01273 
01274    ast_module_user_remove(u);
01275 
01276    return res;
01277 }
01278 
01279 /*!
01280  * \brief OSP Application OSPFinish
01281  * \param chan Channel
01282  * \param data Parameter
01283  * \return 0 Success, -1 Failed
01284  */
01285 static int ospfinished_exec(struct ast_channel* chan, void* data)
01286 {
01287    int res = 1;
01288    struct ast_module_user *u;
01289    int priority_jump = 0;
01290    int cause = 0;
01291    struct varshead *headp;
01292    struct ast_var_t *current;
01293    int inhandle = OSP_INVALID_HANDLE;
01294    int outhandle = OSP_INVALID_HANDLE;
01295    int recorded = 0;
01296    time_t start, connect, end;
01297    unsigned int release;
01298    char buffer[OSP_INTSTR_SIZE];
01299    const char *status;
01300    char *tmp;
01301 
01302    AST_DECLARE_APP_ARGS(args,
01303       AST_APP_ARG(cause);
01304       AST_APP_ARG(options);
01305    );
01306    
01307    u = ast_module_user_add(chan);
01308 
01309    if (!(tmp = ast_strdupa(data))) {
01310       ast_log(LOG_ERROR, "Out of memory\n");
01311       ast_module_user_remove(u);
01312       return -1;
01313    }
01314 
01315    AST_STANDARD_APP_ARGS(args, tmp);
01316 
01317    if ((args.options) && (strchr(args.options, 'j'))) {
01318       priority_jump = 1;
01319    }
01320    ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
01321 
01322    headp = &chan->varshead;
01323    AST_LIST_TRAVERSE(headp, current, entries) {
01324       if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01325          if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
01326             inhandle = OSP_INVALID_HANDLE;
01327          }
01328       } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01329          if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
01330             outhandle = OSP_INVALID_HANDLE;
01331          }
01332       } else if (!recorded &&
01333          (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
01334          !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") || 
01335          !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS"))) 
01336       {
01337          if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
01338             recorded = 1;
01339          }
01340       }
01341    }
01342    ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
01343    ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
01344    ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
01345 
01346    if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
01347       cause = 0;
01348    }
01349    ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
01350 
01351    if (chan->cdr) {
01352       start = chan->cdr->start.tv_sec;
01353       connect = chan->cdr->answer.tv_sec;
01354       if (connect) {
01355          end = time(NULL);
01356       } else {
01357          end = connect;
01358       }
01359    } else {
01360       start = 0;
01361       connect = 0;
01362       end = 0;
01363    }
01364    ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
01365    ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
01366    ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
01367 
01368    release = chan->_softhangup ? 0 : 1;
01369 
01370    if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
01371       ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for outbound call\n");
01372    }
01373    switch (cause) {
01374       case AST_CAUSE_NORMAL_CLEARING:
01375          break;
01376       default:
01377          cause = AST_CAUSE_NO_ROUTE_DESTINATION;
01378          break;
01379    }
01380    if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
01381       ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for inbound call\n");
01382    }
01383    snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
01384    pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01385    pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
01386 
01387    if (res > 0) {
01388       status = AST_OSP_SUCCESS;
01389    } else if (!res) {
01390       status = AST_OSP_FAILED;
01391    } else {
01392       status = AST_OSP_ERROR;
01393    }
01394    pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
01395 
01396    if(!res) {
01397       if (priority_jump || ast_opt_priority_jumping) {
01398          ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01399          res = 0;
01400       } else {
01401          res = -1;
01402       }
01403    } else {
01404       res = 0;
01405    }
01406 
01407    ast_module_user_remove(u);
01408 
01409    return res;
01410 }
01411 
01412 /* OSP Module APIs */
01413 
01414 static int osp_load(void)
01415 {
01416    const char* t;
01417    unsigned int v;
01418    struct ast_config* cfg;
01419    int error = OSPC_ERR_NO_ERROR;
01420 
01421    cfg = ast_config_load(OSP_CONFIG_FILE);
01422    if (cfg) {
01423       t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
01424       if (t && ast_true(t)) {
01425          if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
01426             ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
01427             OSPPInit(0);
01428          } else {
01429             osp_hardware = 1;
01430          }
01431       } else {
01432          OSPPInit(0);
01433       }
01434       ast_log(LOG_DEBUG, "OSP: osp_hardware '%d'\n", osp_hardware);
01435 
01436       t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
01437       if (t) {
01438          if ((sscanf(t, "%30d", &v) == 1) && 
01439             ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH))) 
01440          {
01441             osp_tokenformat = v;
01442          } else {
01443             ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n", 
01444                TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
01445          }
01446       }
01447       ast_log(LOG_DEBUG, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
01448 
01449       t = ast_category_browse(cfg, NULL);
01450       while(t) {
01451          if (strcasecmp(t, OSP_GENERAL_CAT)) {
01452             osp_create_provider(cfg, t);
01453          }
01454          t = ast_category_browse(cfg, t);
01455       }
01456 
01457       osp_initialized = 1;
01458 
01459       ast_config_destroy(cfg);
01460    } else {
01461       ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
01462       return 0;
01463    }
01464    ast_log(LOG_DEBUG, "OSP: osp_initialized '%d'\n", osp_initialized);
01465 
01466    return 1;
01467 }
01468 
01469 static int osp_unload(void)
01470 {
01471    struct osp_provider* p;
01472    struct osp_provider* next;
01473 
01474    if (osp_initialized) {
01475       ast_mutex_lock(&osplock);
01476       p = ospproviders;
01477       while(p) {
01478          next = p->next;
01479          OSPPProviderDelete(p->handle, 0);
01480          free(p);
01481          p = next;
01482       }
01483       ospproviders = NULL;
01484       ast_mutex_unlock(&osplock);
01485 
01486       OSPPCleanup();
01487 
01488       osp_tokenformat = TOKEN_ALGO_SIGNED;
01489       osp_hardware = 0;
01490       osp_initialized = 0;
01491    }
01492    return 0;
01493 }
01494 
01495 static int osp_show(int fd, int argc, char* argv[])
01496 {
01497    int i;
01498    int found = 0;
01499    struct osp_provider* p;
01500    const char* provider = NULL;
01501    const char* tokenalgo;
01502 
01503    if ((argc < 2) || (argc > 3)) {
01504       return RESULT_SHOWUSAGE;
01505    }
01506    if (argc > 2) {
01507       provider = argv[2];
01508    }
01509    if (!provider) {
01510       switch (osp_tokenformat) {
01511          case TOKEN_ALGO_BOTH:
01512             tokenalgo = "Both";
01513             break;
01514          case TOKEN_ALGO_UNSIGNED:
01515             tokenalgo = "Unsigned";
01516             break;
01517          case TOKEN_ALGO_SIGNED:
01518          default:
01519             tokenalgo = "Signed";
01520             break;
01521       }
01522       ast_cli(fd, "OSP: %s %s %s\n", 
01523          osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
01524    }
01525 
01526    ast_mutex_lock(&osplock);
01527    p = ospproviders;
01528    while(p) {
01529       if (!provider || !strcasecmp(p->name, provider)) {
01530          if (found) {
01531             ast_cli(fd, "\n");
01532          }
01533          ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
01534          ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
01535          ast_cli(fd, "Local Certificate: %s\n", p->localcert);
01536          for (i = 0; i < p->cacount; i++) {
01537             ast_cli(fd, "CA Certificate %d:  %s\n", i + 1, p->cacerts[i]);
01538          }
01539          for (i = 0; i < p->spcount; i++) {
01540             ast_cli(fd, "Service Point %d:   %s\n", i + 1, p->srvpoints[i]);
01541          }
01542          ast_cli(fd, "Max Connections:   %d\n", p->maxconnections);
01543          ast_cli(fd, "Retry Delay:       %d seconds\n", p->retrydelay);
01544          ast_cli(fd, "Retry Limit:       %d\n", p->retrylimit);
01545          ast_cli(fd, "Timeout:           %d milliseconds\n", p->timeout);
01546          ast_cli(fd, "Source:            %s\n", strlen(p->source) ? p->source : "<unspecified>");
01547          ast_cli(fd, "Auth Policy        %d\n", p->authpolicy);
01548          ast_cli(fd, "OSP Handle:        %d\n", p->handle);
01549          found++;
01550       }
01551       p = p->next;
01552    }
01553    ast_mutex_unlock(&osplock);
01554 
01555    if (!found) {
01556       if (provider) {
01557          ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
01558       } else {
01559          ast_cli(fd, "No OSP providers configured\n");
01560       }
01561    }
01562    return RESULT_SUCCESS;
01563 }
01564 
01565 static const char* app1= "OSPAuth";
01566 static const char* synopsis1 = "OSP authentication";
01567 static const char* descrip1 = 
01568 "  OSPAuth([provider[|options]]):  Authenticate a SIP INVITE by OSP and sets\n"
01569 "the variables:\n"
01570 " ${OSPINHANDLE}:  The inbound call transaction handle\n"
01571 " ${OSPINTIMELIMIT}:  The inbound call duration limit in seconds\n"
01572 "\n"
01573 "The option string may contain the following character:\n"
01574 "  'j' -- jump to n+101 priority if the authentication was NOT successful\n"
01575 "This application sets the following channel variable upon completion:\n"
01576 "  OSPAUTHSTATUS  The status of the OSP Auth attempt as a text string, one of\n"
01577 "     SUCCESS | FAILED | ERROR\n";
01578 
01579 static const char* app2= "OSPLookup";
01580 static const char* synopsis2 = "Lookup destination by OSP";
01581 static const char* descrip2 = 
01582 "  OSPLookup(exten[|provider[|options]]):  Looks up an extension via OSP and sets\n"
01583 "the variables, where 'n' is the number of the result beginning with 1:\n"
01584 " ${OSPOUTHANDLE}:  The OSP Handle for anything remaining\n"
01585 " ${OSPTECH}:  The technology to use for the call\n"
01586 " ${OSPDEST}:  The destination to use for the call\n"
01587 " ${OSPCALLING}:  The calling number to use for the call\n"
01588 " ${OSPOUTTOKEN}:  The actual OSP token as a string\n"
01589 " ${OSPOUTTIMELIMIT}:  The outbound call duration limit in seconds\n"
01590 " ${OSPRESULTS}:  The number of OSP results total remaining\n"
01591 "\n"
01592 "The option string may contain the following character:\n"
01593 "  'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01594 "This application sets the following channel variable upon completion:\n"
01595 "  OSPLOOKUPSTATUS   The status of the OSP Lookup attempt as a text string, one of\n"
01596 "     SUCCESS | FAILED | ERROR\n";
01597 
01598 static const char* app3 = "OSPNext";
01599 static const char* synopsis3 = "Lookup next destination by OSP";
01600 static const char* descrip3 = 
01601 "  OSPNext(cause[|options]):  Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
01602 "See OSPLookup for more information\n"
01603 "\n"
01604 "The option string may contain the following character:\n"
01605 "  'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01606 "This application sets the following channel variable upon completion:\n"
01607 "  OSPNEXTSTATUS  The status of the OSP Next attempt as a text string, one of\n"
01608 "     SUCCESS | FAILED |ERROR\n";
01609 
01610 static const char* app4 = "OSPFinish";
01611 static const char* synopsis4 = "Record OSP entry";
01612 static const char* descrip4 = 
01613 "  OSPFinish([status[|options]]):  Records call state for ${OSPINHANDLE}, according to\n"
01614 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
01615 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
01616 "\n"
01617 "The option string may contain the following character:\n"
01618 "  'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
01619 "This application sets the following channel variable upon completion:\n"
01620 "  OSPFINISHSTATUS   The status of the OSP Finish attempt as a text string, one of\n"
01621 "     SUCCESS | FAILED |ERROR \n";
01622 
01623 static const char osp_usage[] =
01624 "Usage: osp show\n"
01625 "       Displays information on Open Settlement Protocol support\n";
01626 
01627 static struct ast_cli_entry cli_osp[] = {
01628    { { "osp", "show", NULL},
01629    osp_show, "Displays OSP information",
01630    osp_usage },
01631 };
01632 
01633 static int load_module(void)
01634 {
01635    int res;
01636    
01637    if(!osp_load())
01638       return AST_MODULE_LOAD_DECLINE;
01639 
01640    ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01641    res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
01642    res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
01643    res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
01644    res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
01645 
01646    return res;
01647 }
01648 
01649 static int unload_module(void)
01650 {
01651    int res;
01652    
01653    res = ast_unregister_application(app4);
01654    res |= ast_unregister_application(app3);
01655    res |= ast_unregister_application(app2);
01656    res |= ast_unregister_application(app1);
01657    ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01658    osp_unload();
01659 
01660    ast_module_user_hangup_all();
01661 
01662    return res;
01663 }
01664 
01665 static int reload(void)
01666 {
01667    osp_unload();
01668    osp_load();
01669 
01670    return 0;
01671 }
01672 
01673 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
01674       .load = load_module,
01675       .unload = unload_module,
01676       .reload = reload,
01677       );

Generated on Thu Oct 11 06:41:59 2012 for Asterisk - the Open Source PBX by  doxygen 1.5.6