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;
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;
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;
}
int x=0;
char req[1024];
const char *dundiargs;
- struct ast_app *dial;
if (ast_strlen_zero(data))
data = context;
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;
}
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);
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;