Close #1915: Added API pjsip_udp_transport_start2() that can create both IPv4 and IPv6 SIP UDP transports.

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5284 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Nanang Izzuddin 2016-05-10 05:13:57 +00:00
parent 4a4d95c8f4
commit 4123ec4ffd
2 changed files with 185 additions and 53 deletions

View File

@ -26,6 +26,7 @@
*/
#include <pjsip/sip_transport.h>
#include <pj/sock_qos.h>
PJ_BEGIN_DECL
@ -59,6 +60,99 @@ enum
};
/**
* Settings to be specified when creating the UDP transport. Application
* should initialize this structure with its default values by calling
* pjsip_udp_transport_cfg_default().
*/
typedef struct pjsip_udp_transport_cfg
{
/**
* Address family to use. Valid values are pj_AF_INET() and
* pj_AF_INET6(). Default is pj_AF_INET().
*/
int af;
/**
* Address to bind the socket to.
*/
pj_sockaddr bind_addr;
/**
* Optional published address, which is the address to be
* advertised as the address of this SIP transport.
* By default the bound address will be used as the published address.
*/
pjsip_host_port addr_name;
/**
* Number of simultaneous asynchronous accept() operations to be
* supported. It is recommended that the number here corresponds to
* the number of processors in the system (or the number of SIP
* worker threads).
*
* Default: 1
*/
unsigned async_cnt;
/**
* QoS traffic type to be set on this transport. When application wants
* to apply QoS tagging to the transport, it's preferable to set this
* field rather than \a qos_param fields since this is more portable.
*
* Default is QoS not set.
*/
pj_qos_type qos_type;
/**
* Set the low level QoS parameters to the transport. This is a lower
* level operation than setting the \a qos_type field and may not be
* supported on all platforms.
*
* Default is QoS not set.
*/
pj_qos_params qos_params;
/**
* Specify options to be set on the transport.
*
* By default there is no options.
*
*/
pj_sockopt_params sockopt_params;
} pjsip_udp_transport_cfg;
/**
* Initialize pjsip_udp_transport_cfg structure with default values for
* the specifed address family.
*
* @param cfg The structure to initialize.
* @param af Address family to be used.
*/
PJ_DECL(void) pjsip_udp_transport_cfg_default(pjsip_udp_transport_cfg *cfg,
int af);
/**
* Start UDP IPv4/IPv6 transport.
*
* @param endpt The SIP endpoint.
* @param cfg UDP transport settings. Application should initialize
* this setting with #pjsip_udp_transport_cfg_default().
* @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_start2(
pjsip_endpoint *endpt,
const pjsip_udp_transport_cfg *cfg,
pjsip_transport **p_transport);
/**
* Start UDP transport.
*

View File

@ -869,6 +869,81 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt,
async_cnt, p_transport);
}
/*
* Initialize pjsip_udp_transport_cfg structure with default values.
*/
PJ_DEF(void) pjsip_udp_transport_cfg_default(pjsip_udp_transport_cfg *cfg,
int af)
{
pj_bzero(cfg, sizeof(*cfg));
cfg->af = af;
pj_sockaddr_init(cfg->af, &cfg->bind_addr, NULL, 0);
cfg->async_cnt = 1;
}
/*
* pjsip_udp_transport_start2()
*
* Create a UDP socket in the specified address and start a transport.
*/
PJ_DEF(pj_status_t) pjsip_udp_transport_start2(
pjsip_endpoint *endpt,
const pjsip_udp_transport_cfg *cfg,
pjsip_transport **p_transport)
{
pj_sock_t sock;
pj_status_t status;
pjsip_host_port addr_name;
char addr_buf[PJ_INET6_ADDRSTRLEN];
pjsip_transport_type_e transport_type;
pj_uint16_t af;
int addr_len;
PJ_ASSERT_RETURN(endpt && cfg && cfg->async_cnt, PJ_EINVAL);
if (cfg->bind_addr.addr.sa_family == pj_AF_INET()) {
af = pj_AF_INET();
transport_type = PJSIP_TRANSPORT_UDP;
addr_len = sizeof(pj_sockaddr_in);
} else {
af = pj_AF_INET6();
transport_type = PJSIP_TRANSPORT_UDP6;
addr_len = sizeof(pj_sockaddr_in6);
}
status = create_socket(af, &cfg->bind_addr, addr_len, &sock);
if (status != PJ_SUCCESS)
return status;
/* Apply QoS, if specified */
pj_sock_apply_qos2(sock, cfg->qos_type, &cfg->qos_params,
2, THIS_FILE, "SIP UDP transport");
/* Apply sockopt, if specified */
if (cfg->sockopt_params.cnt)
pj_sock_setsockopt_params(sock, &cfg->sockopt_params);
if (cfg->addr_name.host.slen == 0) {
/* Address name is not specified.
* Build a name based on bound address.
*/
status = get_published_name(sock, addr_buf, sizeof(addr_buf),
&addr_name);
if (status != PJ_SUCCESS) {
pj_sock_close(sock);
return status;
}
} else {
addr_name = cfg->addr_name;
}
return pjsip_udp_transport_attach2(endpt, transport_type, sock,
&addr_name, cfg->async_cnt,
p_transport);
}
/*
* pjsip_udp_transport_start()
*
@ -880,37 +955,18 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt,
unsigned async_cnt,
pjsip_transport **p_transport)
{
pj_sock_t sock;
pj_status_t status;
char addr_buf[PJ_INET6_ADDRSTRLEN];
pjsip_host_port bound_name;
pjsip_udp_transport_cfg cfg;
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
pjsip_udp_transport_cfg_default(&cfg, pj_AF_INET());
if (local_a)
pj_sockaddr_cp(&cfg.bind_addr, local_a);
if (a_name)
cfg.addr_name = *a_name;
cfg.async_cnt = async_cnt;
status = create_socket(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in),
&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 );
return pjsip_udp_transport_start2(endpt, &cfg, p_transport);
}
/*
* pjsip_udp_transport_start()
*
@ -922,34 +978,16 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_start6(pjsip_endpoint *endpt,
unsigned async_cnt,
pjsip_transport **p_transport)
{
pj_sock_t sock;
pj_status_t status;
char addr_buf[PJ_INET6_ADDRSTRLEN];
pjsip_host_port bound_name;
pjsip_udp_transport_cfg cfg;
PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
pjsip_udp_transport_cfg_default(&cfg, pj_AF_INET6());
if (local_a)
pj_sockaddr_cp(&cfg.bind_addr, local_a);
if (a_name)
cfg.addr_name = *a_name;
cfg.async_cnt = async_cnt;
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_attach2(endpt, PJSIP_TRANSPORT_UDP6,
sock, a_name, async_cnt, p_transport);
return pjsip_udp_transport_start2(endpt, &cfg, p_transport);
}
/*