From ae725add450df37ef623bf1a81710026e454a0b2 Mon Sep 17 00:00:00 2001 From: Oleg Moskalenko Date: Sun, 9 Nov 2014 22:52:25 -0800 Subject: [PATCH] Imported Upstream version 4.2.3.1 --- ChangeLog | 5 + INSTALL | 2 +- README.turnutils | 7 - TODO | 2 +- debian/etc/ufw/applications.d/turnserver | 4 - man/man1/turnadmin.1 | 2 +- man/man1/turnserver.1 | 4 +- man/man1/turnutils.1 | 9 +- rpm/build.settings.sh | 2 +- rpm/turnserver.spec | 4 +- src/apps/uclient/mainuclient.c | 3 +- src/apps/uclient/startuclient.c | 252 +++++++++++------------ src/apps/uclient/uclient.c | 192 +++++++++++++++-- src/apps/uclient/uclient.h | 2 +- src/ns_turn_defs.h | 2 +- 15 files changed, 323 insertions(+), 169 deletions(-) delete mode 100644 debian/etc/ufw/applications.d/turnserver diff --git a/ChangeLog b/ChangeLog index 5ff78954..e436ef3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +11/07/2014 Oleg Moskalenko +Version 4.2.3.1 'Monza': + - Request re-transmission implemented in uclient test program. + - TLS connection procedure improved in uclient test program. + 10/26/2014 Oleg Moskalenko Version 4.2.2.2 'Monza': - Black- and white- IP lists are divided per realm diff --git a/INSTALL b/INSTALL index 81ca3e9f..b4140dc0 100644 --- a/INSTALL +++ b/INSTALL @@ -774,7 +774,7 @@ CREATE TABLE turn_realm_option ( # oAuth key storage table. # CREATE TABLE oauth_key ( - kid varchar(128), /* + kid varchar(128), ikm_key varchar(256) default '', timestamp bigint default 0, lifetime integer default 0, diff --git a/README.turnutils b/README.turnutils index 618800b4..106983e6 100644 --- a/README.turnutils +++ b/README.turnutils @@ -8,13 +8,6 @@ for testing and for setting up the TURN server. The compiled binary image of this program is located in bin/ sub-directory. -WARNING: the turnutils_uclient program is a primitive client application. -It does not implement the re-transmission pattern that is necessary for -a correct TURN client implementation. In TURN, the retransmission burden -is lying almost entirely on the client application. We provide the messaging -functionality in the client library, but the client must implement -the correct Networking IO processing in the client program code. - 2. turnutils_peer: a simple stateless UDP-only "echo" server, to be used as the final server in relay pattern ("peer"). For every incoming UDP packet, it simply echoes it back. diff --git a/TODO b/TODO index 9f427caf..182c3a20 100644 --- a/TODO +++ b/TODO @@ -105,7 +105,7 @@ ================================================================== -nope +none ================================================================== diff --git a/debian/etc/ufw/applications.d/turnserver b/debian/etc/ufw/applications.d/turnserver deleted file mode 100644 index 4513de3f..00000000 --- a/debian/etc/ufw/applications.d/turnserver +++ /dev/null @@ -1,4 +0,0 @@ -[Turnserver] -title=Coturn Turnserver -description=Free open source implementation of TURN and STUN Server -ports=3478,3479,5349,5350,49152:65535/tcp|3478,3479,5349,5350,49152:65535/udp diff --git a/man/man1/turnadmin.1 b/man/man1/turnadmin.1 index e47caf77..41688d14 100644 --- a/man/man1/turnadmin.1 +++ b/man/man1/turnadmin.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index cd6d82f7..2f921a98 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION The \fBTURN Server\fP project contains the source code of a TURN server and TURN client @@ -277,7 +277,7 @@ it does not make much sense with the short\-term mechanism. .TP .B \fB\-\-oauth\fP -Support oAuth authentication. +Support oAuth authentication, as in the third\-party TURN specs document. .TP .B \fB\-\-dh566\fP diff --git a/man/man1/turnutils.1 b/man/man1/turnutils.1 index ec39407f..260ca5f7 100644 --- a/man/man1/turnutils.1 +++ b/man/man1/turnutils.1 @@ -1,5 +1,5 @@ .\" Text automatically generated by txt2man -.TH TURN 1 "28 September 2014" "" "" +.TH TURN 1 "09 November 2014" "" "" .SH GENERAL INFORMATION A set of turnutils_* programs provides some utility functionality to be used @@ -11,13 +11,6 @@ for testing and for setting up the TURN server. (this program is provided for the testing purposes only !) The compiled binary image of this program is located in bin/ sub\-directory. -.PP -WARNING: the \fIturnutils_uclient\fP program is a primitive client application. -It does not implement the re\-transmission pattern that is necessary for -a correct TURN client implementation. In TURN, the retransmission burden -is lying almost entirely on the client application. We provide the messaging -functionality in the client library, but the client must implement -the correct Networking IO processing in the client program code. .TP .B 2. diff --git a/rpm/build.settings.sh b/rpm/build.settings.sh index c4ea5977..d44c2d13 100755 --- a/rpm/build.settings.sh +++ b/rpm/build.settings.sh @@ -2,7 +2,7 @@ # Common settings script. -TURNVERSION=4.2.2.2 +TURNVERSION=4.2.3.1 BUILDDIR=~/rpmbuild ARCH=`uname -p` TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn diff --git a/rpm/turnserver.spec b/rpm/turnserver.spec index 561da6eb..5cea7dba 100644 --- a/rpm/turnserver.spec +++ b/rpm/turnserver.spec @@ -1,5 +1,5 @@ Name: turnserver -Version: 4.2.2.2 +Version: 4.2.3.1 Release: 0%{dist} Summary: Coturn TURN Server @@ -294,6 +294,8 @@ fi %{_includedir}/turn/client/TurnMsgLib.h %changelog +* Thu Nov 07 2014 Oleg Moskalenko + - Sync to 4.2.3.1 * Sun Oct 26 2014 Oleg Moskalenko - Sync to 4.2.2.2 * Sun Oct 05 2014 Oleg Moskalenko diff --git a/src/apps/uclient/mainuclient.c b/src/apps/uclient/mainuclient.c index 4c2c4a3e..164fdaa6 100644 --- a/src/apps/uclient/mainuclient.c +++ b/src/apps/uclient/mainuclient.c @@ -146,7 +146,6 @@ static char Usage[] = " -k Private key file (for secure connections only).\n" " -E CA file for server certificate verification, \n" " if the server certificate to be verified.\n" - " -F Cipher suite for TLS/DTLS. Default value is DEFAULT.\n" " -p TURN server port (Default: 3478 unsecure, 5349 secure).\n" " -n Number of messages to send (Default: 5).\n" " -d Local interface device (optional).\n" @@ -188,7 +187,7 @@ void recalculate_restapi_hmac(void) { g_upwd[pwd_length] = 0; } } - free(pwd); + turn_free(pwd,strlen(pwd)+1); } } } diff --git a/src/apps/uclient/startuclient.c b/src/apps/uclient/startuclient.c index c60da2cd..afe0b660 100644 --- a/src/apps/uclient/startuclient.c +++ b/src/apps/uclient/startuclient.c @@ -76,11 +76,12 @@ static int get_allocate_address_family(ioa_addr *relay_addr) { ///////////////////////////////////////// -static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) +static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr, int *try_again) { int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num); + SSL *ssl; - SSL *ssl = SSL_NEW(root_tls_ctx[ctxtype]); + ssl = SSL_NEW(root_tls_ctx[ctxtype]); if(use_tcp) { SSL_set_fd(ssl, fd); @@ -133,8 +134,8 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) } break; } else { - TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect\n", - __FUNCTION__); + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect: rc=%d, ctx=%d\n", + __FUNCTION__,rc,ctxtype); switch (SSL_get_error(ssl, rc)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: @@ -143,8 +144,13 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr) default: { char buf[1025]; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", - ERR_error_string(ERR_get_error(), buf), SSL_get_error( - ssl, rc)); + ERR_error_string(ERR_get_error(), buf), SSL_get_error(ssl, rc)); + if(ctxtype>0) { + if(try_again) { + *try_again = 1; + return NULL; + } + } exit(-1); } }; @@ -259,8 +265,13 @@ static int clnet_connect(uint16_t clnet_remote_port, const char *remote_address, } if (use_secure) { - clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr); + int try_again = 0; + clnet_info->ssl = tls_connect(clnet_info->fd, &remote_addr,&try_again); if (!clnet_info->ssl) { + if(try_again) { + close(clnet_fd); + goto start_socket; + } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); } @@ -317,15 +328,15 @@ static int clnet_allocate(int verbose, app_ur_conn_info *clnet_info, ioa_addr *relay_addr, int af, - char *turn_addr, u16bits *turn_port, - stun_tid *in_tid, - stun_tid *out_tid) { + char *turn_addr, u16bits *turn_port) { int af_cycle = 0; int reopen_socket = 0; int allocate_finished; + stun_buffer request_message, response_message; + beg_allocate: allocate_finished=0; @@ -344,15 +355,14 @@ static int clnet_allocate(int verbose, reopen_socket = 0; } - stun_buffer message; - if(!in_tid && current_reservation_token) { + if(current_reservation_token) { af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT; } int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4); int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6); - if(!no_rtcp && !in_tid) { + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { af4 = 0; af6 = 0; @@ -360,42 +370,34 @@ static int clnet_allocate(int verbose, } if(!dos) - stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME, af4, af6, relay_transport, mobility); else - stun_set_allocate_request(&message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); + stun_set_allocate_request(&request_message, UCLIENT_SESSION_LIFETIME/3, af4, af6, relay_transport, mobility); if(bps) - stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps); - - if(in_tid) { - stun_tid_message_cpy(message.buf, in_tid); - } + stun_attr_add_bandwidth_str(request_message.buf, (size_t*)(&(request_message.len)), bps); if(dont_fragment) - stun_attr_add(&message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); - if(!no_rtcp && !in_tid) { + stun_attr_add(&request_message, STUN_ATTRIBUTE_DONT_FRAGMENT, NULL, 0); + if(!no_rtcp) { if (!never_allocate_rtcp && allocate_rtcp) { uint64_t reservation_token = ioa_ntoh64(current_reservation_token); - stun_attr_add(&message, STUN_ATTRIBUTE_RESERVATION_TOKEN, + stun_attr_add(&request_message, STUN_ATTRIBUTE_RESERVATION_TOKEN, (char*) (&reservation_token), 8); } else { - stun_attr_add_even_port(&message, 1); + stun_attr_add_even_port(&request_message, 1); } } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); - - if(out_tid) { - stun_tid_from_message_str(message.buf, (size_t)message.len, out_tid); - } + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!allocate_sent) { - int len = send_buffer(clnet_info, &message,0,0); + int len = send_buffer(clnet_info, &request_message,0,0); if (len > 0) { if (verbose) { @@ -415,25 +417,24 @@ static int clnet_allocate(int verbose, ////////allocate response==>> { int allocate_received = 0; - stun_buffer message; while (!allocate_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "allocate response received: \n"); } - message.len = len; + response_message.len = len; int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { allocate_received = 1; allocate_finished = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } @@ -443,13 +444,13 @@ static int clnet_allocate(int verbose, { int found = 0; - stun_attr_ref sar = stun_attr_get_first(&message); + stun_attr_ref sar = stun_attr_get_first(&response_message); while (sar) { int attr_type = stun_attr_get_type(sar); if(attr_type == STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS) { - if (stun_attr_get_addr(&message, sar, relay_addr, NULL) < 0) { + if (stun_attr_get_addr(&response_message, sar, relay_addr, NULL) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: !!!: relay addr cannot be received (1)\n", __FUNCTION__); @@ -480,7 +481,7 @@ static int clnet_allocate(int verbose, } } - sar = stun_attr_get_next(&message,sar); + sar = stun_attr_get_next(&response_message,sar); } if(!found) { @@ -492,16 +493,16 @@ static int clnet_allocate(int verbose, } stun_attr_ref rt_sar = stun_attr_get_first_by_type( - &message, STUN_ATTRIBUTE_RESERVATION_TOKEN); + &response_message, STUN_ATTRIBUTE_RESERVATION_TOKEN); uint64_t rtv = stun_attr_get_reservation_token_value(rt_sar); current_reservation_token = rtv; if (verbose) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: rtv=%llu\n", __FUNCTION__, (long long unsigned int)rtv); - read_mobility_ticket(clnet_info, &message); + read_mobility_ticket(clnet_info, &response_message); - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -510,7 +511,7 @@ static int clnet_allocate(int verbose, recalculate_restapi_hmac(); } goto beg_allocate; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { if(err_code == SHA_TOO_WEAK_ERROR_CODE && (clnet_info->shatype == SHATYPE_SHA1) && use_short_term) { clnet_info->shatype = SHATYPE_SHA256; @@ -522,12 +523,12 @@ static int clnet_allocate(int verbose, if(err_code == 300) { if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } ioa_addr alternate_server; - if(stun_attr_get_first_addr(&message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { + if(stun_attr_get_first_addr(&response_message, STUN_ATTRIBUTE_ALTERNATE_SERVER, &alternate_server, NULL)==-1) { //error } else if(turn_addr && turn_port){ addr_to_string_no_port(&alternate_server, (u08bits*)turn_addr); @@ -571,9 +572,7 @@ static int clnet_allocate(int verbose, exit(-1); } - if(!in_tid) { - allocate_rtcp = !allocate_rtcp; - } + allocate_rtcp = !allocate_rtcp; if (1) { @@ -632,24 +631,23 @@ static int clnet_allocate(int verbose, { int refresh_sent = 0; - stun_buffer message; - stun_init_request(STUN_METHOD_REFRESH, &message); + stun_init_request(STUN_METHOD_REFRESH, &request_message); uint32_t lt = htonl(UCLIENT_SESSION_LIFETIME); - stun_attr_add(&message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); + stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) <, 4); if(clnet_info->s_mobile_id[0]) { - stun_attr_add(&message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); + stun_attr_add(&request_message, STUN_ATTRIBUTE_MOBILITY_TICKET, (const char*)clnet_info->s_mobile_id, strlen(clnet_info->s_mobile_id)); } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!refresh_sent) { - int len = send_buffer(clnet_info, &message, 0,0); + int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { @@ -659,7 +657,7 @@ static int clnet_allocate(int verbose, if(clnet_info->s_mobile_id[0]) { usleep(10000); - send_buffer(clnet_info, &message, 0,0); + send_buffer(clnet_info, &request_message, 0,0); } } else { perror("send"); @@ -673,13 +671,12 @@ static int clnet_allocate(int verbose, ////////refresh response==>> { int refresh_received = 0; - stun_buffer message; while (!refresh_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if(clnet_info->s_mobile_id[0]) { - len = recv_buffer(clnet_info, &message, 1, 0); + len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); } if (len > 0) { @@ -687,16 +684,16 @@ static int clnet_allocate(int verbose, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "refresh response received: \n"); } - message.len = len; + response_message.len = len; int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { - read_mobility_ticket(clnet_info, &message); + if (stun_is_success_response(&response_message)) { + read_mobility_ticket(clnet_info, &response_message); refresh_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -705,7 +702,7 @@ static int clnet_allocate(int verbose, recalculate_restapi_hmac(); } goto beg_refresh; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { refresh_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "error %d (%s)\n", err_code,(char*)err_msg); @@ -729,28 +726,28 @@ static int clnet_allocate(int verbose, static int turn_channel_bind(int verbose, uint16_t *chn, app_ur_conn_info *clnet_info, ioa_addr *peer_addr) { + stun_buffer request_message, response_message; + beg_bind: { int cb_sent = 0; - stun_buffer message; - if(negative_test) { - *chn = stun_set_channel_bind_request(&message, peer_addr, (u16bits)random()); + *chn = stun_set_channel_bind_request(&request_message, peer_addr, (u16bits)random()); } else { - *chn = stun_set_channel_bind_request(&message, peer_addr, *chn); + *chn = stun_set_channel_bind_request(&request_message, peer_addr, *chn); } - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { - int len = send_buffer(clnet_info, &message, 0,0); + int len = send_buffer(clnet_info, &request_message, 0,0); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind sent\n"); @@ -771,10 +768,9 @@ static int turn_channel_bind(int verbose, uint16_t *chn, { int cb_received = 0; - stun_buffer message; while (!cb_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -782,12 +778,12 @@ static int turn_channel_bind(int verbose, uint16_t *chn, } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { cb_received = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } @@ -795,7 +791,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success: 0x%x\n", (int) (*chn)); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -804,7 +800,7 @@ static int turn_channel_bind(int verbose, uint16_t *chn, recalculate_restapi_hmac(); } goto beg_bind; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "channel bind: error %d (%s)\n", err_code,(char*)err_msg); @@ -836,30 +832,30 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, addr_to_string(peer_addr,(u08bits*)saddr); } + stun_buffer request_message, response_message; + beg_cp: { int cp_sent = 0; - stun_buffer message; - - stun_init_request(STUN_METHOD_CREATE_PERMISSION, &message); + stun_init_request(STUN_METHOD_CREATE_PERMISSION, &request_message); { int addrindex; for(addrindex=0;addrindex 0) { if (verbose) { @@ -881,10 +877,9 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, { int cp_received = 0; - stun_buffer message; while (!cp_received) { - int len = recv_buffer(clnet_info, &message, 1, 0); + int len = recv_buffer(clnet_info, &response_message, 1, 0, NULL, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -892,19 +887,19 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { cp_received = 1; if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -913,7 +908,7 @@ static int turn_create_permission(int verbose, app_ur_conn_info *clnet_info, recalculate_restapi_hmac(); } goto beg_cp; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cp_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "create permission error %d (%s)\n", err_code,(char*)err_msg); @@ -960,9 +955,7 @@ int start_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - stun_tid tid; - - clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); + clnet_allocate(verbose, clnet_info_probe, &relay_addr, default_address_family, remote_address, &clnet_remote_port); /* Real: */ @@ -982,20 +975,15 @@ int start_connection(uint16_t clnet_remote_port0, } int af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr); - if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,NULL,&tid) < 0) { + if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL) < 0) { exit(-1); } - //strcpy((char*)g_uname,"qqq"); - //if (clnet_allocate(verbose, clnet_info, &relay_addr, af, NULL,NULL,&tid,NULL) < 0) { - // exit(-1); - //} - if(rare_event()) return 0; if(!no_rtcp) { af = default_address_family ? default_address_family : get_allocate_address_family(&peer_addr_rtcp); - if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info_rtcp, &relay_addr_rtcp, af,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; @@ -1182,7 +1170,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, char remote_address[1025]; STRCPY(remote_address,remote_address0); - clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port,NULL,NULL); + clnet_allocate(verbose, clnet_info_probe, &relay_addr1, default_address_family, remote_address, &clnet_remote_port); if(rare_event()) return 0; @@ -1215,7 +1203,7 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(!no_rtcp) { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) < 0) { exit(-1); } @@ -1223,13 +1211,13 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info1_rtcp, - &relay_addr1_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { + &relay_addr1_rtcp, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { exit(-1); } @@ -1237,20 +1225,20 @@ int start_c2c_connection(uint16_t clnet_remote_port0, if(rare_event()) return 0; if (clnet_allocate(verbose, clnet_info2_rtcp, - &relay_addr2_rtcp, default_address_family,NULL,NULL,NULL,NULL) < 0) { + &relay_addr2_rtcp, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; } else { - if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL,NULL,NULL) + if (clnet_allocate(verbose, clnet_info1, &relay_addr1, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; if(!(clnet_info2->is_peer)) { - if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL,NULL,NULL) < 0) { + if (clnet_allocate(verbose, clnet_info2, &relay_addr2, default_address_family,NULL,NULL) < 0) { exit(-1); } if(rare_event()) return 0; @@ -1421,27 +1409,28 @@ int turn_tcp_connect(int verbose, app_ur_conn_info *clnet_info, ioa_addr *peer_a static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, app_tcp_conn_info *atc, int errorOK) { + stun_buffer request_message, response_message; + beg_cb: { int cb_sent = 0; - stun_buffer message; u32bits cid = atc->cid; - stun_init_request(STUN_METHOD_CONNECTION_BIND, &message); + stun_init_request(STUN_METHOD_CONNECTION_BIND, &request_message); - stun_attr_add(&message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); + stun_attr_add(&request_message, STUN_ATTRIBUTE_CONNECTION_ID, (const s08bits*)&cid,4); - add_origin(&message); + add_origin(&request_message); - if(add_integrity(clnet_info, &message)<0) return -1; + if(add_integrity(clnet_info, &request_message)<0) return -1; - stun_attr_add_fingerprint_str(message.buf,(size_t*)&(message.len)); + stun_attr_add_fingerprint_str(request_message.buf,(size_t*)&(request_message.len)); while (!cb_sent) { - int len = send_buffer(clnet_info, &message, 1, atc); + int len = send_buffer(clnet_info, &request_message, 1, atc); if (len > 0) { if (verbose) { @@ -1465,10 +1454,9 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a { int cb_received = 0; - stun_buffer message; while (!cb_received) { - int len = recv_buffer(clnet_info, &message, 1, atc); + int len = recv_buffer(clnet_info, &response_message, 1, 1, atc, &request_message); if (len > 0) { if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, @@ -1476,21 +1464,21 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a } int err_code = 0; u08bits err_msg[129]; - if (stun_is_success_response(&message)) { + if (stun_is_success_response(&response_message)) { if(clnet_info->nonce[0] || use_short_term) { - if(check_integrity(clnet_info, &message)<0) + if(check_integrity(clnet_info, &response_message)<0) return -1; } - if(stun_get_method(&message)!=STUN_METHOD_CONNECTION_BIND) + if(stun_get_method(&response_message)!=STUN_METHOD_CONNECTION_BIND) continue; cb_received = 1; if (verbose) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "success\n"); } atc->tcp_data_bound = 1; - } else if (stun_is_challenge_response_str(message.buf, (size_t)message.len, + } else if (stun_is_challenge_response_str(response_message.buf, (size_t)response_message.len, &err_code,err_msg,sizeof(err_msg), clnet_info->realm,clnet_info->nonce, clnet_info->server_name, &(clnet_info->oauth))) { @@ -1499,7 +1487,7 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a recalculate_restapi_hmac(); } goto beg_cb; - } else if (stun_is_error_response(&message, &err_code,err_msg,sizeof(err_msg))) { + } else if (stun_is_error_response(&response_message, &err_code,err_msg,sizeof(err_msg))) { cb_received = 1; TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "connection bind error %d (%s)\n", err_code,(char*)err_msg); @@ -1522,7 +1510,11 @@ static int turn_tcp_connection_bind(int verbose, app_ur_conn_info *clnet_info, a void tcp_data_connect(app_ur_session *elem, u32bits cid) { - int clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); + int clnet_fd; + + again: + + clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, SOCK_STREAM, 0); if (clnet_fd < 0) { perror("socket"); exit(-1); @@ -1594,8 +1586,14 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid) } if(use_secure) { - elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr)); + int try_again = 0; + elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again); if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { + if(try_again) { + close(clnet_fd); + --elem->pinfo.tcp_conn_number; + goto again; + } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); diff --git a/src/apps/uclient/uclient.c b/src/apps/uclient/uclient.c index d7aa0db5..7403b880 100644 --- a/src/apps/uclient/uclient.c +++ b/src/apps/uclient/uclient.c @@ -40,6 +40,8 @@ #include #include +#include + static int verbose_packets=0; static size_t current_clients_number = 0; @@ -69,6 +71,8 @@ static app_ur_session** elems = NULL; #define SLEEP_INTERVAL (234) +#define MAX_LISTENING_CYCLE_NUMBER (7) + int RTP_PACKET_INTERVAL = 20; static inline s64bits time_minus(u64bits t1, u64bits t2) { @@ -302,11 +306,68 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con return ret; } -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, - app_tcp_conn_info *atc) { +static int wait_fd(int fd, unsigned int cycle) { + + if(fd>=(int)FD_SETSIZE) { + return 1; + } else { + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd,&fds); + + if(dos && cycle==0) + return 0; + + struct timeval start_time; + struct timeval ctime; + gettimeofday(&start_time,NULL); + + ctime.tv_sec = start_time.tv_sec; + ctime.tv_usec = start_time.tv_usec; + + int rc = 0; + + do { + struct timeval timeout = {0,0}; + if(cycle == 0) { + timeout.tv_usec = 500000; + } else { + + timeout.tv_sec = 1; + while(--cycle) timeout.tv_sec = timeout.tv_sec + timeout.tv_sec; + + if(ctime.tv_sec > start_time.tv_sec) { + if(ctime.tv_sec >= start_time.tv_sec + timeout.tv_sec) { + break; + } else { + timeout.tv_sec -= (ctime.tv_sec - start_time.tv_sec); + } + } + } + rc = select(fd+1,&fds,NULL,NULL,&timeout); + if((rc<0) && (errno == EINTR)) { + gettimeofday(&ctime,NULL); + } else { + break; + } + } while(1); + + return rc; + } +} + +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message) { int rc = 0; + stun_tid tid; + u16bits method = 0; + + if(request_message) { + stun_tid_from_message(request_message, &tid); + method = stun_get_method(request_message); + } + ioa_socket_raw fd = clnet_info->fd; if (atc) fd = atc->tcp_data_fd; @@ -315,6 +376,24 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, if (atc) ssl = atc->tcp_data_ssl; + recv_again: + + if(!use_tcp && sync && request_message && (fd>=0)) { + + unsigned int cycle = 0; + while(cycle < MAX_LISTENING_CYCLE_NUMBER) { + int serc = wait_fd(fd,cycle); + if(serc>0) + break; + if(serc<0) { + return -1; + } + if(send_buffer(clnet_info, request_message, data_connection, atc)<=0) + return -1; + ++cycle; + } + } + if (!use_secure && !use_tcp && fd >= 0) { /* Plain UDP */ @@ -331,9 +410,9 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, message->len = rc; - } else if (use_secure && ssl && !(clnet_info->broken)) { + } else if (use_secure && !use_tcp && ssl && !(clnet_info->broken)) { - /* TLS/DTLS */ + /* DTLS */ int message_received = 0; int cycle = 0; @@ -400,6 +479,74 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, } } + } else if (use_secure && use_tcp && ssl && !(clnet_info->broken)) { + + /* TLS*/ + + int message_received = 0; + int cycle = 0; + while (!message_received && cycle++ < 100) { + + if (SSL_get_shutdown(ssl)) + return -1; + rc = 0; + do { + rc = SSL_read(ssl, message->buf, sizeof(message->buf) - 1); + if (rc < 0 && errno == EAGAIN && sync) + continue; + } while (rc < 0 && (errno == EINTR)); + + if (rc > 0) { + + if (clnet_verbose) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "response received: size=%d\n", rc); + } + message->len = rc; + message_received = 1; + + } else { + + int sslerr = SSL_get_error(ssl, rc); + + switch (sslerr) { + case SSL_ERROR_NONE: + /* Try again ? */ + break; + case SSL_ERROR_WANT_WRITE: + /* Just try again later */ + break; + case SSL_ERROR_WANT_READ: + /* continue with reading */ + break; + case SSL_ERROR_ZERO_RETURN: + /* Try again */ + break; + case SSL_ERROR_SYSCALL: + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Socket read error 111.999: \n"); + if (handle_socket_error()) + break; + case SSL_ERROR_SSL: { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "SSL write error: \n"); + char buf[1024]; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s (%d)\n", + ERR_error_string(ERR_get_error(), buf), + SSL_get_error(ssl, rc)); + } + default: + clnet_info->broken = 1; + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, + "Unexpected error while reading: rc=%d, sslerr=%d\n", + rc, sslerr); + return -1; + } + + if (!sync) + break; + } + } + } else if (!use_secure && use_tcp && fd >= 0) { /* Plain TCP */ @@ -465,6 +612,27 @@ int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, } } + if(rc>0) { + if(request_message) { + + stun_tid recv_tid; + u16bits recv_method = 0; + + stun_tid_from_message(message, &recv_tid); + recv_method = stun_get_method(message); + + if(method != recv_method) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Received wrong response method: 0x%x, expected 0x%x; trying again...\n",(unsigned int)recv_method,(unsigned int)method); + goto recv_again; + } + + if(memcmp(tid.tsx_id,recv_tid.tsx_id,STUN_TID_SIZE)) { + TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Received wrong response tid; trying again...\n"); + goto recv_again; + } + } + } + return rc; } @@ -488,7 +656,7 @@ static int client_read(app_ur_session *elem, int is_tcp_data, app_tcp_conn_info TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "before read ...\n"); } - rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, atc); + rc = recv_buffer(clnet_info, &(elem->in_buffer), 0, is_tcp_data, atc, NULL); if (clnet_verbose && verbose_packets) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "read %d bytes\n", (int) rc); @@ -792,13 +960,13 @@ void client_input_handler(evutil_socket_t fd, short what, void* arg) { if(elem->pinfo.tcp_conn) { int i = 0; for(i=0;i<(int)(elem->pinfo.tcp_conn_number);++i) { - if(elem->pinfo.tcp_conn[i]) { - if((fd==elem->pinfo.tcp_conn[i]->tcp_data_fd) && (elem->pinfo.tcp_conn[i]->tcp_data_bound)) { - is_tcp_data = 1; - atc = elem->pinfo.tcp_conn[i]; - break; - } - } + if(elem->pinfo.tcp_conn[i]) { + if((fd==elem->pinfo.tcp_conn[i]->tcp_data_fd) && (elem->pinfo.tcp_conn[i]->tcp_data_bound)) { + is_tcp_data = 1; + atc = elem->pinfo.tcp_conn[i]; + break; + } + } } } int rc = client_read(elem, is_tcp_data, atc); diff --git a/src/apps/uclient/uclient.h b/src/apps/uclient/uclient.h index ea3958a1..43ff021d 100644 --- a/src/apps/uclient/uclient.h +++ b/src/apps/uclient/uclient.h @@ -99,7 +99,7 @@ void start_mclient(const char *remote_address, int port, int messagenumber, int mclient); int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_connection, app_tcp_conn_info *atc); -int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, app_tcp_conn_info *atc); +int recv_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int sync, int data_connection, app_tcp_conn_info *atc, stun_buffer* request_message); void client_input_handler(evutil_socket_t fd, short what, void* arg); diff --git a/src/ns_turn_defs.h b/src/ns_turn_defs.h index fc28026b..482b856c 100644 --- a/src/ns_turn_defs.h +++ b/src/ns_turn_defs.h @@ -31,7 +31,7 @@ #ifndef __IOADEFS__ #define __IOADEFS__ -#define TURN_SERVER_VERSION "4.2.2.2" +#define TURN_SERVER_VERSION "4.2.3.1" #define TURN_SERVER_VERSION_NAME "Monza" #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"