summaryrefslogtreecommitdiffstats
path: root/tinyNET
diff options
context:
space:
mode:
authorMamadou DIOP <bossiel@yahoo.fr>2016-05-24 00:11:39 +0200
committerMamadou DIOP <bossiel@yahoo.fr>2016-05-24 00:11:39 +0200
commit3383de3026cd0afb06747069c05a600fd07ec02e (patch)
tree421b8f5a13c6da7770ce781e199265dc3c7076be /tinyNET
parentaff961eb2374344cb9a62cd9c4f0fae1edf4dbc0 (diff)
downloaddoubango-3383de3026cd0afb06747069c05a600fd07ec02e.zip
doubango-3383de3026cd0afb06747069c05a600fd07ec02e.tar.gz
Make ICE dual-satck (IPv46) more versatile
Diffstat (limited to 'tinyNET')
-rwxr-xr-xtinyNET/src/ice/tnet_ice_ctx.c106
-rwxr-xr-xtinyNET/src/tnet_nat.c10
-rwxr-xr-xtinyNET/src/tnet_nat.h1
-rwxr-xr-xtinyNET/src/tnet_socket.h1
-rwxr-xr-xtinyNET/src/tnet_transport.c1
-rwxr-xr-xtinyNET/src/tnet_utils.c74
-rwxr-xr-xtinyNET/src/tnet_utils.h3
7 files changed, 150 insertions, 46 deletions
diff --git a/tinyNET/src/ice/tnet_ice_ctx.c b/tinyNET/src/ice/tnet_ice_ctx.c
index 6e5e5be..924e0d3 100755
--- a/tinyNET/src/ice/tnet_ice_ctx.c
+++ b/tinyNET/src/ice/tnet_ice_ctx.c
@@ -80,6 +80,8 @@
#define kIcePairsBuildingTimeMax 2500 // maximum time to build pairs
+#define kIceDefaultDualStack tsk_true
+
typedef tsk_list_t tnet_ice_servers_L_t;
static const char* foundation_default = tsk_null;
@@ -194,6 +196,12 @@ static tnet_ice_server_t* tnet_ice_server_create(
TSK_DEBUG_ERROR("Invalid server address (host=%s, port=%d, transport=%d)", str_server_addr, u_server_port, e_transport);
return tsk_null;
}
+ if (obj_server_addr.ss_family == AF_INET6) {
+ TNET_SOCKET_TYPE_SET_IPV6Only(e_transport);
+ }
+ else {
+ TNET_SOCKET_TYPE_SET_IPV4Only(e_transport);
+ }
if ((ice_server = tsk_object_new(&tnet_ice_server_def_s))) {
ice_server->e_proto = e_proto;
@@ -218,6 +226,7 @@ typedef struct tnet_ice_ctx_s {
tnet_ice_callback_f callback;
const void* userdata;
tsk_bool_t use_ipv6;
+ tsk_bool_t dual_stack;
tsk_bool_t use_rtcp;
tsk_bool_t use_rtcpmux;
tsk_bool_t is_video;
@@ -400,6 +409,8 @@ static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app)
*/
ctx->Rc = kIceDefaultRC;
+ ctx->dual_stack = kIceDefaultDualStack;
+
ctx->tie_breaker = ((tsk_time_now() << 32) ^ tsk_time_now());
ctx->is_ice_jingle = tsk_false;
ctx->is_stun_enabled = kIceDefaultStunEnabled;
@@ -595,6 +606,15 @@ int tnet_ice_ctx_add_server(
TSK_DEBUG_ERROR("'%s' not a valid transport proto", transport_proto);
return -1;
}
+ if (self->dual_stack) {
+ TNET_SOCKET_TYPE_SET_IPV46(socket_type);
+ }
+ else if (self->use_ipv6) {
+ TNET_SOCKET_TYPE_SET_IPV6Only(socket_type);
+ }
+ else {
+ TNET_SOCKET_TYPE_SET_IPV4Only(socket_type);
+ }
return _tnet_ice_ctx_server_add(self, e_proto,
socket_type, server_addr, server_port,
kStunSoftware,
@@ -1117,7 +1137,7 @@ bail:
// Started -> (GatherHostCandidates) -> (GatheringHostCandidates)
static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandidates(va_list *app)
{
- int ret = 0;
+ int ret = 0, i;
tnet_ice_ctx_t* self;
tnet_addresses_L_t* addresses;
const tsk_list_item_t *item;
@@ -1129,21 +1149,42 @@ static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandi
uint16_t local_pref, curr_local_pref;
tnet_ip_t best_local_ip;
tsk_bool_t check_best_local_ip;
+ int af_inets[2] = { AF_UNSPEC, AF_UNSPEC };
static const tsk_bool_t dnsserver = tsk_false;
static const long if_index_any = -1; // any interface
static const char* destination = "doubango.org";
self = va_arg(*app, tnet_ice_ctx_t *);
- socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4;
-
- addresses = tnet_get_addresses((self->use_ipv6 ? AF_INET6 : AF_INET), self->unicast, self->anycast, self->multicast, dnsserver, if_index_any);
- if (!addresses || TSK_LIST_IS_EMPTY(addresses)) {
- TSK_DEBUG_ERROR("Failed to get addresses");
+ socket_type = self->dual_stack
+ ? tnet_socket_type_udp_ipv46
+ : (self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4);
+
+ // Create list of addresses
+ if (!(addresses = tsk_list_create())) {
+ TSK_DEBUG_ERROR("Failed to create addresses-list");
ret = -1;
goto bail;
- }
-
-
+ }
+ // Set IPv4 flag
+ if (TNET_SOCKET_TYPE_IS_IPV4(socket_type)) {
+ af_inets[0] = AF_INET;
+ }
+ // Set IPv6 flag
+ if (TNET_SOCKET_TYPE_IS_IPV6(socket_type)) {
+ af_inets[1] = AF_INET6;
+ }
+
+ /* IPv4/IPv6 addresses */
+ for (i = 0; i < sizeof(af_inets)/sizeof(af_inets[0]); ++i) {
+ if (af_inets[i] != AF_UNSPEC) {
+ tnet_addresses_L_t* list = tnet_get_addresses(af_inets[i], self->unicast, self->anycast, self->multicast, dnsserver, if_index_any);
+ if (list && !TSK_LIST_IS_EMPTY(list)) {
+ tsk_list_pushback_list(addresses, list);
+ }
+ TSK_OBJECT_SAFE_FREE(list);
+ }
+ }
+
check_best_local_ip = (tnet_getbestsource(destination, 5060, socket_type, &best_local_ip) == 0);
curr_local_pref = local_pref = check_best_local_ip ? 0xFFFE : 0xFFFF;
@@ -1163,7 +1204,7 @@ static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandi
}
// host candidates
- ret = tnet_ice_utils_create_sockets(socket_type,
+ ret = tnet_ice_utils_create_sockets((address->family == AF_INET6) ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4,
address->ip, &socket_rtp,
self->use_rtcp ? &socket_rtcp : tsk_null);
if (ret == 0) {
@@ -1371,7 +1412,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
if (!(candidate = (tnet_ice_candidate_t*)item->data)) {
continue;
}
- if (candidate->socket && tsk_strnullORempty(candidate->stun.srflx_addr)) {
+ if (candidate->socket && candidate->transport_e == ice_server->e_transport && tsk_strnullORempty(candidate->stun.srflx_addr)) {
ret = tnet_ice_candidate_send_stun_bind_request(candidate, &ice_server->obj_server_addr, ice_server->str_username, ice_server->str_password);
}
}
@@ -2759,8 +2800,9 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
const char* str_software,
const char* str_username, const char* str_password)
{
- struct tnet_ice_server_s* ice_server;
- int ret = -1;
+ struct tnet_ice_server_s* ice_server = tsk_null;
+ enum tnet_socket_type_e e_transports[2] = { tnet_socket_type_invalid, tnet_socket_type_invalid};
+ int ret = -1, i;
if (!self || !e_proto || !str_server_addr || !u_server_port) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
@@ -2782,12 +2824,38 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
ret = 0; // Not an error
goto bail;
}
- if (!(ice_server = tnet_ice_server_create(e_proto, e_transport, str_server_addr, u_server_port, str_software, str_username, str_password))) {
- TSK_DEBUG_ERROR("Failed to create ICE server(proto=%d, transport=%d, addr=%s, port=%hu)", e_proto, e_transport, str_server_addr, u_server_port);
- goto bail;
- }
- tsk_list_push_back_data(self->servers, (void**)&ice_server);
- TSK_OBJECT_SAFE_FREE(ice_server);
+ // Guess the supported IP versions from the server address
+ if (self->dual_stack) {
+ enum tnet_socket_type_e server_addr_type = tnet_get_type(str_server_addr, u_server_port);
+ if (TNET_SOCKET_TYPE_IS_IPV4(server_addr_type)) {
+ e_transports[0] = e_transport;
+ TNET_SOCKET_TYPE_SET_IPV4Only(e_transports[0]);
+ }
+ if (TNET_SOCKET_TYPE_IS_IPV6(server_addr_type)) {
+ e_transports[1] = e_transport;
+ TNET_SOCKET_TYPE_SET_IPV6Only(e_transports[1]);
+ }
+ }
+ else {
+ e_transports[0] = e_transport;
+ if (self->use_ipv6) {
+ TNET_SOCKET_TYPE_SET_IPV6Only(e_transports[0]);
+ }
+ else {
+ TNET_SOCKET_TYPE_SET_IPV4Only(e_transports[0]);
+ }
+ }
+ // Add the ICE servers
+ for (i = 0; i < sizeof(e_transports)/sizeof(e_transports[0]); ++i) {
+ if (TNET_SOCKET_TYPE_IS_VALID(e_transports[i])) {
+ if (!(ice_server = tnet_ice_server_create(e_proto, e_transports[i], str_server_addr, u_server_port, str_software, str_username, str_password))) {
+ TSK_DEBUG_ERROR("Failed to create ICE server(proto=%d, transport=%d, addr=%s, port=%hu)", e_proto, e_transport, str_server_addr, u_server_port);
+ goto bail;
+ }
+ tsk_list_push_back_data(self->servers, (void**)&ice_server);
+ TSK_OBJECT_SAFE_FREE(ice_server);
+ }
+ }
ret = 0;
bail:
diff --git a/tinyNET/src/tnet_nat.c b/tinyNET/src/tnet_nat.c
index 7e536c1..1a9df9f 100755
--- a/tinyNET/src/tnet_nat.c
+++ b/tinyNET/src/tnet_nat.c
@@ -129,6 +129,16 @@ int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_se
return 0;
}
+int tnet_nat_get_socket_type(const struct tnet_nat_ctx_s* p_self, enum tnet_socket_type_e* type)
+{
+ if (!p_self || !type) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *type = p_self->socket_type;
+ return 0;
+}
+
/**@ingroup tnet_nat_group
*
* Sets the address and port of the STUN/TURN server.
diff --git a/tinyNET/src/tnet_nat.h b/tinyNET/src/tnet_nat.h
index 626851d..fd45365 100755
--- a/tinyNET/src/tnet_nat.h
+++ b/tinyNET/src/tnet_nat.h
@@ -30,6 +30,7 @@ struct tnet_nat_ctx_s;
struct tnet_stun_binding_s;
enum tnet_socket_type_e;
+TINYNET_API int tnet_nat_get_socket_type(const struct tnet_nat_ctx_s* p_self, enum tnet_socket_type_e* type);
TINYNET_API int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_srv_addr);
TINYNET_API int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_srv_addr, tnet_port_t u_srv_port);
TINYNET_API tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, const tnet_fd_t localFD);
diff --git a/tinyNET/src/tnet_socket.h b/tinyNET/src/tnet_socket.h
index daceb53..fb518ac 100755
--- a/tinyNET/src/tnet_socket.h
+++ b/tinyNET/src/tnet_socket.h
@@ -132,6 +132,7 @@ tnet_socket_type_t;
#define TNET_SOCKET_TYPE_SET_IPV4Only(type) (type = TNET_SOCKET_TYPE_IS_IPV6(type) ? (type ^TNET_SOCKET_TYPE_IPV6)|TNET_SOCKET_TYPE_IPV4 : type)
#define TNET_SOCKET_TYPE_SET_IPV6(type) (type |= TNET_SOCKET_TYPE_IPV6)
#define TNET_SOCKET_TYPE_SET_IPV6Only(type) (type = TNET_SOCKET_TYPE_IS_IPV4(type) ? (type ^TNET_SOCKET_TYPE_IPV4)|TNET_SOCKET_TYPE_IPV6 : type)
+#define TNET_SOCKET_TYPE_SET_IPV46(type) (type |= TNET_SOCKET_TYPE_IPV46)
#define TNET_SOCKET_TYPE_SET_IPSEC(type) (type |=TNET_SOCKET_TYPE_IPSEC)
diff --git a/tinyNET/src/tnet_transport.c b/tinyNET/src/tnet_transport.c
index fe9810e..4c17315 100755
--- a/tinyNET/src/tnet_transport.c
+++ b/tinyNET/src/tnet_transport.c
@@ -157,6 +157,7 @@ tnet_transport_t* tnet_transport_create(const char* host, tnet_port_t port, tnet
if ((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))) {
transport->local_ip = tsk_strdup(transport->master->ip);
transport->bind_local_port = transport->master->port;
+ transport->type = transport->master->type;
}
else {
TSK_DEBUG_ERROR("Failed to create master socket");
diff --git a/tinyNET/src/tnet_utils.c b/tinyNET/src/tnet_utils.c
index d01facd..693f672 100755
--- a/tinyNET/src/tnet_utils.c
+++ b/tinyNET/src/tnet_utils.c
@@ -837,7 +837,7 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty
tnet_addresses_L_t* addresses = tsk_null;
const tsk_list_item_t* item;
- if (!(addresses = tnet_get_addresses(TNET_SOCKET_TYPE_IS_IPV6(type) ? AF_INET6 : AF_INET, tsk_true, tsk_false, tsk_false, tsk_false, dwBestIfIndex))) {
+ if (!(addresses = tnet_get_addresses(destAddr.ss_family, tsk_true, tsk_false, tsk_false, tsk_false, dwBestIfIndex))) {
ret = -2;
TSK_DEBUG_ERROR("Failed to retrieve addresses.");
goto bail;
@@ -1053,34 +1053,50 @@ int tnet_getpeername(tnet_fd_t fd, struct sockaddr_storage *result)
return -1;
}
-/**@ingroup tnet_utils_group
- * Retrieves the socket type of a File Descriptor.
- * @param fd The File descriptor for which to retrive the type.
- * @retval @ref tnet_socket_type_t.
- */
-tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd)
+tnet_socket_type_t tnet_get_type(const char* host, tnet_port_t port)
{
- tnet_socket_type_t type = tnet_socket_type_invalid;
-
- /*if(fd >0)
- {
- struct sockaddr_storage ss;
- if(!tnet_get_sockaddr(fd, &ss))
- {
- if(((struct sockaddr *)&ss)->sa_family == AF_INET)
- {
- TNET_SOCKET_TYPE_AS_IPV4(type);
- }
- else if(((struct sockaddr *)&ss)->sa_family == AF_INET6)
- {
- TNET_SOCKET_TYPE_AS_IPV6(type);
- }
- }
- }*/
-
- return type;
+ tnet_socket_type_t ret = TNET_SOCKET_TYPE_UDP;
+ if (host) {
+ int status;
+ tsk_istr_t srv;
+ struct addrinfo *result = tsk_null;
+ struct addrinfo hints;
+ const struct addrinfo *ptr = tsk_null;
+
+ /* set the port: used as the default service */
+ if (port) {
+ tsk_itoa(port, &srv);
+ }
+ else {
+ memset(srv, '\0', sizeof(srv));
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+
+ if ((status = tnet_getaddrinfo(host, srv, &hints, &result))) {
+ TNET_PRINT_LAST_ERROR("getaddrinfo(%s:%d) failed", host, port);
+ goto done;
+ }
+
+ for (ptr = result; ptr; ptr = ptr->ai_next) {
+ if (ptr->ai_family == AF_INET) {
+ TNET_SOCKET_TYPE_SET_IPV4(ret);
+ }
+ else if (ptr->ai_family == AF_INET6) {
+ TNET_SOCKET_TYPE_SET_IPV6(ret);
+ }
+ }
+done:
+ tnet_freeaddrinfo(result);
+ }
+
+ return ret;
}
+
/**@ingroup tnet_utils_group
* Gets the IP family of the @a host (e.g. "google.com" or "192.168.16.104" or "::1").
* If the @a host is FQDN associated with both IPv4 and IPv6 then the result is unpredictable.
@@ -1127,6 +1143,12 @@ done:
return ret;
}
+tsk_bool_t tnet_is_ipv6(const char* host, tnet_port_t port)
+{
+ tnet_socket_type_t type = tnet_get_type(host, port);
+ return TNET_SOCKET_TYPE_IS_IPV6(type);
+}
+
/**@ingroup tnet_utils_group
* Gets the IP address and the Port of a @b sockaddr object.
* @param addr [in] A pointer to @b sockaddr structure for which to retrieve the IP address and port.
diff --git a/tinyNET/src/tnet_utils.h b/tinyNET/src/tnet_utils.h
index a3abbc9..9ed6765 100755
--- a/tinyNET/src/tnet_utils.h
+++ b/tinyNET/src/tnet_utils.h
@@ -93,8 +93,9 @@ TINYNET_API int tnet_getaddrinfo(const char *node, const char *service, const st
TINYNET_API void tnet_freeaddrinfo(struct addrinfo *ai);
TINYNET_API int tnet_getsockname(tnet_fd_t fd, struct sockaddr_storage *result);
TINYNET_API int tnet_getpeername(tnet_fd_t fd, struct sockaddr_storage *result);
-TINYNET_API tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd);
TINYNET_API tnet_family_t tnet_get_family(const char* host, tnet_port_t port);
+TINYNET_API tnet_socket_type_t tnet_get_type(const char* host, tnet_port_t port);
+TINYNET_API tsk_bool_t tnet_is_ipv6(const char* host, tnet_port_t port);
TINYNET_API int tnet_get_ip_n_port(tnet_fd_t fd, tsk_bool_t getlocal, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_get_sockip_n_port(const struct sockaddr *addr, tnet_ip_t *ip, tnet_port_t *port);
TINYNET_API int tnet_get_peerip_n_port(tnet_fd_t localFD, tnet_ip_t *ip, tnet_port_t *port);
OpenPOWER on IntegriCloud