Browse Source

Imported Upstream version 4.2.2.2

Oleg Moskalenko 11 years ago
parent
commit
fa7c546d6f

+ 12 - 1
ChangeLog

@@ -1,3 +1,14 @@
+10/26/2014 Oleg Moskalenko <[email protected]>
+Version 4.2.2.2 'Monza':
+	- Black- and white- IP lists are divided per realm
+		(the DB schema for those two tables changed);
+	- Updated Redis database schema.
+	- Debian UFW file added (Issue 1 fixed).
+	- TCP/TLS tests extended.
+	- Relay RTCP sockets ports allocation fixed.
+	- List of libraries cleaned.
+	- SSL renegotiation callback fixed.
+
 10/05/2014 Oleg Moskalenko <[email protected]>
 Version 4.2.1.2 'Monza':
 	- oAuth security experimental implementation;
@@ -13,7 +24,7 @@ Version 4.2.1.2 'Monza':
 	- Quota allocation fixed.
 	- Core dump fixed.
 	- Bandwidth allocation fixed.
-	- Memory code clening.
+	- Memory code cleaning.
 	- Logging fixed.
 	
 08/14/2014 Oleg Moskalenko <[email protected]>

+ 32 - 30
INSTALL

@@ -700,7 +700,7 @@ The schema description:
 # Table for long-term credentials mechanism authorization:
 #
 CREATE TABLE turnusers_lt (
-    realm varchar(512),
+    realm varchar(512) default '',
     name varchar(512),
     hmackey char(128),
     PRIMARY KEY (realm,name)
@@ -727,7 +727,7 @@ CREATE TABLE turnusers_st (
 # mechanism:
 #
 CREATE TABLE turn_secret (
-	realm varchar(512),
+	realm varchar(512) default '',
     value varchar(512),
 	primary key (realm,value)
 );
@@ -735,15 +735,17 @@ CREATE TABLE turn_secret (
 # Table holding "white" allowed peer IP ranges.
 #
 CREATE TABLE allowed_peer_ip (
+	realm varchar(512) default '',
 	ip_range varchar(256),
-	primary key (ip_range)
+	primary key (realm,ip_range)
 );
 
 # Table holding "black" denied peer IP ranges.
 #
 CREATE TABLE denied_peer_ip (
+	realm varchar(512) default '',
 	ip_range varchar(256),
-	primary key (ip_range)
+	primary key (realm,ip_range)
 );
 
 # Table to match origin to realm.
@@ -763,7 +765,7 @@ CREATE TABLE turn_origin_to_realm (
 # Values for them are integers (in text form).
 #
 CREATE TABLE turn_realm_option (
-	realm varchar(512),
+	realm varchar(512) default '',
 	opt varchar(32),
 	value varchar(128),
 	primary key (realm,opt)
@@ -842,7 +844,7 @@ Of course, the administrators can play with the connection string as they want.
 
 When starting the turnserver, the psql-userdb parameter will be, for example:
 
-turnserver ... --psql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
+turnserver ... --psql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30"
 
 Or, for 9.x PostgreSQL versions: 
 turnserver ... --psql-userdb=postgresql://username:password@/databasename ...
@@ -856,20 +858,20 @@ Fill in users, for example:
 
   Shared secret for the TURN REST API:
   
-  $ bin/turnadmin -s logen -e "host=localhost dbname=turn user=turn password=turn"
+  $ bin/turnadmin -s logen -e "host=localhost dbname=coturn user=turn password=turn"
   
   Long-term credentials mechanism:
   
-  $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
+  $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
   
   Long-term credentials mechanism with SHA256 extention:
-  $ bin/turnadmin -a -e "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
+  $ bin/turnadmin -a -e "host=localhost dbname=coturn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
   
   Short-term credentials mechanism:
    
-  $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -A -e "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
+  $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -A -e "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
 
 XV. MySQL (MariaDB) setup
 
@@ -911,20 +913,20 @@ the root account.
 
   Shared secret for the TURN REST API:
   
-  $ bin/turnadmin -s logen -M "host=localhost dbname=turn user=turn password=turn"
+  $ bin/turnadmin -s logen -M "host=localhost dbname=coturn user=turn password=turn"
   
   Long-term credentials mechanism:
   
-  $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
+  $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
   
   Long-term credentials mechanism with SHA256 extention:
-  $ bin/turnadmin -a -M "host=localhost dbname=turn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
+  $ bin/turnadmin -a -M "host=localhost dbname=coturn user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
   
   Short-term credentials mechanism:
    
-  $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -A -M "host=localhost dbname=turn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
+  $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -A -M "host=localhost dbname=coturn user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
 
 7) Now we can use mysql in the turnserver.
 
@@ -942,11 +944,11 @@ The format of the MySQL connection string is:
 So, an example of the MySQL database parameter in the TURN server command 
 line would be:
 
---mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
+--mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30"
 
 Or in the turnserver.conf file:
 
-mysql-userdb="host=localhost dbname=turn user=turn password=turn connect_timeout=30"
+mysql-userdb="host=localhost dbname=coturn user=turn password=turn connect_timeout=30"
 
 If you have to use a secure MySQL connection (SSL) then you have to use also
 the optional connection string parameters for the secure communications:
@@ -975,11 +977,11 @@ http://hergert.me/docs/mongo-c-driver/mongoc_uri.html:
 So, an example of the MongoDB database parameter in the TURN server command 
 line would be:
 
---mongo-userdb="mongodb://localhost:27017/turndb"
+--mongo-userdb="mongodb://localhost:27017/coturn"
 
 Or in the turnserver.conf file:
 
-mongo-userdb="mongodb://localhost:27017/turndb"
+mongo-userdb="mongodb://localhost:27017/coturn"
 
 The meanings of the MongoDB keys are the same as for the other databases, see the 
 explanations for the Postgres, for example.
@@ -1010,11 +1012,11 @@ connection string is:
 So, an example of the Redis database parameter in the TURN server command 
 line would be:
 
---redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30"
+--redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30"
 
 Or in the turnserver.conf file:
 
-redis-userdb="ip=127.0.0.1 dbname=0 password=turn connect_timeout=30"
+redis-userdb="ip=127.0.0.1 dbname=2 password=turn connect_timeout=30"
 
 Redis can be also used for the TURN allocation status check and for status and 
 traffic notifications.
@@ -1040,20 +1042,20 @@ Redis TURN admin commands:
 
   Shared secret for the TURN REST API:
   
-  $ bin/turnadmin -s logen -N "host=localhost dbname=0 user=turn password=turn"
+  $ bin/turnadmin -s logen -N "host=localhost dbname=2 user=turn password=turn"
   
   Long-term credentials mechanism:
   
-  $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
+  $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic
   
   Long-term credentials mechanism with SHA256 extention:
-  $ bin/turnadmin -a -N "host=localhost dbname=0 user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
+  $ bin/turnadmin -a -N "host=localhost dbname=2 user=turn password=turn" -u bethod -r north.gov -p king-of-north --sha256
   
   Short-term credentials mechanism:
    
-  $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u gorst -r north.gov -p hero
-  $ bin/turnadmin -A -N "host=localhost dbname=0 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
+  $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u gorst -r north.gov -p hero
+  $ bin/turnadmin -A -N "host=localhost dbname=2 user=turn password=turn" -u ninefingers -r north.gov -p youhavetoberealistic 
   
 See the file testredisdbsetup.sh for the data structure examples.
 

+ 3 - 2
TODO

@@ -47,7 +47,8 @@
 
 ==================================================================
 
-
+1) Per-realm black/white lists.
+ 
 ==================================================================
 
 ###   VI. STANDARDS SUPPORT   ###
@@ -104,7 +105,7 @@
 
 ==================================================================
 
-Nope
+nope
 
 ==================================================================
 

+ 13 - 4
configure

@@ -585,6 +585,7 @@ SYSTEM=`uname`
 if [ "${SYSTEM}" = "SunOS" ] ; then
 # Solaris ? is this you ?!
     OSCFLAGS="${OSCFLAGS} -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 -DTURN_NO_GETDOMAINNAME"
+    OSLIBS="${OSLIBS} -lnsl"
 fi
 
 #########################
@@ -823,8 +824,6 @@ fi
 ###########################
 
 testlib socket
-testlib nsl
-testlib dl
 testlib rt
 testlib wldap32
 ER=$?
@@ -952,13 +951,23 @@ fi
 testlib event_core
 ER=$?
 if ! [ ${ER} -eq 0 ] ; then
-    testlib event_extra
     ${ECHO_CMD} "Libevent2 runtime found."
+    testlib event_extra
+    ER=$?
+    if ! [ ${ER} -eq 0 ] ; then
+	${ECHO_CMD} "Libevent2 runtime 'extra' found."
+    else
+	${ECHO_CMD} "ERROR: Libevent2 'extra' runtime library is not installed properly in required location."
+	${ECHO_CMD} "See the INSTALL file."
+	${ECHO_CMD} "Abort."
+	cleanup
+	exit
+    fi
 else
     testlib event
     ER=$?
     if ! [ ${ER} -eq 0 ] ; then
-		${ECHO_CMD} "Libevent2 runtime found."
+		${ECHO_CMD} "Libevent2 runtime found (old style)."
     else
 		${ECHO_CMD} "ERROR: Libevent2 runtime libraries are not installed properly in required location."
 		${ECHO_CMD} "See the INSTALL file."

+ 4 - 0
debian/etc/ufw/applications.d/turnserver

@@ -0,0 +1,4 @@
+[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

+ 1 - 1
rpm/build.settings.sh

@@ -2,7 +2,7 @@
 
 # Common settings script.
 
-TURNVERSION=4.2.1.2
+TURNVERSION=4.2.2.2
 BUILDDIR=~/rpmbuild
 ARCH=`uname -p`
 TURNSERVER_SVN_URL=http://coturn.googlecode.com/svn

+ 3 - 1
rpm/turnserver.spec

@@ -1,5 +1,5 @@
 Name:		turnserver
-Version:	4.2.1.2
+Version:	4.2.2.2
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 
@@ -294,6 +294,8 @@ fi
 %{_includedir}/turn/client/TurnMsgLib.h
 
 %changelog
+* Sun Oct 26 2014 Oleg Moskalenko <[email protected]>
+  - Sync to 4.2.2.2
 * Sun Oct 05 2014 Oleg Moskalenko <[email protected]>
   - Sync to 4.2.1.2
 * Thu Aug 14 2014 Oleg Moskalenko <[email protected]>

+ 35 - 21
src/apps/common/ns_turn_utils.c

@@ -664,15 +664,13 @@ int get_canonic_origin(const char* o, char *co, int sz)
 #include <set>
 #include <string>
 
-using namespace std;
-
 static volatile int tmm_init = 0;
 static pthread_mutex_t tm;
 
 typedef void* ptrtype;
-typedef set<ptrtype> ptrs_t;
-typedef map<string,ptrs_t> str_to_ptrs_t;
-typedef map<ptrtype,string> ptr_to_str_t;
+typedef std::set<ptrtype> ptrs_t;
+typedef std::map<std::string,ptrs_t> str_to_ptrs_t;
+typedef std::map<ptrtype,std::string> ptr_to_str_t;
 
 static str_to_ptrs_t str_to_ptrs;
 static ptr_to_str_t ptr_to_str;
@@ -692,7 +690,7 @@ static void add_tm_ptr(void *ptr, const char *id) {
   if(!ptr)
     return;
 
-  string sid(id);
+  std::string sid(id);
 
   str_to_ptrs_t::iterator iter;
 
@@ -701,7 +699,7 @@ static void add_tm_ptr(void *ptr, const char *id) {
   iter = str_to_ptrs.find(sid);
 
   if(iter == str_to_ptrs.end()) {
-    set<ptrtype> sp;
+    std::set<ptrtype> sp;
     sp.insert(ptr);
     str_to_ptrs[sid]=sp;
   } else {
@@ -730,7 +728,7 @@ static void del_tm_ptr(void *ptr, const char *id) {
 
   } else {
 
-    string sid = pts_iter->second;
+    std::string sid = pts_iter->second;
     ptr_to_str.erase(pts_iter);
 
     str_to_ptrs_t::iterator iter = str_to_ptrs.find(sid);
@@ -749,11 +747,27 @@ static void del_tm_ptr(void *ptr, const char *id) {
   pthread_mutex_unlock(&tm);
 }
 
-static void tm_id(char *id, const char* file, int line) {
-  sprintf(id,"%s:%d",file,line);
+static void tm_id(char *id, const char* function, int line) {
+  sprintf(id,"%s:%d",function,line);
+}
+
+#define TM_START() char id[128];tm_id(id,function,line);tm_init()
+
+extern "C" void* debug_ptr_add_func(void *ptr, const char* function, int line) {
+
+	TM_START();
+
+	add_tm_ptr(ptr,id);
+
+	return ptr;
 }
 
-#define TM_START() char id[128];tm_id(id,file,line);tm_init()
+extern "C" void debug_ptr_del_func(void *ptr, const char* function, int line) {
+
+	TM_START();
+
+	del_tm_ptr(ptr,id);
+}
 
 extern "C" void tm_print_func(void);
 void tm_print_func(void) {
@@ -767,8 +781,8 @@ void tm_print_func(void) {
   pthread_mutex_unlock(&tm);
 } 
 
-extern "C" void *turn_malloc_func(size_t sz, const char* file, int line);
-void *turn_malloc_func(size_t sz, const char* file, int line) {
+extern "C" void *turn_malloc_func(size_t sz, const char* function, int line);
+void *turn_malloc_func(size_t sz, const char* function, int line) {
 
   TM_START();
 
@@ -779,8 +793,8 @@ void *turn_malloc_func(size_t sz, const char* file, int line) {
   return ptr;
 }
 
-extern "C" void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line);
-void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line) {
+extern "C" void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line);
+void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line) {
 
   UNUSED_ARG(old_sz);
 
@@ -796,8 +810,8 @@ void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* fil
   return ptr;
 }
 
-extern "C" void turn_free_func(void *ptr, size_t sz, const char* file, int line);
-void turn_free_func(void *ptr, size_t sz, const char* file, int line) {
+extern "C" void turn_free_func(void *ptr, size_t sz, const char* function, int line);
+void turn_free_func(void *ptr, size_t sz, const char* function, int line) {
 
   UNUSED_ARG(sz);
 
@@ -818,8 +832,8 @@ void turn_free_simple(void *ptr) {
   free(ptr);
 }
 
-extern "C" void *turn_calloc_func(size_t number, size_t size, const char* file, int line);
-void *turn_calloc_func(size_t number, size_t size, const char* file, int line) {
+extern "C" void *turn_calloc_func(size_t number, size_t size, const char* function, int line);
+void *turn_calloc_func(size_t number, size_t size, const char* function, int line) {
   
   TM_START();
 
@@ -830,8 +844,8 @@ void *turn_calloc_func(size_t number, size_t size, const char* file, int line) {
   return ptr;
 }
 
-extern "C" char *turn_strdup_func(const char* s, const char* file, int line);
-char *turn_strdup_func(const char* s, const char* file, int line) {
+extern "C" char *turn_strdup_func(const char* s, const char* function, int line);
+char *turn_strdup_func(const char* s, const char* function, int line) {
 
   TM_START();
 

+ 72 - 40
src/apps/relay/dbdrivers/dbd_mongo.c

@@ -969,48 +969,80 @@ static void mongo_auth_ping(void * rch) {
 	UNUSED_ARG(rch);
   // NOOP
 }
-  
-static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) {
-  char * collection_name = 	(char *)turn_malloc(strlen(kind) + 9);
-  sprintf(collection_name, "%s_peer_ip", kind);
-  mongoc_collection_t * collection = mongo_get_collection(collection_name); 
-  turn_free(collection_name, strlen(kind) + 9);
 
-	if(!collection)
-    return -1;
-    
-  bson_t query;
-  bson_init(&query);
-  
-  bson_t fields;
-  bson_init(&fields);
-  BSON_APPEND_INT32(&fields, "ip_range", 1);
-  
-  mongoc_cursor_t * cursor;
-  cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, &query, &fields, NULL);
-  
-  int ret = -1;
+static int mongo_read_realms_ip_lists(const char *kind, ip_range_list_t * list)
+{
+	int ret = 0;
+
+	char field_name[129];
+	sprintf(field_name, "%s_peer_ip", kind);
+
+	mongoc_collection_t * collection = mongo_get_collection("realm");
+
+	if (!collection)
+		return ret;
+
+	bson_t query;
+	bson_init(&query);
+
+	bson_t fields;
+	bson_init(&fields);
+	BSON_APPEND_INT32(&fields, "realm", 1);
+	BSON_APPEND_INT32(&fields, field_name, 1);
+
+	mongoc_cursor_t * cursor;
+	cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0,
+			&query, &fields, NULL);
+
+	if (!cursor) {
+		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
+				"Error querying MongoDB collection 'realm'\n");
+		ret = -1;
+	} else {
+		const bson_t * item;
+		uint32_t length;
+		bson_iter_t iter;
+		char realm[513];
+
+		while (mongoc_cursor_next(cursor, &item)) {
+
+			if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "realm")
+					&& BSON_ITER_HOLDS_UTF8(&iter)) {
+
+				STRCPY(realm,bson_iter_utf8(&iter, &length));
+
+				if (bson_iter_init(&iter, item) && bson_iter_find(&iter,
+						field_name) && BSON_ITER_HOLDS_ARRAY(&iter)) {
+					const uint8_t *docbuf = NULL;
+					uint32_t doclen = 0;
+					bson_t ip_range_array;
+					bson_iter_t ip_range_iter;
+
+					bson_iter_array(&iter, &doclen, &docbuf);
+					bson_init_static(&ip_range_array, docbuf, doclen);
+
+					if (bson_iter_init(&ip_range_iter, &ip_range_array)) {
+						while (bson_iter_next(&ip_range_iter)) {
+							if (BSON_ITER_HOLDS_UTF8(&ip_range_iter)) {
+								const char* ip_range = bson_iter_utf8(&ip_range_iter, &length);
+								add_ip_list_range(ip_range, realm, list);
+							}
+						}
+					}
+				}
+			}
+		}
+		mongoc_cursor_destroy(cursor);
+	}
+	mongoc_collection_destroy(collection);
+	bson_destroy(&query);
+	bson_destroy(&fields);
+
+	return ret;
+}
   
-  if (!cursor) {
-		TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error querying MongoDB collection '%s'\n", collection_name);
-  } else {
-    const bson_t * item;
-    uint32_t length;
-    bson_iter_t iter;
-    const char * value;
-    while(mongoc_cursor_next(cursor, &item)) {
-    	if (bson_iter_init(&iter, item) && bson_iter_find(&iter, "ip_range") && BSON_ITER_HOLDS_UTF8(&iter)) {
-        value = bson_iter_utf8(&iter, &length);
-		add_ip_list_range(value, list);
-      }
-    }
-    mongoc_cursor_destroy(cursor);
-    ret = 0;
-  }
-  mongoc_collection_destroy(collection);
-  bson_destroy(&query);
-  bson_destroy(&fields);
-  return ret;
+static int mongo_get_ip_list(const char *kind, ip_range_list_t * list) {
+	return mongo_read_realms_ip_lists(kind, list);
 }
   
 

+ 18 - 3
src/apps/relay/dbdrivers/dbd_mysql.c

@@ -896,11 +896,22 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) {
 	MYSQL * myc = get_mydb_connection();
 	if(myc) {
 		char statement[TURN_LONG_STRING_SIZE];
-		snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
+		snprintf(statement,sizeof(statement),"select ip_range,realm from %s_peer_ip",kind);
 		int res = mysql_query(myc, statement);
+
+		if(res) {
+			static int wrong_table_reported = 0;
+			if(!wrong_table_reported) {
+				wrong_table_reported = 1;
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving MySQL DB information; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n");
+			}
+			snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
+			res = mysql_query(myc, statement);
+		}
+
 		if(res == 0) {
 			MYSQL_RES *mres = mysql_store_result(myc);
-			if(mres && mysql_field_count(myc)==1) {
+			if(mres && mysql_field_count(myc)==2) {
 				for(;;) {
 					MYSQL_ROW row = mysql_fetch_row(mres);
 					if(!row) {
@@ -913,7 +924,11 @@ static int mysql_get_ip_list(const char *kind, ip_range_list_t * list) {
 								char kval[TURN_LONG_STRING_SIZE];
 								ns_bcopy(row[0],kval,sz);
 								kval[sz]=0;
-								add_ip_list_range(kval,list);
+								sz = lengths[1];
+								char rval[TURN_LONG_STRING_SIZE];
+								ns_bcopy(row[1],rval,sz);
+								rval[sz]=0;
+								add_ip_list_range(kval,rval,list);
 							}
 						}
 					}

+ 25 - 12
src/apps/relay/dbdrivers/dbd_pgsql.c

@@ -645,30 +645,43 @@ static void pgsql_auth_ping(void * rch) {
 	}
 }
   
-static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list) {
-  int ret = -1;
+
+static int pgsql_get_ip_list(const char *kind, ip_range_list_t * list)
+{
+	int ret = -1;
 	PGconn * pqc = get_pqdb_connection();
-	if(pqc) {
+	if (pqc) {
 		char statement[TURN_LONG_STRING_SIZE];
-		snprintf(statement,sizeof(statement),"select ip_range from %s_peer_ip",kind);
+		snprintf(statement, sizeof(statement), "select ip_range,realm from %s_peer_ip", kind);
 		PGresult *res = PQexec(pqc, statement);
 
-		if(res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
+		if (!res || (PQresultStatus(res) != PGRES_TUPLES_OK)) {
+			static int wrong_table_reported = 0;
+			if(!wrong_table_reported) {
+				wrong_table_reported = 1;
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error retrieving PostgreSQL DB information: %s; probably, the tables 'allowed_peer_ip' and/or 'denied_peer_ip' have to be upgraded to include the realm column.\n",PQerrorMessage(pqc));
+			}
+			snprintf(statement, sizeof(statement), "select ip_range,'' from %s_peer_ip", kind);
+			res = PQexec(pqc, statement);
+		}
+
+		if (res && (PQresultStatus(res) == PGRES_TUPLES_OK)) {
 			int i = 0;
-			for(i=0;i<PQntuples(res);i++) {
-				char *kval = PQgetvalue(res,i,0);
-				if(kval) {
-					add_ip_list_range(kval,list);
+			for (i = 0; i < PQntuples(res); i++) {
+				char *kval = PQgetvalue(res, i, 0);
+				char *rval = PQgetvalue(res, i, 1);
+				if (kval) {
+					add_ip_list_range(kval, rval, list);
 				}
 			}
-      ret = 0;
+			ret = 0;
 		}
 
-		if(res) {
+		if (res) {
 			PQclear(res);
 		}
 	}
-  return ret;
+	return ret;
 }
   
 static void pgsql_reread_realms(secrets_list_t * realms_list) {

+ 91 - 125
src/apps/relay/dbdrivers/dbd_redis.c

@@ -396,18 +396,13 @@ static int set_redis_realm_opt(char *realm, const char* key, unsigned long *valu
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
-  int ret = -1;
+static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm)
+{
+	int ret = -1;
 	redisContext *rc = get_redis_connection();
-	if(rc) {
-		redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm);
-		if(reply) {
-
-			secrets_list_t keys;
-			size_t isz = 0;
-			char s[257];
-
-			init_secrets_list(&keys);
+	if (rc) {
+		redisReply *reply = (redisReply*) redisCommand(rc, "smembers turn/realm/%s/secret", (char*) realm);
+		if (reply) {
 
 			if (reply->type == REDIS_REPLY_ERROR)
 				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
@@ -417,34 +412,16 @@ static int redis_get_auth_secrets(secrets_list_t *sl, u08bits *realm) {
 			} else {
 				size_t i;
 				for (i = 0; i < reply->elements; ++i) {
-					add_to_secrets_list(&keys,reply->element[i]->str);
+					add_to_secrets_list(sl, reply->element[i]->str);
 				}
 			}
 
-			for(isz=0;isz<keys.sz;++isz) {
-				snprintf(s,sizeof(s),"get %s", keys.secrets[isz]);
-				redisReply *rget = (redisReply *)redisCommand(rc, s);
-				if(rget) {
-					if (rget->type == REDIS_REPLY_ERROR)
-						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
-					else if (rget->type != REDIS_REPLY_STRING) {
-						if (rget->type != REDIS_REPLY_NIL)
-							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
-					} else {
-						add_to_secrets_list(sl,rget->str);
-					}
-					turnFreeRedisReply(rget);
-				}
-			}
-
-			clean_secrets_list(&keys);
-
 			ret = 0;
 
 			turnFreeRedisReply(reply);
 		}
 	}
-  return ret;
+	return ret;
 }
   
 static int redis_get_user_key(u08bits *usname, u08bits *realm, hmackey_t key) {
@@ -780,18 +757,20 @@ static int redis_list_oauth_keys(void) {
   return ret;
 }
   
-static int redis_show_secret(u08bits *realm) {
-  int ret = -1;
+
+static int redis_show_secret(u08bits *realm)
+{
+	int ret = -1;
 	donot_print_connection_success = 1;
 	redisContext *rc = get_redis_connection();
-	if(rc) {
+	if (rc) {
 		redisReply *reply = NULL;
-		if(realm && realm[0]) {
-			reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*",(char*)realm);
+		if (realm && realm[0]) {
+			reply = (redisReply*) redisCommand(rc, "keys turn/realm/%s/secret", (char*) realm);
 		} else {
-			reply = (redisReply*)redisCommand(rc, "keys turn/realm/*/secret/*");
+			reply = (redisReply*) redisCommand(rc, "keys turn/realm/*/secret");
 		}
-		if(reply) {
+		if (reply) {
 			secrets_list_t keys;
 			size_t isz = 0;
 			char s[257];
@@ -806,21 +785,26 @@ static int redis_show_secret(u08bits *realm) {
 			} else {
 				size_t i;
 				for (i = 0; i < reply->elements; ++i) {
-					add_to_secrets_list(&keys,reply->element[i]->str);
+					add_to_secrets_list(&keys, reply->element[i]->str);
 				}
 			}
 
-			for(isz=0;isz<keys.sz;++isz) {
-				snprintf(s,sizeof(s),"get %s", keys.secrets[isz]);
-				redisReply *rget = (redisReply *)redisCommand(rc, s);
-				if(rget) {
-					if (rget->type == REDIS_REPLY_ERROR)
+			for (isz = 0; isz < keys.sz; ++isz) {
+				snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]);
+				redisReply *rget = (redisReply *) redisCommand(rc, s);
+				if (rget) {
+					if (rget->type == REDIS_REPLY_ERROR) {
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
-					else if (rget->type != REDIS_REPLY_STRING) {
+					} else if (rget->type == REDIS_REPLY_STRING) {
+						printf("%s\n", rget->str);
+					} else if (rget->type != REDIS_REPLY_ARRAY) {
 						if (rget->type != REDIS_REPLY_NIL)
 							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
 					} else {
-						printf("%s\n",rget->str);
+						size_t i;
+						for (i = 0; i < rget->elements; ++i) {
+							printf("%s\n", rget->element[i]->str);
+						}
 					}
 				}
 				turnFreeRedisReply(rget);
@@ -829,88 +813,44 @@ static int redis_show_secret(u08bits *realm) {
 			clean_secrets_list(&keys);
 
 			turnFreeRedisReply(reply);
-      ret = 0;
+			ret = 0;
 		}
 	}
-  return ret;
+	return ret;
 }
   
-static int redis_del_secret(u08bits *secret, u08bits *realm) {
-  int ret = -1;
+
+static int redis_del_secret(u08bits *secret, u08bits *realm)
+{
+	int ret = -1;
 	donot_print_connection_success = 1;
 	redisContext *rc = get_redis_connection();
-	if(rc) {
-		redisReply *reply = (redisReply*)redisCommand(rc, "keys turn/realm/%s/secret/*", (char*)realm);
-		if(reply) {
-			secrets_list_t keys;
-			size_t isz = 0;
-			char s[TURN_LONG_STRING_SIZE];
-
-			init_secrets_list(&keys);
-
-			if (reply->type == REDIS_REPLY_ERROR)
-				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", reply->str);
-			else if (reply->type != REDIS_REPLY_ARRAY) {
-				if (reply->type != REDIS_REPLY_NIL)
-					TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", reply->type);
-			} else {
-				size_t i;
-				for (i = 0; i < reply->elements; ++i) {
-					add_to_secrets_list(&keys,reply->element[i]->str);
-				}
-			}
-
-			for(isz=0;isz<keys.sz;++isz) {
-				if(!secret || (secret[0]==0)) {
-					snprintf(s,sizeof(s),"del %s", keys.secrets[isz]);
-					turnFreeRedisReply(redisCommand(rc, s));
-				} else {
-					snprintf(s,sizeof(s),"get %s", keys.secrets[isz]);
-					redisReply *rget = (redisReply *)redisCommand(rc, s);
-					if(rget) {
-						if (rget->type == REDIS_REPLY_ERROR)
-							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
-						else if (rget->type != REDIS_REPLY_STRING) {
-							if (rget->type != REDIS_REPLY_NIL)
-								TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
-						} else {
-							if(!strcmp((char*)secret,rget->str)) {
-								snprintf(s,sizeof(s),"del %s", keys.secrets[isz]);
-								turnFreeRedisReply(redisCommand(rc, s));
-							}
-						}
-						turnFreeRedisReply(rget);
-					}
-				}
-			}
-
-			turnFreeRedisReply(redisCommand(rc, "save"));
-
-			clean_secrets_list(&keys);
-
-			turnFreeRedisReply(reply);
-      ret = 0;
-		}
+	if (rc) {
+		turnFreeRedisReply(redisCommand(rc, "srem turn/realm/%s/secret %s", (char*) realm, (char*) secret));
+		turnFreeRedisReply(redisCommand(rc, "save"));
+		ret = 0;
 	}
-  return ret;
+	return ret;
 }
   
-static int redis_set_secret(u08bits *secret, u08bits *realm) {
-  int ret = -1;
+
+static int redis_set_secret(u08bits *secret, u08bits *realm)
+{
+	int ret = -1;
 	donot_print_connection_success = 1;
 	redisContext *rc = get_redis_connection();
-	if(rc) {
+	if (rc) {
 		char s[TURN_LONG_STRING_SIZE];
 
 		redis_del_secret(secret, realm);
 
-		snprintf(s,sizeof(s),"set turn/realm/%s/secret/%lu %s", (char*)realm, (unsigned long)turn_time(), secret);
+		snprintf(s, sizeof(s), "sadd turn/realm/%s/secret %s", (char*) realm, secret);
 
 		turnFreeRedisReply(redisCommand(rc, s));
 		turnFreeRedisReply(redisCommand(rc, "save"));
-    ret = 0;
+		ret = 0;
 	}
-  return ret;
+	return ret;
 }
   
 static int redis_add_origin(u08bits *origin, u08bits *realm) {
@@ -1094,14 +1034,19 @@ static void redis_auth_ping(void * rch) {
 		send_message_to_redis((redis_context_handle)rch, "publish", "__XXX__", "__YYY__");
 }
   
-static int redis_get_ip_list(const char *kind, ip_range_list_t * list) {
-  int ret = -1;
+
+
+static int redis_get_ip_list(const char *kind, ip_range_list_t * list)
+{
+	int ret = -1;
 	redisContext *rc = get_redis_connection();
-	if(rc) {
+	if (rc) {
 		char statement[TURN_LONG_STRING_SIZE];
-		snprintf(statement,sizeof(statement),"keys turn/%s-peer-ip/*", kind);
-		redisReply *reply = (redisReply*)redisCommand(rc, statement);
-		if(reply) {
+		const char* header = "turn/realm/";
+		size_t header_len = strlen(header);
+		snprintf(statement, sizeof(statement), "keys %s*/%s-peer-ip", header,kind);
+		redisReply *reply = (redisReply*) redisCommand(rc, statement);
+		if (reply) {
 			secrets_list_t keys;
 			size_t isz = 0;
 			char s[257];
@@ -1116,33 +1061,54 @@ static int redis_get_ip_list(const char *kind, ip_range_list_t * list) {
 			} else {
 				size_t i;
 				for (i = 0; i < reply->elements; ++i) {
-					add_to_secrets_list(&keys,reply->element[i]->str);
+					add_to_secrets_list(&keys, reply->element[i]->str);
 				}
 			}
 
-			for(isz=0;isz<keys.sz;++isz) {
-				snprintf(s,sizeof(s),"get %s", keys.secrets[isz]);
-				redisReply *rget = (redisReply *)redisCommand(rc, s);
-				if(rget) {
-					if (rget->type == REDIS_REPLY_ERROR)
+			for (isz = 0; isz < keys.sz; ++isz) {
+
+				char *realm = NULL;
+
+				snprintf(s, sizeof(s), "smembers %s", keys.secrets[isz]);
+
+				redisReply *rget = (redisReply *) redisCommand(rc, s);
+
+				char *ptr = ((char*)keys.secrets[isz])+header_len;
+				char *sep = strstr(ptr, "/");
+				if (sep) {
+					*sep = 0;
+					realm = ptr;
+				}
+
+				if (rget) {
+					if (rget->type == REDIS_REPLY_ERROR) {
 						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error: %s\n", rget->str);
-					else if (rget->type != REDIS_REPLY_STRING) {
+					} else if (rget->type == REDIS_REPLY_STRING) {
+						add_ip_list_range(rget->str, realm, list);
+					} else if (rget->type != REDIS_REPLY_ARRAY) {
 						if (rget->type != REDIS_REPLY_NIL)
 							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Unexpected type: %d\n", rget->type);
 					} else {
-						add_ip_list_range(rget->str,list);
+						size_t i;
+						for (i = 0; i < rget->elements; ++i) {
+							add_ip_list_range(rget->element[i]->str, realm, list);
+						}
 					}
 					turnFreeRedisReply(rget);
 				}
+
+				if(sep) {
+					*sep='/';
+				}
 			}
 
 			clean_secrets_list(&keys);
 
 			turnFreeRedisReply(reply);
-      ret = 0;
+			ret = 0;
 		}
 	}
-  return ret;
+	return ret;
 }
   
 static void redis_reread_realms(secrets_list_t * realms_list) {

+ 4 - 4
src/apps/relay/dtls_listener.c

@@ -266,7 +266,7 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty
 	timeout.tv_usec = 0;
 	BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
 
-	connecting_ssl = SSL_new(server->dtls_ctx);
+	connecting_ssl = SSL_NEW(server->dtls_ctx);
 
 	SSL_set_accept_state(connecting_ssl);
 
@@ -285,7 +285,7 @@ static ioa_socket_handle dtls_server_input_handler(dtls_listener_relay_server_ty
 			SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN);
 			SSL_shutdown(connecting_ssl);
 		}
-		SSL_free(connecting_ssl);
+		SSL_FREE(connecting_ssl);
 	}
 
 	return rc;
@@ -536,7 +536,7 @@ static int create_new_connected_udp_socket(
 		timeout.tv_usec = 0;
 		BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
 
-		connecting_ssl = SSL_new(server->dtls_ctx);
+		connecting_ssl = SSL_NEW(server->dtls_ctx);
 
 		SSL_set_accept_state(connecting_ssl);
 
@@ -552,7 +552,7 @@ static int create_new_connected_udp_socket(
 				SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN);
 				SSL_shutdown(connecting_ssl);
 			}
-			SSL_free(connecting_ssl);
+			SSL_FREE(connecting_ssl);
 			IOA_CLOSE_SOCKET(ret);
 			return -1;
 		}

+ 8 - 6
src/apps/relay/mainrelay.c

@@ -77,7 +77,7 @@ DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
 {
   NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,NULL,NULL,NULL
 },
-{NULL, NULL, 0},{NULL, NULL, 0},
+{NULL, 0},{NULL, 0},
 NEV_UNKNOWN, 
 { "Unknown", "UDP listening socket per session", "UDP thread per network endpoint", "UDP thread per CPU core" },
 //////////////// Relay servers //////////////////////////////////
@@ -1230,10 +1230,10 @@ static void set_option(int c, char *value)
 		add_tls_alternate_server(value);
 		break;
 	case ALLOWED_PEER_IPS:
-		if (add_ip_list_range(value, &turn_params.ip_whitelist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "White listing: %s\n", value);
+		if (add_ip_list_range(value, NULL, &turn_params.ip_whitelist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "White listing: %s\n", value);
 		break;
 	case DENIED_PEER_IPS:
-		if (add_ip_list_range(value, &turn_params.ip_blacklist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Black listing: %s\n", value);
+		if (add_ip_list_range(value, NULL, &turn_params.ip_blacklist) == 0) TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Black listing: %s\n", value);
 		break;
 	case CIPHER_LIST_OPT:
 		STRCPY(turn_params.cipher_list,value);
@@ -1701,9 +1701,11 @@ static void drop_privileges(void)
 static void init_domain(void)
 {
 #if !defined(TURN_NO_GETDOMAINNAME)
-	getdomainname(turn_params.domain,sizeof(turn_params.domain)-1);
-	if(!strcmp(turn_params.domain,"(none)")) 
-	  turn_params.domain[0]=0;
+	if(getdomainname(turn_params.domain,sizeof(turn_params.domain)-1)<0) {
+		turn_params.domain[0]=0;
+	} else if(!strcmp(turn_params.domain,"(none)")) {
+		turn_params.domain[0]=0;
+	}
 #endif
 }
 

+ 4 - 13
src/apps/relay/netengine.c

@@ -1005,11 +1005,8 @@ static void setup_listener(void)
 
 	{
 		struct bufferevent *pair[2];
-		int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS;
 
-		opts |= BEV_OPT_THREADSAFE;
-
-		bufferevent_pair_new(turn_params.listener.event_base, opts, pair);
+		bufferevent_pair_new(turn_params.listener.event_base, TURN_BUFFEREVENTS_OPTIONS, pair);
 		turn_params.listener.in_buf = pair[0];
 		turn_params.listener.out_buf = pair[1];
 		bufferevent_setcb(turn_params.listener.in_buf, listener_receive_message, NULL, NULL, &turn_params.listener);
@@ -1548,7 +1545,6 @@ void run_listener_server(struct listener_server *ls)
 static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int to_set_rfc5780)
 {
 	struct bufferevent *pair[2];
-	int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS;
 
 	if(e) {
 		rs->event_base = e->event_base;
@@ -1573,15 +1569,13 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
 		ioa_engine_set_rtcp_map(rs->ioa_eng, turn_params.listener.rtcpmap);
 	}
 
-	opts |= BEV_OPT_THREADSAFE;
-
-	bufferevent_pair_new(rs->event_base, opts, pair);
+	bufferevent_pair_new(rs->event_base, TURN_BUFFEREVENTS_OPTIONS, pair);
 	rs->in_buf = pair[0];
 	rs->out_buf = pair[1];
 	bufferevent_setcb(rs->in_buf, relay_receive_message, NULL, NULL, rs);
 	bufferevent_enable(rs->in_buf, EV_READ);
 
-	bufferevent_pair_new(rs->event_base, opts, pair);
+	bufferevent_pair_new(rs->event_base, TURN_BUFFEREVENTS_OPTIONS, pair);
 	rs->auth_in_buf = pair[0];
 	rs->auth_out_buf = pair[1];
 	bufferevent_setcb(rs->auth_in_buf, relay_receive_auth_message, NULL, NULL, rs);
@@ -1683,11 +1677,8 @@ static void* run_auth_server_thread(void *arg)
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (auth thread): %s\n",event_base_get_method(turn_params.authserver.event_base));
 
 	struct bufferevent *pair[2];
-	int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS;
-
-	opts |= BEV_OPT_THREADSAFE;
 
-	bufferevent_pair_new(turn_params.authserver.event_base, opts, pair);
+	bufferevent_pair_new(turn_params.authserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair);
 	turn_params.authserver.in_buf = pair[0];
 	turn_params.authserver.out_buf = pair[1];
 	bufferevent_setcb(turn_params.authserver.in_buf, auth_server_receive_message, NULL, NULL, &turn_params.authserver);

+ 76 - 103
src/apps/relay/ns_ioalib_engine_impl.c

@@ -681,12 +681,11 @@ static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read)
 	return 1;
 }
 
-int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s)
+int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm)
 {
   if (e && in_reservation_token && s) {
-    *s = rtcp_map_get(e->map_rtcp, in_reservation_token);
+    *s = rtcp_map_get(e->map_rtcp, in_reservation_token, realm);
     if (*s) {
-      rtcp_map_del_savefd(e->map_rtcp, in_reservation_token);
       return 0;
     }
   }
@@ -1166,12 +1165,17 @@ int create_relay_ioa_sockets(ioa_engine_handle e,
 										(transport == STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE) ? TCP_SOCKET : UDP_SOCKET,
 										RELAY_SOCKET);
 				if (*rtp_s == NULL) {
-					if (rtcp_s)
+					int rtcp_bound = 0;
+					if (rtcp_s && *rtcp_s) {
+						rtcp_bound = (*rtcp_s)->bound;
 						IOA_CLOSE_SOCKET(*rtcp_s);
+					}
 					addr_set_port(&local_addr, port);
 					turnipports_release(tp, transport, &local_addr);
-					if (rtcp_port >= 0)
+					if (rtcp_port >= 0 && !rtcp_bound) {
+						addr_set_port(&rtcp_local_addr, rtcp_port);
 						turnipports_release(tp, transport, &rtcp_local_addr);
+					}
 					perror("socket");
 					return -1;
 				}
@@ -1184,12 +1188,17 @@ int create_relay_ioa_sockets(ioa_engine_handle e,
 					break;
 				} else {
 					IOA_CLOSE_SOCKET(*rtp_s);
-					if (rtcp_s)
+					int rtcp_bound = 0;
+					if (rtcp_s && *rtcp_s) {
+						rtcp_bound = (*rtcp_s)->bound;
 						IOA_CLOSE_SOCKET(*rtcp_s);
+					}
 					addr_set_port(&local_addr, port);
 					turnipports_release(tp, transport, &local_addr);
-					if (rtcp_port >= 0)
+					if (rtcp_port >= 0 && !rtcp_bound) {
+						addr_set_port(&rtcp_local_addr, rtcp_port);
 						turnipports_release(tp, transport, &rtcp_local_addr);
+					}
 					rtcp_port = -1;
 				}
 			}
@@ -1305,11 +1314,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr)
 		if (events & BEV_EVENT_CONNECTED) {
 			ret->conn_cb = NULL;
 			ret->conn_arg = NULL;
-			if(ret->conn_bev) {
-				bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE);
-				bufferevent_free(ret->conn_bev);
-				ret->conn_bev=NULL;
-			}
+			BUFFEREVENT_FREE(ret->conn_bev);
 			ret->connected = 1;
 			if(cb) {
 				cb(1,arg);
@@ -1318,11 +1323,7 @@ static void connect_eventcb(struct bufferevent *bev, short events, void *ptr)
 			/* An error occured while connecting. */
 			ret->conn_cb = NULL;
 			ret->conn_arg = NULL;
-			if(ret->conn_bev) {
-				bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE);
-				bufferevent_free(ret->conn_bev);
-				ret->conn_bev=NULL;
-			}
+			BUFFEREVENT_FREE(ret->conn_bev);
 			if(cb) {
 				cb(0,arg);
 			}
@@ -1364,15 +1365,12 @@ ioa_socket_handle ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, io
 
 	set_ioa_socket_session(ret, s->session);
 
-	if(ret->conn_bev) {
-		bufferevent_disable(ret->conn_bev,EV_READ|EV_WRITE);
-		bufferevent_free(ret->conn_bev);
-		ret->conn_bev=NULL;
-	}
+	BUFFEREVENT_FREE(ret->conn_bev);
 
 	ret->conn_bev = bufferevent_socket_new(ret->e->event_base,
 					ret->fd,
-					BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+					TURN_BUFFEREVENTS_OPTIONS);
+	debug_ptr_add(ret->conn_bev);
 	bufferevent_setcb(ret->conn_bev, NULL, NULL, connect_eventcb, ret);
 
 	ret->conn_arg = arg;
@@ -1450,8 +1448,6 @@ void add_socket_to_map(ioa_socket_handle s, ur_addr_map *amap)
 				&(s->remote_addr),
 				(ur_addr_map_value_type)s);
 		s->sockets_container = amap;
-
-		//printf("%s: 111.111: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap));
 	}
 }
 
@@ -1459,14 +1455,10 @@ void delete_socket_from_map(ioa_socket_handle s)
 {
 	if(s && s->sockets_container) {
 
-		//ur_addr_map *amap = s->sockets_container;
-
 		ur_addr_map_del(s->sockets_container,
 				&(s->remote_addr),
 				NULL);
 		s->sockets_container = NULL;
-
-		//printf("%s: 111.222: amap=0x%lx: ne=%lu, sz=%lu\n",__FUNCTION__,(unsigned long)amap,(unsigned long)ur_addr_map_num_elements(amap),(unsigned long)ur_addr_map_size(amap));
 	}
 }
 
@@ -1577,16 +1569,8 @@ static void close_socket_net_data(ioa_socket_handle s)
 			evconnlistener_free(s->list_ev);
 			s->list_ev = NULL;
 		}
-		if(s->conn_bev) {
-			bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE);
-			bufferevent_free(s->conn_bev);
-			s->conn_bev=NULL;
-		}
-		if(s->bev) {
-			bufferevent_disable(s->bev,EV_READ|EV_WRITE);
-			bufferevent_free(s->bev);
-			s->bev=NULL;
-		}
+		BUFFEREVENT_FREE(s->conn_bev);
+		BUFFEREVENT_FREE(s->bev);
 
 		if (s->ssl) {
 			if (!s->broken) {
@@ -1607,8 +1591,7 @@ static void close_socket_net_data(ioa_socket_handle s)
 					log_socket_event(s, "SSL shutdown received, socket to be closed",0);
 				}
 			}
-			SSL_free(s->ssl);
-			s->ssl = NULL;
+			SSL_FREE(s->ssl);
 		}
 
 		if (s->fd >= 0) {
@@ -1630,18 +1613,10 @@ void detach_socket_net_data(ioa_socket_handle s)
 		}
 		s->acb = NULL;
 		s->acbarg = NULL;
-		if(s->conn_bev) {
-			bufferevent_disable(s->conn_bev,EV_READ|EV_WRITE);
-			bufferevent_free(s->conn_bev);
-			s->conn_bev=NULL;
-		}
+		BUFFEREVENT_FREE(s->conn_bev);
 		s->conn_arg=NULL;
 		s->conn_cb=NULL;
-		if(s->bev) {
-			bufferevent_disable(s->bev,EV_READ|EV_WRITE);
-			bufferevent_free(s->bev);
-			s->bev=NULL;
-		}
+		BUFFEREVENT_FREE(s->bev);
 	}
 }
 
@@ -1666,7 +1641,8 @@ void close_ioa_socket(ioa_socket_handle s)
 
 		ioa_network_buffer_delete(s->e, s->defer_nbh);
 
-		if(s->bound && s->e && s->e->tp) {
+		if(s->bound && s->e && s->e->tp &&
+				((s->sat == RELAY_SOCKET)||(s->sat == RELAY_RTCP_SOCKET))) {
 			turnipports_release(s->e->tp,
 					((s->st == TCP_SOCKET) ? STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE : STUN_ATTRIBUTE_TRANSPORT_UDP_VALUE),
 					&(s->local_addr));
@@ -1685,7 +1661,7 @@ void close_ioa_socket(ioa_socket_handle s)
 	}
 }
 
-ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach)
+ioa_socket_handle detach_ioa_socket(ioa_socket_handle s)
 {
 	ioa_socket_handle ret = NULL;
 
@@ -1717,13 +1693,29 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach)
 
 		evutil_socket_t udp_fd = -1;
 
-		if(s->parent_s && full_detach) {
+		if(s->parent_s) {
 			udp_fd = socket(s->local_addr.ss.sa_family, SOCK_DGRAM, 0);
 			if (udp_fd < 0) {
 				perror("socket");
 				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"%s: Cannot allocate new socket\n",__FUNCTION__);
 				return ret;
 			}
+			if(sock_bind_to_device(udp_fd, (unsigned char*)(s->e->relay_ifname))<0) {
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname));
+			}
+
+			if(addr_bind(udp_fd,&(s->local_addr),1)<0) {
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n");
+				close(udp_fd);
+				return ret;
+			}
+
+			int connect_err=0;
+			if(addr_connect(udp_fd, &(s->remote_addr), &connect_err)<0) {
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot connect new detached udp server socket to remote addr\n");
+				close(udp_fd);
+				return ret;
+			}
 		}
 
 		detach_socket_net_data(s);
@@ -1747,13 +1739,12 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach)
 
 		ret->realm_hash = s->realm_hash;
 
-		set_socket_ssl(ret,s->ssl);
+		SSL* ssl = s->ssl;
+		set_socket_ssl(s,NULL);
+		set_socket_ssl(ret,ssl);
 		ret->fd = s->fd;
 
-		if(s->parent_s)
-			ret->family = s->parent_s->family;
-		else
-			ret->family = s->family;
+		ret->family = get_ioa_socket_address_family(s);
 
 		ret->st = s->st;
 		ret->sat = s->sat;
@@ -1764,39 +1755,14 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach)
 		addr_cpy(&(ret->remote_addr),&(s->remote_addr));
 
 		STRCPY(ret->orig_ctx_type, s->orig_ctx_type);
-
-		ioa_socket_handle parent_s = s->parent_s;
-		ur_addr_map *sockets_container = s->sockets_container;
 		
 		delete_socket_from_map(s);
 		delete_socket_from_parent(s);
 
-		if(udp_fd<0) {
-
-		  add_socket_to_parent(parent_s, ret);
-		  add_socket_to_map(ret,sockets_container);
-
-		} else {
+		if(udp_fd>=0) {
 
 			ret->fd = udp_fd;
 
-			if(sock_bind_to_device(udp_fd, (unsigned char*)(s->e->relay_ifname))<0) {
-			    TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind udp server socket to device %s\n",(char*)(s->e->relay_ifname));
-			}
-
-			if(addr_bind(udp_fd,&(s->local_addr),1)<0) {
-				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot bind new detached udp server socket to local addr\n");
-				IOA_CLOSE_SOCKET(ret);
-				return ret;
-			}
-
-			int connect_err=0;
-			if(addr_connect(udp_fd, &(s->remote_addr), &connect_err)<0) {
-				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot connect new detached udp server socket to remote addr\n");
-				IOA_CLOSE_SOCKET(ret);
-				return ret;
-			}
-
 			set_socket_options(ret);
 		}
 
@@ -1806,7 +1772,6 @@ ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach)
 		ret->current_tos = s->current_tos;
 		ret->default_tos = s->default_tos;
 
-		set_socket_ssl(s,NULL);
 		s->fd = -1;
 	}
 
@@ -1847,12 +1812,15 @@ void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc)
 }
 
 int get_ioa_socket_address_family(ioa_socket_handle s) {
-	if(!s) {
+
+	int first_time = 1;
+	beg:
+	if (!(s && (s->magic == SOCKET_MAGIC) && !(s->done))) {
 		return AF_INET;
-	} else if(s->done) {
-		return s->family;
-	} else if(s->parent_s) {
-		return s->parent_s->family;
+	} else if(first_time && s->parent_s && (s != s->parent_s)) {
+		first_time = 0;
+		s = s->parent_s;
+		goto beg;
 	} else {
 		return s->family;
 	}
@@ -1877,7 +1845,7 @@ void set_ioa_socket_app_type(ioa_socket_handle s, SOCKET_APP_TYPE sat) {
 	if(s)
 		s->sat = sat;
 }
- 
+
 ioa_addr* get_local_addr_from_ioa_socket(ioa_socket_handle s)
 {
 	if (s && (s->magic == SOCKET_MAGIC) && !(s->done)) {
@@ -2382,7 +2350,7 @@ static int socket_input_worker(ioa_socket_handle s)
 #if defined(SSL_TXT_TLSV1_2)
 			case TURN_TLS_v1_2:
 				if(s->e->tls_ctx_v1_2) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_2));
+					set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_2));
 					STRCPY(s->orig_ctx_type,"TLSv1.2");
 				}
 				break;
@@ -2390,20 +2358,20 @@ static int socket_input_worker(ioa_socket_handle s)
 #if defined(SSL_TXT_TLSV1_1)
 			case TURN_TLS_v1_1:
 				if(s->e->tls_ctx_v1_1) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_1));
+					set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_1));
 					STRCPY(s->orig_ctx_type,"TLSv1.1");
 				}
 				break;
 #endif
 			case TURN_TLS_v1_0:
 				if(s->e->tls_ctx_v1_0) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_v1_0));
+					set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_v1_0));
 					STRCPY(s->orig_ctx_type,"TLSv1.0");
 				}
 				break;
 			default:
 				if(s->e->tls_ctx_ssl23) {
-					set_socket_ssl(s,SSL_new(s->e->tls_ctx_ssl23));
+					set_socket_ssl(s,SSL_NEW(s->e->tls_ctx_ssl23));
 					STRCPY(s->orig_ctx_type,"SSLv23");
 				} else {
 					s->tobeclosed = 1;
@@ -2415,7 +2383,8 @@ static int socket_input_worker(ioa_socket_handle s)
 								s->fd,
 								s->ssl,
 								BUFFEREVENT_SSL_ACCEPTING,
-								BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+								TURN_BUFFEREVENTS_OPTIONS);
+				debug_ptr_add(s->bev);
 				bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
 								eventcb_bev, s);
 				bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
@@ -2430,7 +2399,8 @@ static int socket_input_worker(ioa_socket_handle s)
 			}
 			s->bev = bufferevent_socket_new(s->e->event_base,
 							s->fd,
-							BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+							TURN_BUFFEREVENTS_OPTIONS);
+			debug_ptr_add(s->bev);
 			bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
 					eventcb_bev, s);
 			bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
@@ -3254,7 +3224,8 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
 					} else {
 						s->bev = bufferevent_socket_new(s->e->event_base,
 										s->fd,
-										BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+										TURN_BUFFEREVENTS_OPTIONS);
+						debug_ptr_add(s->bev);
 						bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
 							eventcb_bev, s);
 						bufferevent_setwatermark(s->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
@@ -3272,19 +3243,21 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
 #if !defined(TURN_NO_TLS)
 						if(!(s->ssl)) {
 							//??? how we can get to this point ???
-							set_socket_ssl(s,SSL_new(e->tls_ctx_ssl23));
+							set_socket_ssl(s,SSL_NEW(e->tls_ctx_ssl23));
 							STRCPY(s->orig_ctx_type,"SSLv23");
 							s->bev = bufferevent_openssl_socket_new(s->e->event_base,
 											s->fd,
 											s->ssl,
 											BUFFEREVENT_SSL_ACCEPTING,
-											BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+											TURN_BUFFEREVENTS_OPTIONS);
+							debug_ptr_add(s->bev);
 						} else {
 							s->bev = bufferevent_openssl_socket_new(s->e->event_base,
 											s->fd,
 											s->ssl,
 											BUFFEREVENT_SSL_OPEN,
-											BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+											TURN_BUFFEREVENTS_OPTIONS);
+							debug_ptr_add(s->bev);
 						}
 						bufferevent_setcb(s->bev, socket_input_handler_bev, socket_output_handler_bev,
 							eventcb_bev, s);
@@ -3693,7 +3666,7 @@ void* allocate_super_memory_region_func(super_memory_t *r, size_t size, const ch
 
 		if(!region) {
 			r->sm_chunk += 1;
-			r->super_memory = (char**)turn_realloc(r->super_memory,0,(r->sm_chunk+1) * sizeof(char*));
+			r->super_memory = (char**)turn_realloc(r->super_memory,0, (r->sm_chunk+1) * sizeof(char*));
 			r->super_memory[r->sm_chunk] = (char*)turn_malloc(TURN_SM_SIZE);
 			ns_bzero(r->super_memory[r->sm_chunk],TURN_SM_SIZE);
 			r->sm_allocated = (size_t*)turn_realloc(r->sm_allocated,0,(r->sm_chunk+1) * sizeof(size_t*));

+ 27 - 16
src/apps/relay/turncli.c

@@ -312,7 +312,7 @@ static void cli_print_str_array(struct cli_session* cs, char **value, size_t sz,
 
 static void cli_print_ip_range_list(struct cli_session* cs, ip_range_list_t *value, const char* name, int changeable)
 {
-	if(cs && cs->ts && name && value && value->ranges_number && value->ranges) {
+	if(cs && cs->ts && name && value && value->ranges_number && value->rs) {
 		const char *sc="";
 		if(changeable==1)
 			sc=" (*)";
@@ -320,8 +320,15 @@ static void cli_print_ip_range_list(struct cli_session* cs, ip_range_list_t *val
 			sc=" (**)";
 		size_t i;
 		for(i=0;i<value->ranges_number;++i) {
-			if(value->ranges[i])
-				myprintf(cs,"  %s: %s%s\n",name,value->ranges[i],sc);
+			if(value->rs[i].realm[0]) {
+				if(cs->realm[0] && strcmp(cs->realm,value->rs[i].realm)) {
+					continue;
+				} else {
+					myprintf(cs,"  %s: %s (%s)%s\n",name,value->rs[i].str,value->rs[i].realm,sc);
+				}
+			} else {
+				myprintf(cs,"  %s: %s%s\n",name,value->rs[i].str,sc);
+			}
 		}
 	}
 }
@@ -753,8 +760,19 @@ static void cli_print_configuration(struct cli_session* cs)
 		cli_print_uint(cs,(unsigned long)turn_params.min_port,"min-port",0);
 		cli_print_uint(cs,(unsigned long)turn_params.max_port,"max-port",0);
 
-		cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP",0);
-		cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP",0);
+		cli_print_ip_range_list(cs,&turn_params.ip_whitelist,"Whitelist IP (static)",0);
+		{
+			ip_range_list_t* l = get_ip_list("allowed");
+			cli_print_ip_range_list(cs,l,"Whitelist IP (dynamic)",0);
+			ip_list_free(l);
+		}
+
+		cli_print_ip_range_list(cs,&turn_params.ip_blacklist,"Blacklist IP (static)",0);
+		{
+			ip_range_list_t* l = get_ip_list("denied");
+			cli_print_ip_range_list(cs,l,"Blacklist IP (dynamic)",0);
+			ip_list_free(l);
+		}
 
 		cli_print_flag(cs,turn_params.no_multicast_peers,"no-multicast-peers",1);
 		cli_print_flag(cs,turn_params.no_loopback_peers,"no-loopback-peers",1);
@@ -882,12 +900,7 @@ static void close_cli_session(struct cli_session* cs)
 			cs->ts = NULL;
 		}
 
-		if(cs->bev) {
-			bufferevent_flush(cs->bev,EV_READ|EV_WRITE,BEV_FLUSH);
-			bufferevent_disable(cs->bev,EV_READ|EV_WRITE);
-			bufferevent_free(cs->bev);
-			cs->bev=NULL;
-		}
+		BUFFEREVENT_FREE(cs->bev);
 
 		if(cs->fd>=0) {
 			close(cs->fd);
@@ -1174,7 +1187,8 @@ static void cliserver_input_handler(struct evconnlistener *l, evutil_socket_t fd
 
 	clisession->bev = bufferevent_socket_new(cliserver.event_base,
 					fd,
-					BEV_OPT_THREADSAFE | BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS);
+					TURN_BUFFEREVENTS_OPTIONS);
+	debug_ptr_add(clisession->bev);
 	bufferevent_setcb(clisession->bev, cli_socket_input_handler_bev, NULL,
 			cli_eventcb_bev, clisession);
 	bufferevent_setwatermark(clisession->bev, EV_READ|EV_WRITE, 0, BUFFEREVENT_HIGH_WATERMARK);
@@ -1205,11 +1219,8 @@ void setup_cli_thread(void)
 	TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"IO method (cli thread): %s\n",event_base_get_method(cliserver.event_base));
 
 	struct bufferevent *pair[2];
-	int opts = BEV_OPT_DEFER_CALLBACKS | BEV_OPT_UNLOCK_CALLBACKS;
-
-	opts |= BEV_OPT_THREADSAFE;
 
-	bufferevent_pair_new(cliserver.event_base, opts, pair);
+	bufferevent_pair_new(cliserver.event_base, TURN_BUFFEREVENTS_OPTIONS, pair);
 	cliserver.in_buf = pair[0];
 	cliserver.out_buf = pair[1];
 	bufferevent_setcb(cliserver.in_buf, cli_server_receive_message, NULL, NULL, &cliserver);

+ 17 - 25
src/apps/relay/userdb.c

@@ -1377,33 +1377,24 @@ const ip_range_list_t* ioa_get_blacklist(ioa_engine_handle e)
 	return ipblacklist;
 }
 
-static ip_range_list_t* get_ip_list(const char *kind)
+ip_range_list_t* get_ip_list(const char *kind)
 {
-	ip_range_list_t *ret = (ip_range_list_t*)turn_malloc(sizeof(ip_range_list_t));
+	ip_range_list_t *ret = (ip_range_list_t*) turn_malloc(sizeof(ip_range_list_t));
 	ns_bzero(ret,sizeof(ip_range_list_t));
 
-  turn_dbdriver_t * dbd = get_dbdriver();
-  if (dbd && dbd->get_ip_list) {
-    (*dbd->get_ip_list)(kind, ret);
+	turn_dbdriver_t * dbd = get_dbdriver();
+	if (dbd && dbd->get_ip_list) {
+		(*dbd->get_ip_list)(kind, ret);
 	}
 
 	return ret;
 }
 
-static void ip_list_free(ip_range_list_t *l)
+void ip_list_free(ip_range_list_t *l)
 {
 	if(l) {
-		size_t i;
-		for(i=0;i<l->ranges_number;++i) {
-			if(l->ranges && l->ranges[i])
-			  turn_free(l->ranges[i],0);
-			if(l->encaddrsranges && l->encaddrsranges[i])
-			  turn_free(l->encaddrsranges[i],0);
-		}
-		if(l->ranges)
-		  turn_free(l->ranges,0);
-		if(l->encaddrsranges)
-		  turn_free(l->encaddrsranges,0);
+		if(l->rs)
+		  turn_free(l->rs,l->ranges_number * sizeof(ip_range_t));
 		turn_free(l,sizeof(ip_range_list_t));
 	}
 }
@@ -1432,7 +1423,7 @@ void update_white_and_black_lists(void)
 
 /////////////// add ACL record ///////////////////
 
-int add_ip_list_range(const char * range0, ip_range_list_t * list)
+int add_ip_list_range(const char * range0, const char * realm, ip_range_list_t * list)
 {
 	char *range = turn_strdup(range0);
 
@@ -1465,13 +1456,14 @@ int add_ip_list_range(const char * range0, ip_range_list_t * list)
 		*separator = '-';
 
 	++(list->ranges_number);
-	list->ranges = (char**) turn_realloc(list->ranges, 0, sizeof(char*) * list->ranges_number);
-	list->ranges[list->ranges_number - 1] = range;
-	list->encaddrsranges = (ioa_addr_range**) turn_realloc(list->encaddrsranges, 0, sizeof(ioa_addr_range*) * list->ranges_number);
-
-	list->encaddrsranges[list->ranges_number - 1] = (ioa_addr_range*) turn_malloc(sizeof(ioa_addr_range));
-
-	ioa_addr_range_set(list->encaddrsranges[list->ranges_number - 1], &min, &max);
+	list->rs = (ip_range_t*) turn_realloc(list->rs, 0, sizeof(ip_range_t) * list->ranges_number);
+	STRCPY(list->rs[list->ranges_number - 1].str,range);
+	if(realm)
+		STRCPY(list->rs[list->ranges_number - 1].realm,realm);
+	else
+		list->rs[list->ranges_number - 1].realm[0]=0;
+	turn_free(range,0);
+	ioa_addr_range_set(&(list->rs[list->ranges_number - 1].enc), &min, &max);
 
 	return 0;
 }

+ 3 - 1
src/apps/relay/userdb.h

@@ -208,7 +208,9 @@ void reread_realms(void);
 int add_user_account(char *user, int dynamic);
 int adminuser(u08bits *user, u08bits *realm, u08bits *pwd, u08bits *secret, u08bits *origin, TURNADMIN_COMMAND_TYPE ct, int is_st, perf_options_t* po);
 
-int add_ip_list_range(const char* range, ip_range_list_t * list);
+int add_ip_list_range(const char* range, const char* realm, ip_range_list_t * list);
+ip_range_list_t* get_ip_list(const char *kind);
+void ip_list_free(ip_range_list_t *l);
 
 ///////////// Redis //////////////////////
 

+ 1 - 0
src/apps/uclient/mainuclient.c

@@ -365,6 +365,7 @@ int main(int argc, char **argv)
 		case 'P':
 			passive_tcp = 1;
 			/* implies 'T': */
+			/* no break */
 		case 'T':
 			relay_transport = STUN_ATTRIBUTE_TRANSPORT_TCP_VALUE;
 			break;

+ 1 - 0
src/apps/uclient/session.h

@@ -75,6 +75,7 @@ typedef struct {
   char rsaddr[129];
   char ifname[129];
   ioa_addr peer_addr;
+  ioa_addr relay_addr;
   ioa_socket_raw fd;
   SSL *ssl;
   int broken;

+ 9 - 8
src/apps/uclient/startuclient.c

@@ -80,7 +80,7 @@ static SSL* tls_connect(ioa_socket_raw fd, ioa_addr *remote_addr)
 {
 	int ctxtype = (int)(((unsigned long)random())%root_tls_ctx_num);
 
-	SSL *ssl = SSL_new(root_tls_ctx[ctxtype]);
+	SSL *ssl = SSL_NEW(root_tls_ctx[ctxtype]);
 
 	if(use_tcp) {
 		SSL_set_fd(ssl, fd);
@@ -456,21 +456,23 @@ static int clnet_allocate(int verbose,
 										return -1;
 									} else {
 										if (verbose) {
-											ioa_addr remote_addr;
-											memcpy(&remote_addr, relay_addr,sizeof(ioa_addr));
-											addr_debug_print(verbose, &remote_addr,"Received relay addr");
+											ioa_addr raddr;
+											memcpy(&raddr, relay_addr,sizeof(ioa_addr));
+											addr_debug_print(verbose, &raddr,"Received relay addr");
 										}
 
 										if(!addr_any(relay_addr)) {
 											if(relay_addr->ss.sa_family == AF_INET) {
 												if(default_address_family != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
 													found = 1;
+													addr_cpy(&(clnet_info->relay_addr),relay_addr);
 													break;
 												}
 											}
 											if(relay_addr->ss.sa_family == AF_INET6) {
 												if(default_address_family == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6) {
 													found = 1;
+													addr_cpy(&(clnet_info->relay_addr),relay_addr);
 													break;
 												}
 											}
@@ -588,8 +590,7 @@ static int clnet_allocate(int verbose,
 			  int close_socket = (int)(random()%2);
 			  if(ssl && !close_socket) {
 				  SSL_shutdown(ssl);
-				  SSL_free(ssl);
-				  ssl = NULL;
+				  SSL_FREE(ssl);
 				  fd = -1;
 			  } else if(fd>=0) {
 				  close(fd);
@@ -613,7 +614,7 @@ static int clnet_allocate(int verbose,
 
 		  if(ssl) {
 			  SSL_shutdown(ssl);
-		  	  SSL_free(ssl);
+		  	  SSL_FREE(ssl);
 		  } else if(fd>=0) {
 		  	  close(fd);
 		  }
@@ -1535,7 +1536,7 @@ void tcp_data_connect(app_ur_session *elem, u32bits cid)
 
 	++elem->pinfo.tcp_conn_number;
 	int i = (int)(elem->pinfo.tcp_conn_number-1);
-	elem->pinfo.tcp_conn=(app_tcp_conn_info**)realloc(elem->pinfo.tcp_conn,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*));
+	elem->pinfo.tcp_conn=(app_tcp_conn_info**)turn_realloc(elem->pinfo.tcp_conn,0,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*));
 	elem->pinfo.tcp_conn[i]=(app_tcp_conn_info*)turn_malloc(sizeof(app_tcp_conn_info));
 	ns_bzero(elem->pinfo.tcp_conn[i],sizeof(app_tcp_conn_info));
 

+ 27 - 22
src/apps/uclient/uclient.c

@@ -140,8 +140,7 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) {
 	      SSL_shutdown(cdi->pinfo.tcp_conn[i]->tcp_data_ssl);
 	    }
 	    if(cdi->pinfo.tcp_conn[i]->tcp_data_ssl) {
-	      SSL_free(cdi->pinfo.tcp_conn[i]->tcp_data_ssl);
-	      cdi->pinfo.tcp_conn[i]->tcp_data_ssl = NULL;
+	      SSL_FREE(cdi->pinfo.tcp_conn[i]->tcp_data_ssl);
 	    }
 	    if(cdi->pinfo.tcp_conn[i]->tcp_data_fd>=0) {
 	    	socket_closesocket(cdi->pinfo.tcp_conn[i]->tcp_data_fd);
@@ -153,8 +152,10 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) {
 	}
       }
       cdi->pinfo.tcp_conn_number=0;
-      turn_free(cdi->pinfo.tcp_conn, 111);
-      cdi->pinfo.tcp_conn=NULL;
+      if(cdi->pinfo.tcp_conn) {
+    	  turn_free(cdi->pinfo.tcp_conn, 111);
+    	  cdi->pinfo.tcp_conn=NULL;
+      }
     }
     if(cdi->pinfo.ssl && !(cdi->pinfo.broken)) {
 	    if(!(SSL_get_shutdown(cdi->pinfo.ssl) & SSL_SENT_SHUTDOWN)) {
@@ -163,8 +164,7 @@ static void uc_delete_session_elem_data(app_ur_session* cdi) {
 	    }
     }
     if(cdi->pinfo.ssl) {
-	    SSL_free(cdi->pinfo.ssl);
-	    cdi->pinfo.ssl = NULL;
+	    SSL_FREE(cdi->pinfo.ssl);
     }
     if(cdi->pinfo.fd>=0) {
     	socket_closesocket(cdi->pinfo.fd);
@@ -863,8 +863,7 @@ static int start_client(const char *remote_address, int port,
 		   clnet_info_rtcp, &chnum_rtcp);
 		   
   if(clnet_info_probe.ssl) {
-  	SSL_free(clnet_info_probe.ssl);
-  	clnet_info_probe.ssl = NULL;
+  	SSL_FREE(clnet_info_probe.ssl);
   	clnet_info_probe.fd = -1;
   } else if(clnet_info_probe.fd != -1) {
 	  socket_closesocket(clnet_info_probe.fd);
@@ -969,8 +968,7 @@ static int start_c2c(const char *remote_address, int port,
 		       clnet_info2_rtcp, &chnum2_rtcp);
 		       
   if(clnet_info_probe.ssl) {
-	SSL_free(clnet_info_probe.ssl);
-	clnet_info_probe.ssl = NULL;
+	SSL_FREE(clnet_info_probe.ssl);
 	clnet_info_probe.fd = -1;
   } else if(clnet_info_probe.fd != -1) {
 	  socket_closesocket(clnet_info_probe.fd);
@@ -1219,7 +1217,7 @@ void start_mclient(const char *remote_address, int port,
 	      ++mclient;
 	}
 
-	elems = (app_ur_session**)malloc(sizeof(app_ur_session)*((mclient*2)+1)+sizeof(void*));
+	elems = (app_ur_session**)turn_malloc(sizeof(app_ur_session)*((mclient*2)+1)+sizeof(void*));
 
 	__turn_getMSTime();
 	u32bits stime = current_time;
@@ -1294,9 +1292,12 @@ void start_mclient(const char *remote_address, int port,
 					int connect_err = 0;
 					socket_connect(elems[i]->pinfo.fd, &(elems[i]->pinfo.remote_addr), &connect_err);
 				}
-			} else if((i%2) == 0) {
-				if (turn_tcp_connect(clnet_verbose, &(elems[i]->pinfo), &(elems[i]->pinfo.peer_addr)) < 0) {
-					exit(-1);
+			} else {
+				int j = 0;
+				for(j=i+1;j<total_clients;j++) {
+					if (turn_tcp_connect(clnet_verbose, &(elems[i]->pinfo), &(elems[j]->pinfo.relay_addr)) < 0) {
+						exit(-1);
+					}
 				}
 			}
 		}
@@ -1328,18 +1329,22 @@ void start_mclient(const char *remote_address, int port,
 					break;
 			} else {
 				for(i=0;i<total_clients;++i) {
-					if(elems[i]->pinfo.tcp_conn_number>0 &&
-							elems[i]->pinfo.tcp_conn[0]->tcp_data_bound) {
-						completed += elems[i]->pinfo.tcp_conn_number;
+					int j = 0;
+					for(j=0;j<(int)elems[i]->pinfo.tcp_conn_number;j++) {
+						if(elems[i]->pinfo.tcp_conn[j]->tcp_data_bound) {
+							completed++;
+						}
 					}
 				}
-				if(completed >= total_clients)
+				if(completed >= total_clients*(total_clients-1)) {
+					TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%d connections are completed\n",(int)(completed));
 					break;
+				}
 			}
 			run_events(0);
-			if(current_time > connect_wait_start_time + STARTING_TCP_RELAY_TIME) {
-				TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: %d connections are not completed\n",
-						(int)(total_clients - completed));
+			if(current_time > connect_wait_start_time + STARTING_TCP_RELAY_TIME + total_clients) {
+				TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: %d connections are completed, not enough\n",
+						(int)(completed));
 				break;
 			}
 		}
@@ -1410,7 +1415,7 @@ void start_mclient(const char *remote_address, int port,
 				(unsigned long)min_jitter,
 				(unsigned long)max_jitter);
 
-	free(elems);
+	turn_free(elems,0);
 }
 
 ///////////////////////////////////////////

+ 2 - 2
src/apps/uclient/uclient.h

@@ -43,8 +43,8 @@ extern "C" {
 
 //////////////////////////////////////////////
 
-#define STOPPING_TIME (5)
-#define STARTING_TCP_RELAY_TIME (10)
+#define STOPPING_TIME (10)
+#define STARTING_TCP_RELAY_TIME (30)
 
 extern int clmessage_length;
 extern int do_not_use_channel;

+ 23 - 6
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.2.1.2"
+#define TURN_SERVER_VERSION "4.2.2.2"
 #define TURN_SERVER_VERSION_NAME "Monza"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 
@@ -120,13 +120,17 @@ static inline u64bits _ioa_ntoh64(u64bits v)
 #define TURN_LOG_FUNC(level, ...) printf (__VA_ARGS__)
 
   void tm_print_func(void);
-  void *turn_malloc_func(size_t sz, const char* file, int line);
-  void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* file, int line);
-  void turn_free_func(void *ptr, size_t sz, const char* file, int line);
+  void *turn_malloc_func(size_t sz, const char* function, int line);
+  void *turn_realloc_func(void *ptr, size_t old_sz, size_t new_sz, const char* function, int line);
+  void turn_free_func(void *ptr, size_t sz, const char* function, int line);
   void turn_free_simple(void *ptr);
-  void *turn_calloc_func(size_t number, size_t size, const char* file, int line);
-  char *turn_strdup_func(const char* s, const char* file, int line);
+  void *turn_calloc_func(size_t number, size_t size, const char* function, int line);
+  char *turn_strdup_func(const char* s, const char* function, int line);
+  void* debug_ptr_add_func(void *ptr, const char* function, int line);
+  void debug_ptr_del_func(void *ptr, const char* function, int line);
 
+#define debug_ptr_add(ptr) debug_ptr_add_func((ptr),__FUNCTION__,__LINE__)
+#define debug_ptr_del(ptr) debug_ptr_del_func((ptr),__FUNCTION__,__LINE__)
 #define tm_print() tm_print_func()
 #define turn_malloc(sz) turn_malloc_func((size_t)(sz),__FUNCTION__,__LINE__)
 #define turn_free(ptr,sz) turn_free_func((ptr),(size_t)(sz),__FUNCTION__,__LINE__)
@@ -134,8 +138,12 @@ static inline u64bits _ioa_ntoh64(u64bits v)
 #define turn_calloc(number, sz) turn_calloc_func((number),(size_t)(sz),__FUNCTION__,__LINE__)
 #define turn_strdup(s) turn_strdup_func((s),__FUNCTION__,__LINE__)
 
+#define SSL_NEW(ctx) ((SSL*)debug_ptr_add(SSL_new(ctx)))
+
 #else
 
+#define debug_ptr_add(ptr)
+#define debug_ptr_del(ptr)
 #define tm_print() 
 #define turn_malloc(sz) malloc((size_t)(sz))
 #define turn_free(ptr,sz) free((ptr))
@@ -144,8 +152,13 @@ static inline u64bits _ioa_ntoh64(u64bits v)
 #define turn_strdup(s) strdup((s))
 #define turn_free_simple free
 
+#define SSL_NEW(ctx) SSL_new(ctx)
+
 #endif
 
+#define SSL_FREE(ssl) do { debug_ptr_del(ssl); SSL_free(ssl); ssl = NULL; } while(0)
+#define BUFFEREVENT_FREE(be) do { if(be) { debug_ptr_del(be); bufferevent_flush(be,EV_READ|EV_WRITE,BEV_FLUSH); bufferevent_disable(be,EV_READ|EV_WRITE); bufferevent_free(be); be = NULL;} } while(0)
+
 #define turn_time() ((turn_time_t)time(NULL))
 
 typedef int vint;
@@ -187,6 +200,10 @@ typedef u32bits turn_time_t;
 		}\
 	} } while(0)
 
+//////////////// Bufferevents /////////////////////
+
+#define TURN_BUFFEREVENTS_OPTIONS (BEV_OPT_DEFER_CALLBACKS | BEV_OPT_THREADSAFE | BEV_OPT_UNLOCK_CALLBACKS)
+
 //////////////// KERNEL-LEVEL CHANNEL HANDLERS /////////
 
 #if !defined(TURN_CHANNEL_HANDLER_KERNEL)

+ 11 - 4
src/server/ns_turn_ioalib.h

@@ -137,9 +137,16 @@ typedef struct _realm_options_t realm_options_t;
 
 //////// IP White/black listing ///////////
 
+struct _ip_range {
+	char str[257];
+	char realm[513];
+	ioa_addr_range enc;
+};
+
+typedef struct _ip_range ip_range_t;
+
 struct _ip_range_list {
-	char **ranges;
-	ioa_addr_range **encaddrsranges;
+	ip_range_t *rs;
 	size_t ranges_number;
 };
 
@@ -215,7 +222,7 @@ int create_relay_ioa_sockets(ioa_engine_handle e, ioa_socket_handle client_s,
 
 ioa_socket_handle  ioa_create_connecting_tcp_relay_socket(ioa_socket_handle s, ioa_addr *peer_addr, connect_cb cb, void *arg);
 
-int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s);
+int get_ioa_socket_from_reservation(ioa_engine_handle e, u64bits in_reservation_token, ioa_socket_handle *s, u08bits *realm);
 
 int get_ioa_socket_address_family(ioa_socket_handle s);
 SOCKET_TYPE get_ioa_socket_type(ioa_socket_handle s);
@@ -235,7 +242,7 @@ int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, in
 int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos);
 void close_ioa_socket(ioa_socket_handle s);
 #define IOA_CLOSE_SOCKET(S) do { if(S) { close_ioa_socket(S); S = NULL; } } while(0)
-ioa_socket_handle detach_ioa_socket(ioa_socket_handle s, int full_detach);
+ioa_socket_handle detach_ioa_socket(ioa_socket_handle s);
 void detach_socket_net_data(ioa_socket_handle s);
 int set_df_on_ioa_socket(ioa_socket_handle s, int value);
 void set_do_not_use_df(ioa_socket_handle s);

+ 67 - 62
src/server/ns_turn_maps_rtcp.c

@@ -85,6 +85,54 @@ static int timeout_check(ur_map_key_type key,
   return 0;
 }
 
+static void rtcp_alloc_free(ur_map_value_type value)
+{
+	rtcp_alloc_type *at = (rtcp_alloc_type *)value;
+	if (at) {
+		IOA_CLOSE_SOCKET(at->s);
+		turn_free(at,sizeof(rtcp_alloc_type));
+	}
+}
+
+static void rtcp_alloc_free_savefd(ur_map_value_type value)
+{
+	rtcp_alloc_type *at = (rtcp_alloc_type *) value;
+	if (at) {
+		turn_free(at,sizeof(rtcp_alloc_type));
+	}
+}
+
+static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) {
+  UNUSED_ARG(key);
+  if(value) {
+    rtcp_alloc_free(value);
+  }
+  return 0;
+}
+
+/**
+ * @ret:
+ * 1 - success
+ * 0 - not found
+ */
+static int rtcp_map_del(rtcp_map* map, rtcp_token_type token) {
+  if(!rtcp_map_valid(map)) return 0;
+  else {
+    TURN_MUTEX_LOCK(&map->mutex);
+    int ret = ur_map_del(map->map,token,rtcp_alloc_free);
+    TURN_MUTEX_UNLOCK(&map->mutex);
+    return ret;
+  }
+}
+
+static int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) {
+  if(!rtcp_map_valid(map)) return 0;
+  else {
+    int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd);
+    return ret;
+  }
+}
+
 static void rtcp_map_timeout_handler(ioa_engine_handle e, void* arg) {
   
   UNUSED_ARG(e);
@@ -166,69 +214,26 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type token, ioa_socket_handle s) {
  * >=0 - success
  * <0 - not found
  */
-ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token) {
-  if(!rtcp_map_valid(map)) return NULL;
-  else {
-    ur_map_value_type value;
-    TURN_MUTEX_LOCK(&map->mutex);
-    int ret = ur_map_get(map->map,token,&value);
-    //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.111: ret=%d, value=%llu, token=%llu\n",__FUNCTION__,ret,(unsigned long)value,token);
-    TURN_MUTEX_UNLOCK(&map->mutex);
-    if(!ret) return NULL;
-    rtcp_alloc_type* rval=(rtcp_alloc_type*)value;
-    if(!rval) return NULL;
-    //TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"%s: 111.222: ret=%d, token=%llu\n",__FUNCTION__,ret,token);
-    return rval->s;
-  }
-}
-
-static void rtcp_alloc_free(ur_map_value_type value)
-{
-	rtcp_alloc_type *at = (rtcp_alloc_type *)value;
-	if (at) {
-		IOA_CLOSE_SOCKET(at->s);
-		turn_free(at,sizeof(rtcp_alloc_type));
-	}
-}
-
-static void rtcp_alloc_free_savefd(ur_map_value_type value)
-{
-	rtcp_alloc_type *at = (rtcp_alloc_type *) value;
-	if (at) {
-		turn_free(at,sizeof(rtcp_alloc_type));
+ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm) {
+	ioa_socket_handle s = NULL;
+	if (rtcp_map_valid(map)) {
+		ur_map_value_type value;
+		TURN_MUTEX_LOCK(&map->mutex);
+		int ret = ur_map_get(map->map, token, &value);
+		if (ret) {
+			rtcp_alloc_type* rval = (rtcp_alloc_type*) value;
+			if (rval) {
+				s = rval->s;
+				if(!check_realm_hash(s,realm)) {
+					s = NULL;
+				} else {
+					rtcp_map_del_savefd(map, token);
+				}
+			}
+		}
+		TURN_MUTEX_UNLOCK(&map->mutex);
 	}
-}
-
-static int foreachcb_free(ur_map_key_type key, ur_map_value_type value) {
-  UNUSED_ARG(key);
-  if(value) {
-    rtcp_alloc_free(value);
-  }
-  return 0;
-}
-
-/**
- * @ret:
- * 1 - success
- * 0 - not found
- */
-int rtcp_map_del(rtcp_map* map, rtcp_token_type token) {
-  if(!rtcp_map_valid(map)) return 0;
-  else {
-    TURN_MUTEX_LOCK(&map->mutex);
-    int ret = ur_map_del(map->map,token,rtcp_alloc_free);
-    TURN_MUTEX_UNLOCK(&map->mutex);
-    return ret;
-  }
-}
-int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token) {
-  if(!rtcp_map_valid(map)) return 0;
-  else {
-    TURN_MUTEX_LOCK(&map->mutex);
-    int ret = ur_map_del(map->map,token,rtcp_alloc_free_savefd);
-    TURN_MUTEX_UNLOCK(&map->mutex);
-    return ret;
-  }
+	return s;
 }
 
 void rtcp_map_free(rtcp_map** map) {

+ 1 - 9
src/server/ns_turn_maps_rtcp.h

@@ -61,15 +61,7 @@ int rtcp_map_put(rtcp_map* map, rtcp_token_type key, ioa_socket_handle s);
  * >=0 - success
  * <0 - not found
  */
-ioa_socket_handle rtcp_map_get(const rtcp_map* map, rtcp_token_type token);
-
-/**
- * @ret:
- * 1 - success
- * 0 - not found
- */
-int rtcp_map_del(rtcp_map* map, rtcp_token_type token);
-int rtcp_map_del_savefd(rtcp_map* map, rtcp_token_type token);
+ioa_socket_handle rtcp_map_get(rtcp_map* map, rtcp_token_type token, u08bits *realm);
 
 /**
  * @ret:

+ 36 - 25
src/server/ns_turn_server.c

@@ -250,8 +250,10 @@ static int send_turn_message_to(turn_turnserver *server, ioa_network_buffer_hand
 
 /////////////////// Peer addr check /////////////////////////////
 
-static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
+static int good_peer_addr(turn_turnserver *server, const char* realm, ioa_addr *peer_addr)
 {
+#define CHECK_REALM(r) if((r)[0] && realm && realm[0] && strcmp((r),realm)) continue
+
 	if(server && peer_addr) {
 		if(*(server->no_multicast_peers) && ioa_addr_is_multicast(peer_addr))
 			return 0;
@@ -264,7 +266,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
 			if(server->ip_whitelist) {
 				// White listing of addr ranges
 				for (i = server->ip_whitelist->ranges_number - 1; i >= 0; --i) {
-					if (ioa_addr_in_range(server->ip_whitelist->encaddrsranges[i], peer_addr))
+					CHECK_REALM(server->ip_whitelist->rs[i].realm);
+					if (ioa_addr_in_range(&(server->ip_whitelist->rs[i].enc), peer_addr))
 						return 1;
 				}
 			}
@@ -276,7 +279,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
 				if(wl) {
 					// White listing of addr ranges
 					for (i = wl->ranges_number - 1; i >= 0; --i) {
-						if (ioa_addr_in_range(wl->encaddrsranges[i], peer_addr)) {
+						CHECK_REALM(wl->rs[i].realm);
+						if (ioa_addr_in_range(&(wl->rs[i].enc), peer_addr)) {
 							ioa_unlock_whitelist(server->e);
 							return 1;
 						}
@@ -289,10 +293,11 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
 			if(server->ip_blacklist) {
 				// Black listing of addr ranges
 				for (i = server->ip_blacklist->ranges_number - 1; i >= 0; --i) {
-					if (ioa_addr_in_range(server->ip_blacklist->encaddrsranges[i], peer_addr)) {
+					CHECK_REALM(server->ip_blacklist->rs[i].realm);
+					if (ioa_addr_in_range(&(server->ip_blacklist->rs[i].enc), peer_addr)) {
 						char saddr[129];
 						addr_to_string_no_port(peer_addr,(u08bits*)saddr);
-						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,server->ip_blacklist->ranges[i]);
+						TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,server->ip_blacklist->rs[i].str);
 						return 0;
 					}
 				}
@@ -305,11 +310,12 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
 				if(bl) {
 					// Black listing of addr ranges
 					for (i = bl->ranges_number - 1; i >= 0; --i) {
-						if (ioa_addr_in_range(bl->encaddrsranges[i], peer_addr)) {
+						CHECK_REALM(bl->rs[i].realm);
+						if (ioa_addr_in_range(&(bl->rs[i].enc), peer_addr)) {
 							ioa_unlock_blacklist(server->e);
 							char saddr[129];
 							addr_to_string_no_port(peer_addr,(u08bits*)saddr);
-							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,bl->ranges[i]);
+							TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "A peer IP %s denied in the range: %s\n",saddr,bl->rs[i].str);
 							return 0;
 						}
 					}
@@ -320,6 +326,8 @@ static int good_peer_addr(turn_turnserver *server, ioa_addr *peer_addr)
 		}
 	}
 
+#undef CHECK_REALM
+
 	return 1;
 }
 
@@ -1525,7 +1533,7 @@ static int handle_turn_refresh(turn_turnserver *server,
 				if(tsid != server->id) {
 
 					if(server->send_socket_to_relay) {
-						ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket,1);
+						ioa_socket_handle new_s = detach_ioa_socket(ss->client_socket);
 						if(new_s) {
 						  if(server->send_socket_to_relay(tsid, mid, tid, new_s, message_integrity, 
 										  RMT_MOBILE_SOCKET, in_buffer, can_resume)<0) {
@@ -1616,7 +1624,7 @@ static int handle_turn_refresh(turn_turnserver *server,
 
 								//Transfer socket:
 
-								ioa_socket_handle s = detach_ioa_socket(ss->client_socket,1);
+								ioa_socket_handle s = detach_ioa_socket(ss->client_socket);
 
 								ss->to_be_closed = 1;
 
@@ -2076,7 +2084,7 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg)
 			return;
 		}
 
-		if(!good_peer_addr(server, peer_addr)) {
+		if(!good_peer_addr(server, ss->realm_options.name, peer_addr)) {
 			u08bits saddr[256];
 			addr_to_string(peer_addr, saddr);
 			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: an attempt to connect from a peer with forbidden address: %s\n", __FUNCTION__,saddr);
@@ -2226,7 +2234,7 @@ static int handle_turn_connect(turn_turnserver *server,
 			*reason = (const u08bits *)"Where is Peer Address ?";
 
 		} else {
-			if(!good_peer_addr(server,&peer_addr)) {
+			if(!good_peer_addr(server,ss->realm_options.name,&peer_addr)) {
 				*err_code = 403;
 				*reason = (const u08bits *) "Forbidden IP";
 			} else {
@@ -2310,7 +2318,7 @@ static int handle_turn_connection_bind(turn_turnserver *server,
 				turnserver_id sid = (id & 0xFF000000)>>24;
 				ioa_socket_handle s = ss->client_socket;
 				if(s && !ioa_socket_tobeclosed(s)) {
-					ioa_socket_handle new_s = detach_ioa_socket(s,1);
+					ioa_socket_handle new_s = detach_ioa_socket(s);
 					if(new_s) {
 					  if(server->send_socket_to_relay(sid, id, tid, new_s, message_integrity, RMT_CB_SOCKET, in_buffer, can_resume)<0) {
 					    *err_code = 400;
@@ -2588,7 +2596,7 @@ static int handle_turn_channel_bind(turn_turnserver *server,
 					*err_code = 400;
 					*reason = (const u08bits *)"You cannot use the same peer with different channel number";
 				} else {
-					if(!good_peer_addr(server,&peer_addr)) {
+					if(!good_peer_addr(server,ss->realm_options.name,&peer_addr)) {
 						*err_code = 403;
 						*reason = (const u08bits *) "Forbidden IP";
 					} else {
@@ -3015,7 +3023,7 @@ static int handle_turn_create_permission(turn_turnserver *server,
 					if(!get_relay_socket(a,peer_addr.ss.sa_family)) {
 						*err_code = 443;
 						*reason = (const u08bits *)"Peer Address Family Mismatch";
-					} else if(!good_peer_addr(server, &peer_addr)) {
+					} else if(!good_peer_addr(server, ss->realm_options.name, &peer_addr)) {
 						*err_code = 403;
 						*reason = (const u08bits *) "Forbidden IP";
 					} else {
@@ -4072,6 +4080,11 @@ int shutdown_client_connection(turn_turnserver *server, ts_ur_super_session *ss,
 	dec_quota(ss);
 	dec_bps(ss);
 
+	allocation* alloc = get_allocation_ss(ss);
+	if (!is_allocation_valid(alloc)) {
+		force = 1;
+	}
+
 	if(!force && ss->is_mobile) {
 
 		if (ss->client_socket && server->verbose) {
@@ -4246,7 +4259,7 @@ static int create_relay_connection(turn_turnserver* server,
 				   int *err_code, const u08bits **reason,
 				   accept_cb acb) {
 
-	if (server && ss && ss->client_socket) {
+	if (server && ss && ss->client_socket && !ioa_socket_tobeclosed(ss->client_socket)) {
 
 		allocation* a = get_allocation_ss(ss);
 		relay_endpoint_session* newelem = NULL;
@@ -4256,8 +4269,10 @@ static int create_relay_connection(turn_turnserver* server,
 
 			ioa_socket_handle s = NULL;
 
-			if (get_ioa_socket_from_reservation(server->e, in_reservation_token,
-					&s) < 0) {
+			if ((get_ioa_socket_from_reservation(server->e, in_reservation_token,&s,(u08bits*)ss->realm_options.name) < 0)||
+				!s ||
+				ioa_socket_tobeclosed(s)) {
+
 				IOA_CLOSE_SOCKET(s);
 				*err_code = 508;
 				*reason = (const u08bits *)"Cannot find reserved socket";
@@ -4268,16 +4283,12 @@ static int create_relay_connection(turn_turnserver* server,
 
 			newelem = get_relay_session_ss(ss,family);
 
-			IOA_CLOSE_SOCKET(newelem->s);
-
-			ns_bzero(newelem, sizeof(relay_endpoint_session));
-			newelem->s = s;
+			if(newelem->s != s) {
 
-			if(!check_realm_hash(newelem->s,(u08bits*)ss->realm_options.name)) {
 				IOA_CLOSE_SOCKET(newelem->s);
-				*err_code = 508;
-				*reason = (const u08bits *)"Cannot find a valid reserved socket for this realm";
-				return -1;
+
+				ns_bzero(newelem, sizeof(relay_endpoint_session));
+				newelem->s = s;
 			}
 
 			addr_debug_print(server->verbose, get_local_addr_from_ioa_socket(newelem->s), "Local relay addr (RTCP)");

+ 7 - 5
turndb/schema.sql

@@ -1,6 +1,6 @@
 
 CREATE TABLE turnusers_lt (
-    realm varchar(512),
+    realm varchar(512) default '',
     name varchar(512),
     hmackey char(128),
     PRIMARY KEY (realm,name)
@@ -12,19 +12,21 @@ CREATE TABLE turnusers_st (
 );
 
 CREATE TABLE turn_secret (
-	realm varchar(512),
+	realm varchar(512) default '',
     value varchar(512),
 	primary key (realm,value)
 );
 
 CREATE TABLE allowed_peer_ip (
+	realm varchar(512) default '',
 	ip_range varchar(256),
-	primary key (ip_range)
+	primary key (realm,ip_range)
 );
 
 CREATE TABLE denied_peer_ip (
+	realm varchar(512) default '',
 	ip_range varchar(256),
-	primary key (ip_range)
+	primary key (realm,ip_range)
 );
 
 CREATE TABLE turn_origin_to_realm (
@@ -34,7 +36,7 @@ CREATE TABLE turn_origin_to_realm (
 );
 
 CREATE TABLE turn_realm_option (
-	realm varchar(512),
+	realm varchar(512) default '',
 	opt varchar(32),
 	value varchar(128),
 	primary key (realm,opt)

+ 23 - 21
turndb/schema.userdb.redis

@@ -18,23 +18,24 @@ are not bound to a realm). So, there will be key "turn/user/gorst/password"
 and the value will be "hero".
 
 3) For the shared secrets (REST API), several key/value pairs 
-may be used (same as in SQL schema). The key will be 
-"turn/realm/<realm-name>/secret/<arbitrary secret ID>" and the value will be 
-"<secret>". For example, if we have secrets "hero1", "hero2" and "hero3", 
-then we will have keys "turn/realm/north.gov/secret/123",
-"turn/realm/north.gov/secret/234", "turn/realm/north.gov/secret/345" 
-and their values will be  "hero1", "hero2", "hero3". The turnserver will 
-issue command "keys turn/realm/north.gov/secret/*" it it will try to use the 
-obtained keys in arbitrary order.
-
-4) The "white" and "black" peer IP ranges are stored as keys of the
-following form: "turn/allowed-peer-ip/<arbitrary>" or 
-"turn/denied-peer-ip/<arbitrary>"
+may be used (same as in SQL schema). The secrets are stored as members 
+of an unordered set. The name of the set will be 
+"turn/realm/<realm-name>/secret" and the value(s) will be the secret(s).
+For example, if we have secrets "hero1", "hero2" and "hero3", 
+then we will have set "turn/realm/north.gov/secret" with values
+"hero1", "hero2" and "hero3". The turnserver will try to use the 
+secrets in arbitrary order.
+
+4) The "white" and "black" peer IP ranges are stored as unordered sets
+of the following names:  
+"turn/realm/<realm>/allowed-peer-ip" and
+"turn/realm/<realm>/denied-peer-ip".
 
 The meaning of the keys is the same as the meaning of allowed-peer-ip and
-denied-peer-ip turnserver command-line option. The only difference is that 
-the option values are "static" (they remain the same for the lifetime of 
-the turnserver process) but the database records can be dynamically changed 
+denied-peer-ip turnserver command-line option (with the addition of the realm option).
+The only difference is that the turnserver option values are "static" 
+(they remain the same for the lifetime of the turnserver process) but 
+the database records can be dynamically changed 
 and they will be almost immediately "seen" by the turnserver process.
 
 5) For the oAuth authentication, there is a hash structure with the key 
@@ -93,7 +94,7 @@ This example sets user database for:
   	with default realm "north.gov";
   * long-term credentials with open passwords and 
   	with default realm "north.gov";
-  * TURN REST API with shared secret "logen";
+  * TURN REST API with shared secrets "logen", etc;
   * short-term credentials mechanism, with open passwords;
   * Black and white IP peer lists used.
   * Information how to match ORIGIN field with extra
@@ -122,8 +123,8 @@ set turn/realm/north.gov/user/gorst/password "hero"
 set turn/realm/crinna.org/user/whirrun/password "sword"
 set turn/realm/crinna.org/user/stranger-come-knocking/password "civilization"
 
-set turn/realm/north.gov/secret/1368426581 "logen"
-set turn/realm/crinna.org/secret/777888999 "north"
+sadd turn/realm/north.gov/secret "logen" "bloody9"
+sadd turn/realm/crinna.org/secret "north" "library"
 
 set turn/user/ninefingers/password "youhavetoberealistic"
 set turn/user/gorst/password "hero"
@@ -140,10 +141,11 @@ set turn/realm/crinna.org/user-quota 8000
 set turn/origin/http://crinna.org:80 crinna.org
 set turn/origin/https://bligh.edu:443 crinna.org
 
-set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
-set turn/denied-peer-ip/234567 "123::45"
+sadd turn/realm/north.gov/allowed-peer-ip "172.17.13.200" "172.17.13.201"
+sadd turn/realm/crinna.org/allowed-peer-ip "172.17.13.202"
 
-set turn/allowed-peer-ip/345678 "172.17.13.200"
+sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17.133-172.17.19.56" "123::45"
+sadd turn/realm/crinna.org/denied-peer-ip "123::77"
 
 hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-128-CBC' auth_alg 'HMAC-SHA-256-128'
 

+ 12 - 7
turndb/testmongosetup.sh

@@ -4,6 +4,12 @@ mongo $* <<EOF
 
 use coturn;
 
+db.turnusers_lt.ensureIndex({ realm: 1, name: 1 }, { unique: 1 });
+db.turnusers_st.ensureIndex({ name: 1 }, { unique: 1 });
+db.turn_secret.ensureIndex({ realm: 1 }, { unique: 1 });
+db.realm.ensureIndex({ realm: 1 }, { unique: 1 });
+db.oauth_key.ensureIndex({ kid: 1 }, {unique: 1 });
+
 db.turnusers_lt.insert({ realm: 'north.gov', name: 'ninefingers', hmackey: 'bc807ee29df3c9ffa736523fb2c4e8ee' });
 db.turnusers_lt.insert({ realm: 'north.gov', name: 'gorst', hmackey: '7da2270ccfa49786e0115366d3a3d14d' });
 db.turnusers_lt.insert({ realm: 'crinna.org', name: 'whirrun', hmackey: '6972e85e51f36e53b0b61759c5a5219a' });
@@ -23,7 +29,9 @@ db.realm.insert({
     "max-bps" : 500000,
     "user-quota" : 10000,
     "total-quota" : 12000 
-  }
+  },
+  allowed_peer_ip: [ '172.17.13.200', '172.17.13.201' ],
+  denied_peer_ip: ['172.17.13.133-172.17.14.56', '123::45', '172.17.17.133-172.17.19.56']
 });
 
 db.realm.insert({
@@ -33,14 +41,11 @@ db.realm.insert({
     "max-bps" : 400000,
     "user-quota" : 8000,
     "total-quota" : 10000 
-  }
+  },
+  allowed_peer_ip: [ '172.17.13.200', '172.17.13.201' ],
+  denied_peer_ip: ['172.17.13.133-172.17.14.56', '123::45', '123::77']
 });
 
-db.allowed_peer_ip.insert({ ip_range: '172.17.13.200' });
-
-db.denied_peer_ip.insert({ ip_range: '172.17.13.133-172.17.14.56' });
-db.denied_peer_ip.insert({ ip_range: '123::45' });
-
 db.oauth_key.insert({ kid: 'north', 
 					ikm_key: 'Y2FybGVvbg==', 
 					hkdf_hash_func: 'SHA-256', 

+ 6 - 5
turndb/testredisdbsetup.sh

@@ -21,8 +21,8 @@ set turn/realm/north.gov/user/bethod/password "king-of-north"
 set turn/realm/crinna.org/user/whirrun/password "sword"
 set turn/realm/crinna.org/user/stranger-come-knocking/password "civilization"
 
-set turn/realm/north.gov/secret/1368426581 "logen"
-set turn/realm/crinna.org/secret/777888999 "north"
+sadd turn/realm/north.gov/secret "logen" "bloody9"
+sadd turn/realm/crinna.org/secret "north" "library"
 
 set turn/user/ninefingers/password "youhavetoberealistic"
 set turn/user/gorst/password "hero"
@@ -42,10 +42,11 @@ set turn/realm/crinna.org/user-quota 8000
 set turn/origin/http://crinna.org:80 crinna.org
 set turn/origin/https://bligh.edu:443 crinna.org
 
-set turn/denied-peer-ip/123456 "172.17.13.133-172.17.14.56"
-set turn/denied-peer-ip/234567 "123::45"
+sadd turn/realm/north.gov/allowed-peer-ip "172.17.13.200" "172.17.13.201"
+sadd turn/realm/crinna.org/allowed-peer-ip "172.17.13.202"
 
-set turn/allowed-peer-ip/345678 "172.17.13.200"
+sadd turn/realm/north.gov/denied-peer-ip "172.17.13.133-172.17.14.56" "172.17.17.133-172.17.19.56" "123::45"
+sadd turn/realm/crinna.org/denied-peer-ip "123::77"
 
 hmset turn/oauth/kid/north ikm_key Y2FybGVvbg== hkdf_hash_func 'SHA-256' as_rs_alg 'AES-256-CBC' auth_alg 'HMAC-SHA-256-128'
 hmset turn/oauth/kid/oldempire ikm_key YXVsY3Vz hkdf_hash_func 'SHA-256' as_rs_alg 'AEAD-AES-256-GCM'

+ 4 - 0
turndb/testsqldbsetup.sql

@@ -23,9 +23,13 @@ insert into turn_realm_option (realm,opt,value) values('north.gov','user-quota',
 insert into turn_realm_option (realm,opt,value) values('crinna.org','user-quota','8000');
 
 insert into allowed_peer_ip (ip_range) values('172.17.13.200');
+insert into allowed_peer_ip (realm,ip_range) values('north.gov','172.17.13.201');
+insert into allowed_peer_ip (realm,ip_range) values('crinna.org','172.17.13.202');
 
 insert into denied_peer_ip (ip_range) values('172.17.13.133-172.17.14.56');
 insert into denied_peer_ip (ip_range) values('123::45');
+insert into denied_peer_ip (realm,ip_range) values('north.gov','172.17.17.133-172.17.19.56');
+insert into denied_peer_ip (realm,ip_range) values('crinna.org','123::77');
 
 insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('north','Y2FybGVvbg==',0,0,'SHA-256','AES-256-CBC','','HMAC-SHA-256-128','');
 insert into oauth_key (kid,ikm_key,timestamp,lifetime,hkdf_hash_func,as_rs_alg,as_rs_key,auth_alg,auth_key) values('oldempire','YXVsY3Vz',0,0,'SHA-256','AEAD-AES-256-GCM','','','');