1
0
mirror of https://github.com/coturn/coturn.git synced 2026-05-05 10:46:10 +02:00

Imported Upstream version 4.2.3.1

This commit is contained in:
Oleg Moskalenko 2014-11-09 22:52:25 -08:00
parent fa7c546d6f
commit ae725add45
15 changed files with 323 additions and 169 deletions

View File

@ -1,3 +1,8 @@
11/07/2014 Oleg Moskalenko <mom040267@gmail.com>
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 <mom040267@gmail.com>
Version 4.2.2.2 'Monza':
- Black- and white- IP lists are divided per realm

View File

@ -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,

View File

@ -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.

2
TODO
View File

@ -105,7 +105,7 @@
==================================================================
nope
none
==================================================================

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 <mom040267@gmail.com>
- Sync to 4.2.3.1
* Sun Oct 26 2014 Oleg Moskalenko <mom040267@gmail.com>
- Sync to 4.2.2.2
* Sun Oct 05 2014 Oleg Moskalenko <mom040267@gmail.com>

View File

@ -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);
}
}
}

View File

@ -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*) &lt, 4);
stun_attr_add(&request_message, STUN_ATTRIBUTE_LIFETIME, (const char*) &lt, 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<addrnum;++addrindex) {
stun_attr_add_addr(&message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr+addrindex);
stun_attr_add_addr(&request_message, STUN_ATTRIBUTE_XOR_PEER_ADDRESS, peer_addr+addrindex);
}
}
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 (!cp_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) {
@ -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);

View File

@ -40,6 +40,8 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <sys/select.h>
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);

View File

@ -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);

View File

@ -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 "'"