summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/stun
diff options
context:
space:
mode:
authorMamadou DIOP <bossiel@yahoo.fr>2015-08-17 01:56:35 +0200
committerMamadou DIOP <bossiel@yahoo.fr>2015-08-17 01:56:35 +0200
commit631fffee8a28b1bec5ed1f1d26a20e0135967f99 (patch)
tree74afe3bf3efe15aa82bcd0272b2b0f4d48c2d837 /tinyNET/src/stun
parent7908865936604036e6f200f1b5e069f8752f3a3a (diff)
downloaddoubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.zip
doubango-631fffee8a28b1bec5ed1f1d26a20e0135967f99.tar.gz
-
Diffstat (limited to 'tinyNET/src/stun')
-rw-r--r--tinyNET/src/stun/AStyle.sh1
-rw-r--r--tinyNET/src/stun/tnet_stun.c440
-rw-r--r--tinyNET/src/stun/tnet_stun.h127
-rw-r--r--tinyNET/src/stun/tnet_stun_attr.c651
-rw-r--r--tinyNET/src/stun/tnet_stun_attr.h81
-rw-r--r--tinyNET/src/stun/tnet_stun_attribute.c1176
-rw-r--r--tinyNET/src/stun/tnet_stun_attribute.h356
-rw-r--r--tinyNET/src/stun/tnet_stun_binding.c127
-rw-r--r--tinyNET/src/stun/tnet_stun_binding.h67
-rw-r--r--tinyNET/src/stun/tnet_stun_message.c495
-rw-r--r--tinyNET/src/stun/tnet_stun_message.h246
-rw-r--r--tinyNET/src/stun/tnet_stun_pkt.c751
-rw-r--r--tinyNET/src/stun/tnet_stun_pkt.h187
-rw-r--r--tinyNET/src/stun/tnet_stun_types.h373
-rw-r--r--tinyNET/src/stun/tnet_stun_utils.c201
-rw-r--r--tinyNET/src/stun/tnet_stun_utils.h45
16 files changed, 5324 insertions, 0 deletions
diff --git a/tinyNET/src/stun/AStyle.sh b/tinyNET/src/stun/AStyle.sh
new file mode 100644
index 0000000..9d81f4d
--- /dev/null
+++ b/tinyNET/src/stun/AStyle.sh
@@ -0,0 +1 @@
+../../../thirdparties/win32/bin/AStyle.exe --style=k/r --lineend=linux --mode=c --add-brackets --break-closing-brackets --recursive "*.c" "*.h" \ No newline at end of file
diff --git a/tinyNET/src/stun/tnet_stun.c b/tinyNET/src/stun/tnet_stun.c
new file mode 100644
index 0000000..d8566b2
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun.c
@@ -0,0 +1,440 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun.c
+// * @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#include "tnet_stun.h"
+//
+//#include "../tnet_nat.h"
+//#include "../tnet_utils.h"
+//
+//#include "tsk_md5.h"
+//#include "tsk_string.h"
+//#include "tsk_memory.h"
+//#include "tsk_buffer.h"
+//#include "tsk_debug.h"
+//
+//#include <string.h>
+//
+///**@defgroup tnet_stun_group STUN2 (RFC 5389) implementation.
+//*/
+//
+//
+///**@ingroup tnet_stun_group
+//* Creates new @ref tnet_stun_binding_t object.
+//*/
+//tnet_stun_binding_t* tnet_stun_binding_create(tnet_fd_t fd, tnet_socket_type_t socket_type, const char* server_address, tnet_port_t server_port, const char* username, const char* password)
+//{
+// return tsk_object_new(tnet_stun_binding_def_t, fd, socket_type, server_address, server_port, username, password);
+//}
+//
+///**@ingroup tnet_stun_group
+// *
+// * Create generic STUN2 request with all mandatory headers and attributes.
+// *
+// * @param [in,out] binding The binding object from which to create the request.
+// *
+// * @retval STUN2 request if succeed and NULL otherwise.
+//**/
+//tnet_stun_pkt_t *tnet_stun_create_request(const tnet_stun_binding_t* binding)
+//{
+// tnet_stun_pkt_t *message = tnet_stun_message_create(binding->username, binding->password);
+//
+// if(message) {
+// message->realm = tsk_strdup(binding->realm);
+// message->nonce = tsk_strdup(binding->nonce);
+//
+// /* Set the request type (RFC 5389 defines only one type) */
+// message->type = stun_binding_request;
+//
+// { /* Create random transaction id */
+// tsk_istr_t random;
+// tsk_md5digest_t digest;
+//
+// tsk_strrandom(&random);
+// TSK_MD5_DIGEST_CALC(random, sizeof(random), digest);
+//
+// memcpy(message->transac_id, digest, TNET_STUN_TRANSACID_SIZE);
+// }
+//
+// /* Add software attribute */
+// if(binding->software) {
+// tnet_stun_attr_t* attribute = (tnet_stun_attr_t*)tnet_stun_attribute_software_create(binding->software, tsk_strlen(binding->software));
+// tnet_stun_message_add_attribute(message, &attribute);
+// }
+// }
+//
+// return message;
+//}
+//
+//int tnet_stun_send_reliably(const tnet_stun_pkt_t* message)
+//{
+// return -1;
+//}
+//
+//
+///**@ingroup tnet_stun_group
+// *
+// * Internal function to send a STUN message using unrealiable protocol such as UDP.
+// *
+// *
+// * @param localFD The local file descriptor.
+// * @param RTO The Retransmission TimeOut.
+// * @param Rc The Number of retransmissions.
+// * @param [in,out] message The message to send.
+// * @param [in,out] server The destination STUN server.
+// *
+// * @return The response from the server or NULL if transport error.
+//**/
+//tnet_stun_pkt_resp_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_pkt_t* message, struct sockaddr* server)
+//{
+// /* RFC 5389 - 7.2.1. Sending over UDP
+// STUN indications are not retransmitted; thus, indication transactions over UDP
+// are not reliable.
+// */
+// //int retransmit = (message->type == stun_binding_request);
+//
+// int ret = -1;
+// uint16_t i, rto = RTO;
+// struct timeval tv;
+// fd_set set;
+//
+// tsk_buffer_t *buffer = tnet_stun_pkt_serialize(message);
+// tnet_stun_pkt_resp_t *response = tsk_null;
+//
+// if(!buffer) {
+// goto bail;
+// }
+//
+// {
+////#ifndef SIO_UDP_CONNRESET
+////# ifndef IOC_VENDOR
+////# define IOC_VENDOR 0x18000000
+////# endif
+////# ifndef _WSAIOW
+////# define _WSAIOW(x,y) (IOC_IN|(x)|(y))
+////# endif
+////# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
+////#endif
+//// DWORD dwBytesReturned = 0;
+//// BOOL bNewBehavior = TRUE;
+//// DWORD status;
+////
+//// // disable new behavior using
+//// // IOCTL: SIO_UDP_CONNRESET
+//// status = WSAIoctl(localFD, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
+//// NULL, 0, &dwBytesReturned, NULL, NULL);
+// }
+//
+// tv.tv_sec = 0;
+// tv.tv_usec = 0;
+//
+// /* RFC 5389 - 7.2.1. Sending over UDP
+// A client SHOULD retransmit a STUN request message starting with an
+// interval of RTO ("Retransmission TimeOut"), doubling after each
+// retransmission.
+//
+// e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
+// */
+// for(i=0; i<Rc; i++) {
+// tv.tv_sec += rto/1000;
+// tv.tv_usec += (rto% 1000) * 1000;
+//
+// FD_ZERO(&set);
+// FD_SET(localFD, &set);
+//
+// ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
+//
+// if((ret = select(localFD+1, &set, NULL, NULL, &tv))<0) {
+// goto bail;
+// }
+// else if(ret == 0) {
+// /* timeout */
+// TSK_DEBUG_INFO("STUN request timedout at %d", i);
+// rto *= 2;
+// continue;
+// }
+// else if(FD_ISSET(localFD, &set)) {
+// /* there is data to read */
+//
+// tsk_size_t len = 0;
+// void* data = 0;
+//
+// TSK_DEBUG_INFO("STUN request got response");
+//
+// /* Check how how many bytes are pending */
+// if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0) {
+// goto bail;
+// }
+//
+// if(len==0) {
+// TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
+// continue;
+// }
+//
+// /* Receive pending data */
+// data = tsk_calloc(len, sizeof(uint8_t));
+// if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0) {
+// TSK_FREE(data);
+//
+// TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
+// goto bail;
+// }
+//
+// /* Parse the incoming response. */
+// response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
+// TSK_FREE(data);
+//
+// if(response) {
+// if(tnet_stun_transacid_cmp(message->transac_id, response->transac_id)) {
+// /* Not same transaction id */
+// TSK_OBJECT_SAFE_FREE(response);
+// continue;
+// }
+// }
+//
+// goto bail;
+// }
+// else {
+// continue;
+// }
+// }
+//
+//bail:
+// TSK_OBJECT_SAFE_FREE(buffer);
+//
+// return response;
+//}
+//
+///**@ingroup tnet_stun_group
+// * Internal function to send a STUN2 binding request over the network.
+// *
+// * @param [in,out] context The NAT context holding the user preferences.
+// * @param [in,out] binding The STUN binding object used to create the message to send.
+// *
+// * @return Zero if succeed and non-zero error code otherwise.
+//**/
+//int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *binding)
+//{
+// int ret = -1;
+// tnet_stun_pkt_resp_t *response = 0;
+// tnet_stun_pkt_req_t *request = 0;
+//
+//
+// goto stun_phase0;
+//
+// /* RFC 5389 - 10.2.1.1. First Request
+// If the client has not completed a successful request/response
+// transaction with the server (as identified by hostname, if the DNS
+// procedures of Section 9 are used, else IP address if not), it SHOULD
+// omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
+// In other words, the very first request is sent as if there were no
+// authentication or message integrity applied.
+// */
+//stun_phase0: {
+// if(!(request = tnet_stun_create_request(binding))) {
+// goto bail;
+// }
+//
+// if(TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type)) {
+// response = tnet_stun_send_unreliably(binding->localFD, context->RTO, context->Rc, request, (struct sockaddr*)&binding->server);
+// }
+//
+// if(response) {
+// if(TNET_STUN_PKT_RESP_IS_ERROR(response)) {
+// short code = tnet_stun_message_get_errorcode(response);
+// const char* realm = tnet_stun_message_get_realm(response);
+// const char* nonce = tnet_stun_message_get_nonce(response);
+//
+// if(code == 401 && realm && nonce) {
+// if(!binding->nonce) {
+// /* First time we get a nonce */
+// tsk_strupdate(&binding->nonce, nonce);
+// tsk_strupdate(&binding->realm, realm);
+//
+// /* Delete the message and response before retrying*/
+// TSK_OBJECT_SAFE_FREE(response);
+// TSK_OBJECT_SAFE_FREE(request);
+//
+// // Send again using new transaction identifier
+// return tnet_stun_send_bind(context, binding);
+// }
+// else {
+// ret = -3;
+// }
+// }
+// else {
+// ret = -2;
+// }
+// }
+// else {
+// const tnet_stun_attr_t *attribute;
+// if((attribute= tnet_stun_message_get_attribute(response, stun_xor_mapped_address))) {
+// ret = 0;
+// binding->xmaddr = tsk_object_ref((void*)attribute);
+// }
+// else if((attribute= tnet_stun_message_get_attribute(response, stun_mapped_address))) {
+// ret = 0;
+// binding->maddr = tsk_object_ref((void*)attribute);
+// }
+// }
+// }
+// }
+// /* END OF stun_phase0 */
+//
+//bail:
+// TSK_OBJECT_SAFE_FREE(response);
+// TSK_OBJECT_SAFE_FREE(request);
+//
+// return ret;
+//}
+//
+///**@ingroup tnet_stun_group
+// *
+// * Public function to create a binding context.
+// *
+// * @param [in,out] nat_context The NAT context.
+// * @param localFD The local file descriptor for which to create the binding context.
+// *
+// * @return A valid binding id if succeed and @ref kStunBindingInvalidId otherwise. If the returned id is valid then
+// * the newly created binding will contain the server reflexive address associated to the local file descriptor.
+//**/
+//tnet_stun_binding_id_t tnet_stun_bind(const tnet_nat_context_t* nat_context, tnet_fd_t localFD)
+//{
+// tnet_stun_binding_id_t id = kStunBindingInvalidId;
+//
+// tnet_stun_binding_t *binding = 0;
+//
+// if(nat_context && localFD != TNET_INVALID_FD) {
+// if(!(binding = tnet_stun_binding_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password))) {
+// goto bail;
+// }
+//
+// if(tnet_stun_send_bind(nat_context, binding)) {
+// TSK_OBJECT_SAFE_FREE(binding);
+// goto bail;
+// }
+//
+// id = binding->id;
+// tsk_list_push_back_data(nat_context->stun_bindings, (void**)&binding);
+// }
+//
+//bail:
+// return id;
+//}
+//
+///**@ingroup tnet_stun_group
+// * Compares two transaction ids.
+// *
+// * @param id1 The first transaction identifier.
+// * @param id2 The second transaction identifier.
+// *
+// * @return Zero if the two identifiers are equal and non-zero value otherwise.
+//**/
+//int tnet_stun_transacid_cmp(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2)
+//{
+// tsk_size_t i;
+// for(i=0; i<sizeof(tnet_stun_transac_id_t); i++) {
+// if(id1[i] != id2[i]) {
+// return (id1[i] - id2[i]);
+// }
+// }
+// return 0;
+//}
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+////=================================================================================================
+//// STUN2 BINDING object definition
+////
+//static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_binding_t *binding = self;
+// if(binding) {
+// static tnet_stun_binding_id_t __binding_unique_id = 0;
+//
+// const char* server_address;
+// tnet_port_t server_port;
+//
+// binding->id = ++__binding_unique_id;
+//
+// binding->localFD = va_arg(*app, tnet_fd_t);
+// binding->socket_type = va_arg(*app, tnet_socket_type_t);
+//
+// server_address = tsk_strdup(va_arg(*app, const char*));
+//#if defined(__GNUC__)
+// server_port = (tnet_port_t)va_arg(*app, unsigned);
+//#else
+// server_port = va_arg(*app, tnet_port_t);
+//#endif
+//
+// binding->username = tsk_strdup(va_arg(*app, const char*));
+// binding->password = tsk_strdup(va_arg(*app, const char*));
+//
+// if(server_address) {
+// tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
+// }
+//
+// binding->software = tsk_strdup(TNET_SOFTWARE);
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
+//{
+// tnet_stun_binding_t *binding = self;
+// if(binding) {
+// TSK_FREE(binding->username);
+// TSK_FREE(binding->password);
+// TSK_FREE(binding->realm);
+// TSK_FREE(binding->nonce);
+//
+// TSK_FREE(binding->software);
+//
+// TSK_OBJECT_SAFE_FREE(binding->maddr);
+// TSK_OBJECT_SAFE_FREE(binding->xmaddr);
+// }
+//
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_binding_def_s = {
+// sizeof(tnet_stun_binding_t),
+// tnet_stun_binding_ctor,
+// tnet_stun_binding_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;
+//
+//
diff --git a/tinyNET/src/stun/tnet_stun.h b/tinyNET/src/stun/tnet_stun.h
new file mode 100644
index 0000000..26f0def
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun.h
@@ -0,0 +1,127 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun.h
+// * @brief Session Traversal Utilities for NAT (STUN) implementation as per RFC 5389 and RFC 3489(Obsolete).
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#ifndef TNET_STUN_H
+//#define TNET_STUN_H
+//
+//#include "tinynet_config.h"
+//#include "stun/tnet_stun_message.h"
+//#include "tnet_types.h"
+//#include "tnet_socket.h"
+//
+//#include "tsk_object.h"
+//
+//TNET_BEGIN_DECLS
+//
+///**@ingroup tnet_stun_group
+//*/
+////typedef uint64_t tnet_stun_binding_id_t;
+///**@ingroup tnet_stun_group
+// * @def kStunBindingInvalidId
+// * STUN2 invalid binding id.
+//**/
+///**@ingroup tnet_stun_group
+// * @def TNET_STUN_IS_VALID_BINDING_ID
+// * Checks the validity of the STUN @a id.
+//**/
+//#define kStunBindingInvalidId 0
+//#define TNET_STUN_IS_VALID_BINDING_ID(id) (id != kStunBindingInvalidId)
+//
+///**@ingroup tnet_stun_group
+// * Default port for both TCP and UDP protos as per RFC 5389 subclause 9.
+//**/
+//#define TNET_STUN_TCP_UDP_DEFAULT_PORT 3478
+//
+///**@ingroup tnet_stun_group
+// * Default port for TLS protocol as per RFC 5389 subclause 9.
+//**/
+//#define TNET_STUN_TLS_DEFAULT_PORT 5349
+//
+//
+///**@ingroup tnet_stun_group
+// * STUN2 magic cookie value in network byte order as per RFC 5389 subclause 6.
+//**/
+//#define kStunMagicCookieLong 0x2112A442
+//
+///**@ingroup tnet_stun_group
+// * STUN2 header size as per RFC 5389 subclause 6.
+//**/
+//#define kStunAttrHdrSizeInOctets 20
+//
+///**@ingroup tnet_stun_group
+// * STUN2 binding context.
+//**/
+//typedef struct tnet_stun_binding_s {
+// TSK_DECLARE_OBJECT;
+//
+// //! A unique id to identify this binding.
+// tnet_stun_binding_id_t id;
+//
+// //! The username to authenticate to the STUN server.
+// char* username;
+// //! The password to authenticate to the STUN server.
+// char* password;
+// //! The realm.
+// char* realm;
+// //! The nonce.
+// char* nonce;
+// //! The client name.
+// char* software;
+// //! Local file descriptor for which to get server reflexive address.
+// tnet_fd_t localFD;
+// //! The type of the bound socket.
+// tnet_socket_type_t socket_type;
+// //! The address of the STUN server.
+// struct sockaddr_storage server;
+// //! Server reflexive address of the local socket(STUN1 as per RFC 3489).
+// tnet_stun_attribute_mapped_addr_t *maddr;
+// //! XORed server reflexive address (STUN2 as per RFC 5389).
+// tnet_stun_attribute_xmapped_addr_t *xmaddr;
+//} tnet_stun_binding_t;
+//
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_binding_def_t;
+///**@ingroup tnet_stun_group
+// * List of @ref tnet_stun_binding_t elements.
+//**/
+//typedef tsk_list_t tnet_stun_bindings_L_t;
+//
+////#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
+//struct struct tnet_nat_ctx_s;
+////#endif
+//
+//int tnet_stun_send_reliably(const tnet_stun_pkt_t* message);
+//tnet_stun_pkt_resp_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_pkt_t* message, struct sockaddr* server);
+//TINYNET_API tnet_stun_binding_id_t tnet_stun_bind(const struct struct tnet_nat_ctx_s* nat_context, tnet_fd_t localFD);
+//int tnet_stun_transacid_cmp(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
+//
+//TNET_END_DECLS
+//
+//
+//#endif /* TNET_STUN_H */
+//
diff --git a/tinyNET/src/stun/tnet_stun_attr.c b/tinyNET/src/stun/tnet_stun_attr.c
new file mode 100644
index 0000000..4c31c05
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_attr.c
@@ -0,0 +1,651 @@
+/* Copyright (C) 2015 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stun/tnet_stun_attr.h"
+#include "stun/tnet_stun_utils.h"
+
+#include "tnet_endianness.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#define kWithoutPadding tsk_false
+#define kWithPadding tsk_true
+
+#if !defined(PRINT_DESTROYED_MSG)
+# define PRINT_DESTROYED_MSG 0
+#endif
+
+#define ALIGN_ON_32BITS(size_in_octes) if (((size_in_octes) & 3)) (size_in_octes) += (4 - ((size_in_octes) & 3));
+#define ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(p_buffer, size_in_octes) \
+ if (((size_in_octes) & 3)) { \
+ int c = (4 - ((size_in_octes) & 3)); \
+ memset(p_buffer, 0, c); \
+ (size_in_octes) += c; \
+ }
+
+#define IS_ADDRESS_XOR(e_type) \
+ (e_type == tnet_stun_attr_type_xor_mapped_address || e_type == tnet_stun_attr_type_xor_peer_address || e_type == tnet_stun_attr_type_xor_relayed_address)
+#define IS_VDATA_UINT8(e_type) \
+ (e_type == tnet_stun_attr_type_requested_transport)
+#define IS_VDATA_UINT16(e_type) \
+ (e_type == tnet_stun_attr_type_channel_number)
+#define IS_VDATA_UINT32(e_type) \
+ (e_type == tnet_stun_attr_type_fingerprint || e_type == tnet_stun_attr_type_lifetime || e_type == tnet_stun_attr_type_ice_priority || e_type == tnet_stun_attr_type_connection_id)
+#define IS_VDATA_UINT64(e_type) \
+ (e_type == tnet_stun_attr_type_ice_controlled || e_type == tnet_stun_attr_type_ice_controlling)
+
+static int _tnet_stun_attr_cmp(const tsk_object_t *_att1, const tsk_object_t *_att2)
+{
+ const tnet_stun_attr_t *pc_att1 = (const tnet_stun_attr_t *)_att1;
+ const tnet_stun_attr_t *pc_att2 = (const tnet_stun_attr_t *)_att2;
+
+ return (int)(pc_att1 - pc_att2);
+}
+
+static int _tnet_stun_attr_get_size_in_octetunits(const tnet_stun_attr_t* pc_self, tsk_bool_t with_padding, tsk_size_t* p_size)
+{
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ switch (pc_self->hdr.e_type) {
+ case tnet_stun_attr_type_mapped_address:
+ case tnet_stun_attr_type_alternate_server:
+ case tnet_stun_attr_type_xor_mapped_address:
+ case tnet_stun_attr_type_xor_peer_address:
+ case tnet_stun_attr_type_xor_relayed_address: {
+ extern const tsk_object_def_t *tnet_stun_attr_address_def_t;
+ const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self;
+ if (pc_self->__def__ != tnet_stun_attr_address_def_t) {
+ TSK_DEBUG_ERROR("Invalid base type");
+ return -2;
+ }
+ *p_size = (kStunAttrHdrSizeInOctets + 1/*Ignored*/ + 1/*Family*/ + 2/*Port*/ + ((_pc_self->e_family == tnet_stun_address_family_ipv6) ? 16 : 4));
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ case tnet_stun_attr_type_data:
+ case tnet_stun_attr_type_unknown_attrs:
+ case tnet_stun_attr_type_dont_fragment:
+ case tnet_stun_attr_type_software:
+ case tnet_stun_attr_type_nonce:
+ case tnet_stun_attr_type_realm:
+ case tnet_stun_attr_type_username:
+ case tnet_stun_attr_type_password:
+ case tnet_stun_attr_type_channel_number:
+ case tnet_stun_attr_type_message_integrity:
+ case tnet_stun_attr_type_fingerprint:
+ case tnet_stun_attr_type_lifetime:
+ case tnet_stun_attr_type_requested_transport:
+ case tnet_stun_attr_type_ice_use_candidate:
+ case tnet_stun_attr_type_ice_priority:
+ case tnet_stun_attr_type_ice_controlled:
+ case tnet_stun_attr_type_ice_controlling:
+ case tnet_stun_attr_type_connection_id: {
+ extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t;
+ const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self;
+ if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) {
+ TSK_DEBUG_ERROR("Invalid base type");
+ return -2;
+ }
+ *p_size = (kStunAttrHdrSizeInOctets + _pc_self->u_data_size);
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ case tnet_stun_attr_type_error_code: {
+ const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self;
+ *p_size = (kStunAttrHdrSizeInOctets + 4 + (tsk_size_t)tsk_strlen(_pc_self->p_reason_phrase));
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ default: {
+ TSK_DEBUG_WARN("Attribute type=%d is unknown. Don't be surprised if something goes wrong.", pc_self->hdr.e_type);
+ *p_size = (kStunAttrHdrSizeInOctets + pc_self->hdr.u_length);
+ if (with_padding) {
+ ALIGN_ON_32BITS(*p_size);
+ }
+ return 0;
+ }
+ }
+}
+
+static int _tnet_stun_attr_write(const tnet_stun_transac_id_t* pc_transac_id, const tnet_stun_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t with_padding, tsk_size_t *p_written)
+{
+ tsk_size_t n_min_req_size;
+ int ret;
+ if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = _tnet_stun_attr_get_size_in_octetunits(pc_self, with_padding, &n_min_req_size))) {
+ return ret;
+ }
+ if (n_min_req_size > n_buff_size) {
+ TSK_DEBUG_ERROR("Buffer too short %u<%u", (unsigned)n_buff_size, (unsigned)n_min_req_size);
+ return -2;
+ }
+
+ *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->hdr.e_type);
+ // *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)pc_self->hdr.u_length);
+ *p_written = kStunAttrHdrSizeInOctets;
+
+ switch (pc_self->hdr.e_type) {
+ case tnet_stun_attr_type_mapped_address:
+ case tnet_stun_attr_type_alternate_server:
+ case tnet_stun_attr_type_xor_mapped_address:
+ case tnet_stun_attr_type_xor_peer_address:
+ case tnet_stun_attr_type_xor_relayed_address: {
+ tsk_size_t u_addr_size;
+ extern const tsk_object_def_t *tnet_stun_attr_address_def_t;
+ const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self;
+ tsk_bool_t b_xor = IS_ADDRESS_XOR(pc_self->hdr.e_type);
+ if (pc_self->__def__ != tnet_stun_attr_address_def_t) {
+ TSK_DEBUG_ERROR("Invalid base type");
+ return -2;
+ }
+ p_buff_ptr[*p_written] = 0x00; // Reserved
+ p_buff_ptr[*p_written + 1] = _pc_self->e_family;
+ u_addr_size = (_pc_self->e_family == tnet_stun_address_family_ipv6 ? 16 : 4);
+ if (b_xor) {
+ tsk_size_t u;
+ *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port ^ kStunMagicCookieShort);
+ *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[0])) ^ kStunMagicCookieLong);
+ for (u = 4; u < u_addr_size; u += 4) {
+ if (pc_transac_id) {
+ *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ tnet_ntohl(*((uint32_t*)(*pc_transac_id + u - 4))));
+ }
+ else {
+ *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ 0);
+ }
+ }
+ }
+ else {
+ *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port);
+ memcpy(&p_buff_ptr[*p_written + 4], _pc_self->address, u_addr_size);
+ }
+
+ *p_written += 4 + u_addr_size;
+ *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets);
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ return 0;
+ }
+
+ case tnet_stun_attr_type_data:
+ case tnet_stun_attr_type_unknown_attrs:
+ case tnet_stun_attr_type_dont_fragment:
+ case tnet_stun_attr_type_software:
+ case tnet_stun_attr_type_nonce:
+ case tnet_stun_attr_type_realm:
+ case tnet_stun_attr_type_username:
+ case tnet_stun_attr_type_password:
+ case tnet_stun_attr_type_channel_number:
+ case tnet_stun_attr_type_message_integrity:
+ case tnet_stun_attr_type_fingerprint:
+ case tnet_stun_attr_type_lifetime:
+ case tnet_stun_attr_type_requested_transport:
+ case tnet_stun_attr_type_ice_use_candidate:
+ case tnet_stun_attr_type_ice_priority:
+ case tnet_stun_attr_type_ice_controlled:
+ case tnet_stun_attr_type_ice_controlling:
+ case tnet_stun_attr_type_connection_id: {
+ extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t;
+ const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self;
+ if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) {
+ TSK_DEBUG_ERROR("Invalid base type");
+ return -2;
+ }
+ if (_pc_self->p_data_ptr && _pc_self->u_data_size) {
+ if (IS_VDATA_UINT16(pc_self->hdr.e_type) && _pc_self->u_data_size == 2) {
+ *((uint16_t*)&p_buff_ptr[*p_written]) = tnet_htons_2(&_pc_self->p_data_ptr[0]);
+ }
+ else if (IS_VDATA_UINT32(pc_self->hdr.e_type) && _pc_self->u_data_size == 4) {
+ *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]);
+ }
+ else if (IS_VDATA_UINT64(pc_self->hdr.e_type) && _pc_self->u_data_size == 8) {
+ *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]);
+ *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[4]);
+ }
+ else if (pc_self->hdr.e_type == tnet_stun_attr_type_unknown_attrs && _pc_self->u_data_size && !(_pc_self->u_data_size & 1)) {
+ uint16_t u;
+ for (u = 0; u < _pc_self->u_data_size; u += 2) {
+ *((uint16_t*)&p_buff_ptr[*p_written + u]) = tnet_htons_2(&_pc_self->p_data_ptr[u]);
+ }
+ }
+ else {
+ memcpy(&p_buff_ptr[*p_written], _pc_self->p_data_ptr, _pc_self->u_data_size);
+ }
+ *p_written += _pc_self->u_data_size;
+ }
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets);
+ return 0;
+ }
+ case tnet_stun_attr_type_error_code: {
+ const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self;
+ *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl(((_pc_self->u_class & 0x07) << 8) | _pc_self->u_number);
+ if (_pc_self->p_reason_phrase) {
+ memcpy(&p_buff_ptr[*p_written + 4], _pc_self->p_reason_phrase, tsk_strlen(_pc_self->p_reason_phrase));
+ }
+ *p_written += 4 + tsk_strlen(_pc_self->p_reason_phrase);
+ if (with_padding) {
+ ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written);
+ }
+ *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets);
+ return 0;
+ }
+ default: {
+ TSK_DEBUG_ERROR("Attribute type=%d is unknown.", pc_self->hdr.e_type);
+ return -2;
+ }
+ }
+}
+
+int tnet_stun_attr_init(tnet_stun_attr_t* p_self, tnet_stun_attr_type_t e_type, uint16_t u_length)
+{
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ p_self->hdr.e_type = e_type;
+ p_self->hdr.u_length = u_length;
+ return 0;
+}
+
+int tnet_stun_attr_get_size_in_octetunits_without_padding(const tnet_stun_attr_t* pc_self, tsk_size_t* p_size)
+{
+ return _tnet_stun_attr_get_size_in_octetunits(pc_self, kWithoutPadding, p_size);
+}
+
+int tnet_stun_attr_get_size_in_octetunits_with_padding(const tnet_stun_attr_t* pc_self, tsk_size_t* p_size)
+{
+ return _tnet_stun_attr_get_size_in_octetunits(pc_self, kWithPadding, p_size);
+}
+
+int tnet_stun_attr_write_without_padding(const tnet_stun_transac_id_t* pc_transac_id, const tnet_stun_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ return _tnet_stun_attr_write(pc_transac_id, pc_self, p_buff_ptr, n_buff_size, kWithoutPadding, p_written);
+}
+
+int tnet_stun_attr_write_with_padding(const tnet_stun_transac_id_t* pc_transac_id, const tnet_stun_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ return _tnet_stun_attr_write(pc_transac_id, pc_self, p_buff_ptr, n_buff_size, kWithPadding, p_written);
+}
+
+int tnet_stun_attr_read(const tnet_stun_transac_id_t* pc_transac_id, const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, tnet_stun_attr_t** pp_attr)
+{
+ tnet_stun_attr_type_t Type;
+ uint16_t Length, PadLength;
+ int ret = -1;
+ static const void* kNullBuffPtr = tsk_null;
+ if (!pc_buff_ptr || !n_buff_size || !pp_attr || !p_consumed_octets) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (n_buff_size < kStunAttrHdrSizeInOctets) {
+ TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size);
+ return -2;
+ }
+
+ Type = tnet_ntohs_2(&pc_buff_ptr[0]);
+ Length = tnet_ntohs_2(&pc_buff_ptr[2]);
+ if (Length > n_buff_size) {
+ TSK_DEBUG_ERROR("Buffer too short(%u). Length=%u", (unsigned)n_buff_size, (unsigned)Length);
+ return -3;
+ }
+
+ PadLength = (Length & 0x03) ? (4 - (Length & 0x03)) : 0;
+
+ *pp_attr = tsk_null;
+ *p_consumed_octets = kStunAttrHdrSizeInOctets + Length + PadLength;
+
+ switch (Type) {
+ case tnet_stun_attr_type_mapped_address:
+ case tnet_stun_attr_type_alternate_server:
+ case tnet_stun_attr_type_xor_mapped_address:
+ case tnet_stun_attr_type_xor_peer_address:
+ case tnet_stun_attr_type_xor_relayed_address: {
+ // First 8bits must be ignored
+ tnet_stun_address_family_t e_family = pc_buff_ptr[5];
+ uint16_t u_port = tnet_ntohs_2(&pc_buff_ptr[6]);
+ tnet_stun_attr_address_t* p_attr;
+ tsk_bool_t b_xor = IS_ADDRESS_XOR(Type);
+ uint16_t u, u_addr_size = (e_family == tnet_stun_address_family_ipv6) ? 16 : 4;
+
+ if (b_xor) {
+ u_port ^= kStunMagicCookieShort;
+ }
+ if ((ret = tnet_stun_attr_address_create(Type, e_family, u_port, (const tnet_stun_addr_t*)kNullBuffPtr, &p_attr))) {
+ return ret;
+ }
+ if (b_xor) {
+ *((uint32_t*)&p_attr->address[0]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8]) ^ kStunMagicCookieLong);
+ for (u = 4; u < u_addr_size; u += 4) {
+ if (pc_transac_id) {
+ *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ tnet_ntohl_2(((uint32_t*)(*pc_transac_id + u - 4))));
+ }
+ else {
+ *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ 0);
+ }
+ }
+ }
+ else {
+ memcpy(p_attr->address, &pc_buff_ptr[8], u_addr_size);
+ }
+ *pp_attr = TNET_STUN_ATTR(p_attr);
+ break;
+ }
+
+ case tnet_stun_attr_type_error_code: {
+ // First 21bits must be ignored
+ uint8_t Class = pc_buff_ptr[6] & 0x07;
+ uint8_t Number = pc_buff_ptr[7] & 0xff;
+ tnet_stun_attr_error_code_t* p_attr;
+ if ((ret = tnet_stun_attr_error_code_create(Class, Number, &pc_buff_ptr[8], (Length - 4), &p_attr))) {
+ return ret;
+ }
+ *pp_attr = TNET_STUN_ATTR(p_attr);
+ break;
+ }
+
+ case tnet_stun_attr_type_data:
+ case tnet_stun_attr_type_unknown_attrs:
+ case tnet_stun_attr_type_dont_fragment:
+ case tnet_stun_attr_type_software:
+ case tnet_stun_attr_type_nonce:
+ case tnet_stun_attr_type_realm:
+ case tnet_stun_attr_type_username:
+ case tnet_stun_attr_type_password:
+ case tnet_stun_attr_type_channel_number:
+ case tnet_stun_attr_type_message_integrity:
+ case tnet_stun_attr_type_fingerprint:
+ case tnet_stun_attr_type_lifetime:
+ case tnet_stun_attr_type_requested_transport:
+ case tnet_stun_attr_type_ice_use_candidate:
+ case tnet_stun_attr_type_ice_priority:
+ case tnet_stun_attr_type_ice_controlled:
+ case tnet_stun_attr_type_ice_controlling:
+ case tnet_stun_attr_type_connection_id:
+ default: {
+ tnet_stun_attr_vdata_t* p_attr;
+ if (IS_VDATA_UINT16(Type) && Length == 2) {
+ uint16_t u16 = tnet_ntohs_2(&pc_buff_ptr[4]);
+ if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u16, 2, &p_attr))) {
+ return ret;
+ }
+ }
+ else if (IS_VDATA_UINT32(Type) && Length == 4) {
+ uint32_t u32 = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]);
+ if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u32, 4, &p_attr))) {
+ return ret;
+ }
+ }
+ else if (IS_VDATA_UINT64(Type) && Length == 8) {
+ uint64_t u64 = ((uint64_t)tnet_ntohl_2(&pc_buff_ptr[4])) << 32;
+ u64 |= tnet_ntohl_2(&pc_buff_ptr[8]);
+ if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u64, 8, &p_attr))) {
+ return ret;
+ }
+ }
+ else if (Type == tnet_stun_attr_type_unknown_attrs && Length && !(Length & 1)) {
+ uint16_t u;
+ uint8_t *_p_data_ptr = tsk_malloc(Length);
+ if (!_p_data_ptr) {
+ TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", Length);
+ return -4;
+ }
+ memcpy(_p_data_ptr, &pc_buff_ptr[4], Length);
+ for (u = 0; u < Length; u += 2) {
+ *((uint16_t*)&_p_data_ptr[u]) = tnet_htons_2(&_p_data_ptr[u]);
+ }
+ if ((ret = tnet_stun_attr_vdata_create(Type, _p_data_ptr, Length, &p_attr))) {
+ TSK_FREE(_p_data_ptr);
+ return ret;
+ }
+ TSK_FREE(_p_data_ptr);
+ }
+ else {
+ if ((ret = tnet_stun_attr_vdata_create(Type, &pc_buff_ptr[4], Length, &p_attr))) {
+ return ret;
+ }
+ }
+ *pp_attr = TNET_STUN_ATTR(p_attr);
+ break;
+ }
+ }
+ return ret;
+}
+
+// ============== VDATA (USERNAME, MESSAGE-INTEGRITY, ...) ================ //
+int tnet_stun_attr_vdata_create(tnet_stun_attr_type_t e_type, const uint8_t* pc_data_ptr, uint16_t u_data_size, tnet_stun_attr_vdata_t** pp_attr)
+{
+ int ret = -1;
+ uint16_t u_length = pc_data_ptr ? u_data_size : 0;
+ tnet_stun_attr_vdata_t* p_attr = tsk_null;
+ extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t;
+ if (!pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (!(p_attr = tsk_object_new(tnet_stun_attr_vdata_def_t))) {
+ ret = -2;
+ goto bail;
+ }
+ if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), e_type, u_length))) {
+ goto bail;
+ }
+ if (u_length) {
+ if (!(p_attr->p_data_ptr = tsk_malloc(u_length + 1))) {
+ ret = -3;
+ goto bail;
+ }
+ memcpy(p_attr->p_data_ptr, pc_data_ptr, u_length);
+ p_attr->u_data_size = u_length;
+ p_attr->p_data_ptr[u_length] = '\0';
+ }
+ *pp_attr = p_attr;
+
+bail:
+ if (ret) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ }
+ return ret;
+}
+
+int tnet_stun_attr_vdata_update(tnet_stun_attr_vdata_t* p_self, const uint8_t* pc_data_ptr, uint16_t u_data_size)
+{
+ uint16_t _u_data_size = (pc_data_ptr && u_data_size) ? u_data_size : 0;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (_u_data_size) {
+ if (!(p_self->p_data_ptr = tsk_realloc(p_self->p_data_ptr, _u_data_size + 1))) {
+ p_self->u_data_size = 0;
+ ((tnet_stun_attr_t*)p_self)->hdr.u_length = 0;
+ return -3;
+ }
+ memcpy(p_self->p_data_ptr, pc_data_ptr, _u_data_size);
+ p_self->p_data_ptr[_u_data_size] = '\0';
+ }
+ else {
+ TSK_FREE(p_self->p_data_ptr);
+ }
+ p_self->u_data_size = _u_data_size;
+ ((tnet_stun_attr_t*)p_self)->hdr.u_length = p_self->u_data_size;
+ return 0;
+}
+
+static tsk_object_t* tnet_stun_attr_vdata_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_stun_attr_vdata_t *p_vdata = (tnet_stun_attr_vdata_t *)self;
+ if (p_vdata) {
+ }
+ return self;
+}
+static tsk_object_t* tnet_stun_attr_vdata_dtor(tsk_object_t * self)
+{
+ tnet_stun_attr_vdata_t *p_vdata = (tnet_stun_attr_vdata_t *)self;
+ if (p_vdata) {
+#if PRINT_DESTROYED_MSG
+ TSK_DEBUG_INFO("*** STUN Attribute(VDATA) destroyed ***");
+#endif
+ TSK_FREE(p_vdata->p_data_ptr);
+ }
+ return self;
+}
+static const tsk_object_def_t tnet_stun_attr_vdata_def_s = {
+ sizeof(tnet_stun_attr_vdata_t),
+ tnet_stun_attr_vdata_ctor,
+ tnet_stun_attr_vdata_dtor,
+ _tnet_stun_attr_cmp,
+};
+const tsk_object_def_t *tnet_stun_attr_vdata_def_t = &tnet_stun_attr_vdata_def_s;
+
+
+// ============== ADDRESS ================ //
+int tnet_stun_attr_address_create(tnet_stun_attr_type_t e_type, tnet_stun_address_family_t e_family, uint16_t u_port, const tnet_stun_addr_t* pc_addr, tnet_stun_attr_address_t** pp_attr)
+{
+ int ret = -1;
+ extern const tsk_object_def_t *tnet_stun_attr_address_def_t;
+ tnet_stun_attr_address_t* p_attr = tsk_null;
+ uint16_t u_length = (e_family == tnet_stun_address_family_ipv6) ? 16 : 4;
+ if (!pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_attr = tsk_object_new(tnet_stun_attr_address_def_t))) {
+ ret = -2;
+ goto bail;
+ }
+ if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), e_type, u_length))) {
+ goto bail;
+ }
+ p_attr->e_family = e_family;
+ p_attr->u_port = u_port;
+ if (pc_addr) {
+ memcpy(p_attr->address, *pc_addr, u_length);
+ }
+ *pp_attr = p_attr;
+
+bail:
+ if (ret) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ }
+ return ret;
+}
+
+static tsk_object_t* tnet_stun_attr_address_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_stun_attr_address_t *p_addr = (tnet_stun_attr_address_t *)self;
+ if (p_addr) {
+ }
+ return self;
+}
+static tsk_object_t* tnet_stun_attr_address_dtor(tsk_object_t * self)
+{
+ tnet_stun_attr_address_t *p_addr = (tnet_stun_attr_address_t *)self;
+ if (p_addr) {
+#if PRINT_DESTROYED_MSG
+ TSK_DEBUG_INFO("*** STUN Attribute(ADDRESS) destroyed ***");
+#endif
+ }
+ return self;
+}
+static const tsk_object_def_t tnet_stun_attr_address_def_s = {
+ sizeof(tnet_stun_attr_address_t),
+ tnet_stun_attr_address_ctor,
+ tnet_stun_attr_address_dtor,
+ _tnet_stun_attr_cmp,
+};
+const tsk_object_def_t *tnet_stun_attr_address_def_t = &tnet_stun_attr_address_def_s;
+
+
+
+// ================ 15.6. ERROR-CODE ========== //
+int tnet_stun_attr_error_code_create(uint8_t u_class, uint8_t u_number, const void* pc_reason_phrase, uint16_t u_reason_phrase, struct tnet_stun_attr_error_code_s** pp_attr)
+{
+ int ret = -1;
+ extern const tsk_object_def_t *tnet_stun_attr_error_code_def_t;
+ tnet_stun_attr_error_code_t* p_attr = tsk_null;
+ uint16_t u_length = (uint16_t)(4 + tsk_strlen(pc_reason_phrase));
+ if (!pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(p_attr = tsk_object_new(tnet_stun_attr_error_code_def_t))) {
+ ret = -2;
+ goto bail;
+ }
+ if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), tnet_stun_attr_type_error_code, u_length))) {
+ goto bail;
+ }
+ p_attr->u_class = u_class;
+ p_attr->u_number = u_number;
+ if (pc_reason_phrase && u_reason_phrase) {
+ if (!(p_attr->p_reason_phrase = tsk_strndup(pc_reason_phrase, u_reason_phrase))) {
+ ret = -3;
+ goto bail;
+ }
+ }
+ *pp_attr = p_attr;
+
+bail:
+ if (ret) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ }
+ return ret;
+}
+
+static tsk_object_t* tnet_stun_attr_error_code_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self;
+ if (p_ec) {
+ }
+ return self;
+}
+static tsk_object_t* tnet_stun_attr_error_code_dtor(tsk_object_t * self)
+{
+ tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self;
+ if (p_ec) {
+#if PRINT_DESTROYED_MSG
+ TSK_DEBUG_INFO("*** STUN Attribute(ERROR-CODE) destroyed ***");
+#endif
+ TSK_FREE(p_ec->p_reason_phrase);
+ }
+ return self;
+}
+static const tsk_object_def_t tnet_stun_attr_error_code_def_s = {
+ sizeof(tnet_stun_attr_error_code_t),
+ tnet_stun_attr_error_code_ctor,
+ tnet_stun_attr_error_code_dtor,
+ _tnet_stun_attr_cmp,
+};
+const tsk_object_def_t *tnet_stun_attr_error_code_def_t = &tnet_stun_attr_error_code_def_s;
diff --git a/tinyNET/src/stun/tnet_stun_attr.h b/tinyNET/src/stun/tnet_stun_attr.h
new file mode 100644
index 0000000..0052c66
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_attr.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TNET_STUN_ATTR_H
+#define TNET_STUN_ATTR_H
+
+#include "tinynet_config.h"
+#include "stun/tnet_stun_types.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+
+TNET_BEGIN_DECLS
+
+// rfc5389 - 15. STUN Attributes
+typedef struct tnet_stun_attr_hdr_xs {
+ enum tnet_stun_attr_type_e e_type; // 16bits
+ uint16_t u_length; // 16bits prior to padding, measured in bytes (WITHOUT header)
+} tnet_stun_attr_hdr_xt;
+
+typedef struct tnet_stun_attr_s {
+ TSK_DECLARE_OBJECT;
+ struct tnet_stun_attr_s* pc_base;
+ struct tnet_stun_attr_hdr_xs hdr;
+} tnet_stun_attr_t;
+#define TNET_STUN_DECLARE_ATTR struct tnet_stun_attr_s __base__
+#define TNET_STUN_ATTR(p_self) ((struct tnet_stun_attr_s*)(p_self))
+typedef tsk_list_t tnet_stun_attrs_L_t;
+int tnet_stun_attr_init(struct tnet_stun_attr_s* p_self, enum tnet_stun_attr_type_e e_type, uint16_t u_length);
+TINYNET_API int tnet_stun_attr_get_size_in_octetunits_without_padding(const struct tnet_stun_attr_s* pc_self, tsk_size_t* p_size);
+TINYNET_API int tnet_stun_attr_get_size_in_octetunits_with_padding(const struct tnet_stun_attr_s* pc_self, tsk_size_t* p_size);
+TINYNET_API int tnet_stun_attr_write_without_padding(const tnet_stun_transac_id_t* pc_transac_id, const struct tnet_stun_attr_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYNET_API int tnet_stun_attr_write_with_padding(const tnet_stun_transac_id_t* pc_transac_id, const struct tnet_stun_attr_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYNET_API int tnet_stun_attr_read(const tnet_stun_transac_id_t* pc_transac_id, const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, struct tnet_stun_attr_s** pp_attr);
+
+// ============== VDATA (USERNAME, MESSAGE-INTEGRITY, REALM, NONCE, ...) ================ //
+typedef struct tnet_stun_attr_vdata_s {
+ TNET_STUN_DECLARE_ATTR;
+ uint8_t *p_data_ptr;
+ uint16_t u_data_size;
+} tnet_stun_attr_vdata_t;
+int tnet_stun_attr_vdata_create(enum tnet_stun_attr_type_e e_type, const uint8_t* pc_data_ptr, uint16_t u_data_size, struct tnet_stun_attr_vdata_s** pp_attr);
+int tnet_stun_attr_vdata_update(struct tnet_stun_attr_vdata_s* p_self, const uint8_t* pc_data_ptr, uint16_t u_data_size);
+
+// ============== ADDRESS ================ //
+typedef struct tnet_stun_attr_address_s {
+ TNET_STUN_DECLARE_ATTR;
+ enum tnet_stun_address_family_e e_family; // 8bits
+ uint16_t u_port; // 16bits
+ tnet_stun_addr_t address; // always in network byte order. Use tnet_stun_utils_inet_pton()
+} tnet_stun_attr_address_t;
+
+int tnet_stun_attr_address_create(enum tnet_stun_attr_type_e e_type, enum tnet_stun_address_family_e e_family, uint16_t u_port, const tnet_stun_addr_t* pc_addr, struct tnet_stun_attr_address_s** pp_attr);
+
+// ================ 15.6. ERROR-CODE ========== //
+typedef struct tnet_stun_attr_error_code_s {
+ TNET_STUN_DECLARE_ATTR;
+ uint8_t u_class; // 3bits
+ uint8_t u_number; // 8bits
+ char* p_reason_phrase;
+} tnet_stun_attr_error_code_t;
+int tnet_stun_attr_error_code_create(uint8_t u_class, uint8_t u_number, const void* pc_reason_phrase, uint16_t u_reason_phrase, struct tnet_stun_attr_error_code_s** pp_attr);
+
+TNET_END_DECLS
+
+#endif /* TNET_STUN_ATTR_H */
diff --git a/tinyNET/src/stun/tnet_stun_attribute.c b/tinyNET/src/stun/tnet_stun_attribute.c
new file mode 100644
index 0000000..b8efdcc
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_attribute.c
@@ -0,0 +1,1176 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun_attribute.c
+// * @brief STUN2(RFC 5389) attribute parser.
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#include "tnet_stun_attribute.h"
+//
+//#include "tnet_stun.h"
+//
+//#include "../tnet_types.h"
+//#include "../tnet_endianness.h"
+//
+//#include "../turn/tnet_turn_attribute.h"
+//#include "stun/tnet_stun_types.h"
+//
+//#include "tsk_memory.h"
+//#include "tsk_string.h"
+//#include "tsk_debug.h"
+//
+//#include <string.h>
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15. STUN Attributes
+//* Creates new @ref tnet_stun_attribute_def_t object.
+//*/
+//tnet_stun_attr_t* tnet_stun_attribute_create()
+//{
+// return tsk_object_new(tnet_stun_attribute_def_t);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.1. MAPPED-ADDRESS.
+//* Creates new @ref tnet_stun_attribute_mapped_addr_t object.
+//*/
+//tnet_stun_attribute_mapped_addr_t* tnet_stun_attribute_mapped_address_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_mapped_addr_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS.
+//* Creates new @ref tnet_stun_attribute_xmapped_addr_t object.
+//*/
+//tnet_stun_attribute_xmapped_addr_t* tnet_stun_attribute_xmapped_address_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_xmapped_addr_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.3. USERNAME.
+//* Creates new @ref tnet_stun_attribute_username_t object.
+//*/
+//tnet_stun_attribute_username_t* tnet_stun_attribute_username_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_username_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.4. MESSAGE-INTEGRITY.
+//* Creates new @ref tnet_stun_attribute_integrity_t object.
+//*/
+//tnet_stun_attribute_integrity_t* tnet_stun_attribute_integrity_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_integrity_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.5. FINGERPRINT.
+//* Creates new @ref tnet_stun_attribute_fingerprint_t object.
+//*/
+//tnet_stun_attribute_fingerprint_t* tnet_stun_attribute_fingerprint_create(uint32_t fingerprint)
+//{
+// return tsk_object_new(tnet_stun_attribute_fingerprint_def_t, fingerprint);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.6. ERROR-CODE
+//* Creates new @ref tnet_stun_attribute_errorcode_t object.
+//*/
+//tnet_stun_attribute_errorcode_t* tnet_stun_attribute_errorcode_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_errorcode_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.7. REALM.
+//* Creates new @ref tnet_stun_attribute_realm_t object.
+//*/
+//tnet_stun_attribute_realm_t* tnet_stun_attribute_realm_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_realm_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.8. NONCE.
+//* Creates new @ref tnet_stun_attribute_nonce_t object.
+//*/
+//tnet_stun_attribute_nonce_t* tnet_stun_attribute_nonce_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_nonce_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES.
+//* Creates new @ref tnet_stun_attribute_unknowns_t object.
+//*/
+//tnet_stun_attribute_unknowns_t* tnet_stun_attribute_unknowns_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_unknowns_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.10. SOFTWARE.
+//* Creates new @ref tnet_stun_attribute_software_t object.
+//*/
+//tnet_stun_attribute_software_t* tnet_stun_attribute_software_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_software_def_t, payload, payload_size);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.11. ALTERNATE-SERVER.
+//* Creates new @ref tnet_stun_attribute_altserver_t object.
+//*/
+//tnet_stun_attribute_altserver_t* tnet_stun_attribute_altserver_create(const void* payload, tsk_size_t payload_size)
+//{
+// return tsk_object_new(tnet_stun_attribute_altserver_def_t, payload, payload_size);
+//}
+//
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. PRIORITY */
+//tnet_stun_attribute_ice_priority_t* tnet_stun_attribute_ice_priority_create(uint32_t value)
+//{
+// return tsk_object_new(tnet_stun_attribute_ice_priority_def_t, value);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. USE_CANDIDATE */
+//tnet_stun_attribute_ice_use_candidate_t* tnet_stun_attribute_ice_use_candidate_create()
+//{
+// return tsk_object_new(tnet_stun_attribute_ice_use_candidate_def_t);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. ICE_CONTROLLED */
+//tnet_stun_attribute_ice_controlled_t* tnet_stun_attribute_ice_controlled_create(uint64_t value)
+//{
+// return tsk_object_new(tnet_stun_attribute_ice_controlled_def_t, value);
+//}
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. ICE_CONTROLLING */
+//tnet_stun_attribute_ice_controlling_t* tnet_stun_attribute_ice_controlling_create(uint64_t value)
+//{
+// return tsk_object_new(tnet_stun_attribute_ice_controlling_def_t, value);
+//}
+//
+//
+//
+//
+///**@ingroup tnet_stun_group
+//* Creates @ref tnet_stun_attr_t from raw buffer.
+//* @param data Raw buffer from which to create the STUN attribute.*
+//* @param size The size of the eaw buffer.
+//* @retval @ref tnet_stun_attr_t object if succeed and NULL other wise.
+//*/
+//tnet_stun_attr_t* tnet_stun_attribute_deserialize(const void* data, tsk_size_t size)
+//{
+// tnet_stun_attr_t *attribute = 0;
+// const uint8_t* dataPtr = data;
+//
+// tnet_stun_attr_type_t type = (tnet_stun_attr_type_t)tnet_ntohs_2(dataPtr);
+// uint16_t length = tnet_ntohs_2(&dataPtr[2]);
+//
+// /* Check validity */
+// if(!data || size<=4/* Type(2-bytes) plus Length (2-bytes) */) {
+// return 0;
+// }
+//
+// dataPtr += (2 /* Type */+ 2/* Length */);
+//
+// /* Attribute Value
+// */
+//
+// switch(type) {
+// /* RFC 5389 - 15.1. MAPPED-ADDRESS */
+// case stun_mapped_address: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_mapped_address_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/
+// case stun_xor_mapped_address: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_xmapped_address_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.3. USERNAME*/
+// case stun_username: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_username_create(dataPtr, length);
+// break;
+// }
+//
+//
+// /* RFC 5389 - MESSAGE-INTEGRITY*/
+// case stun_message_integrity: {
+// if(length == TSK_SHA1_DIGEST_SIZE) {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_integrity_create(dataPtr, length);
+// }
+// break;
+// }
+//
+// /* RFC 5389 - 15.5. FINGERPRINT*/
+// case stun_fingerprint: {
+// uint32_t fingerprint = tnet_htonl_2(dataPtr);
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
+// break;
+// }
+//
+// /* RFC 5389 - 15.6. ERROR-CODE*/
+// case stun_error_code: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_errorcode_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.7. REALM*/
+// case stun_realm: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_realm_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.8. NONCE*/
+// case stun_nonce: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_nonce_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES*/
+// case stun_unknown_attributes: {
+// TSK_DEBUG_ERROR("DESERIALIZE:UNKNOWN-ATTRIBUTES ==> NOT IMPLEMENTED");
+// attribute = tnet_stun_attribute_create();
+// break;
+// }
+//
+// /* RFC 5389 - 15.10. SOFTWARE */
+// case stun_software: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_software_create(dataPtr, length);
+// break;
+// }
+//
+// /* RFC 5389 - 15.11. ALTERNATE-SERVER */
+// case stun_alternate_server: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_altserver_create(dataPtr, length);
+// break;
+// }
+//
+// /* draft-ietf-behave-turn-16 subclause 14 */
+// case stun_channel_number:
+// case stun_lifetime:
+// case stun_reserved2:
+// case stun_xor_peer_address:
+// case stun_data:
+// case stun_xor_relayed_address:
+// case stun_even_port:
+// case stun_requested_transport:
+// case stun_dont_fragment:
+// case stun_reserved3:
+// case stun_reservation_token: {
+// //attribute = tnet_turn_attribute_deserialize(type, length, dataPtr, length);
+// attribute = 0;
+// break;
+// }
+//
+// /* RFC 5245 - 19.1. PRIORITY */
+// case stun_ice_priority: {
+// if(length >= 4) {
+// uint32_t value = dataPtr[0] << 24 | dataPtr[1] << 16 | dataPtr[2] << 8 | dataPtr[3];
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_ice_priority_create(value);
+// }
+// break;
+// }
+// /* RFC 5245 - 19.1. USE_CANDIDATE */
+// case stun_ice_use_candidate: {
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_ice_use_candidate_create();
+// break;
+// }
+// /* RFC 5245 - 19.1. ICE_CONTROLLED*/
+// case stun_ice_controlled: {
+// if(length >= 8) {
+// uint64_t value = ((((uint64_t)dataPtr[0]) << 56) | (((uint64_t)dataPtr[1]) << 48) | (((uint64_t)dataPtr[2]) << 40) | (((uint64_t)dataPtr[3]) << 32) | (((uint64_t)dataPtr[4]) << 24) | (((uint64_t)dataPtr[5]) << 16) | ((uint64_t)dataPtr[6]) << 8 | ((uint64_t)dataPtr[7]));
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_ice_controlled_create(value);
+// }
+// break;
+// }
+// /* RFC 5245 - 19.1. ICE_CONTROLLING*/
+// case stun_ice_controlling: {
+// if(length >= 8) {
+// uint64_t value = ((((uint64_t)dataPtr[0]) << 56) | (((uint64_t)dataPtr[1]) << 48) | (((uint64_t)dataPtr[2]) << 40) | (((uint64_t)dataPtr[3]) << 32) | (((uint64_t)dataPtr[4]) << 24) | (((uint64_t)dataPtr[5]) << 16) | ((uint64_t)dataPtr[6]) << 8 | ((uint64_t)dataPtr[7]));
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_ice_controlling_create(value);
+// }
+// break;
+// }
+//
+//
+// default:
+// //TSK_DEBUG_WARN("==> NOT IMPLEMENTED");
+// break;
+// }
+//
+// if(!attribute) {
+// /* Create default */
+// attribute = tnet_stun_attribute_create();
+// }
+//
+// /* Set common values (Do I need this ==> already set by the constructor). */
+// attribute->type = type;
+// attribute->length = length;
+//
+// return attribute;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Serializes a @ref tnet_stun_attr_t objet in binary format.
+//* @param attribute The STUN attribute to serialize.
+//* @param output The output binary buffer.
+//* @retval Zero if succeed and non-zero error code otherwise.
+//*/
+//int tnet_stun_attribute_serialize(const tnet_stun_attr_t* attribute, tsk_buffer_t *output)
+//{
+// if(!attribute || !output) {
+// return -1;
+// }
+//
+// /* Attribute Type
+// */
+// {
+// uint16_t type = tnet_htons(attribute->type);
+// tsk_buffer_append(output, &(type), 2);
+// }
+//
+// /* Attribute Length
+// */
+// {
+// uint16_t length = tnet_htons(attribute->length);
+// tsk_buffer_append(output, &(length), 2);
+// }
+//
+// /* Attribute Value */
+// // NEED to be refactorized
+//
+// switch(attribute->type) {
+// /* RFC 5389 - 15.1. MAPPED-ADDRESS */
+// case stun_mapped_address: {
+// uint32_t u32 = 0;
+// tnet_stun_attribute_mapped_addr_t* ma = (tnet_stun_attribute_mapped_addr_t*)attribute;
+// tsk_size_t addr_size, i;
+// uint32_t addr[4];
+//
+// u32 |= (ma->family << 16);
+// u32 |= (ma->port);
+// u32 = tnet_htonl(u32);
+// tsk_buffer_append(output, &u32, 4);
+//
+// addr_size = (ma->family == stun_ipv6 ? 16 : 4);
+// for(i = 0; i < addr_size; i += 4) {
+// addr[i >> 2] = tnet_htonl_2(&ma->address[i]);
+// }
+// tsk_buffer_append(output, addr, addr_size);
+//
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/
+// case stun_xor_mapped_address: {
+// uint32_t u32 = 0;
+// tnet_stun_attribute_xmapped_addr_t* xma = (tnet_stun_attribute_xmapped_addr_t*)attribute;
+// tsk_size_t addr_size, i;
+// uint32_t addr[4];
+//
+// u32 |= (xma->family << 16);
+// u32 |= (xma->xport);
+// u32 = tnet_htonl(u32);
+// tsk_buffer_append(output, &u32, 4);
+//
+// addr_size = (xma->family == stun_ipv6 ? 16 : 4);
+// for(i = 0; i < addr_size; i += 4) {
+// addr[i >> 2] = tnet_htonl_2(&xma->xaddress[i]);
+// }
+// tsk_buffer_append(output, addr, addr_size);
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.3. USERNAME*/
+// case stun_username: {
+// tnet_stun_attribute_username_t *username = (tnet_stun_attribute_username_t*)attribute;
+// tsk_buffer_append(output, username->value, tsk_strlen(username->value));
+// return 0;
+// }
+//
+//
+// /* RFC 5389 - MESSAGE-INTEGRITY*/
+// case stun_message_integrity: {
+// tnet_stun_attribute_integrity_t *integrity = (tnet_stun_attribute_integrity_t*)attribute;
+// tsk_buffer_append(output, integrity->sha1digest, TSK_SHA1_DIGEST_SIZE);
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.5. FINGERPRINT*/
+// case stun_fingerprint: {
+// uint32_t fingerprint = /*tnet_htonl*/(((tnet_stun_attribute_fingerprint_t*)attribute)->value);
+// tsk_buffer_append(output, &fingerprint, 4);
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.6. ERROR-CODE*/
+// case stun_error_code: {
+// uint32_t u32 = 0;
+// tnet_stun_attribute_errorcode_t *errorcode = (tnet_stun_attribute_errorcode_t*)attribute;
+// u32 |= (errorcode->_class & 0x07) << 8;
+// u32 |= errorcode->number;
+// u32 = tnet_htonl(u32);
+// tsk_buffer_append(output, &u32, 4);
+// tsk_buffer_append(output, errorcode->reason_phrase, tsk_strlen(errorcode->reason_phrase));
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.7. REALM*/
+// case stun_realm: {
+// tnet_stun_attribute_realm_t *realm = (tnet_stun_attribute_realm_t*)attribute;
+// tsk_buffer_append(output, realm->value, tsk_strlen(realm->value));
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.8. NONCE*/
+// case stun_nonce: {
+// tnet_stun_attribute_nonce_t *nonce = (tnet_stun_attribute_nonce_t*)attribute;
+// tsk_buffer_append(output, nonce->value, tsk_strlen(nonce->value));
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES*/
+// case stun_unknown_attributes: {
+// TSK_DEBUG_ERROR("NOT IMPLEMENTED");
+// return -3;
+// }
+//
+// /* RFC 5389 - 15.10. SOFTWARE */
+// case stun_software: {
+// tnet_stun_attribute_software_t *software = (tnet_stun_attribute_software_t*)attribute;
+// tsk_buffer_append(output, software->value, tsk_strlen(software->value));
+// return 0;
+// }
+//
+// /* RFC 5389 - 15.11. ALTERNATE-SERVER */
+// case stun_alternate_server: {
+// TSK_DEBUG_ERROR("NOT IMPLEMENTED");
+// return -3;
+// }
+// /* draft-ietf-behave-turn-16 - */
+// case stun_channel_number:
+// case stun_lifetime:
+// case stun_reserved2:
+// case stun_xor_peer_address:
+// case stun_data:
+// case stun_xor_relayed_address:
+// case stun_even_port:
+// case stun_requested_transport:
+// case stun_dont_fragment:
+// case stun_reserved3:
+// case stun_reservation_token: {
+// return -1;//tnet_turn_attribute_serialize(attribute, output);
+// }
+//
+//
+// /* RFC 5245 - 19.1. PRIORITY */
+// case stun_ice_priority: {
+// uint32_t value = tnet_htonl(((tnet_stun_attribute_ice_priority_t*)attribute)->value);
+// tsk_buffer_append(output, &value, 4);
+// return 0;
+// }
+// /* RFC 5245 - 19.1. USE_CANDIDATE */
+// case stun_ice_use_candidate: {
+// // no body
+// return 0;
+// }
+// /* RFC 5245 - 19.1. ICE_CONTROLLED */
+// case stun_ice_controlled: {
+// uint64_t value = ((tnet_stun_attribute_ice_controlled_t*)attribute)->value;
+// value = ((((uint64_t)tnet_htonl(value >> 32)) << 32) | ((uint64_t)tnet_htonl(value & 0xFFFFFFFF)));
+// tsk_buffer_append(output, &value, 8);
+// return 0;
+// }
+// /* RFC 5245 - 19.1. ICE_CONTROLLING */
+// case stun_ice_controlling: {
+// uint64_t value = ((tnet_stun_attribute_ice_controlling_t*)attribute)->value;
+// value = ((((uint64_t)tnet_htonl(value >> 32)) << 32) | ((uint64_t)tnet_htonl(value & 0xFFFFFFFF)));
+// tsk_buffer_append(output, &value, 8);
+// return 0;
+// }
+//
+// default:
+// return -2;
+// }
+//}
+//
+///**@ingroup tnet_stun_group
+//* Pads a STUN attribute to align it on 4 octets.
+//* @param attribute The STUN attribute to pad.
+//* @param output The output buffer into which to put zeros.
+//*/
+//void tnet_stun_attribute_pad(const tnet_stun_attr_t* attribute, tsk_buffer_t *output)
+//{
+// if(attribute->length & 0x03) {
+// static uint32_t zeros = 0x00000000;
+// tsk_buffer_append(output, &zeros, 4-(attribute->length & 0x03));
+// }
+//}
+//
+//
+//
+//
+////=================================================================================================
+//// [[RFC 5389 - 15. STUN Attributes]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attr_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attr_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_def_s = {
+// sizeof(tnet_stun_attr_t),
+// tnet_stun_attribute_ctor,
+// tnet_stun_attribute_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_def_t = &tnet_stun_attribute_def_s;
+//
+//
+////=================================================================================================
+//// [[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 */
+//
+// 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);
+// }
+// }
+// }
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_mapped_address;
+// TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_mapped_addr_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_mapped_addr_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_mapped_addr_def_s = {
+// sizeof(tnet_stun_attribute_mapped_addr_t),
+// tnet_stun_attribute_mapped_addr_ctor,
+// tnet_stun_attribute_mapped_addr_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_mapped_addr_def_t = &tnet_stun_attribute_mapped_addr_def_s;
+//
+////=================================================================================================
+//// [[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 */
+//
+// 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) ^ kStunMagicCookieLong);
+// memcpy(&attribute->xaddress[i], &addr, 4);
+// payloadPtr+=4;
+// }
+// }
+// else {
+// TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family);
+// }
+// }
+// }
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_mapped_address;
+// TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
+//
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_xmapped_addr_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_xmapped_addr_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_xmapped_addr_def_s = {
+// sizeof(tnet_stun_attribute_xmapped_addr_t),
+// tnet_stun_attribute_xmapped_addr_ctor,
+// tnet_stun_attribute_xmapped_addr_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t = &tnet_stun_attribute_xmapped_addr_def_s;
+//
+//
+////=================================================================================================
+//// [[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;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_username_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_username_t *attribute = self;
+// if(attribute) {
+// TSK_FREE(attribute->value);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_username_def_s = {
+// sizeof(tnet_stun_attribute_username_t),
+// tnet_stun_attribute_username_ctor,
+// tnet_stun_attribute_username_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_username_def_t = &tnet_stun_attribute_username_def_s;
+//
+//
+////=================================================================================================
+//// [[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;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_integrity_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_integrity_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_integrity_def_s = {
+// sizeof(tnet_stun_attribute_integrity_t),
+// tnet_stun_attribute_integrity_ctor,
+// tnet_stun_attribute_integrity_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_integrity_def_t = &tnet_stun_attribute_integrity_def_s;
+//
+//
+////=================================================================================================
+//// [[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;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_fingerprint_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_fingerprint_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_fingerprint_def_s = {
+// sizeof(tnet_stun_attribute_fingerprint_t),
+// tnet_stun_attribute_fingerprint_ctor,
+// tnet_stun_attribute_fingerprint_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t = &tnet_stun_attribute_fingerprint_def_s;
+//
+//
+//
+////=================================================================================================
+//// [[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;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_errorcode_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_errorcode_t *attribute = self;
+// if(attribute) {
+// TSK_FREE(attribute->reason_phrase);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_errorcode_def_s = {
+// sizeof(tnet_stun_attribute_errorcode_t),
+// tnet_stun_attribute_errorcode_ctor,
+// tnet_stun_attribute_errorcode_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t = &tnet_stun_attribute_errorcode_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5389 - 15.7. REALM]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_realm_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_realm_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_realm;
+// TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_realm_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_realm_t *attribute = self;
+// if(attribute) {
+// TSK_FREE(attribute->value);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_realm_def_s = {
+// sizeof(tnet_stun_attribute_realm_t),
+// tnet_stun_attribute_realm_ctor,
+// tnet_stun_attribute_realm_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_realm_def_t = &tnet_stun_attribute_realm_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5389 - 15.8. NONCE]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_nonce_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_nonce_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_nonce;
+// TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_nonce_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_nonce_t *attribute = self;
+// if(attribute) {
+// TSK_FREE(attribute->value);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_nonce_def_s = {
+// sizeof(tnet_stun_attribute_nonce_t),
+// tnet_stun_attribute_nonce_ctor,
+// tnet_stun_attribute_nonce_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_nonce_def_t = &tnet_stun_attribute_nonce_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_unknowns_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_unknowns_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_unknown_attributes;
+// attribute->value = tsk_buffer_create_null();
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_unknowns_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_unknowns_t *attribute = self;
+// if(attribute) {
+// TSK_OBJECT_SAFE_FREE(attribute->value);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_unknowns_def_s = {
+// sizeof(tnet_stun_attribute_unknowns_t),
+// tnet_stun_attribute_unknowns_ctor,
+// tnet_stun_attribute_unknowns_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t = &tnet_stun_attribute_unknowns_def_s;
+//
+////=================================================================================================
+//// [[RFC 5389 - 15.10. SOFTWARE]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_software_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_software_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_software;
+//
+// attribute->value = tsk_strndup(payload, payload_size);
+// TNET_STUN_ATTRIBUTE(attribute)->length = tsk_strlen(attribute->value);
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_software_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_software_t *attribute = self;
+// if(attribute) {
+// TSK_FREE(attribute->value);
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_software_def_s = {
+// sizeof(tnet_stun_attribute_software_t),
+// tnet_stun_attribute_software_ctor,
+// tnet_stun_attribute_software_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_software_def_t = &tnet_stun_attribute_software_def_s;
+//
+////=================================================================================================
+//// [[RFC 5389 - 15.11. ALTERNATE-SERVER]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_altserver_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_altserver_t *attribute = self;
+// if(attribute) {
+// const void *payload = va_arg(*app, const void*);
+// tsk_size_t payload_size = va_arg(*app, tsk_size_t);
+//
+// const uint8_t *payloadPtr = (const uint8_t*)payload;
+// payloadPtr += 1; /* Ignore first 8bits */
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_alternate_server;
+// TNET_STUN_ATTRIBUTE(attribute)->length = payload_size;
+//
+// attribute->family = (tnet_stun_addr_family_t) (*(payloadPtr++));
+// attribute->port = tnet_ntohs_2(payloadPtr);
+// payloadPtr+=2;
+//
+// if(attribute->family == stun_ipv4) {
+// uint32_t addr = tnet_htonl_2(payloadPtr);
+// memcpy(attribute->server, &addr, 4);
+// payloadPtr+=4;
+// }
+// else if(attribute->family == stun_ipv6) {
+// TSK_DEBUG_ERROR("IPv6 not supported yet.");
+// }
+// else {
+// TSK_DEBUG_ERROR("UNKNOWN FAMILY.");
+// }
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_altserver_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_altserver_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_altserver_def_s = {
+// sizeof(tnet_stun_attribute_altserver_t),
+// tnet_stun_attribute_altserver_ctor,
+// tnet_stun_attribute_altserver_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_altserver_def_t = &tnet_stun_attribute_altserver_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5245 - 19.1. PRIORITY]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_ice_priority_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_ice_priority_t *attribute = self;
+// if(attribute) {
+// attribute->value = va_arg(*app, uint32_t);
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_ice_priority;
+// TNET_STUN_ATTRIBUTE(attribute)->length = 4;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_ice_priority_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_ice_priority_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_ice_priority_def_s = {
+// sizeof(tnet_stun_attribute_ice_priority_t),
+// tnet_stun_attribute_ice_priority_ctor,
+// tnet_stun_attribute_ice_priority_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_ice_priority_def_t = &tnet_stun_attribute_ice_priority_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5245 - 19.1. USE-CANDIDATE]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_ice_use_candidate_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_ice_use_candidate_t *attribute = self;
+// if(attribute) {
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_ice_use_candidate;
+// TNET_STUN_ATTRIBUTE(attribute)->length = 0;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_ice_use_candidate_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_ice_use_candidate_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_ice_use_candidate_def_s = {
+// sizeof(tnet_stun_attribute_ice_use_candidate_t),
+// tnet_stun_attribute_ice_use_candidate_ctor,
+// tnet_stun_attribute_ice_use_candidate_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_def_t = &tnet_stun_attribute_ice_use_candidate_def_s;
+//
+//
+////=================================================================================================
+//// [[RFC 5245 - 19.1. ICE-CONTROLLED]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_ice_controlled_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_ice_controlled_t *attribute = self;
+// if(attribute) {
+// attribute->value = va_arg(*app, uint64_t);
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_ice_controlled;
+// TNET_STUN_ATTRIBUTE(attribute)->length = 8;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_ice_controlled_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_ice_controlled_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_ice_controlled_def_s = {
+// sizeof(tnet_stun_attribute_ice_controlled_t),
+// tnet_stun_attribute_ice_controlled_ctor,
+// tnet_stun_attribute_ice_controlled_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_ice_controlled_def_t = &tnet_stun_attribute_ice_controlled_def_s;
+//
+//
+//
+////=================================================================================================
+//// [[RFC 5245 - 19.1. ICE-CONTROLLING]] object definition
+////
+//static tsk_object_t* tnet_stun_attribute_ice_controlling_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_attribute_ice_controlling_t *attribute = self;
+// if(attribute) {
+// attribute->value = va_arg(*app, uint64_t);
+//
+// TNET_STUN_ATTRIBUTE(attribute)->type = stun_ice_controlling;
+// TNET_STUN_ATTRIBUTE(attribute)->length = 8;
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_attribute_ice_controlling_dtor(tsk_object_t * self)
+//{
+// tnet_stun_attribute_ice_controlling_t *attribute = self;
+// if(attribute) {
+// }
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_attribute_ice_controlling_def_s = {
+// sizeof(tnet_stun_attribute_ice_controlling_t),
+// tnet_stun_attribute_ice_controlling_ctor,
+// tnet_stun_attribute_ice_controlling_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_attribute_ice_controlling_def_t = &tnet_stun_attribute_ice_controlling_def_s;
diff --git a/tinyNET/src/stun/tnet_stun_attribute.h b/tinyNET/src/stun/tnet_stun_attribute.h
new file mode 100644
index 0000000..d9e0de7
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_attribute.h
@@ -0,0 +1,356 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun_attribute.h
+// * @brief STUN2(RFC 5389) attribute parser.
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#ifndef TNET_STUN_ATTRIBUTE_H
+//#define TNET_STUN_ATTRIBUTE_H
+//
+//#include "tinynet_config.h"
+//
+//#include "tnet_types.h"
+//
+//#include "tsk_object.h"
+//#include "tsk_buffer.h"
+//#include "tsk_sha1.h"
+//
+///**@ingroup tnet_stun_group
+//* @def TNET_STUN_ATTRIBUTE
+//* Converts (cast) any STUN attribute to @ref tnet_stun_attr_t pointer.
+//* @param self The attribute to convert (cast).
+//* @retval A pointer to @ref tnet_stun_attr_t object.
+//*/
+//TNET_BEGIN_DECLS
+//
+//#define TNET_STUN_ATTRIBUTE(self) ((tnet_stun_attr_t*)(self))
+//
+///**@ingroup tnet_stun_group
+// * STUN IP family as per RFC 5389 subclause 15.1.
+//**/
+//typedef enum tnet_stun_addr_family_e {
+// stun_ipv4 = 0x01,
+// stun_ipv6 = 0x02
+//}
+//tnet_stun_addr_family_t;
+//
+///**@ingroup tnet_stun_group
+// * STUN attribute types as per RFC 5389 subclause 18.2.
+//**/
+//typedef enum tnet_stun_attr_type_e {
+// /* === RFC 5389 - Comprehension-required range (0x0000-0x7FFF) */
+// stun_reserved = 0x0000, /**< (Reserved) */
+// stun_mapped_address = 0x0001, /**< http://tools.ietf.org/html/rfc5389#page-32 */
+// stun_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
+// stun_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
+// stun_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
+// stun_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
+// stun_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
+// stun_password = 0x0007, /**< (Reserved; was PASSWORD) */
+// stun_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
+// stun_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
+// stun_unknown_attributes = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+// stun_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
+// stun_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+// stun_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+// stun_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
+//
+// /* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
+// stun_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
+// stun_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
+// stun_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
+//
+// /* === draft-ietf-behave-turn-16 */
+// stun_channel_number = 0x000C, /**< draft-ietf-behave-turn-16 - CHANNEL-NUMBER */
+// stun_lifetime = 0x000D, /**< draft-ietf-behave-turn-16 - LIFETIME */
+// stun_reserved2 = 0x0010, /**< draft-ietf-behave-turn-16 - Reserved (was BANDWIDTH) */
+// stun_xor_peer_address = 0x0012, /**< draft-ietf-behave-turn-16 - XOR-PEER-ADDRESS */
+// stun_data = 0x0013, /**< draft-ietf-behave-turn-16 - DATA */
+// stun_xor_relayed_address = 0x0016, /**< draft-ietf-behave-turn-16 - XOR-RELAYED-ADDRESS */
+// stun_even_port = 0x0018, /**< draft-ietf-behave-turn-16 - EVEN-PORT */
+// stun_requested_transport = 0x0019, /**< draft-ietf-behave-turn-16 - REQUESTED-TRANSPORT */
+// stun_dont_fragment = 0x001A, /**< draft-ietf-behave-turn-16 - DONT-FRAGMENT */
+// stun_reserved3 = 0x0021, /**< draft-ietf-behave-turn-16 - Reserved (was TIMER-VAL) */
+// stun_reservation_token = 0x0022, /**< draft-ietf-behave-turn-16 - RESERVATION-TOKEN */
+//
+// /* RFC 5245 */
+// stun_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
+// stun_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
+// stun_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
+// stun_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
+//}
+//tnet_stun_attr_type_t;
+//
+//
+///**@ingroup tnet_stun_group
+// RFC 5389 - 15. STUN Attributes
+//*/
+//typedef struct tnet_stun_attribute_s {
+// TSK_DECLARE_OBJECT;
+// /*
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Type | Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Value (variable) ....
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+// tnet_stun_attr_type_t type;
+// uint16_t length;
+//}
+//tnet_stun_attr_t;
+//
+//typedef tsk_list_t tnet_stun_attributes_L_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_def_t;
+//
+//#define TNET_STUN_DECLARE_ATTRIBUTE tnet_stun_attr_t attribute
+//
+//
+///**@ingroup tnet_stun_group
+// *RFC 5389 - 15.1. MAPPED-ADDRESS
+// */
+//typedef struct tnet_stun_attribute_mapped_addr_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// /*
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |0 0 0 0 0 0 0 0| Family | Port |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// | Address (32 bits or 128 bits) |
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+// tnet_stun_addr_family_t family;
+// uint16_t port;
+// uint8_t address[16];
+//}
+//tnet_stun_attribute_mapped_addr_t;
+//
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_mapped_addr_def_t;
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS
+//*/
+//typedef struct tnet_stun_attribute_xmapped_addr_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// /*
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |x x x x x x x x| Family | X-Port |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | X-Address (Variable)
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+// tnet_stun_addr_family_t family;
+// uint16_t xport;
+// uint8_t xaddress[16];
+//}
+//tnet_stun_attribute_xmapped_addr_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t;
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.3. USERNAME.
+//*/
+//typedef struct tnet_stun_attribute_username_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// char* value;
+//}
+//tnet_stun_attribute_username_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.4. MESSAGE-INTEGRITY.
+//*/
+//typedef struct tnet_stun_attribute_integrity_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// tsk_sha1digest_t sha1digest;
+//}
+//tnet_stun_attribute_integrity_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.5. FINGERPRINT.
+//*/
+//typedef struct tnet_stun_attribute_fingerprint_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// uint32_t value;
+//}
+//tnet_stun_attribute_fingerprint_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
+//
+///**@ingroup tnet_stun_group
+// *RFC 5389 - 15.6. ERROR-CODE
+//*/
+//typedef struct tnet_stun_attribute_errorcode_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+// /*
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Reserved, should be 0 |Class| Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Reason Phrase (variable) ..
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+// uint8_t _class;
+// uint8_t number;
+// char* reason_phrase;
+//}
+//tnet_stun_attribute_errorcode_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t;
+//
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.7. REALM. */
+//typedef struct tnet_stun_attribute_realm_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// char* value;
+//}
+//tnet_stun_attribute_realm_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
+//
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.8. NONCE. */
+//typedef struct tnet_stun_attribute_nonce_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// char* value;
+//}
+//tnet_stun_attribute_nonce_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_nonce_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES. */
+//typedef struct tnet_stun_attribute_unknowns_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// tsk_buffer_t *value;
+//}
+//tnet_stun_attribute_unknowns_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.10. SOFTWARE. */
+//typedef struct tnet_stun_attribute_software_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// char *value;
+//}
+//tnet_stun_attribute_software_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_software_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5389 - 15.11. ALTERNATE-SERVER. */
+//typedef struct tnet_stun_attribute_altserver_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//
+// tnet_stun_addr_family_t family;
+// uint16_t port;
+// uint8_t server[128];
+//}
+//tnet_stun_attribute_altserver_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_altserver_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. New Attributes */
+//typedef struct tnet_stun_attribute_ice_priority_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+// uint32_t value;
+//}
+//tnet_stun_attribute_ice_priority_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_priority_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. New Attributes */
+//typedef struct tnet_stun_attribute_ice_use_candidate_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+//}
+//tnet_stun_attribute_ice_use_candidate_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. New Attributes */
+//typedef struct tnet_stun_attribute_ice_controlled_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+// uint64_t value;
+//}
+//tnet_stun_attribute_ice_controlled_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlled_def_t;
+//
+///**@ingroup tnet_stun_group
+//* RFC 5245 - 19.1. New Attributes */
+//typedef struct tnet_stun_attribute_ice_controlling_s {
+// TNET_STUN_DECLARE_ATTRIBUTE;
+// uint64_t value;
+//}
+//tnet_stun_attribute_ice_controlling_t;
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlling_def_t;
+//
+//tnet_stun_attr_t* tnet_stun_attribute_deserialize(const void* data, tsk_size_t size);
+//int tnet_stun_attribute_serialize(const tnet_stun_attr_t* attribute, tsk_buffer_t *output);
+//void tnet_stun_attribute_pad(const tnet_stun_attr_t* attribute, tsk_buffer_t *output);
+//
+//
+//
+//
+//tnet_stun_attr_t* tnet_stun_attribute_create();
+//TINYNET_API tnet_stun_attribute_mapped_addr_t* tnet_stun_attribute_mapped_address_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_xmapped_addr_t* tnet_stun_attribute_xmapped_address_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_username_t* tnet_stun_attribute_username_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_integrity_t* tnet_stun_attribute_integrity_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_fingerprint_t* tnet_stun_attribute_fingerprint_create(uint32_t fingerprint);
+//TINYNET_API tnet_stun_attribute_errorcode_t* tnet_stun_attribute_errorcode_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_realm_t* tnet_stun_attribute_realm_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_nonce_t* tnet_stun_attribute_nonce_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_unknowns_t* tnet_stun_attribute_unknowns_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_software_t* tnet_stun_attribute_software_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_altserver_t* tnet_stun_attribute_altserver_create(const void* payload, tsk_size_t payload_size);
+//TINYNET_API tnet_stun_attribute_ice_priority_t* tnet_stun_attribute_ice_priority_create(uint32_t value);
+//TINYNET_API tnet_stun_attribute_ice_use_candidate_t* tnet_stun_attribute_ice_use_candidate_create();
+//TINYNET_API tnet_stun_attribute_ice_controlled_t* tnet_stun_attribute_ice_controlled_create(uint64_t value);
+//TINYNET_API tnet_stun_attribute_ice_controlling_t* tnet_stun_attribute_ice_controlling_create(uint64_t value);
+//
+//
+//TNET_END_DECLS
+//
+//#endif /* TNET_STUN_ATTRIBUTE_H */
+//
diff --git a/tinyNET/src/stun/tnet_stun_binding.c b/tinyNET/src/stun/tnet_stun_binding.c
new file mode 100644
index 0000000..6455751
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_binding.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stun/tnet_stun_binding.h"
+#include "stun/tnet_stun_pkt.h"
+#include "stun/tnet_stun_attr.h"
+#include "tnet_utils.h"
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+int tnet_stun_binding_create(tnet_fd_t fd, enum tnet_socket_type_e socket_type, const char* pc_server_address, tnet_port_t server_port, const char* pc_username, const char* pc_password, tnet_stun_binding_t** pp_bind)
+{
+ extern const tsk_object_def_t *tnet_stun_binding_def_t;
+ static long __unique_id = 0;
+
+ if (!pp_bind) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(*pp_bind = tsk_object_new(tnet_stun_binding_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create STUN binding object");
+ return -2;
+ }
+ tsk_atomic_inc(&__unique_id);
+ (*pp_bind)->id = __unique_id;
+ (*pp_bind)->localFD = fd;
+ (*pp_bind)->socket_type = socket_type;
+ (*pp_bind)->p_username = tsk_strdup(pc_username);
+ (*pp_bind)->p_password = tsk_strdup(pc_password);
+
+ if (pc_server_address && server_port) {
+ int ret;
+ if ((ret = tnet_sockaddr_init(pc_server_address, server_port, socket_type, &(*pp_bind)->addr_server))) {
+ TSK_OBJECT_SAFE_FREE((*pp_bind));
+ TSK_DEBUG_ERROR("Failed to init STUN server address");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int tnet_stun_binding_create_req(const struct tnet_stun_binding_s* pc_self, struct tnet_stun_pkt_s **pp_req)
+{
+ int ret;
+ if (!pc_self || !pp_req) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, pp_req))) {
+ TSK_DEBUG_ERROR("Failed to create STUN Bind request");
+ goto bail;
+ }
+ // add attributes
+ (*pp_req)->opt.dontfrag = 0;
+ ret = tnet_stun_pkt_attrs_add(*pp_req,
+ TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ if (pc_self->p_username && pc_self->p_realm && pc_self->p_nonce) {
+ if ((ret = tnet_stun_pkt_auth_prepare(*pp_req, pc_self->p_username, pc_self->p_password, pc_self->p_realm, pc_self->p_nonce))) {
+ goto bail;
+ }
+ }
+
+bail:
+ if (ret) {
+ TSK_OBJECT_SAFE_FREE(*pp_req);
+ }
+ return ret;
+}
+
+static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_stun_binding_t *p_bind = (tnet_stun_binding_t *)self;
+ if (p_bind) {
+ }
+ return self;
+}
+static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
+{
+ tnet_stun_binding_t *p_bind = (tnet_stun_binding_t *)self;
+ if (p_bind) {
+ TSK_DEBUG_INFO("*** STUN BINDING destroyed ***");
+ TSK_FREE(p_bind->p_username);
+ TSK_FREE(p_bind->p_password);
+ TSK_FREE(p_bind->p_realm);
+ TSK_FREE(p_bind->p_nonce);
+
+ TSK_OBJECT_SAFE_FREE(p_bind->p_maddr);
+ TSK_OBJECT_SAFE_FREE(p_bind->p_xmaddr);
+ }
+ return self;
+}
+static int tnet_stun_binding_cmp(const tsk_object_t *_bind1, const tsk_object_t *_bind2)
+{
+ const tnet_stun_binding_t *pc_bind1 = (const tnet_stun_binding_t *)_bind1;
+ const tnet_stun_binding_t *pc_bind2 = (const tnet_stun_binding_t *)_bind2;
+
+ return (pc_bind1 && pc_bind2) ? (int)(pc_bind1->id - pc_bind2->id) : (int)(pc_bind1 - pc_bind2);
+}
+static const tsk_object_def_t tnet_stun_binding_def_s = {
+ sizeof(tnet_stun_binding_t),
+ tnet_stun_binding_ctor,
+ tnet_stun_binding_dtor,
+ tnet_stun_binding_cmp,
+};
+const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;
diff --git a/tinyNET/src/stun/tnet_stun_binding.h b/tinyNET/src/stun/tnet_stun_binding.h
new file mode 100644
index 0000000..d7e2ae4
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_binding.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TNET_STUN_BINDING_H
+#define TNET_STUN_BINDING_H
+
+#include "tinynet_config.h"
+#include "tnet_socket.h"
+#include "stun/tnet_stun_types.h"
+#include "stun/tnet_stun_attr.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+
+TNET_BEGIN_DECLS
+
+struct tnet_stun_pkt_s;
+
+typedef struct tnet_stun_binding_s {
+ TSK_DECLARE_OBJECT;
+
+ //! A unique id to identify this binding.
+ tnet_stun_binding_id_t id;
+
+ //! The username to authenticate to the STUN server.
+ char* p_username;
+ //! The password to authenticate to the STUN server.
+ char* p_password;
+ //! The realm.
+ char* p_realm;
+ //! The nonce.
+ char* p_nonce;
+ //! Local file descriptor for which to get server reflexive address.
+ tnet_fd_t localFD;
+ //! The type of the bound socket.
+ enum tnet_socket_type_e socket_type;
+ //! The address of the STUN server.
+ struct sockaddr_storage addr_server;
+ //! Server reflexive address of the local socket(STUN1 as per RFC 3489).
+ struct tnet_stun_attr_address_s *p_maddr;
+ //! XORed server reflexive address (STUN2 as per RFC 5389).
+ struct tnet_stun_attr_address_s *p_xmaddr;
+}
+tnet_stun_binding_t;
+typedef tsk_list_t tnet_stun_bindings_L_t;
+
+int tnet_stun_binding_create(tnet_fd_t fd, enum tnet_socket_type_e socket_type, const char* pc_server_address, tnet_port_t server_port, const char* pc_username, const char* pc_password, tnet_stun_binding_t** pp_bind);
+int tnet_stun_binding_create_req(const struct tnet_stun_binding_s* pc_self, struct tnet_stun_pkt_s **pp_req);
+
+TNET_END_DECLS
+
+#endif /* TNET_STUN_BINDING_H */
diff --git a/tinyNET/src/stun/tnet_stun_message.c b/tinyNET/src/stun/tnet_stun_message.c
new file mode 100644
index 0000000..25d29a5
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_message.c
@@ -0,0 +1,495 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun_message.c
+// * @brief STUN2 (RFC 5389) message parser.
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#include "tnet_stun_message.h"
+//
+//#include "tnet_stun.h"
+//
+//#include "../tnet_types.h"
+//#include "../tnet_endianness.h"
+//#include "../turn/tnet_turn_attribute.h"
+//#include "stun/tnet_stun_types.h"
+//
+//#include "tsk_memory.h"
+//#include "tsk_hmac.h"
+//#include "tsk_string.h"
+//#include "tsk_ppfcs32.h"
+//
+//#include <string.h>
+//
+//static int __pred_find_attribute_by_type(const tsk_list_item_t *item, const void *att_type)
+//{
+// if(item && item->data) {
+// tnet_stun_attr_t *att = item->data;
+// tnet_stun_attr_type_t type = *((tnet_stun_attr_type_t*)att_type);
+// return (att->type - type);
+// }
+// return -1;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Creates new STUN message.
+//* @retval @ref tnet_stun_pkt_t object.
+//* @sa tnet_stun_message_create_null.
+//*/
+//
+//tnet_stun_pkt_t* tnet_stun_message_create(const char* username, const char* password)
+//{
+// return tsk_object_new(tnet_stun_message_def_t, username, password);
+//}
+//
+///**@ingroup tnet_stun_group
+//* Creates new STUN message.
+//* @retval @ref tnet_stun_pkt_t object.
+//* @sa tnet_stun_message_create.
+//*/
+//tnet_stun_pkt_t* tnet_stun_message_create_null()
+//{
+// return tnet_stun_message_create(tsk_null, tsk_null);
+//}
+//
+//#define SERIALIZE_N_ADD_ATTRIBUTE(att_name, payload, payload_size) \
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_##att_name##_create(payload, payload_size); \
+// tnet_stun_attribute_serialize(attribute, output); \
+// tnet_stun_attribute_pad(attribute, output); \
+// TSK_OBJECT_SAFE_FREE(attribute);
+//
+///**@ingroup tnet_stun_group
+// * Serializes a STUN message as binary data.
+// * @param [in,out] self The STUN message to serialize.
+// * @retval A buffer holding the binary data (result) if serialization succeed and zero otherwise.
+//**/
+//tsk_buffer_t* tnet_stun_pkt_serialize(const tnet_stun_pkt_t *self)
+//{
+// tsk_buffer_t *output = 0;
+// tnet_stun_attr_t *attribute;
+// unsigned compute_integrity = self->integrity;
+//
+// if(!self) {
+// goto bail;
+// }
+//
+// output = tsk_buffer_create_null();
+//
+// /* RFC 5389 - 6. STUN Message Structure
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |0 0| STUN Message Type | Message Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Magic Cookie |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// | Transaction ID (96 bits) |
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+//
+// /* STUN Message Type
+// */
+// {
+// uint16_t type = tnet_htons(self->type);
+// tsk_buffer_append(output, &(type), 2);
+// }
+//
+// /* Message Length ==> Will be updated after attributes have been added. */
+// {
+// static const uint16_t length = 0;
+// tsk_buffer_append(output, &(length), 2);
+// }
+//
+// /* Magic Cookie
+// */
+// {
+// uint32_t cookie = tnet_htonl(self->cookie);
+// tsk_buffer_append(output, &(cookie), 4);
+// }
+//
+//
+// /* Transaction ID (96 bits==>16bytes)
+// */
+// tsk_buffer_append(output, self->transac_id, TNET_STUN_TRANSACID_SIZE);
+//
+// /* DONT-FRAGMENT
+// */
+// if(self->dontfrag) {
+// /*attribute = (tnet_stun_attr_t *)tnet_turn_attribute_dontfrag_create();
+// tnet_stun_attribute_serialize(attribute, output);
+// TSK_OBJECT_SAFE_FREE(attribute);*/
+// }
+//
+// /* AUTHENTICATION */
+// if(self->realm && self->nonce) { // long term
+// SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm));
+// SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce));
+//
+// compute_integrity = !self->nointegrity;
+// }
+// else if(self->password) { // short term
+// compute_integrity = !self->nointegrity;
+// }
+//
+// if(compute_integrity && self->username) {
+// SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
+// }
+//
+// /*=== Attributes === */
+// {
+// tsk_list_item_t *item;
+// tsk_list_foreach(item, self->attributes) {
+// attribute = item->data;
+// tnet_stun_attribute_serialize(attribute, output);
+// tnet_stun_attribute_pad(attribute, output);
+// }
+// }
+//
+// /* Message Length: The message length MUST contain the size, in bytes, of the message
+// not including the 20-byte STUN header.
+// */
+// {
+// // compute length for 'MESSAGE-INTEGRITY'
+// // will be computed again to store the correct value
+// uint16_t length = (output->size) - kStunAttrHdrSizeInOctets;
+//#if 0
+// if(self->fingerprint) {
+// length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
+// }
+//#endif
+//
+// if(compute_integrity) {
+// length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
+// }
+//
+// *(((uint16_t*)output->data)+1) = tnet_htons(length);
+// }
+//
+// /* MESSAGE-INTEGRITY */
+// if(compute_integrity) {
+// /* RFC 5389 - 15.4. MESSAGE-INTEGRITY
+// The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
+//
+// For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
+// For short-term credentials ==> key = SASLprep(password)
+// */
+//
+// tsk_sha1digest_t hmac;
+//
+// if(self->username && self->realm && self->password) { // long term
+// char* keystr = tsk_null;
+// tsk_md5digest_t md5;
+// tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
+// TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
+// hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
+//
+// TSK_FREE(keystr);
+// }
+// else { // short term
+// hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
+// }
+//
+// SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
+// }
+//
+// // LENGTH
+// *(((uint16_t*)output->data) + 1) = tnet_htons((output->size - kStunAttrHdrSizeInOctets + (self->fingerprint ? 8 : 0)));
+//
+// /* FINGERPRINT */
+// if(self->fingerprint) { //JINGLE_ICE
+// /* RFC 5389 - 15.5. FINGERPRINT
+// The FINGERPRINT attribute MAY be present in all STUN messages. The
+// value of the attribute is computed as the CRC-32 of the STUN message
+// up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
+// the 32-bit value 0x5354554e
+// */
+// uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size);
+// fingerprint ^= 0x5354554e;
+// fingerprint = tnet_htonl(fingerprint);
+//
+// attribute = (tnet_stun_attr_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
+// tnet_stun_attribute_serialize(attribute, output);
+// TSK_OBJECT_SAFE_FREE(attribute);
+// }
+//
+//bail:
+// return output;
+//}
+//
+//
+///**@ingroup tnet_stun_group
+// *
+// * Deserializes a STUN message from binary data.
+// *
+// * @param [in,out] data A pointer to the binary data.
+// * @param size The size of the binary data.
+// *
+// * @retval A STUN message if deserialization succeed or NULL otherwise.
+//**/
+//tnet_stun_pkt_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size)
+//{
+// tnet_stun_pkt_t *message = 0;
+// uint8_t* dataPtr, *dataEnd;
+//
+//
+// if(!data || (size < kStunAttrHdrSizeInOctets) || !TNET_STUN_BUFF_IS_STUN2(data, size)) {
+// goto bail;
+// }
+//
+// dataPtr = (uint8_t*)data;
+// dataEnd = (dataPtr + size);
+//
+// message = tnet_stun_message_create_null();
+//
+// /* Message Type
+// */
+// message->type = (tnet_stun_pkt_type_t)tnet_ntohs_2(dataPtr);
+// dataPtr += 2;
+//
+// /* Message Length
+// */
+// message->length = tnet_ntohs_2(dataPtr);
+// dataPtr += 2;
+//
+// /* Check message validity
+// */
+// if((message->length + kStunAttrHdrSizeInOctets) != size) {
+// TSK_OBJECT_SAFE_FREE(message);
+// goto bail;
+// }
+//
+// /* Magic Cookie
+// ==> already set by the constructor and checked by @ref TNET_IS_STUN2
+// */
+// dataPtr += 4;
+//
+// /* Transaction ID
+// */
+// memcpy(message->transac_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
+// dataPtr += TNET_STUN_TRANSACID_SIZE;
+//
+// /* == Parse attributes
+// */
+// while(dataPtr < dataEnd) {
+// tnet_stun_attr_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr));
+// if(attribute) {
+// tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */);
+// att_size += (att_size & 0x03) ? 4-(att_size & 0x03) : 0; // Skip zero bytes used to pad the attribute.
+//
+// dataPtr += att_size;
+// tsk_list_push_back_data(message->attributes, (void**)&attribute);
+//
+// continue;
+// }
+// else {
+// continue;
+// }
+// }
+//
+//bail:
+// return message;
+//}
+//
+///**@ingroup tnet_stun_group
+//*/
+//tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
+//{
+// return (tnet_stun_message_get_attribute(self, type) != tsk_null);
+//}
+//
+///**@ingroup tnet_stun_group
+//* Adds an attribute to a STUN message.
+//* @param self The STUN message into which to add the attribute.
+//* @param attribute The attribute to add.
+//* @retval Zero if succeed and non-zero error code otherwise.
+//*/
+//int tnet_stun_message_add_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_t** attribute)
+//{
+// if(self && attribute && *attribute) {
+// tsk_list_push_back_data(self->attributes, (void**)attribute);
+// return 0;
+// }
+// return -1;
+//}
+//
+///**@ingroup tnet_stun_group
+//*/
+//int tnet_stun_message_remove_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
+//{
+// if(self && self->attributes) {
+// tsk_list_remove_item_by_pred(self->attributes, __pred_find_attribute_by_type, &type);
+// }
+// return 0;
+//}
+//
+//
+///**@ingroup tnet_stun_group
+//* Gets a STUN attribute from a message.
+//* @param self The message from which to get the attribute.
+//* @param type The type of the attribute to retrieve.
+//* @retval @ref tnet_stun_attr_t object if found and NULL otherwise.
+//*/
+//const tnet_stun_attr_t* tnet_stun_message_get_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type)
+//{
+// tnet_stun_attr_t* attribute;
+//
+// if(self && !TSK_LIST_IS_EMPTY(self->attributes)) {
+// tsk_list_item_t *item;
+// tsk_list_foreach(item, self->attributes) {
+// if((attribute = item->data) && attribute->type == type) {
+// return attribute;
+// }
+// }
+// }
+// return 0;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Gets the STUN error-code attribute value from the message.
+//* @param self The STUN message from which to get the error code.
+//* @retval The error code if the message contain such attribute or -1 otherwise.
+//*/
+//short tnet_stun_message_get_errorcode(const tnet_stun_pkt_t *self)
+//{
+// const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code);
+// if(error) {
+// return ((error->_class*100) + error->number);
+// }
+// return -1;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Gets the STUN @b realm attribute value from the message.
+//* @param self The STUN message from which to get the @b realm.
+//* @retval The @b realm as a string pointer code if the message contain such attribute or NULL otherwise.
+//*/
+//const char* tnet_stun_message_get_realm(const tnet_stun_pkt_t *self)
+//{
+// const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm);
+// if(realm) {
+// return realm->value;
+// }
+// return 0;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Gets the STUN @b nonce attribute value from the message.
+//* @param self The STUN message from which to get the @b nonce.
+//* @retval The @b nonce as a string pointer code if the message contain such attribute or NULL otherwise.
+//*/
+//const char* tnet_stun_message_get_nonce(const tnet_stun_pkt_t *self)
+//{
+// const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce);
+// if(nonce) {
+// return nonce->value;
+// }
+// return 0;
+//}
+//
+///**@ingroup tnet_stun_group
+//* Gets the STUN @b lifetime attribute value from the message.
+//* @param self The STUN message from which to get the @b lifetime.
+//* @retval The @b lifetime (any positive value) if the message contain such attribute or -1 otherwise.
+//*/
+//int32_t tnet_stun_message_get_lifetime(const tnet_stun_pkt_t *self)
+//{
+// /*const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime);
+// if(lifetime) {
+// return lifetime->value;
+// }*/
+// return -1;
+//}
+//
+///**@ingroup tnet_stun_group
+//*/
+//tsk_bool_t tnet_stun_utils_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2)
+//{
+// tsk_size_t i;
+// static const tsk_size_t size = sizeof(tnet_stun_transac_id_t);
+// for(i = 0; i < size; i++) {
+// if(id1[i] != id2[i]) {
+// return tsk_false;
+// }
+// }
+// return tsk_true;
+//}
+//
+//
+//
+//
+//
+//
+////=================================================================================================
+//// STUN2 MESSAGE object definition
+////
+//static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app)
+//{
+// tnet_stun_pkt_t *message = self;
+// if(message) {
+// message->username = tsk_strdup(va_arg(*app, const char*));
+// message->password = tsk_strdup(va_arg(*app, const char*));
+//
+// message->cookie = kStunMagicCookieLong;
+// message->attributes = tsk_list_create();
+//
+// message->fingerprint = 1;
+// message->integrity = 0;
+//
+// {
+// // Create random transaction id
+// int i;
+// for(i = 0; i < sizeof(message->transac_id)/sizeof(message->transac_id[0]); ++i) {
+// message->transac_id[i] = rand();
+// }
+// }
+// }
+// return self;
+//}
+//
+//static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self)
+//{
+// tnet_stun_pkt_t *message = self;
+// if(message) {
+// TSK_FREE(message->username);
+// TSK_FREE(message->password);
+// TSK_FREE(message->realm);
+// TSK_FREE(message->nonce);
+//
+// TSK_OBJECT_SAFE_FREE(message->attributes);
+// }
+//
+// return self;
+//}
+//
+//static const tsk_object_def_t tnet_stun_message_def_s = {
+// sizeof(tnet_stun_pkt_t),
+// tnet_stun_message_ctor,
+// tnet_stun_message_dtor,
+// tsk_null,
+//};
+//const tsk_object_def_t *tnet_stun_message_def_t = &tnet_stun_message_def_s;
+//
diff --git a/tinyNET/src/stun/tnet_stun_message.h b/tinyNET/src/stun/tnet_stun_message.h
new file mode 100644
index 0000000..70660f5
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_message.h
@@ -0,0 +1,246 @@
+///*
+//* Copyright (C) 2010-2011 Mamadou Diop.
+//*
+//* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
+//*
+//* This file is part of Open Source Doubango Framework.
+//*
+//* DOUBANGO is free software: you can redistribute it and/or modify
+//* it under the terms of the GNU General Public License as published by
+//* the Free Software Foundation, either version 3 of the License, or
+//* (at your option) any later version.
+//*
+//* DOUBANGO is distributed in the hope that it will be useful,
+//* but WITHOUT ANY WARRANTY; without even the implied warranty of
+//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//* GNU General Public License for more details.
+//*
+//* You should have received a copy of the GNU General Public License
+//* along with DOUBANGO.
+//*
+//*/
+//
+///**@file tnet_stun_message.h
+// * @brief STUN2 (RFC 5389) message parser.
+// *
+// * @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
+// *
+//
+// */
+//#ifndef TNET_STUN_MESSAGE_H
+//#define TNET_STUN_MESSAGE_H
+//
+//#include "tinynet_config.h"
+//#include "stun/tnet_stun_attribute.h"
+//
+//#include "tsk_buffer.h"
+//
+//TNET_BEGIN_DECLS
+//
+//#define TNET_STUN_CLASS_REQUEST_MASK (0x0000)
+//#define TNET_STUN_CLASS_INDICATION_MASK (0x0010)
+//#define TNET_STUN_CLASS_SUCCESS_MASK (0x0100)
+//#define TNET_STUN_CLASS_ERROR_MASK (0x0110)
+//
+///**@ingroup tnet_stun_group
+//* @def TNET_STUN_MESSAGE_IS_REQUEST
+//* Checks whether the STUN message is a request or not.
+//*/
+///**@ingroup tnet_stun_group
+//* @def TNET_STUN_MESSAGE_IS_INDICATION
+//* Checks whether the STUN message is an indicaton message or not.
+//*/
+///**@ingroup tnet_stun_group
+//* @def TNET_STUN_PKT_RESP_IS_SUCCESS
+//* Checks whether the STUN message is a success response or not.
+//*/
+///**@ingroup tnet_stun_group
+//* @def TNET_STUN_PKT_RESP_IS_ERROR
+//* Checks whether the STUN message is an error response or not.
+//*/
+//#define TNET_STUN_MESSAGE_IS_REQUEST(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_REQUEST_MASK))
+//#define TNET_STUN_MESSAGE_IS_RESPONSE(self) (TNET_STUN_PKT_RESP_IS_SUCCESS((self)) || TNET_STUN_PKT_RESP_IS_ERROR((self)))
+//#define TNET_STUN_MESSAGE_IS_INDICATION(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_INDICATION_MASK))
+//#define TNET_STUN_PKT_RESP_IS_SUCCESS(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_SUCCESS_MASK))
+//#define TNET_STUN_PKT_RESP_IS_ERROR(self) ((self) && (((self)->type & 0x0110) == TNET_STUN_CLASS_ERROR_MASK))
+//
+///**@ingroup tnet_stun_group
+// * Checks if the pointer to the buffer hold a STUN header by checking that it starts with 0b00 and contain the magic cookie.
+// * As per RFC 5389 subclause 19: Explicitly point out that the most significant 2 bits of STUN are
+// * 0b00, allowing easy differentiation with RTP packets when used with ICE.
+// * As per RFC 5389 subclause 6: The magic cookie field MUST contain the fixed value 0x2112A442 in
+// * network byte order.
+// *
+// * @param PU8 The pointer to the buffer holding the STUN raw data.
+//**/
+//#define TNET_STUN_BUFF_IS_STUN2(PU8, SIZE) \
+// ( \
+// ((PU8)) && \
+// ((SIZE) >= kStunAttrHdrSizeInOctets) && \
+// (((PU8)[0] & 0xc0) == 0x00) && \
+// ( PU8[4] == 0x21 && PU8[5] == 0x12 && PU8[6] == 0xA4 && PU8[7] == 0x42 ) \
+// )
+//#define TNET_IS_STUN2 TNET_STUN_BUFF_IS_STUN2 // for backward compatibility
+//
+///**@ingroup tnet_stun_group
+// * STUN trasactionn ID size (96bits = 12bytes).
+//*/
+//#define TNET_STUN_TRANSACID_SIZE 12
+//
+///**@ingroup tnet_stun_group
+// * Defines an alias representing the STUN transaction id type.
+//**/
+//typedef uint8_t tnet_stun_transac_id_t[TNET_STUN_TRANSACID_SIZE];
+//
+///**@ingroup tnet_stun_group
+// * List of all supported STUN classes as per RFC 5389 subcaluse 6.
+//**/
+//typedef enum tnet_stun_class_type_e {
+// stun_class_request = 0x00, /**< Request class: 0b00 */
+// stun_class_indication = 0x01, /**< Indication class: 0b01 */
+// stun_class_success_response = 0x02, /**< Success response class: 0b10 */
+// stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
+//}
+//tnet_stun_class_type_t;
+//
+///**@ingroup tnet_stun_group
+// * List of all supported STUN methods.
+// * RFC 5389 only define one method(Bining). All other methods have been defined
+// * by TURN (draft-ietf-behave-turn-16 and draft-ietf-behave-turn-tcp-05).
+//**/
+//typedef enum tnet_stun_method_type_e {
+// stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
+//
+// stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
+// stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
+// stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
+// stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
+// stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
+// stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
+//}
+//tnet_stun_method_type_t;
+//
+///**@ingroup tnet_stun_group
+//* List of all supported STUN types.
+//*/
+//typedef enum tnet_stun_pkt_type_e {
+// /* RFC 5389 - 6. STUN Message Structure
+//
+// The message type defines the message class (request, success
+// response, failure response, or indication) and the message method
+// (the primary function) of the STUN message. Although there are four
+// message classes, there are only two types of transactions in STUN:
+// request/response transactions (which consist of a request message and
+// a response message) and indication transactions (which consist of a
+// single indication message). Response classes are split into error
+// and success responses to aid in quickly processing the STUN message.
+//
+// The message type field is decomposed further into the following
+// structure:
+//
+// 0 1
+// 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
+// |M |M |M|M|M|C|M|M|M|C|M|M|M|M|
+// |11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+// +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+// stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
+// stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
+// stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
+// stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
+//
+// stun_allocate_request = (stun_method_allocate | TNET_STUN_CLASS_REQUEST_MASK),
+// stun_allocate_indication = (stun_method_allocate | TNET_STUN_CLASS_INDICATION_MASK),
+// stun_allocate_success_response = (stun_method_allocate | TNET_STUN_CLASS_SUCCESS_MASK),
+// stun_allocate_error_response = (stun_method_allocate | TNET_STUN_CLASS_ERROR_MASK),
+//
+// stun_refresh_request = (stun_method_refresh | TNET_STUN_CLASS_REQUEST_MASK),
+// stun_refresh_indication = (stun_method_refresh | TNET_STUN_CLASS_INDICATION_MASK),
+// stun_refresh_success_response = (stun_method_refresh | TNET_STUN_CLASS_SUCCESS_MASK),
+// stun_refresh_error_response = (stun_method_refresh | TNET_STUN_CLASS_ERROR_MASK),
+//
+// stun_send_indication = (stun_method_send | TNET_STUN_CLASS_INDICATION_MASK),
+//
+// stun_data_indication = (stun_method_data | TNET_STUN_CLASS_INDICATION_MASK),
+//
+// stun_createpermission_request = (stun_method_createpermission | TNET_STUN_CLASS_REQUEST_MASK),
+// stun_createpermission_indication = (stun_method_createpermission | TNET_STUN_CLASS_INDICATION_MASK),
+// stun_createpermission_success_response = (stun_method_createpermission | TNET_STUN_CLASS_SUCCESS_MASK),
+// stun_createpermission_error_response = (stun_method_createpermission | TNET_STUN_CLASS_ERROR_MASK),
+//
+// stun_channelbind_request = (stun_method_channelbind | TNET_STUN_CLASS_REQUEST_MASK),
+// stun_channelbind_indication = (stun_method_channelbind | TNET_STUN_CLASS_INDICATION_MASK),
+// stun_channelbind_success_response = (stun_method_channelbind | TNET_STUN_CLASS_SUCCESS_MASK),
+// stun_channelbind_error_response = (stun_method_channelbind | TNET_STUN_CLASS_ERROR_MASK),
+//}
+//tnet_stun_pkt_type_t;
+//
+///**@ingroup tnet_stun_group
+// *
+// * STUN Message structure as per RFC 5389 subclause 6.
+// * http://tools.ietf.org/html/rfc5389#section-6
+//*/
+//typedef struct tnet_stun_pkt_s {
+// TSK_DECLARE_OBJECT;
+//
+// /*
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |0 0| STUN Message Type | Message Length |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | Magic Cookie |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | |
+// | Transaction ID (96 bits) |
+// | |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// */
+//
+// tnet_stun_pkt_type_t type;
+// uint16_t length;
+// uint32_t cookie;
+// tnet_stun_transac_id_t transaction_id;
+//
+// unsigned fingerprint:1;
+// unsigned integrity:1;
+// unsigned dontfrag:1;
+// unsigned nointegrity:1;
+//
+// char* username;
+// char* password;
+// char* realm;
+// char* nonce;
+//
+// tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
+//}
+//tnet_stun_pkt_t;
+//
+//typedef tnet_stun_pkt_t tnet_stun_pkt_resp_t;
+//typedef tnet_stun_pkt_t tnet_stun_pkt_req_t;
+//
+//TINYNET_API tsk_buffer_t* tnet_stun_pkt_serialize(const tnet_stun_pkt_t *message);
+//tnet_stun_pkt_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size);
+//tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
+//TINYNET_API int tnet_stun_message_add_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_t** attribute);
+//int tnet_stun_message_remove_attribute(tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
+//const tnet_stun_attr_t* tnet_stun_message_get_attribute(const tnet_stun_pkt_t *self, tnet_stun_attr_type_t type);
+//short tnet_stun_message_get_errorcode(const tnet_stun_pkt_t *self);
+//const char* tnet_stun_message_get_realm(const tnet_stun_pkt_t *self);
+//const char* tnet_stun_message_get_nonce(const tnet_stun_pkt_t *self);
+//int32_t tnet_stun_message_get_lifetime(const tnet_stun_pkt_t *self);
+//tsk_bool_t tnet_stun_utils_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2);
+//
+//
+//TINYNET_API tnet_stun_pkt_t* tnet_stun_message_create(const char* username, const char* password);
+//TINYNET_API tnet_stun_pkt_t* tnet_stun_message_create_null();
+//
+//TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_message_def_t;
+//
+//
+//TNET_END_DECLS
+//
+//
+//#endif /* TNET_STUN_MESSAGE_H */
+//
diff --git a/tinyNET/src/stun/tnet_stun_pkt.c b/tinyNET/src/stun/tnet_stun_pkt.c
new file mode 100644
index 0000000..e4d559d
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_pkt.c
@@ -0,0 +1,751 @@
+/* Copyright (C) 2015 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stun/tnet_stun_pkt.h"
+#include "stun/tnet_stun_utils.h"
+
+#include "tnet_endianness.h"
+
+#include "tsk_sha1.h"
+#include "tsk_hmac.h"
+#include "tsk_md5.h"
+#include "tsk_ppfcs32.h"
+#include "tsk_buffer.h"
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#if !defined(PRINT_DESTROYED_MSG)
+# define PRINT_DESTROYED_MSG 0
+#endif
+
+int tnet_stun_pkt_create(tnet_stun_pkt_type_t e_type, uint16_t u_length, const tnet_stun_transac_id_t* pc_transac_id, tnet_stun_pkt_t** pp_attr)
+{
+ extern const tsk_object_def_t *tnet_stun_pkt_def_t;
+ if (!pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!(*pp_attr = tsk_object_new(tnet_stun_pkt_def_t))) {
+ TSK_DEBUG_ERROR("Failed to create STUN pkt object");
+ return -2;
+ }
+ if (!((*pp_attr)->p_list_attrs = tsk_list_create())) {
+ TSK_OBJECT_SAFE_FREE(*pp_attr);
+ return -3;
+ }
+ if (pc_transac_id) {
+ memcpy((*pp_attr)->transac_id, *pc_transac_id, sizeof(tnet_stun_transac_id_t));
+ }
+ else {
+ tnet_stun_utils_transac_id_rand(&(*pp_attr)->transac_id);
+ }
+ (*pp_attr)->e_type = e_type;
+ (*pp_attr)->u_length = u_length;
+ return 0;
+}
+
+int tnet_stun_pkt_attr_add(tnet_stun_pkt_t* p_self, tnet_stun_attr_t** pp_attr)
+{
+ if (!p_self || !pp_attr || !*pp_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ tsk_list_push_back_data(p_self->p_list_attrs, (void**)pp_attr);
+ return 0;
+}
+
+int tnet_stun_pkt_attrs_add(tnet_stun_pkt_t* p_self, ...)
+{
+ va_list ap;
+ int ret = 0;
+ tnet_stun_pkt_attr_add_t e_add_attr;
+ if (!p_self) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ va_start(ap, p_self);
+
+ while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) {
+ switch (e_add_attr) {
+ case tnet_stun_pkt_attr_add_vdata: {
+ // (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE)
+ enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e);
+ const uint8_t* P_DATA_PTR = va_arg(ap, const uint8_t*);
+ uint16_t U_DATA_SIZE = tsk_va_arg_u16(ap);
+ tnet_stun_attr_vdata_t *p_attr;
+ if ((ret = tnet_stun_attr_vdata_create(E_TYPE, P_DATA_PTR, U_DATA_SIZE, &p_attr))) {
+ goto bail;
+ }
+ if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ goto bail;
+ }
+ break;
+ }
+ case tnet_stun_pkt_attr_add_address: {
+ // (enum tnet_stun_attr_type_e)(E_TYPE), (enum tnet_stun_address_family_e)(E_FAMILY), (uint16_t)(U_PORT), (const tnet_stun_addr_t*)PC_ADDR_PTR
+ enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e);
+ enum tnet_stun_address_family_e E_FAMILY = va_arg(ap, enum tnet_stun_address_family_e);
+ uint16_t U_PORT = tsk_va_arg_u16(ap);
+ const tnet_stun_addr_t* PC_ADDR_PTR = va_arg(ap, const tnet_stun_addr_t*);
+ tnet_stun_attr_address_t *p_attr;
+ if ((ret = tnet_stun_attr_address_create(E_TYPE, E_FAMILY, U_PORT, PC_ADDR_PTR, &p_attr))) {
+ goto bail;
+ }
+ if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ goto bail;
+ }
+ break;
+ }
+ case tnet_stun_pkt_attr_add_error_code: {
+ // (uint8_t)(U8_CLASS), (uint8_t)(U8_NUMBER), (const char*)(PC_REASON_STR)
+ uint8_t U8_CLASS = tsk_va_arg_u8(ap);
+ uint8_t U8_NUMBER = tsk_va_arg_u8(ap);
+ const char* PC_REASON_STR = va_arg(ap, const char*);
+ tnet_stun_attr_error_code_t *p_attr;
+ if ((ret = tnet_stun_attr_error_code_create(U8_CLASS, U8_NUMBER, PC_REASON_STR, (uint16_t)tsk_strlen(PC_REASON_STR), &p_attr))) {
+ goto bail;
+ }
+ if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ goto bail;
+ }
+ break;
+ }
+ case tnet_stun_pkt_attr_add_unknown_attrs: {
+ // (...)
+ tsk_buffer_t* p_buffer = tsk_buffer_create_null();
+ tnet_stun_attr_vdata_t *p_attr;
+ uint16_t u_16;
+ if (!p_buffer) {
+ TSK_DEBUG_ERROR("Failed to create buffer");
+ ret = -4;
+ goto bail;
+ }
+ while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) {
+ if (e_add_attr != tnet_stun_pkt_attr_add_unknown_attrs_val) {
+ TSK_OBJECT_SAFE_FREE(p_buffer);
+ TSK_DEBUG_ERROR("Arguments corrupted or invalid.");
+ ret = -3;
+ goto bail;
+ }
+ u_16 = tsk_va_arg_u16(ap);
+ tsk_buffer_append(p_buffer, &u_16, 2);
+ }
+ if ((ret = tnet_stun_attr_vdata_create(tnet_stun_attr_type_unknown_attrs, p_buffer->data, (uint16_t)p_buffer->size, &p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_buffer);
+ goto bail;
+ }
+ TSK_OBJECT_SAFE_FREE(p_buffer);
+ if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) {
+ TSK_OBJECT_SAFE_FREE(p_attr);
+ goto bail;
+ }
+ break;
+ }
+ default: {
+ TSK_DEBUG_ERROR("Arguments corrupted or invalid.");
+ ret = -2;
+ goto bail;
+ }
+ }
+ }
+
+bail:
+ va_end(ap);
+ return ret;
+}
+
+int tnet_stun_pkt_attr_remove(struct tnet_stun_pkt_s* p_self, enum tnet_stun_attr_type_e e_type)
+{
+ tsk_list_item_t* pc_item;
+ tnet_stun_attr_t* pc_attr;
+ if (!p_self || !p_self->p_list_attrs) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+again:
+ tsk_list_foreach(pc_item, p_self->p_list_attrs) {
+ if ((pc_attr = (tnet_stun_attr_t*)pc_item->data)) {
+ if (pc_attr->hdr.e_type == e_type) {
+ tsk_list_remove_item(p_self->p_list_attrs, pc_item);
+ goto again;
+ }
+ }
+ }
+ return 0;
+}
+
+int tnet_stun_pkt_attr_find(const tnet_stun_pkt_t* pc_self, tnet_stun_attr_type_t e_type, tsk_size_t u_index, const tnet_stun_attr_t** ppc_attr)
+{
+ const tsk_list_item_t* pc_item;
+ const tnet_stun_attr_t* pc_attr;
+ if (!pc_self || !ppc_attr) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *ppc_attr = tsk_null;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) {
+ if (pc_attr->hdr.e_type == e_type && !u_index--) {
+ *ppc_attr = pc_attr;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+tsk_bool_t tnet_stun_pkt_attr_exists(const tnet_stun_pkt_t* pc_self, tnet_stun_attr_type_t e_type)
+{
+ const tnet_stun_attr_t* pc_attr;
+ int ret = tnet_stun_pkt_attr_find(pc_self, e_type, 0, &pc_attr);
+ return (pc_attr && (ret == 0));
+}
+
+int tnet_stun_pkt_get_size_in_octetunits_without_padding(const tnet_stun_pkt_t* pc_self, tsk_size_t* p_size)
+{
+ const tsk_list_item_t* pc_item;
+ const tnet_stun_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *p_size = kStunPktHdrSizeInOctets;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) {
+ if ((ret = tnet_stun_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) {
+ return ret;
+ }
+ *p_size += n_size;
+ }
+ }
+ if (pc_self->opt.fingerprint) {
+ *p_size += kStunAttrHdrSizeInOctets + 4;
+ }
+ if (pc_self->opt.dontfrag) {
+ *p_size += kStunAttrHdrSizeInOctets;
+ }
+ return 0;
+}
+
+int tnet_stun_pkt_get_size_in_octetunits_with_padding(const tnet_stun_pkt_t* pc_self, tsk_size_t* p_size)
+{
+ const tsk_list_item_t* pc_item;
+ const tnet_stun_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ if (!pc_self || !p_size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *p_size = kStunPktHdrSizeInOctets;
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) {
+ if ((ret = tnet_stun_attr_get_size_in_octetunits_with_padding(pc_attr, &n_size))) {
+ return ret;
+ }
+ *p_size += n_size;
+ }
+ }
+ if (pc_self->opt.fingerprint) {
+ *p_size += kStunAttrHdrSizeInOctets + 4;
+ }
+ if (pc_self->opt.dontfrag) {
+ *p_size += kStunAttrHdrSizeInOctets;
+ }
+ return 0;
+}
+
+int tnet_stun_pkt_write_with_padding(const tnet_stun_pkt_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written)
+{
+ const tsk_list_item_t* pc_item;
+ const tnet_stun_attr_t* pc_attr;
+ tsk_size_t n_size;
+ int ret;
+ uint8_t *_p_buff_ptr = p_buff_ptr, *_p_msg_int_start;
+ if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, p_written))) {
+ return ret;
+ }
+ if ((n_buff_size < *p_written)) {
+ TSK_DEBUG_ERROR("Buffer too short: %u<%u", (unsigned)n_buff_size, (unsigned)*p_written);
+ return -1;
+ }
+
+ // write header
+ *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->e_type);
+ *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(kStunMagicCookie);
+ memcpy(&p_buff_ptr[8], pc_self->transac_id, sizeof(pc_self->transac_id));
+
+ p_buff_ptr += kStunPktHdrSizeInOctets;
+ n_buff_size -= kStunPktHdrSizeInOctets;
+
+ // write attributes
+ tsk_list_foreach(pc_item, pc_self->p_list_attrs) {
+ if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) {
+ if ((pc_attr->hdr.e_type == tnet_stun_attr_type_message_integrity)) {
+ continue; // because 'MESSAGE-INTEGRITY' must be the latest attribute
+ }
+ if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) {
+ return ret;
+ }
+ p_buff_ptr += n_size;
+ n_buff_size -= n_size;
+ }
+ }
+
+ // DONT-FRAGMENT
+ if (pc_self->opt.dontfrag && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_dont_fragment, &pc_attr) == 0 && !pc_attr) {
+ *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_dont_fragment); // Type
+ *((uint16_t*)&p_buff_ptr[2]) = 0; // Length
+ p_buff_ptr += 4;
+ }
+
+ // MESSAGE-INTEGRITY
+ if (!tsk_strnullORempty(pc_self->p_pwd) && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_message_integrity, &pc_attr) == 0 && pc_attr) {
+ /* RFC 5389 - 15.4. MESSAGE-INTEGRITY
+ The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
+
+ For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
+ For short-term credentials ==> key = SASLprep(password)
+ */
+
+ tsk_sha1digest_t hmac;
+ const tnet_stun_attr_vdata_t *pc_attr_username = tsk_null, *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null;
+ static const uint16_t kMsgIntTotalLength = kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE;
+ _p_msg_int_start = p_buff_ptr;
+
+ // write attribute
+ if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) {
+ return ret;
+ }
+ p_buff_ptr += n_size;
+ n_buff_size -= n_size;
+
+ // Length (must be correct before computing message integrity)
+ *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets));
+
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_username, (const tnet_stun_attr_t**)&pc_attr_username))) {
+ return ret;
+ }
+ if (pc_attr_username) {
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm))) {
+ return ret;
+ }
+ if (pc_attr_realm) {
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce))) {
+ return ret;
+ }
+ }
+ }
+ if (pc_attr_username && pc_attr_realm && pc_attr_nonce) {
+ // LONG-TERM
+ char* p_keystr = tsk_null;
+ tsk_md5digest_t md5;
+ tsk_sprintf(&p_keystr, "%s:%s:%s", pc_attr_username->p_data_ptr, pc_attr_realm->p_data_ptr, pc_self->p_pwd);
+ TSK_MD5_DIGEST_CALC(p_keystr, (tsk_size_t)tsk_strlen(p_keystr), md5);
+ hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
+ TSK_FREE(p_keystr);
+ }
+ else {
+ // SHORT-TERM
+ hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), pc_self->p_pwd, (tsk_size_t)tsk_strlen(pc_self->p_pwd), hmac);
+ }
+
+ // update MESSAGE-INTEGRITY attribute value
+ if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, hmac, TSK_SHA1_DIGEST_SIZE))) {
+ return ret;
+ }
+ if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, _p_msg_int_start, kMsgIntTotalLength, &n_size))) {
+ return ret;
+ }
+ }
+
+ // Length before computing FINGERPRINT
+ *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets + ((pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) ? 8 : 0)));
+
+ if (pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) {
+ /* RFC 5389 - 15.5. FINGERPRINT
+ The FINGERPRINT attribute MAY be present in all STUN messages. The
+ value of the attribute is computed as the CRC-32 of the STUN message
+ up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
+ the 32-bit value 0x5354554e
+ */
+ uint32_t u_fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, _p_buff_ptr, (int32_t)(p_buff_ptr - _p_buff_ptr)) ^ kStunFingerprintXorConst;
+ *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_fingerprint); // Type
+ *((uint16_t*)&p_buff_ptr[2]) = tnet_htons(4); // Length
+ *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(u_fingerprint);
+ p_buff_ptr += 8;
+ }
+
+ *p_written = (tsk_size_t)(p_buff_ptr - _p_buff_ptr);
+ return 0;
+}
+
+int tnet_stun_pkt_write_with_padding_2(const struct tnet_stun_pkt_s* pc_self, struct tsk_buffer_s** pp_buff)
+{
+ tsk_size_t u_buff_size;
+ int ret;
+ if (!pc_self || !pp_buff) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pp_buff = tsk_null;
+ if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, &u_buff_size))) {
+ goto bail;
+ }
+ u_buff_size += kStunBuffMinPad;
+ if (!(*pp_buff = tsk_buffer_create(tsk_null, u_buff_size))) {
+ goto bail;
+ }
+ if ((ret = tnet_stun_pkt_write_with_padding(pc_self, (*pp_buff)->data, (*pp_buff)->size, &(*pp_buff)->size))) {
+ goto bail;
+ }
+bail:
+ if (ret) {
+ TSK_OBJECT_SAFE_FREE(*pp_buff);
+ }
+ return ret;
+}
+
+int tnet_stun_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete)
+{
+ if (!pb_is_complete) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pb_is_complete = tsk_false;
+ if (pc_buff_ptr && n_buff_size >= kStunPktHdrSizeInOctets) {
+ tsk_size_t n_paylen_in_octets = tnet_ntohs_2(&pc_buff_ptr[2]);
+ *pb_is_complete = ((n_buff_size - kStunPktHdrSizeInOctets) >= n_paylen_in_octets);
+ }
+ return 0;
+}
+
+int tnet_stun_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tnet_stun_pkt_t** pp_pkt)
+{
+ tsk_bool_t b_is_complete;
+ uint16_t PayloadLengthInOctets;
+ tnet_stun_pkt_type_t Type;
+ tnet_stun_transac_id_t transac_id;
+ uint32_t MagicCookie;
+ int ret;
+
+ if (!pc_buff_ptr || !n_buff_size || !pp_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (!TNET_STUN_BUFF_IS_STUN2(pc_buff_ptr, n_buff_size)) {
+ TSK_DEBUG_ERROR("Buffer doesn't contain a valid STUN2 pkt");
+ return -2;
+ }
+ if ((ret = tnet_stun_pkt_is_complete(pc_buff_ptr, n_buff_size, &b_is_complete))) {
+ return ret;
+ }
+ if (!b_is_complete) {
+ TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size);
+ return -3;
+ }
+
+ // read the header
+ Type = tnet_ntohs_2(&pc_buff_ptr[0]);
+ PayloadLengthInOctets = tnet_ntohs_2(&pc_buff_ptr[2]);
+ MagicCookie = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]);
+ if (MagicCookie != kStunMagicCookieLong) {
+ TSK_DEBUG_ERROR("%x not a valid STUN2 magic cookie", MagicCookie);
+ return -4;
+ }
+ memcpy(transac_id, &pc_buff_ptr[8], sizeof(tnet_stun_transac_id_t));
+ // create the pkt
+ if ((ret = tnet_stun_pkt_create(Type, PayloadLengthInOctets, (const tnet_stun_transac_id_t*)&transac_id, pp_pkt))) {
+ return ret;
+ }
+
+ if (PayloadLengthInOctets > 0) {
+ tnet_stun_attr_t* p_attr;
+ tsk_size_t n_consumed_octets;
+ pc_buff_ptr += kStunPktHdrSizeInOctets;
+ do {
+ if ((ret = tnet_stun_attr_read((const tnet_stun_transac_id_t*)&(*pp_pkt)->transac_id, pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) {
+ return ret;
+ }
+ if ((ret = tnet_stun_pkt_attr_add((*pp_pkt), &p_attr))) {
+ TSK_OBJECT_SAFE_FREE((*pp_pkt));
+ return ret;
+ }
+ PayloadLengthInOctets -= (uint16_t)n_consumed_octets;
+ pc_buff_ptr += n_consumed_octets;
+ } while (PayloadLengthInOctets >= kStunAttrHdrSizeInOctets);
+ }
+
+ return 0;
+}
+
+int tnet_stun_pkt_auth_prepare(tnet_stun_pkt_t* p_self, const char* pc_usr_name, const char* pc_pwd, const char* pc_realm, const char* pc_nonce)
+{
+ const tnet_stun_attr_t* pc_attr;
+ int ret;
+ static const tsk_sha1digest_t __pc_sha1digestEmpty = { 0 };
+ static const uint16_t __u_sha1digestEmpty = sizeof(__pc_sha1digestEmpty);
+ if (!p_self /*|| !pc_usr_name*/ || !pc_pwd /*|| !pc_realm || !pc_nonce*/) { // "username", "realm" and "nonce" are null for short-term authentication
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ // USERNAME
+ if (pc_usr_name) { // LONG-TERM, optional for SHORT-TERM
+ if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_username, &pc_attr))) {
+ goto bail;
+ }
+ if (pc_attr) {
+ if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_usr_name, (uint16_t)tsk_strlen(pc_usr_name)))) {
+ goto bail;
+ }
+ }
+ else {
+ ret = tnet_stun_pkt_attrs_add(p_self,
+ TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(pc_usr_name),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ }
+ }
+ // REALM
+ if (pc_realm) { // LONG-TERM
+ if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_realm, &pc_attr))) {
+ goto bail;
+ }
+ if (pc_attr) {
+ if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_realm, (uint16_t)tsk_strlen(pc_realm)))) {
+ goto bail;
+ }
+ }
+ else {
+ ret = tnet_stun_pkt_attrs_add(p_self,
+ TNET_STUN_PKT_ATTR_ADD_REALM_ZT(pc_realm),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ }
+ }
+ // NONCE
+ if (pc_nonce) { // LONG-TERM
+ if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_nonce, &pc_attr))) {
+ goto bail;
+ }
+ if (pc_attr) {
+ if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_nonce, (uint16_t)tsk_strlen(pc_nonce)))) {
+ goto bail;
+ }
+ }
+ else {
+ ret = tnet_stun_pkt_attrs_add(p_self,
+ TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(pc_nonce),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ }
+ }
+ // MESSAGE-INTEGRITY
+ if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_message_integrity, &pc_attr))) {
+ goto bail;
+ }
+ if (!pc_attr) {
+ ret = tnet_stun_pkt_attrs_add(p_self,
+ TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_sha1digestEmpty, __u_sha1digestEmpty),
+ TNET_STUN_PKT_ATTR_ADD_NULL());
+ if (ret) {
+ goto bail;
+ }
+ }
+
+ // PASSWORD
+ tsk_strupdate(&p_self->p_pwd, pc_pwd);
+
+bail:
+ return ret;
+}
+
+// pc_resp = 401 or 438
+int tnet_stun_pkt_auth_prepare_2(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_resp)
+{
+ const tnet_stun_attr_vdata_t* pc_attr;
+ const char *pc_nonce, *pc_realm;
+ int ret;
+ if (!p_self || !pc_usr_name || !pc_pwd || !pc_resp) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ // NONCE
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr))) {
+ goto bail;
+ }
+ if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) {
+ TSK_DEBUG_ERROR("Invalid NONCE in 401");
+ ret = -3;
+ goto bail;
+ }
+ pc_nonce = (const char*)pc_attr->p_data_ptr;
+ // REALM
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr))) {
+ goto bail;
+ }
+ if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) {
+ TSK_DEBUG_ERROR("Invalid REALM in 401");
+ ret = -3;
+ goto bail;
+ }
+ pc_realm = (const char*)pc_attr->p_data_ptr;
+
+ if ((ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, pc_realm, pc_nonce))) {
+ goto bail;
+ }
+
+ // TRANSACTION-ID
+ if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) {
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+int tnet_stun_pkt_auth_copy(tnet_stun_pkt_t* p_self, const char* pc_usr_name, const char* pc_pwd, const tnet_stun_pkt_t* pc_pkt)
+{
+ const tnet_stun_attr_vdata_t *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null;
+ int ret;
+ tsk_bool_t b_ok;
+ if (!p_self || !pc_pwd || !pc_usr_name || !pc_pkt) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ b_ok =
+ (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm)) == 0 && pc_attr_realm
+ && (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce)) == 0 && pc_attr_nonce;
+
+ if (b_ok && (ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, (const char*)pc_attr_realm->p_data_ptr, (const char*)pc_attr_nonce->p_data_ptr))) {
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+int tnet_stun_pkt_get_errorcode(const struct tnet_stun_pkt_s* pc_self, uint16_t* pu_code)
+{
+ const tnet_stun_attr_error_code_t* pc_attr;
+ int ret;
+ if (!pc_self && !pu_code) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *pu_code = 0;
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr))) {
+ return ret;
+ }
+ if (pc_attr) {
+ *pu_code = (pc_attr->u_class * 100) + pc_attr->u_number;
+ }
+ return 0;
+}
+
+int tnet_stun_pkt_process_err420(struct tnet_stun_pkt_s *p_self, const struct tnet_stun_pkt_s *pc_pkt_resp420)
+{
+ const tnet_stun_attr_vdata_t* pc_attr;
+ uint16_t u16;
+ int ret;
+ tsk_bool_t b_done = tsk_false;
+ if (!p_self || !pc_pkt_resp420) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) {
+ goto bail;
+ }
+ if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) {
+ TSK_DEBUG_ERROR("UNKNOWN-ATTRIBUTES missing in 420");
+ ret = -3;
+ goto bail;
+ }
+ for (u16 = 0; u16 < pc_attr->u_data_size; u16 += 2) {
+ switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) {
+ case tnet_stun_attr_type_dont_fragment: {
+ p_self->opt.dontfrag = 0;
+ b_done = tsk_true;
+ break;
+ }
+ case tnet_stun_attr_type_fingerprint: {
+ p_self->opt.fingerprint = 0;
+ b_done = tsk_true;
+ break;
+ }
+ }
+ }
+
+ if (b_done) {
+ // TRANSACTION-ID
+ if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) {
+ goto bail;
+ }
+ }
+
+bail:
+ return ret;
+}
+
+static tsk_object_t* tnet_stun_pkt_ctor(tsk_object_t * self, va_list * app)
+{
+ tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self;
+ if (p_pkt) {
+ p_pkt->opt.fingerprint = kStunOptFingerPrint;
+ p_pkt->opt.dontfrag = kStunOptDontFragment;
+ }
+ return self;
+}
+static tsk_object_t* tnet_stun_pkt_dtor(tsk_object_t * self)
+{
+ tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self;
+ if (p_pkt) {
+#if PRINT_DESTROYED_MSG
+ TSK_DEBUG_INFO("*** STUN pkt destroyed ***");
+#endif
+ TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs);
+ TSK_FREE(p_pkt->p_pwd);
+ }
+ return self;
+}
+static const tsk_object_def_t tnet_stun_pkt_def_s = {
+ sizeof(tnet_stun_pkt_t),
+ tnet_stun_pkt_ctor,
+ tnet_stun_pkt_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tnet_stun_pkt_def_t = &tnet_stun_pkt_def_s;
diff --git a/tinyNET/src/stun/tnet_stun_pkt.h b/tinyNET/src/stun/tnet_stun_pkt.h
new file mode 100644
index 0000000..da27673
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_pkt.h
@@ -0,0 +1,187 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TNET_STUN_PKT_H
+#define TNET_STUN_PKT_H
+
+#include "tinynet_config.h"
+#include "stun/tnet_stun_attr.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+#include "tsk_buffer.h"
+
+TNET_BEGIN_DECLS
+
+
+/**@ingroup tnet_stun_group
+* @def TNET_STUN_PKT_IS_REQ
+* Checks whether the STUN message is a request or not.
+*/
+/**@ingroup tnet_stun_group
+* @def TNET_STUN_PKT_IS_INDICATION
+* Checks whether the STUN message is an indicaton message or not.
+*/
+/**@ingroup tnet_stun_group
+* @def TNET_STUN_RESP_IS_SUCCESS
+* Checks whether the STUN message is a success response or not.
+*/
+/**@ingroup tnet_stun_group
+* @def TNET_STUN_RESP_IS_ERROR
+* Checks whether the STUN message is an error response or not.
+*/
+#define TNET_STUN_PKT_IS_REQ(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_request))
+#define TNET_STUN_PKT_IS_RESP(p_self) (TNET_STUN_PKT_RESP_IS_SUCCESS((p_self)) || TNET_STUN_PKT_RESP_IS_ERROR((p_self)))
+#define TNET_STUN_PKT_IS_INDICATION(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_indication))
+#define TNET_STUN_PKT_RESP_IS_SUCCESS(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_success))
+#define TNET_STUN_PKT_RESP_IS_ERROR(p_self) ((p_self) && (((p_self)->e_type & 0x0110) == tnet_stun_mask_error))
+
+typedef enum tnet_stun_pkt_attr_add_e {
+ tnet_stun_pkt_attr_add_null = 0,
+ tnet_stun_pkt_attr_add_none = tnet_stun_pkt_attr_add_null,
+ tnet_stun_pkt_attr_add_vdata,
+ tnet_stun_pkt_attr_add_address,
+ tnet_stun_pkt_attr_add_error_code,
+ tnet_stun_pkt_attr_add_unknown_attrs,
+ tnet_stun_pkt_attr_add_unknown_attrs_val,
+}
+tnet_stun_pkt_attr_add_t;
+
+#define TNET_STUN_PKT_ATTR_ADD_NULL() tnet_stun_pkt_attr_add_null
+#define TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, P_DATA_PTR, U_DATA_SIZE) tnet_stun_pkt_attr_add_vdata, (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE)
+#define TNET_STUN_PKT_ATTR_ADD_UINT0(E_TYPE) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, tsk_null, 0)
+#define TNET_STUN_PKT_ATTR_ADD_UINT8(E_TYPE, U8) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U8, 1)
+#define TNET_STUN_PKT_ATTR_ADD_UINT16(E_TYPE, U16) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U16, 2)
+#define TNET_STUN_PKT_ATTR_ADD_UINT32(E_TYPE, U32) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U32, 4)
+#define TNET_STUN_PKT_ATTR_ADD_UINT64(E_TYPE, U64) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, &U64, 8)
+#define TNET_STUN_PKT_ATTR_ADD_STR(E_TYPE, PC_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(E_TYPE, PC_STR, tsk_strlen(PC_STR))
+#define TNET_STUN_PKT_ATTR_ADD_ADDRESS(E_TYPE, E_FAMILY, U_PORT, PC_ADDR_PTR) tnet_stun_pkt_attr_add_address, (enum tnet_stun_attr_type_e)(E_TYPE), (enum tnet_stun_address_family_e)(E_FAMILY), (uint16_t)(U_PORT), (const tnet_stun_addr_t*)PC_ADDR_PTR
+#define TNET_STUN_PKT_ATTR_ADD_ADDRESS_V4(E_TYPE, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS((E_TYPE), tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_ADDRESS_V6(E_TYPE, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS((E_TYPE), tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
+// rfc5389 - 15.1. MAPPED-ADDRESS
+#define TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS(tnet_stun_attr_type_mapped_address, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
+// rfc5389 - 15.2. XOR-MAPPED-ADDRESS
+#define TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS(tnet_stun_attr_type_xor_mapped_address, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
+// rfc5389 - 15.3. USERNAME
+#define TNET_STUN_PKT_ATTR_ADD_USERNAME(PC_USERNAME_STR, U_USERNAME_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_username, (PC_USERNAME_STR), (U_USERNAME_STR))
+#define TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(PC_USERNAME_STR) TNET_STUN_PKT_ATTR_ADD_USERNAME(PC_USERNAME_STR, tsk_strlen(PC_USERNAME_STR))
+// rfc5389 - 15.4. MESSAGE-INTEGRITY
+#define TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(PC_SHA1_STR, U_SHA1_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_message_integrity, (PC_SHA1_STR), (U_SHA1_STR))
+#define TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY_ZT(PC_SHA1_STR) TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(PC_SHA1_STR, tsk_strlen(PC_SHA1_STR))
+// rfc5389 - 15.5. FINGERPRINT
+#define TNET_STUN_PKT_ATTR_ADD_FINGERPRINT(U32_CRC32) TNET_STUN_PKT_ATTR_ADD_UINT32(tnet_stun_attr_type_fingerprint, U32_CRC32)
+// rfc5389 - 15.6. ERROR-CODE
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(U8_CLASS, U8_NUMBER, PC_REASON_STR) tnet_stun_pkt_attr_add_error_code, (uint8_t)(U8_CLASS), (uint8_t)(U8_NUMBER), (const char*)(PC_REASON_STR)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_TRY_ALTERNATE() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassTryAlternate, kStunErrorNumberTryAlternate, kStunErrorPhraseTryAlternate)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_BAD_REQUEST() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassBadRequest, kStunErrorNumberBadRequest, kStunErrorPhraseBadRequest)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNAUTHORIZED() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassUnauthorized, kStunErrorNumberUnauthorized, kStunErrorPhraseUnauthorized)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNKNOWN_ATTRIBUTE() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassUnknownAttribute, kStunErrorNumberUnknownAttribute, kStunErrorPhraseUnknownAttribute)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_STALE_NONCE() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassStaleNonce, kStunErrorNumberStaleNonce, kStunErrorPhraseStaleNonce)
+#define TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_SERVER_ERROR() TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(kStunErrorClassServerError, kStunErrorNumberServerError, kStunErrorPhraseServerError)
+// rfc5389 - 15.7. REALM
+#define TNET_STUN_PKT_ATTR_ADD_REALM(PC_REALM_STR, U_REALM_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_realm, (PC_REALM_STR), (U_REALM_STR))
+#define TNET_STUN_PKT_ATTR_ADD_REALM_ZT(PC_REALM_STR) TNET_STUN_PKT_ATTR_ADD_REALM(PC_REALM_STR, tsk_strlen(PC_REALM_STR))
+// rfc5389 - 15.8. NONCE
+#define TNET_STUN_PKT_ATTR_ADD_NONCE(PC_NONCE_STR, U_NONCE_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_nonce, (PC_NONCE_STR), (U_NONCE_STR))
+#define TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(PC_NONCE_STR) TNET_STUN_PKT_ATTR_ADD_NONCE(PC_NONCE_STR, tsk_strlen(PC_NONCE_STR))
+// rfc5389 - 15.9. UNKNOWN-ATTRIBUTES
+#define TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS(...) tnet_stun_pkt_attr_add_unknown_attrs, ##__VA_ARGS__
+#define TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(U16_VAL) tnet_stun_pkt_attr_add_unknown_attrs_val, (uint16_t)U16_VAL
+// rfc5389 - 15.10. SOFTWARE
+#define TNET_STUN_PKT_ATTR_ADD_SOFTWARE(PC_SOFTWARE_STR, U_SOFTWARE_STR) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_software, (PC_SOFTWARE_STR), (U_SOFTWARE_STR))
+#define TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(PC_SOFTWARE_STR) TNET_STUN_PKT_ATTR_ADD_SOFTWARE(PC_SOFTWARE_STR, tsk_strlen(PC_SOFTWARE_STR))
+// rfc5389 - 15.11. ALTERNATE-SERVER
+#define TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS(tnet_stun_attr_type_alternate_server, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
+
+// rfc5766(TURN) - 14.1. CHANNEL-NUMBER
+#define TNET_STUN_PKT_ATTR_ADD_CHANNEL_NUMBER(U16_CHANNEL_NUMBER) TNET_STUN_PKT_ATTR_ADD_UINT16(tnet_stun_attr_type_channel_number, U16_CHANNEL_NUMBER)
+// rfc5766(TURN) - 14.2. LIFETIME
+#define TNET_STUN_PKT_ATTR_ADD_LIFETIME(U32_LIFETIME) TNET_STUN_PKT_ATTR_ADD_UINT32(tnet_stun_attr_type_lifetime, U32_LIFETIME)
+// rfc5766(TURN) - 14.3. XOR-PEER-ADDRESS
+#define TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_ADDRESS(tnet_stun_attr_type_xor_peer_address, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
+#define TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
+// rfc5766(TURN) - 14.4. DATA
+#define TNET_STUN_PKT_ATTR_ADD_DATA(PC_DATA_PTR, U_DATA_SIZE) TNET_STUN_PKT_ATTR_ADD_VDATA(tnet_stun_attr_type_data, (PC_DATA_PTR), (U_DATA_SIZE))
+// rfc5766(TURN) - 14.7. REQUESTED-TRANSPORT
+#define TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(U8_PROTOCOL) TNET_STUN_PKT_ATTR_ADD_UINT8(tnet_stun_attr_type_requested_transport, U8_PROTOCOL)
+// rfc5766(TURN) - 14.8. DONT-FRAGMENT
+#define TNET_STUN_PKT_ATTR_ADD_DONT_FRAGMENT() TNET_STUN_PKT_ATTR_ADD_UINT0(tnet_stun_attr_type_dont_fragment)
+
+// rfc5245(ICE) - 19.1. New Attributes (PRIORITY)
+#define TNET_STUN_PKT_ATTR_ADD_ICE_PRIORITY(U32_PRIORITY) TNET_STUN_PKT_ATTR_ADD_UINT32(tnet_stun_attr_type_ice_priority, U32_PRIORITY)
+// rfc5245(ICE) - 19.1. New Attributes (USE-CANDIDATE)
+#define TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE() TNET_STUN_PKT_ATTR_ADD_UINT0(tnet_stun_attr_type_ice_use_candidate)
+// rfc5245(ICE) - 19.1. New Attributes (ICE-CONTROLLED)
+#define TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(U64_CONTROLLED) TNET_STUN_PKT_ATTR_ADD_UINT64(tnet_stun_attr_type_ice_controlled, U64_CONTROLLED)
+// rfc5245(ICE) - 19.1. New Attributes (ICE-CONTROLLED)
+#define TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLING(U64_CONTROLLING) TNET_STUN_PKT_ATTR_ADD_UINT64(tnet_stun_attr_type_ice_controlling, U64_CONTROLLING)
+
+// rfc6062 - 6.2. New STUN Attributes (CONNECTION-ID)
+#define TNET_STUN_PKT_ATTR_ADD_CONNECTION_ID(U32_CONNECTION_ID) TNET_STUN_PKT_ATTR_ADD_UINT32(tnet_stun_attr_type_connection_id, U32_CONNECTION_ID)
+
+typedef struct tnet_stun_pkt_s {
+ TSK_DECLARE_OBJECT;
+ enum tnet_stun_pkt_type_e e_type;
+ uint16_t u_length; // 16bits: contain the size, in bytes, of the message not including the 20-byte STUN header
+ tnet_stun_transac_id_t transac_id; // 96bits : always in network byte-order
+ tnet_stun_attrs_L_t* p_list_attrs;
+ struct {
+ unsigned fingerprint:1;
+ unsigned dontfrag:1;
+ } opt;
+ char *p_pwd;
+} tnet_stun_pkt_t;
+#define TNET_STUN_DECLARE_PKT struct tnet_stun_pkt_s __base__
+#define TNET_STUN_PKT(p_self) ((struct tnet_stun_pkt_s*)(p_self))
+typedef tsk_list_t tnet_stun_pkts_L_t;
+typedef tnet_stun_pkt_t tnet_stun_pkt_req_t;
+typedef tnet_stun_pkt_t tnet_stun_pkt_resp_t;
+
+TINYNET_API int tnet_stun_pkt_create(enum tnet_stun_pkt_type_e e_type, uint16_t u_length, const tnet_stun_transac_id_t* pc_transac_id, struct tnet_stun_pkt_s** pp_attr);
+#define tnet_stun_pkt_create_empty(e_type, pp_attr) tnet_stun_pkt_create((e_type), 0, tsk_null, (pp_attr))
+TINYNET_API int tnet_stun_pkt_attr_add(struct tnet_stun_pkt_s* p_self, struct tnet_stun_attr_s** pp_attr);
+TINYNET_API int tnet_stun_pkt_attrs_add(struct tnet_stun_pkt_s* p_self, ...);
+TINYNET_API int tnet_stun_pkt_attr_remove(struct tnet_stun_pkt_s* p_self, enum tnet_stun_attr_type_e e_type);
+TINYNET_API int tnet_stun_pkt_attr_find(const struct tnet_stun_pkt_s* pc_self, enum tnet_stun_attr_type_e e_type, tsk_size_t u_index, const struct tnet_stun_attr_s** ppc_attr);
+#define tnet_stun_pkt_attr_find_first(pc_self, e_type, ppc_attr) tnet_stun_pkt_attr_find((pc_self), (e_type), 0, (ppc_attr))
+TINYNET_API tsk_bool_t tnet_stun_pkt_attr_exists(const struct tnet_stun_pkt_s* pc_self, enum tnet_stun_attr_type_e e_type);
+TINYNET_API int tnet_stun_pkt_get_size_in_octetunits_without_padding(const struct tnet_stun_pkt_s* pc_self, tsk_size_t* p_size);
+TINYNET_API int tnet_stun_pkt_get_size_in_octetunits_with_padding(const struct tnet_stun_pkt_s* pc_self, tsk_size_t* p_size);
+TINYNET_API int tnet_stun_pkt_write_with_padding(const struct tnet_stun_pkt_s* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written);
+TINYNET_API int tnet_stun_pkt_write_with_padding_2(const struct tnet_stun_pkt_s* pc_self, struct tsk_buffer_s** pp_buff);
+TINYNET_API int tnet_stun_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete);
+TINYNET_API int tnet_stun_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, struct tnet_stun_pkt_s** pp_pkt);
+TINYNET_API int tnet_stun_pkt_auth_prepare(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const char* pc_realm, const char* pc_nonce);
+#define tnet_stun_pkt_auth_prepare_longterm(p_self, pc_usr_name, pc_pwd, pc_realm, pc_nonce) tnet_stun_pkt_auth_prepare((p_self), (pc_usr_name), (pc_pwd), (pc_realm), (pc_nonce))
+#define tnet_stun_pkt_auth_prepare_shortterm(p_self, pc_usr_name, pc_pwd) tnet_stun_pkt_auth_prepare((p_self), (pc_usr_name), (pc_pwd), tsk_null, tsk_null)
+#define tnet_stun_pkt_auth_prepare_shortterm_2(p_self, pc_pwd) tnet_stun_pkt_auth_prepare_shortterm((p_self), tsk_null, (pc_pwd))
+TINYNET_API int tnet_stun_pkt_auth_prepare_2(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_resp);
+TINYNET_API int tnet_stun_pkt_auth_copy(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_pkt);
+TINYNET_API int tnet_stun_pkt_get_errorcode(const struct tnet_stun_pkt_s* pc_self, uint16_t* pu_code);
+TINYNET_API int tnet_stun_pkt_process_err420(struct tnet_stun_pkt_s *p_self, const struct tnet_stun_pkt_s *pc_pkt_resp420);
+
+TNET_END_DECLS
+
+#endif /* TNET_STUN_PKT_H */
diff --git a/tinyNET/src/stun/tnet_stun_types.h b/tinyNET/src/stun/tnet_stun_types.h
new file mode 100644
index 0000000..386f471
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_types.h
@@ -0,0 +1,373 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TNET_STUN_TYPES_H
+#define TNET_STUN_TYPES_H
+
+#include "tinynet_config.h"
+
+TNET_BEGIN_DECLS
+
+typedef uint8_t tnet_stun_addr_t[16]; // IPv4(32bits) or IPv6(128bits)
+typedef uint64_t tnet_stun_binding_id_t;
+typedef long tnet_turn_peer_id_t;
+
+/**@ingroup tnet_stun_group
+ * Checks if the pointer to the buffer hold a STUN header by checking that it starts with 0b00 and contain the magic cookie.
+ * As per RFC 5389 subclause 19: Explicitly point out that the most significant 2 bits of STUN are
+ * 0b00, allowing easy differentiation with RTP packets when used with ICE.
+ * As per RFC 5389 subclause 6: The magic cookie field MUST contain the fixed value 0x2112A442 in
+ * network byte order.
+ *
+ * @param PU8 The pointer to the buffer holding the STUN raw data.
+**/
+#define TNET_STUN_BUFF_IS_STUN2(PU8, SIZE) \
+ ( \
+ ((PU8)) && \
+ ((SIZE) >= kStunPktHdrSizeInOctets) && \
+ (((PU8)[0] & 0xc0) == 0x00) && \
+ ( PU8[4] == 0x21 && PU8[5] == 0x12 && PU8[6] == 0xA4 && PU8[7] == 0x42 ) \
+ )
+
+// rfc5766 - 11. Channels
+#define TNET_STUN_BUFF_IS_CHANNEL_DATA(PU8, SIZE) \
+ ( \
+ ((PU8)) && \
+ ((SIZE) >= kStunChannelDataHdrSizeInOctets) && \
+ (((PU8)[0] & 0xc0) == 0x40) \
+ )
+
+#define kStunOptFingerPrint 1
+#define kStunOptDontFragment 1
+
+#define kStunErrCodeUnauthorized 401
+#define kStunErrCodeUnknownAttributes 420
+#define kStunErrCodeStaleNonce 438
+#define kStunErrCodeIceConflict 487
+
+// Estimate of the round-trip time (RTT) in millisecond.
+#define kStunRTO 500
+
+// Number of retransmission for UDP retransmission in millisecond.
+// 7.2.1. Sending over UDP
+// Rc SHOULD be configurable and SHOULD have a default of 7.
+#define kStunRC /*7*/4/* 7 is too hight */
+
+#define kStunBindingInvalidId 0
+
+#if !defined(kStunBuffMinPad)
+# define kStunBuffMinPad 40 // to make the buffer kasher
+#endif /* kStunBuffMinPad */
+
+#if !defined(kStunSoftware)
+# define kStunSoftware TNET_SOFTWARE
+#endif /* kStunSoftware */
+
+#if !defined(kStunPortDefaultTcpUdp)
+# define kStunPortDefaultTcpUdp 3478
+#endif /* kStunPortDefaultTcpUdp */
+
+#if !defined(kStunPortDefaultTls)
+# define kStunPortDefaultTls 5349
+#endif /* kStunPortDefaultTls */
+
+// rfc5389 - 15. STUN Attributes
+#if !defined(kStunAttrHdrSizeInOctets)
+# define kStunAttrHdrSizeInOctets 4
+#endif /* kStunAttrHdrSizeInOctets */
+
+// rfc5389 - 6. STUN Message Structure
+#if !defined(kStunPktHdrSizeInOctets)
+# define kStunPktHdrSizeInOctets 20
+#endif /* kStunPktHdrSizeInOctets */
+
+// STUN2 magic cookie value in network byte order as per RFC 5389 subclause 6.
+#if !defined(kStunMagicCookieLong)
+# define kStunMagicCookieLong 0x2112A442
+#endif /* kStunMagicCookieLong */
+#if !defined(kStunMagicCookie)
+# define kStunMagicCookie kStunMagicCookieLong
+#endif /* kStunMagicCookie */
+#if !defined(kStunMagicCookieShort)
+# define kStunMagicCookieShort 0x2112
+#endif /* kStunMagicCookieShort */
+
+#if !defined (kStunFingerprintXorConst)
+# define kStunFingerprintXorConst 0x5354554e
+#endif /* kStunFingerprintXorConst */
+
+// STUN trasactionn ID size (96bits = 12bytes)
+#if !defined(kStunTransacIdSize)
+# define kStunTransacIdSize 12
+#endif
+typedef uint8_t tnet_stun_transac_id_t[kStunTransacIdSize];
+
+/**@ingroup tnet_stun_group
+ * List of all supported STUN classes as per RFC 5389 subcaluse 6.
+**/
+typedef enum tnet_stun_class_e {
+ tnet_stun_class_request = 0x00, /**< Request class: 0b00 */
+ tnet_stun_class_indication = 0x01, /**< Indication class: 0b01 */
+ tnet_stun_class_success_response = 0x02, /**< Success response class: 0b10 */
+ tnet_stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
+}
+tnet_stun_class_t;
+
+/**@ingroup tnet_stun_group
+ * List of all supported STUN methods.
+ * RFC 5389 defines only one method(Bining). All other methods have been defined by TURN (rfc5766 section 13).
+**/
+typedef enum tnet_stun_method_e {
+ tnet_stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
+
+ tnet_stun_method_allocate = 0x0003, /**< rfc5766 - Allocate (only request/response semantics defined) */
+ tnet_stun_method_refresh = 0x0004, /**< rfc5766 - Refresh (only request/response semantics defined) */
+ tnet_stun_method_send = 0x0006, /**< rfc5766 - Send (only indication semantics defined) */
+ tnet_stun_method_data = 0x0007, /**< rfc5766 - Data (only indication semantics defined) */
+ tnet_stun_method_createpermission = 0x0008, /**< rfc5766 - CreatePermission (only request/response semantics defined */
+ tnet_stun_method_channelbind = 0x0009, /**< rfc5766 - ChannelBind (only request/response semantics defined) */
+ tnet_stun_method_connect = 0x000a,/**< rfc6062 - Connect */
+ tnet_stun_method_connectionbind = 0x000b,/**< rfc6062 - ConnectionBind */
+ tnet_stun_method_connectionattempt = 0x000c,/**< rfc6062 - ConnectionAttempt */
+}
+tnet_stun_method_t;
+
+/**@ingroup tnet_stun_group
+*/
+typedef enum tnet_stun_mask_e {
+ tnet_stun_mask_request = 0x0000,
+ tnet_stun_mask_indication = 0x0010,
+ tnet_stun_mask_success = 0x0100,
+ tnet_stun_mask_error = 0x0110
+}
+tnet_stun_mask_t;
+
+/**@ingroup tnet_stun_group
+ * STUN IP family as per RFC 5389 subclause 15.1.
+**/
+typedef enum tnet_stun_address_family_e {
+ tnet_stun_address_family_ipv4 = 0x01,
+ tnet_stun_address_family_ipv6 = 0x02
+} tnet_stun_address_family_t;
+
+// rfc5766 - 14.7. REQUESTED-TRANSPORT
+typedef enum tnet_turn_transport_e {
+ tnet_turn_transport_udp = 17,
+ tnet_turn_transport_tcp = 6
+}
+tnet_turn_transport_t;
+
+// RFC 5389 - 15.6. ERROR-CODE
+#define kStunErrorClassTryAlternate 3
+#define kStunErrorNumberTryAlternate 0
+#define kStunErrorPhraseTryAlternate "Try Alternate"
+#define kStunErrorClassBadRequest 4
+#define kStunErrorNumberBadRequest 0
+#define kStunErrorPhraseBadRequest "Bad Request"
+#define kStunErrorClassUnauthorized 4
+#define kStunErrorNumberUnauthorized 1
+#define kStunErrorPhraseUnauthorized "Unauthorized"
+#define kStunErrorClassUnknownAttribute 4
+#define kStunErrorNumberUnknownAttribute 20
+#define kStunErrorPhraseUnknownAttribute "Unknown Attribute"
+#define kStunErrorClassStaleNonce 4
+#define kStunErrorNumberStaleNonce 38
+#define kStunErrorPhraseStaleNonce "Stale Nonce"
+#define kStunErrorClassServerError 5
+#define kStunErrorNumberServerError 0
+#define kStunErrorPhraseServerError "Server Error"
+// rfc5766 - 15. New STUN Error Response Codes
+#define kStunErrorClassForbidden 4
+#define kStunErrorNumberForbidden 3
+#define kStunErrorPhraseForbidden "Forbidden"
+#define kStunErrorClassAllocationMismatch 4
+#define kStunErrorNumberAllocationMismatch 37
+#define kStunErrorPhraseAllocationMismatch "Allocation Mismatch"
+#define kStunErrorClassWrongCredentials 4
+#define kStunErrorNumberWrongCredentials 42
+#define kStunErrorPhraseWrongCredentials "Wrong Credentials"
+#define kStunErrorClassUnsupportedTransportProtocol 4
+#define kStunErrorNumberUnsupportedTransportProtocol 42
+#define kStunErrorPhraseUnsupportedTransportProtocol "Unsupported Transport Protocol"
+#define kStunErrorClassAllocationQuotaReached 4
+#define kStunErrorNumberAllocationQuotaReached 86
+#define kStunErrorPhraseAllocationQuotaReached "Allocation Quota Reached"
+#define kStunErrorClassInsufficientCapacity 5
+#define kStunErrorNumberInsufficientCapacity 8
+#define kStunErrorPhraseInsufficientCapacity "Insufficient Capacity"
+
+
+/**@ingroup tnet_stun_group
+ * STUN attr types as per RFC 5389 subclause 18.2.
+**/
+typedef enum tnet_stun_attr_type_e {
+ /* === RFC 5389 - Comprehension-required range (0x0000-0x7FFF) */
+ tnet_stun_attr_type_reserved = 0x0000, /**< (Reserved) */
+ tnet_stun_attr_type_mapped_address = 0x0001, /**< http://tools.ietf.org/html/rfc5389#page-32 */
+ tnet_stun_attr_type_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
+ tnet_stun_attr_type_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
+ tnet_stun_attr_type_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
+ tnet_stun_attr_type_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
+ tnet_stun_attr_type_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
+ tnet_stun_attr_type_password = 0x0007, /**< (Reserved; was PASSWORD) */
+ tnet_stun_attr_type_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
+ tnet_stun_attr_type_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
+ tnet_stun_attr_type_unknown_attrs = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+ tnet_stun_attr_type_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
+ tnet_stun_attr_type_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+ tnet_stun_attr_type_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
+ tnet_stun_attr_type_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
+
+ /* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
+ tnet_stun_attr_type_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
+ tnet_stun_attr_type_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
+ tnet_stun_attr_type_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
+
+ /* === rfc5766 */
+ tnet_stun_attr_type_channel_number = 0x000C, /**< rfc5766 - CHANNEL-NUMBER */
+ tnet_stun_attr_type_lifetime = 0x000D, /**< rfc5766 - LIFETIME */
+ tnet_stun_attr_type_reserved2 = 0x0010, /**< rfc5766 - Reserved (was BANDWIDTH) */
+ tnet_stun_attr_type_xor_peer_address = 0x0012, /**< rfc5766 - XOR-PEER-ADDRESS */
+ tnet_stun_attr_type_data = 0x0013, /**< rfc5766 - DATA */
+ tnet_stun_attr_type_xor_relayed_address = 0x0016, /**< rfc5766 - XOR-RELAYED-ADDRESS */
+ tnet_stun_attr_type_even_port = 0x0018, /**< rfc5766 - EVEN-PORT */
+ tnet_stun_attr_type_requested_transport = 0x0019, /**< rfc5766 - REQUESTED-TRANSPORT */
+ tnet_stun_attr_type_dont_fragment = 0x001A, /**< rfc5766 - DONT-FRAGMENT */
+ tnet_stun_attr_type_reserved3 = 0x0021, /**< rfc5766 - Reserved (was TIMER-VAL) */
+ tnet_stun_attr_type_reservation_token = 0x0022, /**< rfc5766 - RESERVATION-TOKEN */
+
+ /* RFC 5245 */
+ tnet_stun_attr_type_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
+ tnet_stun_attr_type_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
+ tnet_stun_attr_type_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
+ tnet_stun_attr_type_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
+
+ /* rfc6062 */
+ tnet_stun_attr_type_connection_id = 0x002a, /**< 6.2. New STUN Attributes */
+} tnet_stun_attr_type_t;
+
+
+/**@ingroup tnet_stun_group
+* List of all supported STUN message types.
+*/
+typedef enum tnet_stun_pkt_type_e {
+ /* RFC 5389 - 6. STUN Message Structure
+
+ The message type defines the message class (request, success
+ response, failure response, or indication) and the message method
+ (the primary function) of the STUN message. Although there are four
+ message classes, there are only two types of transactions in STUN:
+ request/response transactions (which consist of a request message and
+ a response message) and indication transactions (which consist of a
+ single indication message). Response classes are split into error
+ and success responses to aid in quickly processing the STUN message.
+
+ The message type field is decomposed further into the following
+ structure:
+
+ 0 1
+ 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
+ |M |M |M|M|M|C|M|M|M|C|M|M|M|M|
+ |11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+ +--+--+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ tnet_stun_pkt_type_binding_request = (tnet_stun_method_binding | tnet_stun_mask_request),
+ tnet_stun_pkt_type_binding_indication = (tnet_stun_method_binding | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_binding_success_response = (tnet_stun_method_binding | tnet_stun_mask_success),
+ tnet_stun_pkt_type_binding_error_response = (tnet_stun_method_binding | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_allocate_request = (tnet_stun_method_allocate | tnet_stun_mask_request),
+ tnet_stun_pkt_type_allocate_indication = (tnet_stun_method_allocate | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_allocate_success_response = (tnet_stun_method_allocate | tnet_stun_mask_success),
+ tnet_stun_pkt_type_allocate_error_response = (tnet_stun_method_allocate | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_refresh_request = (tnet_stun_method_refresh | tnet_stun_mask_request),
+ tnet_stun_pkt_type_refresh_indication = (tnet_stun_method_refresh | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_refresh_success_response = (tnet_stun_method_refresh | tnet_stun_mask_success),
+ tnet_stun_pkt_type_refresh_error_response = (tnet_stun_method_refresh | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_send_indication = (tnet_stun_method_send | tnet_stun_mask_indication),
+
+ tnet_stun_pkt_type_data_indication = (tnet_stun_method_data | tnet_stun_mask_indication),
+
+ tnet_stun_pkt_type_createpermission_request = (tnet_stun_method_createpermission | tnet_stun_mask_request),
+ tnet_stun_pkt_type_createpermission_indication = (tnet_stun_method_createpermission | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_createpermission_success_response = (tnet_stun_method_createpermission | tnet_stun_mask_success),
+ tnet_stun_pkt_type_createpermission_error_response = (tnet_stun_method_createpermission | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_channelbind_request = (tnet_stun_method_channelbind | tnet_stun_mask_request),
+ tnet_stun_pkt_type_channelbind_indication = (tnet_stun_method_channelbind | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_channelbind_success_response = (tnet_stun_method_channelbind | tnet_stun_mask_success),
+ tnet_stun_pkt_type_channelbind_error_response = (tnet_stun_method_channelbind | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_connect_request = (tnet_stun_method_connect | tnet_stun_mask_request),
+ tnet_stun_pkt_type_connect_indication = (tnet_stun_method_connect | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_connect_success_response = (tnet_stun_method_connect | tnet_stun_mask_success),
+ tnet_stun_pkt_type_connect_error_response = (tnet_stun_method_connect | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_connectionbind_request = (tnet_stun_method_connectionbind | tnet_stun_mask_request),
+ tnet_stun_pkt_type_connectionbind_indication = (tnet_stun_method_connectionbind | tnet_stun_mask_indication),
+ tnet_stun_pkt_type_connectionbind_success_response = (tnet_stun_method_connectionbind | tnet_stun_mask_success),
+ tnet_stun_pkt_type_connectionbind_error_response = (tnet_stun_method_connectionbind | tnet_stun_mask_error),
+
+ tnet_stun_pkt_type_connectionattempt_indication = (tnet_stun_method_connectionattempt | tnet_stun_mask_indication),
+}
+tnet_stun_pkt_type_t;
+
+/* RFC 5389 - 7.2.1. Sending over UDP
+ A client SHOULD retransmit a STUN request message starting with an
+ interval of RTO ("Retransmission TimeOut"), doubling after each
+ retransmission.
+
+ e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
+ */
+#define kStunUdpRetransmitTimoutMinInMs 500
+#define kStunUdpRetransmitTimoutMaxInMs 31500
+
+// rfc5766 - 2.2. Allocations
+#if !defined(kTurnAllocationTimeOutInSec)
+# define kTurnAllocationTimeOutInSec 600 /* 10min */ // FIXME
+#endif /* kTurnAllocationTimeOutInSec */
+
+// rfc5766 - 2.3. Permissions
+#if !defined(kTurnPermissionTimeOutInSec)
+# define kTurnPermissionTimeOutInSec 300 /* 5min */
+#endif /* kTurnPermissionTimeOutInSec */
+
+// rfc5766 - 2.5. Channels
+#if !defined(kTurnChannelBindingTimeOutInSec)
+# define kTurnChannelBindingTimeOutInSec 600 /* 10min */
+#endif /* kTurnChannelBindingTimeOutInSec */
+
+// rfc5766 - 11.4. The ChannelData Message
+#if !defined(kStunChannelDataHdrSizeInOctets)
+# define kStunChannelDataHdrSizeInOctets 4
+#endif /* kStunChannelDataHdrSizeInOctets */
+
+// Not part of the standard
+typedef enum tnet_stun_state_e {
+ tnet_stun_state_none,
+ tnet_stun_state_trying,
+ tnet_stun_state_ok,
+ tnet_stun_state_nok
+} tnet_stun_state_t;
+
+TNET_END_DECLS
+
+#endif /* TNET_STUN_TYPES_H */
diff --git a/tinyNET/src/stun/tnet_stun_utils.c b/tinyNET/src/stun/tnet_stun_utils.c
new file mode 100644
index 0000000..8e35075
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_utils.c
@@ -0,0 +1,201 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "stun/tnet_stun_utils.h"
+#include "stun/tnet_stun_pkt.h"
+#include "stun/tnet_stun_attr.h"
+
+#include "tnet_utils.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+int tnet_stun_utils_inet_pton(tsk_bool_t b_v6, const char* p_src, tnet_stun_addr_t* p_dst)
+{
+ int ret;
+ if (!p_src || !p_dst) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if ((ret = tnet_inet_pton(b_v6 ? AF_INET6 : AF_INET, p_src, *p_dst) != 1)) { // success == 1
+ TSK_DEBUG_ERROR("tnet_inet_pton() with error code = %d", ret);
+ return -3;
+ }
+ return 0;
+}
+
+int tnet_stun_utils_inet_ntop(tsk_bool_t b_v6, const tnet_stun_addr_t* pc_src, tnet_ip_t* p_dst)
+{
+ if (!pc_src || !p_dst) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if (tnet_inet_ntop(b_v6 ? AF_INET6 : AF_INET, *pc_src, *p_dst, sizeof(*p_dst)) == tsk_null) {
+ TSK_DEBUG_ERROR("tnet_inet_ntop() failed");
+ return -2;
+ }
+ return 0;
+}
+
+int tnet_stun_utils_transac_id_rand(tnet_stun_transac_id_t* p_transac_id)
+{
+ tsk_size_t u;
+ static tsk_size_t __u_size = sizeof(tnet_stun_transac_id_t);
+ static long __l_chan_num = 0;
+
+ tsk_atomic_inc(&__l_chan_num);
+
+ if (!p_transac_id) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ for (u = 0; (u < __u_size) && (u < sizeof(long)); ++u) {
+ *(((uint8_t*)p_transac_id) + u) = (__l_chan_num >> (u << 3)) & 0xFF;
+ }
+ for (u = sizeof(long); u < __u_size; ++u) {
+ *(((uint8_t*)p_transac_id) + u) = rand() % 0xFF;
+ }
+ return 0;
+}
+
+int tnet_stun_utils_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size, const uint8_t* pc_buf2_ptr, tsk_size_t n_buff2_size)
+{
+ int ret;
+ tsk_size_t u;
+ if (!pc_buf1_ptr || !pc_buf2_ptr || (n_buff1_size != n_buff2_size)) {
+ return -1;
+ }
+ for (u = 0; u < n_buff1_size; ++u) {
+ if ((ret = (pc_buf1_ptr[u] - pc_buf2_ptr[u]))) {
+ return ret;
+ }
+ }
+ return 0;
+}
+
+int tnet_stun_utils_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const struct tnet_stun_pkt_s* pc_stun_req, struct sockaddr* p_addr_server, struct tnet_stun_pkt_s** pp_stun_resp)
+{
+ int ret = -1;
+ uint16_t i, rto = RTO;
+ struct timeval tv;
+ fd_set set;
+ void* p_buff_ptr = tsk_null;
+ tsk_size_t u_buff_size;
+
+ if (!pc_stun_req || !p_addr_server || !pp_stun_resp) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ /* RFC 5389 - 7.2.1. Sending over UDP
+ STUN indications are not retransmitted; thus, indication transactions over UDP
+ are not reliable.
+ */
+ *pp_stun_resp = tsk_null;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_stun_req, &u_buff_size))) {
+ goto bail;
+ }
+ u_buff_size += kStunBuffMinPad;
+ if (!(p_buff_ptr = tsk_malloc(u_buff_size))) {
+ goto bail;
+ }
+ if ((ret = tnet_stun_pkt_write_with_padding(pc_stun_req, p_buff_ptr, u_buff_size, &u_buff_size))) {
+ goto bail;
+ }
+
+ /* RFC 5389 - 7.2.1. Sending over UDP
+ A client SHOULD retransmit a STUN request message starting with an
+ interval of RTO ("Retransmission TimeOut"), doubling after each
+ retransmission.
+
+ e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
+ */
+ for (i = 0; i < Rc; i++) {
+ tv.tv_sec += rto/1000;
+ tv.tv_usec += (rto% 1000) * 1000;
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_usec -= 1000000;
+ tv.tv_sec++;
+ }
+
+ FD_ZERO(&set);
+ FD_SET(localFD, &set);
+
+ if ((ret = tnet_sockfd_sendto(localFD, p_addr_server, p_buff_ptr, u_buff_size))) {
+ // do nothing... not an error
+ }
+
+ if ((ret = select(localFD+1, &set, NULL, NULL, &tv)) < 0) {
+ goto bail;
+ }
+ else if (ret == 0) {
+ /* timeout */
+ TSK_DEBUG_INFO("STUN request timedout at %d", i);
+ rto *= 2;
+ continue;
+ }
+ else if (FD_ISSET(localFD, &set)) {
+ /* there is data to read */
+
+ unsigned int len = 0;
+ void* data = 0;
+
+ TSK_DEBUG_INFO("STUN request got response");
+
+ /* Check how how many bytes are pending */
+ if ((ret = tnet_ioctlt(localFD, FIONREAD, &len)) < 0) {
+ goto bail;
+ }
+
+ if(len == 0) {
+ TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
+ continue;
+ }
+
+ /* Receive pending data */
+ data = tsk_malloc(len);
+ if ((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, p_addr_server)) < 0) {
+ TSK_FREE(data);
+
+ TSK_DEBUG_ERROR("Recv STUN dgrams failed with error code:%d", tnet_geterrno());
+ goto bail;
+ }
+
+ /* Parse the incoming response. */
+ ret = tnet_stun_pkt_read(data, (tsk_size_t)ret, pp_stun_resp);
+ TSK_FREE(data);
+ if (*pp_stun_resp) {
+ if (tnet_stun_utils_transac_id_cmp((*pp_stun_resp)->transac_id, pc_stun_req->transac_id) != 0) {
+ /* Not same transaction id */
+ TSK_OBJECT_SAFE_FREE(*pp_stun_resp);
+ continue;
+ }
+ }
+ goto bail;
+ }
+ else {
+ continue;
+ }
+ }
+
+bail:
+ TSK_FREE(p_buff_ptr);
+ return (*pp_stun_resp) ? 0 : -4;
+}
diff --git a/tinyNET/src/stun/tnet_stun_utils.h b/tinyNET/src/stun/tnet_stun_utils.h
new file mode 100644
index 0000000..c2999c7
--- /dev/null
+++ b/tinyNET/src/stun/tnet_stun_utils.h
@@ -0,0 +1,45 @@
+/* Copyright (C) 2014 Mamadou DIOP.
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#ifndef TNET_STUN_UTILS_H
+#define TNET_STUN_UTILS_H
+
+#include "tinynet_config.h"
+#include "stun/tnet_stun_types.h"
+
+#include "tnet_types.h"
+
+struct tnet_stun_pkt_s;
+
+TNET_BEGIN_DECLS
+
+TINYNET_API int tnet_stun_utils_inet_pton(tsk_bool_t b_v6, const char* p_src, tnet_stun_addr_t* p_dst);
+#define tnet_stun_utils_inet_pton_v4(p_src, p_dst) tnet_stun_utils_inet_pton(tsk_false, (p_src), (p_dst))
+#define tnet_stun_utils_inet_pton_v6(p_src, p_dst) tnet_stun_utils_inet_pton(tsk_true, (p_src), (p_dst))
+TINYNET_API int tnet_stun_utils_inet_ntop(tsk_bool_t b_v6, const tnet_stun_addr_t* pc_src, tnet_ip_t* p_dst);
+#define tnet_stun_utils_inet_ntop_v4(pc_src, p_dst) tnet_stun_utils_inet_ntop(tsk_false, (pc_src), (p_dst))
+#define tnet_stun_utils_inet_ntop_v6(pc_src, p_dst) tnet_stun_utils_inet_ntop(tsk_true, (pc_src), (p_dst))
+TINYNET_API int tnet_stun_utils_transac_id_rand(tnet_stun_transac_id_t* p_transac_id);
+TINYNET_API int tnet_stun_utils_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_size, const uint8_t* pc_buf2_ptr, tsk_size_t n_buff2_size);
+#define tnet_stun_utils_transac_id_cmp(pc_tid1, pc_tid2) tnet_stun_utils_buff_cmp((pc_tid1), sizeof(tnet_stun_transac_id_t), (pc_tid2), sizeof(tnet_stun_transac_id_t))
+#define tnet_stun_utils_transac_id_equals(pc_tid1, pc_tid2) (tnet_stun_utils_transac_id_cmp((pc_tid1), (pc_tid2)) == 0)
+int tnet_stun_utils_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const struct tnet_stun_pkt_s* pc_stun_req, struct sockaddr* p_addr_server, struct tnet_stun_pkt_s** pp_stun_resp);
+
+TNET_END_DECLS
+
+#endif /* TNET_STUN_UTILS_H */
OpenPOWER on IntegriCloud