//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.2.  LIFETIME]] object definition
//
static tsk_object_t* tnet_turn_attribute_lifetime_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_lifetime_t *attribute = self;
	if(attribute){
		attribute->value = /*tnet_htonl*/(va_arg(*app, uint32_t));
		TNET_STUN_ATTRIBUTE(attribute)->type = stun_lifetime;
		TNET_STUN_ATTRIBUTE(attribute)->length = 4;
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.5.  FINGERPRINT]] object definition
//
static tsk_object_t* tnet_stun_attribute_fingerprint_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_fingerprint_t *attribute = self;
	if(attribute){
		attribute->value = va_arg(*app, uint32_t);
		
		TNET_STUN_ATTRIBUTE(attribute)->type = stun_fingerprint;
		TNET_STUN_ATTRIBUTE(attribute)->length = 4;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.7.  REQUESTED-TRANSPORT]] object definition
//
static tsk_object_t* tnet_turn_attribute_reqtrans_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_reqtrans_t *attribute = self;
	if(attribute){
		attribute->protocol = va_arg(*app, tnet_proto_t);

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_requested_transport;
		TNET_STUN_ATTRIBUTE(attribute)->length = 4;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.6.  EVEN-PORT]] object definition
//
static tsk_object_t* tnet_turn_attribute_even_port_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_even_port_t *attribute = self;
	if(attribute){
		attribute->R = va_arg(*app, unsigned);

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_even_port;
		TNET_STUN_ATTRIBUTE(attribute)->length = 1;
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.2.  XOR-MAPPED-ADDRESS]] object definition
//
static tsk_object_t* tnet_stun_attribute_xmapped_addr_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_xmapped_addr_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		if(payload && payload_size){
			const uint8_t *payloadPtr = (const uint8_t*)payload;
			payloadPtr += 1; /* Ignore first 8bits */

			TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_mapped_address;
			TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
			
			attribute->family = (tnet_stun_addr_family_t)(*(payloadPtr++));

			/*	RFC 5389 - 15.2.  XOR-MAPPED-ADDRESS
				X-Port is computed by taking the mapped port in host byte order,
				XOR'ing it with the most significant 16 bits of the magic cookie, and
				then the converting the result to network byte order.
			*/
			attribute->xport = tnet_ntohs_2(payloadPtr);
			attribute->xport ^= 0x2112;
			payloadPtr+=2;
			
			
			{	/*=== Compute IP address */

				/*	RFC 5389 - 15.2.  XOR-MAPPED-ADDRESS
					If the IP address family is IPv4, X-Address is computed by taking the mapped IP
					address in host byte order, XOR'ing it with the magic cookie, and
					converting the result to network byte order.
				*/
				tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0);
				if(addr_size){	
					tsk_size_t i;
					uint32_t addr;

					for(i=0; i<addr_size; i+=4){
						addr = tnet_ntohl(tnet_ntohl_2(payloadPtr) ^ TNET_STUN_MAGIC_COOKIE);
						memcpy(&attribute->xaddress[i], &addr, 4);
						payloadPtr+=4;
					}
				}
				else{
					TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family);
				}
			}
		}
		
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.3.  USERNAME]] object definition
//
static tsk_object_t* tnet_stun_attribute_username_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_username_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		attribute->value = tsk_strndup(payload, payload_size);

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_username;
		TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.3.  XOR-PEER-ADDRESS]] object definition
//
static tsk_object_t* tnet_turn_attribute_xpeer_addr_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_xpeer_addr_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);
		
		if(payload && payload_size){
		}
		TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_peer_address;
		TNET_STUN_ATTRIBUTE(attribute)->length = 8;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.4.  DATA]] object definition
//
static tsk_object_t* tnet_turn_attribute_data_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_data_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		if(payload && payload_size){
			attribute->value = tsk_buffer_create(payload, payload_size);
		}
		TNET_STUN_ATTRIBUTE(attribute)->type = stun_data;
		TNET_STUN_ATTRIBUTE(attribute)->length = (uint16_t)payload_size;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.1.  CHANNEL-NUMBER]] object definition
//
static tsk_object_t* tnet_turn_attribute_channelnum_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_channelnum_t *attribute = self;
	if(attribute){
#if defined (__GNUC__)
		attribute->number = (uint16_t)(va_arg(*app, unsigned));
#else
		attribute->number = (va_arg(*app, uint16_t));
#endif

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_channel_number;
		TNET_STUN_ATTRIBUTE(attribute)->length = 2;
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.4.  MESSAGE-INTEGRITY]] object definition
//
static tsk_object_t* tnet_stun_attribute_integrity_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_integrity_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);
		
		if(payload_size == TSK_SHA1_DIGEST_SIZE){
			memcpy(attribute->sha1digest, payload, TSK_SHA1_DIGEST_SIZE);

			TNET_STUN_ATTRIBUTE(attribute)->type = stun_message_integrity;
			TNET_STUN_ATTRIBUTE(attribute)->length = TSK_SHA1_DIGEST_SIZE;
		}
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.6.  ERROR-CODE]] object definition
//
static tsk_object_t* tnet_stun_attribute_errorcode_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_errorcode_t *attribute = self;
	if(attribute){
		const uint8_t *payload = (const uint8_t*)va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		if(payload_size >4){
			uint32_t code = tnet_htonl_2(payload);
			payload += 4;

			attribute->_class = code >>8;
			attribute->number = (code & 0xFF);
			attribute->reason_phrase = tsk_strndup((const char*)payload, (payload_size-4));
		}
		
		TNET_STUN_ATTRIBUTE(attribute)->type = stun_error_code;
		TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
	}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.9.  RESERVATION-TOKEN]] object definition
//
static tsk_object_t* tnet_turn_attribute_restoken_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_restoken_t *attribute = self;
	if(attribute){
		//--const void *payload = va_arg(*app, const void*);
		//--tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_reservation_token;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.8.  DONT-FRAGMENT]] object definition
//
static tsk_object_t* tnet_turn_attribute_dontfrag_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_dontfrag_t *attribute = self;
	if(attribute){
		//const void *payload = va_arg(*app, const void*);
		//tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		TNET_STUN_ATTRIBUTE(attribute)->type = stun_dont_fragment;
	}
	return self;
}
//=================================================================================================
//	[[draft-ietf-behave-turn-16 - 14.5.  XOR-RELAYED-ADDRESS]] object definition
//
static tsk_object_t* tnet_turn_attribute_xrelayed_addr_ctor(tsk_object_t * self, va_list * app)
{
	tnet_turn_attribute_xrelayed_addr_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		if(payload && payload_size){
			const uint8_t *payloadPtr = (const uint8_t*)payload;
			payloadPtr += 1; /* Ignore first 8bits */

			TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_relayed_address;
			TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
			
			attribute->family = (tnet_stun_addr_family_t)(*(payloadPtr++));

			attribute->xport = tnet_ntohs_2(payloadPtr);
			attribute->xport ^= 0x2112;
			payloadPtr+=2;

			{	/*=== Compute IP address */
				tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0);
				if(addr_size){	
					tsk_size_t i;
					uint32_t addr;

					for(i=0; i<addr_size; i+=4){
						addr = tnet_htonl_2(payloadPtr);
						addr ^= TNET_STUN_MAGIC_COOKIE;
						memcpy(&attribute->xaddress[i], &addr, 4);
						payloadPtr+=4;
					}
				}
				else{
					TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family);
				}
			}			
		}
	}
	return self;
}
//=================================================================================================
//	[[RFC 5389 - 15.1.  MAPPED-ADDRESS]] object definition
//
static tsk_object_t* tnet_stun_attribute_mapped_addr_ctor(tsk_object_t * self, va_list * app)
{
	tnet_stun_attribute_mapped_addr_t *attribute = self;
	if(attribute){
		const void *payload = va_arg(*app, const void*);
		tsk_size_t payload_size = va_arg(*app, tsk_size_t);

		if(payload && payload_size){
			const uint8_t *payloadPtr = (const uint8_t*)payload;
			payloadPtr += 1; /* Ignore first 8bits */

			TNET_STUN_ATTRIBUTE(attribute)->type = stun_mapped_address;
			TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;

			attribute->family = (tnet_stun_addr_family_t) (*(payloadPtr++));
			attribute->port = tnet_ntohs_2(payloadPtr);
			payloadPtr+=2;

			{	/*=== Compute IP address */
				tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0);
				if(addr_size){	
					tsk_size_t i;

					for(i=0; i<addr_size; i+=4){
						// ntohl() not needed : byte per byte to avoid endianness problem
						attribute->address[i] = payloadPtr[0],
							attribute->address[i+1] = payloadPtr[1],
							attribute->address[i+2] = payloadPtr[2],
							attribute->address[i+3] = payloadPtr[3];
						payloadPtr+=4;
					}
				}
				else{
					TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family);
				}
			}
		}
	}
	return self;
}