diff options
author | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
---|---|---|
committer | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
commit | 50dfb4359619563012997bc3ddafb7667741066c (patch) | |
tree | db234c1edc3240a653363b5735fc4077af4b8720 /tinyNET/src/turn | |
parent | 94b2219209038e05dd26395f6fb700be4d1062c0 (diff) | |
download | doubango-50dfb4359619563012997bc3ddafb7667741066c.zip doubango-50dfb4359619563012997bc3ddafb7667741066c.tar.gz |
Add new QoS implementation
Code formatting
Diffstat (limited to 'tinyNET/src/turn')
-rwxr-xr-x | tinyNET/src/turn/tnet_turn.c | 72 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn.h | 12 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_attribute.c | 56 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_attribute.h | 10 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_message.c | 16 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_message.h | 6 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_session.c | 3460 | ||||
-rwxr-xr-x | tinyNET/src/turn/tnet_turn_session.h | 47 |
8 files changed, 1842 insertions, 1837 deletions
diff --git a/tinyNET/src/turn/tnet_turn.c b/tinyNET/src/turn/tnet_turn.c index 0f38d02..fc37d68 100755 --- a/tinyNET/src/turn/tnet_turn.c +++ b/tinyNET/src/turn/tnet_turn.c @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* @@ -97,7 +97,7 @@ // request->nonce = tsk_strdup(allocation->nonce); // // /* Create random transaction id */ -// { +// { // tsk_istr_t random; // tsk_md5digest_t digest; // @@ -176,8 +176,8 @@ // tnet_turn_attribute_t *attribute; // tnet_turn_channel_binding_id_t number; // uint32_t lifetime; -// -// +// +// // channel_binding = va_arg(*app, const tnet_turn_channel_binding_t *); // number = tnet_htons(channel_binding->id); // lifetime = tnet_htonl(channel_binding->timeout); @@ -216,7 +216,7 @@ // tnet_turn_attribute_xpeer_addr_t* xpeer = tsk_object_ref(va_arg(*app, tnet_turn_attribute_xpeer_addr_t *)); // const void* data = va_arg(*app, const void *); // tsk_size_t size = va_arg(*app, tsk_size_t); -// +// // /* // draft-ietf-behave-turn-16 - 10.1. Forming a Send Indication // @@ -255,7 +255,7 @@ // attribute->xaddress[1] = 0xA1; // attribute->xaddress[2] = 0x83; // attribute->xaddress[3] = 0x47; -// +// // tnet_stun_message_add_attribute(request, (tnet_stun_attr_t**)&attribute); // // /*if((attribute = tnet_turn_attribute_even_port_create(context->enable_evenport))) @@ -293,7 +293,7 @@ // { /* First time we get a nonce */ // tsk_strupdate(&allocation->nonce, nonce); // tsk_strupdate(&allocation->realm, realm); -// +// // /* Delete the message and response before retrying*/ // TSK_OBJECT_SAFE_FREE(response); // TSK_OBJECT_SAFE_FREE(request); @@ -347,7 +347,7 @@ // TSK_OBJECT_SAFE_FREE(response); // } // } -// +// // TSK_OBJECT_SAFE_FREE(request); // return ret; //} @@ -357,12 +357,12 @@ //tnet_turn_allocation_id_t tnet_turn_allocate(const tnet_nat_context_t* nat_context, const tnet_fd_t localFD, tnet_socket_type_t socket_type) //{ // tnet_turn_allocation_id_t id = TNET_TURN_INVALID_ALLOCATION_ID; -// +// // if(nat_context){ // int ret; // tnet_turn_allocation_t* allocation = tnet_turn_allocation_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password); // allocation->software = tsk_strdup(nat_context->software); -// +// // if((ret = tnet_turn_send_request(nat_context, allocation, tnet_turn_create_request_allocate))){ // TSK_DEBUG_ERROR("TURN allocation failed with error code:%d.", ret); // TSK_OBJECT_SAFE_FREE(allocation); @@ -422,9 +422,9 @@ // // if(nat_context && allocation){ // int ret; -// +// // channel_binding = tnet_turn_channel_binding_create(allocation); -// +// // if(channel_binding){ // if(((struct sockaddr*)peer)->sa_family == AF_INET){ // struct sockaddr_in *sin = ((struct sockaddr_in*)peer); @@ -433,7 +433,7 @@ // channel_binding->xpeer = tnet_turn_attribute_xpeer_addr_create_null(); // channel_binding->xpeer->family = stun_ipv4; // channel_binding->xpeer->xport = ((sin->sin_port) ^ tnet_htons(0x2112)); -// +// // _sin_addr = tnet_htonl_2(&sin->sin_addr) ^tnet_htonl(kStunMagicCookieLong); // memcpy(channel_binding->xpeer->xaddress, &_sin_addr, sizeof(_sin_addr)); // } @@ -453,7 +453,7 @@ // if((ret = tnet_turn_send_request(nat_context, allocation, tnet_turn_create_request_channel_bind, channel_binding))){ // TSK_DEBUG_ERROR("TURN (CHANNEL-BIND) failed with error code:%d.", ret); // TSK_OBJECT_SAFE_FREE(channel_binding); -// +// // goto bail; // } // else{ @@ -566,8 +566,8 @@ //{ // tnet_turn_channel_binding_t *channel_binding = self; // if(channel_binding){ -// static tnet_turn_channel_binding_id_t __allocation_unique_id = 0x4000; /* 0x4000 through 0x7FFF */ -// +// static tnet_turn_channel_binding_id_t __allocation_unique_id = 0x4000; /* 0x4000 through 0x7FFF */ +// // channel_binding->id = __allocation_unique_id++; // channel_binding->allocation = va_arg(*app, const tnet_turn_allocation_t *); // channel_binding->timeout = TNET_TURN_CHANBIND_TIMEOUT_DEFAULT; /* 10 minutes as per draft-ietf-behave-turn-16 subclause 11 */ @@ -580,21 +580,21 @@ //} // //static tsk_object_t* tnet_turn_channel_binding_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_channel_binding_t *channel_binding = self; // if(channel_binding){ // TSK_OBJECT_SAFE_FREE(channel_binding->xpeer); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_channel_binding_def_s = +//static const tsk_object_def_t tnet_turn_channel_binding_def_s = //{ // sizeof(tnet_turn_channel_binding_t), -// tnet_turn_channel_binding_ctor, +// tnet_turn_channel_binding_ctor, // tnet_turn_channel_binding_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_channel_binding_def_t = &tnet_turn_channel_binding_def_s; // @@ -611,21 +611,21 @@ //} // //static tsk_object_t* tnet_turn_permission_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_permission_t *permission = self; // if(permission){ // TSK_OBJECT_SAFE_FREE(permission->xpeer); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_permission_def_s = +//static const tsk_object_def_t tnet_turn_permission_def_s = //{ // sizeof(tnet_turn_permission_t), -// tnet_turn_permission_ctor, +// tnet_turn_permission_ctor, // tnet_turn_permission_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_permission_def_t = &tnet_turn_permission_def_s; // @@ -639,7 +639,7 @@ // tnet_turn_allocation_t *allocation = self; // if(allocation){ // static tnet_turn_allocation_id_t __allocation_unique_id = 0; -// +// // const char* server_address; // tnet_port_t server_port; // @@ -647,7 +647,7 @@ // // allocation->localFD = va_arg(*app, tnet_fd_t); // allocation->socket_type = va_arg(*app, tnet_socket_type_t); -// +// // server_address = va_arg(*app, const char*); //#if defined(__GNUC__) // server_port = (tnet_port_t)va_arg(*app, unsigned); @@ -668,7 +668,7 @@ //} // //static tsk_object_t* tnet_turn_allocation_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_allocation_t *allocation = self; // if(allocation){ // TSK_FREE(allocation->relay_address); @@ -679,23 +679,23 @@ // TSK_FREE(allocation->nonce); // // TSK_FREE(allocation->software); -// +// // TSK_OBJECT_SAFE_FREE(allocation->xmaddr); // TSK_OBJECT_SAFE_FREE(allocation->maddr); // // TSK_OBJECT_SAFE_FREE(allocation->channel_bindings); // TSK_OBJECT_SAFE_FREE(allocation->permissions); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_allocation_def_s = +//static const tsk_object_def_t tnet_turn_allocation_def_s = //{ // sizeof(tnet_turn_allocation_t), -// tnet_turn_allocation_ctor, +// tnet_turn_allocation_ctor, // tnet_turn_allocation_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_allocation_def_t = &tnet_turn_allocation_def_s; // diff --git a/tinyNET/src/turn/tnet_turn.h b/tinyNET/src/turn/tnet_turn.h index af3a5e4..f1c050e 100755 --- a/tinyNET/src/turn/tnet_turn.h +++ b/tinyNET/src/turn/tnet_turn.h @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* @@ -113,15 +113,15 @@ //typedef struct tnet_turn_allocation_s //{ // TSK_DECLARE_OBJECT; -// +// // tnet_turn_allocation_id_t id; /**< Unique id. */ -// +// // char* relay_address; /**< the relayed transport address */ // //! Server reflexive address of the local socket(STUN1 as per RFC 3489). // tnet_stun_attribute_mapped_addr_t *maddr; // //! XORed server reflexive address (STUN2 as per RFC 5389). // tnet_stun_attribute_xmapped_addr_t *xmaddr; -// +// // /* 5-tuple */ // tnet_fd_t localFD; // tnet_socket_type_t socket_type; diff --git a/tinyNET/src/turn/tnet_turn_attribute.c b/tinyNET/src/turn/tnet_turn_attribute.c index 719f926..5dc3ee3 100755 --- a/tinyNET/src/turn/tnet_turn_attribute.c +++ b/tinyNET/src/turn/tnet_turn_attribute.c @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* @@ -116,7 +116,7 @@ // // /* Attribute Value // */ -// +// // switch(type) // { // /* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER */ @@ -176,7 +176,7 @@ // TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); // break; // } -// +// // /* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN */ // case stun_reservation_token: // { @@ -296,7 +296,7 @@ // TSK_DEBUG_ERROR("SERIALIZE:TOKEN ==> NOT IMPLEMENTED"); // return -3; // } -// +// // default: break; // } // @@ -324,8 +324,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_channelnum_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_channelnum_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_channelnum_t *attribute = self; // if(attribute){ // } @@ -357,8 +357,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_lifetime_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_lifetime_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_lifetime_t *attribute = self; // if(attribute){ // } @@ -386,7 +386,7 @@ // if(attribute){ // const void *payload = va_arg(*app, const void*); // tsk_size_t payload_size = va_arg(*app, tsk_size_t); -// +// // if(payload && payload_size){ // } // TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_peer_address; @@ -395,8 +395,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_xpeer_addr_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_xpeer_addr_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_xpeer_addr_t *attribute = self; // if(attribute){ // } @@ -432,8 +432,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_data_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_data_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_data_t *attribute = self; // if(attribute){ // TSK_OBJECT_SAFE_FREE(attribute->value); @@ -466,7 +466,7 @@ // // TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_relayed_address; // TNET_STUN_ATTRIBUTE(attribute)->length = payload_size; -// +// // attribute->family = (tnet_stun_addr_family_t)(*(payloadPtr++)); // // attribute->xport = tnet_ntohs_2(payloadPtr); @@ -475,7 +475,7 @@ // // { /*=== Compute IP address */ // tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0); -// if(addr_size){ +// if(addr_size){ // tsk_size_t i; // uint32_t addr; // @@ -489,14 +489,14 @@ // else{ // TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family); // } -// } +// } // } // } // return self; //} // -//static tsk_object_t* tnet_turn_attribute_xrelayed_addr_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_xrelayed_addr_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_xrelayed_addr_t *attribute = self; // if(attribute){ // } @@ -528,8 +528,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_even_port_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_even_port_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_even_port_t *attribute = self; // if(attribute){ // } @@ -561,8 +561,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_reqtrans_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_reqtrans_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_reqtrans_t *attribute = self; // if(attribute){ // } @@ -594,8 +594,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_dontfrag_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_dontfrag_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_dontfrag_t *attribute = self; // if(attribute){ // } @@ -628,8 +628,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_restoken_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_restoken_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_restoken_t *attribute = self; // if(attribute){ // } diff --git a/tinyNET/src/turn/tnet_turn_attribute.h b/tinyNET/src/turn/tnet_turn_attribute.h index 127116c..998379e 100755 --- a/tinyNET/src/turn/tnet_turn_attribute.h +++ b/tinyNET/src/turn/tnet_turn_attribute.h @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* @@ -117,7 +117,7 @@ //typedef struct tnet_turn_attribute_even_port_s //{ // TNET_STUN_DECLARE_ATTRIBUTE; -// +// ///* // 0 1 2 3 4 5 6 7 // +-+-+-+-+-+-+-+-+ @@ -136,7 +136,7 @@ //typedef struct tnet_turn_attribute_reqtrans_s //{ // TNET_STUN_DECLARE_ATTRIBUTE; -///* +///* // draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 diff --git a/tinyNET/src/turn/tnet_turn_message.c b/tinyNET/src/turn/tnet_turn_message.c index 989fd2b..b0eff46 100755 --- a/tinyNET/src/turn/tnet_turn_message.c +++ b/tinyNET/src/turn/tnet_turn_message.c @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* @@ -144,20 +144,20 @@ //} // //static tsk_object_t* tnet_turn_channel_data_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_channel_data_t *message = self; // if(message){ // TSK_FREE(message->data); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_channel_data_def_s = +//static const tsk_object_def_t tnet_turn_channel_data_def_s = //{ // sizeof(tnet_turn_channel_data_t), -// tnet_turn_channel_data_ctor, +// tnet_turn_channel_data_ctor, // tnet_turn_channel_data_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_channel_data_def_t = &tnet_turn_channel_data_def_s; diff --git a/tinyNET/src/turn/tnet_turn_message.h b/tinyNET/src/turn/tnet_turn_message.h index c518366..c98d4f0 100755 --- a/tinyNET/src/turn/tnet_turn_message.h +++ b/tinyNET/src/turn/tnet_turn_message.h @@ -2,19 +2,19 @@ //* Copyright (C) 2010-2011 Mamadou Diop. //* //* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]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. //* diff --git a/tinyNET/src/turn/tnet_turn_session.c b/tinyNET/src/turn/tnet_turn_session.c index e131dbc..801f01a 100755 --- a/tinyNET/src/turn/tnet_turn_session.c +++ b/tinyNET/src/turn/tnet_turn_session.c @@ -45,143 +45,141 @@ typedef tnet_stun_pkt_t tnet_turn_pkt_t; -typedef struct tnet_turn_peer_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_turn_peer_s { + TSK_DECLARE_OBJECT; - tnet_turn_peer_id_t id; + tnet_turn_peer_id_t id; - uint16_t u_chan_num; - uint32_t u_conn_id; // rfc6062 - 6.2.1. CONNECTION-ID, For streams only - tnet_fd_t conn_fd; // Connected FD: used for Streams only + uint16_t u_chan_num; + uint32_t u_conn_id; // rfc6062 - 6.2.1. CONNECTION-ID, For streams only + tnet_fd_t conn_fd; // Connected FD: used for Streams only - tnet_stun_addr_t addr_ip; - char* p_addr_ip; - uint16_t u_addr_port; - tsk_bool_t b_ipv6; - tsk_bool_t b_stream_connected; - tsk_buffer_t *p_stream_buff_in; + tnet_stun_addr_t addr_ip; + char* p_addr_ip; + uint16_t u_addr_port; + tsk_bool_t b_ipv6; + tsk_bool_t b_stream_connected; + tsk_buffer_t *p_stream_buff_in; tsk_buffer_t *p_stream_buff_out; - - tnet_stun_state_t e_createperm_state; - tnet_stun_state_t e_chanbind_state; - tnet_stun_state_t e_connect_state; - tnet_stun_state_t e_connbind_state; - - tnet_turn_pkt_t* p_pkt_createperm; - tnet_stun_pkt_t* p_pkt_sendind; - tnet_stun_pkt_t* p_pkt_chanbind; - tnet_stun_pkt_t* p_pkt_connect; // For streams only - tnet_stun_pkt_t* p_pkt_connbind; // For streams only - - struct { - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } createperm; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } chanbind; - } fresh; // schedule refresh - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } createperm; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } chanbind; - } rtt; // retransmit (UDP only, to deal with pkt loss) - } timer; + + tnet_stun_state_t e_createperm_state; + tnet_stun_state_t e_chanbind_state; + tnet_stun_state_t e_connect_state; + tnet_stun_state_t e_connbind_state; + + tnet_turn_pkt_t* p_pkt_createperm; + tnet_stun_pkt_t* p_pkt_sendind; + tnet_stun_pkt_t* p_pkt_chanbind; + tnet_stun_pkt_t* p_pkt_connect; // For streams only + tnet_stun_pkt_t* p_pkt_connbind; // For streams only + + struct { + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } createperm; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } chanbind; + } fresh; // schedule refresh + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } createperm; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } chanbind; + } rtt; // retransmit (UDP only, to deal with pkt loss) + } timer; } tnet_turn_peer_t; typedef tsk_list_t tnet_turn_peers_L_t; -typedef struct tnet_turn_session_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_turn_session_s { + TSK_DECLARE_OBJECT; + + tsk_bool_t b_prepared; + tsk_bool_t b_started; + tsk_bool_t b_stopping; + enum tnet_stun_state_e e_alloc_state; + enum tnet_stun_state_e e_refresh_state; - tsk_bool_t b_prepared; - tsk_bool_t b_started; - tsk_bool_t b_stopping; - enum tnet_stun_state_e e_alloc_state; - enum tnet_stun_state_e e_refresh_state; - - enum tnet_turn_transport_e e_req_transport; + enum tnet_turn_transport_e e_req_transport; - uint32_t u_lifetime_alloc_in_sec; + uint32_t u_lifetime_alloc_in_sec; - tnet_turn_pkt_t* p_pkt_alloc; - tnet_stun_pkt_t* p_pkt_refresh; + tnet_turn_pkt_t* p_pkt_alloc; + tnet_stun_pkt_t* p_pkt_refresh; - void* p_buff_send_ptr; - tsk_size_t u_buff_send_size; + void* p_buff_send_ptr; + tsk_size_t u_buff_send_size; - void* p_buff_chandata_ptr; - tsk_size_t u_buff_chandata_size; + void* p_buff_chandata_ptr; + tsk_size_t u_buff_chandata_size; - char* p_rel_ip; - uint16_t u_rel_port; - tsk_bool_t b_rel_ipv6; + char* p_rel_ip; + uint16_t u_rel_port; + tsk_bool_t b_rel_ipv6; + + char* p_srflx_ip; + uint16_t u_srflx_port; + tsk_bool_t b_srflx_ipv6; - char* p_srflx_ip; - uint16_t u_srflx_port; - tsk_bool_t b_srflx_ipv6; - struct { tsk_bool_t auto_detect; struct tnet_proxyinfo_s* info; } proxy; - struct { - char* path_priv; - char* path_pub; - char* path_ca; - tsk_bool_t verify; - } ssl; - - struct { - char* p_usr_name; - char* p_pwd; - } cred; - - struct { - tnet_turn_session_callback_f f_fun; - struct tnet_turn_session_event_xs e; - } cb; - - struct { - tsk_timer_manager_handle_t *p_mgr; - tsk_timer_id_t u_timer_id_refresh; // To refresh Alloc (Send Refresh Indication) - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } alloc; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } refresh; - } rtt; // retransmit (UDP only) - } timer; - - tnet_socket_t* p_lcl_sock; - char* p_srv_host; - uint16_t u_srv_port; - tsk_bool_t b_stream_connected; + struct { + char* path_priv; + char* path_pub; + char* path_ca; + tsk_bool_t verify; + } ssl; + + struct { + char* p_usr_name; + char* p_pwd; + } cred; + + struct { + tnet_turn_session_callback_f f_fun; + struct tnet_turn_session_event_xs e; + } cb; + + struct { + tsk_timer_manager_handle_t *p_mgr; + tsk_timer_id_t u_timer_id_refresh; // To refresh Alloc (Send Refresh Indication) + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } alloc; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } refresh; + } rtt; // retransmit (UDP only) + } timer; + + tnet_socket_t* p_lcl_sock; + char* p_srv_host; + uint16_t u_srv_port; + tsk_bool_t b_stream_connected; tsk_buffer_t* p_stream_buff_out; // data pending until the socket is connected - tsk_bool_t b_stream_error; // Unrecoverable error occured - tsk_buffer_t *p_stream_buff_in; - struct sockaddr_storage srv_addr; - struct tnet_transport_s* p_transport; + tsk_bool_t b_stream_error; // Unrecoverable error occured + tsk_buffer_t *p_stream_buff_in; + struct sockaddr_storage srv_addr; + struct tnet_transport_s* p_transport; - tnet_turn_peers_L_t* p_list_peers; + tnet_turn_peers_L_t* p_list_peers; - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } tnet_turn_session_t; @@ -207,87 +205,99 @@ static int _tnet_turn_peer_create(const char* pc_peer_ip, uint16_t u_peer_port, static int _tnet_turn_peer_find_by_xpeer(const tnet_turn_peers_L_t* pc_peers, const tnet_stun_attr_address_t* pc_xpeer, const tnet_turn_peer_t **ppc_peer); /*** PREDICATES ***/ -static int __pred_find_peer_by_id(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->id - *((const tnet_turn_peer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_id(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->id - *((const tnet_turn_peer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_fd(const tsk_list_item_t *item, const void *fd) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->conn_fd - *((const tnet_fd_t*)fd)); - } - return -1; +static int __pred_find_peer_by_fd(const tsk_list_item_t *item, const void *fd) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->conn_fd - *((const tnet_fd_t*)fd)); + } + return -1; } -static int __pred_find_peer_by_channum(const tsk_list_item_t *item, const void *pu_chan_num) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->u_chan_num - *((const uint16_t*)pu_chan_num)); - } - return -1; +static int __pred_find_peer_by_channum(const tsk_list_item_t *item, const void *pu_chan_num) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->u_chan_num - *((const uint16_t*)pu_chan_num)); + } + return -1; } -static int __pred_find_peer_by_timer_rtt_createperm(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.createperm.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_rtt_createperm(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.createperm.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_timer_fresh_createperm(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.createperm.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_fresh_createperm(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.createperm.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_transacid_createperm(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_createperm(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_timer_rtt_chanbind(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.chanbind.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_rtt_chanbind(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.chanbind.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_timer_fresh_chanbind(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.chanbind.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_fresh_chanbind(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.chanbind.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_transacid_chanbind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_chanbind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_connect(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_connect(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_connectionbind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_connectionbind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } #define _tnet_turn_session_raise_event0(_p_self, _e_type, _u_peer_id) \ @@ -321,117 +331,117 @@ static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, co int tnet_turn_session_create(struct tnet_socket_s* p_lcl_sock, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, struct tnet_turn_session_s** pp_self) { - int ret; - extern const tsk_object_def_t *tnet_turn_session_def_t; - tnet_turn_session_t* p_self; - if (!p_lcl_sock || !TNET_SOCKET_IS_VALID(p_lcl_sock) || !pc_srv_host || !u_srv_port || !pp_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!(p_self = tsk_object_new(tnet_turn_session_def_t))) { - TSK_DEBUG_ERROR("Failed to create 'tnet_turn_session_def_t' object"); - return -2; - } - if (!(p_self->p_list_peers = tsk_list_create())) { - TSK_DEBUG_ERROR("Failed to create list"); - ret = -3; - goto bail; - } - if (TNET_SOCKET_TYPE_IS_STREAM(p_lcl_sock->type) && !(p_self->p_stream_buff_in = tsk_buffer_create_null())) { - TSK_DEBUG_ERROR("Failed to stream buffer"); - ret = -4; - goto bail; - } - if ((ret = tnet_sockaddr_init(pc_srv_host, u_srv_port, p_lcl_sock->type, &p_self->srv_addr))) { - TSK_DEBUG_ERROR("Invalid TURN SRV address [%s:%u]", pc_srv_host, u_srv_port); - goto bail; - } - tsk_strupdate(&p_self->p_srv_host, pc_srv_host); - p_self->u_srv_port = u_srv_port; - p_self->p_lcl_sock = tsk_object_ref(p_lcl_sock); - p_self->e_req_transport = e_req_transport; - p_self->cb.e.pc_session = p_self; - *pp_self = p_self; + int ret; + extern const tsk_object_def_t *tnet_turn_session_def_t; + tnet_turn_session_t* p_self; + if (!p_lcl_sock || !TNET_SOCKET_IS_VALID(p_lcl_sock) || !pc_srv_host || !u_srv_port || !pp_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!(p_self = tsk_object_new(tnet_turn_session_def_t))) { + TSK_DEBUG_ERROR("Failed to create 'tnet_turn_session_def_t' object"); + return -2; + } + if (!(p_self->p_list_peers = tsk_list_create())) { + TSK_DEBUG_ERROR("Failed to create list"); + ret = -3; + goto bail; + } + if (TNET_SOCKET_TYPE_IS_STREAM(p_lcl_sock->type) && !(p_self->p_stream_buff_in = tsk_buffer_create_null())) { + TSK_DEBUG_ERROR("Failed to stream buffer"); + ret = -4; + goto bail; + } + if ((ret = tnet_sockaddr_init(pc_srv_host, u_srv_port, p_lcl_sock->type, &p_self->srv_addr))) { + TSK_DEBUG_ERROR("Invalid TURN SRV address [%s:%u]", pc_srv_host, u_srv_port); + goto bail; + } + tsk_strupdate(&p_self->p_srv_host, pc_srv_host); + p_self->u_srv_port = u_srv_port; + p_self->p_lcl_sock = tsk_object_ref(p_lcl_sock); + p_self->e_req_transport = e_req_transport; + p_self->cb.e.pc_session = p_self; + *pp_self = p_self; bail: - if (ret) { - TSK_OBJECT_SAFE_FREE(p_self); - } - return ret; + if (ret) { + TSK_OBJECT_SAFE_FREE(p_self); + } + return ret; } int tnet_turn_session_create_2(const char* pc_lcl_ip, uint16_t u_lcl_port, enum tnet_socket_type_e e_lcl_type, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, struct tnet_turn_session_s** pp_self) { - tnet_socket_t* p_lcl_sock; - int ret; - if (!pc_srv_host || !u_srv_port || !pp_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!(p_lcl_sock = tnet_socket_create(pc_lcl_ip, u_lcl_port, e_lcl_type))) { - TSK_DEBUG_ERROR("Failed to create socket(%s:%u$%d)", pc_lcl_ip, u_lcl_port, e_lcl_type); - return -2; - } - ret = tnet_turn_session_create(p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); - TSK_OBJECT_SAFE_FREE(p_lcl_sock); - return ret; + tnet_socket_t* p_lcl_sock; + int ret; + if (!pc_srv_host || !u_srv_port || !pp_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!(p_lcl_sock = tnet_socket_create(pc_lcl_ip, u_lcl_port, e_lcl_type))) { + TSK_DEBUG_ERROR("Failed to create socket(%s:%u$%d)", pc_lcl_ip, u_lcl_port, e_lcl_type); + return -2; + } + ret = tnet_turn_session_create(p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); + TSK_OBJECT_SAFE_FREE(p_lcl_sock); + return ret; } int tnet_turn_session_create_4(struct tnet_socket_s* p_lcl_sock, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, enum tnet_socket_type_e e_srv_type, struct tnet_turn_session_s** pp_self) { - struct tnet_socket_s* _p_lcl_sock; - int ret; + struct tnet_socket_s* _p_lcl_sock; + int ret; - if (TNET_SOCKET_TYPE_IS_STREAM(e_srv_type)) { - // For stream the socket will be connected to the server and this is why we need to create a new socket - if (!(_p_lcl_sock = tnet_socket_create(p_lcl_sock->ip, TNET_SOCKET_PORT_ANY/*p_lcl_sock->port*/, e_srv_type))) { - return -2; - } - } - else { - // For UDP, use the socket socket - _p_lcl_sock = tsk_object_ref(p_lcl_sock); - } - ret = tnet_turn_session_create(_p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); - TSK_OBJECT_SAFE_FREE(_p_lcl_sock); - return ret; + if (TNET_SOCKET_TYPE_IS_STREAM(e_srv_type)) { + // For stream the socket will be connected to the server and this is why we need to create a new socket + if (!(_p_lcl_sock = tnet_socket_create(p_lcl_sock->ip, TNET_SOCKET_PORT_ANY/*p_lcl_sock->port*/, e_srv_type))) { + return -2; + } + } + else { + // For UDP, use the socket socket + _p_lcl_sock = tsk_object_ref(p_lcl_sock); + } + ret = tnet_turn_session_create(_p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); + TSK_OBJECT_SAFE_FREE(_p_lcl_sock); + return ret; } int tnet_turn_session_set_cred(tnet_turn_session_t* p_self, const char* pc_usr_name, const char* pc_pwd) { - if (!p_self || !pc_usr_name || !pc_pwd) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_strupdate(&p_self->cred.p_usr_name, pc_usr_name); - tsk_strupdate(&p_self->cred.p_pwd, pc_pwd); + if (!p_self || !pc_usr_name || !pc_pwd) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_strupdate(&p_self->cred.p_usr_name, pc_usr_name); + tsk_strupdate(&p_self->cred.p_pwd, pc_pwd); - return 0; + return 0; } int tnet_turn_session_set_callback(struct tnet_turn_session_s* p_self, tnet_turn_session_callback_f f_fun, const void* pc_usr_data) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - p_self->cb.f_fun = f_fun; - p_self->cb.e.pc_usr_data = pc_usr_data; - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + p_self->cb.f_fun = f_fun; + p_self->cb.e.pc_usr_data = pc_usr_data; + return 0; } int tnet_turn_session_set_ssl_certs(struct tnet_turn_session_s* p_self, const char* path_priv, const char* path_pub, const char* path_ca, tsk_bool_t verify) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - tsk_strupdate(&p_self->ssl.path_priv, path_priv); - tsk_strupdate(&p_self->ssl.path_pub, path_pub); - tsk_strupdate(&p_self->ssl.path_ca, path_ca); - p_self->ssl.verify = verify; - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + tsk_strupdate(&p_self->ssl.path_priv, path_priv); + tsk_strupdate(&p_self->ssl.path_pub, path_pub); + tsk_strupdate(&p_self->ssl.path_ca, path_ca); + p_self->ssl.verify = verify; + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_set_proxy_auto_detect(struct tnet_turn_session_s* p_self, tsk_bool_t auto_detect) @@ -461,99 +471,99 @@ int tnet_turn_session_set_proxy_info(struct tnet_turn_session_s* p_self, struct int tnet_turn_session_prepare(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (p_self->b_prepared) { - goto bail; - } + if (p_self->b_prepared) { + goto bail; + } - p_self->e_alloc_state = tnet_stun_state_none; - p_self->e_refresh_state = tnet_stun_state_none; + p_self->e_alloc_state = tnet_stun_state_none; + p_self->e_refresh_state = tnet_stun_state_none; - p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; - p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; + p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; + p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; - p_self->timer.u_timer_id_refresh = TSK_INVALID_TIMER_ID; - p_self->u_lifetime_alloc_in_sec = kTurnAllocationTimeOutInSec; + p_self->timer.u_timer_id_refresh = TSK_INVALID_TIMER_ID; + p_self->u_lifetime_alloc_in_sec = kTurnAllocationTimeOutInSec; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); - // create timer manager - if (!p_self->timer.p_mgr && !(p_self->timer.p_mgr = tsk_timer_manager_create())) { - TSK_DEBUG_ERROR("Failed to create timer manager"); + // create timer manager + if (!p_self->timer.p_mgr && !(p_self->timer.p_mgr = tsk_timer_manager_create())) { + TSK_DEBUG_ERROR("Failed to create timer manager"); ret = -4; - goto bail; - } + goto bail; + } - // create transport + // create transport if (!p_self->p_transport) { - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - // Use the DGram socket as master - p_self->p_transport = tnet_transport_create_2(p_self->p_lcl_sock, kTurnTransportFriendlyName); - } - else { - // Use the Stream socket later and connect it - p_self->p_transport = tnet_transport_create(p_self->p_lcl_sock->ip, TNET_SOCKET_PORT_ANY, p_self->p_lcl_sock->type, kTurnTransportFriendlyName); - } - if (!p_self->p_transport) { - TSK_DEBUG_ERROR("Failed to create %s Transport", kTurnTransportFriendlyName); - ret = -5; - goto bail; - } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + // Use the DGram socket as master + p_self->p_transport = tnet_transport_create_2(p_self->p_lcl_sock, kTurnTransportFriendlyName); + } + else { + // Use the Stream socket later and connect it + p_self->p_transport = tnet_transport_create(p_self->p_lcl_sock->ip, TNET_SOCKET_PORT_ANY, p_self->p_lcl_sock->type, kTurnTransportFriendlyName); + } + if (!p_self->p_transport) { + TSK_DEBUG_ERROR("Failed to create %s Transport", kTurnTransportFriendlyName); + ret = -5; + goto bail; + } } // set transport callback - if ((ret = tnet_transport_set_callback(p_self->p_transport, TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type) ? _tnet_turn_session_transport_layer_dgram_cb : _tnet_turn_session_transport_layer_stream_cb, p_self))) { + if ((ret = tnet_transport_set_callback(p_self->p_transport, TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type) ? _tnet_turn_session_transport_layer_dgram_cb : _tnet_turn_session_transport_layer_stream_cb, p_self))) { goto bail; - } + } - p_self->b_prepared = tsk_true; + p_self->b_prepared = tsk_true; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_start(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (p_self->b_started) { - goto bail; - } - if (!p_self->b_prepared) { - TSK_DEBUG_ERROR("TURN session not prepared yet"); - ret = -2; - goto bail; - } + if (p_self->b_started) { + goto bail; + } + if (!p_self->b_prepared) { + TSK_DEBUG_ERROR("TURN session not prepared yet"); + ret = -2; + goto bail; + } - // start timer manager - if ((ret = tsk_timer_manager_start(p_self->timer.p_mgr))) { - TSK_DEBUG_ERROR("Failed to start TURN timer manager"); - goto bail; - } + // start timer manager + if ((ret = tsk_timer_manager_start(p_self->timer.p_mgr))) { + TSK_DEBUG_ERROR("Failed to start TURN timer manager"); + goto bail; + } + + // set SSL certificates + if (TNET_SOCKET_TYPE_IS_TLS(p_self->p_lcl_sock->type) || TNET_SOCKET_TYPE_IS_WSS(p_self->p_lcl_sock->type)) { + if ((ret = tnet_transport_tls_set_certs(p_self->p_transport, p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv, p_self->ssl.verify))) { + TSK_DEBUG_ERROR("Failed to set SSL certificates: '%s', '%s', '%s'", p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv); + goto bail; + } + } - // set SSL certificates - if (TNET_SOCKET_TYPE_IS_TLS(p_self->p_lcl_sock->type) || TNET_SOCKET_TYPE_IS_WSS(p_self->p_lcl_sock->type)) { - if ((ret = tnet_transport_tls_set_certs(p_self->p_transport, p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv, p_self->ssl.verify))) { - TSK_DEBUG_ERROR("Failed to set SSL certificates: '%s', '%s', '%s'", p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv); - goto bail; - } - } - // Proxy info if ((ret = tnet_transport_set_proxy_auto_detect(p_self->p_transport, p_self->proxy.auto_detect))) { TSK_DEBUG_ERROR("Failed to set proxy autodetect option"); @@ -566,218 +576,218 @@ int tnet_turn_session_start(tnet_turn_session_t* p_self) } } - // start network transport - if ((ret = tnet_transport_start(p_self->p_transport))) { - TSK_DEBUG_ERROR("Failed to start TURN transport"); - goto bail; - } - - // Connect to the server - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { - tnet_fd_t fd; - p_self->b_stream_connected = tsk_false; - p_self->b_stream_error = tsk_false; - fd = tnet_transport_connectto_3(p_self->p_transport, p_self->p_lcl_sock, p_self->p_srv_host, p_self->u_srv_port, p_self->p_lcl_sock->type); - if (fd != p_self->p_lcl_sock->fd) { - TSK_DEBUG_ERROR("Failed to connect to TURN server(%s:%d)", p_self->p_srv_host, p_self->u_srv_port); - ret = -3; - goto bail; - } - TSK_DEBUG_INFO("TURN server connection fd = %d", p_self->p_lcl_sock->fd); - } + // start network transport + if ((ret = tnet_transport_start(p_self->p_transport))) { + TSK_DEBUG_ERROR("Failed to start TURN transport"); + goto bail; + } + + // Connect to the server + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { + tnet_fd_t fd; + p_self->b_stream_connected = tsk_false; + p_self->b_stream_error = tsk_false; + fd = tnet_transport_connectto_3(p_self->p_transport, p_self->p_lcl_sock, p_self->p_srv_host, p_self->u_srv_port, p_self->p_lcl_sock->type); + if (fd != p_self->p_lcl_sock->fd) { + TSK_DEBUG_ERROR("Failed to connect to TURN server(%s:%d)", p_self->p_srv_host, p_self->u_srv_port); + ret = -3; + goto bail; + } + TSK_DEBUG_INFO("TURN server connection fd = %d", p_self->p_lcl_sock->fd); + } - p_self->b_started = tsk_true; + p_self->b_started = tsk_true; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_allocate(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } - // create Allocate Request - p_self->e_alloc_state = tnet_stun_state_none; - p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_allocate_request, &p_self->p_pkt_alloc))) { - TSK_DEBUG_ERROR("Failed to create TURN Allocate request"); - goto bail; - } - // add attributes - p_self->p_pkt_alloc->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_alloc, - TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), - TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(p_self->e_req_transport), - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_alloc))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_self->timer.rtt.alloc.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.alloc.id, p_self->timer.rtt.alloc.u_timeout); - } - p_self->e_alloc_state = tnet_stun_state_trying; + // create Allocate Request + p_self->e_alloc_state = tnet_stun_state_none; + p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_allocate_request, &p_self->p_pkt_alloc))) { + TSK_DEBUG_ERROR("Failed to create TURN Allocate request"); + goto bail; + } + // add attributes + p_self->p_pkt_alloc->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_alloc, + TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), + TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(p_self->e_req_transport), + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_alloc))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_self->timer.rtt.alloc.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.alloc.id, p_self->timer.rtt.alloc.u_timeout); + } + p_self->e_alloc_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_relayed_addr(const struct tnet_turn_session_s* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6) { - int ret = 0; + int ret = 0; - if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - tsk_strupdate(pp_ip, p_self->p_rel_ip); - *pu_port = p_self->u_rel_port; - *pb_ipv6 = p_self->b_rel_ipv6; + tsk_strupdate(pp_ip, p_self->p_rel_ip); + *pu_port = p_self->u_rel_port; + *pb_ipv6 = p_self->b_rel_ipv6; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_srflx_addr(const tnet_turn_session_t* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6) { - int ret = 0; + int ret = 0; - if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - tsk_strupdate(pp_ip, p_self->p_srflx_ip); - *pu_port = p_self->u_srflx_port; - *pb_ipv6 = p_self->b_srflx_ipv6; + tsk_strupdate(pp_ip, p_self->p_srflx_ip); + *pu_port = p_self->u_srflx_port; + *pb_ipv6 = p_self->b_srflx_ipv6; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_state_alloc(const struct tnet_turn_session_s* pc_self, enum tnet_stun_state_e *pe_state) { - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *pe_state = pc_self->e_alloc_state; - return 0; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *pe_state = pc_self->e_alloc_state; + return 0; } int tnet_turn_session_get_socket_local(struct tnet_turn_session_s* p_self, struct tnet_socket_s** pp_lcl_sock) { - if (!p_self || !pp_lcl_sock) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - *pp_lcl_sock = (struct tnet_socket_s*)tsk_object_ref(p_self->p_lcl_sock); - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self || !pp_lcl_sock) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + *pp_lcl_sock = (struct tnet_socket_s*)tsk_object_ref(p_self->p_lcl_sock); + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_get_state_createperm(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, enum tnet_stun_state_e *pe_state) { - const tnet_turn_peer_t *pc_peer; - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pe_state = pc_peer->e_createperm_state; - } - else { - *pe_state = tnet_stun_state_none; - if (u_peer_id != kTurnPeerIdInvalid) { - TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); - } - } - tsk_safeobj_unlock(pc_self); - return 0; + const tnet_turn_peer_t *pc_peer; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pe_state = pc_peer->e_createperm_state; + } + else { + *pe_state = tnet_stun_state_none; + if (u_peer_id != kTurnPeerIdInvalid) { + TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_state_connbind(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, enum tnet_stun_state_e *pe_state) { - const tnet_turn_peer_t *pc_peer; - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pe_state = pc_peer->e_connbind_state; - } - else { - *pe_state = tnet_stun_state_none; - if (u_peer_id != kTurnPeerIdInvalid) { - TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); - } - } - tsk_safeobj_unlock(pc_self); - return 0; + const tnet_turn_peer_t *pc_peer; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pe_state = pc_peer->e_connbind_state; + } + else { + *pe_state = tnet_stun_state_none; + if (u_peer_id != kTurnPeerIdInvalid) { + TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_req_transport(const struct tnet_turn_session_s* pc_self, enum tnet_turn_transport_e *pe_transport) { - if (!pc_self || !pe_transport) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pe_transport = pc_self->e_req_transport; - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pe_transport) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pe_transport = pc_self->e_req_transport; + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_bytes_count(const struct tnet_turn_session_s* pc_self, uint64_t* bytes_in, uint64_t* bytes_out) @@ -791,459 +801,459 @@ int tnet_turn_session_get_bytes_count(const struct tnet_turn_session_s* pc_self, int tnet_turn_session_createpermission(struct tnet_turn_session_s* p_self, const char* pc_peer_addr, uint16_t u_peer_port, tnet_turn_peer_id_t* pu_id) { - int ret = 0; - tnet_turn_peer_t *p_peer = tsk_null; + int ret = 0; + tnet_turn_peer_t *p_peer = tsk_null; - if (!p_self || !pc_peer_addr || !u_peer_port || !pu_id) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(p_self); + if (!p_self || !pc_peer_addr || !u_peer_port || !pu_id) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if ((ret = _tnet_turn_peer_create(pc_peer_addr, u_peer_port, TNET_SOCKET_TYPE_IS_IPV6(p_self->p_lcl_sock->type), &p_peer))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { - if (!p_peer->p_stream_buff_in && !(p_peer->p_stream_buff_in = tsk_buffer_create_null())) { - TSK_DEBUG_ERROR("Failed to create stream buffer for peer with id=%ld", p_peer->id); - ret = -5; - goto bail; - } - } - if ((ret = _tnet_turn_session_send_permission(p_self, p_peer))) { - goto bail; - } - *pu_id = p_peer->id; - tsk_list_push_back_data(p_self->p_list_peers, (void**)&p_peer); + tsk_safeobj_lock(p_self); + + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if ((ret = _tnet_turn_peer_create(pc_peer_addr, u_peer_port, TNET_SOCKET_TYPE_IS_IPV6(p_self->p_lcl_sock->type), &p_peer))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { + if (!p_peer->p_stream_buff_in && !(p_peer->p_stream_buff_in = tsk_buffer_create_null())) { + TSK_DEBUG_ERROR("Failed to create stream buffer for peer with id=%ld", p_peer->id); + ret = -5; + goto bail; + } + } + if ((ret = _tnet_turn_session_send_permission(p_self, p_peer))) { + goto bail; + } + *pu_id = p_peer->id; + tsk_list_push_back_data(p_self->p_list_peers, (void**)&p_peer); bail: - TSK_OBJECT_SAFE_FREE(p_peer); - tsk_safeobj_unlock(p_self); - return ret; + TSK_OBJECT_SAFE_FREE(p_peer); + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_deletepermission(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_id) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - tsk_list_remove_item_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_id); - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + tsk_list_remove_item_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_id); + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_chanbind(tnet_turn_session_t* p_self, tnet_turn_peer_id_t u_peer_id) { - int ret = 0; - tnet_turn_peer_t *pc_peer; + int ret = 0; + tnet_turn_peer_t *pc_peer; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -5; + goto bail; + } - // ChannelBind must not be used for streams (e.g. TCP, TLS....) - if (p_self->e_req_transport != tnet_turn_transport_udp) { - TSK_DEBUG_ERROR("TURN ChannelBind not supported for stream"); - ret = -6; - goto bail; - } + // ChannelBind must not be used for streams (e.g. TCP, TLS....) + if (p_self->e_req_transport != tnet_turn_transport_udp) { + TSK_DEBUG_ERROR("TURN ChannelBind not supported for stream"); + ret = -6; + goto bail; + } - // create ChannelBind Request if doesn't exist (ChannelBind refresh *must* have same id) - pc_peer->e_chanbind_state = tnet_stun_state_none; - pc_peer->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; - if (!pc_peer->p_pkt_chanbind) { - pc_peer->u_chan_num = _tnet_turn_session_get_unique_chan_num(); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_channelbind_request, &pc_peer->p_pkt_chanbind))) { - TSK_DEBUG_ERROR("Failed to create TURN ChannelBind request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_chanbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - pc_peer->p_pkt_chanbind->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_chanbind, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_CHANNEL_NUMBER(pc_peer->u_chan_num), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_chanbind->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_chanbind))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - pc_peer->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.rtt.chanbind.id, pc_peer->timer.rtt.chanbind.u_timeout); - } - pc_peer->e_chanbind_state = tnet_stun_state_trying; + // create ChannelBind Request if doesn't exist (ChannelBind refresh *must* have same id) + pc_peer->e_chanbind_state = tnet_stun_state_none; + pc_peer->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; + if (!pc_peer->p_pkt_chanbind) { + pc_peer->u_chan_num = _tnet_turn_session_get_unique_chan_num(); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_channelbind_request, &pc_peer->p_pkt_chanbind))) { + TSK_DEBUG_ERROR("Failed to create TURN ChannelBind request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_chanbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + pc_peer->p_pkt_chanbind->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_chanbind, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_CHANNEL_NUMBER(pc_peer->u_chan_num), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_chanbind->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_chanbind))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + pc_peer->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.rtt.chanbind.id, pc_peer->timer.rtt.chanbind.u_timeout); + } + pc_peer->e_chanbind_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } // TCP-Connect rfc6062 - 4.3. Initiating a Connection int tnet_turn_session_connect(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_peer_id) { - int ret = 0; - tnet_turn_peer_t *pc_peer; + int ret = 0; + tnet_turn_peer_t *pc_peer; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -5; + goto bail; + } - // Connect must be used for streams (e.g. TCP, TLS....) only - if (p_self->e_req_transport != tnet_turn_transport_tcp) { - TSK_DEBUG_ERROR("TURN Connect not supported for UDP relay"); - ret = -6; - goto bail; - } + // Connect must be used for streams (e.g. TCP, TLS....) only + if (p_self->e_req_transport != tnet_turn_transport_tcp) { + TSK_DEBUG_ERROR("TURN Connect not supported for UDP relay"); + ret = -6; + goto bail; + } - // create Connect Request if doesn't exist (Connect refresh *must* have same id) - pc_peer->e_connect_state = tnet_stun_state_none; - pc_peer->e_connbind_state = tnet_stun_state_none; - if (!pc_peer->p_pkt_connect) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connect_request, &pc_peer->p_pkt_connect))) { - TSK_DEBUG_ERROR("Failed to create TURN Connect request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_connect, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - pc_peer->p_pkt_connect->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_connect, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_connect->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_connect))) { - goto bail; - } - pc_peer->e_connect_state = tnet_stun_state_trying; + // create Connect Request if doesn't exist (Connect refresh *must* have same id) + pc_peer->e_connect_state = tnet_stun_state_none; + pc_peer->e_connbind_state = tnet_stun_state_none; + if (!pc_peer->p_pkt_connect) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connect_request, &pc_peer->p_pkt_connect))) { + TSK_DEBUG_ERROR("Failed to create TURN Connect request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_connect, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + pc_peer->p_pkt_connect->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_connect, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_connect->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_connect))) { + goto bail; + } + pc_peer->e_connect_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_send_data(tnet_turn_session_t* p_self, tnet_turn_peer_id_t u_peer_id, const void* pc_data_ptr, uint16_t u_data_size) { - int ret = 0; - tnet_turn_peer_t* pc_peer; + int ret = 0; + tnet_turn_peer_t* pc_peer; - if (!p_self || !pc_data_ptr || !u_data_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pc_data_ptr || !u_data_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -3; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -4; - goto bail; - } - if (pc_peer->e_createperm_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN permission for the remote peer"); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -3; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -4; + goto bail; + } + if (pc_peer->e_createperm_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN permission for the remote peer"); + ret = -5; + goto bail; + } - /** Send Stream **/ - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type) && p_self->e_req_transport == tnet_turn_transport_tcp) { - ret = _tnet_turn_session_send_stream_raw(p_self, pc_peer, pc_data_ptr, u_data_size); - goto bail; - } + /** Send Stream **/ + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type) && p_self->e_req_transport == tnet_turn_transport_tcp) { + ret = _tnet_turn_session_send_stream_raw(p_self, pc_peer, pc_data_ptr, u_data_size); + goto bail; + } - /*** ChannelData ***/ - if (pc_peer->e_chanbind_state == tnet_stun_state_ok) { - ret = _tnet_turn_session_send_chandata(p_self, pc_peer, pc_data_ptr, u_data_size); - goto bail; - } + /*** ChannelData ***/ + if (pc_peer->e_chanbind_state == tnet_stun_state_ok) { + ret = _tnet_turn_session_send_chandata(p_self, pc_peer, pc_data_ptr, u_data_size); + goto bail; + } + + /*** Send indication ***/ + if (!pc_peer->p_pkt_sendind) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_send_indication, &pc_peer->p_pkt_sendind))) { + TSK_DEBUG_ERROR("Failed to create TURN SendIndication request"); + goto bail; + } + pc_peer->p_pkt_sendind->opt.dontfrag = 0; + // add authinfo + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_sendind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + else { + const tnet_stun_attr_vdata_t *pc_attr_data; + if ((ret = tnet_stun_pkt_attr_find_first(pc_peer->p_pkt_sendind, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data))) { + goto bail; + } + if (!pc_attr_data) { + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, + TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + else { + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr_data, pc_data_ptr, u_data_size))) { + goto bail; + } + } + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_sendind->transac_id))) { + goto bail; + } + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_peer->p_pkt_sendind))) { + goto bail; + } - /*** Send indication ***/ - if (!pc_peer->p_pkt_sendind) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_send_indication, &pc_peer->p_pkt_sendind))) { - TSK_DEBUG_ERROR("Failed to create TURN SendIndication request"); - goto bail; - } - pc_peer->p_pkt_sendind->opt.dontfrag = 0; - // add authinfo - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_sendind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - else { - const tnet_stun_attr_vdata_t *pc_attr_data; - if ((ret = tnet_stun_pkt_attr_find_first(pc_peer->p_pkt_sendind, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data))) { - goto bail; - } - if (!pc_attr_data) { - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, - TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - else { - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr_data, pc_data_ptr, u_data_size))) { - goto bail; - } - } - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_sendind->transac_id))) { - goto bail; - } - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_peer->p_pkt_sendind))) { - goto bail; - } - bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_is_active(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, tsk_bool_t *pb_active) { - if (!pc_self || !pb_active) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_active = pc_self->b_started - && (pc_self->e_alloc_state == tnet_stun_state_ok); - if (*pb_active) { - const tnet_turn_peer_t* pc_peer; - if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pb_active = (pc_peer->e_createperm_state == tnet_stun_state_ok); - } - else { - *pb_active = tsk_false; - } - } - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_active) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_active = pc_self->b_started + && (pc_self->e_alloc_state == tnet_stun_state_ok); + if (*pb_active) { + const tnet_turn_peer_t* pc_peer; + if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pb_active = (pc_peer->e_createperm_state == tnet_stun_state_ok); + } + else { + *pb_active = tsk_false; + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_is_stream(const struct tnet_turn_session_s* pc_self, tsk_bool_t *pb_stream) { - if (!pc_self || !pb_stream) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_stream = TNET_SOCKET_TYPE_IS_STREAM(pc_self->p_lcl_sock->type) ? tsk_true : tsk_false; - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_stream) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_stream = TNET_SOCKET_TYPE_IS_STREAM(pc_self->p_lcl_sock->type) ? tsk_true : tsk_false; + tsk_safeobj_unlock(pc_self); + return 0; } // Check "ConnectionBind" sent and underlaying socket is connected int tnet_turn_session_is_stream_connected(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, tsk_bool_t *pb_connected) { - if (!pc_self || !pb_connected) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_connected = pc_self->b_started - && (pc_self->e_alloc_state == tnet_stun_state_ok); - if (*pb_connected) { - const tnet_turn_peer_t* pc_peer; - if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pb_connected = (pc_peer->conn_fd != TNET_INVALID_FD && pc_peer->b_stream_connected && pc_peer->e_connbind_state == tnet_stun_state_ok); - } - else { - *pb_connected = tsk_false; - } - } - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_connected) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_connected = pc_self->b_started + && (pc_self->e_alloc_state == tnet_stun_state_ok); + if (*pb_connected) { + const tnet_turn_peer_t* pc_peer; + if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pb_connected = (pc_peer->conn_fd != TNET_INVALID_FD && pc_peer->b_stream_connected && pc_peer->e_connbind_state == tnet_stun_state_ok); + } + else { + *pb_connected = tsk_false; + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_stop(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - // FIXME - // tsk_safeobj_lock(p_self); + // FIXME + // tsk_safeobj_lock(p_self); - p_self->b_stopping = tsk_true; + p_self->b_stopping = tsk_true; - if (p_self->e_alloc_state == tnet_stun_state_ok) { - // UnAlloc - p_self->u_lifetime_alloc_in_sec = 0; - _tnet_turn_session_send_refresh(p_self); - } + if (p_self->e_alloc_state == tnet_stun_state_ok) { + // UnAlloc + p_self->u_lifetime_alloc_in_sec = 0; + _tnet_turn_session_send_refresh(p_self); + } - if (p_self->timer.p_mgr) { - ret = tsk_timer_manager_stop(p_self->timer.p_mgr); - } + if (p_self->timer.p_mgr) { + ret = tsk_timer_manager_stop(p_self->timer.p_mgr); + } - // free transport to force next call to prepare() to create new one with new sockets + // free transport to force next call to prepare() to create new one with new sockets if (p_self->p_transport) { tnet_transport_shutdown(p_self->p_transport); TSK_OBJECT_SAFE_FREE(p_self->p_transport); } - // clear peers - tsk_list_clear_items(p_self->p_list_peers); + // clear peers + tsk_list_clear_items(p_self->p_list_peers); - p_self->b_prepared = tsk_false; - p_self->b_started = tsk_false; - p_self->b_stopping = tsk_false; + p_self->b_prepared = tsk_false; + p_self->b_started = tsk_false; + p_self->b_stopping = tsk_false; - // tsk_safeobj_unlock(p_self); + // tsk_safeobj_unlock(p_self); - return ret; + return ret; } static int _tnet_turn_session_peer_find_by_id(const tnet_turn_session_t* pc_self, tnet_turn_peer_id_t id, const struct tnet_turn_peer_s **ppc_peer) { - const tsk_list_item_t *pc_item; - const struct tnet_turn_peer_s *pc_peer; - if (!pc_self || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_self->p_list_peers) { - if (!(pc_peer = pc_item->data)) { - continue; - } - if (pc_peer->id == id) { - *ppc_peer = pc_peer; - break; - } - } - return 0; + const tsk_list_item_t *pc_item; + const struct tnet_turn_peer_s *pc_peer; + if (!pc_self || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_self->p_list_peers) { + if (!(pc_peer = pc_item->data)) { + continue; + } + if (pc_peer->id == id) { + *ppc_peer = pc_peer; + break; + } + } + return 0; } static int _tnet_turn_session_peer_find_by_timer(const tnet_turn_session_t* pc_self, tsk_timer_id_t id, const struct tnet_turn_peer_s **ppc_peer) { - const tsk_list_item_t *pc_item; - const struct tnet_turn_peer_s *pc_peer; - if (!pc_self || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_self->p_list_peers) { - if (!(pc_peer = pc_item->data)) { - continue; - } - if (pc_peer->timer.rtt.chanbind.id == id || pc_peer->timer.rtt.createperm.id == id) { - *ppc_peer = pc_peer; - break; - } - } - return 0; + const tsk_list_item_t *pc_item; + const struct tnet_turn_peer_s *pc_peer; + if (!pc_self || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_self->p_list_peers) { + if (!(pc_peer = pc_item->data)) { + continue; + } + if (pc_peer->timer.rtt.chanbind.id == id || pc_peer->timer.rtt.createperm.id == id) { + *ppc_peer = pc_peer; + break; + } + } + return 0; } static uint16_t _tnet_turn_session_get_unique_chan_num() { - // rfc5766 - The channel number is in the range 0x4000 through 0x7FFE (inclusive) - static long __l_chan_num = 0; - tsk_atomic_inc(&__l_chan_num); - return (__l_chan_num % (0x7FFE - 0x4000)) + 0x4000; + // rfc5766 - The channel number is in the range 0x4000 through 0x7FFE (inclusive) + static long __l_chan_num = 0; + tsk_atomic_inc(&__l_chan_num); + return (__l_chan_num % (0x7FFE - 0x4000)) + 0x4000; } static int _tnet_turn_session_send_chandata(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - int ret = 0; - tsk_size_t PadSize, NeededSize; - uint8_t* _p_buff_chandata_ptr; + int ret = 0; + tsk_size_t PadSize, NeededSize; + uint8_t* _p_buff_chandata_ptr; if (!p_self || !pc_peer || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1257,45 +1267,45 @@ static int _tnet_turn_session_send_chandata(tnet_turn_session_t* p_self, const t ret = -2; goto bail; } - if (pc_peer->e_chanbind_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN data channel for peer id = %ld", pc_peer->id); + if (pc_peer->e_chanbind_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN data channel for peer id = %ld", pc_peer->id); ret = -3; goto bail; } - // rfc5766 - 11.5. Sending a ChannelData Message - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - // Over UDP, the padding is not required but MAY be included. - PadSize = 0; - } - else { - // Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to - // a multiple of four bytes in order to ensure the alignment of subsequent messages. - PadSize = (u_buff_size & 0x03) ? (4 - (u_buff_size & 0x03)) : 0; - } - NeededSize = kStunChannelDataHdrSizeInOctets + u_buff_size + PadSize; - - if (p_self->u_buff_chandata_size < NeededSize) { - if (!(p_self->p_buff_chandata_ptr = tsk_realloc(p_self->p_buff_chandata_ptr, NeededSize))) { - p_self->u_buff_chandata_size = 0; - ret = -4; - goto bail; - } - p_self->u_buff_chandata_size = NeededSize; - } - _p_buff_chandata_ptr = (uint8_t*)p_self->p_buff_chandata_ptr; + // rfc5766 - 11.5. Sending a ChannelData Message + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + // Over UDP, the padding is not required but MAY be included. + PadSize = 0; + } + else { + // Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to + // a multiple of four bytes in order to ensure the alignment of subsequent messages. + PadSize = (u_buff_size & 0x03) ? (4 - (u_buff_size & 0x03)) : 0; + } + NeededSize = kStunChannelDataHdrSizeInOctets + u_buff_size + PadSize; - *((uint16_t*)&_p_buff_chandata_ptr[0]) = tnet_htons(pc_peer->u_chan_num); // Channel Number - *((uint16_t*)&_p_buff_chandata_ptr[2]) = tnet_htons((uint16_t)u_buff_size); // Length - memcpy(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets], pc_buff_ptr, u_buff_size); // Application Data - if (PadSize) { - memset(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets + u_buff_size], 0, PadSize); // Set padding bytes to zero (not required but ease debugging) - } + if (p_self->u_buff_chandata_size < NeededSize) { + if (!(p_self->p_buff_chandata_ptr = tsk_realloc(p_self->p_buff_chandata_ptr, NeededSize))) { + p_self->u_buff_chandata_size = 0; + ret = -4; + goto bail; + } + p_self->u_buff_chandata_size = NeededSize; + } + _p_buff_chandata_ptr = (uint8_t*)p_self->p_buff_chandata_ptr; + + *((uint16_t*)&_p_buff_chandata_ptr[0]) = tnet_htons(pc_peer->u_chan_num); // Channel Number + *((uint16_t*)&_p_buff_chandata_ptr[2]) = tnet_htons((uint16_t)u_buff_size); // Length + memcpy(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets], pc_buff_ptr, u_buff_size); // Application Data + if (PadSize) { + memset(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets + u_buff_size], 0, PadSize); // Set padding bytes to zero (not required but ease debugging) + } + + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_chandata_ptr, NeededSize))) { + goto bail; + } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_chandata_ptr, NeededSize))) { - goto bail; - } - bail: // unlock() tsk_safeobj_unlock(p_self); @@ -1304,7 +1314,7 @@ bail: static int _tnet_turn_session_send_stream_raw(tnet_turn_session_t* p_self, tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - int ret = 0; + int ret = 0; if (!p_self || !pc_peer || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1318,20 +1328,20 @@ static int _tnet_turn_session_send_stream_raw(tnet_turn_session_t* p_self, tnet_ ret = -2; goto bail; } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - TSK_DEBUG_ERROR("Must not call this function for non-stream transports"); + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + TSK_DEBUG_ERROR("Must not call this function for non-stream transports"); ret = -3; goto bail; - } - if (pc_peer->e_connbind_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN TCP connection for peer id = %ld", pc_peer->id); + } + if (pc_peer->e_connbind_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN TCP connection for peer id = %ld", pc_peer->id); ret = -4; goto bail; } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, pc_buff_ptr, u_buff_size))) { - goto bail; - } + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, pc_buff_ptr, u_buff_size))) { + goto bail; + } bail: // unlock() @@ -1341,202 +1351,202 @@ bail: static int _tnet_turn_session_send_refresh(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - p_self->e_refresh_state = tnet_stun_state_none; - // create RefreshIndication Request - p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_refresh_request, &p_self->p_pkt_refresh))) { - TSK_DEBUG_ERROR("Failed to create TURN RefreshIndication request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(p_self->p_pkt_refresh, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + p_self->e_refresh_state = tnet_stun_state_none; + // create RefreshIndication Request + p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_refresh_request, &p_self->p_pkt_refresh))) { + TSK_DEBUG_ERROR("Failed to create TURN RefreshIndication request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(p_self->p_pkt_refresh, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); #if 0 - if (p_self->u_lifetime_alloc_in_sec == 0) { - const tnet_stun_attr_vdata_t *pc_attr_nonce = tsk_null; - tnet_stun_pkt_attr_find_first(p_self->p_pkt_refresh, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce); - if (pc_attr_nonce) { - pc_attr_nonce->p_data_ptr[0] = 'a'; - } - } + if (p_self->u_lifetime_alloc_in_sec == 0) { + const tnet_stun_attr_vdata_t *pc_attr_nonce = tsk_null; + tnet_stun_pkt_attr_find_first(p_self->p_pkt_refresh, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce); + if (pc_attr_nonce) { + pc_attr_nonce->p_data_ptr[0] = 'a'; + } + } #endif - // add attributes - ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_refresh, - TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - p_self->p_pkt_refresh->opt.dontfrag = 0; - p_self->p_pkt_refresh->opt.fingerprint = 0; - if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_refresh))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_self->timer.rtt.refresh.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.refresh.id, p_self->timer.rtt.refresh.u_timeout); - } - p_self->e_refresh_state = tnet_stun_state_trying; + // add attributes + ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_refresh, + TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + p_self->p_pkt_refresh->opt.dontfrag = 0; + p_self->p_pkt_refresh->opt.fingerprint = 0; + if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_refresh))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_self->timer.rtt.refresh.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.refresh.id, p_self->timer.rtt.refresh.u_timeout); + } + p_self->e_refresh_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_permission(struct tnet_turn_session_s* p_self, tnet_turn_peer_t *p_peer) { - int ret = 0; - if (!p_self || !p_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(p_self); + int ret = 0; + if (!p_self || !p_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + tsk_safeobj_lock(p_self); - // create CreatePermission Request - p_peer->e_createperm_state = tnet_stun_state_none; - p_peer->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_createpermission_request, &p_peer->p_pkt_createperm))) { - TSK_DEBUG_ERROR("Failed to create TURN CreatePermission request"); - goto bail; - } - // add authinfo - tnet_stun_pkt_auth_copy(p_peer->p_pkt_createperm, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - p_peer->p_pkt_createperm->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_createperm, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, p_peer->p_pkt_createperm))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_peer->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_peer->timer.rtt.createperm.id, p_peer->timer.rtt.createperm.u_timeout); - } - p_peer->e_createperm_state = tnet_stun_state_trying; + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + + // create CreatePermission Request + p_peer->e_createperm_state = tnet_stun_state_none; + p_peer->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_createpermission_request, &p_peer->p_pkt_createperm))) { + TSK_DEBUG_ERROR("Failed to create TURN CreatePermission request"); + goto bail; + } + // add authinfo + tnet_stun_pkt_auth_copy(p_peer->p_pkt_createperm, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + p_peer->p_pkt_createperm->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_createperm, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, p_peer->p_pkt_createperm))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_peer->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_peer->timer.rtt.createperm.id, p_peer->timer.rtt.createperm.u_timeout); + } + p_peer->e_createperm_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } // TCP-Connect rfc6062 - 4.3. Initiating a Connection static int _tnet_turn_session_send_connbind(struct tnet_turn_session_s* p_self, tnet_turn_peer_t *p_peer) { - int ret = 0; + int ret = 0; - if (!p_self || !p_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !p_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - // ConnectionBind must be sent after Connect - if (p_peer->e_connect_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN connection yet"); - ret = -6; - goto bail; - } - - // Connect must be used for streams (e.g. TCP, TLS....) only - if (p_self->e_req_transport != tnet_turn_transport_tcp) { - TSK_DEBUG_ERROR("TURN ConnectionBind not supported for UDP transport"); - ret = -7; - goto bail; - } + // ConnectionBind must be sent after Connect + if (p_peer->e_connect_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN connection yet"); + ret = -6; + goto bail; + } - // create Connect Request if doesn't exist (Connect refresh *must* have same id) - p_peer->e_connbind_state = tnet_stun_state_none; - if (!p_peer->p_pkt_connbind) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connectionbind_request, &p_peer->p_pkt_connbind))) { - TSK_DEBUG_ERROR("Failed to create TURN ConnectionBind request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(p_peer->p_pkt_connbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - p_peer->p_pkt_connbind->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_connbind, - // Error "420" when XOR-PEER-ADDRESS attribute is added to ConnectionBind request - /* TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), */ - TNET_STUN_PKT_ATTR_ADD_CONNECTION_ID(p_peer->u_conn_id), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&p_peer->p_pkt_connbind->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt_0(p_self, p_peer, p_peer->p_pkt_connbind))) { - goto bail; - } - p_peer->e_connbind_state = tnet_stun_state_trying; + // Connect must be used for streams (e.g. TCP, TLS....) only + if (p_self->e_req_transport != tnet_turn_transport_tcp) { + TSK_DEBUG_ERROR("TURN ConnectionBind not supported for UDP transport"); + ret = -7; + goto bail; + } + + // create Connect Request if doesn't exist (Connect refresh *must* have same id) + p_peer->e_connbind_state = tnet_stun_state_none; + if (!p_peer->p_pkt_connbind) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connectionbind_request, &p_peer->p_pkt_connbind))) { + TSK_DEBUG_ERROR("Failed to create TURN ConnectionBind request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(p_peer->p_pkt_connbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + p_peer->p_pkt_connbind->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_connbind, + // Error "420" when XOR-PEER-ADDRESS attribute is added to ConnectionBind request + /* TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), */ + TNET_STUN_PKT_ATTR_ADD_CONNECTION_ID(p_peer->u_conn_id), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&p_peer->p_pkt_connbind->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt_0(p_self, p_peer, p_peer->p_pkt_connbind))) { + goto bail; + } + p_peer->e_connbind_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { int ret = 0; - tsk_size_t u_sent_bytes = 0; + tsk_size_t u_sent_bytes = 0; if (!p_self || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1551,28 +1561,28 @@ static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tne goto bail; } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { #if 1 - u_sent_bytes = tnet_transport_sendto(p_self->p_transport, p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_sendto(p_self->p_transport, p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); #endif } else { - if (pc_peer && pc_peer->b_stream_connected && pc_peer->conn_fd != TNET_INVALID_FD) { - // Send using Peer connection if connected - // Should never be called because for now requested transport is always equal to UDP + if (pc_peer && pc_peer->b_stream_connected && pc_peer->conn_fd != TNET_INVALID_FD) { + // Send using Peer connection if connected + // Should never be called because for now requested transport is always equal to UDP #if 1 - u_sent_bytes = tnet_transport_send(p_self->p_transport, pc_peer->conn_fd, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_send(p_self->p_transport, pc_peer->conn_fd, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_sockfd_send(pc_peer->conn_fd, pc_buff_ptr, u_buff_size, 0); + u_sent_bytes = tnet_sockfd_send(pc_peer->conn_fd, pc_buff_ptr, u_buff_size, 0); #endif - } - else { + } + else { tsk_bool_t b_delay_send = tsk_false; - // Connect if not already done - if (!p_self->b_stream_connected) { - ret = tnet_sockfd_waitUntilWritable(p_self->p_lcl_sock->fd, kTurnTransportConnectTimeout); + // Connect if not already done + if (!p_self->b_stream_connected) { + ret = tnet_sockfd_waitUntilWritable(p_self->p_lcl_sock->fd, kTurnTransportConnectTimeout); if (ret == 0) { // socket is valid but not connected (e.g. Proxy handshaking not completed yet) TSK_DEBUG_INFO("Saving %u TURN bytes and waiting for 'connected' event before sending", (unsigned)u_buff_size); if (!p_self->p_stream_buff_out && !(p_self->p_stream_buff_out = tsk_buffer_create_null())) { @@ -1594,17 +1604,17 @@ static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tne ret = -6; goto bail; } - } - if (!b_delay_send && p_self->b_stream_connected) { + } + if (!b_delay_send && p_self->b_stream_connected) { #if 1 - u_sent_bytes = tnet_transport_send(p_self->p_transport, p_self->p_lcl_sock->fd, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_send(p_self->p_transport, p_self->p_lcl_sock->fd, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_socket_send_stream(p_self->p_lcl_sock, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_socket_send_stream(p_self->p_lcl_sock, pc_buff_ptr, u_buff_size); #endif - } - } + } + } } - if (u_sent_bytes != u_buff_size) { + if (u_sent_bytes != u_buff_size) { TSK_DEBUG_ERROR("Failed to send %u bytes. Only %u sent", (unsigned)u_buff_size, (unsigned)u_sent_bytes); ret = -2; goto bail; @@ -1618,21 +1628,21 @@ bail: static int _tnet_turn_session_send_buff(tnet_turn_session_t* p_self, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - return _tnet_turn_session_send_buff_0(p_self, tsk_null/*peer*/, pc_buff_ptr, u_buff_size); + return _tnet_turn_session_send_buff_0(p_self, tsk_null/*peer*/, pc_buff_ptr, u_buff_size); } static int _tnet_turn_session_send_pkt_0(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const tnet_turn_pkt_t *pc_pkt) { - int ret; - tsk_size_t u_min_size; - if (!p_self || !pc_pkt) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + int ret; + tsk_size_t u_min_size; + if (!p_self || !pc_pkt) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_pkt, &u_min_size))) { + if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_pkt, &u_min_size))) { goto bail; } u_min_size += kStunBuffMinPad; @@ -1649,32 +1659,32 @@ static int _tnet_turn_session_send_pkt_0(tnet_turn_session_t* p_self, const tnet if ((ret = tnet_stun_pkt_write_with_padding(pc_pkt, p_self->p_buff_send_ptr, p_self->u_buff_send_size, &u_min_size))) { goto bail; } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_send_ptr, u_min_size))) { - goto bail; - } + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_send_ptr, u_min_size))) { + goto bail; + } bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_pkt(tnet_turn_session_t* p_self, const tnet_turn_pkt_t *pc_pkt) { - return _tnet_turn_session_send_pkt_0(p_self, tsk_null/*peer*/, pc_pkt); + return _tnet_turn_session_send_pkt_0(p_self, tsk_null/*peer*/, pc_pkt); } // 420 = Unknown Attribute int _tnet_turn_session_process_err420_pkt(tnet_turn_pkt_t *p_pkt_req, const tnet_turn_pkt_t *pc_pkt_resp420) { - const tnet_stun_attr_vdata_t* pc_attr; - uint16_t u16; - int ret; - tsk_bool_t b_done = tsk_false; - if (!p_pkt_req || !pc_pkt_resp420) { - TSK_DEBUG_ERROR("Invalid parameter"); + const tnet_stun_attr_vdata_t* pc_attr; + uint16_t u16; + int ret; + tsk_bool_t b_done = tsk_false; + if (!p_pkt_req || !pc_pkt_resp420) { + TSK_DEBUG_ERROR("Invalid parameter"); return -1; - } - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { + } + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { goto bail; } if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) { @@ -1682,288 +1692,284 @@ int _tnet_turn_session_process_err420_pkt(tnet_turn_pkt_t *p_pkt_req, const tnet ret = -3; goto bail; } - for (u16 = 0; u16 < pc_attr->u_data_size; u16+=2) { - switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { - case tnet_stun_attr_type_dont_fragment: - { - p_pkt_req->opt.dontfrag = 0; - b_done = tsk_true; - break; - } - case tnet_stun_attr_type_fingerprint: - { - p_pkt_req->opt.fingerprint = 0; - b_done = tsk_true; - break; - } - } - } + for (u16 = 0; u16 < pc_attr->u_data_size; u16+=2) { + switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { + case tnet_stun_attr_type_dont_fragment: { + p_pkt_req->opt.dontfrag = 0; + b_done = tsk_true; + break; + } + case tnet_stun_attr_type_fingerprint: { + p_pkt_req->opt.fingerprint = 0; + b_done = tsk_true; + break; + } + } + } - if (b_done) { - // TRANSACTION-ID - if ((ret = tnet_stun_utils_transac_id_rand(&p_pkt_req->transac_id))) { - goto bail; - } - } + if (b_done) { + // TRANSACTION-ID + if ((ret = tnet_stun_utils_transac_id_rand(&p_pkt_req->transac_id))) { + goto bail; + } + } bail: - return ret; + return ret; } static int _tnet_turn_session_process_incoming_pkt(struct tnet_turn_session_s* p_self, const tnet_turn_pkt_t *pc_pkt, tsk_bool_t *pb_processed) { - int ret = 0; + int ret = 0; if (!p_self || !pc_pkt || !pb_processed) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - *pb_processed = tsk_false; + *pb_processed = tsk_false; // lock() tsk_safeobj_lock(p_self); - switch (pc_pkt->e_type) { - case tnet_stun_pkt_type_allocate_success_response: - case tnet_stun_pkt_type_allocate_error_response: - case tnet_stun_pkt_type_createpermission_success_response: - case tnet_stun_pkt_type_createpermission_error_response: - case tnet_stun_pkt_type_channelbind_success_response: - case tnet_stun_pkt_type_channelbind_error_response: - case tnet_stun_pkt_type_refresh_success_response: - case tnet_stun_pkt_type_refresh_error_response: - case tnet_stun_pkt_type_connect_success_response: - case tnet_stun_pkt_type_connect_error_response: - case tnet_stun_pkt_type_connectionbind_success_response: - case tnet_stun_pkt_type_connectionbind_error_response: - { - const tnet_stun_attr_error_code_t* pc_attr_err = tsk_null; - uint16_t u_code = 0; - tnet_turn_pkt_t *pc_pkt_req = tsk_null; - tnet_turn_peer_t* pc_peer = tsk_null; - + switch (pc_pkt->e_type) { + case tnet_stun_pkt_type_allocate_success_response: + case tnet_stun_pkt_type_allocate_error_response: + case tnet_stun_pkt_type_createpermission_success_response: + case tnet_stun_pkt_type_createpermission_error_response: + case tnet_stun_pkt_type_channelbind_success_response: + case tnet_stun_pkt_type_channelbind_error_response: + case tnet_stun_pkt_type_refresh_success_response: + case tnet_stun_pkt_type_refresh_error_response: + case tnet_stun_pkt_type_connect_success_response: + case tnet_stun_pkt_type_connect_error_response: + case tnet_stun_pkt_type_connectionbind_success_response: + case tnet_stun_pkt_type_connectionbind_error_response: { + const tnet_stun_attr_error_code_t* pc_attr_err = tsk_null; + uint16_t u_code = 0; + tnet_turn_pkt_t *pc_pkt_req = tsk_null; + tnet_turn_peer_t* pc_peer = tsk_null; + #define CANCEL_TIMER(parent, which) \ if (TSK_TIMER_ID_IS_VALID(parent->timer.rtt.which.id)) { \ tsk_timer_manager_cancel(p_self->timer.p_mgr, parent->timer.rtt.which.id); \ parent->timer.rtt.which.id = TSK_INVALID_TIMER_ID; \ } - // Find request - if (p_self->p_pkt_alloc && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_alloc->transac_id, pc_pkt->transac_id) == 0) { - pc_pkt_req = p_self->p_pkt_alloc; - CANCEL_TIMER(p_self, alloc); - CANCEL_TIMER(p_self, refresh); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_createperm, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_createperm; - CANCEL_TIMER(pc_peer, createperm); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_sendind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_sendind; - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_chanbind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_chanbind; - CANCEL_TIMER(pc_peer, chanbind); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connect, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_connect; - // TCP: no timer - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connectionbind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_connbind; - // TCP: no timer - } - else if (p_self->p_pkt_refresh && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_refresh->transac_id, pc_pkt->transac_id) == 0) { - pc_pkt_req = p_self->p_pkt_refresh; - CANCEL_TIMER(p_self, refresh); - } - - if (!pc_pkt_req) { - TSK_DEBUG_INFO("No matching request[TID=%s]", pc_pkt->transac_id); - // Not an error as the "fd" could be shared by several processes (e.g. ICE) - goto bail; - } - - /*** SUCCESS ***/ - if (TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { - // --- ALLOC --- // - if (pc_pkt_req == p_self->p_pkt_alloc) { - const tnet_stun_attr_address_t *pc_attr_addr; - tnet_ip_t ip_addr; - const tnet_stun_attr_vdata_t *pc_attr_lifetime; - // XOR-MAPPED-ADDRESS (optional) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr) { - if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr)) == 0) { - p_self->b_srflx_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); - p_self->u_srflx_port = pc_attr_addr->u_port; - tsk_strupdate(&p_self->p_srflx_ip, ip_addr); - } - } - // LIFETIME (optional) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { - p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); - } - // XOR-RELAYED-ADDRESS (required) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_relayed_address, (const tnet_stun_attr_t**)&pc_attr_addr))) { - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - if (!pc_attr_addr) { - TSK_DEBUG_ERROR("XOR-RELAYED-ADDRESS missing in success response for Allocate"); - ret = -4; - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr))) { - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - - // Uncomment to test [TURN Client] <-> [Turn Server] <-> [Any Client] + // Find request + if (p_self->p_pkt_alloc && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_alloc->transac_id, pc_pkt->transac_id) == 0) { + pc_pkt_req = p_self->p_pkt_alloc; + CANCEL_TIMER(p_self, alloc); + CANCEL_TIMER(p_self, refresh); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_createperm, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_createperm; + CANCEL_TIMER(pc_peer, createperm); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_sendind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_sendind; + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_chanbind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_chanbind; + CANCEL_TIMER(pc_peer, chanbind); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connect, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_connect; + // TCP: no timer + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connectionbind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_connbind; + // TCP: no timer + } + else if (p_self->p_pkt_refresh && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_refresh->transac_id, pc_pkt->transac_id) == 0) { + pc_pkt_req = p_self->p_pkt_refresh; + CANCEL_TIMER(p_self, refresh); + } + + if (!pc_pkt_req) { + TSK_DEBUG_INFO("No matching request[TID=%s]", pc_pkt->transac_id); + // Not an error as the "fd" could be shared by several processes (e.g. ICE) + goto bail; + } + + /*** SUCCESS ***/ + if (TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { + // --- ALLOC --- // + if (pc_pkt_req == p_self->p_pkt_alloc) { + const tnet_stun_attr_address_t *pc_attr_addr; + tnet_ip_t ip_addr; + const tnet_stun_attr_vdata_t *pc_attr_lifetime; + // XOR-MAPPED-ADDRESS (optional) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr) { + if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr)) == 0) { + p_self->b_srflx_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); + p_self->u_srflx_port = pc_attr_addr->u_port; + tsk_strupdate(&p_self->p_srflx_ip, ip_addr); + } + } + // LIFETIME (optional) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { + p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); + } + // XOR-RELAYED-ADDRESS (required) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_relayed_address, (const tnet_stun_attr_t**)&pc_attr_addr))) { + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + if (!pc_attr_addr) { + TSK_DEBUG_ERROR("XOR-RELAYED-ADDRESS missing in success response for Allocate"); + ret = -4; + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr))) { + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + + // Uncomment to test [TURN Client] <-> [Turn Server] <-> [Any Client] #if 0 - { - struct sockaddr_storage to; - tnet_sockaddr_init(ip_addr, pc_attr_addr->u_port, p_self->p_lcl_sock->type, &to); - tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data - tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data - } + { + struct sockaddr_storage to; + tnet_sockaddr_init(ip_addr, pc_attr_addr->u_port, p_self->p_lcl_sock->type, &to); + tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data + tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data + } #endif - // Schedule refresh - TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); - - p_self->e_alloc_state = tnet_stun_state_ok; - p_self->b_rel_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); - p_self->u_rel_port = pc_attr_addr->u_port; - tsk_strupdate(&p_self->p_rel_ip, ip_addr); - - _tnet_turn_session_raise_event_alloc_ok(p_self); - } - // --- CREATE-PERMISSION --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { - TSK_DEBUG_INFO("TURN 'CREATE-PERMISSION' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_createperm_state = tnet_stun_state_ok; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.createperm.id, pc_peer->timer.fresh.createperm.u_timeout); - _tnet_turn_session_raise_event_createperm_ok(p_self, pc_peer->id); - } - // --- CHANNEL-BIND --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { - TSK_DEBUG_INFO("TURN 'CHANNEL-BIND' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_chanbind_state = tnet_stun_state_ok; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.chanbind.id, pc_peer->timer.fresh.chanbind.u_timeout); - _tnet_turn_session_raise_event_chanbind_ok(p_self, pc_peer->id); - } - // --- CONNECT --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connect_request) { - TSK_DEBUG_INFO("TURN 'CONNECT' OK for peer-id = %ld", pc_peer->id); - if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { - goto bail; - } - } - // --- CONNECTION-BIND --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connectionbind_request) { - TSK_DEBUG_INFO("TURN 'CONNECTION-BIND' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_connbind_state = tnet_stun_state_ok; - _tnet_turn_session_raise_event_connectionbind_ok(p_self, pc_peer->id); - } - // --- REFRESH --- // - else if (pc_pkt_req == p_self->p_pkt_refresh) { - const tnet_stun_attr_vdata_t *pc_attr_lifetime; - TSK_DEBUG_INFO("TURN 'REFRESH' OK for peer-id = %ld", pc_peer ? pc_peer->id : -1); - p_self->e_refresh_state = tnet_stun_state_ok; - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { - p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); - } - TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); - _tnet_turn_session_raise_event_refresh_ok(p_self); - } - } - /*** ERROR ***/ - else { - tsk_bool_t b_nok = tsk_true; - if ((ret = tnet_stun_pkt_get_errorcode(pc_pkt, &u_code))) { - goto bail; - } - if (u_code > 299) { - tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr_err); - } - if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { - if (u_code == kStunErrCodeUnauthorized) { - // Make sure this is not an authentication failure (#2 401) - // Do not send another req to avoid endless messages - if ((tnet_stun_pkt_attr_exists(pc_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? - TSK_DEBUG_ERROR("TURN authentication failed"); - goto check_nok; - // INDICATION messages cannot receive 401 responses - } - } - if ((ret = tnet_stun_pkt_auth_prepare_2(pc_pkt_req, p_self->cred.p_usr_name, p_self->cred.p_pwd, pc_pkt))) { - goto check_nok; - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { - b_nok = tsk_false; goto check_nok; - } - } - else if (u_code == kStunErrCodeUnknownAttributes) { - if((ret = _tnet_turn_session_process_err420_pkt(pc_pkt_req, pc_pkt))) { - goto check_nok; - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { - b_nok = tsk_false; goto check_nok; - } - } + // Schedule refresh + TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); + + p_self->e_alloc_state = tnet_stun_state_ok; + p_self->b_rel_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); + p_self->u_rel_port = pc_attr_addr->u_port; + tsk_strupdate(&p_self->p_rel_ip, ip_addr); + + _tnet_turn_session_raise_event_alloc_ok(p_self); + } + // --- CREATE-PERMISSION --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { + TSK_DEBUG_INFO("TURN 'CREATE-PERMISSION' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_createperm_state = tnet_stun_state_ok; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.createperm.id, pc_peer->timer.fresh.createperm.u_timeout); + _tnet_turn_session_raise_event_createperm_ok(p_self, pc_peer->id); + } + // --- CHANNEL-BIND --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { + TSK_DEBUG_INFO("TURN 'CHANNEL-BIND' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_chanbind_state = tnet_stun_state_ok; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.chanbind.id, pc_peer->timer.fresh.chanbind.u_timeout); + _tnet_turn_session_raise_event_chanbind_ok(p_self, pc_peer->id); + } + // --- CONNECT --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connect_request) { + TSK_DEBUG_INFO("TURN 'CONNECT' OK for peer-id = %ld", pc_peer->id); + if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { + goto bail; + } + } + // --- CONNECTION-BIND --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connectionbind_request) { + TSK_DEBUG_INFO("TURN 'CONNECTION-BIND' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_connbind_state = tnet_stun_state_ok; + _tnet_turn_session_raise_event_connectionbind_ok(p_self, pc_peer->id); + } + // --- REFRESH --- // + else if (pc_pkt_req == p_self->p_pkt_refresh) { + const tnet_stun_attr_vdata_t *pc_attr_lifetime; + TSK_DEBUG_INFO("TURN 'REFRESH' OK for peer-id = %ld", pc_peer ? pc_peer->id : -1); + p_self->e_refresh_state = tnet_stun_state_ok; + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { + p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); + } + TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); + _tnet_turn_session_raise_event_refresh_ok(p_self); + } + } + /*** ERROR ***/ + else { + tsk_bool_t b_nok = tsk_true; + if ((ret = tnet_stun_pkt_get_errorcode(pc_pkt, &u_code))) { + goto bail; + } + if (u_code > 299) { + tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr_err); + } + if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { + if (u_code == kStunErrCodeUnauthorized) { + // Make sure this is not an authentication failure (#2 401) + // Do not send another req to avoid endless messages + if ((tnet_stun_pkt_attr_exists(pc_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? + TSK_DEBUG_ERROR("TURN authentication failed"); + goto check_nok; + // INDICATION messages cannot receive 401 responses + } + } + if ((ret = tnet_stun_pkt_auth_prepare_2(pc_pkt_req, p_self->cred.p_usr_name, p_self->cred.p_pwd, pc_pkt))) { + goto check_nok; + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { + b_nok = tsk_false; + goto check_nok; + } + } + else if (u_code == kStunErrCodeUnknownAttributes) { + if((ret = _tnet_turn_session_process_err420_pkt(pc_pkt_req, pc_pkt))) { + goto check_nok; + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { + b_nok = tsk_false; + goto check_nok; + } + } check_nok: - if (b_nok) { - TSK_DEBUG_INFO("--- TURN response code = %hu, phrase = %s, peer-id=%ld, ---", - u_code, pc_attr_err ? pc_attr_err->p_reason_phrase : "null", pc_peer ? pc_peer->id : -1); - if (pc_pkt_req == p_self->p_pkt_alloc) { - p_self->e_alloc_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_alloc_nok(p_self); - } - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { - pc_peer->e_chanbind_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_chanbind_nok(p_self, pc_peer->id); - } - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { - pc_peer->e_createperm_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_createperm_nok(p_self, pc_peer->id); - } - else if (pc_pkt_req == p_self->p_pkt_refresh) { - p_self->e_refresh_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_refresh_nok(p_self); - } - } - } - - break; - } - case tnet_stun_pkt_type_connectionattempt_indication: - { - // Indicates we already have an active connection - const tnet_stun_attr_address_t *pc_attr_xor_peer_addr; - tnet_turn_peer_t* pc_peer = tsk_null; - // XOR-PEER-ADDRESS - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xor_peer_addr)) == 0 && pc_attr_xor_peer_addr) { - if ((ret = _tnet_turn_peer_find_by_xpeer(p_self->p_list_peers, pc_attr_xor_peer_addr, (const tnet_turn_peer_t**)&pc_peer)) == 0 && pc_peer) { - if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { - goto bail; - } - } - } - break; - } - case tnet_stun_pkt_type_data_indication: - { - TSK_DEBUG_ERROR("Unexpected code called"); // --> DATA-INDICATION must be handled in net-event - break; - } - default: - { - goto bail; - } - } + if (b_nok) { + TSK_DEBUG_INFO("--- TURN response code = %hu, phrase = %s, peer-id=%ld, ---", + u_code, pc_attr_err ? pc_attr_err->p_reason_phrase : "null", pc_peer ? pc_peer->id : -1); + if (pc_pkt_req == p_self->p_pkt_alloc) { + p_self->e_alloc_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_alloc_nok(p_self); + } + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { + pc_peer->e_chanbind_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_chanbind_nok(p_self, pc_peer->id); + } + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { + pc_peer->e_createperm_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_createperm_nok(p_self, pc_peer->id); + } + else if (pc_pkt_req == p_self->p_pkt_refresh) { + p_self->e_refresh_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_refresh_nok(p_self); + } + } + } - *pb_processed = tsk_true; + break; + } + case tnet_stun_pkt_type_connectionattempt_indication: { + // Indicates we already have an active connection + const tnet_stun_attr_address_t *pc_attr_xor_peer_addr; + tnet_turn_peer_t* pc_peer = tsk_null; + // XOR-PEER-ADDRESS + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xor_peer_addr)) == 0 && pc_attr_xor_peer_addr) { + if ((ret = _tnet_turn_peer_find_by_xpeer(p_self->p_list_peers, pc_attr_xor_peer_addr, (const tnet_turn_peer_t**)&pc_peer)) == 0 && pc_peer) { + if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { + goto bail; + } + } + } + break; + } + case tnet_stun_pkt_type_data_indication: { + TSK_DEBUG_ERROR("Unexpected code called"); // --> DATA-INDICATION must be handled in net-event + break; + } + default: { + goto bail; + } + } + + *pb_processed = tsk_true; bail: // unlock() @@ -1974,38 +1980,38 @@ bail: // "pc_pkt" could be "200 response" or "CONNECTATTEMP-INDICATION" int _tnet_turn_session_process_success_connect_pkt(struct tnet_turn_session_s* p_self, tnet_turn_peer_t* pc_peer, const tnet_turn_pkt_t *pc_pkt) { - int ret = 0; - const tnet_stun_attr_vdata_t *pc_attr_connection_id; + int ret = 0; + const tnet_stun_attr_vdata_t *pc_attr_connection_id; if (!p_self || !pc_peer || !pc_pkt) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (pc_pkt->e_type != tnet_stun_pkt_type_connectionattempt_indication && !TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { - TSK_DEBUG_ERROR("Invalid packet type"); - ret = -2; - goto bail; - } - + if (pc_pkt->e_type != tnet_stun_pkt_type_connectionattempt_indication && !TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { + TSK_DEBUG_ERROR("Invalid packet type"); + ret = -2; + goto bail; + } + // lock() tsk_safeobj_lock(p_self); - - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_connection_id, (const tnet_stun_attr_t**)&pc_attr_connection_id)) == 0 && pc_attr_connection_id && pc_attr_connection_id->u_data_size == 4) { - pc_peer->u_conn_id = TSK_TO_UINT32(pc_attr_connection_id->p_data_ptr); - pc_peer->e_connect_state = tnet_stun_state_ok; - _tnet_turn_session_raise_event_connect_ok(p_self, pc_peer->id); - // Connect to the server and send "ConnectionBind" request using the "CONNECTION-ID" once connection is completed - pc_peer->conn_fd = tnet_transport_connectto(p_self->p_transport, p_self->p_srv_host, p_self->u_srv_port, p_self->p_transport->type); - if (pc_peer->conn_fd == TNET_INVALID_FD) { - TSK_DEBUG_ERROR("Failed to connect to %s:%d", p_self->p_srv_host, p_self->u_srv_port); - ret = -3; - goto bail; - } - } + + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_connection_id, (const tnet_stun_attr_t**)&pc_attr_connection_id)) == 0 && pc_attr_connection_id && pc_attr_connection_id->u_data_size == 4) { + pc_peer->u_conn_id = TSK_TO_UINT32(pc_attr_connection_id->p_data_ptr); + pc_peer->e_connect_state = tnet_stun_state_ok; + _tnet_turn_session_raise_event_connect_ok(p_self, pc_peer->id); + // Connect to the server and send "ConnectionBind" request using the "CONNECTION-ID" once connection is completed + pc_peer->conn_fd = tnet_transport_connectto(p_self->p_transport, p_self->p_srv_host, p_self->u_srv_port, p_self->p_transport->type); + if (pc_peer->conn_fd == TNET_INVALID_FD) { + TSK_DEBUG_ERROR("Failed to connect to %s:%d", p_self->p_srv_host, p_self->u_srv_port); + ret = -3; + goto bail; + } + } bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_transport_layer_dgram_cb(const tnet_transport_event_t* e) @@ -2015,252 +2021,252 @@ static int _tnet_turn_session_transport_layer_dgram_cb(const tnet_transport_even static int _tnet_turn_session_transport_layer_stream_cb(const tnet_transport_event_t* e) { - return _tnet_turn_session_transport_layer_process_cb(e); + return _tnet_turn_session_transport_layer_process_cb(e); } static int _tnet_turn_session_transport_layer_process_cb(const tnet_transport_event_t* e) { - tnet_turn_session_t* p_ss = (tnet_turn_session_t*)e->callback_data; - int ret = 0; - tnet_turn_pkt_t* p_pkt = tsk_null; - tsk_buffer_t* p_stream_buff_in = tsk_null; - const void* pc_data = tsk_null; - tsk_size_t u_data_size = 0; - tsk_bool_t b_stream = tsk_false, b_stream_appended = tsk_false, b_pkt_is_complete = tsk_false, b_got_msg= tsk_false; - tnet_turn_peer_t* pc_peer = tsk_null; - switch(e->type){ - case event_data: - break; - case event_brokenpipe: - tsk_safeobj_lock(p_ss); - if (p_ss->p_lcl_sock && e->local_fd == p_ss->p_lcl_sock->fd) { - tnet_fd_t broken_fd = e->local_fd; - tsk_bool_t registered_fd = !!tnet_transport_have_socket(p_ss->p_transport, broken_fd); + tnet_turn_session_t* p_ss = (tnet_turn_session_t*)e->callback_data; + int ret = 0; + tnet_turn_pkt_t* p_pkt = tsk_null; + tsk_buffer_t* p_stream_buff_in = tsk_null; + const void* pc_data = tsk_null; + tsk_size_t u_data_size = 0; + tsk_bool_t b_stream = tsk_false, b_stream_appended = tsk_false, b_pkt_is_complete = tsk_false, b_got_msg= tsk_false; + tnet_turn_peer_t* pc_peer = tsk_null; + switch(e->type) { + case event_data: + break; + case event_brokenpipe: + tsk_safeobj_lock(p_ss); + if (p_ss->p_lcl_sock && e->local_fd == p_ss->p_lcl_sock->fd) { + tnet_fd_t broken_fd = e->local_fd; + tsk_bool_t registered_fd = !!tnet_transport_have_socket(p_ss->p_transport, broken_fd); + if (registered_fd) { + tnet_transport_remove_socket(p_ss->p_transport, &broken_fd); + } + if (tnet_socket_handle_brokenpipe(p_ss->p_lcl_sock) == 0) { if (registered_fd) { - tnet_transport_remove_socket(p_ss->p_transport, &broken_fd); - } - if (tnet_socket_handle_brokenpipe(p_ss->p_lcl_sock) == 0) { - if (registered_fd) { - tnet_transport_add_socket(p_ss->p_transport, p_ss->p_lcl_sock->fd, p_ss->p_lcl_sock->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); - } + tnet_transport_add_socket(p_ss->p_transport, p_ss->p_lcl_sock->fd, p_ss->p_lcl_sock->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); } } + } + tsk_safeobj_unlock(p_ss); + return 0; + case event_connected: + if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { + tsk_safeobj_lock(p_ss); + p_ss->b_stream_connected = tsk_true; + if (p_ss->p_stream_buff_out && p_ss->p_stream_buff_out->size > 0) { + TSK_DEBUG_INFO("Sending %u TURN pending bytes", (unsigned)p_ss->p_stream_buff_out->size); + _tnet_turn_session_send_buff(p_ss, p_ss->p_stream_buff_out->data, (uint16_t)p_ss->p_stream_buff_out->size); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + } tsk_safeobj_unlock(p_ss); - return 0; - case event_connected: - if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { - tsk_safeobj_lock(p_ss); - p_ss->b_stream_connected = tsk_true; - if (p_ss->p_stream_buff_out && p_ss->p_stream_buff_out->size > 0) { - TSK_DEBUG_INFO("Sending %u TURN pending bytes", (unsigned)p_ss->p_stream_buff_out->size); - _tnet_turn_session_send_buff(p_ss, p_ss->p_stream_buff_out->data, (uint16_t)p_ss->p_stream_buff_out->size); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + } + else { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + pc_peer->b_stream_connected = tsk_true; + // Send ConnectionBind + if ((ret = _tnet_turn_session_send_connbind(p_ss, pc_peer))) { + goto bail; } - tsk_safeobj_unlock(p_ss); - } - else { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - pc_peer->b_stream_connected = tsk_true; - // Send ConnectionBind - if ((ret = _tnet_turn_session_send_connbind(p_ss, pc_peer))) { - goto bail; - } - } - tsk_safeobj_unlock(p_ss); - } - return 0; - case event_error: - case event_closed: - case event_removed: - /* case event_removed: */ - if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { - tsk_safeobj_lock(p_ss); - p_ss->b_stream_connected = tsk_false; - p_ss->b_stream_error = (e->type == event_error); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); - tsk_safeobj_unlock(p_ss); - } - else { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - pc_peer->b_stream_connected = tsk_false; - pc_peer->conn_fd = TNET_INVALID_FD; - } - tsk_safeobj_unlock(p_ss); - } - return 0; - default: - return 0; - } + } + tsk_safeobj_unlock(p_ss); + } + return 0; + case event_error: + case event_closed: + case event_removed: + /* case event_removed: */ + if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { + tsk_safeobj_lock(p_ss); + p_ss->b_stream_connected = tsk_false; + p_ss->b_stream_error = (e->type == event_error); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + tsk_safeobj_unlock(p_ss); + } + else { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + pc_peer->b_stream_connected = tsk_false; + pc_peer->conn_fd = TNET_INVALID_FD; + } + tsk_safeobj_unlock(p_ss); + } + return 0; + default: + return 0; + } - /*** If the code reach this line it means we have to deal with a "NET-DATA-EVENT" ***/ + /*** If the code reach this line it means we have to deal with a "NET-DATA-EVENT" ***/ - p_ss->cb.e.pc_enet = e; - pc_data = e->data; - u_data_size = e->size; - b_stream = TNET_SOCKET_TYPE_IS_STREAM(p_ss->p_lcl_sock->type); - b_stream_appended = tsk_false; + p_ss->cb.e.pc_enet = e; + pc_data = e->data; + u_data_size = e->size; + b_stream = TNET_SOCKET_TYPE_IS_STREAM(p_ss->p_lcl_sock->type); + b_stream_appended = tsk_false; handle_data: - b_got_msg = tsk_false; - - // TODO: /!\ - // - When the requested transport is TCP/TLS then we will receive RAW data on the connected peer socket which means no way to guess the end-of-the message - // - No issue for when requested transport is UDP because we'll always have the data encapsulated in CHANNEL-DATA or DATA-INDICATION. - if (b_stream) { - if (!b_stream_appended) { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - p_stream_buff_in = tsk_object_ref(pc_peer->p_stream_buff_in); - } - else { - p_stream_buff_in = tsk_object_ref(p_ss->p_stream_buff_in); - } - tsk_safeobj_unlock(p_ss); - - if ((ret = tsk_buffer_append(p_stream_buff_in, e->data, e->size))) { - goto bail; - } - b_stream_appended = tsk_true; - } - // Guard - if (p_stream_buff_in->size > kTurnStreamChunckMaxSize) { - TSK_DEBUG_ERROR("Too much data in the stream buffer: %u", (unsigned)p_stream_buff_in->size); - tsk_buffer_cleanup(p_stream_buff_in); - goto bail; - } - pc_data = p_stream_buff_in->data; - u_data_size = p_stream_buff_in->size; - } + b_got_msg = tsk_false; - if (!TNET_STUN_BUFF_IS_STUN2(((const uint8_t*)pc_data), u_data_size)) { - // ChannelData ? - if (TNET_STUN_BUFF_IS_CHANNEL_DATA(((const uint8_t*)pc_data), u_data_size)) { - const uint8_t* _p_data = (const uint8_t*)pc_data; - // Channel Number in [0x4000 - 0x7FFF] - // rfc5766 - 11.6. Receiving a ChannelData Message - // rfc5766 - 11.4. The ChannelData Message - // If the message uses a value in the reserved range (0x8000 through 0xFFFF), then the message is silently discarded - static const tsk_size_t kChannelDataHdrSize = 4; // Channel Number(2 bytes) + Length (2 bytes) - uint16_t u_chan_num = tnet_ntohs_2(&_p_data[0]); - if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_channum, &u_chan_num))) { - uint16_t u_len = tnet_ntohs_2(&_p_data[2]); - if (u_len <= (u_data_size - kChannelDataHdrSize)) { - b_got_msg = tsk_true; - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer->id, &_p_data[kChannelDataHdrSize], u_len); - if (p_stream_buff_in) { - /* The padding is not reflected in the length - field of the ChannelData message, so the actual size of a ChannelData - message (including padding) is (4 + Length) rounded up to the nearest - multiple of 4. Over UDP, the padding is not required but MAY be - included. - */ - tsk_size_t u_pad_len = (u_len & 3) ? (4 - (u_len & 3)) : 0; - tsk_buffer_remove(p_stream_buff_in, 0, kChannelDataHdrSize + u_len + u_pad_len); - } - } - else { - TSK_DEBUG_INFO("TURN channel data too short"); - } - } - goto bail; - } // if (TNET_STUN_BUFF_IS_CHANNEL_DATA... - - // Must never happen: Data must be received via CHANNEL-DATA or DATA-INDICATION - TSK_DEBUG_INFO("Calling unexpected code :("); - - if (b_stream) { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - tsk_safeobj_unlock(p_ss); - } - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); - if (p_stream_buff_in) { - tsk_buffer_cleanup(p_stream_buff_in); - } - goto bail; - } // if (!TNET_STUN_BUFF_IS_STUN2... - - /*** At this step it means we have a STUN packet in the buffer ***/ - - // Make sure we have a complete packet in the buffer - if (b_stream) { - if ((ret = tnet_stun_pkt_is_complete(pc_data, u_data_size, &b_pkt_is_complete))) { - goto bail; - } - if (!b_pkt_is_complete) { - TSK_DEBUG_INFO("The stream length is too short to contains a complete STUN/TURN packet"); - goto bail; - } - } + // TODO: /!\ + // - When the requested transport is TCP/TLS then we will receive RAW data on the connected peer socket which means no way to guess the end-of-the message + // - No issue for when requested transport is UDP because we'll always have the data encapsulated in CHANNEL-DATA or DATA-INDICATION. + if (b_stream) { + if (!b_stream_appended) { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + p_stream_buff_in = tsk_object_ref(pc_peer->p_stream_buff_in); + } + else { + p_stream_buff_in = tsk_object_ref(p_ss->p_stream_buff_in); + } + tsk_safeobj_unlock(p_ss); - // Parse the packet - if ((ret = tnet_stun_pkt_read(pc_data, u_data_size, &p_pkt))) { - goto bail; - } + if ((ret = tsk_buffer_append(p_stream_buff_in, e->data, e->size))) { + goto bail; + } + b_stream_appended = tsk_true; + } + // Guard + if (p_stream_buff_in->size > kTurnStreamChunckMaxSize) { + TSK_DEBUG_ERROR("Too much data in the stream buffer: %u", (unsigned)p_stream_buff_in->size); + tsk_buffer_cleanup(p_stream_buff_in); + goto bail; + } + pc_data = p_stream_buff_in->data; + u_data_size = p_stream_buff_in->size; + } - // Remove the parsed data - if (p_stream_buff_in && p_pkt) { - tsk_size_t u_pad_len = (p_pkt->u_length & 3) ? (4 - (p_pkt->u_length & 3)) : 0; - tsk_buffer_remove(p_stream_buff_in, 0, kStunPktHdrSizeInOctets + p_pkt->u_length + u_pad_len); - } + if (!TNET_STUN_BUFF_IS_STUN2(((const uint8_t*)pc_data), u_data_size)) { + // ChannelData ? + if (TNET_STUN_BUFF_IS_CHANNEL_DATA(((const uint8_t*)pc_data), u_data_size)) { + const uint8_t* _p_data = (const uint8_t*)pc_data; + // Channel Number in [0x4000 - 0x7FFF] + // rfc5766 - 11.6. Receiving a ChannelData Message + // rfc5766 - 11.4. The ChannelData Message + // If the message uses a value in the reserved range (0x8000 through 0xFFFF), then the message is silently discarded + static const tsk_size_t kChannelDataHdrSize = 4; // Channel Number(2 bytes) + Length (2 bytes) + uint16_t u_chan_num = tnet_ntohs_2(&_p_data[0]); + if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_channum, &u_chan_num))) { + uint16_t u_len = tnet_ntohs_2(&_p_data[2]); + if (u_len <= (u_data_size - kChannelDataHdrSize)) { + b_got_msg = tsk_true; + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer->id, &_p_data[kChannelDataHdrSize], u_len); + if (p_stream_buff_in) { + /* The padding is not reflected in the length + field of the ChannelData message, so the actual size of a ChannelData + message (including padding) is (4 + Length) rounded up to the nearest + multiple of 4. Over UDP, the padding is not required but MAY be + included. + */ + tsk_size_t u_pad_len = (u_len & 3) ? (4 - (u_len & 3)) : 0; + tsk_buffer_remove(p_stream_buff_in, 0, kChannelDataHdrSize + u_len + u_pad_len); + } + } + else { + TSK_DEBUG_INFO("TURN channel data too short"); + } + } + goto bail; + } // if (TNET_STUN_BUFF_IS_CHANNEL_DATA... - if (p_pkt) { - b_got_msg = tsk_true; - if (p_pkt->e_type == tnet_stun_pkt_type_data_indication) { - const tnet_stun_attr_vdata_t *pc_attr_data; - const tnet_stun_attr_address_t *pc_attr_xpeer; - const tnet_turn_peer_t *pc_peer; - // XOR-PEER-ADDRESS (required) - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xpeer)) || !pc_attr_xpeer) { - TSK_DEBUG_ERROR("XOR-PEER-ADDRESS missing in DATA-INDICATION"); - ret = -4; - goto bail; - } - tsk_safeobj_lock(p_ss); // lock to make sure the list will not be modified - if ((ret = _tnet_turn_peer_find_by_xpeer(p_ss->p_list_peers, pc_attr_xpeer, &pc_peer))) { - tsk_safeobj_unlock(p_ss); - goto bail; - } - tsk_safeobj_unlock(p_ss); // unlock() - // DATA (required) - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data)) || !pc_attr_data) { - TSK_DEBUG_ERROR("DATA missing in DATA-INDICAION"); - ret = -4; - goto bail; - } - - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_attr_data->p_data_ptr, pc_attr_data->u_data_size); - } - else { - tsk_bool_t b_processed; - if ((ret = _tnet_turn_session_process_incoming_pkt(p_ss, p_pkt, &b_processed))) { - goto bail; - } - if (!b_processed) { - const tnet_turn_peer_t *pc_peer; - tsk_safeobj_lock(p_ss); - pc_peer = (const tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - tsk_safeobj_unlock(p_ss); // unlock() - // Forward to listeners (e.g. ICE context) - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); - } - } - } + // Must never happen: Data must be received via CHANNEL-DATA or DATA-INDICATION + TSK_DEBUG_INFO("Calling unexpected code :("); + + if (b_stream) { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + tsk_safeobj_unlock(p_ss); + } + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); + if (p_stream_buff_in) { + tsk_buffer_cleanup(p_stream_buff_in); + } + goto bail; + } // if (!TNET_STUN_BUFF_IS_STUN2... + + /*** At this step it means we have a STUN packet in the buffer ***/ + + // Make sure we have a complete packet in the buffer + if (b_stream) { + if ((ret = tnet_stun_pkt_is_complete(pc_data, u_data_size, &b_pkt_is_complete))) { + goto bail; + } + if (!b_pkt_is_complete) { + TSK_DEBUG_INFO("The stream length is too short to contains a complete STUN/TURN packet"); + goto bail; + } + } + + // Parse the packet + if ((ret = tnet_stun_pkt_read(pc_data, u_data_size, &p_pkt))) { + goto bail; + } + + // Remove the parsed data + if (p_stream_buff_in && p_pkt) { + tsk_size_t u_pad_len = (p_pkt->u_length & 3) ? (4 - (p_pkt->u_length & 3)) : 0; + tsk_buffer_remove(p_stream_buff_in, 0, kStunPktHdrSizeInOctets + p_pkt->u_length + u_pad_len); + } + + if (p_pkt) { + b_got_msg = tsk_true; + if (p_pkt->e_type == tnet_stun_pkt_type_data_indication) { + const tnet_stun_attr_vdata_t *pc_attr_data; + const tnet_stun_attr_address_t *pc_attr_xpeer; + const tnet_turn_peer_t *pc_peer; + // XOR-PEER-ADDRESS (required) + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xpeer)) || !pc_attr_xpeer) { + TSK_DEBUG_ERROR("XOR-PEER-ADDRESS missing in DATA-INDICATION"); + ret = -4; + goto bail; + } + tsk_safeobj_lock(p_ss); // lock to make sure the list will not be modified + if ((ret = _tnet_turn_peer_find_by_xpeer(p_ss->p_list_peers, pc_attr_xpeer, &pc_peer))) { + tsk_safeobj_unlock(p_ss); + goto bail; + } + tsk_safeobj_unlock(p_ss); // unlock() + // DATA (required) + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data)) || !pc_attr_data) { + TSK_DEBUG_ERROR("DATA missing in DATA-INDICAION"); + ret = -4; + goto bail; + } + + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_attr_data->p_data_ptr, pc_attr_data->u_data_size); + } + else { + tsk_bool_t b_processed; + if ((ret = _tnet_turn_session_process_incoming_pkt(p_ss, p_pkt, &b_processed))) { + goto bail; + } + if (!b_processed) { + const tnet_turn_peer_t *pc_peer; + tsk_safeobj_lock(p_ss); + pc_peer = (const tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + tsk_safeobj_unlock(p_ss); // unlock() + // Forward to listeners (e.g. ICE context) + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); + } + } + } bail: - // Handle next message in the stream buffer - if (ret == 0 && b_got_msg && b_stream && p_stream_buff_in && p_stream_buff_in->size > 0) { - goto handle_data; - } + // Handle next message in the stream buffer + if (ret == 0 && b_got_msg && b_stream && p_stream_buff_in && p_stream_buff_in->size > 0) { + goto handle_data; + } - TSK_OBJECT_SAFE_FREE(p_pkt); - TSK_OBJECT_SAFE_FREE(p_stream_buff_in); - p_ss->cb.e.pc_enet = tsk_null; + TSK_OBJECT_SAFE_FREE(p_pkt); + TSK_OBJECT_SAFE_FREE(p_stream_buff_in); + p_ss->cb.e.pc_enet = tsk_null; return ret; } @@ -2288,36 +2294,36 @@ static int _tnet_turn_session_timer_callback(const void* pc_arg, tsk_timer_id_t } tnet_turn_session_t* p_ss = (tnet_turn_session_t*)pc_arg; - tnet_turn_peer_t* pc_peer; - int ret = 0; + tnet_turn_peer_t* pc_peer; + int ret = 0; tsk_safeobj_lock(p_ss); // must - if (p_ss->timer.rtt.alloc.id == timer_id) { - RETRANSMIT(p_ss, alloc, kTurnPeerIdInvalid); + if (p_ss->timer.rtt.alloc.id == timer_id) { + RETRANSMIT(p_ss, alloc, kTurnPeerIdInvalid); } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_chanbind, &timer_id))) { - RETRANSMIT(pc_peer, chanbind, pc_peer->id); + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_chanbind, &timer_id))) { + RETRANSMIT(pc_peer, chanbind, pc_peer->id); } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_createperm, &timer_id))) { - RETRANSMIT(pc_peer, createperm, pc_peer->id); + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_createperm, &timer_id))) { + RETRANSMIT(pc_peer, createperm, pc_peer->id); } - else if (p_ss->timer.rtt.refresh.id == timer_id) { - RETRANSMIT(p_ss, refresh, kTurnPeerIdInvalid); + else if (p_ss->timer.rtt.refresh.id == timer_id) { + RETRANSMIT(p_ss, refresh, kTurnPeerIdInvalid); } - else if (p_ss->timer.u_timer_id_refresh == timer_id) { - if ((ret = _tnet_turn_session_send_refresh(p_ss))) { - goto bail; - } + else if (p_ss->timer.u_timer_id_refresh == timer_id) { + if ((ret = _tnet_turn_session_send_refresh(p_ss))) { + goto bail; + } } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_chanbind, &timer_id))) { - if ((ret = tnet_turn_session_chanbind(p_ss, pc_peer->id))) { - goto bail; - } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_chanbind, &timer_id))) { + if ((ret = tnet_turn_session_chanbind(p_ss, pc_peer->id))) { + goto bail; + } + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_createperm, &timer_id))) { + if ((ret = _tnet_turn_session_send_permission(p_ss, pc_peer))) { + goto bail; + } } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_createperm, &timer_id))) { - if ((ret = _tnet_turn_session_send_permission(p_ss, pc_peer))) { - goto bail; - } - } bail: tsk_safeobj_unlock(p_ss); @@ -2326,71 +2332,71 @@ bail: static int _tnet_turn_peer_create(const char* pc_peer_ip, uint16_t u_peer_port, tsk_bool_t b_ipv6, struct tnet_turn_peer_s **pp_peer) { - extern const tsk_object_def_t *tnet_turn_peer_def_t; - static tnet_turn_peer_id_t __l_peer_id = 0; - tnet_stun_addr_t peer_addr; - int ret; - if (!pc_peer_ip || !u_peer_port || !pp_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if ((ret = tnet_stun_utils_inet_pton(b_ipv6, pc_peer_ip, &peer_addr))) { + extern const tsk_object_def_t *tnet_turn_peer_def_t; + static tnet_turn_peer_id_t __l_peer_id = 0; + tnet_stun_addr_t peer_addr; + int ret; + if (!pc_peer_ip || !u_peer_port || !pp_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if ((ret = tnet_stun_utils_inet_pton(b_ipv6, pc_peer_ip, &peer_addr))) { TSK_DEBUG_ERROR("inet_pton(%s,IPv6=%d) failed", pc_peer_ip, b_ipv6); goto bail; } - if (!(*pp_peer = tsk_object_new(tnet_turn_peer_def_t))) { - TSK_DEBUG_ERROR("Failed to create TURN peer object"); - return -2; - } - (*pp_peer)->p_addr_ip = tsk_strdup(pc_peer_ip); - memcpy((*pp_peer)->addr_ip, peer_addr, sizeof(peer_addr)); - (*pp_peer)->u_addr_port = u_peer_port; - (*pp_peer)->b_ipv6 = b_ipv6; - tsk_atomic_inc(&__l_peer_id); - (*pp_peer)->id = __l_peer_id; - (*pp_peer)->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; - (*pp_peer)->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; - (*pp_peer)->timer.fresh.chanbind.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.fresh.createperm.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.fresh.chanbind.u_timeout = kTurnChannelBindingTimeOutInSec * 1000; - (*pp_peer)->timer.fresh.createperm.u_timeout = kTurnPermissionTimeOutInSec * 1000; - (*pp_peer)->e_chanbind_state = tnet_stun_state_none; - (*pp_peer)->e_createperm_state = tnet_stun_state_none; + if (!(*pp_peer = tsk_object_new(tnet_turn_peer_def_t))) { + TSK_DEBUG_ERROR("Failed to create TURN peer object"); + return -2; + } + (*pp_peer)->p_addr_ip = tsk_strdup(pc_peer_ip); + memcpy((*pp_peer)->addr_ip, peer_addr, sizeof(peer_addr)); + (*pp_peer)->u_addr_port = u_peer_port; + (*pp_peer)->b_ipv6 = b_ipv6; + tsk_atomic_inc(&__l_peer_id); + (*pp_peer)->id = __l_peer_id; + (*pp_peer)->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; + (*pp_peer)->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; + (*pp_peer)->timer.fresh.chanbind.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.fresh.createperm.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.fresh.chanbind.u_timeout = kTurnChannelBindingTimeOutInSec * 1000; + (*pp_peer)->timer.fresh.createperm.u_timeout = kTurnPermissionTimeOutInSec * 1000; + (*pp_peer)->e_chanbind_state = tnet_stun_state_none; + (*pp_peer)->e_createperm_state = tnet_stun_state_none; bail: - return ret; + return ret; } static int _tnet_turn_peer_find_by_xpeer(const tnet_turn_peers_L_t* pc_peers, const tnet_stun_attr_address_t* pc_xpeer, const tnet_turn_peer_t **ppc_peer) { - const tsk_list_item_t *pc_item; - const tnet_turn_peer_t *pc_peer; - if (!pc_peers || !pc_xpeer || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_peers) { - pc_peer = (const tnet_turn_peer_t *)pc_item->data; - if (pc_peer->u_addr_port == pc_xpeer->u_port) { - if (tnet_stun_utils_buff_cmp( - pc_peer->addr_ip, pc_peer->b_ipv6 ? 16 : 4, - pc_xpeer->address, (pc_xpeer->e_family == tnet_stun_address_family_ipv6) ? 16 : 4) == 0) { - *ppc_peer = pc_peer; - return 0; - } - } - } - return 0; + const tsk_list_item_t *pc_item; + const tnet_turn_peer_t *pc_peer; + if (!pc_peers || !pc_xpeer || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_peers) { + pc_peer = (const tnet_turn_peer_t *)pc_item->data; + if (pc_peer->u_addr_port == pc_xpeer->u_port) { + if (tnet_stun_utils_buff_cmp( + pc_peer->addr_ip, pc_peer->b_ipv6 ? 16 : 4, + pc_xpeer->address, (pc_xpeer->e_family == tnet_stun_address_family_ipv6) ? 16 : 4) == 0) { + *ppc_peer = pc_peer; + return 0; + } + } + } + return 0; } static tsk_object_t* tnet_turn_session_ctor(tsk_object_t * self, va_list * app) { tnet_turn_session_t *p_ss = (tnet_turn_session_t *)self; if (p_ss) { - tsk_safeobj_init(p_ss); + tsk_safeobj_init(p_ss); } return self; } @@ -2398,41 +2404,41 @@ static tsk_object_t* tnet_turn_session_dtor(tsk_object_t * self) { tnet_turn_session_t *p_ss = (tnet_turn_session_t *)self; if (p_ss) { - // stop() - tnet_turn_session_stop(p_ss); - // timer.free() - TSK_OBJECT_SAFE_FREE(p_ss->timer.p_mgr); - // cred.free() - TSK_FREE(p_ss->cred.p_usr_name); - TSK_FREE(p_ss->cred.p_pwd); - // others.free() - TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_alloc); - TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_refresh); - TSK_OBJECT_SAFE_FREE(p_ss->p_lcl_sock); - - TSK_FREE(p_ss->p_buff_chandata_ptr); - TSK_FREE(p_ss->p_buff_send_ptr); - TSK_FREE(p_ss->p_rel_ip); - TSK_FREE(p_ss->p_srflx_ip); - TSK_FREE(p_ss->p_srv_host); - - if (p_ss->p_transport) { - tnet_transport_shutdown(p_ss->p_transport); - TSK_OBJECT_SAFE_FREE(p_ss->p_transport); - } - - TSK_OBJECT_SAFE_FREE(p_ss->p_list_peers); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_in); + // stop() + tnet_turn_session_stop(p_ss); + // timer.free() + TSK_OBJECT_SAFE_FREE(p_ss->timer.p_mgr); + // cred.free() + TSK_FREE(p_ss->cred.p_usr_name); + TSK_FREE(p_ss->cred.p_pwd); + // others.free() + TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_alloc); + TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_refresh); + TSK_OBJECT_SAFE_FREE(p_ss->p_lcl_sock); + + TSK_FREE(p_ss->p_buff_chandata_ptr); + TSK_FREE(p_ss->p_buff_send_ptr); + TSK_FREE(p_ss->p_rel_ip); + TSK_FREE(p_ss->p_srflx_ip); + TSK_FREE(p_ss->p_srv_host); + + if (p_ss->p_transport) { + tnet_transport_shutdown(p_ss->p_transport); + TSK_OBJECT_SAFE_FREE(p_ss->p_transport); + } + + TSK_OBJECT_SAFE_FREE(p_ss->p_list_peers); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_in); TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); - + TSK_OBJECT_SAFE_FREE(p_ss->proxy.info); - TSK_FREE(p_ss->ssl.path_priv); - TSK_FREE(p_ss->ssl.path_pub); - TSK_FREE(p_ss->ssl.path_ca); + TSK_FREE(p_ss->ssl.path_priv); + TSK_FREE(p_ss->ssl.path_pub); + TSK_FREE(p_ss->ssl.path_ca); - tsk_safeobj_deinit(p_ss); - TSK_DEBUG_INFO("*** TURN Session destroyed ***"); + tsk_safeobj_deinit(p_ss); + TSK_DEBUG_INFO("*** TURN Session destroyed ***"); } return self; } @@ -2456,7 +2462,7 @@ static tsk_object_t* tnet_turn_peer_ctor(tsk_object_t * self, va_list * app) { tnet_turn_peer_t *p_peer = (tnet_turn_peer_t *)self; if (p_peer) { - + } return self; } @@ -2464,13 +2470,13 @@ static tsk_object_t* tnet_turn_peer_dtor(tsk_object_t * self) { tnet_turn_peer_t *p_peer = (tnet_turn_peer_t *)self; if (p_peer) { - TSK_FREE(p_peer->p_addr_ip); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_chanbind); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_sendind); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connect); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connbind); - TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_in); + TSK_FREE(p_peer->p_addr_ip); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_chanbind); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_sendind); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connect); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connbind); + TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_in); TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_out); #if PRINT_DESTROYED_MSG || 1 TSK_DEBUG_INFO("*** TURN peer destroyed ***"); diff --git a/tinyNET/src/turn/tnet_turn_session.h b/tinyNET/src/turn/tnet_turn_session.h index fa4a030..7357bb1 100755 --- a/tinyNET/src/turn/tnet_turn_session.h +++ b/tinyNET/src/turn/tnet_turn_session.h @@ -33,34 +33,33 @@ struct tnet_proxyinfo_s; enum tnet_socket_type_e; #define kTurnPeerIdInvalid -1 -typedef enum tnet_turn_session_event_type_e -{ - tnet_turn_session_event_type_alloc_ok, - tnet_turn_session_event_type_alloc_nok, - tnet_turn_session_event_type_refresh_ok, - tnet_turn_session_event_type_refresh_nok, - tnet_turn_session_event_type_perm_ok, - tnet_turn_session_event_type_perm_nok, - tnet_turn_session_event_type_recv_data, - tnet_turn_session_event_type_chanbind_ok, - tnet_turn_session_event_type_chanbind_nok, - tnet_turn_session_event_type_connect_ok, - tnet_turn_session_event_type_connect_nok, - tnet_turn_session_event_type_connectionbind_ok, - tnet_turn_session_event_type_connectionbind_nok, +typedef enum tnet_turn_session_event_type_e { + tnet_turn_session_event_type_alloc_ok, + tnet_turn_session_event_type_alloc_nok, + tnet_turn_session_event_type_refresh_ok, + tnet_turn_session_event_type_refresh_nok, + tnet_turn_session_event_type_perm_ok, + tnet_turn_session_event_type_perm_nok, + tnet_turn_session_event_type_recv_data, + tnet_turn_session_event_type_chanbind_ok, + tnet_turn_session_event_type_chanbind_nok, + tnet_turn_session_event_type_connect_ok, + tnet_turn_session_event_type_connect_nok, + tnet_turn_session_event_type_connectionbind_ok, + tnet_turn_session_event_type_connectionbind_nok, } tnet_turn_session_event_type_t; typedef struct tnet_turn_session_event_xs { - enum tnet_turn_session_event_type_e e_type; - tnet_turn_peer_id_t u_peer_id; - const void* pc_usr_data; - const struct tnet_transport_event_s* pc_enet; - struct tnet_turn_session_s* pc_session; - struct { - const void* pc_data_ptr; - tsk_size_t u_data_size; - } data; + enum tnet_turn_session_event_type_e e_type; + tnet_turn_peer_id_t u_peer_id; + const void* pc_usr_data; + const struct tnet_transport_event_s* pc_enet; + struct tnet_turn_session_s* pc_session; + struct { + const void* pc_data_ptr; + tsk_size_t u_data_size; + } data; } tnet_turn_session_event_xt; typedef int (*tnet_turn_session_callback_f)(const struct tnet_turn_session_event_xs *e); |