diff options
Diffstat (limited to 'tinyNET/src/ice')
-rwxr-xr-x | tinyNET/src/ice/tnet_ice.c | 6 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice.h | 6 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_candidate.c | 383 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_candidate.h | 92 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_ctx.c | 947 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_ctx.h | 40 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_event.c | 23 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_event.h | 58 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_pair.c | 1136 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_pair.h | 60 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_utils.c | 230 | ||||
-rwxr-xr-x | tinyNET/src/ice/tnet_ice_utils.h | 4 |
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**)¶m); - } - 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**)¶m); } + 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. * |