Browse Source

Imported Upstream version 4.5.0.6

Oleg Moskalenko 8 years ago
parent
commit
ecd1519f3b

+ 7 - 0
ChangeLog

@@ -1,3 +1,10 @@
+10/17/2016 Oleg Moskalenko <[email protected]>
+Version 4.5.0.6 'dan Eider':
+	- Typos in the text fixed.
+	- TLS1.2 support fixed.
+	- uclient minor performance tweak.
+	- Issue #113 fixed (by David Benjamin)
+
 08/27/2016 Oleg Moskalenko <[email protected]>
 Version 4.5.0.5 'dan Eider':
 	- Typos in the text fixed.

+ 2 - 0
README.turnserver

@@ -153,6 +153,8 @@ Flags:
 
 -o, --daemon		Run server as daemon.
 
+--prod       	 	Production mode: hide the software version.
+
 -f, --fingerprint	Use fingerprints in the TURN messages. If an incoming request
 			contains a fingerprint, then TURN server will always add 
 			fingerprints to the messages in this session, regardless of the

+ 2 - 2
README.turnutils

@@ -39,7 +39,7 @@ be configured to be able to work properly!
 
 6.	turnutils_oauth: a utility that provides OAuth access_token 
 generation(AEAD encryption), validation and decryption. This utility inputs 
-all the keys and lifetimes and any related informations that needed for 
+all the keys and lifetimes and any related information that needed for 
 creation and validationi of an access_token. It outputs a JSON with all OAuth 
 PoP parameters that need to pass to the client. Output is generated accoriding 
 RFC7635 Appendix B, Figure 8. 
@@ -298,7 +298,7 @@ turnutils_oauth utilitiy provides help in OAuth access_token encryption and/or
 decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps 
 for an Auth Server in access_token creation, and also for debuging purposes it 
 helps the access_token validation and decryption. This utility inputs all the 
-keys and lifetimes and any related informations that are needed for encryption 
+keys and lifetimes and any related information that are needed for encryption 
 or decryption of an access_token. It outputs a JSON with all OAuth PoP 
 parameters that need to pass to the client. Output is generated accoriding 
 RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server 

+ 11 - 7
make-man.sh

@@ -1,6 +1,7 @@
 #!/bin/sh
 
-rm -rf man/man1/*
+mkdir -p man/man1
+rm -rf man/man1/*1
 
 txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1
 
@@ -8,10 +9,13 @@ txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclien
 
 txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1
 
-cd man/man1; ln -s turnutils.1 turnutils_uclient.1;cd ../..
-cd man/man1; ln -s turnutils.1 turnutils_peer.1;cd ../..
-cd man/man1; ln -s turnutils.1 turnutils_stunclient.1;cd ../..
-cd man/man1; ln -s turnutils.1 turnutils_natdiscovery.1;cd ../..
-cd man/man1; ln -s turnutils.1 turnutils_oauth.1;cd ../..
-cd man/man1; ln -s turnserver.1 coturn.1;cd ../..
+cd man/man1
 
+ln -s turnutils.1 turnutils_uclient.1
+ln -s turnutils.1 turnutils_peer.1
+ln -s turnutils.1 turnutils_stunclient.1
+ln -s turnutils.1 turnutils_natdiscovery.1
+ln -s turnutils.1 turnutils_oauth.1
+ln -s turnserver.1 coturn.1
+
+cd ../..

+ 1 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "25 September 2016" "" ""
+.TH TURN 1 "13 November 2016" "" ""
 .SH GENERAL INFORMATION
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 

+ 5 - 1
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "25 September 2016" "" ""
+.TH TURN 1 "13 November 2016" "" ""
 .SH GENERAL INFORMATION
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
@@ -228,6 +228,10 @@ Extra verbose mode, very annoying and not recommended.
 Run server as daemon.
 .TP
 .B
+\fB\-\-prod\fP
+Production mode: hide the software version.
+.TP
+.B
 \fB\-f\fP, \fB\-\-fingerprint\fP
 Use fingerprints in the TURN messages. If an incoming request
 contains a fingerprint, then TURN server will always add 

+ 3 - 3
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
-.TH TURN 1 "25 September 2016" "" ""
+.TH TURN 1 "13 November 2016" "" ""
 .SH GENERAL INFORMATION
 
 A set of turnutils_* programs provides some utility functionality to be used
@@ -53,7 +53,7 @@ be configured to be able to work properly!
 6.
 \fIturnutils_oauth\fP: a utility that provides OAuth access_token 
 \fBgeneration\fP(AEAD encryption), validation and decryption. This utility inputs 
-all the keys and lifetimes and any related informations that needed for 
+all the keys and lifetimes and any related information that needed for 
 creation and validationi of an access_token. It outputs a JSON with all OAuth 
 PoP parameters that need to pass to the client. Output is generated accoriding 
 RFC7635 Appendix B, Figure 8. 
@@ -450,7 +450,7 @@ $ \fIturnutils_oauth\fP [\fIoptions\fP]
 decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps 
 for an Auth Server in access_token creation, and also for debuging purposes it 
 helps the access_token validation and decryption. This utility inputs all the 
-keys and lifetimes and any related informations that are needed for encryption 
+keys and lifetimes and any related information that are needed for encryption 
 or decryption of an access_token. It outputs a JSON with all OAuth PoP 
 parameters that need to pass to the client. Output is generated accoriding 
 RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server 

+ 106 - 0
netarch.txt

@@ -0,0 +1,106 @@
+	Coturn architecture, part 1 
+
+	Network architecture
+
+I. INTRODUCTION
+
+This document assumes that the reader is familiar with the various TURN specifications.
+The goal of this document is to provide general information for the Coturn
+administrators and code developers about organization of the network interaction
+in Coturn.
+
+Coturn is a TURN relay server that has several general types of main network interaction:
+
+1) Session establishment and maintenance negotiations with the client application.
+2) Accepting packets to be relayed from the Client application, on the client-facing
+sockets, and relaying those packets, through the relay sockets, to the Peer application.
+3) Accepting packets to be relayed from the Peer application, on the peer-facing
+relay sockets, and relaying those packets, through the Client sockets, to the Client
+application.
+
+There are other, secondary, interations:
+
+1) Communications with the database servers.
+2) Communications with the telnet admin console.
+3) Communications with the client admin browser, over HTTPS.
+
+This document concentrates on the main network communications. It will describe
+how those communicatiuons are organized in the Coturn code.
+
+The key to the understanding how Coturn works is the notions of "listeners" and 
+"general relay servers". 
+
+II. LISTENERS
+
+In Coturn, a "listener" is the entity that initiates dialog with the new client. When a
+new client sends its first packet to TURN, then it is initially accepted by the UDP
+listener (the code in dtls_listener.c) or by TCP listener (the code in tls_listener.c).
+The listeners are smart enough to recognize whether the new session is a TLS session or
+"plain" protocol session, and it handles necessary SSL keys and negotiations.
+
+The listener then creates a client endpoint (depending on the protocol and on the 
+"network engine" - see below).
+
+What happens next depends on the "network engine" that the Coturn is using in runtime.
+If the relay server that will be handling that session is located in a different thread,
+then the listener will "send" the endpoint to that relay server (see the "connect_cb"
+callback function). If the relay server is located in the same thread as the listener,
+then the listener will call the session establishment function itself. See the function
+open_client_connection_session() and where and how it is called in various cases,
+for reference.
+
+The listeners (and the relay servers) configuration is initiated in the function
+setup_servers() in netengine.c. First, setup_listener() creates the necessary generic 
+data structures for the listeners. Second, network-engine-specific functions accosiate 
+listeners with the execution threads and with the relay servers.
+
+There may be multiple listeners in the server, and they may be running in different
+threads.
+
+III. RELAY SERVERS
+
+The relay servers take control over the client sessions after the initial contact was
+established by the listeners. The relay server will be reading the session sockets
+(the client and the relay sockets) and perform the necessary actions on them, according
+to the TURN specs.
+
+There can be multiple relay servers in the system, running in different threads.
+The client sessions are distributed among them in fairly random manner, for load
+balancing.
+
+The relay server will be responsible for the session as long as the session exists.
+It will exclusively handle all session communications. Thus, the session will stay
+within the same thread for its lifetime. The performance benefit is that there will be
+no CPU context switching when the session packets are handled.
+
+There is one exception when a relay server will transfer a session to another relay
+server: the mobility functionality. When the client address changes, it may require
+that the session must be using a different thread - and a different relay server, as
+the result. The the original relay server will have to pack the session, say
+"farewell" to it and ship it to another relay server. The destination relay server
+will adopt the session and the session will stay with the new relay server - until the
+next client address change.
+
+IV. NETWORK ENGINES
+
+UDP communications are rather under-developed, comparing to the TCP communications,
+in modern operational systems. Because TURN stresses UDP communications, UDP
+performance is very important. Different OS's have different capabilities, so Coturn,
+being a portable server, had to employ different strategies for different systems. 
+
+There are three "network engines" (or rather "network threading patterns") implemented
+in Coturn:
+
+1) UDP listener thread per frontend IP (FreeBSD, Solaris) with multiple UDP/TCP
+relay servers. Listeners and relays are in different threads.
+//TODO
+
+2) UDP listener and relay thread per frontend IP, with multiple TCP relay threads
+(early Linux). The listener and the relay servers are related, form pairs and are
+working in the same thread.
+//TODO
+
+3) Multiple UDP and TCP listeners and relay per each frontend IP (advanced Linuxes).
+The listener and the relay servers are related, form pairs and are
+working in the same thread.
+//TODO

+ 1 - 1
rpm/build.settings.sh

@@ -2,7 +2,7 @@
 
 # Common settings script.
 
-TURNVERSION=4.5.0.5
+TURNVERSION=4.5.0.6
 BUILDDIR=~/rpmbuild
 ARCH=`uname -p`
 TURNSERVER_GIT_URL=https://github.com/coturn/coturn.git

+ 3 - 1
rpm/turnserver.spec

@@ -1,5 +1,5 @@
 Name:		turnserver
-Version:	4.5.0.5
+Version:	4.5.0.6
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 
@@ -295,6 +295,8 @@ fi
 %{_includedir}/turn/client/TurnMsgLib.h
 
 %changelog
+* Mon Oct 17 2016 Oleg Moskalenko <[email protected]>
+  - Sync to 4.5.0.6
 * Sat Aug 27 2016 Oleg Moskalenko <[email protected]>
   - Sync to 4.5.0.5
 * Sat Aug 20 2016 Oleg Moskalenko <[email protected]>

+ 4 - 4
src/apps/common/ns_turn_utils.c

@@ -651,11 +651,11 @@ int get_canonic_origin(const char* o, char *co, int sz)
 			}
 			evhttp_uri_free(uri);
 		}
-	}
 
-	if(ret<0) {
-		strncpy(co,o,sz);
-		co[sz]=0;
+		if(ret<0) {
+			strncpy(co,o,sz);
+			co[sz]=0;
+		}
 	}
 
 	return ret;

+ 9 - 3
src/apps/relay/mainrelay.c

@@ -100,7 +100,7 @@ DH_1066, "", "", "",
 0,
 #endif
 
-TURN_VERBOSE_NONE,0,0,
+TURN_VERBOSE_NONE,0,0,0,
 "/var/run/turnserver.pid",
 DEFAULT_STUN_PORT,DEFAULT_STUN_TLS_PORT,0,0,1,
 0,0,0,0,
@@ -435,6 +435,7 @@ static char Usage[] = "Usage: turnserver [options]\n"
 " -v, --verbose					'Moderate' verbose mode.\n"
 " -V, --Verbose					Extra verbose mode, very annoying (for debug purposes only).\n"
 " -o, --daemon					Start process as daemon (detach from current shell).\n"
+" --prod       	 				Production mode: hide the software version.\n"
 " -f, --fingerprint				Use fingerprints in the TURN messages.\n"
 " -a, --lt-cred-mech				Use the long-term credential mechanism.\n"
 " -z, --no-auth					Do not use any credential mechanism, allow anonymous access.\n"
@@ -740,7 +741,8 @@ enum EXTRA_OPTS {
 	ADMIN_TOTAL_QUOTA_OPT,
 	ADMIN_USER_QUOTA_OPT,
 	SERVER_NAME_OPT,
-	OAUTH_OPT
+	OAUTH_OPT,
+	PROD_OPT
 };
 
 struct myoption {
@@ -803,6 +805,7 @@ static const struct myoption long_options[] = {
 				{ "verbose", optional_argument, NULL, 'v' },
 				{ "Verbose", optional_argument, NULL, 'V' },
 				{ "daemon", optional_argument, NULL, 'o' },
+				{ "prod", optional_argument, NULL, PROD_OPT },
 				{ "fingerprint", optional_argument, NULL, 'f' },
 				{ "check-origin-consistency", optional_argument, NULL, CHECK_ORIGIN_CONSISTENCY_OPT },
 				{ "no-udp", optional_argument, NULL, NO_UDP_OPT },
@@ -1167,6 +1170,9 @@ static void set_option(int c, char *value)
 			anon_credentials = 1;
 		}
 		break;
+	case PROD_OPT:
+		turn_params.prod = get_bool_value(value);
+		break;
 	case 'f':
 		turn_params.fingerprint = get_bool_value(value);
 		break;
@@ -2450,7 +2456,7 @@ static int ServerALPNCallback(SSL *ssl,
 		}
 		if((current_len == ha_len) && (memcmp(ptr+1,HTTP_ALPN,ha_len)==0)) {
 			*out = ptr+1;
-			*outlen = ta_len;
+			*outlen = ha_len;
 			SSL_set_app_data(ssl,HTTP_ALPN);
 			found_http = 1;
 		}

+ 1 - 0
src/apps/relay/mainrelay.h

@@ -202,6 +202,7 @@ typedef struct _turn_params_ {
 
   int verbose;
   int turn_daemon;
+  int prod;
 
   int do_not_use_config_file;
 

+ 1 - 0
src/apps/relay/netengine.c

@@ -1638,6 +1638,7 @@ static void setup_relay_server(struct relay_server *rs, ioa_engine_handle e, int
 			 &turn_params.permission_lifetime,
 			 &turn_params.stun_only,
 			 &turn_params.no_stun,
+			 &turn_params.prod,
 			 &turn_params.alternate_servers_list,
 			 &turn_params.tls_alternate_servers_list,
 			 &turn_params.aux_servers_list,

+ 1 - 1
src/apps/relay/ns_ioalib_engine_impl.c

@@ -2179,7 +2179,7 @@ static TURN_TLS_TYPE check_tentative_tls(ioa_socket_raw fd)
 	if(len>0 && ((size_t)len == sizeof(s))) {
 		if((s[0]==22)&&(s[1]==3)&&(s[5]==1)&&(s[9]==3)) {
 			char max_supported = (char)(TURN_TLS_TOTAL-2);
-			if(s[10] >= max_supported)
+			if(s[10] > max_supported)
 				ret = TURN_TLS_SSL23; /* compatibility mode */
 			else
 				ret = (TURN_TLS_TYPE)(s[10]+1);

+ 3 - 1
src/apps/relay/turn_admin_server.c

@@ -1512,7 +1512,9 @@ static void https_finish_page(struct str_buffer *sb, ioa_socket_handle s, int cc
 	str_buffer_append(sb,"</body>\r\n</html>\r\n");
 
 	send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: ");
-	send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE);
+	if(!turn_params.prod) {
+		send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE);
+	}
 	send_str_from_ioa_socket_tcp(s,"\r\n");
 	send_str_from_ioa_socket_tcp(s,get_http_date_header());
 	if(cclose) {

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

@@ -285,7 +285,7 @@ int send_buffer(app_ur_conn_info *clnet_info, stun_buffer* message, int data_con
 		while (left > 0) {
 			do {
 				rc = send(fd, buffer, left, 0);
-			} while (rc < 0 && ((errno == EINTR) || (errno == ENOBUFS)));
+			} while (rc <= 0 && ((errno == EINTR) || (errno == ENOBUFS) || (errno == EAGAIN)));
 			if (rc > 0) {
 				left -= (size_t) rc;
 				buffer += rc;

+ 1 - 1
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.5.0.5"
+#define TURN_SERVER_VERSION "4.5.0.6"
 #define TURN_SERVER_VERSION_NAME "dan Eider"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 

+ 30 - 16
src/server/ns_turn_server.c

@@ -57,6 +57,14 @@ static inline int get_family(int stun_family) {
 
 ////////////////////////////////////////////////
 
+const char * get_version(turn_turnserver *server) {
+	if(server && !server->prod) {
+		return (const char *) TURN_SOFTWARE;
+	} else {
+		return (const char *) "None";
+	}
+}
+
 #define MAX_NUMBER_OF_UNKNOWN_ATTRS (128)
 
 int TURN_MAX_ALLOCATE_TIMEOUT = 60;
@@ -1715,8 +1723,8 @@ static int handle_turn_refresh(turn_turnserver *server,
 										ioa_network_buffer_set_size(nbh,len);
 
 										{
-											static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-											static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+											const u08bits *field = (const u08bits *) get_version(server);
+											size_t fsz = strlen(get_version(server));
 											size_t len = ioa_network_buffer_get_size(nbh);
 											stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 											ioa_network_buffer_set_size(nbh, len);
@@ -2182,8 +2190,8 @@ static void tcp_peer_accept_connection(ioa_socket_handle s, void *arg)
 		ioa_network_buffer_set_size(nbh,len);
 
 		{
-			static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-			static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+			const u08bits *field = (const u08bits *) get_version(server);
+			size_t fsz = strlen(get_version(server));
 			size_t len = ioa_network_buffer_get_size(nbh);
 			stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 			ioa_network_buffer_set_size(nbh, len);
@@ -2459,8 +2467,8 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co
 		}
 
 		{
-			static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-			static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+			size_t fsz = strlen(get_version(server));
+			const u08bits *field = (const u08bits *) get_version(server);
 			size_t len = ioa_network_buffer_get_size(nbh);
 			stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 			ioa_network_buffer_set_size(nbh, len);
@@ -3765,8 +3773,8 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
 					}
 
 					{
-						static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-						static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+						const u08bits *field = (const u08bits *) get_version(server);
+						size_t fsz = strlen(get_version(server));
 						size_t len = ioa_network_buffer_get_size(nbh);
 						stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 						ioa_network_buffer_set_size(nbh, len);
@@ -3866,8 +3874,8 @@ static int handle_turn_command(turn_turnserver *server, ts_ur_super_session *ss,
 		}
 
 		{
-			static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-			static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+			const u08bits *field = (const u08bits *) get_version(server);
+			size_t fsz = strlen(get_version(server));
 			size_t len = ioa_network_buffer_get_size(nbh);
 			stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 			ioa_network_buffer_set_size(nbh, len);
@@ -3947,11 +3955,13 @@ static int handle_old_stun_command(turn_turnserver *server, ts_ur_super_session
 				}
 
 				{
-					size_t newsz = (((sizeof(TURN_SOFTWARE))>>2) + 1)<<2;
+					size_t oldsz = strlen(get_version(server));
+					size_t newsz = (((oldsz)>>2) + 1)<<2;
 					u08bits software[120];
+					ns_bzero(software,sizeof(software));
 					if(newsz>sizeof(software))
 						newsz = sizeof(software);
-					ns_bcopy(TURN_SOFTWARE,software,newsz);
+					ns_bcopy(get_version(server),software,oldsz);
 					size_t len = ioa_network_buffer_get_size(nbh);
 					stun_attr_add_str(ioa_network_buffer_data(nbh), &len, OLD_STUN_ATTRIBUTE_SERVER, software, newsz);
 					ioa_network_buffer_set_size(nbh, len);
@@ -3999,11 +4009,13 @@ static int handle_old_stun_command(turn_turnserver *server, ts_ur_super_session
 		}
 
 		{
-			size_t newsz = (((sizeof(TURN_SOFTWARE))>>2) + 1)<<2;
+			size_t oldsz = strlen(get_version(server));
+			size_t newsz = (((oldsz)>>2) + 1)<<2;
 			u08bits software[120];
+			ns_bzero(software,sizeof(software));
 			if(newsz>sizeof(software))
 				newsz = sizeof(software);
-			ns_bcopy(TURN_SOFTWARE,software,newsz);
+			ns_bcopy(get_version(server),software,oldsz);
 			size_t len = ioa_network_buffer_get_size(nbh);
 			stun_attr_add_str(ioa_network_buffer_data(nbh), &len, OLD_STUN_ATTRIBUTE_SERVER, software, newsz);
 			ioa_network_buffer_set_size(nbh, len);
@@ -4727,8 +4739,8 @@ static void peer_input_handler(ioa_socket_handle s, int event_type,
 				ioa_network_buffer_set_size(nbh,len);
 
 				{
-					static const u08bits *field = (const u08bits *) TURN_SOFTWARE;
-					static const size_t fsz = sizeof(TURN_SOFTWARE)-1;
+					const u08bits *field = (const u08bits *) get_version(server);
+					size_t fsz = strlen(get_version(server));
 					size_t len = ioa_network_buffer_get_size(nbh);
 					stun_attr_add_str(ioa_network_buffer_data(nbh), &len, STUN_ATTRIBUTE_SOFTWARE, field, fsz);
 					ioa_network_buffer_set_size(nbh, len);
@@ -4801,6 +4813,7 @@ void init_turn_server(turn_turnserver* server,
 		vintp permission_lifetime,
 		vintp stun_only,
 		vintp no_stun,
+		vintp prod,
 		turn_server_addrs_list_t *alternate_servers_list,
 		turn_server_addrs_list_t *tls_alternate_servers_list,
 		turn_server_addrs_list_t *aux_servers_list,
@@ -4859,6 +4872,7 @@ void init_turn_server(turn_turnserver* server,
 	server->permission_lifetime = permission_lifetime;
 	server->stun_only = stun_only;
 	server->no_stun = no_stun;
+	server->prod = prod;
 
 	server->dont_fragment = dont_fragment;
 	server->fingerprint = fingerprint;

+ 4 - 0
src/server/ns_turn_server.h

@@ -120,6 +120,7 @@ struct _turn_turnserver {
         vintp permission_lifetime;
 	vintp stun_only;
 	vintp no_stun;
+	vintp prod;
 	vintp secure_stun;
 	turn_credential_type ct;
 	get_alt_addr_cb alt_addr_cb;
@@ -170,6 +171,8 @@ struct _turn_turnserver {
 	const char* oauth_server_name;
 };
 
+const char * get_version(turn_turnserver *server);
+
 ///////////////////////////////////////////
 
 void init_turn_server(turn_turnserver* server,
@@ -192,6 +195,7 @@ void init_turn_server(turn_turnserver* server,
                                     vintp permission_lifetime,
 				    vintp stun_only,
 				    vintp no_stun,
+				    vintp prod,
 				    turn_server_addrs_list_t *alternate_servers_list,
 				    turn_server_addrs_list_t *tls_alternate_servers_list,
 				    turn_server_addrs_list_t *aux_servers_list,