Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion pjsip/include/pjsip/sip_endpoint.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -423,6 +423,18 @@ PJ_DECL(pj_status_t) pjsip_endpt_set_ext_resolver(pjsip_endpoint *endpt,
*/
PJ_DECL(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt);

/**
* Get the external resolver implementation set with
* #pjsip_endpt_set_ext_resolver().
*
* @param endpt The SIP endpoint instance.
*
* @return The external resolver implementation, or NULL when
* none is set.
*/
PJ_DECL(pjsip_ext_resolver*) pjsip_endpt_get_ext_resolver(
pjsip_endpoint *endpt);

/**
* Mark a server address as failed for the specified duration, or clear the
* mark. Please see #pjsip_resolver_set_server_failed() for more info.
Expand Down
16 changes: 15 additions & 1 deletion pjsip/include/pjsip/sip_resolve.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -313,6 +313,20 @@ PJ_DECL(pj_status_t) pjsip_resolver_set_ext_resolver(
*/
PJ_DECL(pj_dns_resolver*) pjsip_resolver_get_resolver(pjsip_resolver_t *res);

/**
* Get the external resolver implementation of the SIP resolver engine.
*
* Note that application normally will use #pjsip_endpt_get_ext_resolver()
* instead since it does not normally have access to the SIP resolver
* instance.
*
* @param res The SIP resolver engine.
*
* @return The external resolver implementation (may be NULL)
*/
PJ_DECL(pjsip_ext_resolver*) pjsip_resolver_get_ext_resolver(
pjsip_resolver_t *res);

/**
* Mark a server address as failed for the specified duration, or clear the
* mark. The mark applies to the IP address and port, whatever the transport
Expand Down
10 changes: 7 additions & 3 deletions pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -4783,8 +4783,12 @@ typedef struct pjsua_acc_config
/**
* Specify if source TCP port should be used as the initial Contact
* address if TCP/TLS transport is used. Note that this feature will
* be automatically turned off when nameserver is configured because
* it may yield different destination address due to DNS SRV resolution.
* be automatically turned off when nameservers are configured
* (\a pjsua_config.nameserver) or when the application sets a DNS
* resolver or an external resolver on the SIP endpoint
* (#pjsip_endpt_set_resolver(),
* #pjsip_endpt_set_ext_resolver()), because they may yield a different
* destination address due to DNS SRV resolution.
* Also some platforms are unable to report the local address of the
* TCP socket when it is still connecting. In these cases, this
* feature will also be turned off.
Expand Down
8 changes: 5 additions & 3 deletions pjsip/include/pjsua2/account.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2013-2026 Teluu Inc. (http://www.teluu.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -778,8 +778,10 @@ struct AccountNatConfig : public PersistentObject
/**
* Specify if source TCP port should be used as the initial Contact
* address if TCP/TLS transport is used. Note that this feature will
* be automatically turned off when nameserver is configured because
* it may yield different destination address due to DNS SRV resolution.
* be automatically turned off when nameservers are configured
* (UaConfig::nameserver) or when the application sets a DNS resolver
* or an external resolver on the SIP endpoint, because they may yield
* a different destination address due to DNS SRV resolution.
* Also some platforms are unable to report the local address of the
* TCP socket when it is still connecting. In these cases, this
* feature will also be turned off.
Expand Down
12 changes: 11 additions & 1 deletion pjsip/src/pjsip/sip_endpoint.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -1347,6 +1347,16 @@ PJ_DEF(pj_dns_resolver*) pjsip_endpt_get_resolver(pjsip_endpoint *endpt)
return pjsip_resolver_get_resolver(endpt->resolver);
}

/*
* Get the external resolver implementation.
*/
PJ_DEF(pjsip_ext_resolver*) pjsip_endpt_get_ext_resolver(
pjsip_endpoint *endpt)
{
PJ_ASSERT_RETURN(endpt, NULL);
return pjsip_resolver_get_ext_resolver(endpt->resolver);
}

/*
* Resolve
*/
Expand Down
12 changes: 11 additions & 1 deletion pjsip/src/pjsip/sip_resolve.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -190,6 +190,16 @@ PJ_DEF(pj_dns_resolver*) pjsip_resolver_get_resolver(pjsip_resolver_t *res)
}


/*
* Public API to get the external resolver implementation.
*/
PJ_DEF(pjsip_ext_resolver*) pjsip_resolver_get_ext_resolver(
pjsip_resolver_t *res)
{
return res->ext_res;
}


/* Find a failed server entry. Must be called with the group lock held. */
static int find_failed(pjsip_resolver_t *resolver, const pj_sockaddr_t *addr)
{
Expand Down
19 changes: 11 additions & 8 deletions pjsip/src/pjsua-lib/pjsua_acc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2008-2026 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -4522,16 +4522,19 @@ static pj_status_t get_uac_addr_for_sip_uri(pjsua_acc_id acc_id,
}

ip_addr_ver = get_ip_addr_ver(&dinfo.addr.host);
if (ip_addr_ver == 0 && pjsua_var.ua_cfg.nameserver_count) {
/* If nameserver is configured, PJSIP will resolve destinations
* by their DNS SRV record first. On the other hand, we will
* resolve destination with DNS A record via pj_getaddrinfo().
* They may yield different IP addresses, hence causing different
* TCP/TLS connection to be created and hence different source
if (ip_addr_ver == 0 &&
(pjsip_endpt_get_resolver(pjsua_var.endpt) ||
pjsip_endpt_get_ext_resolver(pjsua_var.endpt)))
{
/* With a DNS resolver or an external resolver, PJSIP may
* resolve destinations by their DNS SRV record first. On the other
* hand, we would resolve the destination with its DNS A record
* via pj_getaddrinfo(). They may yield different addresses,
* hence a different TCP/TLS connection and a different source
* address.
*/
PJ_LOG(4,(THIS_FILE, "Warning: cannot use source TCP/TLS socket"
" address for Contact when nameserver is configured."));
" address for Contact when a resolver is set."));
goto on_return;
}

Expand Down
101 changes: 101 additions & 0 deletions pjsip/src/test/srv_failover_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2085,6 +2085,103 @@ static int pjsua_restore_once_case(pj_bool_t init_fails)
return rc;
}

#if PJ_HAS_TCP
/* An external resolver that fails every query */
static void no_resolve(pjsip_resolver_t *resolver, pj_pool_t *pool,
const pjsip_host_info *target, void *token,
pjsip_resolver_callback *cb)
{
PJ_UNUSED_ARG(resolver); PJ_UNUSED_ARG(pool); PJ_UNUSED_ARG(target);
(*cb)(PJ_ERESOLVE, token, NULL);
}

/* With an external resolver the destination may come from a DNS SRV
* record: the Contact takes the TCP listener's port, without a probing
* connection to the A record of the name.
*/
static int pjsua_contact_probe_case(void)
{
static pjsip_ext_resolver ext = { &no_resolve };
pjsua_config ua_cfg;
pjsua_logging_config log_cfg;
pjsua_transport_config tcfg;
pjsua_transport_info tinfo;
pjsua_transport_id tp_id;
pjsua_acc_config acc_cfg;
pjsua_acc_id acc_id;
pjsip_tpmgr *tpmgr;
pj_pool_t *pool;
pj_str_t contact, uri = pj_str("sip:localhost;transport=tcp");
unsigned tp_cnt;
char *p;
int rc = 0;

PJ_LOG(3,(THIS_FILE, " Contact with an external resolver"));

if (pjsua_create() != PJ_SUCCESS)
return -3180;
pjsua_config_default(&ua_cfg);
ua_cfg.thread_cnt = 0;
pjsua_logging_config_default(&log_cfg);
log_cfg.level = 3;
log_cfg.console_level = 3;
if (pjsua_init(&ua_cfg, &log_cfg, NULL) != PJ_SUCCESS) {
pjsua_destroy();
return -3181;
}
if (pjsip_endpt_set_ext_resolver(pjsua_get_pjsip_endpt(), &ext) !=
PJ_SUCCESS)
{
pjsua_destroy();
return -3182;
}
pjsua_transport_config_default(&tcfg);
tcfg.port = 0;
if (pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcfg,
&tp_id) != PJ_SUCCESS ||
pjsua_start() != PJ_SUCCESS ||
pjsua_transport_get_info(tp_id, &tinfo) != PJ_SUCCESS)
{
pjsua_destroy();
return -3183;
}
pjsua_acc_config_default(&acc_cfg);
acc_cfg.id = pj_str("sip:test@localhost");
if (pjsua_acc_add(&acc_cfg, PJ_FALSE, &acc_id) != PJ_SUCCESS) {
pjsua_destroy();
return -3184;
}

tpmgr = pjsip_endpt_get_tpmgr(pjsua_get_pjsip_endpt());
tp_cnt = pjsip_tpmgr_get_transport_count(tpmgr);
pool = pjsua_pool_create("probe", 512, 512);
if (pjsua_acc_create_uac_contact(pool, &contact, acc_id,
&uri) != PJ_SUCCESS)
{
rc = -3185;
} else {
pj_str_t port;

p = pj_strchr(&contact, '@');
p = p ? pj_memchr(p, ':', contact.ptr + contact.slen - p) : NULL;
port.ptr = p ? p + 1 : NULL;
port.slen = p ? contact.ptr + contact.slen - port.ptr : 0;
if (!p || pj_strtoul(&port) != (unsigned)tinfo.local_name.port) {
PJ_LOG(1,(THIS_FILE, " Contact %.*s, listener port %d",
(int)contact.slen, contact.ptr, tinfo.local_name.port));
rc = -3186;
} else if (pjsip_tpmgr_get_transport_count(tpmgr) != tp_cnt) {
rc = -3187;
}
}
pj_pool_release(pool);
pjsua_destroy();
if (rc)
PJ_LOG(1,(THIS_FILE, " error: Contact case failed [%d]", rc));
return rc;
}
#endif

int srv_failover_pjsua_test(void)
{
int rc;
Expand All @@ -2106,6 +2203,10 @@ int srv_failover_pjsua_test(void)
rc = pjsua_restore_once_case(PJ_FALSE);
if (rc == 0)
rc = pjsua_restore_once_case(PJ_TRUE);
#if PJ_HAS_TCP
if (rc == 0)
rc = pjsua_contact_probe_case();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conflicts with master: #5298 added pjsua_keeps_option_case() and pjsua_restore_once_case() at this same spot and renamed restore_endpt() to restore_test_endpt(). Appending this case after pjsua_restore_once_case(PJ_TRUE) resolves it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebased, the case follows the restore ones now.

#endif

restore_test_endpt();
return rc;
Expand Down
Loading