Skip to content

Commit

Permalink
Add option for dual stack IPv4&IPv6 account config (#3590)
Browse files Browse the repository at this point in the history
  • Loading branch information
sauwming authored Jun 9, 2023
1 parent de317c6 commit 48800cb
Show file tree
Hide file tree
Showing 16 changed files with 400 additions and 218 deletions.
6 changes: 3 additions & 3 deletions pjsip-apps/src/pjsua/pjsua_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -1713,7 +1713,7 @@ static pj_status_t app_init(void)

app_config_init_video(&acc_cfg);
acc_cfg.rtp_cfg = app_config.rtp_cfg;
acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
// acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
pjsua_acc_modify(aid, &acc_cfg);
}

Expand Down Expand Up @@ -1778,7 +1778,7 @@ static pj_status_t app_init(void)

app_config_init_video(&acc_cfg);
acc_cfg.rtp_cfg = app_config.rtp_cfg;
acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
// acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
pjsua_acc_modify(aid, &acc_cfg);
}

Expand Down Expand Up @@ -1846,7 +1846,7 @@ static pj_status_t app_init(void)

app_config_init_video(&acc_cfg);
acc_cfg.rtp_cfg = app_config.rtp_cfg;
acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
// acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
pjsua_acc_modify(aid, &acc_cfg);
}

Expand Down
2 changes: 1 addition & 1 deletion pjsip-apps/src/pjsua/pjsua_app_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static void usage(void)
puts ("");
puts ("Transport Options:");
#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
puts (" --ipv6 Use IPv6 instead for SIP and media.");
puts (" --ipv6 Create SIP IPv6 transports.");
#endif
puts (" --set-qos Enable QoS tagging for SIP and media.");
puts (" --local-port=port Set TCP/UDP port. This implicitly enables both ");
Expand Down
6 changes: 5 additions & 1 deletion pjsip-apps/src/swig/symbols.i
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,11 @@ typedef enum pjsua_sip_timer_use
typedef enum pjsua_ipv6_use
{
PJSUA_IPV6_DISABLED,
PJSUA_IPV6_ENABLED
PJSUA_IPV6_ENABLED = 1,
PJSUA_IPV6_ENABLED_NO_PREFERENCE = 1,
PJSUA_IPV6_ENABLED_PREFER_IPV4,
PJSUA_IPV6_ENABLED_PREFER_IPV6,
PJSUA_IPV6_ENABLED_USE_IPV6_ONLY
} pjsua_ipv6_use;

typedef enum pjsua_nat64_opt
Expand Down
38 changes: 20 additions & 18 deletions pjsip/include/pjsip/sip_resolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,25 @@ PJ_BEGIN_DECL
* - RFC 3263: Locating SIP Servers
*/

/** Address records. */
typedef struct pjsip_server_address_record
{
/** Preferable transport to be used to contact this address. */
pjsip_transport_type_e type;

/** Server priority (the lower the higher the priority). */
unsigned priority;

/** Server weight (the higher the more load it can handle). */
unsigned weight;

/** The server's address. */
pj_sockaddr addr;

/** Address length. */
int addr_len;
} pjsip_server_address_record;

/**
* The server addresses returned by the resolver.
*/
Expand All @@ -180,24 +199,7 @@ typedef struct pjsip_server_addresses
unsigned count;

/** Address records. */
struct
{
/** Preferable transport to be used to contact this address. */
pjsip_transport_type_e type;

/** Server priority (the lower the higher the priority). */
unsigned priority;

/** Server weight (the higher the more load it can handle). */
unsigned weight;

/** The server's address. */
pj_sockaddr addr;

/** Address length. */
int addr_len;

} entry[PJSIP_MAX_RESOLVED_ADDRESSES];
pjsip_server_address_record entry[PJSIP_MAX_RESOLVED_ADDRESSES];

} pjsip_server_addresses;

Expand Down
40 changes: 36 additions & 4 deletions pjsip/include/pjsip/sip_transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,36 @@ typedef enum pjsip_tpselector_type
/** Use the specific listener to send request. */
PJSIP_TPSELECTOR_LISTENER,

/** Use the IP version criteria to send request. */
PJSIP_TPSELECTOR_IP_VER,

} pjsip_tpselector_type;

/**
* This enumerator describes the IP version criteria for pjsip_tpselector.
*/
typedef enum pjsip_tpselector_ip_ver
{
/** IPv4 only. */
PJSIP_TPSELECTOR_USE_IPV4_ONLY,

/**
* No preference. IP version used will depend on the order of addresses
* returned by pjsip_resolver.
*/
PJSIP_TPSELECTOR_NO_PREFERENCE,

/** IPv4 is preferred. */
PJSIP_TPSELECTOR_PREFER_IPV4,

/** IPv6 is preferred. */
PJSIP_TPSELECTOR_PREFER_IPV6,

/** IPv6 only. */
PJSIP_TPSELECTOR_USE_IPV6_ONLY

} pjsip_tpselector_ip_ver;


/**
* This structure describes the transport/listener preference to be used
Expand Down Expand Up @@ -240,11 +268,15 @@ typedef struct pjsip_tpselector
*/
pj_bool_t disable_connection_reuse;

/** Union representing the transport/listener criteria to be used. */
/**
* Union representing the transport/listener/IP version criteria
* to be used.
*/
union {
pjsip_transport *transport;
pjsip_tpfactory *listener;
void *ptr;
pjsip_transport *transport;
pjsip_tpfactory *listener;
pjsip_tpselector_ip_ver ip_ver;
void *ptr;
} u;

} pjsip_tpselector;
Expand Down
33 changes: 32 additions & 1 deletion pjsip/include/pjsua-lib/pjsua.h
Original file line number Diff line number Diff line change
Expand Up @@ -3677,6 +3677,8 @@ typedef struct pjsua_turn_config

/**
* Specify how IPv6 transport should be used in account config.
* IP version preference only applies for outgoing direction, for incoming
* direction, we will check the corresponding message/offer and match it.
*/
typedef enum pjsua_ipv6_use
{
Expand All @@ -3688,7 +3690,23 @@ typedef enum pjsua_ipv6_use
/**
* IPv6 is enabled.
*/
PJSUA_IPV6_ENABLED
PJSUA_IPV6_ENABLED = 1,
PJSUA_IPV6_ENABLED_NO_PREFERENCE = 1,

/**
* IPv6 is enabled, but IPv4 is preferable.
*/
PJSUA_IPV6_ENABLED_PREFER_IPV4,

/**
* IPv6 is enabled and preferable.
*/
PJSUA_IPV6_ENABLED_PREFER_IPV6,

/**
* Only IPv6 is enabled, IPv4 will not be used.
*/
PJSUA_IPV6_ENABLED_USE_IPV6_ONLY

} pjsua_ipv6_use;

Expand Down Expand Up @@ -4177,8 +4195,21 @@ typedef struct pjsua_acc_config
*/
pjsua_nat64_opt nat64_opt;

/**
* Specify whether IPv6 should be used for SIP signalling.
*
* Default: PJSUA_IPV6_ENABLED_NO_PREFERENCE
* (IP version used will be based on the address resolution
* returned by OS/resolver)
*/
pjsua_ipv6_use ipv6_sip_use;

/**
* Specify whether IPv6 should be used on media.
*
* Default: PJSUA_IPV6_ENABLED_PREFER_IPV4
* (Dual stack media, capable to use IPv4/IPv6.
* Outgoing offer will prefer to use IPv4)
*/
pjsua_ipv6_use ipv6_media_use;

Expand Down
17 changes: 15 additions & 2 deletions pjsip/include/pjsua2/account.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,15 @@ struct AccountSipConfig : public PersistentObject
*/
TransportId transportId;

/**
* Specify whether IPv6 should be used for SIP signalling.
*
* Default: PJSUA_IPV6_ENABLED_NO_PREFERENCE
* (IP version used will be based on the address resolution
* returned by OS/resolver)
*/
pjsua_ipv6_use ipv6Use;

public:
/**
* Read this object from a container node.
Expand Down Expand Up @@ -1033,7 +1042,11 @@ struct AccountMediaConfig : public PersistentObject
SrtpOpt srtpOpt;

/**
* Specify whether IPv6 should be used on media. Default is not used.
* Specify whether IPv6 should be used on media.
*
* Default: PJSUA_IPV6_ENABLED_PREFER_IPV4
* (Dual stack media, capable to use IPv4/IPv6.
* Outgoing offer will prefer to use IPv4)
*/
pjsua_ipv6_use ipv6Use;

Expand Down Expand Up @@ -1082,7 +1095,7 @@ struct AccountMediaConfig : public PersistentObject
streamKaEnabled(false),
srtpUse(PJSUA_DEFAULT_USE_SRTP),
srtpSecureSignaling(PJSUA_DEFAULT_SRTP_SECURE_SIGNALING),
ipv6Use(PJSUA_IPV6_DISABLED),
ipv6Use(PJSUA_IPV6_ENABLED_PREFER_IPV4),
rtcpMuxEnabled(false),
rtcpXrEnabled(PJMEDIA_STREAM_ENABLE_XR),
useLoopMedTp(false),
Expand Down
9 changes: 9 additions & 0 deletions pjsip/src/pjsip/sip_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -2331,6 +2331,15 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
TRACE_((THIS_FILE, "Listener type in tpsel not matched"));
return PJSIP_ETPNOTSUITABLE;
}
} else if (sel && sel->type == PJSIP_TPSELECTOR_IP_VER) {
if ((sel->u.ip_ver == PJSIP_TPSELECTOR_USE_IPV4_ONLY &&
pjsip_transport_type_get_af(type) != pj_AF_INET()) ||
(sel->u.ip_ver == PJSIP_TPSELECTOR_USE_IPV6_ONLY &&
pjsip_transport_type_get_af(type) != pj_AF_INET6()))
{
TRACE_((THIS_FILE, "Address type in tpsel not matched"));
return PJSIP_ETPNOTSUITABLE;
}
}

if (!sel || sel->disable_connection_reuse == PJ_FALSE) {
Expand Down
37 changes: 36 additions & 1 deletion pjsip/src/pjsip/sip_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <pjsip/sip_transaction.h>
#include <pjsip/sip_module.h>
#include <pjsip/sip_errno.h>
#include <pj/array.h>
#include <pj/log.h>
#include <pj/string.h>
#include <pj/guid.h>
Expand All @@ -33,7 +34,7 @@
#include <pj/assert.h>
#include <pj/errno.h>

#define THIS_FILE "endpoint"
#define THIS_FILE "sip_util.c"

static const char *event_str[] =
{
Expand Down Expand Up @@ -1306,6 +1307,29 @@ static void stateless_send_transport_cb( void *token,

}

/* Resort addresses based on preferred address family.
* Note that the order of addresses within the same address family will
* be preserved.
*/
static void resort_address(pjsip_server_addresses *addr, int af)
{
unsigned i = 0, j = 0;

while (j < addr->count) {
if (addr->entry[j].addr.addr.sa_family == af) {
if (i != j) {
pjsip_server_address_record temp;

pj_memcpy(&temp, &addr->entry[j], sizeof(temp));
pj_array_insert(addr->entry, sizeof(addr->entry[0]),
j, i, &temp);
}
i++;
}
j++;
}
}

/* Resolver callback for sending stateless request. */
static void
stateless_send_resolver_callback( pj_status_t status,
Expand Down Expand Up @@ -1382,6 +1406,17 @@ stateless_send_resolver_callback( pj_status_t status,
}
}

if (tdata->tp_sel.type == PJSIP_TPSELECTOR_IP_VER) {
PJ_LOG(5, (THIS_FILE, "Resorting target addresses based on "
"%s preference",
tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4?
"IPv4": "IPv6"));
if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV4)
resort_address(&tdata->dest_info.addr, pj_AF_INET());
else if (tdata->tp_sel.u.ip_ver == PJSIP_TPSELECTOR_PREFER_IPV6)
resort_address(&tdata->dest_info.addr, pj_AF_INET6());
}

/* Process the addresses. */
stateless_send_transport_cb( stateless_data, tdata, -PJ_EPENDING);
}
Expand Down
Loading

0 comments on commit 48800cb

Please sign in to comment.