From 8d17bc774a62c7e6544cd60eb4462fedc17a5218 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 10 May 2016 05:13:57 +0000 Subject: Close #1915: Added API pjsip_udp_transport_start2() that can create both IPv4 and IPv6 SIP UDP transports. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5284 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip/include/pjsip/sip_transport_udp.h | 94 ++++++++++++++++++++++++ pjsip/src/pjsip/sip_transport_udp.c | 126 +++++++++++++++++++++----------- 2 files changed, 176 insertions(+), 44 deletions(-) diff --git a/pjsip/include/pjsip/sip_transport_udp.h b/pjsip/include/pjsip/sip_transport_udp.h index 27c643a7..c68424ef 100644 --- a/pjsip/include/pjsip/sip_transport_udp.h +++ b/pjsip/include/pjsip/sip_transport_udp.h @@ -26,6 +26,7 @@ */ #include +#include 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. * diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c index 9c87fb84..499cbeac 100644 --- a/pjsip/src/pjsip/sip_transport_udp.c +++ b/pjsip/src/pjsip/sip_transport_udp.c @@ -869,87 +869,125 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_attach2( pjsip_endpoint *endpt, async_cnt, p_transport); } + /* - * pjsip_udp_transport_start() + * 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_start( pjsip_endpoint *endpt, - const pj_sockaddr_in *local_a, - const pjsip_host_port *a_name, - unsigned async_cnt, - pjsip_transport **p_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_host_port bound_name; + pjsip_transport_type_e transport_type; + pj_uint16_t af; + int addr_len; + + PJ_ASSERT_RETURN(endpt && cfg && cfg->async_cnt, PJ_EINVAL); - PJ_ASSERT_RETURN(endpt && 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(pj_AF_INET(), local_a, sizeof(pj_sockaddr_in), - &sock); + status = create_socket(af, &cfg->bind_addr, addr_len, &sock); if (status != PJ_SUCCESS) return status; - if (a_name == NULL) { - /* Address name is not specified. + /* 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), - &bound_name); + status = get_published_name(sock, addr_buf, sizeof(addr_buf), + &addr_name); if (status != PJ_SUCCESS) { pj_sock_close(sock); return status; } - - a_name = &bound_name; + } else { + addr_name = cfg->addr_name; } - return pjsip_udp_transport_attach( endpt, sock, a_name, async_cnt, - p_transport ); + return pjsip_udp_transport_attach2(endpt, transport_type, sock, + &addr_name, cfg->async_cnt, + p_transport); } - /* * 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, +PJ_DEF(pj_status_t) pjsip_udp_transport_start( pjsip_endpoint *endpt, + const pj_sockaddr_in *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_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_INET6(), local_a, sizeof(pj_sockaddr_in6), - &sock); - if (status != PJ_SUCCESS) - return status; + return pjsip_udp_transport_start2(endpt, &cfg, p_transport); +} - 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; - } +/* + * 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) +{ + pjsip_udp_transport_cfg cfg; - a_name = &bound_name; - } + 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; - 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); } /* -- cgit v1.2.3