TURN episode #1
This commit is contained in:
parent
f05c0705dd
commit
4a687f2b23
|
@ -126,8 +126,7 @@ tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO,
|
|||
tsk_buffer_t *buffer = tnet_stun_message_serialize(message);
|
||||
tnet_stun_response_t *response = tsk_null;
|
||||
|
||||
if(!buffer)
|
||||
{
|
||||
if(!buffer) {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
@ -256,8 +255,7 @@ int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *
|
|||
In other words, the very first request is sent as if there were no
|
||||
authentication or message integrity applied.
|
||||
*/
|
||||
stun_phase0:
|
||||
{
|
||||
stun_phase0: {
|
||||
if(!(request = tnet_stun_create_request(binding))) {
|
||||
goto bail;
|
||||
}
|
||||
|
@ -431,8 +429,7 @@ static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_binding_def_s =
|
||||
{
|
||||
static const tsk_object_def_t tnet_stun_binding_def_s = {
|
||||
sizeof(tnet_stun_binding_t),
|
||||
tnet_stun_binding_ctor,
|
||||
tnet_stun_binding_dtor,
|
||||
|
|
|
@ -77,8 +77,7 @@ typedef uint64_t tnet_stun_binding_id_t;
|
|||
/**@ingroup tnet_stun_group
|
||||
* STUN2 binding context.
|
||||
**/
|
||||
typedef struct tnet_stun_binding_s
|
||||
{
|
||||
typedef struct tnet_stun_binding_s {
|
||||
TSK_DECLARE_OBJECT;
|
||||
|
||||
//! A unique id to identify this binding.
|
||||
|
|
|
@ -0,0 +1,406 @@
|
|||
/* 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_attr.h"
|
||||
#include "stun/tnet_stun_utils.h"
|
||||
|
||||
#include "tnet_endianness.h"
|
||||
|
||||
#include "tsk_memory.h"
|
||||
#include "tsk_debug.h"
|
||||
|
||||
#define kWithoutPadding tsk_false
|
||||
#define kWithPadding tsk_true
|
||||
|
||||
#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_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)
|
||||
|
||||
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_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_username:
|
||||
case tnet_stun_attr_type_password: {
|
||||
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;
|
||||
}
|
||||
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", n_buff_size, 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_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_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]) = 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]) = 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]) = 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_username:
|
||||
case tnet_stun_attr_type_password: {
|
||||
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) {
|
||||
memcpy(&p_buff_ptr[*p_written], _pc_self->p_data_ptr, _pc_self->u_data_size);
|
||||
*p_written += _pc_self->u_data_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;
|
||||
}
|
||||
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;
|
||||
static const tsk_size_t kNullBuffSize = 0;
|
||||
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)", 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", n_buff_size, 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_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_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, kNullBuffPtr, &p_attr))) {
|
||||
return ret;
|
||||
}
|
||||
if (b_xor) {
|
||||
*((uint32_t*)&p_attr->address[0]) = 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]) = 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]) = 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_username:
|
||||
case tnet_stun_attr_type_password:
|
||||
default: {
|
||||
tnet_stun_attr_vdata_t* p_attr;
|
||||
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))) {
|
||||
ret = -3;
|
||||
goto bail;
|
||||
}
|
||||
memcpy(p_attr->p_data_ptr, pc_data_ptr, u_length);
|
||||
p_attr->u_data_size = u_length;
|
||||
}
|
||||
|
||||
bail:
|
||||
if (ret) {
|
||||
TSK_OBJECT_SAFE_FREE(p_attr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
TSK_DEBUG_INFO("*** STUN Attribute(VDATA) destroyed ***");
|
||||
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) {
|
||||
TSK_DEBUG_INFO("*** STUN Attribute(ADDRESS) destroyed ***");
|
||||
}
|
||||
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;
|
|
@ -0,0 +1,72 @@
|
|||
/* 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, ...) ================ //
|
||||
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);
|
||||
|
||||
|
||||
// ============== ADDRESS ================ //
|
||||
typedef struct tnet_stun_attr_address_s {
|
||||
TNET_STUN_DECLARE_ATTR;
|
||||
enum tnet_stun_address_family 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_family, uint16_t u_port, const tnet_stun_addr_t* pc_addr, struct tnet_stun_attr_address_s** pp_attr);
|
||||
|
||||
TNET_END_DECLS
|
||||
|
||||
#endif /* TNET_STUN_ATTR_H */
|
|
@ -199,8 +199,7 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
uint16_t length = tnet_ntohs_2(&dataPtr[2]);
|
||||
|
||||
/* Check validity */
|
||||
if(!data || size<=4/* Type(2-bytes) plus Length (2-bytes) */)
|
||||
{
|
||||
if(!data || size<=4/* Type(2-bytes) plus Length (2-bytes) */) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -209,33 +208,28 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
/* Attribute Value
|
||||
*/
|
||||
|
||||
switch(type)
|
||||
{
|
||||
switch(type) {
|
||||
/* RFC 5389 - 15.1. MAPPED-ADDRESS */
|
||||
case stun_mapped_address:
|
||||
{
|
||||
case stun_mapped_address: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_mapped_address_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/
|
||||
case stun_xor_mapped_address:
|
||||
{
|
||||
case stun_xor_mapped_address: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_xmapped_address_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.3. USERNAME*/
|
||||
case stun_username:
|
||||
{
|
||||
case stun_username: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_username_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* RFC 5389 - MESSAGE-INTEGRITY*/
|
||||
case stun_message_integrity:
|
||||
{
|
||||
case stun_message_integrity: {
|
||||
if(length == TSK_SHA1_DIGEST_SIZE) {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_integrity_create(dataPtr, length);
|
||||
}
|
||||
|
@ -243,52 +237,45 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
}
|
||||
|
||||
/* RFC 5389 - 15.5. FINGERPRINT*/
|
||||
case stun_fingerprint:
|
||||
{
|
||||
case stun_fingerprint: {
|
||||
uint32_t fingerprint = tnet_htonl_2(dataPtr);
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.6. ERROR-CODE*/
|
||||
case stun_error_code:
|
||||
{
|
||||
case stun_error_code: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_errorcode_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.7. REALM*/
|
||||
case stun_realm:
|
||||
{
|
||||
case stun_realm: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_realm_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.8. NONCE*/
|
||||
case stun_nonce:
|
||||
{
|
||||
case stun_nonce: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_nonce_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES*/
|
||||
case stun_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:
|
||||
{
|
||||
case stun_software: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_software_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.11. ALTERNATE-SERVER */
|
||||
case stun_alternate_server:
|
||||
{
|
||||
case stun_alternate_server: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_altserver_create(dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
@ -304,15 +291,13 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
case stun_requested_transport:
|
||||
case stun_dont_fragment:
|
||||
case stun_reserved3:
|
||||
case stun_reservation_token:
|
||||
{
|
||||
case stun_reservation_token: {
|
||||
attribute = tnet_turn_attribute_deserialize(type, length, dataPtr, length);
|
||||
break;
|
||||
}
|
||||
|
||||
/* RFC 5245 - 19.1. PRIORITY */
|
||||
case stun_ice_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_attribute_t *)tnet_stun_attribute_ice_priority_create(value);
|
||||
|
@ -320,14 +305,12 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
break;
|
||||
}
|
||||
/* RFC 5245 - 19.1. USE_CANDIDATE */
|
||||
case stun_ice_use_candidate:
|
||||
{
|
||||
case stun_ice_use_candidate: {
|
||||
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_ice_use_candidate_create();
|
||||
break;
|
||||
}
|
||||
/* RFC 5245 - 19.1. ICE_CONTROLLED*/
|
||||
case stun_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_attribute_t *)tnet_stun_attribute_ice_controlled_create(value);
|
||||
|
@ -335,8 +318,7 @@ tnet_stun_attribute_t* tnet_stun_attribute_deserialize(const void* data, tsk_siz
|
|||
break;
|
||||
}
|
||||
/* RFC 5245 - 19.1. ICE_CONTROLLING*/
|
||||
case stun_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_attribute_t *)tnet_stun_attribute_ice_controlling_create(value);
|
||||
|
@ -393,8 +375,7 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
|
||||
switch(attribute->type) {
|
||||
/* RFC 5389 - 15.1. MAPPED-ADDRESS */
|
||||
case stun_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;
|
||||
|
@ -415,8 +396,7 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
}
|
||||
|
||||
/* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS*/
|
||||
case stun_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;
|
||||
|
@ -436,8 +416,7 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
}
|
||||
|
||||
/* RFC 5389 - 15.3. USERNAME*/
|
||||
case stun_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;
|
||||
|
@ -445,24 +424,21 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
|
||||
|
||||
/* RFC 5389 - MESSAGE-INTEGRITY*/
|
||||
case stun_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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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;
|
||||
|
@ -474,39 +450,34 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
}
|
||||
|
||||
/* RFC 5389 - 15.7. REALM*/
|
||||
case stun_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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
case stun_unknown_attributes: {
|
||||
TSK_DEBUG_ERROR("NOT IMPLEMENTED");
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* RFC 5389 - 15.10. SOFTWARE */
|
||||
case stun_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:
|
||||
{
|
||||
case stun_alternate_server: {
|
||||
TSK_DEBUG_ERROR("NOT IMPLEMENTED");
|
||||
return -3;
|
||||
}
|
||||
|
@ -521,36 +492,31 @@ int tnet_stun_attribute_serialize(const tnet_stun_attribute_t* attribute, tsk_bu
|
|||
case stun_requested_transport:
|
||||
case stun_dont_fragment:
|
||||
case stun_reserved3:
|
||||
case stun_reservation_token:
|
||||
{
|
||||
case stun_reservation_token: {
|
||||
return tnet_turn_attribute_serialize(attribute, output);
|
||||
}
|
||||
|
||||
|
||||
/* RFC 5245 - 19.1. PRIORITY */
|
||||
case stun_ice_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:
|
||||
{
|
||||
case stun_ice_use_candidate: {
|
||||
// no body
|
||||
return 0;
|
||||
}
|
||||
/* RFC 5245 - 19.1. ICE_CONTROLLED */
|
||||
case stun_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:
|
||||
{
|
||||
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);
|
||||
|
@ -597,8 +563,7 @@ static tsk_object_t* tnet_stun_attribute_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_def_s =
|
||||
{
|
||||
static const tsk_object_def_t tnet_stun_attribute_def_s = {
|
||||
sizeof(tnet_stun_attribute_t),
|
||||
tnet_stun_attribute_ctor,
|
||||
tnet_stun_attribute_dtor,
|
||||
|
@ -659,8 +624,7 @@ static tsk_object_t* tnet_stun_attribute_mapped_addr_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_mapped_addr_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -733,8 +697,7 @@ static tsk_object_t* tnet_stun_attribute_xmapped_addr_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_xmapped_addr_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -770,8 +733,7 @@ static tsk_object_t* tnet_stun_attribute_username_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_username_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -808,8 +770,7 @@ static tsk_object_t* tnet_stun_attribute_integrity_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_integrity_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -841,8 +802,7 @@ static tsk_object_t* tnet_stun_attribute_fingerprint_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_fingerprint_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -886,8 +846,7 @@ static tsk_object_t* tnet_stun_attribute_errorcode_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_errorcode_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -923,8 +882,7 @@ static tsk_object_t* tnet_stun_attribute_realm_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_realm_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -960,8 +918,7 @@ static tsk_object_t* tnet_stun_attribute_nonce_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_nonce_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -995,8 +952,7 @@ static tsk_object_t* tnet_stun_attribute_unknowns_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_unknowns_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1031,8 +987,7 @@ static tsk_object_t* tnet_stun_attribute_software_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_software_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1083,8 +1038,7 @@ static tsk_object_t* tnet_stun_attribute_altserver_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_altserver_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1116,8 +1070,7 @@ static tsk_object_t* tnet_stun_attribute_ice_priority_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_ice_priority_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1147,8 +1100,7 @@ static tsk_object_t* tnet_stun_attribute_ice_use_candidate_dtor(tsk_object_t * s
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_ice_use_candidate_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1180,8 +1132,7 @@ static tsk_object_t* tnet_stun_attribute_ice_controlled_dtor(tsk_object_t * self
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_ice_controlled_def_s =
|
||||
{
|
||||
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,
|
||||
|
@ -1214,8 +1165,7 @@ static tsk_object_t* tnet_stun_attribute_ice_controlling_dtor(tsk_object_t * sel
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_attribute_ice_controlling_def_s =
|
||||
{
|
||||
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,
|
||||
|
|
|
@ -51,8 +51,7 @@ TNET_BEGIN_DECLS
|
|||
/**@ingroup tnet_stun_group
|
||||
* STUN IP family as per RFC 5389 subclause 15.1.
|
||||
**/
|
||||
typedef enum tnet_stun_addr_family_e
|
||||
{
|
||||
typedef enum tnet_stun_addr_family_e {
|
||||
stun_ipv4 = 0x01,
|
||||
stun_ipv6 = 0x02
|
||||
}
|
||||
|
@ -61,8 +60,7 @@ tnet_stun_addr_family_t;
|
|||
/**@ingroup tnet_stun_group
|
||||
* STUN attribute types as per RFC 5389 subclause 18.2.
|
||||
**/
|
||||
typedef enum tnet_stun_attribute_type_e
|
||||
{
|
||||
typedef enum tnet_stun_attribute_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 */
|
||||
|
@ -110,8 +108,7 @@ tnet_stun_attribute_type_t;
|
|||
/**@ingroup tnet_stun_group
|
||||
RFC 5389 - 15. STUN Attributes
|
||||
*/
|
||||
typedef struct tnet_stun_attribute_s
|
||||
{
|
||||
typedef struct tnet_stun_attribute_s {
|
||||
TSK_DECLARE_OBJECT;
|
||||
/*
|
||||
0 1 2 3
|
||||
|
@ -136,8 +133,7 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_def_t;
|
|||
/**@ingroup tnet_stun_group
|
||||
*RFC 5389 - 15.1. MAPPED-ADDRESS
|
||||
*/
|
||||
typedef struct tnet_stun_attribute_mapped_addr_s
|
||||
{
|
||||
typedef struct tnet_stun_attribute_mapped_addr_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
/*
|
||||
|
@ -163,8 +159,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_xmapped_addr_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
/*
|
||||
|
@ -187,8 +182,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_username_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
char* value;
|
||||
|
@ -200,8 +194,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_integrity_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
tsk_sha1digest_t sha1digest;
|
||||
|
@ -213,8 +206,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_fingerprint_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
uint32_t value;
|
||||
|
@ -225,8 +217,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_errorcode_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
/*
|
||||
0 1 2 3
|
||||
|
@ -248,8 +239,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_realm_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
char* value;
|
||||
|
@ -260,8 +250,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_nonce_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
char* value;
|
||||
|
@ -271,8 +260,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_unknowns_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
tsk_buffer_t *value;
|
||||
|
@ -282,8 +270,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_software_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
char *value;
|
||||
|
@ -293,8 +280,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_altserver_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
|
||||
tnet_stun_addr_family_t family;
|
||||
|
@ -306,8 +292,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_ice_priority_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
uint32_t value;
|
||||
}
|
||||
|
@ -316,8 +301,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_ice_use_candidate_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
}
|
||||
tnet_stun_attribute_ice_use_candidate_t;
|
||||
|
@ -325,8 +309,7 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_de
|
|||
|
||||
/**@ingroup tnet_stun_group
|
||||
* RFC 5245 - 19.1. New Attributes */
|
||||
typedef struct tnet_stun_attribute_ice_controlled_s
|
||||
{
|
||||
typedef struct tnet_stun_attribute_ice_controlled_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
uint64_t value;
|
||||
}
|
||||
|
@ -335,8 +318,7 @@ 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
|
||||
{
|
||||
typedef struct tnet_stun_attribute_ice_controlling_s {
|
||||
TNET_STUN_DECLARE_ATTRIBUTE;
|
||||
uint64_t value;
|
||||
}
|
||||
|
|
|
@ -161,8 +161,7 @@ tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self)
|
|||
/*=== Attributes === */
|
||||
{
|
||||
tsk_list_item_t *item;
|
||||
tsk_list_foreach(item, self->attributes)
|
||||
{
|
||||
tsk_list_foreach(item, self->attributes) {
|
||||
attribute = item->data;
|
||||
tnet_stun_attribute_serialize(attribute, output);
|
||||
tnet_stun_attribute_pad(attribute, output);
|
||||
|
@ -177,12 +176,14 @@ tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self)
|
|||
// will be computed again to store the correct value
|
||||
uint16_t length = (output->size) - TNET_STUN_HEADER_SIZE;
|
||||
#if 0
|
||||
if(self->fingerprint)
|
||||
if(self->fingerprint) {
|
||||
length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(compute_integrity)
|
||||
if(compute_integrity) {
|
||||
length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
|
||||
}
|
||||
|
||||
*(((uint16_t*)output->data)+1) = tnet_htons(length);
|
||||
}
|
||||
|
@ -275,8 +276,7 @@ tnet_stun_message_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size
|
|||
|
||||
/* Check message validity
|
||||
*/
|
||||
if((message->length + TNET_STUN_HEADER_SIZE) != size)
|
||||
{
|
||||
if((message->length + TNET_STUN_HEADER_SIZE) != size) {
|
||||
TSK_OBJECT_SAFE_FREE(message);
|
||||
goto bail;
|
||||
}
|
||||
|
@ -458,7 +458,8 @@ static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app)
|
|||
message->fingerprint = 1;
|
||||
message->integrity = 0;
|
||||
|
||||
{ // Create random transaction id
|
||||
{
|
||||
// Create random transaction id
|
||||
int i;
|
||||
for(i = 0; i < sizeof(message->transaction_id)/sizeof(message->transaction_id[0]); ++i) {
|
||||
message->transaction_id[i] = rand();
|
||||
|
@ -483,8 +484,7 @@ static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self)
|
|||
return self;
|
||||
}
|
||||
|
||||
static const tsk_object_def_t tnet_stun_message_def_s =
|
||||
{
|
||||
static const tsk_object_def_t tnet_stun_message_def_s = {
|
||||
sizeof(tnet_stun_message_t),
|
||||
tnet_stun_message_ctor,
|
||||
tnet_stun_message_dtor,
|
||||
|
|
|
@ -95,8 +95,7 @@ typedef uint8_t tnet_stun_transacid_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
|
||||
{
|
||||
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 */
|
||||
|
@ -109,8 +108,7 @@ tnet_stun_class_type_t;
|
|||
* 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
|
||||
{
|
||||
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) */
|
||||
|
@ -125,8 +123,7 @@ tnet_stun_method_type_t;
|
|||
/**@ingroup tnet_stun_group
|
||||
* List of all supported STUN types.
|
||||
*/
|
||||
typedef enum tnet_stun_message_type_e
|
||||
{
|
||||
typedef enum tnet_stun_message_type_e {
|
||||
/* RFC 5389 - 6. STUN Message Structure
|
||||
|
||||
The message type defines the message class (request, success
|
||||
|
@ -184,8 +181,7 @@ tnet_stun_message_type_t;
|
|||
* STUN Message structure as per RFC 5389 subclause 6.
|
||||
* http://tools.ietf.org/html/rfc5389#section-6
|
||||
*/
|
||||
typedef struct tnet_stun_message_s
|
||||
{
|
||||
typedef struct tnet_stun_message_s {
|
||||
TSK_DECLARE_OBJECT;
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
/* 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_pkt.h"
|
||||
#include "stun/tnet_stun_utils.h"
|
||||
|
||||
#include "tnet_endianness.h"
|
||||
|
||||
#include "tsk_memory.h"
|
||||
#include "tsk_debug.h"
|
||||
|
||||
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_add_attr(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_add_attrs(tnet_stun_pkt_t* p_self, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret = 0;
|
||||
tnet_stun_pkt_add_attr_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_add_attr_t)) != tnet_stun_pkt_add_attr_null) {
|
||||
switch (e_add_attr) {
|
||||
case tnet_stun_pkt_add_attr_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 = va_arg(ap, uint16_t);
|
||||
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_add_attr(p_self, (tnet_stun_attr_t**)&p_attr))) {
|
||||
TSK_OBJECT_SAFE_FREE(p_attr);
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tnet_stun_pkt_add_attr_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 = va_arg(ap, uint16_t);
|
||||
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_add_attr(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_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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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", n_buff_size, *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]) = 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 ((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
|
||||
*((uint16_t*)&p_buff_ptr[2-*p_written]) = tnet_htons(*p_written - kStunPktHdrSizeInOctets);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
tsk_size_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_PKT_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)", 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 = tnet_ntohl_2(&pc_buff_ptr[4]);
|
||||
if (MagicCookie != kStunMagicCookieLong) {
|
||||
TSK_DEBUG_ERROR("%x not a valid STUN2 magic cookie");
|
||||
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, &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(&(*pp_pkt)->transac_id, pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) {
|
||||
return ret;
|
||||
}
|
||||
if ((ret = tnet_stun_pkt_add_attr((*pp_pkt), &p_attr))) {
|
||||
TSK_OBJECT_SAFE_FREE((*pp_pkt));
|
||||
return ret;
|
||||
}
|
||||
PayloadLengthInOctets -= n_consumed_octets;
|
||||
pc_buff_ptr += n_consumed_octets;
|
||||
}
|
||||
while (PayloadLengthInOctets >= kStunAttrHdrSizeInOctets);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
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) {
|
||||
TSK_DEBUG_INFO("*** STUN pkt destroyed ***");
|
||||
TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs);
|
||||
TSK_FREE(p_pkt->auth.p_username);
|
||||
TSK_FREE(p_pkt->auth.p_password);
|
||||
TSK_FREE(p_pkt->auth.p_realm);
|
||||
TSK_FREE(p_pkt->auth.p_nonce);
|
||||
}
|
||||
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;
|
|
@ -0,0 +1,110 @@
|
|||
/* 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"
|
||||
|
||||
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((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_add_attr_e {
|
||||
tnet_stun_pkt_add_attr_null = 0,
|
||||
tnet_stun_pkt_add_attr_none = tnet_stun_pkt_add_attr_null,
|
||||
tnet_stun_pkt_add_attr_vdata,
|
||||
tnet_stun_pkt_add_attr_address
|
||||
}
|
||||
tnet_stun_pkt_add_attr_t;
|
||||
|
||||
#define TNET_STUN_PKT_ADD_ATTR_NULL() tnet_stun_pkt_add_attr_null
|
||||
#define TNET_STUN_PKT_ADD_ATTR_VDATA(E_TYPE, P_DATA_PTR, U_DATA_SIZE) tnet_stun_pkt_add_attr_vdata, (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE)
|
||||
#define TNET_STUN_PKT_ADD_ATTR_ADDRESS(E_TYPE, E_FAMILY, U_PORT, PC_ADDR_PTR) tnet_stun_pkt_add_attr_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_ADD_ATTR_ADDRESS_V4(E_TYPE, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_ADDRESS((E_TYPE), tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
|
||||
#define TNET_STUN_PKT_ADD_ATTR_ADDRESS_V6(E_TYPE, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_ADDRESS((E_TYPE), tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
|
||||
// rfc5389 - 15.1. MAPPED-ADDRESS
|
||||
#define TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_ADDRESS(tnet_stun_attr_type_mapped_address, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
|
||||
#define TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
|
||||
#define TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
|
||||
// rfc5389 - 15.2. XOR-MAPPED-ADDRESS
|
||||
#define TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS(E_FAMILY, U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_ADDRESS(tnet_stun_attr_type_xor_mapped_address, (E_FAMILY), (U_PORT), (PC_ADDR_PTR))
|
||||
#define TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS_V4(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS(tnet_stun_address_family_ipv4, (U_PORT), (PC_ADDR_PTR))
|
||||
#define TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS_V6(U_PORT, PC_ADDR_PTR) TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS(tnet_stun_address_family_ipv6, (U_PORT), (PC_ADDR_PTR))
|
||||
|
||||
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 integrity:1;
|
||||
unsigned dontfrag:1;
|
||||
unsigned nointegrity:1;
|
||||
} opt;
|
||||
struct {
|
||||
char* p_username;
|
||||
char* p_password;
|
||||
char* p_realm;
|
||||
char* p_nonce;
|
||||
} auth;
|
||||
} 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;
|
||||
|
||||
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_add_attr(struct tnet_stun_pkt_s* p_self, struct tnet_stun_attr_s** pp_attr);
|
||||
TINYNET_API int tnet_stun_pkt_add_attrs(struct tnet_stun_pkt_s* p_self, ...);
|
||||
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_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);
|
||||
|
||||
TNET_END_DECLS
|
||||
|
||||
#endif /* TNET_STUN_PKT_H */
|
|
@ -0,0 +1,234 @@
|
|||
/* 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)
|
||||
|
||||
/**@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_PKT_IS_STUN2(PU8, SIZE) \
|
||||
( \
|
||||
((PU8)) && \
|
||||
((SIZE) >= kStunPktHdrSizeInOctets) && \
|
||||
(((PU8)[0] & 0xc0) == 0x00) && \
|
||||
( PU8[4] == 0x21 && PU8[5] == 0x12 && PU8[6] == 0xA4 && PU8[7] == 0x42 ) \
|
||||
)
|
||||
|
||||
#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 /* 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_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;
|
||||
|
||||
/**@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 */
|
||||
} 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_t;
|
||||
|
||||
TNET_END_DECLS
|
||||
|
||||
#endif /* TNET_STUN_TYPES_H */
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 "tnet_utils.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, s = sizeof(*p_transac_id);
|
||||
if (!p_transac_id) {
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
for (u = 0; u < s; ++u) {
|
||||
*(((uint8_t*)p_transac_id) + u) = rand() ^ rand();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* 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"
|
||||
|
||||
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);
|
||||
|
||||
TNET_END_DECLS
|
||||
|
||||
#endif /* TNET_STUN_UTILS_H */
|
|
@ -84,6 +84,10 @@ extern Platform::String^ rt_tsk_str_to_managed(char const* str);
|
|||
# include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
|
||||
#if HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
#endif /* HAVE_ARPA_INET_H */
|
||||
|
||||
#ifndef AF_LINK
|
||||
# define AF_LINK AF_PACKET
|
||||
#endif /* AF_LINK */
|
||||
|
@ -1253,6 +1257,133 @@ int tnet_gethostname(tnet_host_t* result)
|
|||
return gethostname(*result, sizeof(*result));
|
||||
}
|
||||
|
||||
/**@ingroup tnet_utils_group
|
||||
* see http://man7.org/linux/man-pages/man3/inet_pton.3.html
|
||||
* @retval 1 if succeed.
|
||||
*/
|
||||
int tnet_inet_pton(int af, const char* src, void* dst)
|
||||
{
|
||||
if (!src || !dst) {
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
#if HAVE_INET_PTON
|
||||
return inet_pton(af, src, dst);
|
||||
#elif TNET_UNDER_WINDOWS
|
||||
# if (_WIN32_WINNT <= 0x0501)
|
||||
{
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
int addr_len = sizeof(addr);
|
||||
if (WSAStringToAddressA((LPSTR)src, af, NULL, (struct sockaddr *)&addr, &addr_len) == 0) {
|
||||
if (af == AF_INET6) {
|
||||
*((struct in6_addr *)dst) = ((struct sockaddr_in6 *)&addr)->sin6_addr;
|
||||
}
|
||||
else {
|
||||
*((struct in_addr *)dst) = ((struct sockaddr_in *)&addr)->sin_addr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
TNET_PRINT_LAST_ERROR("WSAStringToAddressA failed");
|
||||
return -2;
|
||||
}
|
||||
# else
|
||||
return InetPton(af, src, dst);
|
||||
# endif // TNET_UNDER_WINDOWS
|
||||
#else
|
||||
{
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
int ret;
|
||||
if ((ret = tnet_sockaddr_init(src, 0, (af == AF_INET6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4), &addr))) {
|
||||
return -2;
|
||||
}
|
||||
if (af == AF_INET6) {
|
||||
*((struct in6_addr *)dst) = ((struct sockaddr_in6 *)&addr)->sin6_addr;
|
||||
}
|
||||
else {
|
||||
*((struct in_addr *)dst) = ((struct sockaddr_in *)&addr)->sin_addr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@ingroup tnet_utils_group
|
||||
* see http://pubs.opengroup.org/onlinepubs/009695399/functions/inet_ntop.html
|
||||
*/
|
||||
const char *tnet_inet_ntop(int af, const void *src, char *dst, int size)
|
||||
{
|
||||
if (!src || !dst || size <= 0) {
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return tsk_null;
|
||||
}
|
||||
memset(dst, 0, size);
|
||||
#if HAVE_INET_NTOP
|
||||
return inet_ntop(af, src, dst, size);
|
||||
#elif TNET_UNDER_WINDOWS
|
||||
# if (_WIN32_WINNT <= 0x0501)
|
||||
{
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
int addr_len = sizeof(addr);
|
||||
if (af == AF_INET6) {
|
||||
if (size < INET6_ADDRSTRLEN) {
|
||||
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
|
||||
return tsk_null;
|
||||
}
|
||||
addr.ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&addr)->sin6_addr = *((struct in6_addr *)src);
|
||||
}
|
||||
else {
|
||||
if (size < INET_ADDRSTRLEN) {
|
||||
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
|
||||
return tsk_null;
|
||||
}
|
||||
addr.ss_family = AF_INET;
|
||||
((struct sockaddr_in *)&addr)->sin_addr = *((struct in_addr *)src);
|
||||
}
|
||||
if (WSAAddressToStringA((struct sockaddr*)&addr, addr_len, NULL, dst, &size) == 0) {
|
||||
return dst;
|
||||
}
|
||||
TNET_PRINT_LAST_ERROR("WSAAddressToStringA failed");
|
||||
return tsk_null;
|
||||
}
|
||||
# else
|
||||
return InetNtop(af, src, dst, size);
|
||||
# endif // TNET_UNDER_WINDOWS
|
||||
#else
|
||||
{
|
||||
struct sockaddr_storage addr = { 0 };
|
||||
tnet_ip_t ip;
|
||||
if (af == AF_INET6) {
|
||||
if (size < INET6_ADDRSTRLEN) {
|
||||
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
|
||||
return tsk_null;
|
||||
}
|
||||
addr.ss_family = AF_INET6;
|
||||
((struct sockaddr_in6 *)&addr)->sin6_addr = *((struct in6_addr *)src);
|
||||
|
||||
if (tnet_get_sockip((const struct sockaddr *)&addr, &ip)) {
|
||||
return tsk_null;
|
||||
}
|
||||
memcpy(dst, ip, INET6_ADDRSTRLEN);
|
||||
return dst;
|
||||
}
|
||||
else {
|
||||
if (size < INET_ADDRSTRLEN) {
|
||||
TSK_DEBUG_ERROR("Destination size too short(%d)", size);
|
||||
return tsk_null;
|
||||
}
|
||||
addr.ss_family = AF_INET;
|
||||
((struct sockaddr_in *)&addr)->sin_addr = *((struct in_addr *)src);
|
||||
if (tnet_get_sockip((const struct sockaddr *)&addr, &ip)) {
|
||||
return tsk_null;
|
||||
}
|
||||
memcpy(dst, ip, INET_ADDRSTRLEN);
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**@ingroup tnet_utils_group
|
||||
* Waits until the socket becomes writable/readable or @a timeout milliseconds passed.
|
||||
* This function could be used just after you have @a connect()ed a non-blocking socket.
|
||||
|
|
|
@ -130,6 +130,9 @@ TINYNET_API int tnet_get_fd_opened_count(tsk_size_t* count);
|
|||
TINYNET_API int tnet_getnameinfo(const struct sockaddr *sa, socklen_t salen, char* node, socklen_t nodelen, char* service, socklen_t servicelen, int flags);
|
||||
TINYNET_API int tnet_gethostname(tnet_host_t* result);
|
||||
|
||||
TINYNET_API int tnet_inet_pton(int af, const char* src, void* dst);
|
||||
TINYNET_API const char *tnet_inet_ntop(int af, const void *src, char * dst, int size);
|
||||
|
||||
TINYNET_API int tnet_sockfd_waitUntil(tnet_fd_t fd, long timeout, tsk_bool_t writable);
|
||||
#define tnet_sockfd_waitUntilWritable(fd, timeout) tnet_sockfd_waitUntil(fd, timeout, tsk_true)
|
||||
#define tnet_sockfd_waitUntilReadable(fd, timeout) tnet_sockfd_waitUntil(fd, timeout, tsk_false)
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,21 @@
|
|||
/* 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_TEST_TARGETVER_H
|
||||
#define TNET_TEST_TARGETVER_H
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
@ -21,6 +18,8 @@
|
|||
*/
|
||||
#include "stdafx.h"
|
||||
|
||||
#define BAIL_IF_ERR(expr) { int _ret_; if ((_ret_) = (expr)) { TSK_DEBUG_ERROR("Error %d", (_ret_)); goto bail; } }
|
||||
|
||||
#include "tsk.h"
|
||||
|
||||
#include "tinynet.h"
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
@ -17,6 +14,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with DOUBANGO.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TNET_TEST_ICE_H
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
@ -22,13 +19,45 @@
|
|||
#ifndef TNET_TEST_STUN_H
|
||||
#define TNET_TEST_STUN_H
|
||||
|
||||
#define STUN_SERVER_IP "numb.viagenie.ca"
|
||||
#define STUN_SERVER_PORT TNET_STUN_TCP_UDP_DEFAULT_PORT
|
||||
#define STUN_SERVER_PROTO tnet_socket_type_udp_ipv4
|
||||
#include "stun/tnet_stun_pkt.h"
|
||||
#include "stun/tnet_stun_utils.h"
|
||||
|
||||
#define kStunServerIP "numb.viagenie.ca"
|
||||
#define kStunServerPort kStunPortDefaultTcpUdp
|
||||
#define kStunServerProto tnet_socket_type_udp_ipv4
|
||||
|
||||
#define TNET_TEST_STUN_SEND_BUFF(buff_ptr, buff_size) \
|
||||
{ \
|
||||
struct sockaddr_storage addr_to; \
|
||||
tnet_socket_t* socket = tnet_socket_create(0, 0, kStunServerProto); \
|
||||
tnet_sockaddr_init(kStunServerIP, kStunServerPort, kStunServerProto, &addr_to); \
|
||||
tnet_sockfd_sendto(socket->fd, (const struct sockaddr *)&addr_to, (buff_ptr), (buff_size)); \
|
||||
TSK_OBJECT_SAFE_FREE(socket); \
|
||||
} \
|
||||
|
||||
uint8_t __parse_buff_write_ptr[1200];
|
||||
static const tsk_size_t __parse_buff_write_size = sizeof(__parse_buff_write_ptr)/sizeof(__parse_buff_write_ptr[0]);
|
||||
uint8_t __parse_buff_read_ptr[1200];
|
||||
static const tsk_size_t __parse_buff_read_size = sizeof(__parse_buff_read_ptr)/sizeof(__parse_buff_read_ptr[0]);
|
||||
|
||||
// http://tools.ietf.org/html/draft-ietf-behave-stun-test-vectors-04
|
||||
|
||||
void test_stun_dump_transacid(tnet_stun_transacid_t transcid)
|
||||
static int test_stun_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;
|
||||
}
|
||||
|
||||
static void test_stun_dump_transacid(tnet_stun_transacid_t transcid)
|
||||
{
|
||||
char transac_idstriing[TNET_STUN_TRANSACID_SIZE*2+1];
|
||||
tsk_str_from_hex(transcid, TNET_STUN_TRANSACID_SIZE, transac_idstriing);
|
||||
|
@ -38,8 +67,41 @@ void test_stun_dump_transacid(tnet_stun_transacid_t transcid)
|
|||
TSK_DEBUG_INFO("STUN transac id:%s", transac_idstriing);
|
||||
}
|
||||
|
||||
void test_sun_sendMessage()
|
||||
static void test_sun_parser()
|
||||
{
|
||||
tnet_stun_pkt_t* p_pkt = tsk_null;
|
||||
tsk_size_t n_written_bytes, n_read_bytes;
|
||||
static const char* __pc_mapped_addr_ipv4 = "192.168.0.37";
|
||||
static const char* __pc_mapped_addr_ipv6 = "fdf8:f53b:82e4::53";
|
||||
static const uint16_t __u_mapped_addr_port = 5060;
|
||||
tnet_stun_addr_t addr_ipv4, addr_ipv6;
|
||||
|
||||
(n_read_bytes);
|
||||
|
||||
BAIL_IF_ERR(tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &p_pkt));
|
||||
BAIL_IF_ERR(tnet_stun_utils_inet_pton_v4(__pc_mapped_addr_ipv4, &addr_ipv4));
|
||||
BAIL_IF_ERR(tnet_stun_utils_inet_pton_v6(__pc_mapped_addr_ipv6, &addr_ipv6));
|
||||
BAIL_IF_ERR(tnet_stun_pkt_add_attrs(p_pkt,
|
||||
TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4),
|
||||
TNET_STUN_PKT_ADD_ATTR_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6),
|
||||
TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4),
|
||||
TNET_STUN_PKT_ADD_ATTR_XOR_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6),
|
||||
TNET_STUN_PKT_ADD_ATTR_NULL()));
|
||||
BAIL_IF_ERR(tnet_stun_pkt_write_with_padding(p_pkt, __parse_buff_write_ptr, __parse_buff_write_size, &n_written_bytes));
|
||||
// TNET_TEST_STUN_SEND_BUFF(__parse_buff_write_ptr, n_written_bytes);
|
||||
|
||||
TSK_OBJECT_SAFE_FREE(p_pkt);
|
||||
BAIL_IF_ERR(tnet_stun_pkt_read(__parse_buff_write_ptr, n_written_bytes, &p_pkt));
|
||||
BAIL_IF_ERR(tnet_stun_pkt_write_with_padding(p_pkt, __parse_buff_read_ptr, __parse_buff_read_size, &n_read_bytes));
|
||||
TNET_TEST_STUN_SEND_BUFF(__parse_buff_read_ptr, n_read_bytes);
|
||||
|
||||
BAIL_IF_ERR(test_stun_buff_cmp(__parse_buff_write_ptr, n_written_bytes, __parse_buff_read_ptr, n_read_bytes));
|
||||
TSK_DEBUG_INFO("test_sun_parser...OK");
|
||||
|
||||
bail:
|
||||
TSK_OBJECT_SAFE_FREE(p_pkt);
|
||||
|
||||
#if 0
|
||||
tnet_stun_message_t *message = tsk_null;
|
||||
tsk_buffer_t *buffer = tsk_null;
|
||||
tnet_socket_t *socket = tsk_null;
|
||||
|
@ -70,13 +132,13 @@ void test_sun_sendMessage()
|
|||
}
|
||||
|
||||
// Create blocking socket and bind it
|
||||
socket = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO);
|
||||
socket = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, kStunServerProto);
|
||||
if(!TNET_SOCKET_IS_VALID(socket)){
|
||||
goto bail;
|
||||
}
|
||||
|
||||
// Create stun server's sockaddr structure
|
||||
if(tnet_sockaddr_init(STUN_SERVER_IP, STUN_SERVER_PORT, STUN_SERVER_PROTO, &to)){
|
||||
if(tnet_sockaddr_init(kStunServerIP, kStunServerPort, kStunServerProto, &to)){
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
@ -86,39 +148,12 @@ bail:
|
|||
TSK_OBJECT_SAFE_FREE(message);
|
||||
TSK_OBJECT_SAFE_FREE(socket);
|
||||
TSK_OBJECT_SAFE_FREE(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_stun_context()
|
||||
static void test_stun()
|
||||
{
|
||||
// tnet_socket_t *localSocket = 0;
|
||||
// tnet_stun_context_t *context = 0;
|
||||
//
|
||||
// /* Somewhere in Your application ==> Create and bind your local socket
|
||||
// */
|
||||
// if(!(localSocket = tnet_socket_create_EX(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO, 0)))
|
||||
// {
|
||||
// goto bail;
|
||||
// }
|
||||
//
|
||||
// /* Create your STUN2 context
|
||||
// */
|
||||
// if(!(context = TNET_STUN_CONTEXT_CREATE("myusername", "mypassword", localSocket->fd)))
|
||||
// {
|
||||
// goto bail;
|
||||
// }
|
||||
//
|
||||
// tnet_stun_resolve(context, STUN_SERVER_IP, STUN_SERVER_PORT, STUN_SERVER_PROTO);
|
||||
//
|
||||
//bail:
|
||||
// TNET_OBJECT_SAFE_FREE(localSocket);
|
||||
// TNET_OBJECT_SAFE_FREE(context);
|
||||
}
|
||||
|
||||
void test_stun()
|
||||
{
|
||||
//test_stun_transacid();
|
||||
test_sun_sendMessage();
|
||||
//test_stun_context();
|
||||
test_sun_parser();
|
||||
}
|
||||
|
||||
#endif /* TNET_TEST_STUN_H */
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Mamadou Diop.
|
||||
*
|
||||
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
|
||||
/* Copyright (C) 2014 Mamadou DIOP.
|
||||
*
|
||||
* This file is part of Open Source Doubango Framework.
|
||||
*
|
||||
|
|
|
@ -228,6 +228,10 @@
|
|||
RelativePath=".\src\stun\tnet_stun.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_attr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_attribute.c"
|
||||
>
|
||||
|
@ -236,6 +240,14 @@
|
|||
RelativePath=".\src\stun\tnet_stun_message.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_pkt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_utils.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="turn"
|
||||
|
@ -460,6 +472,10 @@
|
|||
RelativePath=".\src\stun\tnet_stun.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_attr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_attribute.h"
|
||||
>
|
||||
|
@ -468,6 +484,18 @@
|
|||
RelativePath=".\src\stun\tnet_stun_message.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_pkt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_types.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\stun\tnet_stun_utils.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="turn"
|
||||
|
|
Loading…
Reference in New Issue