]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pbx_dundi: Add PJSIP support.
authorNaveen Albert <asterisk@phreaknet.org>
Fri, 9 Dec 2022 14:18:26 +0000 (14:18 +0000)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Mon, 10 Apr 2023 19:38:51 +0000 (14:38 -0500)
Adds PJSIP as a supported technology to DUNDi.

To facilitate this, we now allow an endpoint to be specified
for outgoing PJSIP calls. We also allow users to force a specific
channel technology for outgoing SIP-protocol calls.

ASTERISK-28109 #close
ASTERISK-28233 #close

Change-Id: I2e28e5a5d007bd49e3df113ad567b011103899bf

configs/samples/dundi.conf.sample
doc/CHANGES-staging/dundi.txt [new file with mode: 0644]
include/asterisk/dundi.h
pbx/dundi-parser.c
pbx/pbx_dundi.c

index 3e8da2d1f510788ff3578db2b7564889b555e394..2f28f453bba7ca901b5d4aa131518406fba222aa 100644 (file)
@@ -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 (file)
index 0000000..e71f726
--- /dev/null
@@ -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.
index 3f73c1937422b22a58dce7210ff6f4b4b973bfff..ed120018cfd05f6ec01231ebbd34320a4b1c35ec 100644 (file)
@@ -59,6 +59,8 @@ enum {
        DUNDI_PROTO_SIP  = 2,
        /*! ITU H.323 */
        DUNDI_PROTO_H323 = 3,
+       /*! PJSIP */
+       DUNDI_PROTO_PJSIP = 4,
 };
 
 enum {
index bbfc760d092c9ab6dd55566a63ec89881e26381c..5be8f4c301d0c7efff58344827f5486a8d41235e 100644 (file)
@@ -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);
        }
index 58b82a4ad8026fd6d5d111cc06569b57e6644919..d02752ab71ec745015000ac4a523894bcd50fcbd 100644 (file)
@@ -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;