TURN episode #1

This commit is contained in:
bossiel 2014-05-01 05:01:53 +00:00
parent f05c0705dd
commit 4a687f2b23
32 changed files with 4374 additions and 3039 deletions

View File

@ -49,7 +49,7 @@
*/
tnet_stun_binding_t* tnet_stun_binding_create(tnet_fd_t fd, tnet_socket_type_t socket_type, const char* server_address, tnet_port_t server_port, const char* username, const char* password)
{
return tsk_object_new(tnet_stun_binding_def_t, fd, socket_type, server_address, server_port, username, password);
return tsk_object_new(tnet_stun_binding_def_t, fd, socket_type, server_address, server_port, username, password);
}
/**@ingroup tnet_stun_group
@ -62,38 +62,38 @@ tnet_stun_binding_t* tnet_stun_binding_create(tnet_fd_t fd, tnet_socket_type_t s
**/
tnet_stun_message_t *tnet_stun_create_request(const tnet_stun_binding_t* binding)
{
tnet_stun_message_t *message = tnet_stun_message_create(binding->username, binding->password);
tnet_stun_message_t *message = tnet_stun_message_create(binding->username, binding->password);
if(message){
message->realm = tsk_strdup(binding->realm);
message->nonce = tsk_strdup(binding->nonce);
if(message) {
message->realm = tsk_strdup(binding->realm);
message->nonce = tsk_strdup(binding->nonce);
/* Set the request type (RFC 5389 defines only one type) */
message->type = stun_binding_request;
/* Set the request type (RFC 5389 defines only one type) */
message->type = stun_binding_request;
{ /* Create random transaction id */
tsk_istr_t random;
tsk_md5digest_t digest;
{ /* Create random transaction id */
tsk_istr_t random;
tsk_md5digest_t digest;
tsk_strrandom(&random);
TSK_MD5_DIGEST_CALC(random, sizeof(random), digest);
tsk_strrandom(&random);
TSK_MD5_DIGEST_CALC(random, sizeof(random), digest);
memcpy(message->transaction_id, digest, TNET_STUN_TRANSACID_SIZE);
}
memcpy(message->transaction_id, digest, TNET_STUN_TRANSACID_SIZE);
}
/* Add software attribute */
if(binding->software){
tnet_stun_attribute_t* attribute = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(binding->software, tsk_strlen(binding->software));
tnet_stun_message_add_attribute(message, &attribute);
}
}
/* Add software attribute */
if(binding->software) {
tnet_stun_attribute_t* attribute = (tnet_stun_attribute_t*)tnet_stun_attribute_software_create(binding->software, tsk_strlen(binding->software));
tnet_stun_message_add_attribute(message, &attribute);
}
}
return message;
return message;
}
int tnet_stun_send_reliably(const tnet_stun_message_t* message)
{
return -1;
return -1;
}
@ -112,26 +112,25 @@ int tnet_stun_send_reliably(const tnet_stun_message_t* message)
**/
tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO, uint16_t Rc, const tnet_stun_message_t* message, struct sockaddr* server)
{
/* RFC 5389 - 7.2.1. Sending over UDP
STUN indications are not retransmitted; thus, indication transactions over UDP
are not reliable.
*/
//int retransmit = (message->type == stun_binding_request);
/* RFC 5389 - 7.2.1. Sending over UDP
STUN indications are not retransmitted; thus, indication transactions over UDP
are not reliable.
*/
//int retransmit = (message->type == stun_binding_request);
int ret = -1;
uint16_t i, rto = RTO;
struct timeval tv;
fd_set set;
int ret = -1;
uint16_t i, rto = RTO;
struct timeval tv;
fd_set set;
tsk_buffer_t *buffer = tnet_stun_message_serialize(message);
tnet_stun_response_t *response = tsk_null;
tsk_buffer_t *buffer = tnet_stun_message_serialize(message);
tnet_stun_response_t *response = tsk_null;
if(!buffer)
{
goto bail;
}
if(!buffer) {
goto bail;
}
{
{
//#ifndef SIO_UDP_CONNRESET
//# ifndef IOC_VENDOR
//# define IOC_VENDOR 0x18000000
@ -149,86 +148,86 @@ tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO,
// // IOCTL: SIO_UDP_CONNRESET
// status = WSAIoctl(localFD, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
// NULL, 0, &dwBytesReturned, NULL, NULL);
}
}
tv.tv_sec = 0;
tv.tv_usec = 0;
tv.tv_sec = 0;
tv.tv_usec = 0;
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
/* RFC 5389 - 7.2.1. Sending over UDP
A client SHOULD retransmit a STUN request message starting with an
interval of RTO ("Retransmission TimeOut"), doubling after each
retransmission.
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for(i=0; i<Rc; i++){
tv.tv_sec += rto/1000;
tv.tv_usec += (rto% 1000) * 1000;
e.g. 0 ms, 500 ms, 1500 ms, 3500 ms, 7500ms, 15500 ms, and 31500 ms
*/
for(i=0; i<Rc; i++) {
tv.tv_sec += rto/1000;
tv.tv_usec += (rto% 1000) * 1000;
FD_ZERO(&set);
FD_SET(localFD, &set);
FD_ZERO(&set);
FD_SET(localFD, &set);
ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
if((ret = select(localFD+1, &set, NULL, NULL, &tv))<0){
goto bail;
}
else if(ret == 0){
/* timeout */
TSK_DEBUG_INFO("STUN request timedout at %d", i);
rto *= 2;
continue;
}
else if(FD_ISSET(localFD, &set)){
/* there is data to read */
if((ret = select(localFD+1, &set, NULL, NULL, &tv))<0) {
goto bail;
}
else if(ret == 0) {
/* timeout */
TSK_DEBUG_INFO("STUN request timedout at %d", i);
rto *= 2;
continue;
}
else if(FD_ISSET(localFD, &set)) {
/* there is data to read */
tsk_size_t len = 0;
void* data = 0;
tsk_size_t len = 0;
void* data = 0;
TSK_DEBUG_INFO("STUN request got response");
TSK_DEBUG_INFO("STUN request got response");
/* Check how how many bytes are pending */
if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0){
goto bail;
}
/* Check how how many bytes are pending */
if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0) {
goto bail;
}
if(len==0){
TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
if(len==0) {
TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0){
TSK_FREE(data);
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0) {
TSK_FREE(data);
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
goto bail;
}
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
goto bail;
}
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
TSK_FREE(data);
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
TSK_FREE(data);
if(response){
if(tnet_stun_transacid_cmp(message->transaction_id, response->transaction_id)){
/* Not same transaction id */
TSK_OBJECT_SAFE_FREE(response);
continue;
}
}
if(response) {
if(tnet_stun_transacid_cmp(message->transaction_id, response->transaction_id)) {
/* Not same transaction id */
TSK_OBJECT_SAFE_FREE(response);
continue;
}
}
goto bail;
}
else{
continue;
}
}
goto bail;
}
else {
continue;
}
}
bail:
TSK_OBJECT_SAFE_FREE(buffer);
TSK_OBJECT_SAFE_FREE(buffer);
return response;
return response;
}
/**@ingroup tnet_stun_group
@ -241,78 +240,77 @@ bail:
**/
int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *binding)
{
int ret = -1;
tnet_stun_response_t *response = 0;
tnet_stun_request_t *request = 0;
int ret = -1;
tnet_stun_response_t *response = 0;
tnet_stun_request_t *request = 0;
goto stun_phase0;
goto stun_phase0;
/* RFC 5389 - 10.2.1.1. First Request
If the client has not completed a successful request/response
transaction with the server (as identified by hostname, if the DNS
procedures of Section 9 are used, else IP address if not), it SHOULD
omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
In other words, the very first request is sent as if there were no
authentication or message integrity applied.
*/
stun_phase0:
{
if(!(request = tnet_stun_create_request(binding))){
goto bail;
}
/* RFC 5389 - 10.2.1.1. First Request
If the client has not completed a successful request/response
transaction with the server (as identified by hostname, if the DNS
procedures of Section 9 are used, else IP address if not), it SHOULD
omit the USERNAME, MESSAGE-INTEGRITY, REALM, and NONCE attributes.
In other words, the very first request is sent as if there were no
authentication or message integrity applied.
*/
stun_phase0: {
if(!(request = tnet_stun_create_request(binding))) {
goto bail;
}
if(TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type)){
response = tnet_stun_send_unreliably(binding->localFD, context->RTO, context->Rc, request, (struct sockaddr*)&binding->server);
}
if(TNET_SOCKET_TYPE_IS_DGRAM(context->socket_type)) {
response = tnet_stun_send_unreliably(binding->localFD, context->RTO, context->Rc, request, (struct sockaddr*)&binding->server);
}
if(response){
if(TNET_STUN_RESPONSE_IS_ERROR(response)){
short code = tnet_stun_message_get_errorcode(response);
const char* realm = tnet_stun_message_get_realm(response);
const char* nonce = tnet_stun_message_get_nonce(response);
if(response) {
if(TNET_STUN_RESPONSE_IS_ERROR(response)) {
short code = tnet_stun_message_get_errorcode(response);
const char* realm = tnet_stun_message_get_realm(response);
const char* nonce = tnet_stun_message_get_nonce(response);
if(code == 401 && realm && nonce){
if(!binding->nonce){
/* First time we get a nonce */
tsk_strupdate(&binding->nonce, nonce);
tsk_strupdate(&binding->realm, realm);
if(code == 401 && realm && nonce) {
if(!binding->nonce) {
/* First time we get a nonce */
tsk_strupdate(&binding->nonce, nonce);
tsk_strupdate(&binding->realm, realm);
/* Delete the message and response before retrying*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
/* Delete the message and response before retrying*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
// Send again using new transaction identifier
return tnet_stun_send_bind(context, binding);
}
else{
ret = -3;
}
}
else{
ret = -2;
}
}
else{
const tnet_stun_attribute_t *attribute;
if((attribute= tnet_stun_message_get_attribute(response, stun_xor_mapped_address))){
ret = 0;
binding->xmaddr = tsk_object_ref((void*)attribute);
}
else if((attribute= tnet_stun_message_get_attribute(response, stun_mapped_address))){
ret = 0;
binding->maddr = tsk_object_ref((void*)attribute);
}
}
}
}
/* END OF stun_phase0 */
// Send again using new transaction identifier
return tnet_stun_send_bind(context, binding);
}
else {
ret = -3;
}
}
else {
ret = -2;
}
}
else {
const tnet_stun_attribute_t *attribute;
if((attribute= tnet_stun_message_get_attribute(response, stun_xor_mapped_address))) {
ret = 0;
binding->xmaddr = tsk_object_ref((void*)attribute);
}
else if((attribute= tnet_stun_message_get_attribute(response, stun_mapped_address))) {
ret = 0;
binding->maddr = tsk_object_ref((void*)attribute);
}
}
}
}
/* END OF stun_phase0 */
bail:
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
return ret;
return ret;
}
/**@ingroup tnet_stun_group
@ -327,26 +325,26 @@ bail:
**/
tnet_stun_binding_id_t tnet_stun_bind(const tnet_nat_context_t* nat_context, tnet_fd_t localFD)
{
tnet_stun_binding_id_t id = TNET_STUN_INVALID_BINDING_ID;
tnet_stun_binding_id_t id = TNET_STUN_INVALID_BINDING_ID;
tnet_stun_binding_t *binding = 0;
tnet_stun_binding_t *binding = 0;
if(nat_context && localFD != TNET_INVALID_FD){
if(!(binding = tnet_stun_binding_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password))){
goto bail;
}
if(nat_context && localFD != TNET_INVALID_FD) {
if(!(binding = tnet_stun_binding_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password))) {
goto bail;
}
if(tnet_stun_send_bind(nat_context, binding)){
TSK_OBJECT_SAFE_FREE(binding);
goto bail;
}
if(tnet_stun_send_bind(nat_context, binding)) {
TSK_OBJECT_SAFE_FREE(binding);
goto bail;
}
id = binding->id;
tsk_list_push_back_data(nat_context->stun_bindings, (void**)&binding);
}
id = binding->id;
tsk_list_push_back_data(nat_context->stun_bindings, (void**)&binding);
}
bail:
return id;
return id;
}
/**@ingroup tnet_stun_group
@ -359,13 +357,13 @@ bail:
**/
int tnet_stun_transacid_cmp(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2)
{
tsk_size_t i;
for(i=0; i<sizeof(tnet_stun_transacid_t); i++){
if(id1[i] != id2[i]){
return (id1[i] - id2[i]);
}
}
return 0;
tsk_size_t i;
for(i=0; i<sizeof(tnet_stun_transacid_t); i++) {
if(id1[i] != id2[i]) {
return (id1[i] - id2[i]);
}
}
return 0;
}
@ -382,61 +380,60 @@ int tnet_stun_transacid_cmp(const tnet_stun_transacid_t id1, const tnet_stun_tra
//
static tsk_object_t* tnet_stun_binding_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_binding_t *binding = self;
if(binding){
static tnet_stun_binding_id_t __binding_unique_id = 0;
tnet_stun_binding_t *binding = self;
if(binding) {
static tnet_stun_binding_id_t __binding_unique_id = 0;
const char* server_address;
tnet_port_t server_port;
const char* server_address;
tnet_port_t server_port;
binding->id = ++__binding_unique_id;
binding->id = ++__binding_unique_id;
binding->localFD = va_arg(*app, tnet_fd_t);
binding->socket_type = va_arg(*app, tnet_socket_type_t);
binding->localFD = va_arg(*app, tnet_fd_t);
binding->socket_type = va_arg(*app, tnet_socket_type_t);
server_address = tsk_strdup(va_arg(*app, const char*));
server_address = tsk_strdup(va_arg(*app, const char*));
#if defined(__GNUC__)
server_port = (tnet_port_t)va_arg(*app, unsigned);
server_port = (tnet_port_t)va_arg(*app, unsigned);
#else
server_port = va_arg(*app, tnet_port_t);
server_port = va_arg(*app, tnet_port_t);
#endif
binding->username = tsk_strdup(va_arg(*app, const char*));
binding->password = tsk_strdup(va_arg(*app, const char*));
binding->username = tsk_strdup(va_arg(*app, const char*));
binding->password = tsk_strdup(va_arg(*app, const char*));
if(server_address){
tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
}
if(server_address) {
tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
}
binding->software = tsk_strdup(TNET_SOFTWARE);
}
return self;
binding->software = tsk_strdup(TNET_SOFTWARE);
}
return self;
}
static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
{
tnet_stun_binding_t *binding = self;
if(binding){
TSK_FREE(binding->username);
TSK_FREE(binding->password);
TSK_FREE(binding->realm);
TSK_FREE(binding->nonce);
tnet_stun_binding_t *binding = self;
if(binding) {
TSK_FREE(binding->username);
TSK_FREE(binding->password);
TSK_FREE(binding->realm);
TSK_FREE(binding->nonce);
TSK_FREE(binding->software);
TSK_FREE(binding->software);
TSK_OBJECT_SAFE_FREE(binding->maddr);
TSK_OBJECT_SAFE_FREE(binding->xmaddr);
}
TSK_OBJECT_SAFE_FREE(binding->maddr);
TSK_OBJECT_SAFE_FREE(binding->xmaddr);
}
return self;
return self;
}
static const tsk_object_def_t tnet_stun_binding_def_s =
{
sizeof(tnet_stun_binding_t),
tnet_stun_binding_ctor,
tnet_stun_binding_dtor,
tsk_null,
static const tsk_object_def_t tnet_stun_binding_def_s = {
sizeof(tnet_stun_binding_t),
tnet_stun_binding_ctor,
tnet_stun_binding_dtor,
tsk_null,
};
const tsk_object_def_t *tnet_stun_binding_def_t = &tnet_stun_binding_def_s;

View File

@ -77,34 +77,33 @@ typedef uint64_t tnet_stun_binding_id_t;
/**@ingroup tnet_stun_group
* STUN2 binding context.
**/
typedef struct tnet_stun_binding_s
{
TSK_DECLARE_OBJECT;
typedef struct tnet_stun_binding_s {
TSK_DECLARE_OBJECT;
//! A unique id to identify this binding.
tnet_stun_binding_id_t id;
//! A unique id to identify this binding.
tnet_stun_binding_id_t id;
//! The username to authenticate to the STUN server.
char* username;
//! The password to authenticate to the STUN server.
char* password;
//! The realm.
char* realm;
//! The nonce.
char* nonce;
//! The client name.
char* software;
//! Local file descriptor for which to get server reflexive address.
tnet_fd_t localFD;
//! The type of the bound socket.
tnet_socket_type_t socket_type;
//! The address of the STUN server.
struct sockaddr_storage server;
//! Server reflexive address of the local socket(STUN1 as per RFC 3489).
tnet_stun_attribute_mapped_addr_t *maddr;
//! XORed server reflexive address (STUN2 as per RFC 5389).
tnet_stun_attribute_xmapped_addr_t *xmaddr;
}tnet_stun_binding_t;
//! The username to authenticate to the STUN server.
char* username;
//! The password to authenticate to the STUN server.
char* password;
//! The realm.
char* realm;
//! The nonce.
char* nonce;
//! The client name.
char* software;
//! Local file descriptor for which to get server reflexive address.
tnet_fd_t localFD;
//! The type of the bound socket.
tnet_socket_type_t socket_type;
//! The address of the STUN server.
struct sockaddr_storage server;
//! Server reflexive address of the local socket(STUN1 as per RFC 3489).
tnet_stun_attribute_mapped_addr_t *maddr;
//! XORed server reflexive address (STUN2 as per RFC 5389).
tnet_stun_attribute_xmapped_addr_t *xmaddr;
} tnet_stun_binding_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_binding_def_t;
/**@ingroup tnet_stun_group

View File

@ -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;

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -51,58 +51,56 @@ TNET_BEGIN_DECLS
/**@ingroup tnet_stun_group
* STUN IP family as per RFC 5389 subclause 15.1.
**/
typedef enum tnet_stun_addr_family_e
{
stun_ipv4 = 0x01,
stun_ipv6 = 0x02
typedef enum tnet_stun_addr_family_e {
stun_ipv4 = 0x01,
stun_ipv6 = 0x02
}
tnet_stun_addr_family_t;
/**@ingroup tnet_stun_group
* STUN attribute types as per RFC 5389 subclause 18.2.
**/
typedef enum tnet_stun_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 */
stun_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
stun_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
stun_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
stun_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
stun_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_password = 0x0007, /**< (Reserved; was PASSWORD) */
stun_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
stun_unknown_attributes = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
stun_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
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 */
stun_response_address = 0x0002, /**< (Reserved; was RESPONSE-ADDRESS) */
stun_change_address = 0x0003, /**< (Reserved; was CHANGE-ADDRESS) */
stun_source_address = 0x0004, /**< (Reserved; was SOURCE-ADDRESS) */
stun_changed_address = 0x0005, /**< (Reserved; was CHANGED-ADDRESS) */
stun_username = 0x0006, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_password = 0x0007, /**< (Reserved; was PASSWORD) */
stun_message_integrity = 0x0008, /**< http://tools.ietf.org/html/rfc5389#page-34 */
stun_error_code = 0x0009, /**< http://tools.ietf.org/html/rfc5389#page-36 */
stun_unknown_attributes = 0x000A, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_reflected_from = 0x000B, /**< (Reserved; was REFLECTED-FROM) */
stun_realm = 0x0014, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_nonce = 0x0015, /**< http://tools.ietf.org/html/rfc5389#page-38 */
stun_xor_mapped_address = 0x0020, /**< http://tools.ietf.org/html/rfc5389#page-33 */
/* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
stun_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
/* === RFC 5389 - Comprehension-optional range (0x8000-0xFFFF) */
stun_software = 0x8022, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_alternate_server = 0x8023, /**< http://tools.ietf.org/html/rfc5389#page-39 */
stun_fingerprint = 0x8028, /**< http://tools.ietf.org/html/rfc5389#page-36 */
/* === draft-ietf-behave-turn-16 */
stun_channel_number = 0x000C, /**< draft-ietf-behave-turn-16 - CHANNEL-NUMBER */
stun_lifetime = 0x000D, /**< draft-ietf-behave-turn-16 - LIFETIME */
stun_reserved2 = 0x0010, /**< draft-ietf-behave-turn-16 - Reserved (was BANDWIDTH) */
stun_xor_peer_address = 0x0012, /**< draft-ietf-behave-turn-16 - XOR-PEER-ADDRESS */
stun_data = 0x0013, /**< draft-ietf-behave-turn-16 - DATA */
stun_xor_relayed_address = 0x0016, /**< draft-ietf-behave-turn-16 - XOR-RELAYED-ADDRESS */
stun_even_port = 0x0018, /**< draft-ietf-behave-turn-16 - EVEN-PORT */
stun_requested_transport = 0x0019, /**< draft-ietf-behave-turn-16 - REQUESTED-TRANSPORT */
stun_dont_fragment = 0x001A, /**< draft-ietf-behave-turn-16 - DONT-FRAGMENT */
stun_reserved3 = 0x0021, /**< draft-ietf-behave-turn-16 - Reserved (was TIMER-VAL) */
stun_reservation_token = 0x0022, /**< draft-ietf-behave-turn-16 - RESERVATION-TOKEN */
/* === draft-ietf-behave-turn-16 */
stun_channel_number = 0x000C, /**< draft-ietf-behave-turn-16 - CHANNEL-NUMBER */
stun_lifetime = 0x000D, /**< draft-ietf-behave-turn-16 - LIFETIME */
stun_reserved2 = 0x0010, /**< draft-ietf-behave-turn-16 - Reserved (was BANDWIDTH) */
stun_xor_peer_address = 0x0012, /**< draft-ietf-behave-turn-16 - XOR-PEER-ADDRESS */
stun_data = 0x0013, /**< draft-ietf-behave-turn-16 - DATA */
stun_xor_relayed_address = 0x0016, /**< draft-ietf-behave-turn-16 - XOR-RELAYED-ADDRESS */
stun_even_port = 0x0018, /**< draft-ietf-behave-turn-16 - EVEN-PORT */
stun_requested_transport = 0x0019, /**< draft-ietf-behave-turn-16 - REQUESTED-TRANSPORT */
stun_dont_fragment = 0x001A, /**< draft-ietf-behave-turn-16 - DONT-FRAGMENT */
stun_reserved3 = 0x0021, /**< draft-ietf-behave-turn-16 - Reserved (was TIMER-VAL) */
stun_reservation_token = 0x0022, /**< draft-ietf-behave-turn-16 - RESERVATION-TOKEN */
/* RFC 5245 */
stun_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
stun_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
stun_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
stun_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
/* RFC 5245 */
stun_ice_priority = 0x0024, /**< 21.2. STUN Attributes */
stun_ice_use_candidate = 0x0025, /**< 21.2. STUN Attributes */
stun_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */
stun_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */
}
tnet_stun_attribute_type_t;
@ -110,20 +108,19 @@ tnet_stun_attribute_type_t;
/**@ingroup tnet_stun_group
RFC 5389 - 15. STUN Attributes
*/
typedef struct tnet_stun_attribute_s
{
TSK_DECLARE_OBJECT;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_attribute_type_t type;
uint16_t length;
typedef struct tnet_stun_attribute_s {
TSK_DECLARE_OBJECT;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Value (variable) ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_attribute_type_t type;
uint16_t length;
}
tnet_stun_attribute_t;
@ -136,24 +133,23 @@ 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
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_mapped_addr_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address (32 bits or 128 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t address[16];
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0 0 0 0 0 0 0| Family | Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address (32 bits or 128 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t address[16];
}
tnet_stun_attribute_mapped_addr_t;
@ -163,22 +159,21 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_mapped_addr_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.2. XOR-MAPPED-ADDRESS
*/
typedef struct tnet_stun_attribute_xmapped_addr_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_xmapped_addr_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|x x x x x x x x| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t xport;
uint8_t xaddress[16];
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|x x x x x x x x| Family | X-Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| X-Address (Variable)
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
tnet_stun_addr_family_t family;
uint16_t xport;
uint8_t xaddress[16];
}
tnet_stun_attribute_xmapped_addr_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t;
@ -187,11 +182,10 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_xmapped_addr_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.3. USERNAME.
*/
typedef struct tnet_stun_attribute_username_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_username_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
char* value;
}
tnet_stun_attribute_username_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
@ -200,11 +194,10 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.4. MESSAGE-INTEGRITY.
*/
typedef struct tnet_stun_attribute_integrity_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_integrity_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_sha1digest_t sha1digest;
tsk_sha1digest_t sha1digest;
}
tnet_stun_attribute_integrity_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
@ -213,11 +206,10 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.5. FINGERPRINT.
*/
typedef struct tnet_stun_attribute_fingerprint_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_fingerprint_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
uint32_t value;
}
tnet_stun_attribute_fingerprint_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
@ -225,21 +217,20 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
/**@ingroup tnet_stun_group
*RFC 5389 - 15.6. ERROR-CODE
*/
typedef struct tnet_stun_attribute_errorcode_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved, should be 0 |Class| Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reason Phrase (variable) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t _class;
uint8_t number;
char* reason_phrase;
typedef struct tnet_stun_attribute_errorcode_s {
TNET_STUN_DECLARE_ATTRIBUTE;
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved, should be 0 |Class| Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reason Phrase (variable) ..
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
uint8_t _class;
uint8_t number;
char* reason_phrase;
}
tnet_stun_attribute_errorcode_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t;
@ -248,11 +239,10 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_errorcode_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.7. REALM. */
typedef struct tnet_stun_attribute_realm_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_realm_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
char* value;
}
tnet_stun_attribute_realm_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
@ -260,85 +250,77 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.8. NONCE. */
typedef struct tnet_stun_attribute_nonce_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_nonce_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
char* value;
}
tnet_stun_attribute_nonce_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_nonce_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES. */
typedef struct tnet_stun_attribute_unknowns_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_unknowns_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_buffer_t *value;
tsk_buffer_t *value;
}
tnet_stun_attribute_unknowns_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.10. SOFTWARE. */
typedef struct tnet_stun_attribute_software_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_software_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char *value;
char *value;
}
tnet_stun_attribute_software_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_software_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.11. ALTERNATE-SERVER. */
typedef struct tnet_stun_attribute_altserver_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_altserver_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t server[128];
tnet_stun_addr_family_t family;
uint16_t port;
uint8_t server[128];
}
tnet_stun_attribute_altserver_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_altserver_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_priority_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
typedef struct tnet_stun_attribute_ice_priority_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
}
tnet_stun_attribute_ice_priority_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_priority_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_use_candidate_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
typedef struct tnet_stun_attribute_ice_use_candidate_s {
TNET_STUN_DECLARE_ATTRIBUTE;
}
tnet_stun_attribute_ice_use_candidate_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_use_candidate_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_controlled_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
typedef struct tnet_stun_attribute_ice_controlled_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
}
tnet_stun_attribute_ice_controlled_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlled_def_t;
/**@ingroup tnet_stun_group
* RFC 5245 - 19.1. New Attributes */
typedef struct tnet_stun_attribute_ice_controlling_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
typedef struct tnet_stun_attribute_ice_controlling_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint64_t value;
}
tnet_stun_attribute_ice_controlling_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_ice_controlling_def_t;

View File

@ -44,12 +44,12 @@
static int __pred_find_attribute_by_type(const tsk_list_item_t *item, const void *att_type)
{
if(item && item->data){
tnet_stun_attribute_t *att = item->data;
tnet_stun_attribute_type_t type = *((tnet_stun_attribute_type_t*)att_type);
return (att->type - type);
}
return -1;
if(item && item->data) {
tnet_stun_attribute_t *att = item->data;
tnet_stun_attribute_type_t type = *((tnet_stun_attribute_type_t*)att_type);
return (att->type - type);
}
return -1;
}
/**@ingroup tnet_stun_group
@ -60,7 +60,7 @@ static int __pred_find_attribute_by_type(const tsk_list_item_t *item, const void
tnet_stun_message_t* tnet_stun_message_create(const char* username, const char* password)
{
return tsk_object_new(tnet_stun_message_def_t, username, password);
return tsk_object_new(tnet_stun_message_def_t, username, password);
}
/**@ingroup tnet_stun_group
@ -70,7 +70,7 @@ tnet_stun_message_t* tnet_stun_message_create(const char* username, const char*
*/
tnet_stun_message_t* tnet_stun_message_create_null()
{
return tnet_stun_message_create(tsk_null, tsk_null);
return tnet_stun_message_create(tsk_null, tsk_null);
}
#define SERIALIZE_N_ADD_ATTRIBUTE(att_name, payload, payload_size) \
@ -86,18 +86,18 @@ tnet_stun_message_t* tnet_stun_message_create_null()
**/
tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self)
{
tsk_buffer_t *output = 0;
tnet_stun_attribute_t *attribute;
unsigned compute_integrity = self->integrity;
tsk_buffer_t *output = 0;
tnet_stun_attribute_t *attribute;
unsigned compute_integrity = self->integrity;
if(!self){
goto bail;
}
if(!self) {
goto bail;
}
output = tsk_buffer_create_null();
output = tsk_buffer_create_null();
/* RFC 5389 - 6. STUN Message Structure
0 1 2 3
/* RFC 5389 - 6. STUN Message Structure
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
@ -108,134 +108,135 @@ tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self)
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
*/
/* STUN Message Type
*/
{
uint16_t type = tnet_htons(self->type);
tsk_buffer_append(output, &(type), 2);
}
/* STUN Message Type
*/
{
uint16_t type = tnet_htons(self->type);
tsk_buffer_append(output, &(type), 2);
}
/* Message Length ==> Will be updated after attributes have been added. */
{
static const uint16_t length = 0;
tsk_buffer_append(output, &(length), 2);
}
/* Message Length ==> Will be updated after attributes have been added. */
{
static const uint16_t length = 0;
tsk_buffer_append(output, &(length), 2);
}
/* Magic Cookie
*/
{
uint32_t cookie = tnet_htonl(self->cookie);
tsk_buffer_append(output, &(cookie), 4);
}
/* Magic Cookie
*/
{
uint32_t cookie = tnet_htonl(self->cookie);
tsk_buffer_append(output, &(cookie), 4);
}
/* Transaction ID (96 bits==>16bytes)
*/
tsk_buffer_append(output, self->transaction_id, TNET_STUN_TRANSACID_SIZE);
/* Transaction ID (96 bits==>16bytes)
*/
tsk_buffer_append(output, self->transaction_id, TNET_STUN_TRANSACID_SIZE);
/* DONT-FRAGMENT
*/
if(self->dontfrag){
attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_dontfrag_create();
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
/* DONT-FRAGMENT
*/
if(self->dontfrag) {
attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_dontfrag_create();
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
/* AUTHENTICATION */
if(self->realm && self->nonce){ // long term
SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm));
SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce));
/* AUTHENTICATION */
if(self->realm && self->nonce) { // long term
SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm));
SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce));
compute_integrity = !self->nointegrity;
}
else if(self->password){ // short term
compute_integrity = !self->nointegrity;
}
compute_integrity = !self->nointegrity;
}
else if(self->password) { // short term
compute_integrity = !self->nointegrity;
}
if(compute_integrity && self->username){
SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
}
if(compute_integrity && self->username) {
SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
}
/*=== Attributes === */
{
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes)
{
attribute = item->data;
tnet_stun_attribute_serialize(attribute, output);
tnet_stun_attribute_pad(attribute, output);
}
}
/*=== Attributes === */
{
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes) {
attribute = item->data;
tnet_stun_attribute_serialize(attribute, output);
tnet_stun_attribute_pad(attribute, output);
}
}
/* Message Length: The message length MUST contain the size, in bytes, of the message
not including the 20-byte STUN header.
*/
{
// compute length for 'MESSAGE-INTEGRITY'
// will be computed again to store the correct value
uint16_t length = (output->size) - TNET_STUN_HEADER_SIZE;
/* Message Length: The message length MUST contain the size, in bytes, of the message
not including the 20-byte STUN header.
*/
{
// compute length for 'MESSAGE-INTEGRITY'
// will be computed again to store the correct value
uint16_t length = (output->size) - TNET_STUN_HEADER_SIZE;
#if 0
if(self->fingerprint)
length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
if(self->fingerprint) {
length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/);
}
#endif
if(compute_integrity)
length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
if(compute_integrity) {
length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
}
*(((uint16_t*)output->data)+1) = tnet_htons(length);
}
*(((uint16_t*)output->data)+1) = tnet_htons(length);
}
/* MESSAGE-INTEGRITY */
if(compute_integrity){
/* RFC 5389 - 15.4. MESSAGE-INTEGRITY
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
/* MESSAGE-INTEGRITY */
if(compute_integrity) {
/* RFC 5389 - 15.4. MESSAGE-INTEGRITY
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
For short-term credentials ==> key = SASLprep(password)
*/
For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
For short-term credentials ==> key = SASLprep(password)
*/
tsk_sha1digest_t hmac;
tsk_sha1digest_t hmac;
if(self->username && self->realm && self->password){ // long term
char* keystr = tsk_null;
tsk_md5digest_t md5;
tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
if(self->username && self->realm && self->password) { // long term
char* keystr = tsk_null;
tsk_md5digest_t md5;
tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
TSK_FREE(keystr);
}
else{ // short term
hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
}
TSK_FREE(keystr);
}
else { // short term
hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
}
SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
}
SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
}
// LENGTH
*(((uint16_t*)output->data) + 1) = tnet_htons((output->size - TNET_STUN_HEADER_SIZE + (self->fingerprint ? 8 : 0)));
// LENGTH
*(((uint16_t*)output->data) + 1) = tnet_htons((output->size - TNET_STUN_HEADER_SIZE + (self->fingerprint ? 8 : 0)));
/* FINGERPRINT */
if(self->fingerprint){//JINGLE_ICE
/* RFC 5389 - 15.5. FINGERPRINT
The FINGERPRINT attribute MAY be present in all STUN messages. The
value of the attribute is computed as the CRC-32 of the STUN message
up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
the 32-bit value 0x5354554e
*/
uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size);
fingerprint ^= 0x5354554e;
fingerprint = tnet_htonl(fingerprint);
/* FINGERPRINT */
if(self->fingerprint) { //JINGLE_ICE
/* RFC 5389 - 15.5. FINGERPRINT
The FINGERPRINT attribute MAY be present in all STUN messages. The
value of the attribute is computed as the CRC-32 of the STUN message
up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
the 32-bit value 0x5354554e
*/
uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size);
fingerprint ^= 0x5354554e;
fingerprint = tnet_htonl(fingerprint);
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint);
tnet_stun_attribute_serialize(attribute, output);
TSK_OBJECT_SAFE_FREE(attribute);
}
bail:
return output;
return output;
}
@ -250,74 +251,73 @@ bail:
**/
tnet_stun_message_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size)
{
tnet_stun_message_t *message = 0;
uint8_t* dataPtr, *dataEnd;
tnet_stun_message_t *message = 0;
uint8_t* dataPtr, *dataEnd;
if(!data || (size < TNET_STUN_HEADER_SIZE) || !TNET_IS_STUN2_MSG(data, size)){
goto bail;
}
if(!data || (size < TNET_STUN_HEADER_SIZE) || !TNET_IS_STUN2_MSG(data, size)) {
goto bail;
}
dataPtr = (uint8_t*)data;
dataEnd = (dataPtr + size);
dataPtr = (uint8_t*)data;
dataEnd = (dataPtr + size);
message = tnet_stun_message_create_null();
message = tnet_stun_message_create_null();
/* Message Type
*/
message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Message Type
*/
message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Message Length
*/
message->length = tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Message Length
*/
message->length = tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Check message validity
*/
if((message->length + TNET_STUN_HEADER_SIZE) != size)
{
TSK_OBJECT_SAFE_FREE(message);
goto bail;
}
/* Check message validity
*/
if((message->length + TNET_STUN_HEADER_SIZE) != size) {
TSK_OBJECT_SAFE_FREE(message);
goto bail;
}
/* Magic Cookie
==> already set by the constructor and checked by @ref TNET_IS_STUN2
*/
dataPtr += 4;
/* Magic Cookie
==> already set by the constructor and checked by @ref TNET_IS_STUN2
*/
dataPtr += 4;
/* Transaction ID
*/
memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
dataPtr += TNET_STUN_TRANSACID_SIZE;
/* Transaction ID
*/
memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
dataPtr += TNET_STUN_TRANSACID_SIZE;
/* == Parse attributes
*/
while(dataPtr < dataEnd){
tnet_stun_attribute_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr));
if(attribute){
tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */);
att_size += (att_size & 0x03) ? 4-(att_size & 0x03) : 0; // Skip zero bytes used to pad the attribute.
/* == Parse attributes
*/
while(dataPtr < dataEnd) {
tnet_stun_attribute_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr));
if(attribute) {
tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */);
att_size += (att_size & 0x03) ? 4-(att_size & 0x03) : 0; // Skip zero bytes used to pad the attribute.
dataPtr += att_size;
tsk_list_push_back_data(message->attributes, (void**)&attribute);
dataPtr += att_size;
tsk_list_push_back_data(message->attributes, (void**)&attribute);
continue;
}
else{
continue;
}
}
continue;
}
else {
continue;
}
}
bail:
return message;
return message;
}
/**@ingroup tnet_stun_group
*/
tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
return (tnet_stun_message_get_attribute(self, type) != tsk_null);
return (tnet_stun_message_get_attribute(self, type) != tsk_null);
}
/**@ingroup tnet_stun_group
@ -328,21 +328,21 @@ tsk_bool_t tnet_stun_message_has_attribute(const tnet_stun_message_t *self, tnet
*/
int tnet_stun_message_add_attribute(tnet_stun_message_t *self, tnet_stun_attribute_t** attribute)
{
if(self && attribute && *attribute){
tsk_list_push_back_data(self->attributes, (void**)attribute);
return 0;
}
return -1;
if(self && attribute && *attribute) {
tsk_list_push_back_data(self->attributes, (void**)attribute);
return 0;
}
return -1;
}
/**@ingroup tnet_stun_group
*/
int tnet_stun_message_remove_attribute(tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
if(self && self->attributes){
tsk_list_remove_item_by_pred(self->attributes, __pred_find_attribute_by_type, &type);
}
return 0;
if(self && self->attributes) {
tsk_list_remove_item_by_pred(self->attributes, __pred_find_attribute_by_type, &type);
}
return 0;
}
@ -354,17 +354,17 @@ int tnet_stun_message_remove_attribute(tnet_stun_message_t *self, tnet_stun_attr
*/
const tnet_stun_attribute_t* tnet_stun_message_get_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type)
{
tnet_stun_attribute_t* attribute;
tnet_stun_attribute_t* attribute;
if(self && !TSK_LIST_IS_EMPTY(self->attributes)){
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes){
if((attribute = item->data) && attribute->type == type){
return attribute;
}
}
}
return 0;
if(self && !TSK_LIST_IS_EMPTY(self->attributes)) {
tsk_list_item_t *item;
tsk_list_foreach(item, self->attributes) {
if((attribute = item->data) && attribute->type == type) {
return attribute;
}
}
}
return 0;
}
/**@ingroup tnet_stun_group
@ -374,11 +374,11 @@ const tnet_stun_attribute_t* tnet_stun_message_get_attribute(const tnet_stun_mes
*/
short tnet_stun_message_get_errorcode(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code);
if(error){
return ((error->_class*100) + error->number);
}
return -1;
const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code);
if(error) {
return ((error->_class*100) + error->number);
}
return -1;
}
/**@ingroup tnet_stun_group
@ -388,11 +388,11 @@ short tnet_stun_message_get_errorcode(const tnet_stun_message_t *self)
*/
const char* tnet_stun_message_get_realm(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm);
if(realm){
return realm->value;
}
return 0;
const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm);
if(realm) {
return realm->value;
}
return 0;
}
/**@ingroup tnet_stun_group
@ -402,11 +402,11 @@ const char* tnet_stun_message_get_realm(const tnet_stun_message_t *self)
*/
const char* tnet_stun_message_get_nonce(const tnet_stun_message_t *self)
{
const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce);
if(nonce){
return nonce->value;
}
return 0;
const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce);
if(nonce) {
return nonce->value;
}
return 0;
}
/**@ingroup tnet_stun_group
@ -416,25 +416,25 @@ const char* tnet_stun_message_get_nonce(const tnet_stun_message_t *self)
*/
int32_t tnet_stun_message_get_lifetime(const tnet_stun_message_t *self)
{
const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime);
if(lifetime){
return lifetime->value;
}
return -1;
const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime);
if(lifetime) {
return lifetime->value;
}
return -1;
}
/**@ingroup tnet_stun_group
*/
tsk_bool_t tnet_stun_message_transac_id_equals(const tnet_stun_transacid_t id1, const tnet_stun_transacid_t id2)
{
tsk_size_t i;
static const tsk_size_t size = sizeof(tnet_stun_transacid_t);
for(i = 0; i < size; i++){
if(id1[i] != id2[i]){
return tsk_false;
}
}
return tsk_true;
tsk_size_t i;
static const tsk_size_t size = sizeof(tnet_stun_transacid_t);
for(i = 0; i < size; i++) {
if(id1[i] != id2[i]) {
return tsk_false;
}
}
return tsk_true;
}
@ -447,48 +447,48 @@ tsk_bool_t tnet_stun_message_transac_id_equals(const tnet_stun_transacid_t id1,
//
static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app)
{
tnet_stun_message_t *message = self;
if(message){
message->username = tsk_strdup(va_arg(*app, const char*));
message->password = tsk_strdup(va_arg(*app, const char*));
tnet_stun_message_t *message = self;
if(message) {
message->username = tsk_strdup(va_arg(*app, const char*));
message->password = tsk_strdup(va_arg(*app, const char*));
message->cookie = TNET_STUN_MAGIC_COOKIE;
message->attributes = tsk_list_create();
message->cookie = TNET_STUN_MAGIC_COOKIE;
message->attributes = tsk_list_create();
message->fingerprint = 1;
message->integrity = 0;
message->fingerprint = 1;
message->integrity = 0;
{ // 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();
}
}
}
return self;
{
// 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();
}
}
}
return self;
}
static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self)
{
tnet_stun_message_t *message = self;
if(message){
TSK_FREE(message->username);
TSK_FREE(message->password);
TSK_FREE(message->realm);
TSK_FREE(message->nonce);
tnet_stun_message_t *message = self;
if(message) {
TSK_FREE(message->username);
TSK_FREE(message->password);
TSK_FREE(message->realm);
TSK_FREE(message->nonce);
TSK_OBJECT_SAFE_FREE(message->attributes);
}
TSK_OBJECT_SAFE_FREE(message->attributes);
}
return self;
return self;
}
static const tsk_object_def_t tnet_stun_message_def_s =
{
sizeof(tnet_stun_message_t),
tnet_stun_message_ctor,
tnet_stun_message_dtor,
tsk_null,
static const tsk_object_def_t tnet_stun_message_def_s = {
sizeof(tnet_stun_message_t),
tnet_stun_message_ctor,
tnet_stun_message_dtor,
tsk_null,
};
const tsk_object_def_t *tnet_stun_message_def_t = &tnet_stun_message_def_s;

View File

@ -95,12 +95,11 @@ 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
{
stun_class_request = 0x00, /**< Request class: 0b00 */
stun_class_indication = 0x01, /**< Indication class: 0b01 */
stun_class_success_response = 0x02, /**< Success response class: 0b10 */
stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
typedef enum tnet_stun_class_type_e {
stun_class_request = 0x00, /**< Request class: 0b00 */
stun_class_indication = 0x01, /**< Indication class: 0b01 */
stun_class_success_response = 0x02, /**< Success response class: 0b10 */
stun_class_error_response = 0x03, /**< Error/failure response class: 0b11 */
}
tnet_stun_class_type_t;
@ -109,73 +108,71 @@ 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
{
stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
typedef enum tnet_stun_method_type_e {
stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
}
tnet_stun_method_type_t;
/**@ingroup tnet_stun_group
* List of all supported STUN types.
*/
typedef enum tnet_stun_message_type_e
{
/* RFC 5389 - 6. STUN Message Structure
typedef enum tnet_stun_message_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 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:
The message type field is decomposed further into the following
structure:
0 1
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
*/
stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
*/
stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
stun_allocate_request = (stun_method_allocate | TNET_STUN_CLASS_REQUEST_MASK),
stun_allocate_indication = (stun_method_allocate | TNET_STUN_CLASS_INDICATION_MASK),
stun_allocate_success_response = (stun_method_allocate | TNET_STUN_CLASS_SUCCESS_MASK),
stun_allocate_error_response = (stun_method_allocate | TNET_STUN_CLASS_ERROR_MASK),
stun_allocate_request = (stun_method_allocate | TNET_STUN_CLASS_REQUEST_MASK),
stun_allocate_indication = (stun_method_allocate | TNET_STUN_CLASS_INDICATION_MASK),
stun_allocate_success_response = (stun_method_allocate | TNET_STUN_CLASS_SUCCESS_MASK),
stun_allocate_error_response = (stun_method_allocate | TNET_STUN_CLASS_ERROR_MASK),
stun_refresh_request = (stun_method_refresh | TNET_STUN_CLASS_REQUEST_MASK),
stun_refresh_indication = (stun_method_refresh | TNET_STUN_CLASS_INDICATION_MASK),
stun_refresh_success_response = (stun_method_refresh | TNET_STUN_CLASS_SUCCESS_MASK),
stun_refresh_error_response = (stun_method_refresh | TNET_STUN_CLASS_ERROR_MASK),
stun_refresh_request = (stun_method_refresh | TNET_STUN_CLASS_REQUEST_MASK),
stun_refresh_indication = (stun_method_refresh | TNET_STUN_CLASS_INDICATION_MASK),
stun_refresh_success_response = (stun_method_refresh | TNET_STUN_CLASS_SUCCESS_MASK),
stun_refresh_error_response = (stun_method_refresh | TNET_STUN_CLASS_ERROR_MASK),
stun_send_indication = (stun_method_send | TNET_STUN_CLASS_INDICATION_MASK),
stun_send_indication = (stun_method_send | TNET_STUN_CLASS_INDICATION_MASK),
stun_data_indication = (stun_method_data | TNET_STUN_CLASS_INDICATION_MASK),
stun_data_indication = (stun_method_data | TNET_STUN_CLASS_INDICATION_MASK),
stun_createpermission_request = (stun_method_createpermission | TNET_STUN_CLASS_REQUEST_MASK),
stun_createpermission_indication = (stun_method_createpermission | TNET_STUN_CLASS_INDICATION_MASK),
stun_createpermission_success_response = (stun_method_createpermission | TNET_STUN_CLASS_SUCCESS_MASK),
stun_createpermission_error_response = (stun_method_createpermission | TNET_STUN_CLASS_ERROR_MASK),
stun_createpermission_request = (stun_method_createpermission | TNET_STUN_CLASS_REQUEST_MASK),
stun_createpermission_indication = (stun_method_createpermission | TNET_STUN_CLASS_INDICATION_MASK),
stun_createpermission_success_response = (stun_method_createpermission | TNET_STUN_CLASS_SUCCESS_MASK),
stun_createpermission_error_response = (stun_method_createpermission | TNET_STUN_CLASS_ERROR_MASK),
stun_channelbind_request = (stun_method_channelbind | TNET_STUN_CLASS_REQUEST_MASK),
stun_channelbind_indication = (stun_method_channelbind | TNET_STUN_CLASS_INDICATION_MASK),
stun_channelbind_success_response = (stun_method_channelbind | TNET_STUN_CLASS_SUCCESS_MASK),
stun_channelbind_error_response = (stun_method_channelbind | TNET_STUN_CLASS_ERROR_MASK),
stun_channelbind_request = (stun_method_channelbind | TNET_STUN_CLASS_REQUEST_MASK),
stun_channelbind_indication = (stun_method_channelbind | TNET_STUN_CLASS_INDICATION_MASK),
stun_channelbind_success_response = (stun_method_channelbind | TNET_STUN_CLASS_SUCCESS_MASK),
stun_channelbind_error_response = (stun_method_channelbind | TNET_STUN_CLASS_ERROR_MASK),
}
tnet_stun_message_type_t;
@ -184,12 +181,11 @@ 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
{
TSK_DECLARE_OBJECT;
typedef struct tnet_stun_message_s {
TSK_DECLARE_OBJECT;
/*
0 1 2 3
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
@ -200,24 +196,24 @@ typedef struct tnet_stun_message_s
| Transaction ID (96 bits) |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
*/
tnet_stun_message_type_t type;
uint16_t length;
uint32_t cookie;
tnet_stun_transacid_t transaction_id;
tnet_stun_message_type_t type;
uint16_t length;
uint32_t cookie;
tnet_stun_transacid_t transaction_id;
unsigned fingerprint:1;
unsigned integrity:1;
unsigned dontfrag:1;
unsigned nointegrity:1;
unsigned fingerprint:1;
unsigned integrity:1;
unsigned dontfrag:1;
unsigned nointegrity:1;
char* username;
char* password;
char* realm;
char* nonce;
char* username;
char* password;
char* realm;
char* nonce;
tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
}
tnet_stun_message_t;

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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.

View File

@ -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)

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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

View File

@ -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"

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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 */

View File

@ -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.
*

View File

@ -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.
*

View File

@ -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"