From 1e48c84df645f80fa055f36605bf95a72290978b Mon Sep 17 00:00:00 2001 From: Di-Shi Sun Date: Fri, 25 Nov 2011 17:26:46 +0800 Subject: [PATCH] Updated for OSP Toolkit 4.0.2. --- conf/autoload_configs/osp.conf.xml | 4 - src/mod/applications/mod_osp/mod_osp.c | 761 ++++++++++++++++--------- 2 files changed, 486 insertions(+), 279 deletions(-) diff --git a/conf/autoload_configs/osp.conf.xml b/conf/autoload_configs/osp.conf.xml index 419a0033ff..4d1137ebcb 100644 --- a/conf/autoload_configs/osp.conf.xml +++ b/conf/autoload_configs/osp.conf.xml @@ -48,10 +48,6 @@ - - - - diff --git a/src/mod/applications/mod_osp/mod_osp.c b/src/mod/applications/mod_osp/mod_osp.c index 03f9af6fb8..7c839ecc1f 100644 --- a/src/mod/applications/mod_osp/mod_osp.c +++ b/src/mod/applications/mod_osp/mod_osp.c @@ -29,11 +29,6 @@ * */ -/* - * TODO: - * 1. NID -> outbound messages - */ - #include #include #include @@ -67,7 +62,7 @@ #define OSP_DEVICE_ID "" /* OSP device ID */ #define OSP_DEF_MAXDEST 5 /* OSP default max destinations */ #define OSP_MIN_MAXDEST 1 /* OSP min max destinations */ -#define OSP_MAX_MAXDEST 10 /* OSP max max destinations */ +#define OSP_MAX_MAXDEST 12 /* OSP max max destinations */ #define OSP_DEF_PROFILE "default" /* OSP default profile name */ #define OSP_DEF_STRING "" /* OSP default empty string */ #define OSP_DEF_CALLID "UNDEFINED" /* OSP default Call-ID */ @@ -80,7 +75,7 @@ /* OSP Handle Constant */ #define OSP_INVALID_HANDLE -1 /* Invalid OSP handle, provider, transaction etc. */ -/* OSP Supported Destination Protocols for Default Protocol */ +/* OSP Supported Signaling Protocols for Default Protocol */ #define OSP_PROTOCOL_SIP "sip" /* SIP protocol name */ #define OSP_PROTOCOL_H323 "h323" /* H.323 protocol name */ #define OSP_PROTOCOL_IAX "iax" /* IAX protocol name */ @@ -89,48 +84,59 @@ #define OSP_PROTOCOL_UNDEF "undefined" /* Undefined protocol */ #define OSP_PROTOCOL_UNSUP "unsupported" /* Unsupported protocol */ -/* OSP Supported Destination Protocols for Destination Protocol Usage */ +/* OSP Supported Signaling Protocols for Signaling Protocol Usage */ #define OSP_MODULE_SIP "mod_sofia" /* FreeSWITCH SIP module name */ #define OSP_MODULE_H323 "mod_h323" /* FreeSWITCH H.323 module name */ #define OSP_MODULE_IAX "mod_iax" /* FreeSWITCH IAX module name */ #define OSP_MODULE_SKYPE "mod_skypopen" /* FreeSWITCH Skype module name */ /* OSP Variables Name */ -#define OSP_VAR_PROFILE "osp_profile" /* Profile name, in OSP cookie */ -#define OSP_VAR_TRANSID "osp_transaction_id" /* Transaction ID, in OSP cookie */ -#define OSP_VAR_START "osp_start_time" /* Inbound Call start time, in OSP cookie */ -#define OSP_VAR_SRCDEV "osp_source_device" /* Source device IP, in OSP cookie or inbound (actual source device)*/ -#define OSP_VAR_SRCNID "osp_source_nid" /* Source network ID, inbound and in OSP cookie */ -#define OSP_VAR_DESTCOUNT "osp_destination_count" /* Destination count, in OSP cookie */ -#define OSP_VAR_DESTIP "osp_destination_ip" /* Destination IP, in OSP cookie */ -#define OSP_VAR_DESTNID "osp_destination_nid" /* Destination network ID, in OSP cookie */ -#define OSP_VAR_CUSTOMINFO "osp_custom_info_" /* Custom info */ -#define OSP_VAR_OUTPROXY "osp_outbound_proxy" /* Outbound proxy */ -#define OSP_VAR_ROUTECOUNT "osp_route_count" /* Number of destinations */ -#define OSP_VAR_ROUTEPRE "osp_route_" /* Destination prefix */ -#define OSP_VAR_AUTOROUTE "osp_auto_route" /* Bridge route string */ +#define OSP_VAR_PROFILE "osp_profile" /* Profile name, in cookie */ +#define OSP_VAR_TRANSID "osp_transaction_id" /* Transaction ID, in cookie */ +#define OSP_VAR_CALLING "osp_calling" /* Original calling number, in cookie */ +#define OSP_VAR_CALLED "osp_called" /* Original called number, in cookie */ +#define OSP_VAR_START "osp_start_time" /* Inbound Call start time, in cookie */ +#define OSP_VAR_SRCDEV "osp_source_device" /* Source device IP, in cookie or inbound (actual source device)*/ +#define OSP_VAR_SRCNID "osp_source_nid" /* Source network ID, inbound and in cookie */ +#define OSP_VAR_DESTTOTAL "osp_destination_total" /* Total number of destinations in AuthRsp, in cookie */ +#define OSP_VAR_DESTCOUNT "osp_destination_count" /* Destination count, in cookie */ +#define OSP_VAR_DESTIP "osp_destination_ip" /* Destination IP, in cookie */ +#define OSP_VAR_DESTNID "osp_destination_nid" /* Destination network ID, in cookie */ +#define OSP_VAR_CUSTOMINFO "osp_custom_info_" /* Custom info */ +#define OSP_VAR_DNIDUSERPARAM "osp_networkid_userparam" /* Destination network ID user parameter name */ +#define OSP_VAR_DNIDURIPARAM "osp_networkid_uriparam" /* Destination network ID URI parameter name */ +#define OSP_VAR_USERPHONE "osp_user_phone" /* If to add "user=phone" */ +#define OSP_VAR_OUTPROXY "osp_outbound_proxy" /* Outbound proxy */ +#define OSP_VAR_AUTHSTATUS "osp_authreq_status" /* AuthReq Status */ +#define OSP_VAR_ROUTECOUNT "osp_route_count" /* Number of destinations */ +#define OSP_VAR_ROUTEPRE "osp_route_" /* Destination prefix */ +#define OSP_VAR_AUTOROUTE "osp_auto_route" /* Bridge route string */ /* OSP Use Variable Name */ -#define OSP_FS_TOHOST "sip_to_host" /* Inbound SIP To host */ -#define OSP_FS_TOPORT "sip_to_port" /* Inbound SIP To port */ -#define OSP_FS_DIVERSION "sip_h_Diversion" /* Inbound SIP Diversion header */ -#define OSP_FS_OUTCALLID "sip_call_id" /* Outbound SIP Call-ID */ -#define OSP_FS_OUTCALLING "origination_caller_id_number" /* Outbound calling number */ -#define OSP_FS_SIPRELEASE "sip_hangup_disposition" /* SIP release source */ -#define OSP_FS_DOWNCODEC "write_codec" /* Downstream codec */ -#define OSP_FS_UPCODEC "read_codec" /* Upstream codec */ -#define OSP_FS_RTPDOWNOCTS "rtp_audio_out_media_bytes" /* Downstream octets */ -#define OSP_FS_RTPUPOCTS "rtp_audio_in_media_bytes" /* Upstream octets */ -#define OSP_FS_RTPDOWNPKTS "rtp_audio_out_media_packet_count" /* Downstream packets */ -#define OSP_FS_RTPUPPKTS "rtp_audio_in_media_packet_count" /* Upstream packets */ +#define OSP_FS_FROMUSER "sip_from_user" /* Inbound SIP From user */ +#define OSP_FS_TOHOST "sip_to_host" /* Inbound SIP To host */ +#define OSP_FS_TOPORT "sip_to_port" /* Inbound SIP To port */ +#define OSP_FS_RPID "sip_Remote-Party-ID" /* Inbound SIP Remote-Party-ID header */ +#define OSP_FS_PAI "sip_P-Asserted-Identity" /* Inbound SIP P-Asserted-Identity header */ +#define OSP_FS_DIV "sip_h_Diversion" /* Inbound SIP Diversion header */ +#define OSP_FS_PCI "sip_h_P-Charge-Info" /* Inbound SIP P-Charge-Info header */ +#define OSP_FS_OUTCALLID "sip_call_id" /* Outbound SIP Call-ID */ +#define OSP_FS_OUTCALLING "origination_caller_id_number" /* Outbound calling number */ +#define OSP_FS_SIPRELEASE "sip_hangup_disposition" /* SIP release source */ +#define OSP_FS_SRCCODEC "write_codec" /* Source codec */ +#define OSP_FS_DESTCODEC "read_codec" /* Destiantion codec */ +#define OSP_FS_RTPSRCREPOCTS "rtp_audio_out_media_bytes" /* Source->reporter octets */ +#define OSP_FS_RTPDESTREPOCTS "rtp_audio_in_media_bytes" /* Destination->reporter octets */ +#define OSP_FS_RTPSRCREPPKTS "rtp_audio_out_media_packet_count" /* Source->reporter packets */ +#define OSP_FS_RTPDESTREPPKTS "rtp_audio_in_media_packet_count" /* Destination->reporter packets */ typedef struct osp_settings { switch_bool_t debug; /* OSP module debug info flag */ switch_log_level_t loglevel; /* Log level for debug info */ switch_bool_t hardware; /* Crypto hardware flag */ - const char *modules[OSPC_DPROT_NUMBER]; /* Endpoint names */ - const char *profiles[OSPC_DPROT_NUMBER]; /* Endpoint profile names */ - OSPE_DEST_PROTOCOL protocol; /* Default destination protocol */ + const char *modules[OSPC_PROTNAME_NUMBER]; /* Endpoint names */ + const char *profiles[OSPC_PROTNAME_NUMBER]; /* Endpoint profile names */ + OSPE_PROTOCOL_NAME protocol; /* Default signaling protocol */ switch_bool_t shutdown; /* OSP module status */ switch_memory_pool_t *pool; /* OSP module memory pool */ } osp_settings_t; @@ -161,7 +167,6 @@ typedef struct osp_profile { osp_workmode_t workmode; /* OSP work mode */ osp_srvtype_t srvtype; /* OSP service type */ int maxdest; /* Max destinations */ - switch_bool_t userphone; /* Add "user=phone" URI parameter */ OSPTPROVHANDLE provider; /* OSP provider handle */ struct osp_profile *next; /* Next OSP profile */ } osp_profile_t; @@ -169,19 +174,22 @@ typedef struct osp_profile { typedef struct osp_inbound { const char *actsrc; /* Actual source device IP address */ const char *srcdev; /* Source device IP address */ - const char *calling; /* Inbound calling number */ + OSPE_PROTOCOL_NAME protocol; /* Inbound signaling protocol */ + char calling[OSP_SIZE_NORSTR]; /* Inbound calling number */ char called[OSP_SIZE_NORSTR]; /* Inbound called number */ char nprn[OSP_SIZE_NORSTR]; /* Inbound NP routing number */ char npcic[OSP_SIZE_NORSTR]; /* Inbound NP carrier identification code */ int npdi; /* Inbound NP database dip indicator */ const char *tohost; /* Inbound host of To URI */ const char *toport; /* Inbound port of To URI */ + char rpiduser[OSP_SIZE_NORSTR]; /* Inbound user of SIP Remote-Party-ID header */ + char paiuser[OSP_SIZE_NORSTR]; /* Inbound user of SIP P-Asserted-Identity header */ char divuser[OSP_SIZE_NORSTR]; /* Inbound user of SIP Diversion header */ char divhost[OSP_SIZE_NORSTR]; /* Inbound hostport of SIP Diversion header */ + char pciuser[OSP_SIZE_NORSTR]; /* Inbound user of SIP P-Charge-Info header */ const char *srcnid; /* Inbound source network ID */ switch_time_t start; /* Call start time */ const char *cinfo[OSP_MAX_CINFO]; /* Custom info */ - const char *outproxy; /* Outbound proxy IP address */ } osp_inbound_t; typedef struct osp_destination { @@ -194,19 +202,19 @@ typedef struct osp_destination { char npcic[OSP_SIZE_NORSTR]; /* Outbound NP carrier identification code */ int npdi; /* Outbound NP database dip indicator */ char opname[OSPC_OPNAME_NUMBER][OSP_SIZE_NORSTR]; /* Outbound Operator names */ - OSPE_DEST_PROTOCOL protocol; /* Destination protocol */ + OSPE_PROTOCOL_NAME protocol; /* Signaling protocol */ switch_bool_t supported; /* Supported by FreeRADIUS OSP module */ - switch_bool_t userphone; /* Add "user=phone" parameter */ - const char *outproxy; /* Outbound proxy IP */ } osp_destination_t; typedef struct osp_results { const char *profile; /* Profile name */ uint64_t transid; /* Transaction ID */ switch_time_t start; /* Call start time */ + char calling[OSP_SIZE_NORSTR]; /* Original calling number */ char called[OSP_SIZE_NORSTR]; /* Original called number */ const char *srcdev; /* Source device IP */ const char *srcnid; /* Source network ID */ + int status; /* AuthReq status */ int numdest; /* Number of destinations */ osp_destination_t dests[OSP_MAX_SP]; /* Destinations */ } osp_results_t; @@ -214,33 +222,42 @@ typedef struct osp_results { typedef struct osp_cookie { const char *profile; /* Profile name */ uint64_t transid; /* Transaction ID */ + const char *calling; /* Original calling number */ + const char *called; /* Original called number */ switch_time_t start; /* Call start time */ const char *srcdev; /* Source Device IP */ + int desttotal; /* Total number of destinations in AuthRsp */ int destcount; /* Destination count */ const char *dest; /* Destination IP */ const char *srcnid; /* Source network ID */ const char *destnid; /* Destination network ID */ } osp_cookie_t; +typedef struct osp_outbound { + const char *dniduserparam; /* Destination network ID user parameter name */ + const char *dniduriparam; /* Destination network ID URI parameter name */ + switch_bool_t userphone; /* If to add "user=phone" parameter */ + const char *outproxy; /* Outbound proxy IP address */ +} osp_outbound_t; + typedef struct osp_usage { const char *srcdev; /* Source device IP */ const char *callid; /* Call-ID */ - const char *calling; /* Calling number */ - char called[OSP_SIZE_NORSTR]; /* Called number */ - OSPE_DEST_PROTOCOL protocol; /* Destination protocol */ + OSPE_PROTOCOL_NAME inprotocol; /* Inbound signaling protocol */ + OSPE_PROTOCOL_NAME outprotocol; /* Outbound signaling protocol */ int release; /* Release source */ switch_call_cause_t cause; /* Termination cause */ switch_time_t alert; /* Call alert time */ switch_time_t connect; /* Call answer time */ switch_time_t end; /* Call end time */ switch_time_t duration; /* Call duration */ - switch_time_t pdd; /* Post dial delay */ - const char *fcodec; /* Forward codec */ - const char *rcodec; /* Reverse codec */ - int rtpdownoctets; /* RTP downstream bytes */ - int rtpupoctets; /* RTP upstream bytes */ - int rtpdownpackets; /* RTP downstream packets */ - int rtpuppackets; /* RTP upstream packets */ + switch_time_t pdd; /* Post dial delay, in us */ + const char *srccodec; /* Source codec */ + const char *destcodec; /* Destination codec */ + int rtpsrcrepoctets; /* RTP source->reporter bytes */ + int rtpdestrepoctets; /* RTP destination->reporter bytes */ + int rtpsrcreppackets; /* RTP source->reporter packets */ + int rtpdestreppackets; /* RTP destiantion->reporter packets */ } osp_usage_t; typedef struct osp_threadarg { @@ -252,7 +269,7 @@ typedef struct osp_threadarg { time_t connect; /* Call connect time */ time_t end; /* Call end time */ int duration; /* Call duration */ - int pdd; /* Post dial delay */ + int pdd; /* Post dial delay, in ms */ int release; /* EP that released the call */ } osp_threadarg_t; @@ -332,7 +349,7 @@ static switch_status_t osp_load_settings( memset(&osp_globals, 0, sizeof(osp_globals)); osp_globals.loglevel = SWITCH_LOG_DEBUG; osp_globals.pool = pool; - osp_globals.protocol = OSPC_DPROT_SIP; + osp_globals.protocol = OSPC_PROTNAME_SIP; if ((settings = switch_xml_child(cfg, "settings"))) { for (param = switch_xml_child(settings, "param"); param; param = param->next) { @@ -375,26 +392,26 @@ static switch_status_t osp_load_settings( if (switch_strlen_zero(value)) { continue; } else if (!strcasecmp(value, OSP_PROTOCOL_SIP)) { - osp_globals.protocol = OSPC_DPROT_SIP; + osp_globals.protocol = OSPC_PROTNAME_SIP; } else if (!strcasecmp(value, OSP_PROTOCOL_H323)) { - osp_globals.protocol = OSPC_DPROT_Q931; + osp_globals.protocol = OSPC_PROTNAME_Q931; } else if (!strcasecmp(value, OSP_PROTOCOL_IAX)) { - osp_globals.protocol = OSPC_DPROT_IAX; + osp_globals.protocol = OSPC_PROTNAME_IAX; } else if (!strcasecmp(value, OSP_PROTOCOL_SKYPE)) { - osp_globals.protocol = OSPC_DPROT_SKYPE; + osp_globals.protocol = OSPC_PROTNAME_SKYPE; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported default protocol '%s'\n", value); } } else if (!strcasecmp(name, "sip")) { if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_DPROT_SIP] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_globals.modules[OSPC_PROTNAME_SIP] = switch_core_strdup(osp_globals.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate SIP module name\n"); status = SWITCH_STATUS_MEMERR; break; } } if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_DPROT_SIP] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_globals.profiles[OSPC_PROTNAME_SIP] = switch_core_strdup(osp_globals.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate SIP profile name\n"); status = SWITCH_STATUS_MEMERR; break; @@ -402,14 +419,14 @@ static switch_status_t osp_load_settings( } } else if (!strcasecmp(name, "h323")) { if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_DPROT_Q931] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_globals.modules[OSPC_PROTNAME_Q931] = switch_core_strdup(osp_globals.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate H.323 module name\n"); status = SWITCH_STATUS_MEMERR; break; } } if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_DPROT_Q931] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_globals.profiles[OSPC_PROTNAME_Q931] = switch_core_strdup(osp_globals.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate H.323 profile name\n"); status = SWITCH_STATUS_MEMERR; break; @@ -417,14 +434,14 @@ static switch_status_t osp_load_settings( } } else if (!strcasecmp(name, "iax")) { if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_DPROT_IAX] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_globals.modules[OSPC_PROTNAME_IAX] = switch_core_strdup(osp_globals.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate IAX module name\n"); status = SWITCH_STATUS_MEMERR; break; } } if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_DPROT_IAX] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_globals.profiles[OSPC_PROTNAME_IAX] = switch_core_strdup(osp_globals.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate IAX profile name\n"); status = SWITCH_STATUS_MEMERR; break; @@ -432,14 +449,14 @@ static switch_status_t osp_load_settings( } } else if (!strcasecmp(name, "skype")) { if (!switch_strlen_zero(module)) { - if (!(osp_globals.modules[OSPC_DPROT_SKYPE] = switch_core_strdup(osp_globals.pool, module))) { + if (!(osp_globals.modules[OSPC_PROTNAME_SKYPE] = switch_core_strdup(osp_globals.pool, module))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate Skype module name\n"); status = SWITCH_STATUS_MEMERR; break; } } if (!switch_strlen_zero(context)) { - if (!(osp_globals.profiles[OSPC_DPROT_SKYPE] = switch_core_strdup(osp_globals.pool, context))) { + if (!(osp_globals.profiles[OSPC_PROTNAME_SKYPE] = switch_core_strdup(osp_globals.pool, context))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to duplicate Skype profile name\n"); status = SWITCH_STATUS_MEMERR; break; @@ -566,8 +583,6 @@ static switch_status_t osp_load_settings( switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "max-destinations must be between %d and %d\n", OSP_MIN_MAXDEST, OSP_MAX_MAXDEST); } - } else if (!strcasecmp(name, "user-phone")) { - profile->userphone = switch_true(value); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown parameter '%s'\n", name); } @@ -673,35 +688,35 @@ static void osp_init_osptk(void) * return protocol name */ static const char *osp_get_protocol( - OSPE_DEST_PROTOCOL protocol) + OSPE_PROTOCOL_NAME protocol) { const char *name; switch (protocol) { - case OSPC_DPROT_UNKNOWN: + case OSPC_PROTNAME_UNKNOWN: name = OSP_PROTOCOL_UNKNO; break; - case OSPC_DPROT_UNDEFINED: + case OSPC_PROTNAME_UNDEFINED: name = OSP_PROTOCOL_UNDEF; break; - case OSPC_DPROT_SIP: + case OSPC_PROTNAME_SIP: name = OSP_PROTOCOL_SIP; break; - case OSPC_DPROT_Q931: + case OSPC_PROTNAME_Q931: name = OSP_PROTOCOL_H323; break; - case OSPC_DPROT_IAX: + case OSPC_PROTNAME_IAX: name = OSP_PROTOCOL_IAX; break; - case OSPC_DPROT_SKYPE: + case OSPC_PROTNAME_SKYPE: name = OSP_PROTOCOL_SKYPE; break; - case OSPC_DPROT_LRQ: - case OSPC_DPROT_T37: - case OSPC_DPROT_T38: - case OSPC_DPROT_SMPP: - case OSPC_DPROT_XMPP: - case OSPC_DPROT_SMS: + case OSPC_PROTNAME_LRQ: + case OSPC_PROTNAME_T37: + case OSPC_PROTNAME_T38: + case OSPC_PROTNAME_SMPP: + case OSPC_PROTNAME_XMPP: + case OSPC_PROTNAME_SMS: default: name = OSP_PROTOCOL_UNSUP; break; @@ -772,29 +787,29 @@ SWITCH_STANDARD_API(osp_api_function) } stream->write_function(stream, " log-level: %s\n", loglevel); stream->write_function(stream, " crypto-hardware: %s\n", osp_globals.hardware ? "enabled" : "disabled"); - if (switch_strlen_zero(osp_globals.modules[OSPC_DPROT_SIP]) || switch_strlen_zero(osp_globals.profiles[OSPC_DPROT_SIP])) { + if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_SIP]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_SIP])) { stream->write_function(stream, " sip: unsupported\n"); } else { stream->write_function(stream, " sip: %s/%s\n", - osp_globals.modules[OSPC_DPROT_SIP], osp_globals.profiles[OSPC_DPROT_SIP]); + osp_globals.modules[OSPC_PROTNAME_SIP], osp_globals.profiles[OSPC_PROTNAME_SIP]); } - if (switch_strlen_zero(osp_globals.modules[OSPC_DPROT_Q931]) || switch_strlen_zero(osp_globals.profiles[OSPC_DPROT_Q931])) { + if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_Q931]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_Q931])) { stream->write_function(stream, " h323: unsupported\n"); } else { stream->write_function(stream, " h323: %s/%s\n", - osp_globals.modules[OSPC_DPROT_Q931], osp_globals.profiles[OSPC_DPROT_Q931]); + osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931]); } - if (switch_strlen_zero(osp_globals.modules[OSPC_DPROT_IAX]) || switch_strlen_zero(osp_globals.profiles[OSPC_DPROT_IAX])) { + if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_IAX]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_IAX])) { stream->write_function(stream, " iax: unsupported\n"); } else { stream->write_function(stream, " iax: %s/%s\n", - osp_globals.modules[OSPC_DPROT_IAX], osp_globals.profiles[OSPC_DPROT_IAX]); + osp_globals.modules[OSPC_PROTNAME_IAX], osp_globals.profiles[OSPC_PROTNAME_IAX]); } - if (switch_strlen_zero(osp_globals.modules[OSPC_DPROT_SKYPE]) || switch_strlen_zero(osp_globals.profiles[OSPC_DPROT_SKYPE])) { + if (switch_strlen_zero(osp_globals.modules[OSPC_PROTNAME_SKYPE]) || switch_strlen_zero(osp_globals.profiles[OSPC_PROTNAME_SKYPE])) { stream->write_function(stream, " skype: unsupported\n"); } else { stream->write_function(stream, " skype: %s/%s\n", - osp_globals.modules[OSPC_DPROT_SKYPE], osp_globals.profiles[OSPC_DPROT_SKYPE]); + osp_globals.modules[OSPC_PROTNAME_SKYPE], osp_globals.profiles[OSPC_PROTNAME_SKYPE]); } stream->write_function(stream, " default-protocol: %s\n", osp_get_protocol(osp_globals.protocol)); stream->write_function(stream, "============== OSP Profile Settings & Status ==============\n"); @@ -829,7 +844,6 @@ SWITCH_STANDARD_API(osp_api_function) break; } stream->write_function(stream, " max-destinations: %d\n", profile->maxdest); - stream->write_function(stream, " user-phone: %s\n", profile->userphone ? "enabled" : "disabled"); stream->write_function(stream, " status: %s\n", profile->provider != OSP_INVALID_HANDLE ? "enabled" : "disabled"); } } else { @@ -845,86 +859,110 @@ SWITCH_STANDARD_API(osp_api_function) } /* - * Parse URI userinfo - * param user URI userinfo - * param user URI user + * Parse Userinfo for user and LNP + * param userinfo SIP URI userinfo + * param user User part * param usersize Size of user buffer - * param inbound Inbound info + * param rn Routing number + * param rnsize Size of rn buffer + * param cic Carrier Identification Cod + * param cicsize Size of cic buffer + * param npdi NP Database Dip Indicator * return */ static void osp_parse_userinfo( const char *userinfo, char *user, switch_size_t usersize, - osp_inbound_t *inbound) + char *rn, + switch_size_t rnsize, + char *cic, + switch_size_t cicsize, + int *npdi) { char buffer[OSP_SIZE_NORSTR]; char *item; char *tmp; - if (switch_strlen_zero(userinfo)) { + if (!switch_strlen_zero(userinfo)) { + switch_copy_string(buffer, userinfo, sizeof(buffer)); + item = strtok_r(buffer, OSP_USER_DELIM, &tmp); if (user && usersize) { - user[0] = '\0'; + switch_copy_string(user, item, usersize); } - /* It is not necessary to clean inbound */ - return; - } - - switch_copy_string(buffer, userinfo, sizeof(buffer)); - - item = strtok_r(buffer, OSP_USER_DELIM, &tmp); - - if (user && usersize) { - switch_copy_string(user, item, usersize); - } - - if (inbound) { - switch_copy_string(inbound->called, item, sizeof(inbound->called)); - for (item = strtok_r(NULL, OSP_USER_DELIM, &tmp); item; item = strtok_r(NULL, OSP_USER_DELIM, &tmp)) { if (!strncasecmp(item, "rn=", 3)) { - switch_copy_string(inbound->nprn, item + 3, sizeof(inbound->nprn)); + if (rn && rnsize) { + switch_copy_string(rn, item + 3, rnsize); + } } else if (!strncasecmp(item, "cic=", 4)) { - switch_copy_string(inbound->npcic, item + 4, sizeof(inbound->npcic)); + if (cic && cicsize) { + switch_copy_string(cic, item + 4, cicsize); + } } else if (!strcasecmp(item, "npdi")) { - inbound->npdi = 1; + *npdi = 1; } } } } /* - * Parse SIP Diversion - * param diversion SIP Diversion header - * param inbound Inbound info + * Parse SIP header user + * param header SIP header + * param user SIP header user + * param usersize Size of user buffer * return */ -static void osp_parse_diversion( - const char *diversion, - osp_inbound_t *inbound) +static void osp_parse_header_user( + const char *header, + char *user, + switch_size_t usersize) +{ + char buffer[OSP_SIZE_NORSTR]; + char *head; + char *tmp; + char *item; + + if (!switch_strlen_zero(header) && user && usersize) { + *user = '\0'; + switch_copy_string(buffer, header, sizeof(buffer)); + if ((head = strstr(buffer, "sip:"))) { + head += 4; + if ((tmp = strchr(head, OSP_URI_DELIM))) { + *tmp = '\0'; + item = strtok_r(head, OSP_USER_DELIM, &tmp); + switch_copy_string(user, item, usersize); + } + } + } +} + +/* + * Parse SIP header host + * param header SIP header + * param host SIP header host + * param hostsize Size of host buffer + * return + */ +static void osp_parse_header_host( + const char *header, + char *host, + switch_size_t hostsize) { char buffer[OSP_SIZE_NORSTR]; - char userinfo[OSP_SIZE_NORSTR]; char *head; char *tmp; - if (switch_strlen_zero(diversion)) { - /* It is not necessary to clean inbound */ - return; - } - - switch_copy_string(buffer, diversion, sizeof(buffer)); - - if ((head = strstr(buffer, "sip:"))) { - head += 4; - if ((tmp = strchr(head, OSP_URI_DELIM))) { - *tmp = '\0'; - switch_copy_string(userinfo, head, sizeof(userinfo)); - osp_parse_userinfo(userinfo, inbound->divuser, sizeof(inbound->divuser), NULL); - - head = tmp + 1; + if (!switch_strlen_zero(header) && host && hostsize) { + *host = '\0'; + switch_copy_string(buffer, header, sizeof(buffer)); + if ((head = strstr(buffer, "sip:"))) { + head += 4; + if ((tmp = strchr(head, OSP_URI_DELIM))) { + head = tmp + 1; + } tmp = strtok(head, OSP_HOST_DELIM); - switch_copy_string(inbound->divhost, tmp, sizeof(inbound->divhost)); + switch_copy_string(host, tmp, hostsize); } } } @@ -978,25 +1016,33 @@ static void osp_log_authreq( switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, "AuthReq: " - "srvtype = '%s' " - "source = '%s' " - "srcdev = '%s' " - "calling = '%s' " - "called = '%s' " - "lnp = '%s/%s/%d' " - "prefer = '%s' " - "div = '%s/%s' " - "srcnid = '%s' " - "cinfo = '%s/%s/%s/%s/%s/%s/%s/%s' " - "maxcount = '%d'\n", + "srvtype '%s' " + "source '%s' " + "srcdev '%s' " + "protocol '%s' " + "calling '%s' " + "called '%s' " + "lnp '%s/%s/%d' " + "prefer '%s' " + "rpid '%s' " + "pai '%s' " + "div '%s/%s' " + "pci '%s' " + "srcnid '%s' " + "cinfo '%s/%s/%s/%s/%s/%s/%s/%s' " + "maxcount '%d'\n", srvtype, source, srcdev, + osp_get_protocol(inbound->protocol), inbound->calling, inbound->called, inbound->nprn, inbound->npcic, inbound->npdi, term, + inbound->rpiduser, + inbound->paiuser, inbound->divuser, inbound->divhost, + inbound->pciuser, osp_filter_null(inbound->srcnid), osp_filter_null(inbound->cinfo[0]), osp_filter_null(inbound->cinfo[1]), osp_filter_null(inbound->cinfo[2]), osp_filter_null(inbound->cinfo[3]), @@ -1006,6 +1052,31 @@ static void osp_log_authreq( } } +/* + * Get protocol from module name + * param module Module name + * return protocol name + */ +static OSPE_PROTOCOL_NAME osp_get_moduleprotocol( + const char *module) +{ + OSPE_PROTOCOL_NAME protocol; + + if (!strcasecmp(module, OSP_MODULE_SIP)) { + protocol = OSPC_PROTNAME_SIP; + } else if (!strcasecmp(module, OSP_MODULE_H323)) { + protocol = OSPC_PROTNAME_Q931; + } else if (!strcasecmp(module, OSP_MODULE_IAX)) { + protocol = OSPC_PROTNAME_IAX; + } else if (!strcasecmp(module, OSP_MODULE_SKYPE)) { + protocol = OSPC_PROTNAME_SKYPE; + } else { + protocol = OSPC_PROTNAME_UNKNOWN; + } + + return protocol; +} + /* * Get inbound info * param channel Inbound channel @@ -1025,16 +1096,33 @@ static void osp_get_inbound( memset(inbound, 0, sizeof(*inbound)); caller = switch_channel_get_caller_profile(channel); + inbound->actsrc = switch_channel_get_variable(channel, OSP_VAR_SRCDEV); inbound->srcdev = caller->network_addr; - inbound->calling = caller->caller_id_number; - osp_parse_userinfo(caller->destination_number, NULL, 0, inbound); + inbound->protocol = osp_get_moduleprotocol(caller->source); + if ((tmp = switch_channel_get_variable(channel, OSP_FS_FROMUSER))) { + osp_parse_userinfo(tmp, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); + } else { + osp_parse_userinfo(caller->caller_id_number, inbound->calling, sizeof(inbound->calling), NULL, 0, NULL, 0, NULL); + } + osp_parse_userinfo(caller->destination_number, inbound->called, sizeof(inbound->called), inbound->nprn, sizeof(inbound->nprn), + inbound->npcic, sizeof(inbound->npcic), &inbound->npdi); inbound->tohost = switch_channel_get_variable(channel, OSP_FS_TOHOST); inbound->toport = switch_channel_get_variable(channel, OSP_FS_TOPORT); - if ((tmp = switch_channel_get_variable(channel, OSP_FS_DIVERSION))) { - osp_parse_diversion(tmp, inbound); + if ((tmp = switch_channel_get_variable(channel, OSP_FS_RPID))) { + osp_parse_header_user(tmp, inbound->rpiduser, sizeof(inbound->rpiduser)); + } + if ((tmp = switch_channel_get_variable(channel, OSP_FS_PAI))) { + osp_parse_userinfo(tmp, inbound->paiuser, sizeof(inbound->paiuser), NULL, 0, NULL, 0, NULL); + } + if ((tmp = switch_channel_get_variable(channel, OSP_FS_DIV))) { + osp_parse_header_user(tmp, inbound->divuser, sizeof(inbound->divuser)); + osp_parse_header_host(tmp, inbound->divhost, sizeof(inbound->divhost)); + } + if ((tmp = switch_channel_get_variable(channel, OSP_FS_PCI))) { + osp_parse_header_user(tmp, inbound->pciuser, sizeof(inbound->pciuser)); } inbound->srcnid = switch_channel_get_variable(channel, OSP_VAR_SRCNID); @@ -1046,8 +1134,34 @@ static void osp_get_inbound( switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_CUSTOMINFO, i + 1); inbound->cinfo[i] = switch_channel_get_variable(channel, name); } +} - inbound->outproxy = switch_channel_get_variable(channel, OSP_VAR_OUTPROXY); +/* + * Get outbound settings + * param channel Inbound channel + * param outbound Outbound settings + * return + */ +static void osp_get_outbound( + switch_channel_t *channel, + osp_outbound_t *outbound) +{ + const char *value; + + memset(outbound, 0, sizeof(*outbound)); + + /* Get destination network ID namd & location info */ + outbound->dniduserparam = switch_channel_get_variable(channel, OSP_VAR_DNIDUSERPARAM); + outbound->dniduriparam = switch_channel_get_variable(channel, OSP_VAR_DNIDURIPARAM); + + /* Get "user=phone" insert flag */ + value = switch_channel_get_variable(channel, OSP_VAR_USERPHONE); + if (!switch_strlen_zero(value)) { + outbound->userphone = switch_true(value); + } + + /* Get outbound proxy info */ + outbound->outproxy = switch_channel_get_variable(channel, OSP_VAR_OUTPROXY); } /* @@ -1147,7 +1261,7 @@ static switch_status_t osp_check_destination( osp_destination_t *dest) { OSPE_DEST_OSPENABLED enabled; - OSPE_DEST_PROTOCOL protocol; + OSPE_PROTOCOL_NAME protocol; OSPE_OPERATOR_NAME type; int error; switch_status_t status = SWITCH_STATUS_FALSE; @@ -1165,29 +1279,29 @@ static switch_status_t osp_check_destination( } if ((error = OSPPTransactionGetDestProtocol(transaction, &protocol)) != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination protocol, error '%d'\n", error); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get signaling protocol, error '%d'\n", error); return status; } switch(protocol) { - case OSPC_DPROT_UNDEFINED: - case OSPC_DPROT_UNKNOWN: + case OSPC_PROTNAME_UNDEFINED: + case OSPC_PROTNAME_UNKNOWN: protocol = osp_globals.protocol; - case OSPC_DPROT_SIP: - case OSPC_DPROT_Q931: - case OSPC_DPROT_IAX: - case OSPC_DPROT_SKYPE: + case OSPC_PROTNAME_SIP: + case OSPC_PROTNAME_Q931: + case OSPC_PROTNAME_IAX: + case OSPC_PROTNAME_SKYPE: dest->protocol = protocol; if (!switch_strlen_zero(osp_globals.modules[protocol]) && !switch_strlen_zero(osp_globals.profiles[protocol])) { dest->supported = SWITCH_TRUE; status = SWITCH_STATUS_SUCCESS; } break; - case OSPC_DPROT_LRQ: - case OSPC_DPROT_T37: - case OSPC_DPROT_T38: - case OSPC_DPROT_SMPP: - case OSPC_DPROT_XMPP: + case OSPC_PROTNAME_LRQ: + case OSPC_PROTNAME_T37: + case OSPC_PROTNAME_T38: + case OSPC_PROTNAME_SMPP: + case OSPC_PROTNAME_XMPP: default: dest->protocol = protocol; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported protocol '%d'\n", protocol); @@ -1234,16 +1348,16 @@ static void osp_log_authrsp( for (i = 0; i < results->numdest; i++) { switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, "AuthRsp: " - "transid = '%"PRIu64"' " - "destcount = '%d' " - "timelimit = '%u' " - "destination = '%s' " - "calling = '%s' " - "called = '%s' " - "destnid = '%s' " - "lnp = '%s/%s/%d' " - "protocol = '%s' " - "supported = '%d'\n", + "transid '%"PRIu64"' " + "destcount '%d' " + "timelimit '%u' " + "destination '%s' " + "calling '%s' " + "called '%s' " + "destnid '%s' " + "lnp '%s/%s/%d' " + "protocol '%s' " + "supported '%d'\n", results->transid, i + 1, results->dests[i].timelimit, @@ -1262,7 +1376,7 @@ static void osp_log_authrsp( * Do auth/routing request * param profile OSP profile * param transaction Transaction handle - * param source Call originator info + * param inbound Call originator info * param results Routing info * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed */ @@ -1287,10 +1401,15 @@ static switch_status_t osp_do_request( osp_log_authreq(profile, inbound); + OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_SOURCE, inbound->protocol); + OSPPTransactionSetNumberPortability(transaction, inbound->nprn, inbound->npcic, inbound->npdi); + OSPPTransactionSetRemotePartyId(transaction, OSPC_NFORMAT_E164, inbound->rpiduser); + OSPPTransactionSetAssertedId(transaction, OSPC_NFORMAT_E164, inbound->paiuser); osp_convert_inout(inbound->divhost, tmp, sizeof(tmp)); OSPPTransactionSetDiversion(transaction, inbound->divuser, tmp); + OSPPTransactionSetChargeInfo(transaction, OSPC_NFORMAT_E164, inbound->pciuser); OSPPTransactionSetNetworkIds(transaction, inbound->srcnid, NULL); @@ -1352,11 +1471,15 @@ static switch_status_t osp_do_request( NULL, /* Log buffer size */ NULL); /* Log buffer */ if (error != OSPC_ERR_NO_ERROR) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to request routing, error '%d'\n", error); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to request routing for '%s/%s', error '%d'\n", + inbound->calling, inbound->called, error); + results->status = error; results->numdest = 0; return status; } else if (!total) { + results->status = error; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Without destination\n"); + results->status = error; results->numdest = 0; return status; } @@ -1368,6 +1491,7 @@ static switch_status_t osp_do_request( results->transid = 0; } + switch_copy_string(results->calling, inbound->calling, sizeof(results->calling)); switch_copy_string(results->called, inbound->called, sizeof(results->called)); results->srcdev = srcdev; results->srcnid = inbound->srcnid; @@ -1395,13 +1519,13 @@ static switch_status_t osp_do_request( NULL); /* Token buffer */ if (error != OSPC_ERR_NO_ERROR) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get first destination, error '%d'\n", error); + results->status = error; + results->numdest = 0; return status; } osp_convert_outin(term, dest->dest, sizeof(dest->dest)); osp_check_destination(transaction, dest); - dest->userphone = profile->userphone; - dest->outproxy = inbound->outproxy; for (count = 1; count < total; count++) { dest = &results->dests[count]; @@ -1427,17 +1551,19 @@ static switch_status_t osp_do_request( if (error == OSPC_ERR_NO_ERROR) { osp_convert_outin(term, dest->dest, sizeof(dest->dest)); osp_check_destination(transaction, dest); - dest->userphone = profile->userphone; - dest->outproxy = inbound->outproxy; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get destination, error '%d'\n", error); break; } } if (count == total) { + results->status = OSPC_ERR_NO_ERROR; results->numdest = total; osp_log_authrsp(results); status = SWITCH_STATUS_SUCCESS; + } else { + results->status = error; + results->numdest = 0; } return status; @@ -1504,11 +1630,14 @@ static void osp_build_allparam( if (results && head && size) { switch_snprintf(head, size, - "{%s=%s,%s=%"PRIu64",%s=%"PRId64",%s=%s", + "{%s=%s,%s=%"PRIu64",%s=%s,%s=%s,%s=%"PRId64",%s=%s,%s=%d", OSP_VAR_PROFILE, results->profile, OSP_VAR_TRANSID, results->transid, + OSP_VAR_CALLING, results->calling, + OSP_VAR_CALLED, results->called, OSP_VAR_START, results->start, - OSP_VAR_SRCDEV, results->srcdev); + OSP_VAR_SRCDEV, results->srcdev, + OSP_VAR_DESTTOTAL, results->numdest); osp_adjust_len(head, size, len); if (!switch_strlen_zero(results->srcnid)) { @@ -1559,12 +1688,14 @@ static void osp_build_eachparam( /* * Build endpoint string * param dest Destination + * param outbound Outbound settings * param buffer Buffer * param bufsize Buffer size * return */ static void osp_build_endpoint( osp_destination_t *dest, + osp_outbound_t *outbound, char *buffer, switch_size_t bufsize) { @@ -1573,8 +1704,9 @@ static void osp_build_endpoint( if (head && size) { switch (dest->protocol) { - case OSPC_DPROT_SIP: - switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_DPROT_SIP], osp_globals.profiles[OSPC_DPROT_SIP], dest->called); + case OSPC_PROTNAME_SIP: + switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_SIP], osp_globals.profiles[OSPC_PROTNAME_SIP], + dest->called); osp_adjust_len(head, size, len); if (!switch_strlen_zero_buf(dest->nprn)) { @@ -1590,29 +1722,42 @@ static void osp_build_endpoint( osp_adjust_len(head, size, len); } + if (!switch_strlen_zero(outbound->dniduserparam) && !switch_strlen_zero_buf(dest->destnid)) { + switch_snprintf(head, size, ";%s=%s", outbound->dniduserparam, dest->destnid); + osp_adjust_len(head, size, len); + } + switch_snprintf(head, size, "@%s", dest->dest); osp_adjust_len(head, size, len); - if (dest->userphone) { + if (!switch_strlen_zero(outbound->dniduriparam) && !switch_strlen_zero_buf(dest->destnid)) { + switch_snprintf(head, size, ";%s=%s", outbound->dniduriparam, dest->destnid); + osp_adjust_len(head, size, len); + } + + if (outbound->userphone) { switch_snprintf(head, size, ";user=phone"); osp_adjust_len(head, size, len); } - if (dest->outproxy) { - switch_snprintf(head, size, ";fs_path=sip:%s", dest->outproxy); + if (!switch_strlen_zero(outbound->outproxy)) { + switch_snprintf(head, size, ";fs_path=sip:%s", outbound->outproxy); osp_adjust_len(head, size, len); } break; - case OSPC_DPROT_Q931: - switch_snprintf(head, size, "%s/%s/%s@%s", osp_globals.modules[OSPC_DPROT_Q931], osp_globals.profiles[OSPC_DPROT_Q931], dest->called, dest->dest); + case OSPC_PROTNAME_Q931: + switch_snprintf(head, size, "%s/%s/%s@%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], + dest->called, dest->dest); osp_adjust_len(head, size, len); break; - case OSPC_DPROT_IAX: - switch_snprintf(head, size, "%s/%s/%s/%s", osp_globals.modules[OSPC_DPROT_Q931], osp_globals.profiles[OSPC_DPROT_Q931], dest->dest, dest->called); + case OSPC_PROTNAME_IAX: + switch_snprintf(head, size, "%s/%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], + dest->dest, dest->called); osp_adjust_len(head, size, len); break; - case OSPC_DPROT_SKYPE: - switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_DPROT_Q931], osp_globals.profiles[OSPC_DPROT_Q931], dest->called); + case OSPC_PROTNAME_SKYPE: + switch_snprintf(head, size, "%s/%s/%s", osp_globals.modules[OSPC_PROTNAME_Q931], osp_globals.profiles[OSPC_PROTNAME_Q931], + dest->called); osp_adjust_len(head, size, len); break; default: @@ -1625,8 +1770,7 @@ static void osp_build_endpoint( /* * Create route string * param channel Originator channel - * param numdest Numer of destinations - * param destlist Destinations + * param results Routing info * return */ static void osp_create_route( @@ -1639,6 +1783,7 @@ static void osp_create_route( char allparam[OSP_SIZE_NORSTR]; char eachparam[OSP_SIZE_NORSTR]; char endpoint[OSP_SIZE_NORSTR]; + osp_outbound_t outbound; char tmp[OSP_SIZE_ROUSTR]; char buffer[OSP_SIZE_ROUSTR]; int i, len, count, size = sizeof(buffer); @@ -1646,6 +1791,8 @@ static void osp_create_route( switch_event_header_t *hi; char *var; + osp_get_outbound(channel, &outbound); + /* Cleanup OSP varibales in originator */ if ((hi = switch_channel_variable_first(channel))) { for (; hi; hi = hi->next) { @@ -1657,6 +1804,9 @@ static void osp_create_route( switch_channel_variable_last(channel); } + switch_snprintf(value, sizeof(value), "%d", results->status); + switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); + osp_build_allparam(results, head, size); switch_copy_string(allparam, head, sizeof(allparam)); osp_adjust_len(head, size, len); @@ -1666,7 +1816,7 @@ static void osp_create_route( if (dest->supported) { count++; osp_build_eachparam(i + 1, dest, eachparam, sizeof(eachparam)); - osp_build_endpoint(dest, endpoint, sizeof(endpoint)); + osp_build_endpoint(dest, &outbound, endpoint, sizeof(endpoint)); switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_ROUTEPRE, count); switch_snprintf(value, sizeof(value), "%s%s%s", allparam, eachparam, endpoint); @@ -1689,6 +1839,38 @@ static void osp_create_route( switch_channel_set_variable_var_check(channel, OSP_VAR_AUTOROUTE, buffer, SWITCH_FALSE); } +/* + * Export AuthReq status to channel + * param channel Originator channel + * param results Routing info + * return + */ +static void osp_export_failure( + switch_channel_t *channel, + osp_results_t *results) +{ + char value[OSP_SIZE_NORSTR]; + switch_event_header_t *hi; + char *var; + + /* Cleanup OSP varibales in originator */ + if ((hi = switch_channel_variable_first(channel))) { + for (; hi; hi = hi->next) { + var = hi->name; + if (var && !strncmp(var, "osp_", 4)) { + switch_channel_set_variable(channel, var, NULL); + } + } + switch_channel_variable_last(channel); + } + + switch_snprintf(value, sizeof(value), "%d", results->status); + switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); + + switch_snprintf(value, sizeof(value), "%d", results->numdest); + switch_channel_set_variable_var_check(channel, OSP_VAR_ROUTECOUNT, value, SWITCH_FALSE); +} + /* * Macro expands to: * static void osp_app_function(switch_core_session_t *session, const char *data) @@ -1728,6 +1910,8 @@ SWITCH_STANDARD_APP(osp_app_function) retval = osp_request_routing(channel, profile, &results); if (retval == SWITCH_STATUS_SUCCESS) { osp_create_route(channel, &results); + } else { + osp_export_failure(channel, &results); } } @@ -1749,6 +1933,7 @@ static void osp_add_application( char allparam[OSP_SIZE_NORSTR]; char eachparam[OSP_SIZE_NORSTR]; char endpoint[OSP_SIZE_NORSTR]; + osp_outbound_t outbound; char name[OSP_SIZE_NORSTR]; char value[OSP_SIZE_ROUSTR]; int i, count; @@ -1760,6 +1945,8 @@ static void osp_add_application( return; } + osp_get_outbound(channel, &outbound); + switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, "true"); /* Cleanup OSP varibales in originator */ @@ -1773,6 +1960,9 @@ static void osp_add_application( switch_channel_variable_last(channel); } + switch_snprintf(value, sizeof(value), "%d", results->status); + switch_channel_set_variable_var_check(channel, OSP_VAR_AUTHSTATUS, value, SWITCH_FALSE); + osp_build_allparam(results, allparam, sizeof(allparam)); for (count = 0, i = 0; i < results->numdest; i++) { @@ -1780,7 +1970,7 @@ static void osp_add_application( if (dest->supported) { count++; osp_build_eachparam(i + 1, dest, eachparam, sizeof(eachparam)); - osp_build_endpoint(dest, endpoint, sizeof(endpoint)); + osp_build_endpoint(dest, &outbound, endpoint, sizeof(endpoint)); switch_snprintf(name, sizeof(name), "%s%d", OSP_VAR_ROUTEPRE, count); switch_snprintf(value, sizeof(value), "%s%s%s", allparam, eachparam, endpoint); @@ -1822,18 +2012,20 @@ SWITCH_STANDARD_DIALPLAN(osp_dialplan_function) retval = osp_request_routing(channel, profile, &results); if (retval == SWITCH_STATUS_SUCCESS) { osp_add_application(session, channel, &extension, &results); + } else { + osp_export_failure(channel, &results); } return extension; } /* - * Retrieve OSP cookie + * Retrieve cookie * param channel Destination channel - * param cookie OSP cookie + * param cookie Cookie * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed */ -static switch_status_t osp_get_ospcookie( +static switch_status_t osp_get_cookie( switch_channel_t *channel, osp_cookie_t *cookie) { @@ -1847,12 +2039,19 @@ static switch_status_t osp_get_ospcookie( cookie->transid = 0; } + cookie->calling = switch_channel_get_variable(channel, OSP_VAR_CALLING); + cookie->called = switch_channel_get_variable(channel, OSP_VAR_CALLED); + if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_START)) || (sscanf(strvar, "%"PRId64"", &cookie->start) != 1)) { cookie->start = 0; } cookie->srcdev = switch_channel_get_variable(channel, OSP_VAR_SRCDEV); + if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_DESTTOTAL)) || (sscanf(strvar, "%d", &cookie->desttotal) != 1)) { + cookie->desttotal = 0; + } + if (!(strvar = switch_channel_get_variable(channel, OSP_VAR_DESTCOUNT)) || (sscanf(strvar, "%d", &cookie->destcount) != 1)) { cookie->destcount = 0; } @@ -1870,7 +2069,7 @@ static switch_status_t osp_get_ospcookie( * Retrieve usage info * param channel Destination channel * param originator Originator channel - * param cookie OSP cookie + * param cookie Cookie * param usage Usage info * return */ @@ -1894,29 +2093,18 @@ static void osp_get_usage( /* Originator had been checked by osp_on_reporting */ if (originator) { usage->srcdev = originator->network_addr; - usage->calling = originator->caller_id_number; - osp_parse_userinfo(originator->destination_number, usage->called, sizeof(usage->called), NULL); + usage->inprotocol = osp_get_moduleprotocol(originator->source); } terminator = switch_channel_get_caller_profile(channel); - if (!strcasecmp(terminator->source, OSP_MODULE_SIP)) { - usage->protocol = OSPC_DPROT_SIP; + usage->outprotocol = osp_get_moduleprotocol(terminator->source); + if (usage->outprotocol == OSPC_PROTNAME_SIP) { strvar = switch_channel_get_variable(channel, OSP_FS_SIPRELEASE); if (!strvar || !strcasecmp(strvar, "recv_bye")) { usage->release = 1; } - } else if (!strcasecmp(terminator->source, OSP_MODULE_H323)) { - usage->protocol = OSPC_DPROT_Q931; - } else if (!strcasecmp(terminator->source, OSP_MODULE_IAX)) { - usage->protocol = OSPC_DPROT_IAX; - } else if (!strcasecmp(terminator->source, OSP_MODULE_SKYPE)) { - usage->protocol = OSPC_DPROT_SKYPE; - } else { - usage->protocol = OSPC_DPROT_UNKNOWN; } - usage->cause = switch_channel_get_cause_q850(channel); - times = switch_channel_get_timetable(channel); usage->alert = times->progress; usage->connect = times->answered; @@ -1926,19 +2114,27 @@ static void osp_get_usage( usage->pdd = times->answered - cookie->start; } - usage->fcodec = switch_channel_get_variable(channel, OSP_FS_DOWNCODEC); - usage->rcodec = switch_channel_get_variable(channel, OSP_FS_UPCODEC); - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDOWNOCTS)) || (sscanf(strvar, "%d", &usage->rtpdownoctets) != 1)) { - usage->rtpdownoctets = OSP_DEF_STATS; + usage->srccodec = switch_channel_get_variable(channel, OSP_FS_SRCCODEC); + usage->destcodec = switch_channel_get_variable(channel, OSP_FS_DESTCODEC); + if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPOCTS)) || + (sscanf(strvar, "%d", &usage->rtpsrcrepoctets) != 1)) + { + usage->rtpsrcrepoctets = OSP_DEF_STATS; } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPUPOCTS)) || (sscanf(strvar, "%d", &usage->rtpupoctets) != 1)) { - usage->rtpupoctets = OSP_DEF_STATS; + if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPOCTS)) || + (sscanf(strvar, "%d", &usage->rtpdestrepoctets) != 1)) + { + usage->rtpdestrepoctets = OSP_DEF_STATS; } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDOWNPKTS)) || (sscanf(strvar, "%d", &usage->rtpdownpackets) != 1)) { - usage->rtpdownpackets = OSP_DEF_STATS; + if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPSRCREPPKTS)) || + (sscanf(strvar, "%d", &usage->rtpsrcreppackets) != 1)) + { + usage->rtpsrcreppackets = OSP_DEF_STATS; } - if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPUPPKTS)) || (sscanf(strvar, "%d", &usage->rtpuppackets) != 1)) { - usage->rtpuppackets = OSP_DEF_STATS; + if (!(strvar = switch_channel_get_variable(channel, OSP_FS_RTPDESTREPPKTS)) || + (sscanf(strvar, "%d", &usage->rtpdestreppackets) != 1)) + { + usage->rtpdestreppackets = OSP_DEF_STATS; } } @@ -1994,7 +2190,7 @@ static OSPTTHREADRETURN osp_report_thread( /* * Report usage - * param cookie OSP cookie + * param cookie Cookie * param usage Usage * return SWITCH_STATUS_SUCCESS Successful, SWITCH_STATUS_FALSE Failed */ @@ -2003,7 +2199,9 @@ static switch_status_t osp_report_usage( osp_usage_t *usage) { osp_profile_t *profile; - const char *source; + char source[OSP_SIZE_NORSTR]; + char destination[OSP_SIZE_NORSTR]; + char srcdev[OSP_SIZE_NORSTR]; OSPTTRANHANDLE transaction; osp_threadarg_t *info; OSPTTHREADID threadid; @@ -2022,22 +2220,26 @@ static switch_status_t osp_report_usage( } if (profile->workmode == OSP_MODE_INDIRECT) { - source = usage->srcdev; + osp_convert_inout(usage->srcdev, source, sizeof(source)); } else { - source = profile->device; + osp_convert_inout(profile->device, source, sizeof(source)); } + osp_convert_inout(cookie->dest, destination, sizeof(destination)); + + osp_convert_inout(cookie->srcdev, srcdev, sizeof(srcdev)); + error = OSPPTransactionBuildUsageFromScratch( transaction, /* Transaction handle */ cookie->transid, /* Transaction ID */ OSPC_ROLE_SOURCE, /* CDR type, source */ source, /* Source */ - cookie->dest, /* Destination */ - cookie->srcdev, /* Source device */ + destination, /* Destination */ + srcdev, /* Source device */ OSP_DEF_STRING, /* Destination device */ - usage->calling, /* Calling */ + cookie->calling, /* Calling */ OSPC_NFORMAT_E164, /* Calling format */ - usage->called, /* Called */ + cookie->called, /* Called */ OSPC_NFORMAT_E164, /* Called format */ strlen(usage->callid), /* Size of Call-ID */ usage->callid, /* Call-ID */ @@ -2053,6 +2255,9 @@ static switch_status_t osp_report_usage( OSPPTransactionSetDestinationCount(transaction, cookie->destcount); + OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_SOURCE, usage->inprotocol); + OSPPTransactionSetProtocol(transaction, OSPC_PROTTYPE_DESTINATION, usage->outprotocol); + if (!switch_strlen_zero(cookie->srcnid)) { OSPPTransactionSetSrcNetworkId(transaction, cookie->srcnid); } @@ -2061,24 +2266,30 @@ static switch_status_t osp_report_usage( OSPPTransactionSetDestNetworkId(transaction, cookie->destnid); } - if (!switch_strlen_zero(usage->fcodec)) { - OSPPTransactionSetForwardCodec(transaction, usage->fcodec); + if (!switch_strlen_zero(usage->srccodec)) { + OSPPTransactionSetCodec(transaction, OSPC_CODEC_SOURCE, usage->srccodec); } - if (!switch_strlen_zero(usage->rcodec)) { - OSPPTransactionSetReverseCodec(transaction, usage->rcodec); + if (!switch_strlen_zero(usage->destcodec)) { + OSPPTransactionSetCodec(transaction, OSPC_CODEC_DESTINATION, usage->destcodec); } - if (usage->rtpdownoctets != OSP_DEF_STATS) { - OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, usage->rtpdownoctets); + if (usage->rtpsrcrepoctets != OSP_DEF_STATS) { + OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcrepoctets); } - if (usage->rtpupoctets != OSP_DEF_STATS) { - OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, usage->rtpupoctets); + if (usage->rtpdestrepoctets != OSP_DEF_STATS) { + OSPPTransactionSetOctets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestrepoctets); } - if (usage->rtpdownpackets != OSP_DEF_STATS) { - OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SFLOW_DOWNSTREAM, usage->rtpdownpackets); + if (usage->rtpsrcreppackets != OSP_DEF_STATS) { + OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_SRCREP, usage->rtpsrcreppackets); } - if (usage->rtpuppackets != OSP_DEF_STATS) { - OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SFLOW_UPSTREAM, usage->rtpuppackets); + if (usage->rtpdestreppackets != OSP_DEF_STATS) { + OSPPTransactionSetPackets(transaction, OSPC_SMETRIC_RTP, OSPC_SDIR_DESTREP, usage->rtpdestreppackets); + } + + if ((cookie->destcount == cookie->desttotal) || (usage->cause == SWITCH_CAUSE_NORMAL_CLEARING)) { + OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_STOP, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); + } else { + OSPPTransactionSetRoleInfo(transaction, OSPC_RSTATE_INTERIM, OSPC_RFORMAT_OSP, OSPC_RVENDOR_FREESWITCH); } info = (osp_threadarg_t *)malloc(sizeof(osp_threadarg_t)); @@ -2090,7 +2301,7 @@ static switch_status_t osp_report_usage( info->connect = usage->connect / 1000000; info->end = usage->end / 1000000; info->duration = usage->duration / 1000000; - info->pdd = usage->pdd / 1000000; + info->pdd = usage->pdd / 1000; info->release = usage->release; OSPM_THRATTR_INIT(threadattr, error); @@ -2105,7 +2316,7 @@ static switch_status_t osp_report_usage( /* * Log UsageInd parameters - * param cookie OSP cookie + * param cookie Cookie * param usage Usage info * return */ @@ -2116,42 +2327,42 @@ static void osp_log_usageind( if (osp_globals.debug) { switch_log_printf(SWITCH_CHANNEL_LOG, osp_globals.loglevel, "UsageInd: " - "transid = '%"PRIu64"' " - "destcount = '%d' " - "callid = '%s' " - "calling = '%s' " - "called = '%s' " - "srcdev = '%s' " - "dest = '%s' " - "nid = '%s/%s' " - "protocol = '%s' " - "cause = '%d' " - "release = '%s' " - "times = '%"PRId64"/%"PRId64"/%"PRId64"/%"PRId64"' " - "duration = '%"PRId64"' " - "pdd = '%"PRId64"' " - "outsessionid = '%s' " - "codec = '%s/%s' " - "rtpctets = '%d/%d' " - "rtppackets = '%d/%d'\n", + "transid '%"PRIu64"' " + "destcount '%d' " + "callid '%s' " + "calling '%s' " + "called '%s' " + "srcdev '%s' " + "dest '%s' " + "nid '%s/%s' " + "protocol '%s/%s' " + "cause '%d' " + "release '%s' " + "times '%"PRId64"/%"PRId64"/%"PRId64"/%"PRId64"' " + "duration '%"PRId64"' " + "pdd '%"PRId64"' " + "outsessionid '%s' " + "codec '%s/%s' " + "rtpctets '%d/%d' " + "rtppackets '%d/%d'\n", cookie->transid, cookie->destcount, usage->callid, - usage->calling, - usage->called, + cookie->calling, + cookie->called, cookie->srcdev, cookie->dest, osp_filter_null(cookie->srcnid), osp_filter_null(cookie->destnid), - osp_get_protocol(usage->protocol), + osp_get_protocol(usage->inprotocol), osp_get_protocol(usage->outprotocol), usage->cause, usage->release ? "term" : "orig", cookie->start / 1000000, usage->alert / 1000000, usage->connect / 1000000, usage->end / 1000000, usage->duration / 1000000, usage->pdd / 1000000, usage->callid, - osp_filter_null(usage->fcodec), osp_filter_null(usage->rcodec), - usage->rtpdownoctets, usage->rtpupoctets, - usage->rtpdownpackets, usage->rtpuppackets); + osp_filter_null(usage->srccodec), osp_filter_null(usage->destcodec), + usage->rtpsrcrepoctets, usage->rtpdestrepoctets, + usage->rtpsrcreppackets, usage->rtpdestreppackets); } } @@ -2179,7 +2390,7 @@ static switch_status_t osp_on_reporting( return status; } - if (osp_get_ospcookie(channel, &cookie) != SWITCH_STATUS_SUCCESS) { + if (osp_get_cookie(channel, &cookie) != SWITCH_STATUS_SUCCESS) { return status; }