Преглед изворни кода

Imported Upstream version 4.4.2.3

Oleg Moskalenko пре 10 година
родитељ
комит
51dbe81aaa

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2/28/2015 Oleg Moskalenko <[email protected]>
+Version 4.4.2.3 'Ardee West':
+	- bandwidth control fixed;
+	- STUN/TURN control traffic counted separately from data traffic,
+	for the sake of the bandwidth control;
+	- higher bandwidth limit capacity on 64 bits systems;
+	- redis operations with the realm options fixed;
+	
 2/18/2015 Oleg Moskalenko <[email protected]>
 Version 4.4.2.2 'Ardee West':
 	- admin_user table schema fixed;

BIN
examples/var/db/turndb


+ 1 - 1
rpm/build.settings.sh

@@ -2,7 +2,7 @@
 
 # Common settings script.
 
-TURNVERSION=4.4.2.2
+TURNVERSION=4.4.2.3
 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.4.2.2
+Version:	4.4.2.3
 Release:	0%{dist}
 Summary:	Coturn TURN Server
 
@@ -288,6 +288,8 @@ fi
 %{_includedir}/turn/client/TurnMsgLib.h
 
 %changelog
+* Sat Feb 28 2015 Oleg Moskalenko <[email protected]>
+  - Sync to 4.4.2.3
 * Wed Feb 18 2015 Oleg Moskalenko <[email protected]>
   - Sync to 4.4.2.2
 * Tue Feb 3 2015 Oleg Moskalenko <[email protected]>

+ 7 - 10
src/apps/relay/dbdrivers/dbd_mongo.c

@@ -1178,24 +1178,21 @@ static void mongo_reread_realms(secrets_list_t * realms_list) {
 					if (bson_iter_init(&options_iter, &options)) {
 						while (bson_iter_next(&options_iter)) {
 							const char * _k = bson_iter_key(&options_iter);
-							int32_t _v = 0;
+							uint64_t _v = 0;
 							if (BSON_ITER_HOLDS_DOUBLE(&options_iter)) {
-								_v = (int32_t) bson_iter_double(&options_iter);
+								_v = (uint64_t) bson_iter_double(&options_iter);
 							} else if (BSON_ITER_HOLDS_INT32(&options_iter)) {
-								_v = bson_iter_int32(&options_iter);
+								_v = (uint64_t)bson_iter_int32(&options_iter);
 							} else if (BSON_ITER_HOLDS_INT64(&options_iter)) {
-								_v = (int32_t) bson_iter_int64(&options_iter);
+								_v = (uint64_t) bson_iter_int64(&options_iter);
 							}
 							if (_v) {
 								if (!strcmp(_k, "max-bps"))
-									rp->options.perf_options.max_bps
-											= (band_limit_t) _v;
+									rp->options.perf_options.max_bps = (band_limit_t) _v;
 								else if (!strcmp(_k, "total-quota"))
-									rp->options.perf_options.total_quota
-											= (vint) _v;
+									rp->options.perf_options.total_quota = (vint) _v;
 								else if (!strcmp(_k, "user-quota"))
-									rp->options.perf_options.user_quota
-											= (vint) _v;
+									rp->options.perf_options.user_quota = (vint) _v;
 								else {
 									TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,
 											"Unknown realm option: %s\n", _k);

+ 1 - 1
src/apps/relay/dbdrivers/dbd_mysql.c

@@ -1089,7 +1089,7 @@ static void mysql_reread_realms(secrets_list_t * realms_list) {
 								vval[sz]=0;
 								realm_params_t* rp = get_realm(rval);
 								if(!strcmp(oval,"max-bps"))
-									rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
+									rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10);
 								else if(!strcmp(oval,"total-quota"))
 									rp->options.perf_options.total_quota = (vint)atoi(vval);
 								else if(!strcmp(oval,"user-quota"))

+ 1 - 1
src/apps/relay/dbdrivers/dbd_pgsql.c

@@ -819,7 +819,7 @@ static void pgsql_reread_realms(secrets_list_t * realms_list) {
 					if(rval && oval && vval) {
 						realm_params_t* rp = get_realm(rval);
 						if(!strcmp(oval,"max-bps"))
-							rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
+							rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10);
 						else if(!strcmp(oval,"total-quota"))
 							rp->options.perf_options.total_quota = (vint)atoi(vval);
 						else if(!strcmp(oval,"user-quota"))

+ 28 - 17
src/apps/relay/dbdrivers/dbd_redis.c

@@ -1176,7 +1176,7 @@ static void redis_reread_realms(secrets_list_t * realms_list) {
 
 			clean_secrets_list(&keys);
 
-      update_o_to_realm(o_to_realm_new);
+			update_o_to_realm(o_to_realm_new);
 
 			turnFreeRedisReply(reply);
 		}
@@ -1192,25 +1192,36 @@ static void redis_reread_realms(secrets_list_t * realms_list) {
 			for (i = 0; i<rlsz; ++i) {
 				char *realm = realms_list->secrets[i];
 				realm_params_t* rp = get_realm(realm);
-				unsigned long value = 0;
-				if(!set_redis_realm_opt(realm,"max-bps",&value)) {
-					lock_realms();
-					rp->options.perf_options.max_bps = turn_params.max_bps;
-					unlock_realms();
+				{
+					unsigned long value = 0;
+					if(!set_redis_realm_opt(realm,"max-bps",&value)) {
+						lock_realms();
+						rp->options.perf_options.max_bps = turn_params.max_bps;
+						unlock_realms();
+					} else {
+						rp->options.perf_options.max_bps = (band_limit_t)value;
+					}
 				}
-				rp->options.perf_options.max_bps = (band_limit_t)value;
-				if(!set_redis_realm_opt(realm,"total-quota",&value)) {
-					lock_realms();
-					rp->options.perf_options.total_quota = turn_params.total_quota;
-					unlock_realms();
+				{
+					unsigned long value = 0;
+					if(!set_redis_realm_opt(realm,"total-quota",&value)) {
+						lock_realms();
+						rp->options.perf_options.total_quota = turn_params.total_quota;
+						unlock_realms();
+					} else {
+						rp->options.perf_options.total_quota = (vint)value;
+					}
 				}
-				rp->options.perf_options.total_quota = (vint)value;
-				if(!set_redis_realm_opt(realm,"user-quota",&value)) {
-					lock_realms();
-					rp->options.perf_options.user_quota = turn_params.user_quota;
-					unlock_realms();
+				{
+					unsigned long value = 0;
+					if(!set_redis_realm_opt(realm,"user-quota",&value)) {
+						lock_realms();
+						rp->options.perf_options.user_quota = turn_params.user_quota;
+						unlock_realms();
+					} else {
+						rp->options.perf_options.user_quota = (vint)value;
+					}
 				}
-				rp->options.perf_options.user_quota = (vint)value;
 			}
 		}
 	}

+ 1 - 1
src/apps/relay/dbdrivers/dbd_sqlite.c

@@ -1109,7 +1109,7 @@ static void sqlite_reread_realms(secrets_list_t * realms_list)
 
 						realm_params_t* rp = get_realm(rval);
 						if(!strcmp(oval,"max-bps"))
-							rp->options.perf_options.max_bps = (band_limit_t)atol(vval);
+							rp->options.perf_options.max_bps = (band_limit_t)strtoul(vval,NULL,10);
 						else if(!strcmp(oval,"total-quota"))
 							rp->options.perf_options.total_quota = (vint)atoi(vval);
 						else if(!strcmp(oval,"user-quota"))

+ 12 - 10
src/apps/relay/dtls_listener.c

@@ -367,18 +367,20 @@ static int handle_udp_packet(dtls_listener_relay_server_type *server,
 			}
 		}
 
-		if (s && s->read_cb && sm->m.sm.nd.nbh) {
+		if(ioa_socket_check_bandwidth(s,sm->m.sm.nd.nbh,1)) {
 			s->e = ioa_eng;
-			s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1);
-			ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh);
-			sm->m.sm.nd.nbh = NULL;
+			if (s && s->read_cb && sm->m.sm.nd.nbh) {
+				s->read_cb(s, IOA_EV_READ, &(sm->m.sm.nd), s->read_ctx, 1);
+				ioa_network_buffer_delete(ioa_eng, sm->m.sm.nd.nbh);
+				sm->m.sm.nd.nbh = NULL;
 
-			if (ioa_socket_tobeclosed(s)) {
-				ts_ur_super_session *ss = (ts_ur_super_session *) s->session;
-				if (ss) {
-					turn_turnserver *server = (turn_turnserver *) ss->server;
-					if (server) {
-						shutdown_client_connection(server, ss, 0, "UDP packet processing error");
+				if (ioa_socket_tobeclosed(s)) {
+					ts_ur_super_session *ss = (ts_ur_super_session *) s->session;
+					if (ss) {
+						turn_turnserver *server = (turn_turnserver *) ss->server;
+						if (server) {
+							shutdown_client_connection(server, ss, 0, "UDP packet processing error");
+						}
 					}
 				}
 			}

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

@@ -68,7 +68,7 @@ static void write_http_echo(ioa_socket_handle s)
 			len_http = strlen(data_http);
 			ns_bcopy(data_http,data,len_http);
 			ioa_network_buffer_set_size(nbh_http,len_http);
-			send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE);
+			send_data_from_ioa_socket_nbh(s, NULL, nbh_http, TTL_IGNORE, TOS_IGNORE,NULL);
 		}
 	}
 }

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

@@ -1203,12 +1203,12 @@ static void set_option(int c, char *value)
 		get_realm(NULL)->options.perf_options.total_quota = atoi(value);
 		break;
 	case 's':
-		turn_params.max_bps = (band_limit_t)atoi(value);
-		get_realm(NULL)->options.perf_options.max_bps = atoi(value);
+		turn_params.max_bps = (band_limit_t)strtoul(value,NULL,10);
+		get_realm(NULL)->options.perf_options.max_bps = (band_limit_t)strtoul(value,NULL,10);
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed per session\n",(unsigned long)turn_params.max_bps);
 		break;
 	case 'B':
-		turn_params.bps_capacity = (band_limit_t)atoi(value);
+		turn_params.bps_capacity = (band_limit_t)strtoul(value,NULL,10);
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%lu bytes per second allowed, combined server capacity\n",(unsigned long)turn_params.bps_capacity);
 		break;
 	case CHECK_ORIGIN_CONSISTENCY_OPT:

+ 36 - 26
src/apps/relay/ns_ioalib_engine_impl.c

@@ -326,9 +326,6 @@ static void free_blist_elem(ioa_engine_handle e, stun_buffer_list_elem *buf_elem
 
 /************** ENGINE *************************/
 
-#define TURN_JIFFIE_SIZE (3)
-#define TURN_JIFFIE_LENGTH (1<<(TURN_JIFFIE_SIZE))
-
 static void timer_handler(ioa_engine_handle e, void* arg) {
 
   UNUSED_ARG(arg);
@@ -336,7 +333,7 @@ static void timer_handler(ioa_engine_handle e, void* arg) {
   _log_time_value = turn_time();
   _log_time_value_set = 1;
 
-  e->jiffie = _log_time_value >> TURN_JIFFIE_SIZE;
+  e->jiffie = _log_time_value;
 }
 
 ioa_engine_handle create_ioa_engine(super_memory_t *sm,
@@ -640,51 +637,61 @@ void delete_ioa_timer(ioa_timer_handle th)
 
 /************** SOCKETS HELPERS ***********************/
 
-static int ioa_socket_check_bandwidth(ioa_socket_handle s, size_t sz, int read)
+int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nbh, int read)
 {
-	if(read && s && (s->e) && sz &&
-			((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) &&
-			(s->session)) {
+	if(s && (s->e) && nbh &&
+		((s->sat == CLIENT_SOCKET) || (s->sat == RELAY_SOCKET) || (s->sat == RELAY_RTCP_SOCKET)) &&
+		(s->session)) {
+
+		size_t sz = ioa_network_buffer_get_size(nbh);
 
 		band_limit_t max_bps = s->session->bps;
 
 		if(max_bps<1)
 			return 1;
 
-		max_bps = max_bps<<TURN_JIFFIE_SIZE;
+		struct traffic_bytes *traffic = &(s->data_traffic);
+
+		if(s->sat == CLIENT_SOCKET) {
+			u08bits *buf = ioa_network_buffer_data(nbh);
+			if(stun_is_command_message_str(buf,sz)) {
+				u16bits method = stun_get_method_str(buf,sz);
+				if((method != STUN_METHOD_SEND) && (method != STUN_METHOD_DATA)) {
+					traffic = &(s->control_traffic);
+				}
+			}
+		}
 
 		band_limit_t bsz = (band_limit_t)sz;
 
 		if(s->jiffie != s->e->jiffie) {
 
 			s->jiffie = s->e->jiffie;
-			s->jiffie_bytes_read = 0;
-			s->jiffie_bytes_write = 0;
+			traffic->jiffie_bytes_read = 0;
+			traffic->jiffie_bytes_write = 0;
 
 			if(bsz > max_bps) {
-
 				return 0;
-
 			} else {
 				if(read)
-					s->jiffie_bytes_read = bsz;
+					traffic->jiffie_bytes_read = bsz;
 				else
-					s->jiffie_bytes_write = bsz;
+					traffic->jiffie_bytes_write = bsz;
 				return 1;
 			}
 		} else {
 			band_limit_t nsz;
 			if(read)
-				nsz = s->jiffie_bytes_read + bsz;
+				nsz = traffic->jiffie_bytes_read + bsz;
 			else
-				nsz = s->jiffie_bytes_write + bsz;
+				nsz = traffic->jiffie_bytes_write + bsz;
 			if(nsz > max_bps) {
 				return 0;
 			} else {
 				if(read)
-					s->jiffie_bytes_read = nsz;
+					traffic->jiffie_bytes_read = nsz;
 				else
-					s->jiffie_bytes_write = nsz;
+					traffic->jiffie_bytes_write = nsz;
 				return 1;
 			}
 		}
@@ -2385,11 +2392,13 @@ static int socket_input_worker(ioa_socket_handle s)
 	}
 
 	if ((ret!=-1) && (len >= 0)) {
-		if(ioa_socket_check_bandwidth(s,(size_t)len,1)) {
-			if(app_msg_len)
-				buf_elem->buf.len = app_msg_len;
-			else
-				buf_elem->buf.len = len;
+
+		if(app_msg_len)
+			buf_elem->buf.len = app_msg_len;
+		else
+			buf_elem->buf.len = len;
+
+		if(ioa_socket_check_bandwidth(s,buf_elem,1)) {
 
 			if(s->read_cb) {
 				ioa_net_data nd;
@@ -2966,7 +2975,7 @@ int udp_send(ioa_socket_handle s, const ioa_addr* dest_addr, const s08bits* buff
 
 int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr,
 				ioa_network_buffer_handle nbh,
-				int ttl, int tos)
+				int ttl, int tos, int *skip)
 {
 	int ret = -1;
 
@@ -2984,9 +2993,10 @@ int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr,
 		TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "!!! %s socket: 0x%lx was closed\n", __FUNCTION__,(long)s);
 
 	} else if (nbh) {
-		if(!ioa_socket_check_bandwidth(s,ioa_network_buffer_get_size(nbh),0)) {
+		if(!ioa_socket_check_bandwidth(s,nbh,0)) {
 			/* Bandwidth exhausted, we pretend everything is fine: */
 			ret = (int)(ioa_network_buffer_get_size(nbh));
+			if(skip) *skip = 1;
 		} else {
 			if (!ioa_socket_tobeclosed(s) && s->e) {
 

+ 9 - 2
src/apps/relay/ns_ioalib_impl.h

@@ -171,6 +171,11 @@ struct _ioa_engine
 
 #define SOCKET_MAGIC (0xABACADEF)
 
+struct traffic_bytes {
+	band_limit_t jiffie_bytes_read;
+	band_limit_t jiffie_bytes_write;
+};
+
 struct _ioa_socket
 {
 	evutil_socket_t fd;
@@ -207,8 +212,8 @@ struct _ioa_socket
 	int current_tos;
 	stun_buffer_list bufs;
 	turn_time_t jiffie; /* bandwidth check interval */
-	band_limit_t jiffie_bytes_read;
-	band_limit_t jiffie_bytes_write;
+	struct traffic_bytes data_traffic;
+	struct traffic_bytes control_traffic;
 	/* RFC 6062 ==>> */
 	//Connection session:
 	tcp_connection *sub_session;
@@ -303,6 +308,8 @@ int send_data_from_ioa_socket_tcp(ioa_socket_handle s, const void *data, size_t
 int send_str_from_ioa_socket_tcp(ioa_socket_handle s, const void *data);
 int send_ulong_from_ioa_socket_tcp(ioa_socket_handle s, size_t data);
 
+int ioa_socket_check_bandwidth(ioa_socket_handle s, ioa_network_buffer_handle nbh, int read);
+
 ///////////////////////// SUPER MEMORY ////////
 
 #define allocate_super_memory_engine(e,size) allocate_super_memory_engine_func(e, size, __FILE__, __FUNCTION__, __LINE__)

+ 5 - 5
src/apps/relay/turn_admin_server.c

@@ -382,11 +382,11 @@ static void change_cli_param(struct cli_session* cs, const char* pn)
 			cli_print_uint(cs,(unsigned long)turn_params.user_quota,"user-quota",2);
 			return;
 		} else if(strstr(pn,"max-bps")==pn) {
-			set_max_bps((band_limit_t)atol(pn+strlen("max-bps")));
+			set_max_bps((band_limit_t)strtoul(pn+strlen("max-bps"),NULL,10));
 			cli_print_uint(cs,(unsigned long)get_max_bps(),"max-bps",2);
 			return;
 		} else if(strstr(pn,"bps-capacity")==pn) {
-			set_bps_capacity((band_limit_t)atol(pn+strlen("bps-capacity")));
+			set_bps_capacity((band_limit_t)strtoul(pn+strlen("bps-capacity"),NULL,10));
 			cli_print_uint(cs,(unsigned long)get_bps_capacity(),"bps-capacity",2);
 			return;
 		} else if(strstr(pn,"cli-max-output-sessions")==pn) {
@@ -1882,9 +1882,9 @@ static void update_param(const char* pn, const char *value)
 			} else if(strstr(pn,"user-quota")==pn) {
 				turn_params.user_quota = atoi(value);
 			} else if(strstr(pn,"max-bps")==pn) {
-				set_max_bps((band_limit_t)atol(value));
+				set_max_bps((band_limit_t)strtoul(value,NULL,10));
 			} else if(strstr(pn,"bps-capacity")==pn) {
-				set_bps_capacity((band_limit_t)atol(value));
+				set_bps_capacity((band_limit_t)strtoul(value,NULL,10));
 			}
 		}
 		{
@@ -1900,7 +1900,7 @@ static void update_param(const char* pn, const char *value)
 					rp->options.perf_options.user_quota = atoi(value);
 					dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.user_quota,"user-quota");
 				} else if(strstr(pn,"cr-max-bps")==pn) {
-					rp->options.perf_options.max_bps = (band_limit_t)atol(value);
+					rp->options.perf_options.max_bps = (band_limit_t)strtoul(value,NULL,10);
 					dbd->set_realm_option_one((u08bits*)rp->options.name,rp->options.perf_options.max_bps,"max-bps");
 				}
 			}

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

@@ -249,7 +249,7 @@ int main(int argc, char **argv)
 		}
 			break;
 		case 'a':
-			bps = (band_limit_t)atol(optarg);
+			bps = (band_limit_t)strtoul(optarg,NULL,10);
 			break;
 		case 'o':
 			STRCPY(origin,optarg);

+ 1 - 1
src/client/ns_turn_msg.h

@@ -64,7 +64,7 @@ typedef enum {
 typedef u08bits hmackey_t[64];
 
 typedef u08bits password_t[STUN_MAX_PWD_SIZE+1];
-typedef unsigned int band_limit_t;
+typedef unsigned long band_limit_t;
 
 ///////////////////////////////////
 

+ 1 - 1
src/ns_turn_defs.h

@@ -31,7 +31,7 @@
 #ifndef __IOADEFS__
 #define __IOADEFS__
 
-#define TURN_SERVER_VERSION "4.4.2.2"
+#define TURN_SERVER_VERSION "4.4.2.3"
 #define TURN_SERVER_VERSION_NAME "Ardee West"
 #define TURN_SOFTWARE "Coturn-" TURN_SERVER_VERSION " '" TURN_SERVER_VERSION_NAME "'"
 

+ 1 - 1
src/server/ns_turn_ioalib.h

@@ -243,7 +243,7 @@ void clear_ioa_socket_session_if(ioa_socket_handle s, void *ss);
 tcp_connection *get_ioa_socket_sub_session(ioa_socket_handle s);
 void set_ioa_socket_sub_session(ioa_socket_handle s, tcp_connection *tc);
 int register_callback_on_ioa_socket(ioa_engine_handle e, ioa_socket_handle s, int event_type, ioa_net_event_handler cb, void *ctx, int clean_preexisting);
-int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos);
+int send_data_from_ioa_socket_nbh(ioa_socket_handle s, ioa_addr* dest_addr, ioa_network_buffer_handle nbh, int ttl, int tos, int *skip);
 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);

+ 16 - 13
src/server/ns_turn_server.c

@@ -1838,7 +1838,7 @@ static void tcp_deliver_delayed_buffer(unsent_buffer *ub, ioa_socket_handle s, t
 
 			u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh);
 
-			int ret = send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE);
+			int ret = send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
 			if (ret < 0) {
 				set_ioa_socket_tobeclosed(s);
 			} else {
@@ -1877,7 +1877,7 @@ static void tcp_peer_input_handler(ioa_socket_handle s, int event_type, ioa_net_
 
 	u32bits bytes = (u32bits)ioa_network_buffer_get_size(nbh);
 
-	int ret = send_data_from_ioa_socket_nbh(tc->client_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE);
+	int ret = send_data_from_ioa_socket_nbh(tc->client_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
 	if (ret < 0) {
 		set_ioa_socket_tobeclosed(s);
 	} else if(ss) {
@@ -1917,7 +1917,7 @@ static void tcp_client_input_handler_rfc6062data(ioa_socket_handle s, int event_
 		ss->received_bytes += bytes;
 	}
 
-	int ret = send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE);
+	int ret = send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
 	if (ret < 0) {
 		set_ioa_socket_tobeclosed(s);
 	}
@@ -2009,7 +2009,7 @@ static void tcp_peer_connection_completed_callback(int success, void *arg)
 				len_test = strlen(data_test);
 				ns_bcopy(data_test,data,len_test);
 				ioa_network_buffer_set_size(nbh_test,len_test);
-				send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh_test, TTL_IGNORE, TOS_IGNORE);
+				send_data_from_ioa_socket_nbh(tc->peer_s, NULL, nbh_test, TTL_IGNORE, TOS_IGNORE, NULL);
 			}
 		}
 	}
@@ -2490,7 +2490,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co
 		}
 
 		if(ss && !err_code) {
-			send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE);
+			send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
 			tcp_deliver_delayed_buffer(&(tc->ub_to_client),s,ss);
 			IOA_CLOSE_SOCKET(s_to_delete);
 			FUNCEND;
@@ -2501,7 +2501,7 @@ int turnserver_accept_tcp_client_data_connection(turn_turnserver *server, tcp_co
 				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: cannot set TCP tmp client data input callback\n", __FUNCTION__);
 				ioa_network_buffer_delete(server->e, nbh);
 			} else {
-				send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE);
+				send_data_from_ioa_socket_nbh(s, NULL, nbh, TTL_IGNORE, TOS_IGNORE, NULL);
 			}
 		}
 	}
@@ -2978,7 +2978,7 @@ static int handle_turn_send(turn_turnserver *server, ts_ur_super_session *ss,
 					ioa_network_buffer_set_size(nbh,len);
 				}
 				ioa_network_buffer_header_init(nbh);
-				send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss,peer_addr.ss.sa_family), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos);
+				send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss,peer_addr.ss.sa_family), &peer_addr, nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos, NULL);
 				in_buffer->nbh = NULL;
 			}
 
@@ -4103,7 +4103,7 @@ static int write_to_peerchannel(ts_ur_super_session* ss, u16bits chnum, ioa_net_
 
 			ioa_network_buffer_header_init(nbh);
 
-			rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos);
+			rc = send_data_from_ioa_socket_nbh(get_relay_socket_ss(ss, chn->peer_addr.ss.sa_family), &(chn->peer_addr), nbh, in_buffer->recv_ttl-1, in_buffer->recv_tos, NULL);
 			in_buffer->nbh = NULL;
 		}
 	}
@@ -4248,17 +4248,20 @@ static int write_client_connection(turn_turnserver *server, ts_ur_super_session*
 		return -1;
 	} else {
 
-		++(ss->sent_packets);
-		ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh);
-		turn_report_session_usage(ss);
-
 		if (eve(server->verbose)) {
 			TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,
 				"%s: prepare to write to s 0x%lx\n", __FUNCTION__,
 				(long) (ss->client_socket));
 		}
 
-		int ret = send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh, ttl, tos);
+		int skip = 0;
+		int ret = send_data_from_ioa_socket_nbh(ss->client_socket, NULL, nbh, ttl, tos, &skip);
+
+		if(!skip) {
+			++(ss->sent_packets);
+			ss->sent_bytes += (u32bits)ioa_network_buffer_get_size(nbh);
+			turn_report_session_usage(ss);
+		}
 
 		FUNCEND;
 		return ret;