diff --git a/configs/samples/dundi.conf.sample b/configs/samples/dundi.conf.sample index 3e8da2d1f5..2f28f453bb 100644 --- a/configs/samples/dundi.conf.sample +++ b/configs/samples/dundi.conf.sample @@ -75,6 +75,18 @@ autokill=yes ; off by default due to performance impacts. ; ;storehistory=yes +; +; Channel technology to use for outgoing calls using SIP (Session Initiation Protocol). +; Options are 'SIP' for chan_sip and 'PJSIP' for chan_pjsip. Default is 'PJSIP'. +; If specified, all outgoing SIP calls using DUNDi will use the specified channel tech. +; +;outgoing_sip_tech=pjsip +; +; Name of endpoint from pjsip.conf to use for outgoing calls from this system, +; when using the PJSIP technology to complete a call to a SIP-based destination. +; (Required for PJSIP, since PJSIP calls must specify an endpoint explicitly). +; +;pjsip_outgoing_endpoint=outgoing [mappings] ; diff --git a/doc/CHANGES-staging/dundi.txt b/doc/CHANGES-staging/dundi.txt new file mode 100644 index 0000000000..e71f726743 --- /dev/null +++ b/doc/CHANGES-staging/dundi.txt @@ -0,0 +1,5 @@ +Subject: DUNDi + +DUNDi now supports chan_pjsip. Outgoing calls using +PJSIP require the pjsip_outgoing_endpoint option +to be set in dundi.conf. diff --git a/include/asterisk/dundi.h b/include/asterisk/dundi.h index 3f73c19374..ed120018cf 100644 --- a/include/asterisk/dundi.h +++ b/include/asterisk/dundi.h @@ -59,6 +59,8 @@ enum { DUNDI_PROTO_SIP = 2, /*! ITU H.323 */ DUNDI_PROTO_H323 = 3, + /*! PJSIP */ + DUNDI_PROTO_PJSIP = 4, }; enum { diff --git a/pbx/dundi-parser.c b/pbx/dundi-parser.c index bbfc760d09..5be8f4c301 100644 --- a/pbx/dundi-parser.c +++ b/pbx/dundi-parser.c @@ -236,6 +236,8 @@ static char *proto2str(int proto, char *buf, int bufsiz) case DUNDI_PROTO_H323: strncpy(buf, "H.323", bufsiz - 1); break; + case DUNDI_PROTO_PJSIP: + strncpy(buf, "PJSIP", bufsiz - 1); default: snprintf(buf, bufsiz, "Unknown Proto(%d)", proto); } diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index 58b82a4ad8..d02752ab71 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -208,6 +208,8 @@ static char phone[80]; static char secretpath[80]; static char cursecret[80]; static char ipaddr[80]; +static int outgoing_sip_tech; +static char pjsip_outgoing_endpoint[80]; static time_t rotatetime; static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } }; static int dundi_shutdown = 0; @@ -388,12 +390,14 @@ static char *tech2str(int tech) return "SIP"; case DUNDI_PROTO_H323: return "H323"; + case DUNDI_PROTO_PJSIP: + return "PJSIP"; default: return "Unknown"; } } -static int str2tech(char *str) +static int str2tech(const char *str) { if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) return DUNDI_PROTO_IAX; @@ -401,6 +405,8 @@ static int str2tech(char *str) return DUNDI_PROTO_SIP; else if (!strcasecmp(str, "H323")) return DUNDI_PROTO_H323; + else if (!strcasecmp(str, "PJSIP")) + return DUNDI_PROTO_PJSIP; else return -1; } @@ -4816,7 +4822,6 @@ static int dundi_exec(struct ast_channel *chan, const char *context, const char int x=0; char req[1024]; const char *dundiargs; - struct ast_app *dial; if (ast_strlen_zero(data)) data = context; @@ -4834,13 +4839,42 @@ static int dundi_exec(struct ast_channel *chan, const char *context, const char if (x < res) { /* Got a hit! */ dundiargs = pbx_builtin_getvar_helper(chan, "DUNDIDIALARGS"); - snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest, - S_OR(dundiargs, "")); - dial = pbx_findapp("Dial"); - if (dial) - res = pbx_exec(chan, dial, req); - } else + /* Backwards compatibility with lookups using chan_sip even if we don't have it anymore: + * At a protocol level, "SIP" will always be specified, but depending on our configuration, + * we will use the user-specified channel driver (from dundi.conf) to complete the call. + */ + if (!strcasecmp(results[x].tech, "SIP") || !strcasecmp(results[x].tech, "PJSIP")) { + /* Only "SIP" is a valid technology for a DUNDi peer to communicate. + * But if they tell use to use "PJSIP" instead, just interpret it as if they said "SIP" instead. */ + if (strcasecmp(results[x].tech, "SIP")) { + ast_log(LOG_WARNING, "%s cannot be specified by DUNDi peers (peer should use SIP for DUNDi lookups instead)\n", results[x].tech); + } + /* Use whatever we're configured to use for SIP protocol calls. */ + results[x].techint = outgoing_sip_tech; + ast_copy_string(results[x].tech, tech2str(outgoing_sip_tech), sizeof(results[x].tech)); + } + /* PJSIP requires an endpoint to be specified explicitly. */ + if (outgoing_sip_tech == DUNDI_PROTO_PJSIP) { + char *number, *ip = ast_strdupa(results[x].dest); + if (!ast_strlen_zero(pjsip_outgoing_endpoint)) { + ast_log(LOG_WARNING, "PJSIP calls require an endpoint to be specified explicitly (use the pjsip_outgoing_endpoint option in dundi.conf)\n"); + return -1; + } + /* Take IP/number and turn it into sip:number@IP */ + if (ast_strlen_zero(ip)) { + ast_log(LOG_WARNING, "PJSIP destination is empty?\n"); + return -1; + } + number = strsep(&ip, "/"); + snprintf(req, sizeof(req), "%s/%s/sip:%s@%s,,%s", results[x].tech, pjsip_outgoing_endpoint, S_OR(number, ""), ip, S_OR(dundiargs, "")); + ast_debug(1, "Finalized PJSIP Dial: %s\n", req); + } else { /* SIP, or something else. */ + snprintf(req, sizeof(req), "%s/%s,,%s", results[x].tech, results[x].dest, S_OR(dundiargs, "")); + } + res = ast_pbx_exec_application(chan, "Dial", req); + } else { res = -1; + } return res; } @@ -4916,6 +4950,7 @@ static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, s dundi_ttl = DUNDI_DEFAULT_TTL; dundi_cache_time = DUNDI_DEFAULT_CACHE_TIME; any_peer = NULL; + outgoing_sip_tech = DUNDI_PROTO_PJSIP; /* Default for new versions */ AST_LIST_LOCK(&peers); @@ -4986,6 +5021,15 @@ static int set_config(char *config_file, struct ast_sockaddr *sin, int reload, s ast_copy_string(phone, v->value, sizeof(phone)); } else if (!strcasecmp(v->name, "storehistory")) { global_storehistory = ast_true(v->value); + } else if (!strcasecmp(v->name, "outgoing_sip_tech")) { + int outgoing_tech = str2tech(v->value); + if (outgoing_tech != DUNDI_PROTO_SIP && outgoing_tech != DUNDI_PROTO_PJSIP) { + ast_log(LOG_WARNING, "outgoing_sip_tech must be SIP or PJSIP\n"); + } else { + outgoing_sip_tech = outgoing_tech; + } + } else if (!strcasecmp(v->name, "pjsip_outgoing_endpoint")) { + ast_copy_string(pjsip_outgoing_endpoint, v->value, sizeof(pjsip_outgoing_endpoint)); } else if (!strcasecmp(v->name, "cachetime")) { if ((sscanf(v->value, "%30d", &x) == 1)) { dundi_cache_time = x;