Jelajahi Sumber

working on dual allocation

mom040267 11 tahun lalu
induk
melakukan
f7f1784fc1

+ 2 - 0
README.turnutils

@@ -115,6 +115,8 @@ Flags:
 
 
 -B  	Random disconnect after a few initial packets.
 -B  	Random disconnect after a few initial packets.
 
 
+-Z  Dual allocation.
+
 Options with required values:  
 Options with required values:  
 
 
 -l      Message length (Default: 100 Bytes).
 -l      Message length (Default: 100 Bytes).

+ 1 - 1
man/man1/turnadmin.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 July 2014" "" ""
+.TH TURN 1 "15 July 2014" "" ""
 .SH GENERAL INFORMATION
 .SH GENERAL INFORMATION
 
 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 
 \fIturnadmin\fP is a TURN administration tool. This tool can be used to manage 

+ 1 - 1
man/man1/turnserver.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 July 2014" "" ""
+.TH TURN 1 "15 July 2014" "" ""
 .SH GENERAL INFORMATION
 .SH GENERAL INFORMATION
 
 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 
 The \fBTURN Server\fP project contains the source code of a TURN server and TURN client 

+ 5 - 1
man/man1/turnutils.1

@@ -1,5 +1,5 @@
 .\" Text automatically generated by txt2man
 .\" Text automatically generated by txt2man
-.TH TURN 1 "11 July 2014" "" ""
+.TH TURN 1 "15 July 2014" "" ""
 .SH GENERAL INFORMATION
 .SH GENERAL INFORMATION
 
 
 A set of turnutils_* programs provides some utility functionality to be used
 A set of turnutils_* programs provides some utility functionality to be used
@@ -173,6 +173,10 @@ Generate extra requests (create permissions, channel bind).
 Random disconnect after a few initial packets.
 Random disconnect after a few initial packets.
 .TP
 .TP
 .B
 .B
+\fB\-Z\fP
+Dual allocation.
+.TP
+.B
 Options with required values:
 Options with required values:
 .TP
 .TP
 .B
 .B

+ 5 - 4
src/apps/common/stun_buffer.c

@@ -153,17 +153,18 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_
 
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile) {
-  return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, address_family, transport, mobile);
+int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile) {
+  return stun_set_allocate_request_str(buf->buf, (size_t*)(&(buf->len)), lifetime, af4, af6, transport, mobile);
 }
 }
 
 
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
-			       const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr,
+			       const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
+			       const ioa_addr *reflexive_addr,
 			       u32bits lifetime, int error_code, const u08bits *reason,
 			       u32bits lifetime, int error_code, const u08bits *reason,
 			       u64bits reservation_token, char *mobile_id) {
 			       u64bits reservation_token, char *mobile_id) {
 
 
   return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid, 
   return stun_set_allocate_response_str(buf->buf, (size_t*)(&(buf->len)), tid, 
-					relayed_addr, reflexive_addr, 
+					relayed_addr1, relayed_addr2, reflexive_addr,
 					lifetime, error_code, reason,
 					lifetime, error_code, reason,
 					reservation_token, mobile_id);
 					reservation_token, mobile_id);
 
 

+ 3 - 2
src/apps/common/stun_buffer.h

@@ -101,9 +101,10 @@ int stun_is_channel_message(stun_buffer* buf, u16bits* chnumber, int is_padding_
 
 
 ///////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////
 
 
-int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int address_family, u08bits transport, int mobile);
+int stun_set_allocate_request(stun_buffer* buf, u32bits lifetime, int af4, int af6, u08bits transport, int mobile);
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
 int stun_set_allocate_response(stun_buffer* buf, stun_tid* tid, 
-			       const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr,
+			       const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
+			       const ioa_addr *reflexive_addr,
 			       u32bits lifetime,
 			       u32bits lifetime,
 			       int error_code, const u08bits *reason,
 			       int error_code, const u08bits *reason,
 			       u64bits reservation_token, char *mobile_id);
 			       u64bits reservation_token, char *mobile_id);

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

@@ -95,6 +95,8 @@ char origin[STUN_MAX_ORIGIN_SIZE+1] = "\0";
 
 
 band_limit_t bps = 0;
 band_limit_t bps = 0;
 
 
+int dual_allocation = 0;
+
 //////////////// local definitions /////////////////
 //////////////// local definitions /////////////////
 
 
 static char Usage[] =
 static char Usage[] =
@@ -127,6 +129,7 @@ static char Usage[] =
   "		(for testing the non-standard server relay functionality).\n"
   "		(for testing the non-standard server relay functionality).\n"
   "	-G	Generate extra requests (create permissions, channel bind).\n"
   "	-G	Generate extra requests (create permissions, channel bind).\n"
   " -B  Random disconnect after a few initial packets.\n"
   " -B  Random disconnect after a few initial packets.\n"
+  " -Z  Dual allocation.\n"
   "Options:\n"
   "Options:\n"
   "	-l	Message length (Default: 100 Bytes).\n"
   "	-l	Message length (Default: 100 Bytes).\n"
   "	-i	Certificate file (for secure connections only, optional).\n"
   "	-i	Certificate file (for secure connections only, optional).\n"
@@ -201,7 +204,7 @@ int main(int argc, char **argv)
 
 
 	ns_bzero(local_addr, sizeof(local_addr));
 	ns_bzero(local_addr, sizeof(local_addr));
 
 
-	while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:vsyhcxXgtTSAPDNOUHMRIGB")) != -1) {
+	while ((c = getopt(argc, argv, "a:d:p:l:n:L:m:e:r:u:w:i:k:z:W:C:E:F:o:ZvsyhcxXgtTSAPDNOUHMRIGB")) != -1) {
 		switch (c){
 		switch (c){
 		case 'a':
 		case 'a':
 			bps = (band_limit_t)atol(optarg);
 			bps = (band_limit_t)atol(optarg);
@@ -255,6 +258,9 @@ int main(int argc, char **argv)
 		case 'z':
 		case 'z':
 			RTP_PACKET_INTERVAL = atoi(optarg);
 			RTP_PACKET_INTERVAL = atoi(optarg);
 			break;
 			break;
+		case 'Z':
+			dual_allocation = 1;
+			break;
 		case 'A':
 		case 'A':
 			use_short_term = 1;
 			use_short_term = 1;
 			break;
 			break;

+ 5 - 2
src/apps/uclient/startuclient.c

@@ -338,10 +338,13 @@ static int clnet_allocate(int verbose,
 			af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
 			af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
 		}
 		}
 
 
+		int af4 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4);
+		int af6 = dual_allocation || (af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6);
+
 		if(!dos)
 		if(!dos)
-			stun_set_allocate_request(&message, 800, af, relay_transport, mobility);
+			stun_set_allocate_request(&message, 800, af4, af6, relay_transport, mobility);
 		else
 		else
-			stun_set_allocate_request(&message, 300, af, relay_transport, mobility);
+			stun_set_allocate_request(&message, 300, af4, af6, relay_transport, mobility);
 
 
 		if(bps)
 		if(bps)
 			stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps);
 			stun_attr_add_bandwidth_str(message.buf, (size_t*)(&(message.len)), bps);

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

@@ -82,6 +82,7 @@ extern int mobility;
 extern int no_permissions;
 extern int no_permissions;
 extern int extra_requests;
 extern int extra_requests;
 extern band_limit_t bps;
 extern band_limit_t bps;
+extern int dual_allocation;
 
 
 extern char origin[STUN_MAX_ORIGIN_SIZE+1];
 extern char origin[STUN_MAX_ORIGIN_SIZE+1];
 
 

+ 5 - 4
src/client++/TurnMsgLib.h

@@ -848,8 +848,8 @@ public:
 	/**
 	/**
 	 * Construct allocate request
 	 * Construct allocate request
 	 */
 	 */
-	void constructAllocateRequest(u32bits lifetime, int address_family, u08bits transport, int mobile) {
-		stun_set_allocate_request_str(_buffer, &_sz, lifetime, address_family, transport, mobile);
+	void constructAllocateRequest(u32bits lifetime, int af4, int af6, u08bits transport, int mobile) {
+		stun_set_allocate_request_str(_buffer, &_sz, lifetime, af4, af6, transport, mobile);
 	}
 	}
 
 
 	/**
 	/**
@@ -1011,13 +1011,14 @@ public:
 	 * Construct allocate response
 	 * Construct allocate response
 	 */
 	 */
 	void constructAllocateResponse(stun_tid &tid,
 	void constructAllocateResponse(stun_tid &tid,
-					   const ioa_addr &relayed_addr,
+					   const ioa_addr &relayed_addr1,
+					   const ioa_addr &relayed_addr2,
 					   const ioa_addr &reflexive_addr,
 					   const ioa_addr &reflexive_addr,
 					   u32bits lifetime, int error_code, const u08bits *reason,
 					   u32bits lifetime, int error_code, const u08bits *reason,
 					   u64bits reservation_token, char *mobile_id) {
 					   u64bits reservation_token, char *mobile_id) {
 
 
 		stun_set_allocate_response_str(_buffer, &_sz, &tid,
 		stun_set_allocate_response_str(_buffer, &_sz, &tid,
-						   &relayed_addr,
+						   &relayed_addr1, &relayed_addr2,
 						   &reflexive_addr,
 						   &reflexive_addr,
 						   lifetime, error_code, reason,
 						   lifetime, error_code, reason,
 						   reservation_token, mobile_id);
 						   reservation_token, mobile_id);

+ 19 - 15
src/client/ns_turn_msg.c

@@ -644,7 +644,7 @@ int stun_get_message_len_str(u08bits *buf, size_t blen, int padding, size_t *app
 
 
 ////////// ALLOCATE ///////////////////////////////////
 ////////// ALLOCATE ///////////////////////////////////
 
 
-int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family,
+int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6,
 				u08bits transport, int mobile) {
 				u08bits transport, int mobile) {
 
 
   stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len);
   stun_init_request_str(STUN_METHOD_ALLOCATE, buf, len);
@@ -671,30 +671,30 @@ int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, i
   }
   }
 
 
   //ADRESS-FAMILY
   //ADRESS-FAMILY
-  switch (address_family) {
-  case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4:
-  case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6:
-  {
+  if (af4) {
 	  u08bits field[4];
 	  u08bits field[4];
-	  field[0] = (u08bits)address_family;
+	  field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
 	  field[1]=0;
 	  field[1]=0;
 	  field[2]=0;
 	  field[2]=0;
 	  field[3]=0;
 	  field[3]=0;
 	  if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
 	  if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
-	  break;
   }
   }
-  case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT:
-	  /* ignore */
-	  break;
-  default:
-	  return -1;
+
+  if (af6) {
+  	  u08bits field[4];
+  	  field[0] = (u08bits)STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
+  	  field[1]=0;
+  	  field[2]=0;
+  	  field[3]=0;
+  	  if(stun_attr_add_str(buf,len,STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY,field,sizeof(field))<0) return -1;
   };
   };
 
 
   return 0;
   return 0;
 }
 }
 
 
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
-				   const ioa_addr *relayed_addr, const ioa_addr *reflexive_addr,
+				   const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
+				   const ioa_addr *reflexive_addr,
 				   u32bits lifetime, int error_code, const u08bits *reason,
 				   u32bits lifetime, int error_code, const u08bits *reason,
 				   u64bits reservation_token, char* mobile_id) {
 				   u64bits reservation_token, char* mobile_id) {
 
 
@@ -702,8 +702,12 @@ int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid,
 
 
     stun_init_success_response_str(STUN_METHOD_ALLOCATE, buf, len, tid);
     stun_init_success_response_str(STUN_METHOD_ALLOCATE, buf, len, tid);
     
     
-    if(relayed_addr) {
-      if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr)<0) return -1;
+    if(relayed_addr1) {
+      if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr1)<0) return -1;
+    }
+
+    if(relayed_addr2) {
+      if(stun_attr_add_addr_str(buf,len,STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,relayed_addr2)<0) return -1;
     }
     }
     
     
     if(reflexive_addr) {
     if(reflexive_addr) {

+ 2 - 2
src/client/ns_turn_msg.h

@@ -155,9 +155,9 @@ int stun_attr_add_channel_number_str(u08bits* buf, size_t *len, u16bits chnumber
 int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps);
 int stun_attr_add_bandwidth_str(u08bits* buf, size_t *len, band_limit_t bps);
 u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len);
 u16bits stun_attr_get_first_channel_number_str(const u08bits *buf, size_t len);
 
 
-int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int address_family, u08bits transport, int mobile);
+int stun_set_allocate_request_str(u08bits* buf, size_t *len, u32bits lifetime, int af4, int af6, u08bits transport, int mobile);
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
 int stun_set_allocate_response_str(u08bits* buf, size_t *len, stun_tid* tid, 
-				   const ioa_addr *relayed_addr,
+				   const ioa_addr *relayed_addr1, const ioa_addr *relayed_addr2,
 				   const ioa_addr *reflexive_addr,
 				   const ioa_addr *reflexive_addr,
 				   u32bits lifetime, int error_code, const u08bits *reason,
 				   u32bits lifetime, int error_code, const u08bits *reason,
 				   u64bits reservation_token, char *mobile_id);
 				   u64bits reservation_token, char *mobile_id);

+ 67 - 24
src/server/ns_turn_server.c

@@ -899,22 +899,43 @@ static int handle_turn_allocate(turn_turnserver *server,
 			*reason = (const u08bits *)"Wrong TID";
 			*reason = (const u08bits *)"Wrong TID";
 		} else {
 		} else {
 			size_t len = ioa_network_buffer_get_size(nbh);
 			size_t len = ioa_network_buffer_get_size(nbh);
-			ioa_addr xor_relayed_addr;
-			ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET));
-			if(!relayed_addr)
-				relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6));
-			if(relayed_addr) {
+			ioa_addr xor_relayed_addr1, *pxor_relayed_addr1=NULL;
+			ioa_addr xor_relayed_addr2, *pxor_relayed_addr2=NULL;
+			ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET));
+			ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6));
+
+			if(relayed_addr1) {
+				if(server->external_ip_set) {
+					addr_cpy(&xor_relayed_addr1, &(server->external_ip));
+					addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1));
+				} else {
+					addr_cpy(&xor_relayed_addr1, relayed_addr1);
+				}
+				pxor_relayed_addr1 = &xor_relayed_addr1;
+			}
+
+			if(relayed_addr2) {
 				if(server->external_ip_set) {
 				if(server->external_ip_set) {
-					addr_cpy(&xor_relayed_addr, &(server->external_ip));
-					addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr));
+					addr_cpy(&xor_relayed_addr2, &(server->external_ip));
+					addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2));
 				} else {
 				} else {
-					addr_cpy(&xor_relayed_addr, relayed_addr);
+					addr_cpy(&xor_relayed_addr2, relayed_addr2);
+				}
+				pxor_relayed_addr2 = &xor_relayed_addr2;
+			}
+
+			if(pxor_relayed_addr1 || pxor_relayed_addr2) {
+				u32bits lifetime = 0;
+				if(pxor_relayed_addr1) {
+					lifetime = (get_relay_session(a,pxor_relayed_addr1->ss.sa_family)->expiration_time - server->ctime);
+				} else if(pxor_relayed_addr2) {
+					lifetime = (get_relay_session(a,pxor_relayed_addr2->ss.sa_family)->expiration_time - server->ctime);
 				}
 				}
 				stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len,
 				stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len,
 							tid,
 							tid,
-							&xor_relayed_addr,
+							pxor_relayed_addr1, pxor_relayed_addr2,
 							get_remote_addr_from_ioa_socket(ss->client_socket),
 							get_remote_addr_from_ioa_socket(ss->client_socket),
-							(get_relay_session(a,relayed_addr->ss.sa_family)->expiration_time - server->ctime), 0, NULL, 0,
+							lifetime, 0, NULL, 0,
 							ss->s_mobile_id);
 							ss->s_mobile_id);
 				ioa_network_buffer_set_size(nbh,len);
 				ioa_network_buffer_set_size(nbh,len);
 				*resp_constructed = 1;
 				*resp_constructed = 1;
@@ -930,7 +951,8 @@ static int handle_turn_allocate(turn_turnserver *server,
 		int even_port = -1;
 		int even_port = -1;
 		int dont_fragment = 0;
 		int dont_fragment = 0;
 		u64bits in_reservation_token = 0;
 		u64bits in_reservation_token = 0;
-		int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
+		int af4 = 0;
+		int af6 = 0;
 		u08bits username[STUN_MAX_USERNAME_SIZE+1]="\0";
 		u08bits username[STUN_MAX_USERNAME_SIZE+1]="\0";
 		size_t ulen = 0;
 		size_t ulen = 0;
 		band_limit_t bps = 0;
 		band_limit_t bps = 0;
@@ -1047,7 +1069,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 			  if (len != 8) {
 			  if (len != 8) {
 			    *err_code = 400;
 			    *err_code = 400;
 			    *reason = (const u08bits *)"Wrong Format of Reservation Token";
 			    *reason = (const u08bits *)"Wrong Format of Reservation Token";
-			  } else if(af != STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) {
+			  } else if(af4 || af6) {
 				  *err_code = 400;
 				  *err_code = 400;
 				  *reason = (const u08bits *)"Address family attribute can not be used with reservation token request";
 				  *reason = (const u08bits *)"Address family attribute can not be used with reservation token request";
 			  } else {
 			  } else {
@@ -1069,11 +1091,13 @@ static int handle_turn_allocate(turn_turnserver *server,
 					*reason = (const u08bits *)"Address family attribute can not be used with reservation token request";
 					*reason = (const u08bits *)"Address family attribute can not be used with reservation token request";
 				} else {
 				} else {
 					int af_req = stun_get_requested_address_family(sar);
 					int af_req = stun_get_requested_address_family(sar);
-					if(af == STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT) {
+					if(!af4 && !af6) {
 						switch (af_req) {
 						switch (af_req) {
 						case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4:
 						case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4:
+							af4 = 1;
+							break;
 						case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6:
 						case STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6:
-							af = af_req;
+							af6 = 1;
 							break;
 							break;
 						default:
 						default:
 							*err_code = 440;
 							*err_code = 440;
@@ -1149,6 +1173,10 @@ static int handle_turn_allocate(turn_turnserver *server,
 					}
 					}
 				}
 				}
 
 
+				int af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_DEFAULT;
+				if(af4) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV4;
+				else if(af6) af = STUN_ATTRIBUTE_REQUESTED_ADDRESS_FAMILY_VALUE_IPV6;
+
 				if (*err_code || create_relay_connection(server, ss, lifetime,
 				if (*err_code || create_relay_connection(server, ss, lifetime,
 							af, transport,
 							af, transport,
 							even_port, in_reservation_token, &out_reservation_token,
 							even_port, in_reservation_token, &out_reservation_token,
@@ -1173,20 +1201,35 @@ static int handle_turn_allocate(turn_turnserver *server,
 
 
 					size_t len = ioa_network_buffer_get_size(nbh);
 					size_t len = ioa_network_buffer_get_size(nbh);
 
 
-					ioa_addr xor_relayed_addr;
-					ioa_addr *relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET));
-					if(!relayed_addr)
-						relayed_addr = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6));
-					if(relayed_addr) {
+					ioa_addr xor_relayed_addr1, *pxor_relayed_addr1=NULL;
+					ioa_addr xor_relayed_addr2, *pxor_relayed_addr2=NULL;
+					ioa_addr *relayed_addr1 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET));
+					ioa_addr *relayed_addr2 = get_local_addr_from_ioa_socket(get_relay_socket_ss(ss,AF_INET6));
+
+					if(relayed_addr1) {
 						if(server->external_ip_set) {
 						if(server->external_ip_set) {
-							addr_cpy(&xor_relayed_addr, &(server->external_ip));
-							addr_set_port(&xor_relayed_addr,addr_get_port(relayed_addr));
+							addr_cpy(&xor_relayed_addr1, &(server->external_ip));
+							addr_set_port(&xor_relayed_addr1,addr_get_port(relayed_addr1));
 						} else {
 						} else {
-							addr_cpy(&xor_relayed_addr, relayed_addr);
+							addr_cpy(&xor_relayed_addr1, relayed_addr1);
 						}
 						}
+						pxor_relayed_addr1 = &xor_relayed_addr1;
+					}
+
+					if(relayed_addr2) {
+						if(server->external_ip_set) {
+							addr_cpy(&xor_relayed_addr2, &(server->external_ip));
+							addr_set_port(&xor_relayed_addr2,addr_get_port(relayed_addr2));
+						} else {
+							addr_cpy(&xor_relayed_addr2, relayed_addr2);
+						}
+						pxor_relayed_addr2 = &xor_relayed_addr2;
+					}
+
+					if(pxor_relayed_addr1 || pxor_relayed_addr2) {
 
 
 						stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid,
 						stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid,
-									&xor_relayed_addr,
+									pxor_relayed_addr1, pxor_relayed_addr2,
 									get_remote_addr_from_ioa_socket(ss->client_socket), lifetime,
 									get_remote_addr_from_ioa_socket(ss->client_socket), lifetime,
 									0,NULL,
 									0,NULL,
 									out_reservation_token,
 									out_reservation_token,
@@ -1213,7 +1256,7 @@ static int handle_turn_allocate(turn_turnserver *server,
 		}
 		}
 
 
 		size_t len = ioa_network_buffer_get_size(nbh);
 		size_t len = ioa_network_buffer_get_size(nbh);
-		stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id);
+		stun_set_allocate_response_str(ioa_network_buffer_data(nbh), &len, tid, NULL, NULL, NULL, 0, *err_code, *reason, 0, ss->s_mobile_id);
 		ioa_network_buffer_set_size(nbh,len);
 		ioa_network_buffer_set_size(nbh,len);
 		*resp_constructed = 1;
 		*resp_constructed = 1;
 	}
 	}