summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/ice
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/ice')
-rwxr-xr-xtinyNET/src/ice/tnet_ice.c6
-rwxr-xr-xtinyNET/src/ice/tnet_ice.h6
-rwxr-xr-xtinyNET/src/ice/tnet_ice_candidate.c383
-rwxr-xr-xtinyNET/src/ice/tnet_ice_candidate.h92
-rwxr-xr-xtinyNET/src/ice/tnet_ice_ctx.c947
-rwxr-xr-xtinyNET/src/ice/tnet_ice_ctx.h40
-rwxr-xr-xtinyNET/src/ice/tnet_ice_event.c23
-rwxr-xr-xtinyNET/src/ice/tnet_ice_event.h58
-rwxr-xr-xtinyNET/src/ice/tnet_ice_pair.c1136
-rwxr-xr-xtinyNET/src/ice/tnet_ice_pair.h60
-rwxr-xr-xtinyNET/src/ice/tnet_ice_utils.c230
-rwxr-xr-xtinyNET/src/ice/tnet_ice_utils.h4
12 files changed, 1500 insertions, 1485 deletions
diff --git a/tinyNET/src/ice/tnet_ice.c b/tinyNET/src/ice/tnet_ice.c
index 196009b..1252ff6 100755
--- a/tinyNET/src/ice/tnet_ice.c
+++ b/tinyNET/src/ice/tnet_ice.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2010-2015 Mamadou DIOP
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
diff --git a/tinyNET/src/ice/tnet_ice.h b/tinyNET/src/ice/tnet_ice.h
index daffd08..53f9d22 100755
--- a/tinyNET/src/ice/tnet_ice.h
+++ b/tinyNET/src/ice/tnet_ice.h
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2010-2015 Mamadou DIOP
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
diff --git a/tinyNET/src/ice/tnet_ice_candidate.c b/tinyNET/src/ice/tnet_ice_candidate.c
index bb75b33..7900933 100755
--- a/tinyNET/src/ice/tnet_ice_candidate.c
+++ b/tinyNET/src/ice/tnet_ice_candidate.c
@@ -34,15 +34,15 @@
#include <ctype.h>
static int _tnet_ice_candidate_tostring(
- uint8_t* foundation,
- uint32_t comp_id,
- const char* transport_str,
- uint32_t priority,
- const char* connection_addr,
- tnet_port_t port,
- const char* cand_type_str,
- const tsk_params_L_t *extension_att_list,
- char** output);
+ uint8_t* foundation,
+ uint32_t comp_id,
+ const char* transport_str,
+ uint32_t priority,
+ const char* connection_addr,
+ tnet_port_t port,
+ const char* cand_type_str,
+ const tsk_params_L_t *extension_att_list,
+ char** output);
static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type);
static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password);
static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
@@ -54,7 +54,7 @@ static tnet_ice_cand_type_t _tnet_ice_candtype_get_transport_type(const char* ca
static tsk_object_t* tnet_ice_candidate_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_candidate_t *candidate = self;
- if (candidate){
+ if (candidate) {
candidate->extension_att_list = tsk_list_create();
}
return self;
@@ -63,23 +63,23 @@ static tsk_object_t* tnet_ice_candidate_ctor(tsk_object_t * self, va_list * app)
static tsk_object_t* tnet_ice_candidate_dtor(tsk_object_t * self)
{
tnet_ice_candidate_t *candidate = self;
- if (candidate){
+ if (candidate) {
TSK_SAFE_FREE(candidate->transport_str);
TSK_SAFE_FREE(candidate->cand_type_str);
TSK_OBJECT_SAFE_FREE(candidate->extension_att_list);
TSK_OBJECT_SAFE_FREE(candidate->socket);
-
-
+
+
TSK_SAFE_FREE(candidate->stun.nonce);
TSK_SAFE_FREE(candidate->stun.realm);
TSK_SAFE_FREE(candidate->stun.srflx_addr);
-
+
TSK_SAFE_FREE(candidate->turn.relay_addr);
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
-
+
TSK_SAFE_FREE(candidate->ufrag);
TSK_SAFE_FREE(candidate->pwd);
-
+
TSK_SAFE_FREE(candidate->tostring);
}
return self;
@@ -89,16 +89,19 @@ static int tnet_ice_candidate_cmp(const tsk_object_t *_s1, const tsk_object_t *_
{
const tnet_ice_candidate_t *c1 = _s1;
const tnet_ice_candidate_t *c2 = _s2;
-
- if (c1 && c2){
+
+ if (c1 && c2) {
return (int)(c1->priority - c2->priority);
}
- else if (!c1 && !c2) return 0;
- else return -1;
+ else if (!c1 && !c2) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
}
-static const tsk_object_def_t tnet_ice_candidate_def_s =
-{
+static const tsk_object_def_t tnet_ice_candidate_def_s = {
sizeof(tnet_ice_candidate_t),
tnet_ice_candidate_ctor,
tnet_ice_candidate_dtor,
@@ -108,12 +111,12 @@ static const tsk_object_def_t tnet_ice_candidate_def_s =
tnet_ice_candidate_t* tnet_ice_candidate_create(tnet_ice_cand_type_t type_e, tnet_socket_t* socket, tsk_bool_t is_ice_jingle, tsk_bool_t is_rtp, tsk_bool_t is_video, const char* ufrag, const char* pwd, const char *foundation)
{
tnet_ice_candidate_t* candidate;
-
- if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))){
+
+ if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))) {
TSK_DEBUG_ERROR("Failed to create candidate");
return tsk_null;
}
-
+
candidate->type_e = type_e;
candidate->socket = tsk_object_ref(socket);
candidate->local_pref = 0xFFFF;
@@ -121,20 +124,20 @@ tnet_ice_candidate_t* tnet_ice_candidate_create(tnet_ice_cand_type_t type_e, tne
candidate->is_rtp = is_rtp;
candidate->is_video = is_video;
candidate->comp_id = is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP;
- if (foundation){
+ if (foundation) {
memcpy(candidate->foundation, foundation, TSK_MIN(tsk_strlen(foundation), TNET_ICE_CANDIDATE_FOUND_SIZE_PREF));
}
- else{
+ else {
tnet_ice_utils_compute_foundation((char*)candidate->foundation, TSK_MIN(sizeof(candidate->foundation), TNET_ICE_CANDIDATE_FOUND_SIZE_PREF));
}
candidate->priority = tnet_ice_utils_get_priority(candidate->type_e, candidate->local_pref, candidate->is_rtp);
- if (candidate->socket){
+ if (candidate->socket) {
memcpy(candidate->connection_addr, candidate->socket->ip, sizeof(candidate->socket->ip));
candidate->port = candidate->socket->port;
candidate->transport_e = socket->type;
}
tnet_ice_candidate_set_credential(candidate, ufrag, pwd);
-
+
return candidate;
}
@@ -144,104 +147,96 @@ tnet_ice_candidate_t* tnet_ice_candidate_parse(const char* str)
char *v, *copy, *saveptr;
int32_t k;
tnet_ice_candidate_t* candidate;
-
- if (tsk_strnullORempty(str)){
+
+ if (tsk_strnullORempty(str)) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
- if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))){
+
+ if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))) {
TSK_DEBUG_ERROR("Failed to create candidate");
return tsk_null;
}
-
+
k = 0;
copy = tsk_strdup(str);
v = tsk_strtok_r(copy, " ", &saveptr);
-
- while (v){
- switch (k){
- case 0:
- {
- memcpy(candidate->foundation, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->foundation)));
- break;
- }
- case 1:
- {
- candidate->comp_id = atoi(v);
- break;
- }
- case 2:
- {
- candidate->transport_str = tsk_strdup(v);
- break;
- }
- case 3:
- {
- candidate->priority = atoi(v);
- break;
- }
- case 4:
- {
- memcpy(candidate->connection_addr, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->connection_addr)));
- break;
- }
- case 5:
- {
- tnet_family_t family;
- candidate->port = atoi(v);
- family = tnet_get_family(candidate->connection_addr, candidate->port);
- candidate->transport_e = _tnet_ice_candidate_get_transport_type((family == AF_INET6), candidate->transport_str);
- break;
- }
- case 6:
- {
- v = tsk_strtok_r(tsk_null, " ", &saveptr);
- tsk_strupdate(&candidate->cand_type_str, v);
- candidate->type_e = _tnet_ice_candtype_get_transport_type(v);
- break;
- }
- default:
- {
- const char* name = v;
- const char* value = (v = tsk_strtok_r(tsk_null, " ", &saveptr));
- tsk_param_t* param = tsk_param_create(name, value);
- if (param){
- tsk_list_push_back_data(candidate->extension_att_list, (void**)&param);
- }
- break;
+
+ while (v) {
+ switch (k) {
+ case 0: {
+ memcpy(candidate->foundation, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->foundation)));
+ break;
+ }
+ case 1: {
+ candidate->comp_id = atoi(v);
+ break;
+ }
+ case 2: {
+ candidate->transport_str = tsk_strdup(v);
+ break;
+ }
+ case 3: {
+ candidate->priority = atoi(v);
+ break;
+ }
+ case 4: {
+ memcpy(candidate->connection_addr, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->connection_addr)));
+ break;
+ }
+ case 5: {
+ tnet_family_t family;
+ candidate->port = atoi(v);
+ family = tnet_get_family(candidate->connection_addr, candidate->port);
+ candidate->transport_e = _tnet_ice_candidate_get_transport_type((family == AF_INET6), candidate->transport_str);
+ break;
+ }
+ case 6: {
+ v = tsk_strtok_r(tsk_null, " ", &saveptr);
+ tsk_strupdate(&candidate->cand_type_str, v);
+ candidate->type_e = _tnet_ice_candtype_get_transport_type(v);
+ break;
+ }
+ default: {
+ const char* name = v;
+ const char* value = (v = tsk_strtok_r(tsk_null, " ", &saveptr));
+ tsk_param_t* param = tsk_param_create(name, value);
+ if (param) {
+ tsk_list_push_back_data(candidate->extension_att_list, (void**)&param);
}
+ break;
+ }
}
-
+
++k;
v = tsk_strtok_r(tsk_null, " ", &saveptr);
}
-
- if (k < 6){
+
+ if (k < 6) {
TSK_DEBUG_ERROR("Failed to parse: %s", str);
TSK_OBJECT_SAFE_FREE(candidate);
}
TSK_FREE(copy);
-
+
return candidate;
}
int tnet_ice_candidate_set_credential(tnet_ice_candidate_t* self, const char* ufrag, const char* pwd)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_strupdate(&self->ufrag, ufrag);
tsk_strupdate(&self->pwd, pwd);
-
+
return 0;
}
int tnet_ice_candidate_set_rflx_addr(tnet_ice_candidate_t* self, const char* addr, tnet_port_t port)
{
- if (!self || !addr || !port){
+ if (!self || !addr || !port) {
TSK_DEBUG_ERROR("Invalid argument");
return -1;
}
@@ -253,7 +248,7 @@ int tnet_ice_candidate_set_rflx_addr(tnet_ice_candidate_t* self, const char* add
const char* tnet_ice_candidate_get_att_value(const tnet_ice_candidate_t* self, const char* att_name)
{
- if (!self || !att_name){
+ if (!self || !att_name) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
@@ -262,7 +257,7 @@ const char* tnet_ice_candidate_get_att_value(const tnet_ice_candidate_t* self, c
int tnet_ice_candidate_set_local_pref(tnet_ice_candidate_t* self, uint16_t local_pref)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -275,12 +270,12 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self)
{
const char* _transport_str;
char __str[255]; // always allocated: bad idea :(
-
- if (!self){
+
+ if (!self) {
TSK_DEBUG_ERROR("Invalid argument");
return tsk_null;
}
-
+
if (self->type_e == tnet_ice_cand_type_relay && self->turn.ss) {
enum tnet_turn_transport_e e_req_transport = tnet_turn_transport_udp;
tnet_turn_session_get_req_transport(self->turn.ss, &e_req_transport);
@@ -288,47 +283,45 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self)
}
else {
_transport_str = self->transport_str ? self->transport_str : _tnet_ice_candidate_get_transport_str(self->transport_e);
- if (self->is_ice_jingle){
+ if (self->is_ice_jingle) {
tsk_size_t i, s = tsk_strlen(_transport_str);
memset(__str, 0, sizeof(__str));
- for (i = 0; i < s && i < sizeof(__str) / sizeof(__str[0]); ++i){
+ for (i = 0; i < s && i < sizeof(__str) / sizeof(__str[0]); ++i) {
__str[i] = tolower(_transport_str[i]);
}
_transport_str = &__str[0];
}
}
-
+
_tnet_ice_candidate_tostring(
- self->foundation,
- self->comp_id,
- _transport_str,
- self->priority,
- (tsk_strnullORempty(self->connection_addr) && self->socket) ? self->socket->ip : self->connection_addr,
- (self->port <= 0 && self->socket) ? self->socket->port : self->port,
- self->cand_type_str ? self->cand_type_str : _tnet_ice_candidate_get_candtype_str(self->type_e),
- self->extension_att_list,
- &self->tostring);
-
+ self->foundation,
+ self->comp_id,
+ _transport_str,
+ self->priority,
+ (tsk_strnullORempty(self->connection_addr) && self->socket) ? self->socket->ip : self->connection_addr,
+ (self->port <= 0 && self->socket) ? self->socket->port : self->port,
+ self->cand_type_str ? self->cand_type_str : _tnet_ice_candidate_get_candtype_str(self->type_e),
+ self->extension_att_list,
+ &self->tostring);
+
/* <rel-addr> and <rel-port>: convey transport addresses related to the
candidate, useful for diagnostics and other purposes. <rel-addr>
and <rel-port> MUST be present for server reflexive, peer
reflexive, and relayed candidates. */
- switch (self->type_e){
- case tnet_ice_cand_type_srflx:
- case tnet_ice_cand_type_prflx:
- case tnet_ice_cand_type_relay:
- {
- if (self->socket){ // when called from the browser(IE, Safari, Opera or Firefox) webrtc4all
- tsk_strcat_2(&self->tostring, " raddr %s rport %d", self->socket->ip, self->socket->port);
- }
- break;
- }
- default:
- {
- break;
+ switch (self->type_e) {
+ case tnet_ice_cand_type_srflx:
+ case tnet_ice_cand_type_prflx:
+ case tnet_ice_cand_type_relay: {
+ if (self->socket) { // when called from the browser(IE, Safari, Opera or Firefox) webrtc4all
+ tsk_strcat_2(&self->tostring, " raddr %s rport %d", self->socket->ip, self->socket->port);
}
+ break;
}
-
+ default: {
+ break;
+ }
+ }
+
// To ease debugging
if (self->socket) {
tsk_strcat_2(&self->tostring, " tr %s", _tnet_ice_candidate_get_transport_str(self->socket->type));
@@ -343,26 +336,26 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self)
tsk_strcat_2(&self->tostring, " fd %d", self->socket->fd);
}
}
-
+
// WebRTC (Chrome) specific
if (self->is_ice_jingle) {
- if (!tsk_params_have_param(self->extension_att_list, "name")){
+ if (!tsk_params_have_param(self->extension_att_list, "name")) {
tsk_strcat_2(&self->tostring, " name %s", self->is_rtp ? (self->is_video ? "video_rtp" : "rtp") : (self->is_video ? "video_rtcp" : "rtcp"));
}
- if (!tsk_params_have_param(self->extension_att_list, "username")){
+ if (!tsk_params_have_param(self->extension_att_list, "username")) {
tsk_strcat_2(&self->tostring, " username %s", self->ufrag);
}
- if (!tsk_params_have_param(self->extension_att_list, "password")){
+ if (!tsk_params_have_param(self->extension_att_list, "password")) {
tsk_strcat_2(&self->tostring, " password %s", self->pwd);
}
- if (!tsk_params_have_param(self->extension_att_list, "network_name")){
+ if (!tsk_params_have_param(self->extension_att_list, "network_name")) {
tsk_strcat_2(&self->tostring, " network_name %s", "{9EBBE687-CCE6-42D3-87F5-B57BB30DEE23}");
}
- if (!tsk_params_have_param(self->extension_att_list, "generation")){
+ if (!tsk_params_have_param(self->extension_att_list, "generation")) {
tsk_strcat_2(&self->tostring, " generation %s", "0");
}
}
-
+
return self->tostring;
}
@@ -371,56 +364,56 @@ int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, const
tnet_stun_pkt_t *request = tsk_null;
tsk_buffer_t *buffer = tsk_null;
int ret, sendBytes;
-
- if (!self || !server_addr || !TNET_SOCKET_IS_VALID(self->socket)){
+
+ if (!self || !server_addr || !TNET_SOCKET_IS_VALID(self->socket)) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
request = _tnet_ice_candidate_stun_create_bind_request(self, username, password);
- if (!request){
+ if (!request) {
TSK_DEBUG_ERROR("Failed to create STUN request");
ret = -2;
goto bail;
}
-
- if ((ret = tnet_stun_pkt_write_with_padding_2(request, &buffer))){
+
+ if ((ret = tnet_stun_pkt_write_with_padding_2(request, &buffer))) {
TSK_DEBUG_ERROR("Failed to serialize STUN request");
goto bail;
}
-
+
sendBytes = tnet_sockfd_sendto(self->socket->fd, (const struct sockaddr*)server_addr, buffer->data, buffer->size);// return number of sent bytes
- if (sendBytes == buffer->size){
+ if (sendBytes == buffer->size) {
memcpy(self->stun.transac_id, request->transac_id, sizeof(tnet_stun_transac_id_t));
ret = 0;
}
- else{
+ else {
TSK_DEBUG_ERROR("Only %d bytes sent", sendBytes);
ret = -4;
goto bail;
}
-
+
bail:
TSK_OBJECT_SAFE_FREE(request);
TSK_OBJECT_SAFE_FREE(buffer);
-
+
return 0;
}
int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_pkt_resp_t* response, tnet_fd_t fd)
{
int ret = 0;
-
- if (!self || !response){
+
+ if (!self || !response) {
TSK_DEBUG_ERROR("Inavlid parameter");
return -1;
}
-
+
//if(!(_tnet_ice_candidate_stun_transac_id_equals(response->transac_id, self->stun.transac_id))){
// TSK_DEBUG_ERROR("Transaction id mismatch");
// return -2;
//}
-
+
if (TNET_STUN_PKT_RESP_IS_ERROR(response)) {
uint16_t u_code;
if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code))) {
@@ -452,7 +445,7 @@ int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const t
else if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) {
const tnet_stun_attr_address_t* pc_attr_addr;
if (((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)
- || ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)) {
+ || ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)) {
tnet_ip_t ip;
if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip))) {
return ret;
@@ -461,7 +454,7 @@ int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const t
self->stun.srflx_port = pc_attr_addr->u_port;
}
}
-
+
return ret;
}
@@ -470,7 +463,7 @@ const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_
if (candidates) {
const tsk_list_item_t *item;
const tnet_ice_candidate_t* candidate;
-
+
tsk_list_lock(candidates);
tsk_list_foreach(item, candidates) {
if (!(candidate = item->data)) {
@@ -482,13 +475,13 @@ const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_
}
}
}
-
+
return tsk_null;
}
const char* tnet_ice_candidate_get_ufrag(const tnet_ice_candidate_t* self)
{
- if (self){
+ if (self) {
return self->ufrag ? self->ufrag : tnet_ice_candidate_get_att_value(self, "username");
}
return tsk_null;
@@ -496,22 +489,22 @@ const char* tnet_ice_candidate_get_ufrag(const tnet_ice_candidate_t* self)
const char* tnet_ice_candidate_get_pwd(const tnet_ice_candidate_t* self)
{
- if (self){
+ if (self) {
return self->pwd ? self->pwd : tnet_ice_candidate_get_att_value(self, "password");
}
return tsk_null;
}
static int _tnet_ice_candidate_tostring(
- uint8_t* foundation,
- uint32_t comp_id,
- const char* transport_str,
- uint32_t priority,
- const char* connection_addr,
- tnet_port_t port,
- const char* cand_type_str,
- const tsk_params_L_t *extension_att_list,
- char** output)
+ uint8_t* foundation,
+ uint32_t comp_id,
+ const char* transport_str,
+ uint32_t priority,
+ const char* connection_addr,
+ tnet_port_t port,
+ const char* cand_type_str,
+ const tsk_params_L_t *extension_att_list,
+ char** output)
{
if (!output) {
TSK_DEBUG_ERROR("Invalid argument");
@@ -525,10 +518,10 @@ static int _tnet_ice_candidate_tostring(
connection_addr,
port,
cand_type_str);
-
+
if (extension_att_list) {
const tsk_list_item_t *item;
- tsk_list_foreach(item, extension_att_list){
+ tsk_list_foreach(item, extension_att_list) {
tsk_strcat_2(output, " %s %s", TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value);
}
}
@@ -537,11 +530,16 @@ static int _tnet_ice_candidate_tostring(
static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type)
{
- switch (type){
- case tnet_ice_cand_type_host: return TNET_ICE_CANDIDATE_FOUNDATION_HOST;
- case tnet_ice_cand_type_srflx: return TNET_ICE_CANDIDATE_FOUNDATION_SRFLX;
- case tnet_ice_cand_type_prflx: return TNET_ICE_CANDIDATE_FOUNDATION_PRFLX;
- case tnet_ice_cand_type_relay: default: return TNET_ICE_CANDIDATE_FOUNDATION_RELAY;
+ switch (type) {
+ case tnet_ice_cand_type_host:
+ return TNET_ICE_CANDIDATE_FOUNDATION_HOST;
+ case tnet_ice_cand_type_srflx:
+ return TNET_ICE_CANDIDATE_FOUNDATION_SRFLX;
+ case tnet_ice_cand_type_prflx:
+ return TNET_ICE_CANDIDATE_FOUNDATION_PRFLX;
+ case tnet_ice_cand_type_relay:
+ default:
+ return TNET_ICE_CANDIDATE_FOUNDATION_RELAY;
}
}
@@ -550,8 +548,8 @@ static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_tra
{
tsk_size_t i;
static const tsk_size_t size = sizeof(tnet_stun_transac_id_t);
- for (i = 0; i < size; i++){
- if (id1[i] != id2[i]){
+ for (i = 0; i < size; i++) {
+ if (id1[i] != id2[i]) {
return tsk_false;
}
}
@@ -562,12 +560,12 @@ static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_c
{
tnet_stun_pkt_t *request = tsk_null;
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
+
if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &request))) {
TSK_DEBUG_ERROR("Failed to create STUN Bind request");
goto bail;
@@ -585,7 +583,7 @@ static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_c
goto bail;
}
}
-
+
bail:
if (ret) {
TSK_OBJECT_SAFE_FREE(request);
@@ -606,7 +604,7 @@ return TNET_ICE_CANDIDATE_TRANSPORT_##STR; \
TRANSPORT_GET(WS);
TRANSPORT_GET(WSS);
return "UNKNOWN";
-
+
#undef TRANSPORT_GET
}
@@ -616,7 +614,7 @@ static tnet_socket_type_t _tnet_ice_candidate_get_transport_type(tsk_bool_t ipv6
if(tsk_striequals(TNET_ICE_CANDIDATE_TRANSPORT_##STR, transport_str)){ \
return tnet_socket_type_##str##_ipv4; \
}
-
+
TRANSPORT_GET(UDP, udp);
TRANSPORT_GET(TCP, tcp);
TRANSPORT_GET(TLS, tls);
@@ -624,37 +622,42 @@ return tnet_socket_type_##str##_ipv4; \
TRANSPORT_GET(WS, ws);
TRANSPORT_GET(WSS, wss);
return tnet_socket_type_invalid;
-
+
#undef TRANSPORT_GET
}
static const char* _tnet_ice_candidate_get_candtype_str(tnet_ice_cand_type_t candtype_e)
{
- switch (candtype_e){
- case tnet_ice_cand_type_unknown:
- default: return "unknown";
- case tnet_ice_cand_type_host: return TNET_ICE_CANDIDATE_TYPE_HOST;
- case tnet_ice_cand_type_srflx: return TNET_ICE_CANDIDATE_TYPE_SRFLX;
- case tnet_ice_cand_type_prflx: return TNET_ICE_CANDIDATE_TYPE_PRFLX;
- case tnet_ice_cand_type_relay: return TNET_ICE_CANDIDATE_TYPE_RELAY;
+ switch (candtype_e) {
+ case tnet_ice_cand_type_unknown:
+ default:
+ return "unknown";
+ case tnet_ice_cand_type_host:
+ return TNET_ICE_CANDIDATE_TYPE_HOST;
+ case tnet_ice_cand_type_srflx:
+ return TNET_ICE_CANDIDATE_TYPE_SRFLX;
+ case tnet_ice_cand_type_prflx:
+ return TNET_ICE_CANDIDATE_TYPE_PRFLX;
+ case tnet_ice_cand_type_relay:
+ return TNET_ICE_CANDIDATE_TYPE_RELAY;
}
}
static tnet_ice_cand_type_t _tnet_ice_candtype_get_transport_type(const char* candtype_str)
{
- if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_HOST, candtype_str)){
+ if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_HOST, candtype_str)) {
return tnet_ice_cand_type_host;
}
- else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_SRFLX, candtype_str)){
+ else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_SRFLX, candtype_str)) {
return tnet_ice_cand_type_srflx;
}
- else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_PRFLX, candtype_str)){
+ else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_PRFLX, candtype_str)) {
return tnet_ice_cand_type_prflx;
}
- else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_RELAY, candtype_str)){
+ else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_RELAY, candtype_str)) {
return tnet_ice_cand_type_relay;
}
- else{
+ else {
return tnet_ice_cand_type_unknown;
}
}
diff --git a/tinyNET/src/ice/tnet_ice_candidate.h b/tinyNET/src/ice/tnet_ice_candidate.h
index d2cb126..749192d 100755
--- a/tinyNET/src/ice/tnet_ice_candidate.h
+++ b/tinyNET/src/ice/tnet_ice_candidate.h
@@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -59,54 +59,52 @@ TNET_BEGIN_DECLS
#define TNET_ICE_CANDIDATE_FOUND_SIZE_PREF 15
-typedef enum tnet_ice_cand_type_e
-{
- tnet_ice_cand_type_unknown,
- tnet_ice_cand_type_host,
- tnet_ice_cand_type_srflx,
- tnet_ice_cand_type_prflx,
- tnet_ice_cand_type_relay
+typedef enum tnet_ice_cand_type_e {
+ tnet_ice_cand_type_unknown,
+ tnet_ice_cand_type_host,
+ tnet_ice_cand_type_srflx,
+ tnet_ice_cand_type_prflx,
+ tnet_ice_cand_type_relay
}
tnet_ice_cand_type_t;
-typedef struct tnet_ice_candidate_s
-{
- TSK_DECLARE_OBJECT;
-
- tnet_ice_cand_type_t type_e;
- uint8_t foundation[33]; // 1*32ice-char
- uint32_t comp_id; // 1*5DIGIT
- char* transport_str; // "UP" / token
- enum tnet_socket_type_e transport_e;
- uint32_t priority; // 1*10DIGIST [1 - (2**31 - 1)]
- char* cand_type_str; // "host" / "srflx" / "prflx" / "relay" / "token"
- tnet_ip_t connection_addr;
- tnet_port_t port;
- tsk_params_L_t *extension_att_list;
-
- tsk_bool_t is_ice_jingle;
- tsk_bool_t is_rtp;
- tsk_bool_t is_video;
- uint16_t local_pref; // [0 - 65535]
-
- char* ufrag;
- char* pwd;
-
- struct tnet_socket_s* socket;
- struct{
- char* nonce;
- char* realm;
- char* srflx_addr;
- tnet_stun_transac_id_t transac_id;
- tnet_port_t srflx_port;
- } stun;
- struct {
- struct tnet_turn_session_s* ss;
- char* relay_addr;
- tnet_port_t relay_port;
- } turn;
-
- char *tostring;
+typedef struct tnet_ice_candidate_s {
+ TSK_DECLARE_OBJECT;
+
+ tnet_ice_cand_type_t type_e;
+ uint8_t foundation[33]; // 1*32ice-char
+ uint32_t comp_id; // 1*5DIGIT
+ char* transport_str; // "UP" / token
+ enum tnet_socket_type_e transport_e;
+ uint32_t priority; // 1*10DIGIST [1 - (2**31 - 1)]
+ char* cand_type_str; // "host" / "srflx" / "prflx" / "relay" / "token"
+ tnet_ip_t connection_addr;
+ tnet_port_t port;
+ tsk_params_L_t *extension_att_list;
+
+ tsk_bool_t is_ice_jingle;
+ tsk_bool_t is_rtp;
+ tsk_bool_t is_video;
+ uint16_t local_pref; // [0 - 65535]
+
+ char* ufrag;
+ char* pwd;
+
+ struct tnet_socket_s* socket;
+ struct {
+ char* nonce;
+ char* realm;
+ char* srflx_addr;
+ tnet_stun_transac_id_t transac_id;
+ tnet_port_t srflx_port;
+ } stun;
+ struct {
+ struct tnet_turn_session_s* ss;
+ char* relay_addr;
+ tnet_port_t relay_port;
+ } turn;
+
+ char *tostring;
}
tnet_ice_candidate_t;
diff --git a/tinyNET/src/ice/tnet_ice_ctx.c b/tinyNET/src/ice/tnet_ice_ctx.c
index 94d3042..6e5e5be 100755
--- a/tinyNET/src/ice/tnet_ice_ctx.c
+++ b/tinyNET/src/ice/tnet_ice_ctx.c
@@ -84,8 +84,7 @@ typedef tsk_list_t tnet_ice_servers_L_t;
static const char* foundation_default = tsk_null;
-typedef enum tnet_ice_server_proto_e
-{
+typedef enum tnet_ice_server_proto_e {
tnet_ice_server_proto_none = 0x00,
tnet_ice_server_proto_stun = (0x01 << 0),
tnet_ice_server_proto_turn = (0x01 << 1),
@@ -134,10 +133,9 @@ static int _tnet_ice_ctx_fsm_OnTerminated(struct tnet_ice_ctx_s* self);
static tsk_bool_t _tnet_ice_ctx_fsm_cond_NotStarted(struct tnet_ice_ctx_s* self, const void* _any);
static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs *e);
-typedef struct tnet_ice_server_s
-{
+typedef struct tnet_ice_server_s {
TSK_DECLARE_OBJECT;
-
+
enum tnet_socket_type_e e_transport;
tnet_ice_server_proto_t e_proto;
char* str_server_addr;
@@ -165,13 +163,12 @@ static tsk_object_t* tnet_ice_server_dtor(tsk_object_t * self)
TSK_FREE(ice_server->str_software);
TSK_FREE(ice_server->str_username);
TSK_FREE(ice_server->str_password);
-
+
TSK_DEBUG_INFO("*** ICE server destroyed ***");
}
return self;
}
-static const tsk_object_def_t tnet_ice_server_def_s =
-{
+static const tsk_object_def_t tnet_ice_server_def_s = {
sizeof(tnet_ice_server_t),
tnet_ice_server_ctor,
tnet_ice_server_dtor,
@@ -179,25 +176,25 @@ static const tsk_object_def_t tnet_ice_server_def_s =
};
static tnet_ice_server_t* tnet_ice_server_create(
- enum tnet_ice_server_proto_e e_proto,
- enum tnet_socket_type_e e_transport,
- const char* str_server_addr, uint16_t u_server_port,
- const char* str_software,
- const char* str_username, const char* str_password)
+ enum tnet_ice_server_proto_e e_proto,
+ enum tnet_socket_type_e e_transport,
+ const char* str_server_addr, uint16_t u_server_port,
+ const char* str_software,
+ const char* str_username, const char* str_password)
{
tnet_ice_server_t *ice_server;
struct sockaddr_storage obj_server_addr;
-
+
if (tsk_strnullORempty(str_server_addr) || !u_server_port) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
+
if (tnet_sockaddr_init(str_server_addr, u_server_port, e_transport, &obj_server_addr) != 0) {
TSK_DEBUG_ERROR("Invalid server address (host=%s, port=%d, transport=%d)", str_server_addr, u_server_port, e_transport);
return tsk_null;
}
-
+
if ((ice_server = tsk_object_new(&tnet_ice_server_def_s))) {
ice_server->e_proto = e_proto;
ice_server->e_transport = e_transport;
@@ -211,10 +208,9 @@ static tnet_ice_server_t* tnet_ice_server_create(
return ice_server;
}
-typedef struct tnet_ice_ctx_s
-{
+typedef struct tnet_ice_ctx_s {
TSK_DECLARE_RUNNABLE;
-
+
tsk_bool_t is_started;
tsk_bool_t is_active;
tsk_bool_t is_sync_mode;
@@ -229,7 +225,7 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t unicast;
tsk_bool_t anycast;
tsk_bool_t multicast;
-
+
tsk_bool_t is_connchecking;
tsk_bool_t is_controlling;
tsk_bool_t is_ice_jingle;
@@ -237,19 +233,19 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t is_stun_enabled;
uint64_t tie_breaker;
uint64_t concheck_timeout;
-
+
const void* rtp_callback_data;
tnet_ice_rtp_callback_f rtp_callback;
-
+
tnet_ice_servers_L_t *servers;
-
+
char* ufrag;
char* pwd;
-
+
tsk_timer_manager_handle_t* h_timer_mgr;
-
+
tsk_fsm_t* fsm;
-
+
tsk_condwait_handle_t* condwait_pairs;
tnet_ice_candidates_L_t* candidates_local;
tnet_ice_candidates_L_t* candidates_remote;
@@ -257,23 +253,23 @@ typedef struct tnet_ice_ctx_s
tsk_bool_t have_nominated_offer;
tsk_bool_t have_nominated_answer;
tsk_bool_t have_nominated_symetric; /**< Whether symetic RTP has been negotiated */
-
+
uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond */
uint16_t Rc; /**< Number of retransmissions for UDP in millisecond */
-
+
struct {
char* path_priv;
char* path_pub;
char* path_ca;
tsk_bool_t verify;
} ssl;
-
+
struct {
tsk_bool_t auto_detect;
struct tnet_proxyinfo_s* info;
}
proxy;
-
+
struct {
tsk_condwait_handle_t* condwait;
struct tnet_turn_session_s* ss_nominated_rtp;
@@ -281,21 +277,19 @@ typedef struct tnet_ice_ctx_s
struct tnet_turn_session_s* ss_nominated_rtcp;
tnet_turn_peer_id_t peer_id_rtcp;
} turn;
-
+
TSK_DECLARE_SAFEOBJ;
}
tnet_ice_ctx_t;
-typedef struct tnet_ice_action_s
-{
+typedef struct tnet_ice_action_s {
TSK_DECLARE_OBJECT;
-
+
tsk_fsm_action_id id;
}
tnet_ice_action_t;
-typedef enum _fsm_state_e
-{
+typedef enum _fsm_state_e {
_fsm_state_Started,
_fsm_state_GatheringHostCandidates,
_fsm_state_GatheringHostCandidatesDone,
@@ -310,8 +304,7 @@ typedef enum _fsm_state_e
}
_fsm_state_t;
-typedef enum _fsm_action_e
-{
+typedef enum _fsm_action_e {
_fsm_action_Success,
_fsm_action_Failure,
_fsm_action_GatherHostCandidates,
@@ -327,19 +320,18 @@ _fsm_action_t;
static tsk_object_t* tnet_ice_action_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_action_t *action = self;
- if (action){
+ if (action) {
}
return self;
}
static tsk_object_t* tnet_ice_action_dtor(tsk_object_t * self)
{
tnet_ice_action_t *action = self;
- if (action){
+ if (action) {
}
return self;
}
-static const tsk_object_def_t tnet_ice_action_def_s =
-{
+static const tsk_object_def_t tnet_ice_action_def_s = {
sizeof(tnet_ice_action_t),
tnet_ice_action_ctor,
tnet_ice_action_dtor,
@@ -348,7 +340,7 @@ static const tsk_object_def_t tnet_ice_action_def_s =
static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id)
{
tnet_ice_action_t *action = tsk_object_new(&tnet_ice_action_def_s);
- if (action){
+ if (action) {
action->id = id;
}
return action;
@@ -360,59 +352,59 @@ static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id)
static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_ctx_t *ctx = self;
- if (ctx){
+ if (ctx) {
tsk_safeobj_init(ctx);
-
- if (!(ctx->h_timer_mgr = tsk_timer_manager_create())){
+
+ if (!(ctx->h_timer_mgr = tsk_timer_manager_create())) {
TSK_DEBUG_ERROR("Failed to create timer manager");
return tsk_null;
}
- if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))){
+ if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))) {
TSK_DEBUG_ERROR("Failed to create state machine");
return tsk_null;
}
- if (!(ctx->candidates_local = tsk_list_create())){
+ if (!(ctx->candidates_local = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
- if (!(ctx->candidates_remote = tsk_list_create())){
+ if (!(ctx->candidates_remote = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
- if (!(ctx->candidates_pairs = tsk_list_create())){
+ if (!(ctx->candidates_pairs = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create candidates list");
return tsk_null;
}
-
+
// Create condwait for pairs
if (!(ctx->condwait_pairs = tsk_condwait_create())) {
TSK_DEBUG_ERROR("Failed to create condwait for pairs");
return tsk_null;
}
-
+
// Create list objects to hold the servers
- if (!(ctx->servers = tsk_list_create())){
+ if (!(ctx->servers = tsk_list_create())) {
TSK_DEBUG_ERROR("Failed to create server list");
return tsk_null;
}
-
+
tsk_runnable_set_important(TSK_RUNNABLE(self), tsk_false);
-
+
/* 7.2.1. Sending over UDP
In fixed-line access links, a value of 500 ms is RECOMMENDED.
*/
ctx->RTO = kIceDefaultRTO;
-
+
/* 7.2.1. Sending over UDP
Rc SHOULD be configurable and SHOULD have a default of 7.
*/
ctx->Rc = kIceDefaultRC;
-
+
ctx->tie_breaker = ((tsk_time_now() << 32) ^ tsk_time_now());
ctx->is_ice_jingle = tsk_false;
ctx->is_stun_enabled = kIceDefaultStunEnabled;
ctx->is_turn_enabled = kIceDefaultTurnEnabled;
-
+
ctx->concheck_timeout = LONG_MAX;
}
return self;
@@ -420,17 +412,17 @@ static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app)
static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self)
{
tnet_ice_ctx_t *ctx = self;
- if (ctx){
+ if (ctx) {
tnet_ice_ctx_stop(ctx);
- if (ctx->h_timer_mgr){
+ if (ctx->h_timer_mgr) {
tsk_timer_manager_destroy(&ctx->h_timer_mgr);
}
-
+
TSK_OBJECT_SAFE_FREE(ctx->fsm);
TSK_OBJECT_SAFE_FREE(ctx->candidates_local);
TSK_OBJECT_SAFE_FREE(ctx->candidates_remote);
TSK_OBJECT_SAFE_FREE(ctx->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
if (ctx->turn.condwait) {
@@ -440,20 +432,19 @@ static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self)
tsk_condwait_destroy(&ctx->condwait_pairs);
}
TSK_OBJECT_SAFE_FREE(ctx->servers);
-
+
TSK_OBJECT_SAFE_FREE(ctx->proxy.info);
-
+
TSK_FREE(ctx->ssl.path_priv);
TSK_FREE(ctx->ssl.path_pub);
TSK_FREE(ctx->ssl.path_ca);
-
+
tsk_safeobj_deinit(ctx);
}
TSK_DEBUG_INFO("*** ICE context destroyed ***");
return self;
}
-static const tsk_object_def_t tnet_ice_ctx_def_s =
-{
+static const tsk_object_def_t tnet_ice_ctx_def_s = {
sizeof(tnet_ice_ctx_t),
tnet_ice_ctx_ctor,
tnet_ice_ctx_dtor,
@@ -464,12 +455,12 @@ static const tsk_object_def_t tnet_ice_ctx_def_s =
tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv6, tsk_bool_t use_rtcp, tsk_bool_t is_video, tnet_ice_callback_f callback, const void* userdata)
{
tnet_ice_ctx_t* ctx;
-
- if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))){
+
+ if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))) {
TSK_DEBUG_ERROR("Failed to create ICE context object");
return tsk_null;
}
-
+
ctx->is_ice_jingle = is_ice_jingle;
ctx->use_ipv6 = use_ipv6;
ctx->use_rtcp = use_rtcp;
@@ -479,10 +470,10 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
ctx->unicast = tsk_true;
ctx->anycast = tsk_false;
ctx->multicast = tsk_false;
-
+
tnet_ice_utils_set_ufrag(&ctx->ufrag);
tnet_ice_utils_set_pwd(&ctx->pwd);
-
+
ctx->fsm->debug = TNET_ICE_DEBUG_STATE_MACHINE;
tsk_fsm_set_callback_terminated(ctx->fsm, TSK_FSM_ONTERMINATED_F(_tnet_ice_ctx_fsm_OnTerminated), (const void*)ctx);
tsk_fsm_set(ctx->fsm,
@@ -492,14 +483,14 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Success, _fsm_state_GatheringHostCandidatesDone, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success, "ICE_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success"),
// (GatheringHostCandidates) -> (Failure) -> (Terminated)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure, "ICE_GatheringHostCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringHostCandidatesDone) -> (GatherReflexiveCandidates) -> (GatheringReflexiveCandidates)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidatesDone, _fsm_action_GatherReflexiveCandidates, _fsm_state_GatheringReflexiveCandidates, _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates, "ICE_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates"),
// (GatheringReflexiveCandidates) -> (Success) -> GatheringReflexiveCandidatesDone
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Success, _fsm_state_GatheringReflexiveCandidatesDone, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success, "ICE_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success"),
// (GatheringReflexiveCandidates) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_Terminated_X_Failure, "ICE_GatheringReflexiveCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringReflexiveCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates)
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidatesDone, _fsm_action_GatherRelayCandidates, _fsm_state_GatheringRelayCandidates, _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates, "ICE_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates"),
// (GatheringHostCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates)
@@ -508,28 +499,28 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Success, _fsm_state_GatheringRelayCandidatesDone, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success, "ICE_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success"),
// (GatheringRelayCandidates) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_Terminated_X_Failure, "ICE_GatheringRelayCandidates_2_Terminated_X_Failure"),
-
+
// (GatheringComplet) -> (ConnCheck) -> ConnChecking
TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringCompleted, _fsm_action_ConnCheck, _fsm_state_ConnChecking, _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck, "ICE_GatheringCompleted_2_ConnChecking_X_ConnCheck"),
// (ConnChecking) -> (Success) -> ConnCheckingCompleted
TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Success, _fsm_state_ConnCheckingCompleted, _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success, "ICE_ConnChecking_2_ConnCheckingCompleted_X_Success"),
// (ConnChecking) -> (Failure) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_ConnChecking_2_Terminated_X_Failure, "ICE_ConnChecking_2_Terminated_X_Failure"),
-
+
// (Any) -> (GatheringComplet) -> GatheringCompleted
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_GatheringComplet, _fsm_state_GatheringCompleted, _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet, "ICE_Any_2_GatheringCompleted_X_GatheringComplet"),
// (Any) -> (Cancel) -> Started
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_Cancel, _fsm_state_Started, _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel, "ICE_Any_2_Started_X_Cancel"),
// (Any) -> (AnyNotStarted) -> Terminated
TSK_FSM_ADD(tsk_fsm_state_any, tsk_fsm_action_any, _tnet_ice_ctx_fsm_cond_NotStarted, _fsm_state_Terminated, _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted, "ICE_fsm_Any_2_Terminated_X_AnyNotStarted")
- );
-
+ );
+
return ctx;
}
int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -539,34 +530,34 @@ int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata)
// @deprecated: use "tnet_ice_ctx_add_server()"
int tnet_ice_ctx_set_stun(
- tnet_ice_ctx_t* self,
- const char* server_addr,
- uint16_t server_port,
- const char* software,
- const char* username,
- const char* password)
+ tnet_ice_ctx_t* self,
+ const char* server_addr,
+ uint16_t server_port,
+ const char* software,
+ const char* username,
+ const char* password)
{
_tnet_ice_ctx_servers_clear(self);
return tnet_ice_ctx_add_server(
- self,
- "udp",
- server_addr,
- server_port,
- (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/
- tsk_true, /* use_stun*/
- username,
- password);
+ self,
+ "udp",
+ server_addr,
+ server_port,
+ (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/
+ tsk_true, /* use_stun*/
+ username,
+ password);
}
int tnet_ice_ctx_add_server(
- struct tnet_ice_ctx_s* self,
- const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"
- const char* server_addr,
- uint16_t server_port,
- tsk_bool_t use_turn,
- tsk_bool_t use_stun,
- const char* username,
- const char* password)
+ struct tnet_ice_ctx_s* self,
+ const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"
+ const char* server_addr,
+ uint16_t server_port,
+ tsk_bool_t use_turn,
+ tsk_bool_t use_stun,
+ const char* username,
+ const char* password)
{
tnet_socket_type_t socket_type;
tnet_ice_server_proto_t e_proto = tnet_ice_server_proto_none;
@@ -584,7 +575,7 @@ int tnet_ice_ctx_add_server(
if (use_turn) {
e_proto |= tnet_ice_server_proto_turn;
}
-
+
if (tsk_striequals(transport_proto, "udp")) {
socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4;
}
@@ -612,7 +603,7 @@ int tnet_ice_ctx_add_server(
int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -622,7 +613,7 @@ int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode)
int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_mode)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -633,7 +624,7 @@ int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_
// Whether to gather reflexive candidates
int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_enabled)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -644,7 +635,7 @@ int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_e
// Whether to gather relay candidates
int tnet_ice_ctx_set_turn_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t turn_enabled)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -658,19 +649,19 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self)
tsk_bool_t timer_mgr_started = tsk_false;
tsk_bool_t runnable_started = tsk_false;
const char* err = tsk_null;
-
- if (!self){
+
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
-
+
TSK_DEBUG_INFO("tnet_ice_ctx_start");
-
- if (self->is_started){
+
+ if (self->is_started) {
ret = 0;
- if (!self->is_active){
+ if (!self->is_active) {
TSK_DEBUG_INFO("ICE restart");
ret = _tnet_ice_ctx_restart(self);
}
@@ -678,42 +669,42 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self)
tsk_safeobj_unlock(self);
return ret;
}
-
+
/* === Timer manager === */
- if ((ret = tsk_timer_manager_start(self->h_timer_mgr))){
+ if ((ret = tsk_timer_manager_start(self->h_timer_mgr))) {
err = "Failed to start timer manager";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
timer_mgr_started = tsk_true;
-
+
/* === Runnable === */
TSK_RUNNABLE(self)->run = _tnet_ice_ctx_run;
- if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))){
+ if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))) {
err = "Failed to start runnable";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
runnable_started = tsk_true;
-
+
self->is_started = tsk_true; // needed by FSM -> "Must" be before fsm_ast()
self->is_active = tsk_true;
-
- if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))){
+
+ if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))) {
err = "FSM execution failed";
TSK_DEBUG_ERROR("%s", err);
goto bail;
}
-
+
bail:
tsk_safeobj_unlock(self);
-
- if (ret){
+
+ if (ret) {
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_start_failed, err);
- if (timer_mgr_started){
+ if (timer_mgr_started) {
tsk_timer_manager_stop(self->h_timer_mgr);
}
- if (runnable_started){
+ if (runnable_started) {
tsk_runnable_stop(TSK_RUNNABLE(self));
}
self->is_started = tsk_false;
@@ -725,11 +716,11 @@ bail:
// register callback to call when we receive early RTP packets while negotaiating ICE pairs
int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_callback, const void* rtp_callback_data)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->rtp_callback_data = rtp_callback_data;
self->rtp_callback = rtp_callback;
return 0;
@@ -738,13 +729,13 @@ int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_
// timeout (millis): <=0 to disable
int tnet_ice_ctx_set_concheck_timeout(tnet_ice_ctx_t* self, int64_t timeout)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->concheck_timeout = (timeout <= 0 ? LONG_MAX : timeout);
-
+
return 0;
}
@@ -761,34 +752,34 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->is_controlling = is_controlling;
self->is_ice_jingle = is_ice_jingle;
tnet_ice_ctx_set_rtcpmux(self, use_rtcpmux);
-
+
if (tsk_strnullORempty(candidates)) {
// remote party is ICE-lite or doesn't support ICE
return tnet_ice_ctx_cancel(self);
}
-
+
TSK_DEBUG_INFO("tnet_ice_ctx_set_remote_candidates(ufrag=%s, pwd=%s, is_controlling=%d, is_ice_jingle=%d, use_rtcpmux=%d)",
ufrag, pwd, is_controlling, is_ice_jingle, use_rtcpmux);
-
+
tsk_list_lock(self->candidates_pairs);
if (!TSK_LIST_IS_EMPTY(self->candidates_pairs)) {
TSK_DEBUG_WARN("Adding Remote ICE candidates after pairs building");
}
tsk_list_unlock(self->candidates_pairs);
-
+
// active if remote is full-ICE
// in all case we are always full-ICE
// self->is_active = tsk_true;
-
+
tsk_list_lock(self->candidates_remote);
-
+
// clear old candidates
tsk_list_clear_items(self->candidates_remote);
-
+
copy = tsk_strdup(candidates);
size = (tsk_size_t)tsk_strlen(copy);
do {
@@ -819,13 +810,14 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char
}
TSK_OBJECT_SAFE_FREE(candidate);
}
- } while (v && (idx < size));
-
+ }
+ while (v && (idx < size));
+
tsk_list_unlock(self->candidates_remote);
-
+
TSK_FREE(copy);
TSK_OBJECT_SAFE_FREE(added_candidates);
-
+
if (!tnet_ice_ctx_is_connected(self) && tnet_ice_ctx_got_local_candidates(self) && !TSK_LIST_IS_EMPTY(self->candidates_remote)) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck);
}
@@ -866,7 +858,7 @@ int tnet_ice_ctx_set_ssl_certs(struct tnet_ice_ctx_s* self, const char* path_pri
tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return 0;
}
@@ -876,16 +868,16 @@ tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self)
tsk_bool_t tnet_ice_ctx_got_local_candidates(const tnet_ice_ctx_t* self)
{
tsk_fsm_state_id curr_state;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_false;
}
- if (!self->is_started){
+ if (!self->is_started) {
return tsk_false;
}
-
+
curr_state = tsk_fsm_get_current_state(self->fsm);
-
+
return (curr_state >= _fsm_state_GatheringCompleted && curr_state < _fsm_state_Terminated);
}
@@ -893,13 +885,13 @@ const tnet_ice_candidate_t* tnet_ice_ctx_get_local_candidate_at(const tnet_ice_c
{
const tsk_list_item_t *item;
tsk_size_t pos = 0;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
- tsk_list_foreach(item, self->candidates_local){
- if (pos++ == index){
+
+ tsk_list_foreach(item, self->candidates_local) {
+ if (pos++ == index) {
return (const tnet_ice_candidate_t*)item->data;
}
}
@@ -922,9 +914,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtp_active(const struct tnet_ice_ctx_s* self)
{
tsk_bool_t b_active;
return tnet_ice_ctx_is_active(self)
- && self->turn.ss_nominated_rtp
- && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0
- && b_active;
+ && self->turn.ss_nominated_rtp
+ && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0
+ && b_active;
}
tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self)
@@ -935,9 +927,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self)
else {
tsk_bool_t b_active;
return tnet_ice_ctx_is_active(self)
- && self->turn.ss_nominated_rtcp
- && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0
- && b_active;
+ && self->turn.ss_nominated_rtcp
+ && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0
+ && b_active;
}
}
@@ -968,11 +960,11 @@ tsk_bool_t tnet_ice_ctx_use_rtcp(const tnet_ice_ctx_t* self)
}
int tnet_ice_ctx_get_nominated_symetric_candidates(const tnet_ice_ctx_t* self, uint32_t comp_id,
- const tnet_ice_candidate_t** candidate_offer,
- const tnet_ice_candidate_t** candidate_answer_src,
- const tnet_ice_candidate_t** candidate_answer_dest)
+ const tnet_ice_candidate_t** candidate_offer,
+ const tnet_ice_candidate_t** candidate_answer_src,
+ const tnet_ice_candidate_t** candidate_answer_dest)
{
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -993,14 +985,14 @@ int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, ts
int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size)
{
return self->use_rtcpmux
- ? tnet_ice_ctx_send_turn_rtp(self, data, size)
- : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size);
+ ? tnet_ice_ctx_send_turn_rtp(self, data, size)
+ : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size);
}
int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_t* bytes_in, uint64_t* bytes_out)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
@@ -1010,8 +1002,12 @@ int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_
uint64_t _bytes_in, _bytes_out;
ret = tnet_turn_session_get_bytes_count(self->turn.ss_nominated_rtcp, &_bytes_in, &_bytes_out);
if (ret == 0) {
- if (bytes_in) *bytes_in += _bytes_in;
- if (bytes_out) *bytes_out += _bytes_out;
+ if (bytes_in) {
+ *bytes_in += _bytes_in;
+ }
+ if (bytes_out) {
+ *bytes_out += _bytes_out;
+ }
}
}
return ret;
@@ -1058,19 +1054,19 @@ int tnet_ice_ctx_set_proxy_info(struct tnet_ice_ctx_s* self, enum tnet_proxy_typ
int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
if (tsk_fsm_get_current_state(self->fsm) == _fsm_state_Started) {
// Do nothing if already in the "started" state
ret = 0;
goto bail;
}
-
+
self->is_active = tsk_false;
self->have_nominated_symetric = tsk_false;
self->have_nominated_answer = tsk_false;
@@ -1080,7 +1076,7 @@ int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self)
ret = tsk_condwait_broadcast(self->turn.condwait);
}
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Cancel);
-
+
bail:
tsk_safeobj_unlock(self);
return ret;
@@ -1089,18 +1085,18 @@ bail:
int tnet_ice_ctx_stop(tnet_ice_ctx_t* self)
{
int ret;
-
+
if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
tsk_safeobj_lock(self);
if (!self->is_started) {
ret = 0;
goto bail;
}
-
+
self->is_started = tsk_false;
tsk_condwait_broadcast(self->condwait_pairs);
if (self->turn.condwait) {
@@ -1108,7 +1104,7 @@ int tnet_ice_ctx_stop(tnet_ice_ctx_t* self)
}
ret = tsk_timer_manager_stop(self->h_timer_mgr);
ret = tsk_runnable_stop(TSK_RUNNABLE(self));
-
+
bail:
tsk_safeobj_unlock(self);
return ret;
@@ -1136,92 +1132,92 @@ static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandi
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)){
+ if (!addresses || TSK_LIST_IS_EMPTY(addresses)) {
TSK_DEBUG_ERROR("Failed to get addresses");
ret = -1;
goto bail;
}
-
-
+
+
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;
-
+
// lock-list
tsk_list_lock(self->candidates_local);
// clear-list
tsk_list_clear_items(self->candidates_local);
-
- tsk_list_foreach(item, addresses){
- if (!(address = item->data)){
+
+ tsk_list_foreach(item, addresses) {
+ if (!(address = item->data)) {
continue;
}
-
+
// Skip loopback address to avoid problems :)
- if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))){
+ if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))) {
continue;
}
-
+
// host candidates
ret = tnet_ice_utils_create_sockets(socket_type,
address->ip, &socket_rtp,
self->use_rtcp ? &socket_rtcp : tsk_null);
- if (ret == 0){
+ if (ret == 0) {
const char* foundation_rtp = foundation_default;
tsk_list_lock(self->candidates_local);
- if (socket_rtp){
- if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))){
+ if (socket_rtp) {
+ if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))) {
foundation_rtp = (const char*)candidate->foundation;
- if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))){
+ if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))) {
curr_local_pref = 0xFFFF;
check_best_local_ip = tsk_false;
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_front_data(self->candidates_local, (void**)&candidate);
}
- else{
+ else {
curr_local_pref = local_pref--;
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_back_data(self->candidates_local, (void**)&candidate);
}
}
}
- if (socket_rtcp){
- if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))){
+ if (socket_rtcp) {
+ if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))) {
tnet_ice_candidate_set_local_pref(candidate, curr_local_pref);
tsk_list_push_back_data(self->candidates_local, (void**)&candidate);
}
}
tsk_list_unlock(self->candidates_local);
}
-
+
TSK_OBJECT_SAFE_FREE(socket_rtp);
TSK_OBJECT_SAFE_FREE(socket_rtcp);
-
+
// break if no longer running
- if (!self->is_started){
+ if (!self->is_started) {
break;
}
-
+
TSK_DEBUG_INFO("local ip address = %s", address->ip);
}
-
+
// unlock-list
tsk_list_unlock(self->candidates_local);
-
+
bail:
- if (self->is_started){
- if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)){
+ if (self->is_started) {
+ if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success);
}
- else{
+ else {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
TSK_OBJECT_SAFE_FREE(addresses);
return ret;
}
@@ -1231,9 +1227,9 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
{
int ret;
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_succeed, "Gathering host candidates succeed");
if (ret == 0) {
if (self->is_stun_enabled && _tnet_ice_ctx_servers_count_by_proto(self, tnet_ice_server_proto_stun) > 0) {
@@ -1251,7 +1247,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
}
}
}
-
+
return ret;
}
@@ -1259,7 +1255,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo
static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure(va_list *app)
{
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_failed, "Gathering host candidates failed");
}
@@ -1287,16 +1283,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
fd_set set;
tsk_size_t srflx_addr_count_added = 0, srflx_addr_count_skipped = 0, host_addr_count = 0;
long tv_sec, tv_usec; //very important to save these values as timeval could be modified by select() - happens on iOS -
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
// Get ICE servers to use to gather reflexive candidates
ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_stun);
if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) { // not expected to be null or empty because we checked the number of such servers before calling this transition
TSK_DEBUG_WARN("No valid STUN server could be used to gather reflexive candidates");
goto bail;
}
-
+
// set all default values to -1
// = {{ -1 }} will only set the first element
for (i = 0; i < sizeof(fds) / sizeof(fds[0]); ++i) {
@@ -1305,17 +1301,17 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
for (i = 0; i < sizeof(fds_skipped) / sizeof(fds_skipped[0]); ++i) {
fds_skipped[i] = TNET_INVALID_FD;
}
-
+
rc = self->Rc;
tv.tv_sec = tv_sec = 0;
tv.tv_usec = tv_usec = 0;
-
+
// load fds for both rtp and rtcp sockets
tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = item->data)) {
continue;
}
-
+
++host_addr_count;
if ((fds_count < sizeof(fds) / sizeof(fds[0])) && candidate->socket) {
fds[fds_count++] = candidate->socket->fd;
@@ -1324,13 +1320,13 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
}
}
}
-
-
+
+
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
-
+
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for (i = 0; (i < rc && self->is_started && ((srflx_addr_count_added + srflx_addr_count_skipped) < host_addr_count)); ++i) {
@@ -1362,16 +1358,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
#else
tv.tv_usec = tv_usec;
#endif
-
+
TSK_DEBUG_INFO("ICE reflexive candidates gathering ...srv_addr=%s,srv_port=%u,tv_sec=%lu,tv_usec=%lu,rto=%d", ice_server->str_server_addr, ice_server->u_server_port, tv_sec, tv_usec, ice_server->rto);
-
+
FD_ZERO(&set);
for (k = 0; k < fds_count; ++k) {
FD_SET(fds[k], &set);
}
-
+
// sends STUN binding requets
- tsk_list_foreach(item, self->candidates_local){
+ tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = (tnet_ice_candidate_t*)item->data)) {
continue;
}
@@ -1379,7 +1375,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
ret = tnet_ice_candidate_send_stun_bind_request(candidate, &ice_server->obj_server_addr, ice_server->str_username, ice_server->str_password);
}
}
-
+
if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) {
TSK_DEBUG_ERROR("select() failed with error code = %d", tnet_geterrno());
goto bail;
@@ -1398,27 +1394,27 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
unsigned int len = 0;
void* data = 0;
const tnet_ice_candidate_t* candidate_curr;
-
+
// Check how many bytes are pending
if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) {
TSK_DEBUG_ERROR("tnet_ioctlt() failed");
continue;
}
-
+
if (len == 0) {
TSK_DEBUG_INFO("tnet_ioctlt() retured zero bytes");
continue;
}
-
+
// Receive pending data
data = tsk_calloc(len, sizeof(uint8_t));
if ((ret = tnet_sockfd_recv(fd, data, len, 0)) < 0) {
TSK_FREE(data);
-
+
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
continue;
}
-
+
// Parse the incoming response
if ((ret = tnet_stun_pkt_read(data, (tsk_size_t)ret, &response))) {
TSK_FREE(data);
@@ -1435,7 +1431,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
tsk_size_t j;
tsk_bool_t already_skipped = tsk_false;
/* refc 5245- 4.1.3. Eliminating Redundant Candidates
-
+
Next, the agent eliminates redundant candidates. A candidate is
redundant if its transport address equals another candidate, and its
base equals the base of that other candidate. Note that two
@@ -1450,7 +1446,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
break;
}
}
-
+
if (!already_skipped) {
++srflx_addr_count_skipped;
fds_skipped[j] = fd;
@@ -1488,19 +1484,21 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan
}
} // tsk_list_foreach (item, ice_servers)...
} // for (i = 0; (i < rc....
-
+
bail:
TSK_DEBUG_INFO("srflx_addr_count_added=%u, srflx_addr_count_skipped=%u", (unsigned)srflx_addr_count_added, (unsigned)srflx_addr_count_skipped);
- if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) ret = 0; // Hack the returned value if we have at least one success (happens when timeouts)
+ if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) {
+ ret = 0; // Hack the returned value if we have at least one success (happens when timeouts)
+ }
if (self->is_started) {
if (ret == 0) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success);
}
- else{
+ else {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
tsk_list_foreach(item, self->candidates_local) {
if (!(candidate = (tnet_ice_candidate_t*)item->data)) {
continue;
@@ -1515,9 +1513,9 @@ bail:
static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success(va_list *app)
{
tnet_ice_ctx_t* self;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
if (self->is_started) {
int ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_reflexive_candidates_succeed, "Gathering reflexive candidates succeed");
if (ret == 0) {
@@ -1560,19 +1558,19 @@ static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCa
tnet_ice_servers_L_t* ice_servers = tsk_null;
tnet_ice_server_t* ice_server;
tnet_ice_candidates_L_t* candidates_local_copy = tsk_null;;
-
+
// Create TURN condwait handle if not already done
if (!self->turn.condwait && !(self->turn.condwait = tsk_condwait_create())) {
TSK_DEBUG_ERROR("Failed to create TURN condwait handle");
ret = -2;
goto bail;
}
-
+
// Copy local ICE candidates
tsk_list_lock(self->candidates_local);
candidates_local_copy = tsk_list_clone(self->candidates_local);
tsk_list_unlock(self->candidates_local);
-
+
// Take reference to the TURN servers
ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_turn);
if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) {
@@ -1595,14 +1593,14 @@ next_server:
goto bail;
}
ice_server = (tnet_ice_server_t*)item_server->data;
-
+
// Create TURN sessions for each local host candidate
tsk_list_foreach(item, candidates_local_copy) {
if (!(candidate = item->data)) {
continue;
}
TSK_DEBUG_INFO("Gathering relay candidate: local addr=%s=%d, TURN server=%s:%d", candidate->connection_addr, candidate->port, ice_server->str_server_addr, ice_server->u_server_port);
-
+
// Destroy previvious TURN session (if exist)
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
if (candidate->type_e == tnet_ice_cand_type_host && candidate->socket) { // do not create TURN session for reflexive candidates
@@ -1648,16 +1646,16 @@ next_server:
++host_addr_count;
}
} // tsk_list_foreach(item, self->candidates_local) {
-
+
rto = self->RTO;
rc = self->Rc;
-
+
for (i = 0; (i < rc && self->is_started && ((relay_addr_count_ok + relay_addr_count_nok) < host_addr_count));) {
if (!self->is_started || !self->is_active) {
TSK_DEBUG_INFO("ICE context stopped/cancelled while gathering TURN candidates");
goto bail;
}
-
+
u_t0 = tsk_time_now();
tsk_condwait_timedwait(self->turn.condwait, rto);
u_t1 = tsk_time_now();
@@ -1666,7 +1664,7 @@ next_server:
rto <<= 1;
++i;
}
-
+
// count the number of TURN sessions with alloc() = ok/nok and ignore ones without response
relay_addr_count_ok = 0;
tsk_list_foreach(item, candidates_local_copy) {
@@ -1685,7 +1683,7 @@ next_server:
}
}
}
-
+
// add/delete TURN candidates
tsk_list_foreach(item, candidates_local_copy) {
if (!(candidate = item->data) || !candidate->turn.ss) {
@@ -1701,7 +1699,7 @@ next_server:
tnet_port_t relay_port;
tnet_ice_candidate_t* new_cand = tsk_null;
struct tnet_socket_s* p_lcl_sock = tsk_null;
-
+
if ((ret = tnet_turn_session_get_relayed_addr(candidate->turn.ss, &relay_addr, &relay_port, &__b_ipv6))) {
goto bail;
}
@@ -1733,12 +1731,12 @@ next_server:
TSK_OBJECT_SAFE_FREE(candidate->turn.ss);
}
}
-
+
// Try next TURN server
if (self->is_started && item_server && relay_addr_count_added == 0) {
goto next_server;
}
-
+
bail:
if (self->is_started) {
if (ret == 0) {
@@ -1778,34 +1776,34 @@ static int _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel(va_list *app)
{
tnet_ice_ctx_t* self;
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
tsk_list_lock(self->candidates_remote);
tsk_list_clear_items(self->candidates_remote);
tsk_list_unlock(self->candidates_remote);
-
+
tsk_list_lock(self->candidates_pairs);
tsk_list_clear_items(self->candidates_pairs);
tsk_list_unlock(self->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
// Do not clear local candidates because then will be used as fallback if the remote peer is an ICE-lite
// These candidates will be cleared before the next local gathering
// tsk_list_lock(self->candidates_local);
// tsk_list_clear_items(self->candidates_local);
// tsk_list_unlock(self->candidates_local);
-
+
// restore "is_cancelled" until next cancel
// set "is_active" to false to allow ICE re-start
// self->is_cancelled = tsk_false;
// self->is_active = tsk_false;
-
+
// alert user
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_cancelled, "Cancelled");
-
+
return 0;
-
+
}
// Any -> (GatheringComplet) -> GatheringCompleted
@@ -1814,25 +1812,25 @@ static int _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet(va_list
int ret = 0;
tnet_ice_ctx_t* self;
tsk_bool_t has_remote_candidates;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
// alert user
_tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_completed, "Gathering candidates completed");
-
- if (self->is_started){
+
+ if (self->is_started) {
tsk_list_lock(self->candidates_remote);
has_remote_candidates = !TSK_LIST_IS_EMPTY(self->candidates_remote);
tsk_list_unlock(self->candidates_remote);
-
- if (has_remote_candidates){
+
+ if (has_remote_candidates) {
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck);
}
}
- else{
+ else {
return -1;
}
-
+
return ret;
}
@@ -1861,42 +1859,42 @@ static int _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck(va_li
void* recvfrom_buff_ptr = tsk_null;
tsk_size_t recvfrom_buff_size = 0, tries_count = 0, tries_count_min = kIceConnCheckMinTriesMin;
enum tnet_stun_state_e e_state;
-
+
self = va_arg(*app, tnet_ice_ctx_t *);
-
+
self->is_connchecking = tsk_true;
-
+
// "tries_count" and "tries_count_min"
// The connection checks to to the "relay", "prflx", "srflx" and "host" candidates are sent at the same time.
// Because the requests are sent at the same time it's possible to have success check for "relay" (or "srflx") candidates before the "host" candidates.
// "tries_count_min" is the minimum (if success check is not for "host" candidates) tries before giving up.
// The pairs are already sorted ("host"->"srflx"->"prflx", "relay") to make sure to choose the best candidates when there are more than one success conncheck.
-
+
start_conneck:
role_conflict = tsk_false;
restart_conneck = tsk_false;
-
+
tsk_list_lock(self->candidates_pairs);
tsk_list_clear_items(self->candidates_pairs);
tsk_list_unlock(self->candidates_pairs);
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
if ((ret = _tnet_ice_ctx_build_pairs(self, self->candidates_local, self->candidates_remote, self->candidates_pairs, self->is_controlling, self->tie_breaker, self->is_ice_jingle, self->use_rtcpmux))) {
TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
goto bail;
}
-
+
#define _FD_ISSET(_fds, _fds_count, _fd, _isset) { uint16_t __i; *_isset = 0; for (__i = 0; __i < _fds_count; ++__i) { if (_fds[__i] == _fd) { *_isset = 1; break; } } }
-
+
// load fds for both rtp and rtcp sockets / create TURN permissions
tsk_list_lock(self->candidates_pairs);
- tsk_list_foreach(item, self->candidates_pairs){
- if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket){
+ tsk_list_foreach(item, self->candidates_pairs) {
+ if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket) {
continue;
}
-
+
if ((fds_count < sizeof(fds) / sizeof(fds[0])) && pair->candidate_offer->socket) {
if (pair->candidate_offer->turn.ss && (ret = tnet_turn_session_get_state_createperm(pair->candidate_offer->turn.ss, pair->turn_peer_id, &e_state)) == 0) {
if (e_state == tnet_stun_state_none) {
@@ -1924,21 +1922,21 @@ start_conneck:
}
}
tsk_list_unlock(self->candidates_pairs);
-
+
concheck_timeout = self->concheck_timeout;
time_start = time_curr = tsk_time_now();
time_end = (time_start + concheck_timeout);
tries_count_min = fds_turn_count > 0 ? kIceConnCheckMinTriesMax : kIceConnCheckMinTriesMin;
-
+
while (self->is_started && self->is_active && (time_curr < time_end) && !self->have_nominated_symetric) {
tv.tv_sec = 0;
tv.tv_usec = (rto * 1000);
-
+
FD_ZERO(&set);
for (k = 0; k < fds_count; ++k) {
FD_SET(fds[k], &set);
}
-
+
// set new current time here to avoid "continue" skips
// ignore already ellapsed time if new timeout value is defined
time_curr = tsk_time_now();
@@ -1947,7 +1945,7 @@ start_conneck:
time_start = time_curr;
time_end = (time_start + concheck_timeout);
}
-
+
// Send ConnCheck requests
// the pairs are already sorted by priority (from high to low)
if (!self->have_nominated_symetric) {
@@ -1956,21 +1954,22 @@ start_conneck:
continue;
}
switch (pair->state_offer) {
- case tnet_ice_pair_state_failed:
- case tnet_ice_pair_state_succeed:
- continue;
- default: break;
+ case tnet_ice_pair_state_failed:
+ case tnet_ice_pair_state_succeed:
+ continue;
+ default:
+ break;
}
-
+
ret = tnet_ice_pair_send_conncheck((tnet_ice_pair_t *)pair);
}
}
-
+
if (fds_count == 0) {
tsk_thread_sleep(10);
goto check_nomination;
}
-
+
if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) {
TNET_PRINT_LAST_ERROR("select() failed");
goto bail;
@@ -1986,30 +1985,30 @@ start_conneck:
tnet_fd_t fd = fds[k];
unsigned int len = 0;
tsk_size_t read = 0;
-
+
if (!FD_ISSET(fd, &set)) {
continue;
}
-
+
// Check how many bytes are pending
if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) {
continue;
}
-
- if (len == 0){
+
+ if (len == 0) {
// TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
-
+
// Receive pending data
- if (recvfrom_buff_size < len){
- if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))){
+ if (recvfrom_buff_size < len) {
+ if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))) {
recvfrom_buff_size = 0;
goto bail;
}
recvfrom_buff_size = len;
}
-
+
// receive all messages
while (self->is_started && self->is_active && read < len && ret == 0) {
if ((ret = tnet_sockfd_recvfrom(fd, recvfrom_buff_ptr, recvfrom_buff_size, 0, (struct sockaddr *)&remote_addr)) < 0) {
@@ -2024,13 +2023,13 @@ start_conneck:
len = 0;
continue;
}
-
+
TNET_PRINT_LAST_ERROR("Receiving STUN dgrams failed with errno=%d", err);
goto bail;
}
-
+
read += ret;
-
+
// recv() STUN message (request / response)
ret = tnet_ice_ctx_recv_stun_message(self, recvfrom_buff_ptr, (tsk_size_t)ret, fd, &remote_addr, &role_conflict);
if (ret == 0 && role_conflict) {
@@ -2041,13 +2040,13 @@ start_conneck:
}
}
}
-
- check_nomination:
+
+check_nomination:
// check whether we need to re-start connection checking
if (restart_conneck) {
goto start_conneck;
}
-
+
check_rtcp = (self->use_rtcp && !self->use_rtcpmux);
if (!self->have_nominated_offer) {
self->have_nominated_offer = tnet_ice_pairs_have_nominated_offer(self->candidates_pairs, check_rtcp);
@@ -2060,11 +2059,11 @@ start_conneck:
self->have_nominated_symetric &= (got_hosts || ((tries_count++) >= tries_count_min));
}
} // while (self->is_started...
-
+
// "ret" could be "<>0" if last function used was "select()", "recvfrom()", "ioctlt()"...this is why we set the value to #0.
// if there was an error then, we'll jump to "bail:" and next code is skipped
ret = 0;
-
+
bail:
// move to the next state depending on the conncheck result
if (self->is_started) {
@@ -2081,11 +2080,11 @@ bail:
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure);
}
}
-
+
TSK_FREE(recvfrom_buff_ptr);
-
+
self->is_connchecking = tsk_false;
-
+
return ret;
}
@@ -2099,19 +2098,19 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
const tnet_ice_candidate_t *candidate;
tsk_list_t* sessions = tsk_list_create(); // for lock-free TURN sessions destroying
int ret;
-
+
// When destroying TURN sessions the transport is locked by shutdown()
// This function locks "self->candidates_pairs"
// TURN callback locks "self->candidates_pairs"
// TURN callback locks the transport
// => We must not lock the candidates when destroying the TURN session
// Test with WES8 if you want to reproduce the issue
-
+
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp);
TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp);
-
+
tsk_list_lock(self->candidates_pairs);
-
+
// take a reference to the negotiated TURN sessions
ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &pair_offer, &pair_answer_src, &pair_answer_dest);
if (ret == 0) {
@@ -2123,8 +2122,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
TSK_DEBUG_INFO("ICE: nominated symetric RTP pairs: offer:%llu, answer-src:%llu, answser-dest:%llu",
pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0);
}
- if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
-
+ if (ret == 0 && pair_offer) {
+ ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
+ }
+
ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &pair_offer, &pair_answer_src, &pair_answer_dest);
if (ret == 0) {
if (pair_offer && pair_offer->candidate_offer && pair_offer->candidate_offer->type_e == tnet_ice_cand_type_relay && pair_offer->candidate_offer->turn.ss) {
@@ -2136,8 +2137,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
self->use_rtcp ? 1 : 0, self->use_rtcpmux ? 1 : 0,
pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0);
}
- if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
-
+ if (ret == 0 && pair_offer) {
+ ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled
+ }
+
// collect all useless TURN sessions (pairs)
tsk_list_foreach(item, self->candidates_pairs) {
if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->turn.ss) {
@@ -2148,9 +2151,9 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
TSK_OBJECT_SAFE_FREE(pair->candidate_offer->turn.ss);
}
}
-
+
tsk_list_unlock(self->candidates_pairs);
-
+
// collect all useless TURN sessions (local candidates)
tsk_list_lock(self->candidates_local);
tsk_list_foreach(item, self->candidates_local) {
@@ -2163,7 +2166,7 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
}
}
tsk_list_unlock(self->candidates_local);
-
+
// collect all useless TURN sessions (remote candidates)
tsk_list_lock(self->candidates_remote);
tsk_list_foreach(item, self->candidates_remote) {
@@ -2176,10 +2179,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l
}
}
tsk_list_unlock(self->candidates_remote);
-
+
// lock-free destruction
TSK_OBJECT_SAFE_FREE(sessions);
-
+
return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_conncheck_succeed, "ConnCheck succeed");
}
@@ -2203,15 +2206,15 @@ static int _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted(va_list *app)
static int _tnet_ice_ctx_fsm_OnTerminated(tnet_ice_ctx_t* self)
{
TSK_DEBUG_INFO("=== ICE CTX SM Terminated ===");
-
- if (!self){
+
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter.");
return -1;
}
-
+
// still started but no longer active
self->is_active = tsk_false;
-
+
return 0;
}
@@ -2227,10 +2230,10 @@ static int _tnet_ice_ctx_restart(tnet_ice_ctx_t* self)
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
ret = tsk_fsm_set_current_state(self->fsm, _fsm_state_Started);
ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates);
-
+
self->is_active = (ret == 0);
return ret;
}
@@ -2243,9 +2246,9 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
*role_conflict = tsk_false;
-
+
if (!TNET_STUN_BUFF_IS_STUN2(((uint8_t*)data), size)) {
if (self->rtp_callback) {
return self->rtp_callback(self->rtp_callback_data, data, size, local_fd, remote_addr);
@@ -2253,12 +2256,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
TSK_DEBUG_INFO("Not STUN message");
return 0;
}
-
+
if (!self->is_active) {
TSK_DEBUG_INFO("ICE context not active yet");
return 0;
}
-
+
if ((ret = tnet_stun_pkt_read(data, size, &message)) == 0 && message) {
if (message->e_type == tnet_stun_pkt_type_binding_request) {
tsk_bool_t is_local_conncheck_started;
@@ -2278,7 +2281,7 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
if (!pair && is_local_conncheck_started) {
pair = tnet_ice_pairs_find_by_fd_and_addr(self->candidates_pairs, local_fd, remote_addr);
}
- if (!pair && !self->have_nominated_symetric && is_local_conncheck_started){ // pair not found and we're still negotiating
+ if (!pair && !self->have_nominated_symetric && is_local_conncheck_started) { // pair not found and we're still negotiating
// rfc 5245 - 7.1.3.2.1. Discovering Peer Reflexive Candidates
tnet_ice_pair_t* pair_peer = tnet_ice_pair_prflx_create(self->candidates_pairs, local_fd, remote_addr);
if (pair_peer) {
@@ -2292,12 +2295,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
char* resp_phrase = tsk_null;
// authenticate the request
tnet_ice_pair_auth_conncheck(pair, message, data, size, &resp_code, &resp_phrase);
- if (resp_code > 0 && resp_phrase){
- if (resp_code >= 200 && resp_code <= 299){
+ if (resp_code > 0 && resp_phrase) {
+ if (resp_code >= 200 && resp_code <= 299) {
// Before sending the success response check that there are no role conflict
- if (self->is_controlling){ // I'm ICE-CONTROLLING
+ if (self->is_controlling) { // I'm ICE-CONTROLLING
const tnet_stun_attr_vdata_t* stun_att_ice_controlling;
- if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling){
+ if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling) {
TSK_DEBUG_WARN("Role conflicts (SEND)");
if (self->tie_breaker >= *((uint64_t*)stun_att_ice_controlling->p_data_ptr)) {
resp_code = kStunErrCodeIceConflict;
@@ -2363,13 +2366,13 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const
}
}
TSK_OBJECT_SAFE_FREE(message);
-
+
return ret;
}
static int _tnet_ice_ctx_send_turn_raw(struct tnet_ice_ctx_s* self, struct tnet_turn_session_s* turn_ss, tnet_turn_peer_id_t turn_peer_id, const void* data, tsk_size_t size)
{
- if (!self || !turn_ss || !data || !size){
+ if (!self || !turn_ss || !data || !size) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
@@ -2386,21 +2389,21 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
tnet_ice_pair_t *pair;
enum tnet_turn_transport_e e_req_transport;
tnet_family_t addr_family_local, addr_family_remote;
-
+
if (!self || TSK_LIST_IS_EMPTY(local_candidates) || TSK_LIST_IS_EMPTY(remote_candidates) || !result_pairs) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
self->is_building_pairs = tsk_true;
TSK_DEBUG_INFO("ICE: begin building pairs(is_rtcpmuxed=%d)", is_rtcpmuxed);
-
+
tsk_list_clear_items(result_pairs);
-
+
tsk_list_lock(local_candidates);
tsk_list_lock(remote_candidates);
tsk_list_lock(result_pairs);
-
+
tsk_list_foreach(item_local, local_candidates) {
if (!(cand_local = item_local->data)) {
continue;
@@ -2413,7 +2416,7 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
continue;
}
#endif
-
+
tsk_list_foreach(item_remote, remote_candidates) {
if (!(cand_remote = item_remote->data)) {
continue;
@@ -2423,9 +2426,9 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
TSK_DEBUG_INFO("Skipping remote ICE candidate with port = 0");
continue;
}
-
+
// CompIds(1=RTP, 2=RTCP) must match
- if ((cand_remote->comp_id != cand_local->comp_id)){
+ if ((cand_remote->comp_id != cand_local->comp_id)) {
continue;
}
// IP versions must match. Cannot use IPv4 socket to send/recv to IPv6 address.
@@ -2453,18 +2456,18 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
continue;
}
}
-
+
if ((pair = tnet_ice_pair_create(cand_local, cand_remote, is_controlling, tie_breaker, is_ice_jingle))) {
TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %u %s %d] -> [%s %u %u %s %d]",
pair->id,
pair->priority,
-
+
cand_local->foundation,
cand_local->priority,
cand_local->comp_id,
cand_local->connection_addr,
cand_local->port,
-
+
cand_remote->foundation,
cand_remote->priority,
cand_remote->comp_id,
@@ -2479,31 +2482,31 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi
if (!(pair = item_local->data)) {
continue;
}
-
+
TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %s %d] -> [%s %u %s %d]",
pair->id,
pair->priority,
-
+
pair->candidate_offer->foundation,
pair->candidate_offer->comp_id,
pair->candidate_offer->connection_addr,
pair->candidate_offer->port,
-
+
pair->candidate_answer->foundation,
pair->candidate_answer->comp_id,
pair->candidate_answer->connection_addr,
pair->candidate_answer->port);
}
#endif
-
+
tsk_list_unlock(local_candidates);
tsk_list_unlock(remote_candidates);
tsk_list_unlock(result_pairs);
-
+
self->is_building_pairs = tsk_false;
tsk_condwait_broadcast(self->condwait_pairs);
TSK_DEBUG_INFO("ICE: end building pairs");
-
+
return 0;
}
@@ -2514,32 +2517,32 @@ static int _tnet_ice_ctx_fsm_act(tnet_ice_ctx_t* self, tsk_fsm_action_id action_
tnet_ice_event_t* e = tsk_null;
static const char* phrase = "$action$";
int ret = 0;
-
- if (!self || !self->fsm){
+
+ if (!self || !self->fsm) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
- if (!(action = tnet_ice_action_create(action_id))){
+ if (!(action = tnet_ice_action_create(action_id))) {
TSK_DEBUG_ERROR("Failed to create action");
return -2;
}
-
+
if (self->is_sync_mode) {
ret = tsk_fsm_act(self->fsm, action->id, self, action, self, action);
}
else {
- if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))){
+ if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))) {
tnet_ice_event_set_action(e, action);
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e);
goto bail;
}
- else{
+ else {
TSK_DEBUG_ERROR("Failed to create ICE event");
ret = -2;
goto bail;
}
}
-
+
bail:
TSK_OBJECT_SAFE_FREE(e);
TSK_OBJECT_SAFE_FREE(action);
@@ -2549,21 +2552,21 @@ bail:
static int _tnet_ice_ctx_signal_async(tnet_ice_ctx_t* self, tnet_ice_event_type_t type, const char* phrase)
{
tnet_ice_event_t* e;
- if (!self){
+ if (!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
if (self->is_silent_mode && type != tnet_ice_event_type_action) { // silent mode ON and not action to move the FSM
TSK_DEBUG_INFO("ICE silent mode ON...to not notify '%d:%s'", type, phrase);
return 0;
}
-
- if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))){
+
+ if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))) {
TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e);
return 0;
}
- else{
+ else {
TSK_DEBUG_ERROR("Failed to create ICE event");
return -2;
}
@@ -2574,114 +2577,110 @@ static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs *
tnet_ice_ctx_t *ctx = tsk_object_ref(TSK_OBJECT(e->pc_usr_data));
struct tnet_turn_session_s* session = tsk_object_ref(TSK_OBJECT(e->pc_session));
int ret = 0;
-
+
if (!ctx) {
// the ICE context is being destroyed but TURN session not freed yet
goto bail;
}
-
+
switch (e->e_type) {
- case tnet_turn_session_event_type_alloc_ok:
- case tnet_turn_session_event_type_refresh_ok:
- case tnet_turn_session_event_type_chanbind_ok:
- case tnet_turn_session_event_type_connect_ok:
- default:
- {
- break;
- }
-
- case tnet_turn_session_event_type_alloc_nok:
- case tnet_turn_session_event_type_refresh_nok:
- case tnet_turn_session_event_type_perm_nok:
- case tnet_turn_session_event_type_chanbind_nok:
- case tnet_turn_session_event_type_connect_nok:
- {
- // Do not raise error event if no nominated candidate because
- // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case.
- if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) {
- TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id);
- if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) {
- goto bail;
- }
+ case tnet_turn_session_event_type_alloc_ok:
+ case tnet_turn_session_event_type_refresh_ok:
+ case tnet_turn_session_event_type_chanbind_ok:
+ case tnet_turn_session_event_type_connect_ok:
+ default: {
+ break;
+ }
+
+ case tnet_turn_session_event_type_alloc_nok:
+ case tnet_turn_session_event_type_refresh_nok:
+ case tnet_turn_session_event_type_perm_nok:
+ case tnet_turn_session_event_type_chanbind_nok:
+ case tnet_turn_session_event_type_connect_nok: {
+ // Do not raise error event if no nominated candidate because
+ // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case.
+ if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) {
+ TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id);
+ if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) {
+ goto bail;
}
- break;
}
-
- case tnet_turn_session_event_type_perm_ok:
- {
- enum tnet_turn_transport_e e_req_transport;
- if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) {
+ break;
+ }
+
+ case tnet_turn_session_event_type_perm_ok: {
+ enum tnet_turn_transport_e e_req_transport;
+ if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) {
+ goto bail;
+ }
+
+ if (e_req_transport == tnet_turn_transport_tcp) {
+ // TCP-Connect: rfc6062 - 4.3. Initiating a Connection
+ if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) {
goto bail;
}
-
- if (e_req_transport == tnet_turn_transport_tcp) {
- // TCP-Connect: rfc6062 - 4.3. Initiating a Connection
- if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) {
- goto bail;
- }
+ }
+ else {
+ // Bind a channel (not required). If succeed, will be used to save bandwidth usage.
+ // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed.
+ if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) {
+ goto bail;
}
- else {
- // Bind a channel (not required). If succeed, will be used to save bandwidth usage.
- // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed.
- if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) {
- goto bail;
+ }
+ break;
+ }
+
+ case tnet_turn_session_event_type_recv_data: {
+ tsk_bool_t role_conflict;
+ tnet_ice_pair_t* pair = tsk_null;
+ if (e->u_peer_id != kTurnPeerIdInvalid) {
+ const tsk_list_item_t *item;
+ tsk_list_lock(ctx->candidates_pairs);
+ tsk_list_foreach(item, ctx->candidates_pairs) {
+ if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) {
+ pair = tsk_object_ref((void*)item->data);
+ break;
}
}
- break;
+ tsk_list_unlock(ctx->candidates_pairs);
}
-
- case tnet_turn_session_event_type_recv_data:
- {
- tsk_bool_t role_conflict;
- tnet_ice_pair_t* pair = tsk_null;
- if (e->u_peer_id != kTurnPeerIdInvalid) {
- const tsk_list_item_t *item;
- tsk_list_lock(ctx->candidates_pairs);
- tsk_list_foreach(item, ctx->candidates_pairs) {
- if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) {
- pair = tsk_object_ref((void*)item->data);
- break;
- }
- }
- tsk_list_unlock(ctx->candidates_pairs);
- }
-
- ret = _tnet_ice_ctx_recv_stun_message_for_pair(
- ctx,
- pair,
- e->data.pc_data_ptr, e->data.u_data_size,
- e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD,
- e->pc_enet ? &e->pc_enet->remote_addr : tsk_null,
- &role_conflict);
- TSK_OBJECT_SAFE_FREE(pair);
- if (ret) {
+
+ ret = _tnet_ice_ctx_recv_stun_message_for_pair(
+ ctx,
+ pair,
+ e->data.pc_data_ptr, e->data.u_data_size,
+ e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD,
+ e->pc_enet ? &e->pc_enet->remote_addr : tsk_null,
+ &role_conflict);
+ TSK_OBJECT_SAFE_FREE(pair);
+ if (ret) {
+ goto bail;
+ }
+
+ // rebuild candidates if role conflict
+ if (role_conflict) {
+ tsk_list_lock(ctx->candidates_pairs);
+ tsk_list_clear_items(ctx->candidates_pairs);
+ tsk_list_unlock(ctx->candidates_pairs);
+
+ TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
+ TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
+
+ if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) {
+ TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
goto bail;
}
-
- // rebuild candidates if role conflict
- if (role_conflict) {
- tsk_list_lock(ctx->candidates_pairs);
- tsk_list_clear_items(ctx->candidates_pairs);
- tsk_list_unlock(ctx->candidates_pairs);
-
- TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp);
- TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp);
-
- if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) {
- TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed");
- goto bail;
- }
- }
-
- break;
}
+
+ break;
}
-
+ }
+
// alert() waiting threads
if ((ret = tsk_condwait_broadcast(ctx->turn.condwait))) {
goto bail;
}
-
+
bail:
tsk_object_unref(ctx);
tsk_object_unref(session);
@@ -2694,42 +2693,40 @@ static void* TSK_STDCALL _tnet_ice_ctx_run(void* self)
tsk_list_item_t *curr;
tnet_ice_ctx_t *ctx = (tnet_ice_ctx_t *)(self);
tnet_ice_event_t *e;
-
+
TSK_DEBUG_INFO("ICE CTX::run -- START");
-
+
TSK_RUNNABLE_RUN_BEGIN(ctx);
-
+
// must because "ctx->callback(e);" could call a function trying to free "ctx"
// do not move before "TSK_RUNNABLE_RUN_BEGIN(ctx)", otherwise it'll be required to stop the "runnable" to have "ctx->refCount==0"
ctx = tsk_object_ref(ctx);
-
+
if (ctx->is_started && (curr = TSK_RUNNABLE_POP_FIRST(ctx))) {
e = (tnet_ice_event_t*)curr->data;
switch (e->type) {
- case tnet_ice_event_type_action:
- {
- if (e->action) {
- tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action);
- }
- break;
+ case tnet_ice_event_type_action: {
+ if (e->action) {
+ tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action);
}
- default:
- {
- if (ctx->callback){
- ctx->callback(e);
- }
- break;
+ break;
+ }
+ default: {
+ if (ctx->callback) {
+ ctx->callback(e);
}
+ break;
+ }
}
tsk_object_unref(curr);
}
-
+
if (!(ctx = tsk_object_unref(ctx))) {
goto exit;
}
-
+
TSK_RUNNABLE_RUN_END(ctx);
-
+
exit:
if (ctx) {
tsk_list_clear_items(ctx->candidates_local);
@@ -2738,9 +2735,9 @@ exit:
tsk_list_clear_items(ctx->candidates_pairs);
tsk_list_unlock(ctx->candidates_pairs);
}
-
+
TSK_DEBUG_INFO("ICE CTX::run -- STOP");
-
+
return 0;
}
@@ -2768,7 +2765,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
// TURN requires credentials
if ((e_proto & tnet_ice_server_proto_turn) == tnet_ice_server_proto_turn && (tsk_strnullORempty(str_username) || tsk_strnullORempty(str_password))) {
/* rfc5766 - 4. General Behavior
@@ -2791,7 +2788,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s
}
tsk_list_push_back_data(self->servers, (void**)&ice_server);
TSK_OBJECT_SAFE_FREE(ice_server);
-
+
ret = 0;
bail:
tsk_list_unlock(self->servers);
diff --git a/tinyNET/src/ice/tnet_ice_ctx.h b/tinyNET/src/ice/tnet_ice_ctx.h
index 015fdcf..8be8164 100755
--- a/tinyNET/src/ice/tnet_ice_ctx.h
+++ b/tinyNET/src/ice/tnet_ice_ctx.h
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2012-2015 Doubango Telecom <http://www.doubango.org>.
-*
+*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -46,21 +46,21 @@ TINYNET_API struct tnet_ice_ctx_s* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle,
TINYNET_API int tnet_ice_ctx_set_userdata(struct tnet_ice_ctx_s* self, const void* userdata);
//@deprecated: Use "tnet_ice_ctx_add_server()"
TNET_DEPRECATED(TINYNET_API int tnet_ice_ctx_set_stun(
- struct tnet_ice_ctx_s* self,
- const char* server_addr,
- uint16_t server_port,
- const char* software,
- const char* username,
- const char* password));
+ struct tnet_ice_ctx_s* self,
+ const char* server_addr,
+ uint16_t server_port,
+ const char* software,
+ const char* username,
+ const char* password));
TINYNET_API int tnet_ice_ctx_add_server(
- struct tnet_ice_ctx_s* self,
- const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"...
- const char* server_addr,
- uint16_t server_port,
- tsk_bool_t use_turn,
- tsk_bool_t use_stun,
- const char* username,
- const char* password);
+ struct tnet_ice_ctx_s* self,
+ const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"...
+ const char* server_addr,
+ uint16_t server_port,
+ tsk_bool_t use_turn,
+ tsk_bool_t use_stun,
+ const char* username,
+ const char* password);
#define tnet_ice_ctx_add_server_turn(self, transport_proto, server_addr, server_port, username, password) \
tnet_ice_ctx_add_server((self), (transport_proto), (server_addr), (server_port), tsk_true/*use_turn*/, tsk_false/*use_stun*/, (username), (password))
#define tnet_ice_ctx_add_server_stun(self, transport_proto, server_addr, server_port, username, password) \
@@ -90,9 +90,9 @@ TINYNET_API tsk_bool_t tnet_ice_ctx_is_can_recv(const struct tnet_ice_ctx_s* sel
TINYNET_API tsk_bool_t tnet_ice_ctx_use_ipv6(const struct tnet_ice_ctx_s* self);
TINYNET_API tsk_bool_t tnet_ice_ctx_use_rtcp(const struct tnet_ice_ctx_s* self);
TINYNET_API int tnet_ice_ctx_get_nominated_symetric_candidates(const struct tnet_ice_ctx_s* self, uint32_t comp_id,
- const struct tnet_ice_candidate_s** candidate_offer,
- const struct tnet_ice_candidate_s** candidate_answer_src,
- const struct tnet_ice_candidate_s** candidate_answer_dest);
+ const struct tnet_ice_candidate_s** candidate_offer,
+ const struct tnet_ice_candidate_s** candidate_answer_src,
+ const struct tnet_ice_candidate_s** candidate_answer_dest);
TINYNET_API int tnet_ice_ctx_recv_stun_message(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr, tsk_bool_t *role_conflict);
TINYNET_API int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size);
TINYNET_API int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size);
diff --git a/tinyNET/src/ice/tnet_ice_event.c b/tinyNET/src/ice/tnet_ice_event.c
index 480202f..1826c3b 100755
--- a/tinyNET/src/ice/tnet_ice_event.c
+++ b/tinyNET/src/ice/tnet_ice_event.c
@@ -27,24 +27,23 @@
static tsk_object_t* tnet_ice_event_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_event_t *e = self;
- if(e){
-
+ if(e) {
+
}
return self;
}
static tsk_object_t* tnet_ice_event_dtor(tsk_object_t * self)
{
tnet_ice_event_t *e = self;
- if(e){
+ if(e) {
TSK_SAFE_FREE(e->phrase);
TSK_OBJECT_SAFE_FREE(e->action);
e->ctx = tsk_null; // not the owner (const)
}
-
+
return self;
}
-static const tsk_object_def_t tnet_ice_event_def_s =
-{
+static const tsk_object_def_t tnet_ice_event_def_s = {
sizeof(tnet_ice_event_t),
tnet_ice_event_ctor,
tnet_ice_event_dtor,
@@ -56,29 +55,29 @@ const tsk_object_def_t *tnet_ice_event_def_t = &tnet_ice_event_def_s;
tnet_ice_event_t* tnet_ice_event_create(const struct tnet_ice_ctx_s* ctx, tnet_ice_event_type_t type, const char* phrase, const void* userdata)
{
tnet_ice_event_t* e;
-
- if((e = tsk_object_new(tnet_ice_event_def_t))){
+
+ if((e = tsk_object_new(tnet_ice_event_def_t))) {
e->ctx = ctx;
e->type = type;
e->phrase = tsk_strdup(phrase);
e->userdata = userdata;
}
- else{
+ else {
TSK_DEBUG_ERROR("Failed to create ICE event");
}
-
+
return e;
}
int tnet_ice_event_set_action(tnet_ice_event_t* self, struct tnet_ice_action_s* action)
{
- if(!self){
+ if(!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
self->type = tnet_ice_event_type_action;
TSK_OBJECT_SAFE_FREE(self->action);
- if(action){
+ if(action) {
self->action = tsk_object_ref(action);
}
return 0;
diff --git a/tinyNET/src/ice/tnet_ice_event.h b/tinyNET/src/ice/tnet_ice_event.h
index 8f2f72e..404f765 100755
--- a/tinyNET/src/ice/tnet_ice_event.h
+++ b/tinyNET/src/ice/tnet_ice_event.h
@@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -28,40 +28,38 @@
TNET_BEGIN_DECLS
-typedef enum tnet_ice_event_type_e
-{
- // Public events
- tnet_ice_event_type_started,
- tnet_ice_event_type_start_failed,
- tnet_ice_event_type_stopped,
- tnet_ice_event_type_stop_failed,
- tnet_ice_event_type_gathering_host_candidates_failed,
- tnet_ice_event_type_gathering_host_candidates_succeed,
- tnet_ice_event_type_gathering_reflexive_candidates_failed,
- tnet_ice_event_type_gathering_reflexive_candidates_succeed,
- tnet_ice_event_type_gathering_relay_candidates_failed,
- tnet_ice_event_type_gathering_relay_candidates_succeed,
- tnet_ice_event_type_gathering_completed,
- tnet_ice_event_type_conncheck_succeed,
- tnet_ice_event_type_conncheck_failed,
- tnet_ice_event_type_cancelled,
- tnet_ice_event_type_turn_connection_broken,
+typedef enum tnet_ice_event_type_e {
+ // Public events
+ tnet_ice_event_type_started,
+ tnet_ice_event_type_start_failed,
+ tnet_ice_event_type_stopped,
+ tnet_ice_event_type_stop_failed,
+ tnet_ice_event_type_gathering_host_candidates_failed,
+ tnet_ice_event_type_gathering_host_candidates_succeed,
+ tnet_ice_event_type_gathering_reflexive_candidates_failed,
+ tnet_ice_event_type_gathering_reflexive_candidates_succeed,
+ tnet_ice_event_type_gathering_relay_candidates_failed,
+ tnet_ice_event_type_gathering_relay_candidates_succeed,
+ tnet_ice_event_type_gathering_completed,
+ tnet_ice_event_type_conncheck_succeed,
+ tnet_ice_event_type_conncheck_failed,
+ tnet_ice_event_type_cancelled,
+ tnet_ice_event_type_turn_connection_broken,
- // Private events
- tnet_ice_event_type_action
+ // Private events
+ tnet_ice_event_type_action
}
tnet_ice_event_type_t;
-typedef struct tnet_ice_event_s
-{
- TSK_DECLARE_OBJECT;
+typedef struct tnet_ice_event_s {
+ TSK_DECLARE_OBJECT;
- tnet_ice_event_type_t type;
- char* phrase;
- struct tnet_ice_action_s* action;
- const struct tnet_ice_ctx_s* ctx;
+ tnet_ice_event_type_t type;
+ char* phrase;
+ struct tnet_ice_action_s* action;
+ const struct tnet_ice_ctx_s* ctx;
- const void* userdata;
+ const void* userdata;
}
tnet_ice_event_t;
diff --git a/tinyNET/src/ice/tnet_ice_pair.c b/tinyNET/src/ice/tnet_ice_pair.c
index 33e71a5..f917ea2 100755
--- a/tinyNET/src/ice/tnet_ice_pair.c
+++ b/tinyNET/src/ice/tnet_ice_pair.c
@@ -58,7 +58,7 @@
static int __pred_find_by_pair(const tsk_list_item_t *item, const void *pair)
{
- if(item && item->data){
+ if(item && item->data) {
int ret;
tsk_subsat_int32_ptr(item->data, pair, &ret);
return ret;
@@ -70,7 +70,7 @@ static int __pred_find_by_pair(const tsk_list_item_t *item, const void *pair)
static tsk_object_t* tnet_ice_pair_ctor(tsk_object_t * self, va_list * app)
{
tnet_ice_pair_t *pair = self;
- if(pair){
+ if(pair) {
pair->state_offer = tnet_ice_pair_state_frozen;
pair->state_answer = tnet_ice_pair_state_frozen;
}
@@ -90,7 +90,7 @@ static int tnet_ice_pair_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2)
{
const tnet_ice_pair_t *p1 = _p1;
const tnet_ice_pair_t *p2 = _p2;
-
+
if (p1 && p2) {
#if 0
// This is not correct and most differences (if not all) will be equal to "INT_MIN" or "INT_MAX" and this will produce invalid sorting.
@@ -102,11 +102,14 @@ static int tnet_ice_pair_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2)
return (p1->priority == p2->priority) ? 0 : (p1->priority > p2->priority ? 1 : -1);
#endif
}
- else if (!p1 && !p2) return 0;
- else return -1;
+ else if (!p1 && !p2) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
}
-static const tsk_object_def_t tnet_ice_pair_def_s =
-{
+static const tsk_object_def_t tnet_ice_pair_def_s = {
sizeof(tnet_ice_pair_t),
tnet_ice_pair_ctor,
tnet_ice_pair_dtor,
@@ -117,11 +120,11 @@ tnet_ice_pair_t* tnet_ice_pair_create(const tnet_ice_candidate_t* candidate_offe
{
static uint64_t __unique_id = 0;
tnet_ice_pair_t *pair;
- if(!candidate_offer || !candidate_answer){
+ if(!candidate_offer || !candidate_answer) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
+
if ((pair = tsk_object_new(&tnet_ice_pair_def_s))) {
uint64_t G, D;
pair->id = ++__unique_id; // not part of the standard, used to ease debugging
@@ -136,7 +139,7 @@ tnet_ice_pair_t* tnet_ice_pair_create(const tnet_ice_candidate_t* candidate_offe
pair->priority = ((TSK_MIN(G, D)) << 32) + (TSK_MAX(G, D) << 1) + ((G > D) ? 1 : 0);
pair->turn_peer_id = kTurnPeerIdInvalid;
}
-
+
return pair;
}
@@ -148,12 +151,12 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t
const tnet_ice_pair_t *pair_local = tsk_null, *pair = tsk_null;
tnet_ip_t remote_ip;
tnet_port_t remote_port;
-
+
if (!pairs || !remote_addr) {
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
+
tsk_list_foreach(item, pairs) {
if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_answer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) {
continue;
@@ -161,12 +164,12 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t
pair_local = pair;
break;
}
-
+
if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))) {
TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed");
return tsk_null;
}
-
+
if (!pair_local) {
TSK_DEBUG_ERROR("Cannot create prflx candidate with remote ip = %s, remote port = %u and local_fd = %d", remote_ip, remote_port, local_fd);
return tsk_null;
@@ -182,42 +185,42 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t
cand_remote->comp_id = pair_local->candidate_offer->comp_id;
memcpy(cand_remote->connection_addr, remote_ip, sizeof(tnet_ip_t));
cand_remote->port = remote_port;
-
+
TSK_DEBUG_INFO("ICE Pair Reflexive Candidate (%llu, %llu): [%s %u %u %s %d] -> [%s %u %u %s %d]",
pair->id,
pair->priority,
-
+
cand_local->foundation,
cand_local->priority,
cand_local->comp_id,
cand_local->connection_addr,
cand_local->port,
-
+
cand_remote->foundation,
cand_remote->priority,
cand_remote->comp_id,
cand_remote->connection_addr,
cand_remote->port);
-
+
pair_peer = tnet_ice_pair_create(cand_local, cand_remote, pair_local->is_controlling, pair_local->tie_breaker, pair_local->is_ice_jingle);
}
TSK_OBJECT_SAFE_FREE(cand_local);
TSK_OBJECT_SAFE_FREE(cand_remote);
return pair_peer;
}
-
+
return tsk_null;
}
int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
{
int ret;
-
- if(!self){
+
+ if(!self) {
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
-
+
if (self->candidate_offer->turn.ss) {
enum tnet_stun_state_e e_state;
enum tnet_turn_transport_e e_req_transport;
@@ -228,7 +231,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN ConnCheck (peer-id=%ld)", self->turn_peer_id);
goto bail;
}
-
+
if ((ret = tnet_turn_session_get_req_transport(self->candidate_offer->turn.ss, &e_req_transport))) {
goto bail;
}
@@ -244,16 +247,16 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
}
}
}
-
+
if (!self->last_request) {
uint32_t priority;
-
+
// Init remote address
if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &self->remote_addr))) {
TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
goto bail;
}
-
+
if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &self->last_request))) {
goto bail;
}
@@ -266,7 +269,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
if (self->is_ice_jingle) {
tsk_sprintf(&p_uname, "%s%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
- else{
+ else {
tsk_sprintf(&p_uname, "%s:%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer));
}
pc_pwd = tnet_ice_candidate_get_pwd(self->candidate_answer);
@@ -276,7 +279,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
goto bail;
}
}
-
+
priority = tnet_ice_utils_get_priority(tnet_ice_cand_type_prflx, self->candidate_offer->local_pref, self->candidate_offer->is_rtp);
// add attributes
self->last_request->opt.dontfrag = 0;
@@ -333,176 +336,176 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
#if TNET_ICE_AGGRESSIVE_NOMINATION
if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) {
#else
- if (self->is_nominated && !tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) {
+ if (self->is_nominated && !tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) {
#endif
- ret = tnet_stun_pkt_attrs_add(self->last_request,
- TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(),
+ ret = tnet_stun_pkt_attrs_add(self->last_request,
+ TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+
+ if (ret) {
+ goto bail;
+ }
+ b_changed = tsk_true;
+ }
+ }
+ else {
+ tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_use_candidate);
+ tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlling);
+ if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlled)) {
+ ret = tnet_stun_pkt_attrs_add(self->last_request,
+ TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ b_changed = tsk_true;
+ }
+ }
+ // update transac-id if the request structure changed
+ if ((b_changed && (ret = tnet_stun_utils_transac_id_rand(&self->last_request->transac_id)))) {
+ goto bail;
+ }
+ }
+
+ // Send request
+ {
+ tsk_buffer_t *req_buffer = tsk_null;
+ self->last_request->opt.fingerprint = !self->is_ice_jingle;
+ if ((ret = tnet_stun_pkt_write_with_padding_2(self->last_request, &req_buffer))) {
+ goto bail;
+ }
+ if (self->candidate_offer->turn.ss) {
+ // Send using TURN session. Above, we already checked that the TURN session is ready (Alloc=OK, Permission=OK)
+ ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size);
+ }
+ else {
+ int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&self->remote_addr, req_buffer->data, req_buffer->size);
+ ret = (sendBytes == req_buffer->size) ? 0 : -9;
+ }
+ TSK_OBJECT_SAFE_FREE(req_buffer);
+ if (ret) {
+ goto bail;
+ }
+ }
+
+bail:
+ if (ret == 0 && self->state_offer == tnet_ice_pair_state_frozen) {
+ self->state_offer = tnet_ice_pair_state_in_progress;
+ }
+ return ret;
+}
+
+int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr)
+{
+ tnet_stun_pkt_t* message = tsk_null;
+ const char *password, *username;
+ int ret = -1;
+ tsk_bool_t is_error = ((code / 100) != 2);
+
+ if(!self || !phrase || !request || !self->candidate_offer || !self->candidate_answer) {
+ TSK_DEBUG_ERROR("Invalid paramter");
+ return -1;
+ }
+
+ username = tsk_null;
+ password = tnet_ice_candidate_get_pwd(self->candidate_offer);
+
+ if ((ret = tnet_stun_pkt_create_empty(is_error ? tnet_stun_pkt_type_binding_error_response : tnet_stun_pkt_type_binding_success_response, &message)) == 0) {
+ tsk_buffer_t *req_buffer = tsk_null;
+ memcpy(message->transac_id, request->transac_id, sizeof(request->transac_id));
+ message->opt.fingerprint = !self->is_ice_jingle;
+ message->opt.dontfrag = 0;
+
+ // SOFWARE
+ ret = tnet_stun_pkt_attrs_add(message,
+ TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+
+ // SHORT-TERM authentication even for responses
+ if ((ret = tnet_stun_pkt_auth_prepare_shortterm_2(message, password))) {
+ goto bail;
+ }
+
+ // ERROR
+ if (is_error) {
+ ret = tnet_stun_pkt_attrs_add(message,
+ TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(((code / 100) & 0x07), (code - ((code / 100) * 100)), phrase),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ }
+ else {
+ tnet_ip_t remote_ip;
+ tnet_port_t remote_port;
+ if (self->is_ice_jingle) {
+ const tnet_stun_attr_vdata_t *pc_attr_vdata;
+ // USERNAME
+ if ((ret = tnet_stun_pkt_attr_find_first(request, tnet_stun_attr_type_username, (const tnet_stun_attr_t **)&pc_attr_vdata)) == 0 && pc_attr_vdata) {
+ ret = tnet_stun_pkt_attrs_add(message,
+ TNET_STUN_PKT_ATTR_ADD_USERNAME(pc_attr_vdata->p_data_ptr, pc_attr_vdata->u_data_size),
TNET_STUN_PKT_ATTR_ADD_NULL());
-
if (ret) {
goto bail;
}
- b_changed = tsk_true;
}
}
- else {
- tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_use_candidate);
- tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlling);
- if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlled)) {
- ret = tnet_stun_pkt_attrs_add(self->last_request,
- TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker),
+ // MAPPED-ADDRESS and XOR-MAPPED-ADDRESS
+ if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port)) == 0) {
+ tnet_stun_addr_t _addr;
+ tnet_stun_address_family_t _familly = (remote_addr->ss_family == AF_INET6) ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4;
+ if ((ret = tnet_stun_utils_inet_pton((_familly == tnet_stun_address_family_ipv6), remote_ip, &_addr)) == 0) {
+ ret = tnet_stun_pkt_attrs_add(message,
+ TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(_familly, remote_port, &_addr),
+ TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(_familly, remote_port, &_addr),
TNET_STUN_PKT_ATTR_ADD_NULL());
if (ret) {
goto bail;
}
- b_changed = tsk_true;
}
}
- // update transac-id if the request structure changed
- if ((b_changed && (ret = tnet_stun_utils_transac_id_rand(&self->last_request->transac_id)))) {
- goto bail;
- }
}
-
- // Send request
- {
- tsk_buffer_t *req_buffer = tsk_null;
- self->last_request->opt.fingerprint = !self->is_ice_jingle;
- if ((ret = tnet_stun_pkt_write_with_padding_2(self->last_request, &req_buffer))) {
+
+ if (self->candidate_offer->turn.ss) {
+ enum tnet_stun_state_e e_state;
+ if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) {
goto bail;
}
- if (self->candidate_offer->turn.ss) {
- // Send using TURN session. Above, we already checked that the TURN session is ready (Alloc=OK, Permission=OK)
- ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size);
+ if (e_state != tnet_stun_state_ok) {
+ TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN response (peer-id=%ld)", self->turn_peer_id);
+ goto bail;
}
- else {
- int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&self->remote_addr, req_buffer->data, req_buffer->size);
- ret = (sendBytes == req_buffer->size) ? 0 : -9;
+ if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
+ goto bail;
}
- TSK_OBJECT_SAFE_FREE(req_buffer);
- if (ret) {
+ if ((ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size))) {
goto bail;
}
}
-
- bail:
- if (ret == 0 && self->state_offer == tnet_ice_pair_state_frozen) {
- self->state_offer = tnet_ice_pair_state_in_progress;
- }
- return ret;
- }
-
- int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr)
- {
- tnet_stun_pkt_t* message = tsk_null;
- const char *password, *username;
- int ret = -1;
- tsk_bool_t is_error = ((code / 100) != 2);
-
- if(!self || !phrase || !request || !self->candidate_offer || !self->candidate_answer){
- TSK_DEBUG_ERROR("Invalid paramter");
- return -1;
- }
-
- username = tsk_null;
- password = tnet_ice_candidate_get_pwd(self->candidate_offer);
-
- if ((ret = tnet_stun_pkt_create_empty(is_error ? tnet_stun_pkt_type_binding_error_response : tnet_stun_pkt_type_binding_success_response, &message)) == 0) {
- tsk_buffer_t *req_buffer = tsk_null;
- memcpy(message->transac_id, request->transac_id, sizeof(request->transac_id));
- message->opt.fingerprint = !self->is_ice_jingle;
- message->opt.dontfrag = 0;
-
- // SOFWARE
- ret = tnet_stun_pkt_attrs_add(message,
- TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
- TNET_STUN_PKT_ATTR_ADD_NULL());
- if (ret) {
+ else {
+ struct sockaddr_storage dest_addr;
+ int sendBytes;
+ if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))) {
+ TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
goto bail;
}
-
- // SHORT-TERM authentication even for responses
- if ((ret = tnet_stun_pkt_auth_prepare_shortterm_2(message, password))) {
+ if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
goto bail;
}
-
- // ERROR
- if (is_error) {
- ret = tnet_stun_pkt_attrs_add(message,
- TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(((code / 100) & 0x07), (code - ((code / 100) * 100)), phrase),
- TNET_STUN_PKT_ATTR_ADD_NULL());
- if (ret) {
- goto bail;
- }
- }
- else {
- tnet_ip_t remote_ip;
- tnet_port_t remote_port;
- if (self->is_ice_jingle) {
- const tnet_stun_attr_vdata_t *pc_attr_vdata;
- // USERNAME
- if ((ret = tnet_stun_pkt_attr_find_first(request, tnet_stun_attr_type_username, (const tnet_stun_attr_t **)&pc_attr_vdata)) == 0 && pc_attr_vdata) {
- ret = tnet_stun_pkt_attrs_add(message,
- TNET_STUN_PKT_ATTR_ADD_USERNAME(pc_attr_vdata->p_data_ptr, pc_attr_vdata->u_data_size),
- TNET_STUN_PKT_ATTR_ADD_NULL());
- if (ret) {
- goto bail;
- }
- }
- }
- // MAPPED-ADDRESS and XOR-MAPPED-ADDRESS
- if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port)) == 0) {
- tnet_stun_addr_t _addr;
- tnet_stun_address_family_t _familly = (remote_addr->ss_family == AF_INET6) ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4;
- if ((ret = tnet_stun_utils_inet_pton((_familly == tnet_stun_address_family_ipv6), remote_ip, &_addr)) == 0) {
- ret = tnet_stun_pkt_attrs_add(message,
- TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(_familly, remote_port, &_addr),
- TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(_familly, remote_port, &_addr),
- TNET_STUN_PKT_ATTR_ADD_NULL());
- if (ret) {
- goto bail;
- }
- }
- }
- }
-
- if (self->candidate_offer->turn.ss) {
- enum tnet_stun_state_e e_state;
- if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) {
- goto bail;
- }
- if (e_state != tnet_stun_state_ok) {
- TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN response (peer-id=%ld)", self->turn_peer_id);
- goto bail;
- }
- if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
- goto bail;
- }
- if ((ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size))) {
- goto bail;
- }
- }
- else {
- struct sockaddr_storage dest_addr;
- int sendBytes;
- if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))) {
- TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port);
- goto bail;
- }
- if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) {
- goto bail;
- }
- sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size);
- TSK_OBJECT_SAFE_FREE(req_buffer);
- ret = (sendBytes > 0) ? 0 : -2;
- if (ret != 0) {
- TSK_DEBUG_ERROR("ICE pair-answer: failed to send response");
- }
+ sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size);
+ TSK_OBJECT_SAFE_FREE(req_buffer);
+ ret = (sendBytes > 0) ? 0 : -2;
+ if (ret != 0) {
+ TSK_DEBUG_ERROR("ICE pair-answer: failed to send response");
}
}
-
- if (ret == 0 && !is_error) {
- tsk_bool_t change_state =
+ }
+
+ if (ret == 0 && !is_error) {
+ tsk_bool_t change_state =
self->is_ice_jingle // ICE-JINGLE don't have ICE-CONTROLLING/ICE-CONTROLLED attributes
|| (!self->is_controlling && tnet_stun_pkt_attr_exists(request, tnet_stun_attr_type_ice_use_candidate)) // Sender is controlling and uses "ICE-USE-CANDIDATE" attribute
#if TNET_ICE_AGGRESSIVE_NOMINATION || 1 // This is not a typo but a *must*. We've to change the answer state regardless the nomination mode otherwise we'll never get a nominee. Only the offer state is controlled based on the mode and depends on "is_nominated".
@@ -511,301 +514,300 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self)
|| (self->is_controlling && self->is_nominated) // We're controlling and using regular mode
#endif
;
- TNET_ICE_PAIR_DEBUG_INFO("ICE pair-answer changing state to 'succeed' ? %s, comp-id=%d, found=%s, addr=%s",
- change_state?"yes":"no",
- self->candidate_answer->comp_id,
- self->candidate_answer->foundation,
- self->candidate_answer->connection_addr
- );
- if (change_state) {
- self->state_answer = tnet_ice_pair_state_succeed;
- }
- }
-
-
- bail:
- TSK_OBJECT_SAFE_FREE(message);
- return ret;
+ TNET_ICE_PAIR_DEBUG_INFO("ICE pair-answer changing state to 'succeed' ? %s, comp-id=%d, found=%s, addr=%s",
+ change_state?"yes":"no",
+ self->candidate_answer->comp_id,
+ self->candidate_answer->foundation,
+ self->candidate_answer->connection_addr
+ );
+ if (change_state) {
+ self->state_answer = tnet_ice_pair_state_succeed;
+ }
}
-
- int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase)
- {
- const uint8_t* _request_buff = (const uint8_t*)request_buff;
-
- const tnet_stun_attr_t* stun_att;
- const tnet_stun_attr_vdata_t *stun_att_usr_name;
- const tnet_stun_attr_vdata_t *stun_att_fingerprint;
- const tnet_stun_attr_vdata_t *stun_att_integrity;
-
- const tsk_list_item_t *item;
- tsk_sha1digest_t hmac;
- const char* pwd;
-
- tsk_size_t msg_integrity_start = 0, length, i;
-
- if(!self || !request || !request_buff || !request_buff_size || !resp_code || !resp_phrase){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if(!TNET_STUN_BUFF_IS_STUN2(_request_buff, request_buff_size)){
- TSK_DEBUG_ERROR("Not STUN buffer");
- return -1;
- }
-
- pwd = tnet_ice_candidate_get_pwd(self->candidate_offer);
- stun_att_usr_name = tsk_null;
- stun_att_fingerprint = tsk_null;
- stun_att_integrity = tsk_null;
-
- tsk_list_foreach(item, request->p_list_attrs) {
- if ((!(stun_att = (const tnet_stun_attr_t*)item->data))) {
- continue;
- }
-
- switch (stun_att->hdr.e_type) {
- case tnet_stun_attr_type_username:
- {
- stun_att_usr_name = (const tnet_stun_attr_vdata_t *)stun_att;
- break;
- }
- case tnet_stun_attr_type_fingerprint:
- {
- stun_att_fingerprint = (const tnet_stun_attr_vdata_t *)stun_att;
- break;
- }
- case tnet_stun_attr_type_message_integrity:
- {
- stun_att_integrity = (const tnet_stun_attr_vdata_t *)stun_att;
- break;
- }
- default: break;
- }
-
- if (!stun_att_integrity) {
- if ((length = (kStunAttrHdrSizeInOctets + stun_att->hdr.u_length)) & 0x03) {
- length += (4 - (length & 0x03));
- }
- msg_integrity_start += length;
- }
+
+
+bail:
+ TSK_OBJECT_SAFE_FREE(message);
+ return ret;
+}
+
+int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase)
+{
+ const uint8_t* _request_buff = (const uint8_t*)request_buff;
+
+ const tnet_stun_attr_t* stun_att;
+ const tnet_stun_attr_vdata_t *stun_att_usr_name;
+ const tnet_stun_attr_vdata_t *stun_att_fingerprint;
+ const tnet_stun_attr_vdata_t *stun_att_integrity;
+
+ const tsk_list_item_t *item;
+ tsk_sha1digest_t hmac;
+ const char* pwd;
+
+ tsk_size_t msg_integrity_start = 0, length, i;
+
+ if(!self || !request || !request_buff || !request_buff_size || !resp_code || !resp_phrase) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!TNET_STUN_BUFF_IS_STUN2(_request_buff, request_buff_size)) {
+ TSK_DEBUG_ERROR("Not STUN buffer");
+ return -1;
+ }
+
+ pwd = tnet_ice_candidate_get_pwd(self->candidate_offer);
+ stun_att_usr_name = tsk_null;
+ stun_att_fingerprint = tsk_null;
+ stun_att_integrity = tsk_null;
+
+ tsk_list_foreach(item, request->p_list_attrs) {
+ if ((!(stun_att = (const tnet_stun_attr_t*)item->data))) {
+ continue;
}
-
- if (!stun_att_usr_name) {
- TSK_DEBUG_ERROR("USERNAME is missing");
- *resp_code = 400;
- tsk_strupdate(resp_phrase, "USERNAME is missing");
- return -2;
- }
-
- if (!stun_att_integrity || stun_att_integrity->u_data_size != TSK_SHA1_DIGEST_SIZE) {
- if (self->is_ice_jingle) { // Bug introduced in Chrome 20.0.1120.0 (Not security issue as ICE-JINGLE is deprecated and will never be ON)
- *resp_code = 200;
- tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing but accepted");
- return 0;
- }
- else {
- TSK_DEBUG_ERROR("MESSAGE-INTEGRITY is missing");
- *resp_code = 400;
- tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing");
- return -3;
+
+ switch (stun_att->hdr.e_type) {
+ case tnet_stun_attr_type_username: {
+ stun_att_usr_name = (const tnet_stun_attr_vdata_t *)stun_att;
+ break;
+ }
+ case tnet_stun_attr_type_fingerprint: {
+ stun_att_fingerprint = (const tnet_stun_attr_vdata_t *)stun_att;
+ break;
+ }
+ case tnet_stun_attr_type_message_integrity: {
+ stun_att_integrity = (const tnet_stun_attr_vdata_t *)stun_att;
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!stun_att_integrity) {
+ if ((length = (kStunAttrHdrSizeInOctets + stun_att->hdr.u_length)) & 0x03) {
+ length += (4 - (length & 0x03));
}
+ msg_integrity_start += length;
}
-
- if ((kStunPktHdrSizeInOctets + msg_integrity_start) >= request_buff_size) {
- TSK_DEBUG_ERROR("Invalid length");
- *resp_code = 400;
- tsk_strupdate(resp_phrase, "Invalid length");
- return -20;
- }
-
- if (request->u_length != msg_integrity_start) {
- tsk_size_t size = (kStunPktHdrSizeInOctets + msg_integrity_start);
- uint8_t* new_buffer = (uint8_t*)tsk_calloc(size, 1);
- if (!new_buffer) {
- TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)msg_integrity_start);
- return -30;
- }
- memcpy(new_buffer, request_buff, size);
- length = msg_integrity_start + (kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
- new_buffer[2] = (length >> 8) & 0xFF;
- new_buffer[3] = (length & 0xFF);
- hmac_sha1digest_compute(new_buffer, size, pwd, tsk_strlen(pwd), hmac);
- TSK_FREE(new_buffer);
+ }
+
+ if (!stun_att_usr_name) {
+ TSK_DEBUG_ERROR("USERNAME is missing");
+ *resp_code = 400;
+ tsk_strupdate(resp_phrase, "USERNAME is missing");
+ return -2;
+ }
+
+ if (!stun_att_integrity || stun_att_integrity->u_data_size != TSK_SHA1_DIGEST_SIZE) {
+ if (self->is_ice_jingle) { // Bug introduced in Chrome 20.0.1120.0 (Not security issue as ICE-JINGLE is deprecated and will never be ON)
+ *resp_code = 200;
+ tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing but accepted");
+ return 0;
}
else {
- // must never happen
- hmac_sha1digest_compute(request_buff, request_buff_size, pwd, tsk_strlen(pwd), hmac);
- }
-
- for (i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) {
- if (hmac[i] != stun_att_integrity->p_data_ptr[i]) {
- TSK_DEBUG_ERROR("MESSAGE-INTEGRITY mismatch");
- *resp_code = 401;
- tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY mismatch");
- return -40;
- }
- }
-
- *resp_code = 200;
- tsk_strupdate(resp_phrase, "Ok");
-
- return 0;
+ TSK_DEBUG_ERROR("MESSAGE-INTEGRITY is missing");
+ *resp_code = 400;
+ tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing");
+ return -3;
+ }
}
-
- int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_pkt_resp_t* response, tsk_bool_t is_4conncheck)
- {
- if (self && response && TNET_STUN_PKT_IS_RESP(response)) {
- if (self->last_request && tnet_stun_utils_transac_id_equals(self->last_request->transac_id, response->transac_id)){
- // ignore errors (e.g. STALE-CREDENTIALS) which could happen in some special cases before success
- if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) {
- if (is_4conncheck) {
- self->state_offer = tnet_ice_pair_state_succeed; // we must not change the state after connection cheking to make sure another pair won't be picked as nominated
- TNET_ICE_PAIR_DEBUG_INFO("ICE pair-offer changing state to 'succeed', comp-id=%d, found=%s, addr=%s",
- self->candidate_offer->comp_id,
- self->candidate_offer->foundation,
- self->candidate_offer->connection_addr
- );
- }
+
+ if ((kStunPktHdrSizeInOctets + msg_integrity_start) >= request_buff_size) {
+ TSK_DEBUG_ERROR("Invalid length");
+ *resp_code = 400;
+ tsk_strupdate(resp_phrase, "Invalid length");
+ return -20;
+ }
+
+ if (request->u_length != msg_integrity_start) {
+ tsk_size_t size = (kStunPktHdrSizeInOctets + msg_integrity_start);
+ uint8_t* new_buffer = (uint8_t*)tsk_calloc(size, 1);
+ if (!new_buffer) {
+ TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)msg_integrity_start);
+ return -30;
+ }
+ memcpy(new_buffer, request_buff, size);
+ length = msg_integrity_start + (kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
+ new_buffer[2] = (length >> 8) & 0xFF;
+ new_buffer[3] = (length & 0xFF);
+ hmac_sha1digest_compute(new_buffer, size, pwd, tsk_strlen(pwd), hmac);
+ TSK_FREE(new_buffer);
+ }
+ else {
+ // must never happen
+ hmac_sha1digest_compute(request_buff, request_buff_size, pwd, tsk_strlen(pwd), hmac);
+ }
+
+ for (i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) {
+ if (hmac[i] != stun_att_integrity->p_data_ptr[i]) {
+ TSK_DEBUG_ERROR("MESSAGE-INTEGRITY mismatch");
+ *resp_code = 401;
+ tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY mismatch");
+ return -40;
+ }
+ }
+
+ *resp_code = 200;
+ tsk_strupdate(resp_phrase, "Ok");
+
+ return 0;
+}
+
+int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_pkt_resp_t* response, tsk_bool_t is_4conncheck)
+{
+ if (self && response && TNET_STUN_PKT_IS_RESP(response)) {
+ if (self->last_request && tnet_stun_utils_transac_id_equals(self->last_request->transac_id, response->transac_id)) {
+ // ignore errors (e.g. STALE-CREDENTIALS) which could happen in some special cases before success
+ if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) {
+ if (is_4conncheck) {
+ self->state_offer = tnet_ice_pair_state_succeed; // we must not change the state after connection cheking to make sure another pair won't be picked as nominated
+ TNET_ICE_PAIR_DEBUG_INFO("ICE pair-offer changing state to 'succeed', comp-id=%d, found=%s, addr=%s",
+ self->candidate_offer->comp_id,
+ self->candidate_offer->foundation,
+ self->candidate_offer->connection_addr
+ );
}
- else {
- // The response is an error
- uint16_t u_code;
- int ret;
- if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code)) == 0 && u_code == kStunErrCodeIceConflict) {
- TSK_DEBUG_INFO("ICE Pair %llu received conflict error message", self->id);
- // If this code is called this means that we have lower tie-breaker and we must toggle our role
- self->is_controlling = !self->is_controlling;
- TSK_OBJECT_SAFE_FREE(self->last_request); // delete the "last_request" to make sure a new one will be created with right attributes
- }
+ }
+ else {
+ // The response is an error
+ uint16_t u_code;
+ int ret;
+ if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code)) == 0 && u_code == kStunErrCodeIceConflict) {
+ TSK_DEBUG_INFO("ICE Pair %llu received conflict error message", self->id);
+ // If this code is called this means that we have lower tie-breaker and we must toggle our role
+ self->is_controlling = !self->is_controlling;
+ TSK_OBJECT_SAFE_FREE(self->last_request); // delete the "last_request" to make sure a new one will be created with right attributes
}
}
}
- return 0;
}
-
- const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_pkt_t* response)
- {
- if(pairs && response){
- const tsk_list_item_t *item;
- const tnet_ice_pair_t *pair;
- tnet_port_t mapped_port;
- tnet_ip_t mapped_ip;
- tsk_list_foreach(item, pairs){
- if(!(pair = item->data) || !pair->candidate_answer || !pair->candidate_offer){
- continue;
+ return 0;
+}
+
+const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_pkt_t* response)
+{
+ if(pairs && response) {
+ const tsk_list_item_t *item;
+ const tnet_ice_pair_t *pair;
+ tnet_port_t mapped_port;
+ tnet_ip_t mapped_ip;
+ tsk_list_foreach(item, pairs) {
+ if(!(pair = item->data) || !pair->candidate_answer || !pair->candidate_offer) {
+ continue;
+ }
+ if(pair->last_request && tnet_stun_utils_transac_id_equals(pair->last_request->transac_id, response->transac_id)) {
+ // check that mapped/xmapped address match destination
+ const tnet_stun_attr_address_t *xmapped_addr = tsk_null;
+ const tnet_stun_attr_address_t* mapped_addr = tsk_null;
+ const tnet_stun_attr_address_t* _addr;
+
+ tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t **)&xmapped_addr);
+ tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t **)&mapped_addr);
+ _addr = xmapped_addr ? xmapped_addr : mapped_addr;
+
+ if (!_addr) {
+ return pair; // do nothing if the client doesn't return mapped address STUN attribute
}
- if(pair->last_request && tnet_stun_utils_transac_id_equals(pair->last_request->transac_id, response->transac_id)){
- // check that mapped/xmapped address match destination
- const tnet_stun_attr_address_t *xmapped_addr = tsk_null;
- const tnet_stun_attr_address_t* mapped_addr = tsk_null;
- const tnet_stun_attr_address_t* _addr;
-
- tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t **)&xmapped_addr);
- tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t **)&mapped_addr);
- _addr = xmapped_addr ? xmapped_addr : mapped_addr;
-
- if (!_addr) {
- return pair; // do nothing if the client doesn't return mapped address STUN attribute
- }
- /* rfc 5245 7.1.3.2.1. Discovering Peer Reflexive Candidates
-
- The agent checks the mapped address from the STUN response. If the
- transport address does not match any of the local candidates that the
- agent knows about, the mapped address represents a new candidate -- a
- peer reflexive candidate. Like other candidates, it has a type,
- base, priority, and foundation. They are computed as follows:
-
- o Its type is equal to peer reflexive.
-
- o Its base is set equal to the local candidate of the candidate pair
- from which the STUN check was sent.
-
- o Its priority is set equal to the value of the PRIORITY attribute
- in the Binding request.
-
- o Its foundation is selected as described in Section 4.1.1.3.
-
- This peer reflexive candidate is then added to the list of local
- candidates for the media stream. Its username fragment and password
- are the same as all other local candidates for that media stream.
- */
-
- tnet_stun_utils_inet_ntop((_addr->e_family == tnet_stun_address_family_ipv6), &_addr->address, &mapped_ip);
- mapped_port = _addr->u_port;
- if (pair->candidate_offer->type_e != tnet_ice_cand_type_host && (mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_ip, pair->candidate_offer->connection_addr))) {
- TSK_DEBUG_INFO("Mapped address different than local connection address...probably symetric NAT: %s#%s or %u#%u",
- pair->candidate_offer->connection_addr, mapped_ip,
- pair->candidate_offer->port, mapped_port);
- // do we really need to add new local candidate?
- // continue;
- }
- return pair;
+ /* rfc 5245 7.1.3.2.1. Discovering Peer Reflexive Candidates
+
+ The agent checks the mapped address from the STUN response. If the
+ transport address does not match any of the local candidates that the
+ agent knows about, the mapped address represents a new candidate -- a
+ peer reflexive candidate. Like other candidates, it has a type,
+ base, priority, and foundation. They are computed as follows:
+
+ o Its type is equal to peer reflexive.
+
+ o Its base is set equal to the local candidate of the candidate pair
+ from which the STUN check was sent.
+
+ o Its priority is set equal to the value of the PRIORITY attribute
+ in the Binding request.
+
+ o Its foundation is selected as described in Section 4.1.1.3.
+
+ This peer reflexive candidate is then added to the list of local
+ candidates for the media stream. Its username fragment and password
+ are the same as all other local candidates for that media stream.
+ */
+
+ tnet_stun_utils_inet_ntop((_addr->e_family == tnet_stun_address_family_ipv6), &_addr->address, &mapped_ip);
+ mapped_port = _addr->u_port;
+ if (pair->candidate_offer->type_e != tnet_ice_cand_type_host && (mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_ip, pair->candidate_offer->connection_addr))) {
+ TSK_DEBUG_INFO("Mapped address different than local connection address...probably symetric NAT: %s#%s or %u#%u",
+ pair->candidate_offer->connection_addr, mapped_ip,
+ pair->candidate_offer->port, mapped_port);
+ // do we really need to add new local candidate?
+ // continue;
}
+ return pair;
}
}
+ }
+ return tsk_null;
+}
+
+const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pairs, tnet_fd_t local_fd, const struct sockaddr_storage *remote_addr)
+{
+ int ret;
+ const tsk_list_item_t *item;
+ const tnet_ice_pair_t *pair;
+ tnet_ip_t remote_ip;
+ tnet_port_t remote_port;
+
+ if(!pairs || !remote_addr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
-
- const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pairs, tnet_fd_t local_fd, const struct sockaddr_storage *remote_addr)
- {
- int ret;
+
+ if((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))) {
+ TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed");
+ return tsk_null;
+ }
+
+ tsk_list_foreach(item, pairs) {
+ if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) {
+ continue;
+ }
+ if (!tsk_striequals(pair->candidate_answer->connection_addr, remote_ip) || pair->candidate_answer->port != remote_port) {
+ continue;
+ }
+
+ return pair;
+ }
+
+ TSK_DEBUG_INFO("No ICE candidate with remote ip = %s, port = %u and local_fd = %d could be found...probably symetric NAT", remote_ip, remote_port, local_fd);
+
+ return tsk_null;
+}
+
+
+static tsk_bool_t _tnet_ice_pairs_none_succeed(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, const char* foundation, tsk_bool_t answer)
+{
+ if(pairs && foundation) {
const tsk_list_item_t *item;
const tnet_ice_pair_t *pair;
- tnet_ip_t remote_ip;
- tnet_port_t remote_port;
-
- if(!pairs || !remote_addr){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
-
- if((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))){
- TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed");
- return tsk_null;
- }
-
- tsk_list_foreach(item, pairs){
- if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) {
+ const tnet_ice_candidate_t* candidate;
+ tsk_list_foreach(item, pairs) {
+ if(!(pair = item->data) || !(candidate = (answer ? pair->candidate_answer : pair->candidate_offer))) {
continue;
}
- if (!tsk_striequals(pair->candidate_answer->connection_addr, remote_ip) || pair->candidate_answer->port != remote_port) {
+ if(candidate->comp_id != comp_id || !tsk_striequals(candidate->foundation, foundation)) {
continue;
}
-
- return pair;
- }
-
- TSK_DEBUG_INFO("No ICE candidate with remote ip = %s, port = %u and local_fd = %d could be found...probably symetric NAT", remote_ip, remote_port, local_fd);
-
- return tsk_null;
- }
-
-
- static tsk_bool_t _tnet_ice_pairs_none_succeed(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, const char* foundation, tsk_bool_t answer){
- if(pairs && foundation){
- const tsk_list_item_t *item;
- const tnet_ice_pair_t *pair;
- const tnet_ice_candidate_t* candidate;
- tsk_list_foreach(item, pairs){
- if(!(pair = item->data) || !(candidate = (answer ? pair->candidate_answer : pair->candidate_offer))){
- continue;
- }
- if(candidate->comp_id != comp_id || !tsk_striequals(candidate->foundation, foundation)){
- continue;
- }
- if((answer ? pair->state_answer : pair->state_offer) == tnet_ice_pair_state_succeed){
- TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):false", answer?"anwser":"offer", comp_id, foundation);
- return tsk_false;
- }
+ if((answer ? pair->state_answer : pair->state_offer) == tnet_ice_pair_state_succeed) {
+ TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):false", answer?"anwser":"offer", comp_id, foundation);
+ return tsk_false;
}
}
- TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):true", answer?"anwser":"offer", comp_id, foundation);
- return tsk_true;
}
+ TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):true", answer?"anwser":"offer", comp_id, foundation);
+ return tsk_true;
+}
#define _tnet_ice_pairs_none_succeed_answer(pairs, comp_id, foundation) _tnet_ice_pairs_none_succeed((pairs), (comp_id), (foundation), tsk_true)
#define _tnet_ice_pairs_none_succeed_offer(pairs, comp_id, foundation) _tnet_ice_pairs_none_succeed((pairs), (comp_id), (foundation), tsk_false)
-
- // both RTP and RTCP have succeeded
+
+// both RTP and RTCP have succeeded
#define _tnet_ice_pairs_get_nominated_offer_at(pairs, index, comp_id, check_fullness, ret) _tnet_ice_pairs_get_nominated_at((pairs), offer, answer, (index), (comp_id), (check_fullness), (ret))
#define _tnet_ice_pairs_get_nominated_answer_at(pairs, index, comp_id, check_fullness, ret) _tnet_ice_pairs_get_nominated_at((pairs), answer, offer, (index), (comp_id), (check_fullness), (ret))
#define _tnet_ice_pairs_get_nominated_at(pairs, dir_1, dir_2, index, _comp_id, check_fullness, ret) \
@@ -851,138 +853,146 @@ break; \
} \
} \
} \
+
+// true only if both RTP and RTCP are nominated
+tsk_bool_t tnet_ice_pairs_have_nominated_offer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
+{
+ const tnet_ice_pair_t *pair_ = tsk_null;
+ tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
+ TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_offer()");
+ _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_));
+ if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp) {
+ _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_));
+ is_nominated_rtcp =(pair_ != tsk_null);
+ }
+ TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_offer=%s, is_nominated_rtcp_offer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no");
+ return (is_nominated_rtp && is_nominated_rtcp);
+}
- // true only if both RTP and RTCP are nominated
- tsk_bool_t tnet_ice_pairs_have_nominated_offer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
- {
- const tnet_ice_pair_t *pair_ = tsk_null;
- tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
- TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_offer()");
- _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_));
- if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp){
- _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_));
- is_nominated_rtcp =(pair_ != tsk_null);
- }
- TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_offer=%s, is_nominated_rtcp_offer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no");
- return (is_nominated_rtp && is_nominated_rtcp);
- }
-
- // true only if both RTP and RTCP are nominated
- tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
- {
- const tnet_ice_pair_t *pair_ = tsk_null;
- tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
- TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_answer()");
- _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_));
- if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp){
- _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_));
- is_nominated_rtcp =(pair_ != tsk_null);
- }
- TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_answer=%s, is_nominated_rtcp_answer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no");
- return (is_nominated_rtp && is_nominated_rtcp);
- }
-
- // true only if both RTP and RTCP are nominated in symetric way
- tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts)
- {
- const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest;
- tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
- int ret;
-
- if (got_hosts) {
- *got_hosts = tsk_false;
- }
- ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
- if ((is_nominated_rtp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) {
- *got_hosts = (candidate_offer->type_e == tnet_ice_cand_type_host
- && candidate_answer_src->type_e == tnet_ice_cand_type_host
- && candidate_answer_dest->type_e == tnet_ice_cand_type_host);
- }
- if(is_nominated_rtp && check_rtcp){
- ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
- if ((is_nominated_rtcp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) {
- *got_hosts &= (candidate_offer->type_e == tnet_ice_cand_type_host
- && candidate_answer_src->type_e == tnet_ice_cand_type_host
- && candidate_answer_dest->type_e == tnet_ice_cand_type_host);
- }
+// true only if both RTP and RTCP are nominated
+tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
+{
+ const tnet_ice_pair_t *pair_ = tsk_null;
+ tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
+ TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_answer()");
+ _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_));
+ if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp) {
+ _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_));
+ is_nominated_rtcp =(pair_ != tsk_null);
+ }
+ TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_answer=%s, is_nominated_rtcp_answer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no");
+ return (is_nominated_rtp && is_nominated_rtcp);
+}
+
+// true only if both RTP and RTCP are nominated in symetric way
+tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts)
+{
+ const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest;
+ tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true;
+ int ret;
+
+ if (got_hosts) {
+ *got_hosts = tsk_false;
+ }
+ ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
+ if ((is_nominated_rtp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) {
+ *got_hosts = (candidate_offer->type_e == tnet_ice_cand_type_host
+ && candidate_answer_src->type_e == tnet_ice_cand_type_host
+ && candidate_answer_dest->type_e == tnet_ice_cand_type_host);
+ }
+ if(is_nominated_rtp && check_rtcp) {
+ ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest);
+ if ((is_nominated_rtcp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) {
+ *got_hosts &= (candidate_offer->type_e == tnet_ice_cand_type_host
+ && candidate_answer_src->type_e == tnet_ice_cand_type_host
+ && candidate_answer_dest->type_e == tnet_ice_cand_type_host);
}
- return (is_nominated_rtp && is_nominated_rtcp);
}
-
- // true only if both RTP and RTCP are nominated in symetric way
- tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
- {
+ return (is_nominated_rtp && is_nominated_rtcp);
+}
+
+// true only if both RTP and RTCP are nominated in symetric way
+tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp)
+{
#define got_hosts tsk_null
- return tnet_ice_pairs_have_nominated_symetric_2(pairs, check_rtcp, got_hosts);
- }
-
- // gets symetric nominated candidates with the highest priority
- // will succeed only if both RTP and RTCP are ok
- int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
- const tnet_ice_candidate_t** candidate_offer,
- const tnet_ice_candidate_t** candidate_answer_src,
- const tnet_ice_candidate_t** candidate_answer_dest)
- {
- int ret;
- const tnet_ice_pair_t *pair_offer = tsk_null, *pair_answer_src = tsk_null, *pair_answer_dest = tsk_null;
- if (!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- *candidate_offer = tsk_null;
- *candidate_answer_src = tsk_null;
- *candidate_answer_dest = tsk_null;
-
- if ((ret = tnet_ice_pairs_get_nominated_symetric_pairs(pairs, comp_id, &pair_offer, &pair_answer_src, &pair_answer_dest)) == 0) {
- *candidate_offer = pair_offer ? pair_offer->candidate_offer : tsk_null;
- *candidate_answer_src = pair_answer_src ? pair_answer_src->candidate_answer : tsk_null;
- *candidate_answer_dest = pair_answer_dest ? pair_answer_dest->candidate_answer : tsk_null;
- }
- return ret;
+ return tnet_ice_pairs_have_nominated_symetric_2(pairs, check_rtcp, got_hosts);
+}
+
+// gets symetric nominated candidates with the highest priority
+// will succeed only if both RTP and RTCP are ok
+int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
+ const tnet_ice_candidate_t** candidate_offer,
+ const tnet_ice_candidate_t** candidate_answer_src,
+ const tnet_ice_candidate_t** candidate_answer_dest)
+{
+ int ret;
+ const tnet_ice_pair_t *pair_offer = tsk_null, *pair_answer_src = tsk_null, *pair_answer_dest = tsk_null;
+ if (!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
}
-
- int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
- const struct tnet_ice_pair_s** _pair_offer,
- const struct tnet_ice_pair_s** _pair_answer_src,
- const struct tnet_ice_pair_s** _pair_answer_dest)
- {
- const tnet_ice_pair_t *pair_offer = tsk_null;
- const tnet_ice_pair_t *pair_answer = tsk_null;
- tsk_size_t i_offer, i_answer;
- static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly
-
- if (!pairs || !_pair_offer || !_pair_answer_src || !_pair_answer_dest) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- *_pair_offer = tsk_null;
- *_pair_answer_src = tsk_null;
- *_pair_answer_dest = tsk_null;
-
- i_offer = 0;
+
+ *candidate_offer = tsk_null;
+ *candidate_answer_src = tsk_null;
+ *candidate_answer_dest = tsk_null;
+
+ if ((ret = tnet_ice_pairs_get_nominated_symetric_pairs(pairs, comp_id, &pair_offer, &pair_answer_src, &pair_answer_dest)) == 0) {
+ *candidate_offer = pair_offer ? pair_offer->candidate_offer : tsk_null;
+ *candidate_answer_src = pair_answer_src ? pair_answer_src->candidate_answer : tsk_null;
+ *candidate_answer_dest = pair_answer_dest ? pair_answer_dest->candidate_answer : tsk_null;
+ }
+ return ret;
+}
+
+int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
+ const struct tnet_ice_pair_s** _pair_offer,
+ const struct tnet_ice_pair_s** _pair_answer_src,
+ const struct tnet_ice_pair_s** _pair_answer_dest)
+{
+ const tnet_ice_pair_t *pair_offer = tsk_null;
+ const tnet_ice_pair_t *pair_answer = tsk_null;
+ tsk_size_t i_offer, i_answer;
+ static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly
+
+ if (!pairs || !_pair_offer || !_pair_answer_src || !_pair_answer_dest) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ *_pair_offer = tsk_null;
+ *_pair_answer_src = tsk_null;
+ *_pair_answer_dest = tsk_null;
+
+ i_offer = 0;
+ while (1) {
+ _tnet_ice_pairs_get_nominated_offer_at((pairs), i_offer, comp_id, __check_fullness, (pair_offer)); // pair with socket SO as sender
+ if(!pair_offer) {
+ return 0;
+ }
+ ++i_offer;
+ if (pair_offer->candidate_offer->comp_id != comp_id) {
+ continue;
+ }
+ // find another pair with socket SO as receiver
+
+ i_answer = 0;
while (1) {
- _tnet_ice_pairs_get_nominated_offer_at((pairs), i_offer, comp_id, __check_fullness, (pair_offer)); // pair with socket SO as sender
- if(!pair_offer) return 0;
- ++i_offer;
- if (pair_offer->candidate_offer->comp_id != comp_id) continue;
- // find another pair with socket SO as receiver
-
- i_answer = 0;
- while (1) {
- _tnet_ice_pairs_get_nominated_answer_at((pairs), i_answer, comp_id, __check_fullness, (pair_answer));
- if (!pair_answer) break;
- ++i_answer;
- if (pair_answer->candidate_offer->comp_id != comp_id) continue;
- if (pair_answer->candidate_offer == pair_offer->candidate_offer) {
- *_pair_offer = pair_offer;
- *_pair_answer_src = pair_answer;
- *_pair_answer_dest = pair_offer;
- return 0;
- }
+ _tnet_ice_pairs_get_nominated_answer_at((pairs), i_answer, comp_id, __check_fullness, (pair_answer));
+ if (!pair_answer) {
+ break;
+ }
+ ++i_answer;
+ if (pair_answer->candidate_offer->comp_id != comp_id) {
+ continue;
+ }
+ if (pair_answer->candidate_offer == pair_offer->candidate_offer) {
+ *_pair_offer = pair_offer;
+ *_pair_answer_src = pair_answer;
+ *_pair_answer_dest = pair_offer;
+ return 0;
}
}
- return 0;
-
}
+ return 0;
+
+}
diff --git a/tinyNET/src/ice/tnet_ice_pair.h b/tinyNET/src/ice/tnet_ice_pair.h
index 7e40eb8..f3fb73d 100755
--- a/tinyNET/src/ice/tnet_ice_pair.h
+++ b/tinyNET/src/ice/tnet_ice_pair.h
@@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -32,33 +32,31 @@ typedef tsk_list_t tnet_ice_pairs_L_t;
struct tnet_ice_candidate_s;
-typedef enum tnet_ice_pair_state_e
-{
- tnet_ice_pair_state_frozen,
- tnet_ice_pair_state_waiting,
- tnet_ice_pair_state_in_progress,
- tnet_ice_pair_state_succeed,
- tnet_ice_pair_state_failed
+typedef enum tnet_ice_pair_state_e {
+ tnet_ice_pair_state_frozen,
+ tnet_ice_pair_state_waiting,
+ tnet_ice_pair_state_in_progress,
+ tnet_ice_pair_state_succeed,
+ tnet_ice_pair_state_failed
}
tnet_ice_pair_state_t;
-typedef struct tnet_ice_pair_s
-{
- TSK_DECLARE_OBJECT;
+typedef struct tnet_ice_pair_s {
+ TSK_DECLARE_OBJECT;
- uint64_t id;
- uint64_t priority;
- tnet_ice_pair_state_t state_offer;
- tnet_ice_pair_state_t state_answer;
- tsk_bool_t is_ice_jingle;
- tsk_bool_t is_controlling;
- tsk_bool_t is_nominated;
- uint64_t tie_breaker;
- struct tnet_ice_candidate_s* candidate_offer;
- struct tnet_ice_candidate_s* candidate_answer;
- struct tnet_stun_pkt_s* last_request;
- struct sockaddr_storage remote_addr;
- tnet_turn_peer_id_t turn_peer_id;
+ uint64_t id;
+ uint64_t priority;
+ tnet_ice_pair_state_t state_offer;
+ tnet_ice_pair_state_t state_answer;
+ tsk_bool_t is_ice_jingle;
+ tsk_bool_t is_controlling;
+ tsk_bool_t is_nominated;
+ uint64_t tie_breaker;
+ struct tnet_ice_candidate_s* candidate_offer;
+ struct tnet_ice_candidate_s* candidate_answer;
+ struct tnet_stun_pkt_s* last_request;
+ struct sockaddr_storage remote_addr;
+ tnet_turn_peer_id_t turn_peer_id;
}
tnet_ice_pair_t;
@@ -75,12 +73,12 @@ tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs,
tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp);
tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts);
int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
- const struct tnet_ice_candidate_s** candidate_offer,
- const struct tnet_ice_candidate_s** candidate_answer_src,
- const struct tnet_ice_candidate_s** candidate_answer_dest);
+ const struct tnet_ice_candidate_s** candidate_offer,
+ const struct tnet_ice_candidate_s** candidate_answer_src,
+ const struct tnet_ice_candidate_s** candidate_answer_dest);
int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id,
- const struct tnet_ice_pair_s** pair_offer,
- const struct tnet_ice_pair_s** pair_answer_src,
- const struct tnet_ice_pair_s** pair_answer_dest);
+ const struct tnet_ice_pair_s** pair_offer,
+ const struct tnet_ice_pair_s** pair_answer_src,
+ const struct tnet_ice_pair_s** pair_answer_dest);
#endif /* TNET_ICE_PAIR_H */
diff --git a/tinyNET/src/ice/tnet_ice_utils.c b/tinyNET/src/ice/tnet_ice_utils.c
index d4ba8a7..eae514e 100755
--- a/tinyNET/src/ice/tnet_ice_utils.c
+++ b/tinyNET/src/ice/tnet_ice_utils.c
@@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@@ -29,132 +29,144 @@
#include <stdlib.h>
-static const char ice_chars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'k', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'K', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- '0','1', '2', '3', '4', '5', '6', '7', '8', '9'}; // /!\do not add '/' and '+' because of WebRTC password
+static const char ice_chars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'k', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'K', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '0','1', '2', '3', '4', '5', '6', '7', '8', '9'
+ }; // /!\do not add '/' and '+' because of WebRTC password
static const tsk_size_t ice_chars_count = sizeof(ice_chars);
uint32_t tnet_ice_utils_get_priority(tnet_ice_cand_type_t type, uint16_t local_pref, tsk_bool_t is_rtp)
{
- uint32_t pref;
- switch(type){
- case tnet_ice_cand_type_host: pref = TNET_ICE_CANDIDATE_PREF_HOST; break;
- case tnet_ice_cand_type_srflx: pref = TNET_ICE_CANDIDATE_PREF_SRFLX; break;
- case tnet_ice_cand_type_prflx: pref = TNET_ICE_CANDIDATE_PREF_PRFLX; break;
- case tnet_ice_cand_type_relay: default: pref = TNET_ICE_CANDIDATE_PREF_RELAY; break;
- }
- return (pref << 24) +
- (local_pref << 8) +
- ((256 - (is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP)) << 0);
+ uint32_t pref;
+ switch(type) {
+ case tnet_ice_cand_type_host:
+ pref = TNET_ICE_CANDIDATE_PREF_HOST;
+ break;
+ case tnet_ice_cand_type_srflx:
+ pref = TNET_ICE_CANDIDATE_PREF_SRFLX;
+ break;
+ case tnet_ice_cand_type_prflx:
+ pref = TNET_ICE_CANDIDATE_PREF_PRFLX;
+ break;
+ case tnet_ice_cand_type_relay:
+ default:
+ pref = TNET_ICE_CANDIDATE_PREF_RELAY;
+ break;
+ }
+ return (pref << 24) +
+ (local_pref << 8) +
+ ((256 - (is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP)) << 0);
}
int tnet_ice_utils_compute_foundation(char* foundation, tsk_size_t size)
{
-
- tsk_size_t i;
-
- if(!foundation || !size){
- TSK_DEBUG_ERROR("Invalid argument");
- return -1;
- }
- for(
- i = 0; i < size; ++i){
- foundation[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
- }
-
- return 0;
+
+ tsk_size_t i;
+
+ if(!foundation || !size) {
+ TSK_DEBUG_ERROR("Invalid argument");
+ return -1;
+ }
+ for(
+ i = 0; i < size; ++i) {
+ foundation[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
+ }
+
+ return 0;
}
int tnet_ice_utils_create_sockets(tnet_socket_type_t socket_type, const char* local_ip, tnet_socket_t** socket_rtp, tnet_socket_t** socket_rtcp)
{
- tsk_bool_t look4_rtp = (socket_rtp != tsk_null);
- tsk_bool_t look4_rtcp = (socket_rtcp != tsk_null);
- uint8_t retry_count = 10;
- tnet_port_t local_port;
- static const uint64_t port_range_start = 1024;
- static const uint64_t port_range_stop = (65535 - 1/* to be sure rtcp port will be valid */);
- static uint64_t counter = 0;
-
- /* Creates local rtp and rtcp sockets */
- while(retry_count--){
- if(look4_rtp && look4_rtcp){
- tnet_socket_t* socket_fake = tnet_socket_create(local_ip, TNET_SOCKET_PORT_ANY, socket_type);
- if(!socket_fake){
- continue;
- }
- if(!(socket_fake->port & 0x01)){ // even number ?
- *socket_rtp = socket_fake;
- }
- else{
- *socket_rtcp = socket_fake;
- }
- local_port = (socket_fake->port & ~1);
- }
- else{
- local_port = (tnet_port_t)((((tsk_time_epoch() + rand() ) ^ ++counter) % (port_range_stop - port_range_start)) + port_range_start);
- local_port = (local_port & 0xFFFE); /* turn to even number */
- }
-
- /* beacuse failure will cause errors in the log, print a message to alert that there is
- * nothing to worry about */
- TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports [%s:%d]", local_ip, local_port);
-
- if(look4_rtp){
- if(!*socket_rtp && !(*socket_rtp = tnet_socket_create(local_ip, local_port, socket_type))){
- TSK_DEBUG_INFO("Failed to bind to %d", local_port);
- continue;
- }
- }
-
- if(look4_rtcp){
- if(!*socket_rtcp && !(*socket_rtcp = tnet_socket_create(local_ip, (local_port + 1), socket_type))){
- TSK_DEBUG_INFO("Failed to bind to %d", (local_port + 1));
- if(look4_rtp){
- TSK_OBJECT_SAFE_FREE((*socket_rtp));
- }
- continue;
- }
- }
-
- TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports");
- return 0;
- }
-
- TSK_DEBUG_ERROR("Failed to bind sockets");
- return -1;
+ tsk_bool_t look4_rtp = (socket_rtp != tsk_null);
+ tsk_bool_t look4_rtcp = (socket_rtcp != tsk_null);
+ uint8_t retry_count = 10;
+ tnet_port_t local_port;
+ static const uint64_t port_range_start = 1024;
+ static const uint64_t port_range_stop = (65535 - 1/* to be sure rtcp port will be valid */);
+ static uint64_t counter = 0;
+
+ /* Creates local rtp and rtcp sockets */
+ while(retry_count--) {
+ if(look4_rtp && look4_rtcp) {
+ tnet_socket_t* socket_fake = tnet_socket_create(local_ip, TNET_SOCKET_PORT_ANY, socket_type);
+ if(!socket_fake) {
+ continue;
+ }
+ if(!(socket_fake->port & 0x01)) { // even number ?
+ *socket_rtp = socket_fake;
+ }
+ else {
+ *socket_rtcp = socket_fake;
+ }
+ local_port = (socket_fake->port & ~1);
+ }
+ else {
+ local_port = (tnet_port_t)((((tsk_time_epoch() + rand() ) ^ ++counter) % (port_range_stop - port_range_start)) + port_range_start);
+ local_port = (local_port & 0xFFFE); /* turn to even number */
+ }
+
+ /* beacuse failure will cause errors in the log, print a message to alert that there is
+ * nothing to worry about */
+ TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports [%s:%d]", local_ip, local_port);
+
+ if(look4_rtp) {
+ if(!*socket_rtp && !(*socket_rtp = tnet_socket_create(local_ip, local_port, socket_type))) {
+ TSK_DEBUG_INFO("Failed to bind to %d", local_port);
+ continue;
+ }
+ }
+
+ if(look4_rtcp) {
+ if(!*socket_rtcp && !(*socket_rtcp = tnet_socket_create(local_ip, (local_port + 1), socket_type))) {
+ TSK_DEBUG_INFO("Failed to bind to %d", (local_port + 1));
+ if(look4_rtp) {
+ TSK_OBJECT_SAFE_FREE((*socket_rtp));
+ }
+ continue;
+ }
+ }
+
+ TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports");
+ return 0;
+ }
+
+ TSK_DEBUG_ERROR("Failed to bind sockets");
+ return -1;
}
int tnet_ice_utils_set_ufrag(char** ufrag)
{
- if(ufrag){
- char tmp[16]; int i;
- for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i){
- tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
- }
- tmp[i] = '\0';
- tsk_strupdate(ufrag, tmp);
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(ufrag) {
+ char tmp[16];
+ int i;
+ for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i) {
+ tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
+ }
+ tmp[i] = '\0';
+ tsk_strupdate(ufrag, tmp);
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
}
int tnet_ice_utils_set_pwd(char** pwd)
{
- if(pwd){
- char tmp[23]; int i;
- for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i){
- tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
- }
- tmp[i] = '\0';
- tsk_strupdate(pwd, tmp);
- return 0;
- }
- else{
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if(pwd) {
+ char tmp[23];
+ int i;
+ for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i) {
+ tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count];
+ }
+ tmp[i] = '\0';
+ tsk_strupdate(pwd, tmp);
+ return 0;
+ }
+ else {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
} \ No newline at end of file
diff --git a/tinyNET/src/ice/tnet_ice_utils.h b/tinyNET/src/ice/tnet_ice_utils.h
index 8e53915..541bb9a 100755
--- a/tinyNET/src/ice/tnet_ice_utils.h
+++ b/tinyNET/src/ice/tnet_ice_utils.h
@@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
-*
+*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-*
+*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
OpenPOWER on IntegriCloud