diff options
Diffstat (limited to 'tinyNET/src/turn/tnet_turn_attribute.c')
-rw-r--r-- | tinyNET/src/turn/tnet_turn_attribute.c | 649 |
1 files changed, 649 insertions, 0 deletions
diff --git a/tinyNET/src/turn/tnet_turn_attribute.c b/tinyNET/src/turn/tnet_turn_attribute.c new file mode 100644 index 0000000..0bc55ad --- /dev/null +++ b/tinyNET/src/turn/tnet_turn_attribute.c @@ -0,0 +1,649 @@ +/* +* Copyright (C) 2009-2010 Mamadou Diop. +* +* Contact: Mamadou Diop <diopmamadou(at)doubango.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_turn_attribute.c + * @brief New STUN Attributes as per draft-ietf-behave-turn-16 subclause 14. + * + * @author Mamadou Diop <diopmamadou(at)doubango.org> + * + * @date Created: Sat Nov 8 16:54:58 2009 mdiop + */ +#include "tnet_turn_attribute.h" + +#include "../stun/tnet_stun.h" + +#include "../tnet_endianness.h" + +#include "tsk_debug.h" + +#include <string.h> + + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER */ +tnet_turn_attribute_channelnum_t* tnet_turn_attribute_channelnum_create(uint16_t number) +{ + return tsk_object_new(tnet_turn_attribute_channelnum_def_t, number); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.2. LIFETIME */ +tnet_turn_attribute_lifetime_t* tnet_turn_attribute_lifetime_create(uint32_t lifetime) +{ + return tsk_object_new(tnet_turn_attribute_lifetime_def_t, lifetime); +} + + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS */ +tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create(const void* payload, tsk_size_t payload_size) +{ + return tsk_object_new(tnet_turn_attribute_xpeer_addr_def_t, payload, payload_size); +} + +tnet_turn_attribute_xpeer_addr_t* tnet_turn_attribute_xpeer_addr_create_null() +{ + return tnet_turn_attribute_xpeer_addr_create(tsk_null, 0); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.4. DATA */ +tnet_turn_attribute_data_t* tnet_turn_attribute_data_create(const void* payload, tsk_size_t payload_size) +{ + return tsk_object_new(tnet_turn_attribute_data_def_t, payload, payload_size); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS */ +tnet_turn_attribute_xrelayed_addr_t* tnet_turn_attribute_xrelayed_addr_create(const void* payload, tsk_size_t payload_size) +{ + return tsk_object_new(tnet_turn_attribute_xrelayed_addr_def_t, payload, payload_size); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.6. EVEN-PORT */ +tnet_turn_attribute_even_port_t* tnet_turn_attribute_even_port_create(unsigned R) +{ + return tsk_object_new(tnet_turn_attribute_even_port_def_t, R); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT */ +tnet_turn_attribute_reqtrans_t* tnet_turn_attribute_reqtrans_create(tnet_proto_t protocol) +{ + return tsk_object_new(tnet_turn_attribute_reqtrans_def_t, protocol); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT */ +tnet_turn_attribute_dontfrag_t* tnet_turn_attribute_dontfrag_create() +{ + return tsk_object_new(tnet_turn_attribute_dontfrag_def_t); +} + +/**@ingroup tnet_turn_group +* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN */ +tnet_turn_attribute_restoken_t* tnet_turn_attribute_restoken_create(const void* payload, tsk_size_t payload_size) +{ + return tsk_object_new(tnet_turn_attribute_restoken_def_t, payload, payload_size); +} + +/**@ingroup tnet_turn_group +*/ +tnet_stun_attribute_t* tnet_turn_attribute_deserialize(tnet_stun_attribute_type_t type, uint16_t length, const void* payload, tsk_size_t payload_size) +{ + tnet_stun_attribute_t *attribute = tsk_null; + const uint8_t* dataPtr = payload; + + /* Attribute Value + */ + + switch(type) + { + /* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER */ + case stun_channel_number: + { + uint32_t number = tnet_htonl_2(dataPtr); + attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_channelnum_create(number); + break; + } + + /* draft-ietf-behave-turn-16 - 14.2. LIFETIME */ + case stun_lifetime: + { + uint32_t lifetime = tnet_htonl_2(dataPtr); + attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_lifetime_create(lifetime); + break; + } + + /* draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS */ + case stun_xor_peer_address: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + /* draft-ietf-behave-turn-16 - 14.4. DATA */ + case stun_data: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + /* draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS */ + case stun_xor_relayed_address: + { + attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_xrelayed_addr_create(dataPtr, length); + break; + } + + /* draft-ietf-behave-turn-16 - 14.6. EVEN-PORT */ + case stun_even_port: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + /* draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT */ + case stun_requested_transport: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + /* draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT */ + case stun_dont_fragment: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + /* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN */ + case stun_reservation_token: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + + default: + { + TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); + break; + } + } + + if(!attribute){ + /* Create default */ + attribute = tnet_stun_attribute_create(); + } + + return attribute; +} + +/**@ingroup tnet_turn_group +*/ +int tnet_turn_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_buffer_t *output) +{ + if(!attribute || !output){ + return -1; + } + + /* Attribute Value + */ + + switch(attribute->type){ + /* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER */ + case stun_channel_number: + { + tnet_turn_attribute_channelnum_t *number = (tnet_turn_attribute_channelnum_t*)attribute; + tsk_buffer_append(output, &(number->number), 2); + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.2. LIFETIME */ + case stun_lifetime: + { + tnet_turn_attribute_lifetime_t *lifetime = (tnet_turn_attribute_lifetime_t*)attribute; + tsk_buffer_append(output, &(lifetime->value), 4); + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS */ + case stun_xor_peer_address: + { + tnet_turn_attribute_xpeer_addr_t* xpeer = (tnet_turn_attribute_xpeer_addr_t*)attribute; + if(xpeer){ + if(xpeer->family == stun_ipv4){ + uint8_t pad = 0x00; + tsk_buffer_append(output, &pad, 1); + tsk_buffer_append(output, &xpeer->family, 1); + tsk_buffer_append(output, &xpeer->xport, 2); + tsk_buffer_append(output, xpeer->xaddress, 4); + } + else + { + TSK_DEBUG_ERROR("SERIALIZE:XOR-PEER-ADDRESS ==> IPV6 - NOT IMPLEMENTED"); + return -3; + } + } + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.4. DATA */ + case stun_data: + { + tnet_turn_attribute_data_t *data = (tnet_turn_attribute_data_t*)attribute; + if(data->value){ + tsk_buffer_append(output, data->value->data, data->value->size); + } + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS */ + case stun_xor_relayed_address: + { + TSK_DEBUG_ERROR("SERIALIZE:XOR-RELAYED-ADDRESS ==> NOT IMPLEMENTED"); + return -3; + } + + /* draft-ietf-behave-turn-16 - 14.6. EVEN-PORT */ + case stun_even_port: + { + tnet_turn_attribute_even_port_t *even_port = (tnet_turn_attribute_even_port_t*)attribute; + uint8_t value = (even_port->R << 7); + tsk_buffer_append(output, &(value), 1); + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT */ + case stun_requested_transport: + { + tnet_turn_attribute_reqtrans_t *reqtrans = (tnet_turn_attribute_reqtrans_t*)attribute; + tsk_buffer_append(output, &(reqtrans->protocol), 1); + tsk_buffer_append(output, &(reqtrans->rffu), 3); + return 0; + } + + /* draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT */ + case stun_dont_fragment: + { + TSK_DEBUG_ERROR("SERIALIZE:DONT-FRAGMENT ==> NOT IMPLEMENTED"); + return -3; + } + + /* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN */ + case stun_reservation_token: + { + TSK_DEBUG_ERROR("SERIALIZE:TOKEN ==> NOT IMPLEMENTED"); + return -3; + } + } + + return 0; +} + + + + + + + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER]] object definition +// +static tsk_object_t* tnet_turn_attribute_channelnum_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_channelnum_t *attribute = self; + if(attribute){ +#if defined (__GNUC__) + attribute->number = (uint16_t)(va_arg(*app, unsigned)); +#else + attribute->number = (va_arg(*app, uint16_t)); +#endif + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_channel_number; + TNET_STUN_ATTRIBUTE(attribute)->length = 2; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_channelnum_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_channelnum_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_channelnum_def_s = +{ + sizeof(tnet_turn_attribute_channelnum_t), + tnet_turn_attribute_channelnum_ctor, + tnet_turn_attribute_channelnum_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_channelnum_def_t = &tnet_turn_attribute_channelnum_def_s; + + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.2. LIFETIME]] object definition +// +static tsk_object_t* tnet_turn_attribute_lifetime_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_lifetime_t *attribute = self; + if(attribute){ + attribute->value = /*tnet_htonl*/(va_arg(*app, uint32_t)); + TNET_STUN_ATTRIBUTE(attribute)->type = stun_lifetime; + TNET_STUN_ATTRIBUTE(attribute)->length = 4; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_lifetime_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_lifetime_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_lifetime_def_s = +{ + sizeof(tnet_turn_attribute_lifetime_t), + tnet_turn_attribute_lifetime_ctor, + tnet_turn_attribute_lifetime_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_lifetime_def_t = &tnet_turn_attribute_lifetime_def_s; + + + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.3. XOR-PEER-ADDRESS]] object definition +// +static tsk_object_t* tnet_turn_attribute_xpeer_addr_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_xpeer_addr_t *attribute = self; + if(attribute){ + const void *payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size){ + } + TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_peer_address; + TNET_STUN_ATTRIBUTE(attribute)->length = 8; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_xpeer_addr_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_xpeer_addr_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_xpeer_addr_def_s = +{ + sizeof(tnet_turn_attribute_xpeer_addr_t), + tnet_turn_attribute_xpeer_addr_ctor, + tnet_turn_attribute_xpeer_addr_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_xpeer_addr_def_t = &tnet_turn_attribute_xpeer_addr_def_s; + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.4. DATA]] object definition +// +static tsk_object_t* tnet_turn_attribute_data_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_data_t *attribute = self; + if(attribute){ + const void *payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size){ + attribute->value = tsk_buffer_create(payload, payload_size); + } + TNET_STUN_ATTRIBUTE(attribute)->type = stun_data; + TNET_STUN_ATTRIBUTE(attribute)->length = (uint16_t)payload_size; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_data_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_data_t *attribute = self; + if(attribute){ + TSK_OBJECT_SAFE_FREE(attribute->value); + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_data_def_s = +{ + sizeof(tnet_turn_attribute_data_t), + tnet_turn_attribute_data_ctor, + tnet_turn_attribute_data_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_data_def_t = &tnet_turn_attribute_data_def_s; + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.5. XOR-RELAYED-ADDRESS]] object definition +// +static tsk_object_t* tnet_turn_attribute_xrelayed_addr_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_xrelayed_addr_t *attribute = self; + if(attribute){ + const void *payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size){ + const uint8_t *payloadPtr = (const uint8_t*)payload; + payloadPtr += 1; /* Ignore first 8bits */ + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_relayed_address; + TNET_STUN_ATTRIBUTE(attribute)->length = payload_size; + + attribute->family = (tnet_stun_addr_family_t)(*(payloadPtr++)); + + attribute->xport = tnet_ntohs_2(payloadPtr); + attribute->xport ^= 0x2112; + payloadPtr+=2; + + { /*=== Compute IP address */ + tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0); + if(addr_size){ + tsk_size_t i; + uint32_t addr; + + for(i=0; i<addr_size; i+=4){ + addr = tnet_htonl_2(payloadPtr); + addr ^= TNET_STUN_MAGIC_COOKIE; + memcpy(&attribute->xaddress[i], &addr, 4); + payloadPtr+=4; + } + } + else{ + TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family); + } + } + } + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_xrelayed_addr_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_xrelayed_addr_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_xrelayed_addr_def_s = +{ + sizeof(tnet_turn_attribute_xrelayed_addr_t), + tnet_turn_attribute_xrelayed_addr_ctor, + tnet_turn_attribute_xrelayed_addr_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_xrelayed_addr_def_t = &tnet_turn_attribute_xrelayed_addr_def_s; + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.6. EVEN-PORT]] object definition +// +static tsk_object_t* tnet_turn_attribute_even_port_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_even_port_t *attribute = self; + if(attribute){ + attribute->R = va_arg(*app, unsigned); + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_even_port; + TNET_STUN_ATTRIBUTE(attribute)->length = 1; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_even_port_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_even_port_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_even_port_def_s = +{ + sizeof(tnet_turn_attribute_even_port_t), + tnet_turn_attribute_even_port_ctor, + tnet_turn_attribute_even_port_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_even_port_def_t = &tnet_turn_attribute_even_port_def_s; + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT]] object definition +// +static tsk_object_t* tnet_turn_attribute_reqtrans_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_reqtrans_t *attribute = self; + if(attribute){ + attribute->protocol = va_arg(*app, tnet_proto_t); + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_requested_transport; + TNET_STUN_ATTRIBUTE(attribute)->length = 4; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_reqtrans_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_reqtrans_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_reqtrans_def_s = +{ + sizeof(tnet_turn_attribute_reqtrans_t), + tnet_turn_attribute_reqtrans_ctor, + tnet_turn_attribute_reqtrans_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_reqtrans_def_t = &tnet_turn_attribute_reqtrans_def_s; + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.8. DONT-FRAGMENT]] object definition +// +static tsk_object_t* tnet_turn_attribute_dontfrag_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_dontfrag_t *attribute = self; + if(attribute){ + //const void *payload = va_arg(*app, const void*); + //tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_dont_fragment; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_dontfrag_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_dontfrag_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_dontfrag_def_s = +{ + sizeof(tnet_turn_attribute_dontfrag_t), + tnet_turn_attribute_dontfrag_ctor, + tnet_turn_attribute_dontfrag_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_dontfrag_def_t = &tnet_turn_attribute_dontfrag_def_s; + + + +//================================================================================================= +// [[draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN]] object definition +// +static tsk_object_t* tnet_turn_attribute_restoken_ctor(tsk_object_t * self, va_list * app) +{ + tnet_turn_attribute_restoken_t *attribute = self; + if(attribute){ + //--const void *payload = va_arg(*app, const void*); + //--tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + TNET_STUN_ATTRIBUTE(attribute)->type = stun_reservation_token; + } + return self; +} + +static tsk_object_t* tnet_turn_attribute_restoken_dtor(tsk_object_t * self) +{ + tnet_turn_attribute_restoken_t *attribute = self; + if(attribute){ + } + return self; +} + +static const tsk_object_def_t tnet_turn_attribute_restoken_def_s = +{ + sizeof(tnet_turn_attribute_restoken_t), + tnet_turn_attribute_restoken_ctor, + tnet_turn_attribute_restoken_dtor, + tsk_null, +}; +const tsk_object_def_t *tnet_turn_attribute_restoken_def_t = &tnet_turn_attribute_restoken_def_s; |