Ticket #421: initial IPv6 support: UDP transport
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1602 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
62b86ebd8f
commit
23674a3c39
|
@ -132,6 +132,15 @@ pjsip_transport_get_type_from_name(const pj_str_t *name);
|
||||||
PJ_DECL(pjsip_transport_type_e)
|
PJ_DECL(pjsip_transport_type_e)
|
||||||
pjsip_transport_get_type_from_flag(unsigned flag);
|
pjsip_transport_get_type_from_flag(unsigned flag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the socket address family of a given transport type.
|
||||||
|
*
|
||||||
|
* @param type Transport type.
|
||||||
|
*
|
||||||
|
* @return Transport type.
|
||||||
|
*/
|
||||||
|
PJ_DECL(int) pjsip_transport_type_get_af(pjsip_transport_type_e type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get transport flag from type.
|
* Get transport flag from type.
|
||||||
*
|
*
|
||||||
|
@ -162,6 +171,15 @@ pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type);
|
||||||
*/
|
*/
|
||||||
PJ_DECL(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e t);
|
PJ_DECL(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get longer description for the specified transport type.
|
||||||
|
*
|
||||||
|
* @param t Transport type.
|
||||||
|
*
|
||||||
|
* @return Transport description.
|
||||||
|
*/
|
||||||
|
PJ_DECL(const char*) pjsip_transport_get_type_desc(pjsip_transport_type_e t);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
@ -307,7 +325,7 @@ struct pjsip_rx_data
|
||||||
int src_addr_len;
|
int src_addr_len;
|
||||||
|
|
||||||
/** The IP source address string (NULL terminated). */
|
/** The IP source address string (NULL terminated). */
|
||||||
char src_name[16];
|
char src_name[PJ_INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
/** The IP source port number. */
|
/** The IP source port number. */
|
||||||
int src_port;
|
int src_port;
|
||||||
|
@ -506,7 +524,7 @@ struct pjsip_tx_data
|
||||||
pjsip_transport *transport; /**< Transport being used. */
|
pjsip_transport *transport; /**< Transport being used. */
|
||||||
pj_sockaddr dst_addr; /**< Destination address. */
|
pj_sockaddr dst_addr; /**< Destination address. */
|
||||||
int dst_addr_len; /**< Length of address. */
|
int dst_addr_len; /**< Length of address. */
|
||||||
char dst_name[16]; /**< Destination address. */
|
char dst_name[PJ_INET6_ADDRSTRLEN]; /**< Destination address. */
|
||||||
int dst_port; /**< Destination port. */
|
int dst_port; /**< Destination port. */
|
||||||
} tp_info;
|
} tp_info;
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,17 @@ PJ_DECL(pj_status_t) pjsip_udp_transport_start(pjsip_endpoint *endpt,
|
||||||
pjsip_transport **p_transport);
|
pjsip_transport **p_transport);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach UDP socket as a new transport and start the transport.
|
* Start IPv6 UDP transport.
|
||||||
|
*/
|
||||||
|
PJ_DECL(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt,
|
||||||
|
const pj_sockaddr_in6 *local,
|
||||||
|
const pjsip_host_port *a_name,
|
||||||
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach IPv4 UDP socket as a new transport and start the transport.
|
||||||
*
|
*
|
||||||
* @param endpt The SIP endpoint.
|
* @param endpt The SIP endpoint.
|
||||||
* @param sock UDP socket to use.
|
* @param sock UDP socket to use.
|
||||||
|
@ -102,6 +112,29 @@ PJ_DECL(pj_status_t) pjsip_udp_transport_attach(pjsip_endpoint *endpt,
|
||||||
pjsip_transport **p_transport);
|
pjsip_transport **p_transport);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach IPv4 or IPv6 UDP socket as a new transport and start the transport.
|
||||||
|
*
|
||||||
|
* @param endpt The SIP endpoint.
|
||||||
|
* @param type Transport type, which is PJSIP_TRANSPORT_UDP for IPv4
|
||||||
|
* or PJSIP_TRANSPORT_UDP6 for IPv6 socket.
|
||||||
|
* @param sock UDP socket to use.
|
||||||
|
* @param a_name Published address (only the host and port portion is
|
||||||
|
* used).
|
||||||
|
* @param async_cnt Number of simultaneous async operations.
|
||||||
|
* @param p_transport Pointer to receive the transport.
|
||||||
|
*
|
||||||
|
* @return PJ_SUCCESS when the transport has been successfully
|
||||||
|
* started and registered to transport manager, or
|
||||||
|
* the appropriate error code.
|
||||||
|
*/
|
||||||
|
PJ_DECL(pj_status_t) pjsip_udp_transport_attach2(pjsip_endpoint *endpt,
|
||||||
|
pjsip_transport_type_e type,
|
||||||
|
pj_sock_t sock,
|
||||||
|
const pjsip_host_port *a_name,
|
||||||
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the internal socket handle used by the UDP transport. Note
|
* Retrieve the internal socket handle used by the UDP transport. Note
|
||||||
* that this socket normally is registered to ioqueue, so if application
|
* that this socket normally is registered to ioqueue, so if application
|
||||||
|
|
|
@ -82,7 +82,16 @@ typedef enum pjsip_transport_type_e
|
||||||
PJSIP_TRANSPORT_LOOP_DGRAM,
|
PJSIP_TRANSPORT_LOOP_DGRAM,
|
||||||
|
|
||||||
/** Start of user defined transport */
|
/** Start of user defined transport */
|
||||||
PJSIP_TRANSPORT_START_OTHER
|
PJSIP_TRANSPORT_START_OTHER,
|
||||||
|
|
||||||
|
/** Start of IPv6 transports */
|
||||||
|
PJSIP_TRANSPORT_IPV6 = 128,
|
||||||
|
|
||||||
|
/** UDP over IPv6 */
|
||||||
|
PJSIP_TRANSPORT_UDP6 = PJSIP_TRANSPORT_UDP + PJSIP_TRANSPORT_IPV6,
|
||||||
|
|
||||||
|
/** TCP over IPv6 */
|
||||||
|
PJSIP_TRANSPORT_TCP6 = PJSIP_TRANSPORT_TCP + PJSIP_TRANSPORT_IPV6
|
||||||
|
|
||||||
} pjsip_transport_type_e;
|
} pjsip_transport_type_e;
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <pjsip/sip_errno.h>
|
#include <pjsip/sip_errno.h>
|
||||||
#include <pjlib-util/errno.h>
|
#include <pjlib-util/errno.h>
|
||||||
#include <pjlib-util/srv_resolver.h>
|
#include <pjlib-util/srv_resolver.h>
|
||||||
|
#include <pj/addr_resolv.h>
|
||||||
#include <pj/array.h>
|
#include <pj/array.h>
|
||||||
#include <pj/assert.h>
|
#include <pj/assert.h>
|
||||||
#include <pj/ctype.h>
|
#include <pj/ctype.h>
|
||||||
|
@ -137,21 +138,24 @@ PJ_DEF(void) pjsip_resolver_destroy(pjsip_resolver_t *resolver)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal:
|
* Internal:
|
||||||
* determine if an address is a valid IP address.
|
* determine if an address is a valid IP address, and if it is,
|
||||||
|
* return the IP version (4 or 6).
|
||||||
*/
|
*/
|
||||||
static int is_str_ip(const pj_str_t *host)
|
static int get_ip_addr_ver(const pj_str_t *host)
|
||||||
{
|
{
|
||||||
const char *p = host->ptr;
|
pj_in_addr dummy;
|
||||||
const char *end = ((const char*)host->ptr) + host->slen;
|
pj_in6_addr dummy6;
|
||||||
|
|
||||||
while (p != end) {
|
/* First check with inet_aton() */
|
||||||
if (pj_isdigit(*p) || *p=='.') {
|
if (pj_inet_aton(host, &dummy) > 0)
|
||||||
++p;
|
return 4;
|
||||||
} else {
|
|
||||||
return 0;
|
/* Then check if this is an IPv6 address */
|
||||||
}
|
if (pj_inet_pton(pj_AF_INET6(), host, &dummy6) == PJ_SUCCESS)
|
||||||
}
|
return 6;
|
||||||
return 1;
|
|
||||||
|
/* Not an IP address */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,18 +170,18 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
|
||||||
{
|
{
|
||||||
pjsip_server_addresses svr_addr;
|
pjsip_server_addresses svr_addr;
|
||||||
pj_status_t status = PJ_SUCCESS;
|
pj_status_t status = PJ_SUCCESS;
|
||||||
int is_ip_addr;
|
int ip_addr_ver;
|
||||||
struct query *query;
|
struct query *query;
|
||||||
pjsip_transport_type_e type = target->type;
|
pjsip_transport_type_e type = target->type;
|
||||||
|
|
||||||
/* Is it IP address or hostname?. */
|
/* Is it IP address or hostname? And if it's an IP, which version? */
|
||||||
is_ip_addr = is_str_ip(&target->addr.host);
|
ip_addr_ver = get_ip_addr_ver(&target->addr.host);
|
||||||
|
|
||||||
/* Set the transport type if not explicitly specified.
|
/* Set the transport type if not explicitly specified.
|
||||||
* RFC 3263 section 4.1 specify rules to set up this.
|
* RFC 3263 section 4.1 specify rules to set up this.
|
||||||
*/
|
*/
|
||||||
if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
|
if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
|
||||||
if (is_ip_addr || (target->addr.port != 0)) {
|
if (ip_addr_ver || (target->addr.port != 0)) {
|
||||||
#if PJ_HAS_TCP
|
#if PJ_HAS_TCP
|
||||||
if (target->flag & PJSIP_TRANSPORT_SECURE)
|
if (target->flag & PJSIP_TRANSPORT_SECURE)
|
||||||
{
|
{
|
||||||
|
@ -209,18 +213,25 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
|
||||||
type = PJSIP_TRANSPORT_UDP;
|
type = PJSIP_TRANSPORT_UDP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add IPv6 flag for IPv6 address */
|
||||||
|
if (ip_addr_ver == 6)
|
||||||
|
type = (pjsip_transport_type_e)((int)type + PJSIP_TRANSPORT_IPV6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If target is an IP address, or if resolver is not configured,
|
/* If target is an IP address, or if resolver is not configured,
|
||||||
* we can just finish the resolution now using pj_gethostbyname()
|
* we can just finish the resolution now using pj_gethostbyname()
|
||||||
*/
|
*/
|
||||||
if (is_ip_addr || resolver->res == NULL) {
|
if (ip_addr_ver || resolver->res == NULL) {
|
||||||
|
|
||||||
pj_in_addr ip_addr;
|
pj_in_addr ip_addr;
|
||||||
|
int af;
|
||||||
|
pj_addrinfo ai;
|
||||||
|
unsigned count;
|
||||||
pj_uint16_t srv_port;
|
pj_uint16_t srv_port;
|
||||||
|
|
||||||
if (!is_ip_addr) {
|
if (!ip_addr_ver) {
|
||||||
PJ_LOG(5,(THIS_FILE,
|
PJ_LOG(5,(THIS_FILE,
|
||||||
"DNS resolver not available, target '%.*s:%d' type=%s "
|
"DNS resolver not available, target '%.*s:%d' type=%s "
|
||||||
"will be resolved with gethostbyname()",
|
"will be resolved with gethostbyname()",
|
||||||
|
@ -238,14 +249,27 @@ PJ_DEF(void) pjsip_resolve( pjsip_resolver_t *resolver,
|
||||||
srv_port = (pj_uint16_t)target->addr.port;
|
srv_port = (pj_uint16_t)target->addr.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This will eventually call pj_gethostbyname() if the host
|
if (type & PJSIP_TRANSPORT_IPV6) {
|
||||||
* is not an IP address.
|
af = pj_AF_INET6();
|
||||||
*/
|
} else {
|
||||||
status = pj_sockaddr_in_init((pj_sockaddr_in*)&svr_addr.entry[0].addr,
|
af = pj_AF_INET();
|
||||||
&target->addr.host, srv_port);
|
}
|
||||||
|
|
||||||
|
/* Resolve */
|
||||||
|
count = 1;
|
||||||
|
status = pj_getaddrinfo(af, &target->addr.host, &count, &ai);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
|
svr_addr.entry[0].addr.addr.sa_family = (pj_uint16_t)af;
|
||||||
|
pj_memcpy(&svr_addr.entry[0].addr, &ai.ai_addr, sizeof(pj_sockaddr));
|
||||||
|
|
||||||
|
if (af == pj_AF_INET6()) {
|
||||||
|
svr_addr.entry[0].addr.ipv6.sin6_port = pj_htons(srv_port);
|
||||||
|
} else {
|
||||||
|
svr_addr.entry[0].addr.ipv4.sin_port = pj_htons(srv_port);
|
||||||
|
}
|
||||||
|
|
||||||
/* Call the callback. */
|
/* Call the callback. */
|
||||||
ip_addr = ((pj_sockaddr_in*)&svr_addr.entry[0].addr)->sin_addr;
|
ip_addr = ((pj_sockaddr_in*)&svr_addr.entry[0].addr)->sin_addr;
|
||||||
PJ_LOG(5,(THIS_FILE,
|
PJ_LOG(5,(THIS_FILE,
|
||||||
|
|
|
@ -93,22 +93,103 @@ struct pjsip_tpmgr
|
||||||
*/
|
*/
|
||||||
struct transport_names_t
|
struct transport_names_t
|
||||||
{
|
{
|
||||||
pjsip_transport_type_e type;
|
pjsip_transport_type_e type; /* Transport type */
|
||||||
pj_uint16_t port;
|
pj_uint16_t port; /* Default port number */
|
||||||
pj_str_t name;
|
pj_str_t name; /* Id tag */
|
||||||
unsigned flag;
|
const char *description; /* Longer description */
|
||||||
char name_buf[16];
|
unsigned flag; /* Flags */
|
||||||
|
char name_buf[16]; /* For user's transport */
|
||||||
} transport_names[16] =
|
} transport_names[16] =
|
||||||
{
|
{
|
||||||
{ PJSIP_TRANSPORT_UNSPECIFIED, 0, {"Unspecified", 11}, 0},
|
{
|
||||||
{ PJSIP_TRANSPORT_UDP, 5060, {"UDP", 3}, PJSIP_TRANSPORT_DATAGRAM},
|
PJSIP_TRANSPORT_UNSPECIFIED,
|
||||||
{ PJSIP_TRANSPORT_TCP, 5060, {"TCP", 3}, PJSIP_TRANSPORT_RELIABLE},
|
0,
|
||||||
{ PJSIP_TRANSPORT_TLS, 5061, {"TLS", 3}, PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE},
|
{"Unspecified", 11},
|
||||||
{ PJSIP_TRANSPORT_SCTP, 5060, {"SCTP", 4}, PJSIP_TRANSPORT_RELIABLE},
|
"Unspecified",
|
||||||
{ PJSIP_TRANSPORT_LOOP, 15060, {"LOOP", 4}, PJSIP_TRANSPORT_RELIABLE},
|
0
|
||||||
{ PJSIP_TRANSPORT_LOOP_DGRAM, 15060, {"LOOP-DGRAM", 10}, PJSIP_TRANSPORT_DATAGRAM},
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_UDP,
|
||||||
|
5060,
|
||||||
|
{"UDP", 3},
|
||||||
|
"UDP transport",
|
||||||
|
PJSIP_TRANSPORT_DATAGRAM
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_TCP,
|
||||||
|
5060,
|
||||||
|
{"TCP", 3},
|
||||||
|
"TCP transport",
|
||||||
|
PJSIP_TRANSPORT_RELIABLE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_TLS,
|
||||||
|
5061,
|
||||||
|
{"TLS", 3},
|
||||||
|
"TLS transport",
|
||||||
|
PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_SCTP,
|
||||||
|
5060,
|
||||||
|
{"SCTP", 4},
|
||||||
|
"SCTP transport",
|
||||||
|
PJSIP_TRANSPORT_RELIABLE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_LOOP,
|
||||||
|
15060,
|
||||||
|
{"LOOP", 4},
|
||||||
|
"Loopback transport",
|
||||||
|
PJSIP_TRANSPORT_RELIABLE
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_LOOP_DGRAM,
|
||||||
|
15060,
|
||||||
|
{"LOOP-DGRAM", 10},
|
||||||
|
"Loopback datagram transport",
|
||||||
|
PJSIP_TRANSPORT_DATAGRAM
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_UDP6,
|
||||||
|
5060,
|
||||||
|
{"UDP", 3},
|
||||||
|
"UDP IPv6 transport",
|
||||||
|
PJSIP_TRANSPORT_DATAGRAM
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PJSIP_TRANSPORT_TCP6,
|
||||||
|
5060,
|
||||||
|
{"TCP", 3},
|
||||||
|
"TCP IPv6 transport",
|
||||||
|
PJSIP_TRANSPORT_RELIABLE
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct transport_names_t *get_tpname(pjsip_transport_type_e type)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
|
||||||
|
if (transport_names[i].type == type)
|
||||||
|
return &transport_names[i];
|
||||||
|
}
|
||||||
|
pj_assert(!"Invalid transport type!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tools to get address string.
|
||||||
|
*/
|
||||||
|
static const char *addr_string(const pj_sockaddr_t *addr)
|
||||||
|
{
|
||||||
|
static char str[PJ_INET6_ADDRSTRLEN];
|
||||||
|
pj_inet_ntop(((const pj_sockaddr*)addr)->addr.sa_family,
|
||||||
|
pj_sockaddr_get_addr(addr),
|
||||||
|
str, sizeof(str));
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register new transport type to PJSIP.
|
* Register new transport type to PJSIP.
|
||||||
|
@ -153,12 +234,6 @@ PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_name(const pj_str_t
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
/* Sanity check.
|
|
||||||
* Check that transport_names[] are indexed on transport type.
|
|
||||||
*/
|
|
||||||
PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
|
|
||||||
PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);
|
|
||||||
|
|
||||||
if (name->slen == 0)
|
if (name->slen == 0)
|
||||||
return PJSIP_TRANSPORT_UNSPECIFIED;
|
return PJSIP_TRANSPORT_UNSPECIFIED;
|
||||||
|
|
||||||
|
@ -181,12 +256,6 @@ PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_flag(unsigned flag)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
/* Sanity check.
|
|
||||||
* Check that transport_names[] are indexed on transport type.
|
|
||||||
*/
|
|
||||||
PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
|
|
||||||
PJSIP_TRANSPORT_UDP, PJSIP_TRANSPORT_UNSPECIFIED);
|
|
||||||
|
|
||||||
/* Get the transport type for the specified flags. */
|
/* Get the transport type for the specified flags. */
|
||||||
for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
|
for (i=0; i<PJ_ARRAY_SIZE(transport_names); ++i) {
|
||||||
if (transport_names[i].flag == flag) {
|
if (transport_names[i].flag == flag) {
|
||||||
|
@ -198,19 +267,21 @@ PJ_DEF(pjsip_transport_type_e) pjsip_transport_get_type_from_flag(unsigned flag)
|
||||||
return PJSIP_TRANSPORT_UNSPECIFIED;
|
return PJSIP_TRANSPORT_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the socket address family of a given transport type.
|
||||||
|
*/
|
||||||
|
PJ_DEF(int) pjsip_transport_type_get_af(pjsip_transport_type_e type)
|
||||||
|
{
|
||||||
|
if (type | PJSIP_TRANSPORT_IPV6)
|
||||||
|
return pj_AF_INET6();
|
||||||
|
else
|
||||||
|
return pj_AF_INET();
|
||||||
|
}
|
||||||
|
|
||||||
PJ_DEF(unsigned) pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)
|
PJ_DEF(unsigned) pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)
|
||||||
{
|
{
|
||||||
/* Sanity check.
|
|
||||||
* Check that transport_names[] are indexed on transport type.
|
|
||||||
*/
|
|
||||||
PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
|
|
||||||
PJSIP_TRANSPORT_UDP, 0);
|
|
||||||
|
|
||||||
/* Check that argument is valid. */
|
|
||||||
PJ_ASSERT_RETURN((unsigned)type < PJ_ARRAY_SIZE(transport_names), 0);
|
|
||||||
|
|
||||||
/* Return transport flag. */
|
/* Return transport flag. */
|
||||||
return transport_names[type].flag;
|
return get_tpname(type)->flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -218,17 +289,8 @@ PJ_DEF(unsigned) pjsip_transport_get_flag_from_type(pjsip_transport_type_e type)
|
||||||
*/
|
*/
|
||||||
PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)
|
PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e type)
|
||||||
{
|
{
|
||||||
/* Sanity check.
|
|
||||||
* Check that transport_names[] are indexed on transport type.
|
|
||||||
*/
|
|
||||||
PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
|
|
||||||
PJSIP_TRANSPORT_UDP, 0);
|
|
||||||
|
|
||||||
/* Check that argument is valid. */
|
|
||||||
PJ_ASSERT_RETURN((unsigned)type < PJ_ARRAY_SIZE(transport_names), 5060);
|
|
||||||
|
|
||||||
/* Return the port. */
|
/* Return the port. */
|
||||||
return transport_names[type].port;
|
return get_tpname(type)->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -236,17 +298,17 @@ PJ_DEF(int) pjsip_transport_get_default_port_for_type(pjsip_transport_type_e typ
|
||||||
*/
|
*/
|
||||||
PJ_DEF(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e type)
|
PJ_DEF(const char*) pjsip_transport_get_type_name(pjsip_transport_type_e type)
|
||||||
{
|
{
|
||||||
/* Sanity check.
|
/* Return the name. */
|
||||||
* Check that transport_names[] are indexed on transport type.
|
return get_tpname(type)->name.ptr;
|
||||||
*/
|
}
|
||||||
PJ_ASSERT_RETURN(transport_names[PJSIP_TRANSPORT_UDP].type ==
|
|
||||||
PJSIP_TRANSPORT_UDP, "Unknown");
|
|
||||||
|
|
||||||
/* Check that argument is valid. */
|
/*
|
||||||
PJ_ASSERT_RETURN((unsigned)type<PJ_ARRAY_SIZE(transport_names), "Unknown");
|
* Get transport description.
|
||||||
|
*/
|
||||||
/* Return the port. */
|
PJ_DEF(const char*) pjsip_transport_get_type_desc(pjsip_transport_type_e type)
|
||||||
return transport_names[type].name.ptr;
|
{
|
||||||
|
/* Return the description. */
|
||||||
|
return get_tpname(type)->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -556,15 +618,12 @@ PJ_DEF(pj_status_t) pjsip_transport_send( pjsip_transport *tr,
|
||||||
tdata->tp_info.transport = tr;
|
tdata->tp_info.transport = tr;
|
||||||
pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
|
pj_memcpy(&tdata->tp_info.dst_addr, addr, addr_len);
|
||||||
tdata->tp_info.dst_addr_len = addr_len;
|
tdata->tp_info.dst_addr_len = addr_len;
|
||||||
if (((pj_sockaddr*)addr)->addr.sa_family == pj_AF_INET()) {
|
|
||||||
const char *str_addr;
|
pj_inet_ntop(((pj_sockaddr*)addr)->addr.sa_family,
|
||||||
str_addr = pj_inet_ntoa(((pj_sockaddr_in*)addr)->sin_addr);
|
pj_sockaddr_get_addr(addr),
|
||||||
pj_ansi_strcpy(tdata->tp_info.dst_name, str_addr);
|
tdata->tp_info.dst_name,
|
||||||
tdata->tp_info.dst_port = pj_ntohs(((pj_sockaddr_in*)addr)->sin_port);
|
sizeof(tdata->tp_info.dst_name));
|
||||||
} else {
|
tdata->tp_info.dst_port = pj_sockaddr_get_port(addr);
|
||||||
pj_ansi_strcpy(tdata->tp_info.dst_name, "<unknown>");
|
|
||||||
tdata->tp_info.dst_port = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Distribute to modules.
|
/* Distribute to modules.
|
||||||
* When the message reach mod_msg_print, the contents of the message will
|
* When the message reach mod_msg_print, the contents of the message will
|
||||||
|
@ -803,8 +862,8 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
|
||||||
TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d",
|
TRACE_((THIS_FILE,"Transport %s registered: type=%s, remote=%s:%d",
|
||||||
tp->obj_name,
|
tp->obj_name,
|
||||||
pjsip_transport_get_type_name(tp->key.type),
|
pjsip_transport_get_type_name(tp->key.type),
|
||||||
pj_inet_ntoa(((pj_sockaddr_in*)&tp->key.rem_addr)->sin_addr),
|
addr_string(&tp->key.rem_addr),
|
||||||
pj_ntohs(((pj_sockaddr_in*)&tp->key.rem_addr)->sin_port)));
|
pj_sockaddr_get_port(&tp->key.rem_addr)));
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
return PJ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1054,12 +1113,21 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
|
||||||
|
|
||||||
} else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
|
} else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
|
||||||
|
|
||||||
pj_sockaddr_in remote;
|
pj_sockaddr remote;
|
||||||
|
int addr_len;
|
||||||
pjsip_transport *tp;
|
pjsip_transport *tp;
|
||||||
|
|
||||||
pj_sockaddr_in_init(&remote, NULL, 0);
|
pj_bzero(&remote, sizeof(remote));
|
||||||
|
if (type & PJSIP_TRANSPORT_IPV6) {
|
||||||
|
addr_len = sizeof(pj_sockaddr_in6);
|
||||||
|
remote.addr.sa_family = pj_AF_INET6();
|
||||||
|
} else {
|
||||||
|
addr_len = sizeof(pj_sockaddr_in);
|
||||||
|
remote.addr.sa_family = pj_AF_INET();
|
||||||
|
}
|
||||||
|
|
||||||
status = pjsip_tpmgr_acquire_transport(tpmgr, type, &remote,
|
status = pjsip_tpmgr_acquire_transport(tpmgr, type, &remote,
|
||||||
sizeof(remote), NULL, &tp);
|
addr_len, NULL, &tp);
|
||||||
|
|
||||||
if (status == PJ_SUCCESS) {
|
if (status == PJ_SUCCESS) {
|
||||||
pj_strdup(pool, ip_addr, &tp->local_name.host);
|
pj_strdup(pool, ip_addr, &tp->local_name.host);
|
||||||
|
@ -1381,8 +1449,8 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
|
||||||
|
|
||||||
TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d",
|
TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d",
|
||||||
pjsip_transport_get_type_name(type),
|
pjsip_transport_get_type_name(type),
|
||||||
pj_inet_ntoa(((pj_sockaddr_in*)remote)->sin_addr),
|
addr_string(remote),
|
||||||
pj_ntohs(((pj_sockaddr_in*)remote)->sin_port)));
|
pj_sockaddr_get_port(remote)));
|
||||||
|
|
||||||
pj_lock_acquire(mgr->lock);
|
pj_lock_acquire(mgr->lock);
|
||||||
|
|
||||||
|
@ -1462,24 +1530,23 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
|
||||||
if (type == PJSIP_TRANSPORT_LOOP ||
|
if (type == PJSIP_TRANSPORT_LOOP ||
|
||||||
type == PJSIP_TRANSPORT_LOOP_DGRAM)
|
type == PJSIP_TRANSPORT_LOOP_DGRAM)
|
||||||
{
|
{
|
||||||
pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.rem_addr;
|
pj_sockaddr *addr = &key.rem_addr;
|
||||||
|
|
||||||
pj_bzero(addr, sizeof(pj_sockaddr_in));
|
pj_bzero(addr, addr_len);
|
||||||
key_len = sizeof(key.type) + sizeof(pj_sockaddr_in);
|
key_len = sizeof(key.type) + addr_len;
|
||||||
transport = (pjsip_transport*)
|
transport = (pjsip_transport*)
|
||||||
pj_hash_get(mgr->table, &key, key_len, NULL);
|
pj_hash_get(mgr->table, &key, key_len, NULL);
|
||||||
}
|
}
|
||||||
/* For datagram INET transports, try lookup with zero address.
|
/* For datagram transports, try lookup with zero address.
|
||||||
*/
|
*/
|
||||||
else if ((flag & PJSIP_TRANSPORT_DATAGRAM) &&
|
else if (flag & PJSIP_TRANSPORT_DATAGRAM)
|
||||||
(remote_addr->addr.sa_family == pj_AF_INET()))
|
|
||||||
{
|
{
|
||||||
pj_sockaddr_in *addr = (pj_sockaddr_in*)&key.rem_addr;
|
pj_sockaddr *addr = &key.rem_addr;
|
||||||
|
|
||||||
pj_bzero(addr, sizeof(pj_sockaddr_in));
|
pj_bzero(addr, addr_len);
|
||||||
addr->sin_family = pj_AF_INET();
|
addr->addr.sa_family = remote_addr->addr.sa_family;
|
||||||
|
|
||||||
key_len = sizeof(key.type) + sizeof(pj_sockaddr_in);
|
key_len = sizeof(key.type) + addr_len;
|
||||||
transport = (pjsip_transport*)
|
transport = (pjsip_transport*)
|
||||||
pj_hash_get(mgr->table, &key, key_len, NULL);
|
pj_hash_get(mgr->table, &key, key_len, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,13 +289,13 @@ PJ_DEF(pj_status_t) pjsip_tcp_transport_start2(pjsip_endpoint *endpt,
|
||||||
* interface address as the transport's address.
|
* interface address as the transport's address.
|
||||||
*/
|
*/
|
||||||
if (listener_addr->sin_addr.s_addr == 0) {
|
if (listener_addr->sin_addr.s_addr == 0) {
|
||||||
pj_in_addr hostip;
|
pj_sockaddr hostip;
|
||||||
|
|
||||||
status = pj_gethostip(&hostip);
|
status = pj_gethostip(pj_AF_INET(), &hostip);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
listener_addr->sin_addr = hostip;
|
listener_addr->sin_addr.s_addr = hostip.ipv4.sin_addr.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the address name */
|
/* Save the address name */
|
||||||
|
|
|
@ -142,16 +142,23 @@ static void udp_on_read_complete( pj_ioqueue_key_t *key,
|
||||||
*/
|
*/
|
||||||
if (bytes_read > MIN_SIZE) {
|
if (bytes_read > MIN_SIZE) {
|
||||||
pj_size_t size_eaten;
|
pj_size_t size_eaten;
|
||||||
const pj_sockaddr_in *src_addr =
|
const pj_sockaddr *src_addr = &rdata->pkt_info.src_addr;
|
||||||
(pj_sockaddr_in*)&rdata->pkt_info.src_addr;
|
|
||||||
|
|
||||||
/* Init pkt_info part. */
|
/* Init pkt_info part. */
|
||||||
rdata->pkt_info.len = bytes_read;
|
rdata->pkt_info.len = bytes_read;
|
||||||
rdata->pkt_info.zero = 0;
|
rdata->pkt_info.zero = 0;
|
||||||
pj_gettimeofday(&rdata->pkt_info.timestamp);
|
pj_gettimeofday(&rdata->pkt_info.timestamp);
|
||||||
pj_ansi_strcpy(rdata->pkt_info.src_name,
|
if (src_addr->addr.sa_family == pj_AF_INET()) {
|
||||||
pj_inet_ntoa(src_addr->sin_addr));
|
pj_ansi_strcpy(rdata->pkt_info.src_name,
|
||||||
rdata->pkt_info.src_port = pj_ntohs(src_addr->sin_port);
|
pj_inet_ntoa(src_addr->ipv4.sin_addr));
|
||||||
|
rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv4.sin_port);
|
||||||
|
} else {
|
||||||
|
pj_inet_ntop(pj_AF_INET6(),
|
||||||
|
pj_sockaddr_get_addr(&rdata->pkt_info.src_addr),
|
||||||
|
rdata->pkt_info.src_name,
|
||||||
|
sizeof(rdata->pkt_info.src_name));
|
||||||
|
rdata->pkt_info.src_port = pj_ntohs(src_addr->ipv6.sin6_port);
|
||||||
|
}
|
||||||
|
|
||||||
size_eaten =
|
size_eaten =
|
||||||
pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr,
|
pjsip_tpmgr_receive_packet(rdata->tp_info.transport->tpmgr,
|
||||||
|
@ -412,23 +419,32 @@ static pj_status_t udp_shutdown(pjsip_transport *transport)
|
||||||
|
|
||||||
|
|
||||||
/* Create socket */
|
/* Create socket */
|
||||||
static pj_status_t create_socket(const pj_sockaddr_in *local_a,
|
static pj_status_t create_socket(int af, const pj_sockaddr_t *local_a,
|
||||||
pj_sock_t *p_sock)
|
int addr_len, pj_sock_t *p_sock)
|
||||||
{
|
{
|
||||||
pj_sock_t sock;
|
pj_sock_t sock;
|
||||||
pj_sockaddr_in tmp_addr;
|
pj_sockaddr_in tmp_addr;
|
||||||
|
pj_sockaddr_in6 tmp_addr6;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock);
|
status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (local_a == NULL) {
|
if (local_a == NULL) {
|
||||||
pj_sockaddr_in_init(&tmp_addr, NULL, 0);
|
if (af == pj_AF_INET6()) {
|
||||||
local_a = &tmp_addr;
|
pj_bzero(&tmp_addr6, sizeof(tmp_addr6));
|
||||||
|
tmp_addr6.sin6_family = (pj_uint16_t)af;
|
||||||
|
local_a = &tmp_addr6;
|
||||||
|
addr_len = sizeof(tmp_addr6);
|
||||||
|
} else {
|
||||||
|
pj_sockaddr_in_init(&tmp_addr, NULL, 0);
|
||||||
|
local_a = &tmp_addr;
|
||||||
|
addr_len = sizeof(tmp_addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = pj_sock_bind(sock, local_a, sizeof(*local_a));
|
status = pj_sock_bind(sock, local_a, addr_len);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
return status;
|
return status;
|
||||||
|
@ -442,9 +458,10 @@ static pj_status_t create_socket(const pj_sockaddr_in *local_a,
|
||||||
/* Generate transport's published address */
|
/* Generate transport's published address */
|
||||||
static pj_status_t get_published_name(pj_sock_t sock,
|
static pj_status_t get_published_name(pj_sock_t sock,
|
||||||
char hostbuf[],
|
char hostbuf[],
|
||||||
|
int hostbufsz,
|
||||||
pjsip_host_port *bound_name)
|
pjsip_host_port *bound_name)
|
||||||
{
|
{
|
||||||
pj_sockaddr_in tmp_addr;
|
pj_sockaddr tmp_addr;
|
||||||
int addr_len;
|
int addr_len;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
|
@ -454,25 +471,36 @@ static pj_status_t get_published_name(pj_sock_t sock,
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
bound_name->host.ptr = hostbuf;
|
bound_name->host.ptr = hostbuf;
|
||||||
bound_name->port = pj_ntohs(tmp_addr.sin_port);
|
if (tmp_addr.addr.sa_family == pj_AF_INET()) {
|
||||||
|
bound_name->port = pj_ntohs(tmp_addr.ipv4.sin_port);
|
||||||
|
|
||||||
/* If bound address specifies "0.0.0.0", get the IP address
|
/* If bound address specifies "0.0.0.0", get the IP address
|
||||||
* of local hostname.
|
* of local hostname.
|
||||||
*/
|
*/
|
||||||
if (tmp_addr.sin_addr.s_addr == PJ_INADDR_ANY) {
|
if (tmp_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) {
|
||||||
pj_in_addr hostip;
|
pj_sockaddr hostip;
|
||||||
|
|
||||||
status = pj_gethostip(&hostip);
|
status = pj_gethostip(pj_AF_INET(), &hostip);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip.ipv4.sin_addr));
|
||||||
|
} else {
|
||||||
|
/* Otherwise use bound address. */
|
||||||
|
pj_strcpy2(&bound_name->host,
|
||||||
|
pj_inet_ntoa(tmp_addr.ipv4.sin_addr));
|
||||||
|
status = PJ_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
pj_strcpy2(&bound_name->host, pj_inet_ntoa(hostip));
|
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise use bound address. */
|
bound_name->port = pj_ntohs(tmp_addr.ipv6.sin6_port);
|
||||||
pj_strcpy2(&bound_name->host, pj_inet_ntoa(tmp_addr.sin_addr));
|
status = pj_inet_ntop(tmp_addr.addr.sa_family,
|
||||||
|
pj_sockaddr_get_addr(&tmp_addr),
|
||||||
|
hostbuf, hostbufsz);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the published address of the transport */
|
/* Set the published address of the transport */
|
||||||
|
@ -480,6 +508,7 @@ static void udp_set_pub_name(struct udp_transport *tp,
|
||||||
const pjsip_host_port *a_name)
|
const pjsip_host_port *a_name)
|
||||||
{
|
{
|
||||||
enum { INFO_LEN = 80 };
|
enum { INFO_LEN = 80 };
|
||||||
|
char local_addr[PJ_INET6_ADDRSTRLEN];
|
||||||
|
|
||||||
pj_assert(a_name->host.slen != 0);
|
pj_assert(a_name->host.slen != 0);
|
||||||
pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host,
|
pj_strdup_with_null(tp->base.pool, &tp->base.local_name.host,
|
||||||
|
@ -490,10 +519,15 @@ static void udp_set_pub_name(struct udp_transport *tp,
|
||||||
if (tp->base.info == NULL) {
|
if (tp->base.info == NULL) {
|
||||||
tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN);
|
tp->base.info = (char*) pj_pool_alloc(tp->base.pool, INFO_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pj_inet_ntop(tp->base.local_addr.addr.sa_family,
|
||||||
|
pj_sockaddr_get_addr(&tp->base.local_addr),
|
||||||
|
local_addr, sizeof(local_addr));
|
||||||
|
|
||||||
pj_ansi_snprintf(
|
pj_ansi_snprintf(
|
||||||
tp->base.info, INFO_LEN, "udp %s:%d [published as %s:%d]",
|
tp->base.info, INFO_LEN, "udp %s:%d [published as %s:%d]",
|
||||||
pj_inet_ntoa(((pj_sockaddr_in*)&tp->base.local_addr)->sin_addr),
|
local_addr,
|
||||||
pj_ntohs(((pj_sockaddr_in*)&tp->base.local_addr)->sin_port),
|
pj_sockaddr_get_port(&tp->base.local_addr),
|
||||||
tp->base.local_name.host.ptr,
|
tp->base.local_name.host.ptr,
|
||||||
tp->base.local_name.port);
|
tp->base.local_name.port);
|
||||||
}
|
}
|
||||||
|
@ -595,22 +629,30 @@ static pj_status_t start_async_read(struct udp_transport *tp)
|
||||||
*
|
*
|
||||||
* Attach UDP socket and start transport.
|
* Attach UDP socket and start transport.
|
||||||
*/
|
*/
|
||||||
PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
static pj_status_t transport_attach( pjsip_endpoint *endpt,
|
||||||
pj_sock_t sock,
|
pjsip_transport_type_e type,
|
||||||
const pjsip_host_port *a_name,
|
pj_sock_t sock,
|
||||||
unsigned async_cnt,
|
const pjsip_host_port *a_name,
|
||||||
pjsip_transport **p_transport)
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport)
|
||||||
{
|
{
|
||||||
pj_pool_t *pool;
|
pj_pool_t *pool;
|
||||||
struct udp_transport *tp;
|
struct udp_transport *tp;
|
||||||
|
const char *format;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,
|
PJ_ASSERT_RETURN(endpt && sock!=PJ_INVALID_SOCKET && a_name && async_cnt>0,
|
||||||
PJ_EINVAL);
|
PJ_EINVAL);
|
||||||
|
|
||||||
|
/* Object name. */
|
||||||
|
if (type & PJSIP_TRANSPORT_IPV6)
|
||||||
|
format = "udpv6%p";
|
||||||
|
else
|
||||||
|
format = "udp%p";
|
||||||
|
|
||||||
/* Create pool. */
|
/* Create pool. */
|
||||||
pool = pjsip_endpt_create_pool(endpt, "udp%p", PJSIP_POOL_LEN_TRANSPORT,
|
pool = pjsip_endpt_create_pool(endpt, format, PJSIP_POOL_LEN_TRANSPORT,
|
||||||
PJSIP_POOL_INC_TRANSPORT);
|
PJSIP_POOL_INC_TRANSPORT);
|
||||||
if (!pool)
|
if (!pool)
|
||||||
return PJ_ENOMEM;
|
return PJ_ENOMEM;
|
||||||
|
@ -621,9 +663,7 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
||||||
/* Save pool. */
|
/* Save pool. */
|
||||||
tp->base.pool = pool;
|
tp->base.pool = pool;
|
||||||
|
|
||||||
/* Object name. */
|
pj_memcpy(tp->base.obj_name, pool->obj_name, PJ_MAX_OBJ_NAME);
|
||||||
pj_ansi_snprintf(tp->base.obj_name, sizeof(tp->base.obj_name),
|
|
||||||
"udp%p", tp);
|
|
||||||
|
|
||||||
/* Init reference counter. */
|
/* Init reference counter. */
|
||||||
status = pj_atomic_create(pool, 0, &tp->base.ref_cnt);
|
status = pj_atomic_create(pool, 0, &tp->base.ref_cnt);
|
||||||
|
@ -631,25 +671,27 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
/* Init lock. */
|
/* Init lock. */
|
||||||
status = pj_lock_create_recursive_mutex(pool, "udp%p", &tp->base.lock);
|
status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
|
||||||
|
&tp->base.lock);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
/* Set type. */
|
/* Set type. */
|
||||||
tp->base.key.type = PJSIP_TRANSPORT_UDP;
|
tp->base.key.type = type;
|
||||||
|
|
||||||
/* Remote address is left zero (except the family) */
|
/* Remote address is left zero (except the family) */
|
||||||
tp->base.key.rem_addr.addr.sa_family = pj_AF_INET();
|
tp->base.key.rem_addr.addr.sa_family = (pj_uint16_t)
|
||||||
|
((type & PJSIP_TRANSPORT_IPV6) ? pj_AF_INET6() : pj_AF_INET());
|
||||||
|
|
||||||
/* Type name. */
|
/* Type name. */
|
||||||
tp->base.type_name = "UDP";
|
tp->base.type_name = "UDP";
|
||||||
|
|
||||||
/* Transport flag */
|
/* Transport flag */
|
||||||
tp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_UDP);
|
tp->base.flag = pjsip_transport_get_flag_from_type(type);
|
||||||
|
|
||||||
|
|
||||||
/* Length of addressess. */
|
/* Length of addressess. */
|
||||||
tp->base.addr_len = sizeof(pj_sockaddr_in);
|
tp->base.addr_len = sizeof(tp->base.local_addr);
|
||||||
|
|
||||||
/* Init local address. */
|
/* Init local address. */
|
||||||
status = pj_sock_getsockname(sock, &tp->base.local_addr,
|
status = pj_sock_getsockname(sock, &tp->base.local_addr,
|
||||||
|
@ -658,7 +700,10 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
/* Init remote name. */
|
/* Init remote name. */
|
||||||
tp->base.remote_name.host = pj_str("0.0.0.0");
|
if (type == PJSIP_TRANSPORT_UDP)
|
||||||
|
tp->base.remote_name.host = pj_str("0.0.0.0");
|
||||||
|
else
|
||||||
|
tp->base.remote_name.host = pj_str("::0");
|
||||||
tp->base.remote_name.port = 0;
|
tp->base.remote_name.port = 0;
|
||||||
|
|
||||||
/* Set endpoint. */
|
/* Set endpoint. */
|
||||||
|
@ -723,7 +768,8 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
||||||
*p_transport = &tp->base;
|
*p_transport = &tp->base;
|
||||||
|
|
||||||
PJ_LOG(4,(tp->base.obj_name,
|
PJ_LOG(4,(tp->base.obj_name,
|
||||||
"SIP UDP transport started, published address is %.*s:%d",
|
"SIP %s started, published address is %.*s:%d",
|
||||||
|
pjsip_transport_get_type_desc((pjsip_transport_type_e)tp->base.key.type),
|
||||||
(int)tp->base.local_name.host.slen,
|
(int)tp->base.local_name.host.slen,
|
||||||
tp->base.local_name.host.ptr,
|
tp->base.local_name.host.ptr,
|
||||||
tp->base.local_name.port));
|
tp->base.local_name.port));
|
||||||
|
@ -735,6 +781,28 @@ on_error:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PJ_DEF(pj_status_t) pjsip_udp_transport_attach( pjsip_endpoint *endpt,
|
||||||
|
pj_sock_t sock,
|
||||||
|
const pjsip_host_port *a_name,
|
||||||
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport)
|
||||||
|
{
|
||||||
|
return transport_attach(endpt, PJSIP_TRANSPORT_UDP, sock, a_name,
|
||||||
|
async_cnt, p_transport);
|
||||||
|
}
|
||||||
|
|
||||||
|
PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt,
|
||||||
|
pjsip_transport_type_e type,
|
||||||
|
pj_sock_t sock,
|
||||||
|
const pjsip_host_port *a_name,
|
||||||
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport)
|
||||||
|
{
|
||||||
|
return transport_attach(endpt, type, sock, a_name,
|
||||||
|
async_cnt, p_transport);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pjsip_udp_transport_start()
|
* pjsip_udp_transport_start()
|
||||||
*
|
*
|
||||||
|
@ -748,12 +816,13 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
|
||||||
{
|
{
|
||||||
pj_sock_t sock;
|
pj_sock_t sock;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
char addr_buf[16];
|
char addr_buf[PJ_INET6_ADDRSTRLEN];
|
||||||
pjsip_host_port bound_name;
|
pjsip_host_port bound_name;
|
||||||
|
|
||||||
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
|
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
|
||||||
|
|
||||||
status = create_socket(local_a, &sock);
|
status = create_socket(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in),
|
||||||
|
&sock);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -761,7 +830,8 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
|
||||||
/* Address name is not specified.
|
/* Address name is not specified.
|
||||||
* Build a name based on bound address.
|
* Build a name based on bound address.
|
||||||
*/
|
*/
|
||||||
status = get_published_name(sock, addr_buf, &bound_name);
|
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
|
||||||
|
&bound_name);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
return status;
|
return status;
|
||||||
|
@ -775,6 +845,47 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pjsip_udp_transport_start()
|
||||||
|
*
|
||||||
|
* Create a UDP socket in the specified address and start a transport.
|
||||||
|
*/
|
||||||
|
PJ_DEF(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt,
|
||||||
|
const pj_sockaddr_in6 *local_a,
|
||||||
|
const pjsip_host_port *a_name,
|
||||||
|
unsigned async_cnt,
|
||||||
|
pjsip_transport **p_transport)
|
||||||
|
{
|
||||||
|
pj_sock_t sock;
|
||||||
|
pj_status_t status;
|
||||||
|
char addr_buf[PJ_INET_ADDRSTRLEN];
|
||||||
|
pjsip_host_port bound_name;
|
||||||
|
|
||||||
|
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
|
||||||
|
|
||||||
|
status = create_socket(pj_AF_INET6(), local_a, sizeof(pj_sockaddr_in6),
|
||||||
|
&sock);
|
||||||
|
if (status != PJ_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (a_name == NULL) {
|
||||||
|
/* Address name is not specified.
|
||||||
|
* Build a name based on bound address.
|
||||||
|
*/
|
||||||
|
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
|
||||||
|
&bound_name);
|
||||||
|
if (status != PJ_SUCCESS) {
|
||||||
|
pj_sock_close(sock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_name = &bound_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt,
|
||||||
|
p_transport);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve the internal socket handle used by the UDP transport.
|
* Retrieve the internal socket handle used by the UDP transport.
|
||||||
*/
|
*/
|
||||||
|
@ -869,7 +980,7 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
|
||||||
tp = (struct udp_transport*) transport;
|
tp = (struct udp_transport*) transport;
|
||||||
|
|
||||||
if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
|
if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
|
||||||
char addr_buf[16];
|
char addr_buf[PJ_INET_ADDRSTRLEN];
|
||||||
pjsip_host_port bound_name;
|
pjsip_host_port bound_name;
|
||||||
|
|
||||||
/* Request to recreate transport */
|
/* Request to recreate transport */
|
||||||
|
@ -890,7 +1001,8 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
|
||||||
|
|
||||||
/* Create the socket if it's not specified */
|
/* Create the socket if it's not specified */
|
||||||
if (sock == PJ_INVALID_SOCKET) {
|
if (sock == PJ_INVALID_SOCKET) {
|
||||||
status = create_socket(local, &sock);
|
status = create_socket(pj_AF_INET(), local,
|
||||||
|
sizeof(pj_sockaddr_in), &sock);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -899,7 +1011,8 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
|
||||||
* from the bound address.
|
* from the bound address.
|
||||||
*/
|
*/
|
||||||
if (a_name == NULL) {
|
if (a_name == NULL) {
|
||||||
status = get_published_name(sock, addr_buf, &bound_name);
|
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
|
||||||
|
&bound_name);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -1181,18 +1181,33 @@ PJ_DEF(pj_pool_factory*) pjsua_get_pool_factory(void)
|
||||||
* PJSUA SIP Transport API.
|
* PJSUA SIP Transport API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tools to get address string.
|
||||||
|
*/
|
||||||
|
static const char *addr_string(const pj_sockaddr_t *addr)
|
||||||
|
{
|
||||||
|
static char str[128];
|
||||||
|
str[0] = '\0';
|
||||||
|
pj_inet_ntop(((const pj_sockaddr*)addr)->addr.sa_family,
|
||||||
|
pj_sockaddr_get_addr(addr),
|
||||||
|
str, sizeof(str));
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create and initialize SIP socket (and possibly resolve public
|
* Create and initialize SIP socket (and possibly resolve public
|
||||||
* address via STUN, depending on config).
|
* address via STUN, depending on config).
|
||||||
*/
|
*/
|
||||||
static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
static pj_status_t create_sip_udp_sock(int af,
|
||||||
|
const pj_str_t *bind_param,
|
||||||
int port,
|
int port,
|
||||||
pj_sock_t *p_sock,
|
pj_sock_t *p_sock,
|
||||||
pj_sockaddr_in *p_pub_addr)
|
pj_sockaddr *p_pub_addr)
|
||||||
{
|
{
|
||||||
char ip_addr[32];
|
char stun_ip_addr[PJ_INET6_ADDRSTRLEN];
|
||||||
pj_str_t stun_srv;
|
pj_str_t stun_srv;
|
||||||
pj_sock_t sock;
|
pj_sock_t sock;
|
||||||
|
pj_sockaddr bind_addr;
|
||||||
pj_status_t status;
|
pj_status_t status;
|
||||||
|
|
||||||
/* Make sure STUN server resolution has completed */
|
/* Make sure STUN server resolution has completed */
|
||||||
|
@ -1202,14 +1217,27 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock);
|
/* Initialize bound address */
|
||||||
|
if (bind_param->slen) {
|
||||||
|
status = pj_sockaddr_init(af, &bind_addr, bind_param,
|
||||||
|
(pj_uint16_t)port);
|
||||||
|
if (status != PJ_SUCCESS) {
|
||||||
|
pjsua_perror(THIS_FILE,
|
||||||
|
"Unable to resolve transport bound address",
|
||||||
|
status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pj_sockaddr_init(af, &bind_addr, NULL, (pj_uint16_t)port);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE, "socket() error", status);
|
pjsua_perror(THIS_FILE, "socket() error", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = pj_sock_bind_in(sock, pj_ntohl(bound_addr.s_addr),
|
status = pj_sock_bind(sock, &bind_addr, sizeof(bind_addr));
|
||||||
(pj_uint16_t)port);
|
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE, "bind() error", status);
|
pjsua_perror(THIS_FILE, "bind() error", status);
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
|
@ -1218,7 +1246,7 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
||||||
|
|
||||||
/* If port is zero, get the bound port */
|
/* If port is zero, get the bound port */
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
pj_sockaddr_in bound_addr;
|
pj_sockaddr bound_addr;
|
||||||
int namelen = sizeof(bound_addr);
|
int namelen = sizeof(bound_addr);
|
||||||
status = pj_sock_getsockname(sock, &bound_addr, &namelen);
|
status = pj_sock_getsockname(sock, &bound_addr, &namelen);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
|
@ -1227,12 +1255,12 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = pj_ntohs(bound_addr.sin_port);
|
port = pj_sockaddr_get_port(&bound_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pjsua_var.stun_srv.addr.sa_family != 0) {
|
if (pjsua_var.stun_srv.addr.sa_family != 0) {
|
||||||
pj_ansi_strcpy(ip_addr,pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
|
pj_ansi_strcpy(stun_ip_addr,pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
|
||||||
stun_srv = pj_str(ip_addr);
|
stun_srv = pj_str(stun_ip_addr);
|
||||||
} else {
|
} else {
|
||||||
stun_srv.slen = 0;
|
stun_srv.slen = 0;
|
||||||
}
|
}
|
||||||
|
@ -1240,22 +1268,28 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
||||||
/* Get the published address, either by STUN or by resolving
|
/* Get the published address, either by STUN or by resolving
|
||||||
* the name of local host.
|
* the name of local host.
|
||||||
*/
|
*/
|
||||||
if (p_pub_addr->sin_addr.s_addr != 0) {
|
if (pj_sockaddr_has_addr(p_pub_addr)) {
|
||||||
/*
|
/*
|
||||||
* Public address is already specified, no need to resolve the
|
* Public address is already specified, no need to resolve the
|
||||||
* address, only set the port.
|
* address, only set the port.
|
||||||
*/
|
*/
|
||||||
if (p_pub_addr->sin_port == 0)
|
if (pj_sockaddr_get_port(p_pub_addr) == 0)
|
||||||
p_pub_addr->sin_port = pj_htons((pj_uint16_t)port);
|
pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
|
||||||
|
|
||||||
} else if (stun_srv.slen) {
|
} else if (stun_srv.slen) {
|
||||||
/*
|
/*
|
||||||
* STUN is specified, resolve the address with STUN.
|
* STUN is specified, resolve the address with STUN.
|
||||||
*/
|
*/
|
||||||
|
if (af != pj_AF_INET()) {
|
||||||
|
pjsua_perror(THIS_FILE, "Cannot use STUN", PJ_EAFNOTSUP);
|
||||||
|
pj_sock_close(sock);
|
||||||
|
return PJ_EAFNOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
status = pjstun_get_mapped_addr(&pjsua_var.cp.factory, 1, &sock,
|
status = pjstun_get_mapped_addr(&pjsua_var.cp.factory, 1, &sock,
|
||||||
&stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),
|
&stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),
|
||||||
&stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),
|
&stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port),
|
||||||
p_pub_addr);
|
&p_pub_addr->ipv4);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE, "Error contacting STUN server", status);
|
pjsua_perror(THIS_FILE, "Error contacting STUN server", status);
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
|
@ -1263,25 +1297,24 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
pj_bzero(p_pub_addr, sizeof(pj_sockaddr));
|
||||||
|
|
||||||
pj_bzero(p_pub_addr, sizeof(pj_sockaddr_in));
|
status = pj_gethostip(af, p_pub_addr);
|
||||||
|
|
||||||
status = pj_gethostip(&p_pub_addr->sin_addr);
|
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE, "Unable to get local host IP", status);
|
pjsua_perror(THIS_FILE, "Unable to get local host IP", status);
|
||||||
pj_sock_close(sock);
|
pj_sock_close(sock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
p_pub_addr->sin_family = pj_AF_INET();
|
p_pub_addr->addr.sa_family = (pj_uint16_t)af;
|
||||||
p_pub_addr->sin_port = pj_htons((pj_uint16_t)port);
|
pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
|
||||||
}
|
}
|
||||||
|
|
||||||
*p_sock = sock;
|
*p_sock = sock;
|
||||||
|
|
||||||
PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
|
PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
|
||||||
pj_inet_ntoa(p_pub_addr->sin_addr),
|
addr_string(p_pub_addr),
|
||||||
(int)pj_ntohs(p_pub_addr->sin_port)));
|
(int)pj_sockaddr_get_port(p_pub_addr)));
|
||||||
|
|
||||||
return PJ_SUCCESS;
|
return PJ_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1313,14 +1346,14 @@ PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the transport */
|
/* Create the transport */
|
||||||
if (type == PJSIP_TRANSPORT_UDP) {
|
if (type & PJSIP_TRANSPORT_UDP) {
|
||||||
/*
|
/*
|
||||||
* Create UDP transport.
|
* Create UDP transport (IPv4 or IPv6).
|
||||||
*/
|
*/
|
||||||
pjsua_transport_config config;
|
pjsua_transport_config config;
|
||||||
|
char hostbuf[PJ_INET6_ADDRSTRLEN];
|
||||||
pj_sock_t sock = PJ_INVALID_SOCKET;
|
pj_sock_t sock = PJ_INVALID_SOCKET;
|
||||||
pj_sockaddr_in bound_addr;
|
pj_sockaddr pub_addr;
|
||||||
pj_sockaddr_in pub_addr;
|
|
||||||
pjsip_host_port addr_name;
|
pjsip_host_port addr_name;
|
||||||
|
|
||||||
/* Supply default config if it's not specified */
|
/* Supply default config if it's not specified */
|
||||||
|
@ -1329,22 +1362,12 @@ PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
|
||||||
cfg = &config;
|
cfg = &config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize bound address, if any */
|
|
||||||
bound_addr.sin_addr.s_addr = PJ_INADDR_ANY;
|
|
||||||
if (cfg->bound_addr.slen) {
|
|
||||||
status = pj_sockaddr_in_set_str_addr(&bound_addr,&cfg->bound_addr);
|
|
||||||
if (status != PJ_SUCCESS) {
|
|
||||||
pjsua_perror(THIS_FILE,
|
|
||||||
"Unable to resolve transport bound address",
|
|
||||||
status);
|
|
||||||
goto on_return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the public address from the config, if any */
|
/* Initialize the public address from the config, if any */
|
||||||
pj_sockaddr_in_init(&pub_addr, NULL, (pj_uint16_t)cfg->port);
|
pj_sockaddr_init(pjsip_transport_type_get_af(type), &pub_addr,
|
||||||
|
NULL, (pj_uint16_t)cfg->port);
|
||||||
if (cfg->public_addr.slen) {
|
if (cfg->public_addr.slen) {
|
||||||
status = pj_sockaddr_in_set_str_addr(&pub_addr, &cfg->public_addr);
|
status = pj_sockaddr_set_str_addr(pjsip_transport_type_get_af(type),
|
||||||
|
&pub_addr, &cfg->public_addr);
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE,
|
pjsua_perror(THIS_FILE,
|
||||||
"Unable to resolve transport public address",
|
"Unable to resolve transport public address",
|
||||||
|
@ -1356,18 +1379,19 @@ PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
|
||||||
/* Create the socket and possibly resolve the address with STUN
|
/* Create the socket and possibly resolve the address with STUN
|
||||||
* (only when public address is not specified).
|
* (only when public address is not specified).
|
||||||
*/
|
*/
|
||||||
status = create_sip_udp_sock(bound_addr.sin_addr, cfg->port,
|
status = create_sip_udp_sock(pjsip_transport_type_get_af(type),
|
||||||
|
&cfg->bound_addr, cfg->port,
|
||||||
&sock, &pub_addr);
|
&sock, &pub_addr);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_return;
|
goto on_return;
|
||||||
|
|
||||||
addr_name.host = pj_str(pj_inet_ntoa(pub_addr.sin_addr));
|
pj_ansi_strcpy(hostbuf, addr_string(&pub_addr));
|
||||||
addr_name.port = pj_ntohs(pub_addr.sin_port);
|
addr_name.host = pj_str(hostbuf);
|
||||||
|
addr_name.port = pj_sockaddr_get_port(&pub_addr);
|
||||||
|
|
||||||
/* Create UDP transport */
|
/* Create UDP transport */
|
||||||
status = pjsip_udp_transport_attach( pjsua_var.endpt, sock,
|
status = pjsip_udp_transport_attach2(pjsua_var.endpt, type, sock,
|
||||||
&addr_name, 1,
|
&addr_name, 1, &tp);
|
||||||
&tp);
|
|
||||||
if (status != PJ_SUCCESS) {
|
if (status != PJ_SUCCESS) {
|
||||||
pjsua_perror(THIS_FILE, "Error creating SIP UDP transport",
|
pjsua_perror(THIS_FILE, "Error creating SIP UDP transport",
|
||||||
status);
|
status);
|
||||||
|
|
|
@ -346,15 +346,15 @@ static pj_status_t create_rtp_rtcp_sock(const pjsua_transport_config *cfg,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
pj_in_addr addr;
|
pj_sockaddr addr;
|
||||||
|
|
||||||
/* Get local IP address. */
|
/* Get local IP address. */
|
||||||
status = pj_gethostip(&addr);
|
status = pj_gethostip(pj_AF_INET(), &addr);
|
||||||
if (status != PJ_SUCCESS)
|
if (status != PJ_SUCCESS)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
for (i=0; i<2; ++i)
|
for (i=0; i<2; ++i)
|
||||||
mapped_addr[i].sin_addr = addr;
|
mapped_addr[i].sin_addr.s_addr = addr.ipv4.sin_addr.s_addr;
|
||||||
|
|
||||||
mapped_addr[0].sin_port=pj_htons((pj_uint16_t)next_rtp_port);
|
mapped_addr[0].sin_port=pj_htons((pj_uint16_t)next_rtp_port);
|
||||||
mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(next_rtp_port+1));
|
mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(next_rtp_port+1));
|
||||||
|
|
Loading…
Reference in New Issue