summaryrefslogtreecommitdiff
path: root/pjsip/src/pjsua-lib/pjsua_core.c
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-12-01 08:59:25 +0000
committerBenny Prijono <bennylp@teluu.com>2007-12-01 08:59:25 +0000
commit223903c913565d00e54b55f9685a174f1f31ed49 (patch)
treec87466c8a333649fb6ca436199bd6f4f217d527c /pjsip/src/pjsua-lib/pjsua_core.c
parent2e6a62f43b622320d69971cfc07a68ab59e29f1b (diff)
Ticket #421: initial IPv6 support: UDP transport
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1602 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjsip/src/pjsua-lib/pjsua_core.c')
-rw-r--r--pjsip/src/pjsua-lib/pjsua_core.c114
1 files changed, 69 insertions, 45 deletions
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index 578425e2..39a71f8e 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -1182,17 +1182,32 @@ PJ_DEF(pj_pool_factory*) pjsua_get_pool_factory(void)
*/
/*
+ * 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
* 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,
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_sock_t sock;
+ pj_sockaddr bind_addr;
pj_status_t status;
/* 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;
}
- 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) {
pjsua_perror(THIS_FILE, "socket() error", status);
return status;
}
- status = pj_sock_bind_in(sock, pj_ntohl(bound_addr.s_addr),
- (pj_uint16_t)port);
+ status = pj_sock_bind(sock, &bind_addr, sizeof(bind_addr));
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "bind() error", status);
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 == 0) {
- pj_sockaddr_in bound_addr;
+ pj_sockaddr bound_addr;
int namelen = sizeof(bound_addr);
status = pj_sock_getsockname(sock, &bound_addr, &namelen);
if (status != PJ_SUCCESS) {
@@ -1227,12 +1255,12 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
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) {
- pj_ansi_strcpy(ip_addr,pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
- stun_srv = pj_str(ip_addr);
+ pj_ansi_strcpy(stun_ip_addr,pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
+ stun_srv = pj_str(stun_ip_addr);
} else {
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
* 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
* address, only set the port.
*/
- if (p_pub_addr->sin_port == 0)
- p_pub_addr->sin_port = pj_htons((pj_uint16_t)port);
+ if (pj_sockaddr_get_port(p_pub_addr) == 0)
+ pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
} else if (stun_srv.slen) {
/*
* 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,
&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) {
pjsua_perror(THIS_FILE, "Error contacting STUN server", status);
pj_sock_close(sock);
@@ -1263,25 +1297,24 @@ static pj_status_t create_sip_udp_sock(pj_in_addr bound_addr,
}
} else {
+ pj_bzero(p_pub_addr, sizeof(pj_sockaddr));
- pj_bzero(p_pub_addr, sizeof(pj_sockaddr_in));
-
- status = pj_gethostip(&p_pub_addr->sin_addr);
+ status = pj_gethostip(af, p_pub_addr);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Unable to get local host IP", status);
pj_sock_close(sock);
return status;
}
- p_pub_addr->sin_family = pj_AF_INET();
- p_pub_addr->sin_port = pj_htons((pj_uint16_t)port);
+ p_pub_addr->addr.sa_family = (pj_uint16_t)af;
+ pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port);
}
*p_sock = sock;
PJ_LOG(4,(THIS_FILE, "SIP UDP socket reachable at %s:%d",
- pj_inet_ntoa(p_pub_addr->sin_addr),
- (int)pj_ntohs(p_pub_addr->sin_port)));
+ addr_string(p_pub_addr),
+ (int)pj_sockaddr_get_port(p_pub_addr)));
return PJ_SUCCESS;
}
@@ -1313,14 +1346,14 @@ PJ_DEF(pj_status_t) pjsua_transport_create( pjsip_transport_type_e type,
}
/* 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;
+ char hostbuf[PJ_INET6_ADDRSTRLEN];
pj_sock_t sock = PJ_INVALID_SOCKET;
- pj_sockaddr_in bound_addr;
- pj_sockaddr_in pub_addr;
+ pj_sockaddr pub_addr;
pjsip_host_port addr_name;
/* 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;
}
- /* 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 */
- 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) {
- 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) {
pjsua_perror(THIS_FILE,
"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
* (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);
if (status != PJ_SUCCESS)
goto on_return;
- addr_name.host = pj_str(pj_inet_ntoa(pub_addr.sin_addr));
- addr_name.port = pj_ntohs(pub_addr.sin_port);
+ pj_ansi_strcpy(hostbuf, addr_string(&pub_addr));
+ addr_name.host = pj_str(hostbuf);
+ addr_name.port = pj_sockaddr_get_port(&pub_addr);
/* Create UDP transport */
- status = pjsip_udp_transport_attach( pjsua_var.endpt, sock,
- &addr_name, 1,
- &tp);
+ status = pjsip_udp_transport_attach2(pjsua_var.endpt, type, sock,
+ &addr_name, 1, &tp);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error creating SIP UDP transport",
status);