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

@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@ -49,51 +49,51 @@
*/
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
*
* Create generic STUN2 request with all mandatory headers and attributes.
* Create generic STUN2 request with all mandatory headers and attributes.
*
* @param [in,out] binding The binding object from which to create the request.
* @param [in,out] binding The binding object from which to create the request.
*
* @retval STUN2 request if succeed and NULL otherwise.
* @retval STUN2 request if succeed and NULL otherwise.
**/
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);
}
}
return message;
/* 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;
}
int tnet_stun_send_reliably(const tnet_stun_message_t* message)
{
return -1;
return -1;
}
@ -102,36 +102,35 @@ int tnet_stun_send_reliably(const tnet_stun_message_t* message)
* Internal function to send a STUN message using unrealiable protocol such as UDP.
*
*
* @param localFD The local file descriptor.
* @param RTO The Retransmission TimeOut.
* @param Rc The Number of retransmissions.
* @param [in,out] message The message to send.
* @param [in,out] server The destination STUN server.
* @param localFD The local file descriptor.
* @param RTO The Retransmission TimeOut.
* @param Rc The Number of retransmissions.
* @param [in,out] message The message to send.
* @param [in,out] server The destination STUN server.
*
* @return The response from the server or NULL if transport error.
* @return The response from the server or NULL if transport error.
**/
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;
if(!buffer)
{
goto bail;
}
{
tsk_buffer_t *buffer = tnet_stun_message_serialize(message);
tnet_stun_response_t *response = tsk_null;
if(!buffer) {
goto bail;
}
{
//#ifndef SIO_UDP_CONNRESET
//# ifndef IOC_VENDOR
//# define IOC_VENDOR 0x18000000
@ -144,228 +143,227 @@ tnet_stun_response_t* tnet_stun_send_unreliably(tnet_fd_t localFD, uint16_t RTO,
// DWORD dwBytesReturned = 0;
// BOOL bNewBehavior = TRUE;
// DWORD status;
//
//
// // disable new behavior using
// // IOCTL: SIO_UDP_CONNRESET
// status = WSAIoctl(localFD, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
// NULL, 0, &dwBytesReturned, NULL, NULL);
}
}
tv.tv_sec = 0;
tv.tv_usec = 0;
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;
FD_ZERO(&set);
FD_SET(localFD, &set);
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;
ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
FD_ZERO(&set);
FD_SET(localFD, &set);
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 */
ret = tnet_sockfd_sendto(localFD, server, buffer->data, buffer->size);
tsk_size_t len = 0;
void* data = 0;
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_DEBUG_INFO("STUN request got response");
tsk_size_t len = 0;
void* data = 0;
/* 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;
}
TSK_DEBUG_INFO("STUN request got response");
/* 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;
}
/* Check how how many bytes are pending */
if((ret = tnet_ioctlt(localFD, FIONREAD, &len))<0) {
goto bail;
}
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
TSK_FREE(data);
if(len==0) {
TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes");
continue;
}
/* Receive pending data */
data = tsk_calloc(len, sizeof(uint8_t));
if((ret = tnet_sockfd_recvfrom(localFD, data, len, 0, server))<0) {
TSK_FREE(data);
TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno());
goto bail;
}
/* Parse the incoming response. */
response = tnet_stun_message_deserialize(data, (tsk_size_t)ret);
TSK_FREE(data);
if(response) {
if(tnet_stun_transacid_cmp(message->transaction_id, response->transaction_id)) {
/* Not same transaction id */
TSK_OBJECT_SAFE_FREE(response);
continue;
}
}
goto bail;
}
else {
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;
}
}
bail:
TSK_OBJECT_SAFE_FREE(buffer);
TSK_OBJECT_SAFE_FREE(buffer);
return response;
return response;
}
/**@ingroup tnet_stun_group
* Internal function to send a STUN2 binding request over the network.
*
* @param [in,out] context The NAT context holding the user preferences.
* @param [in,out] binding The STUN binding object used to create the message to send.
* @param [in,out] context The NAT context holding the user preferences.
* @param [in,out] binding The STUN binding object used to create the message to send.
*
* @return Zero if succeed and non-zero error code otherwise.
* @return Zero if succeed and non-zero error code otherwise.
**/
int tnet_stun_send_bind(const tnet_nat_context_t* context, tnet_stun_binding_t *binding)
{
int ret = -1;
tnet_stun_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;
/* 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;
}
goto stun_phase0;
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);
}
/* 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(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(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(code == 401 && realm && nonce){
if(!binding->nonce){
/* First time we get a nonce */
tsk_strupdate(&binding->nonce, nonce);
tsk_strupdate(&binding->realm, realm);
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);
/* Delete the message and response before retrying*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
if(code == 401 && realm && nonce) {
if(!binding->nonce) {
/* First time we get a nonce */
tsk_strupdate(&binding->nonce, nonce);
tsk_strupdate(&binding->realm, realm);
/* Delete the message and response before retrying*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(request);
// Send again using new transaction identifier
return tnet_stun_send_bind(context, binding);
}
else {
ret = -3;
}
}
else {
ret = -2;
}
}
else {
const tnet_stun_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
*
* Public function to create a binding context.
*
* @param [in,out] nat_context The NAT context.
* @param localFD The local file descriptor for which to create the binding context.
* @param [in,out] nat_context The NAT context.
* @param localFD The local file descriptor for which to create the binding context.
*
* @return A valid binding id if succeed and @ref TNET_STUN_INVALID_BINDING_ID otherwise. If the returned id is valid then
* the newly created binding will contain the server reflexive address associated to the local file descriptor.
**/
tnet_stun_binding_id_t tnet_stun_bind(const tnet_nat_context_t* nat_context, tnet_fd_t localFD)
{
tnet_stun_binding_id_t id = 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
* Compares two transaction ids.
*
* @param id1 The first transaction identifier.
* @param id2 The second transaction identifier.
* @param id1 The first transaction identifier.
* @param id2 The second transaction identifier.
*
* @return Zero if the two identifiers are equal and non-zero value otherwise.
**/
int tnet_stun_transacid_cmp(const tnet_stun_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);
server_address = tsk_strdup(va_arg(*app, const char*));
binding->localFD = va_arg(*app, tnet_fd_t);
binding->socket_type = va_arg(*app, tnet_socket_type_t);
server_address = tsk_strdup(va_arg(*app, const char*));
#if defined(__GNUC__)
server_port = (tnet_port_t)va_arg(*app, unsigned);
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*));
if(server_address){
tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
}
binding->username = tsk_strdup(va_arg(*app, const char*));
binding->password = tsk_strdup(va_arg(*app, const char*));
binding->software = tsk_strdup(TNET_SOFTWARE);
}
return self;
if(server_address) {
tnet_sockaddr_init(server_address, server_port, binding->socket_type, &binding->server);
}
binding->software = tsk_strdup(TNET_SOFTWARE);
}
return self;
}
static tsk_object_t* tnet_stun_binding_dtor(tsk_object_t * self)
{
tnet_stun_binding_t *binding = self;
if(binding){
TSK_FREE(binding->username);
TSK_FREE(binding->password);
TSK_FREE(binding->realm);
TSK_FREE(binding->nonce);
{
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

@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@ -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

@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@ -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;
char* value;
typedef struct tnet_stun_attribute_username_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_username_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_username_def_t;
@ -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;
tsk_sha1digest_t sha1digest;
typedef struct tnet_stun_attribute_integrity_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_sha1digest_t sha1digest;
}
tnet_stun_attribute_integrity_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
@ -213,132 +206,121 @@ TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_integrity_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.5. FINGERPRINT.
*/
typedef struct tnet_stun_attribute_fingerprint_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
typedef struct tnet_stun_attribute_fingerprint_s {
TNET_STUN_DECLARE_ATTRIBUTE;
uint32_t value;
}
tnet_stun_attribute_fingerprint_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_fingerprint_def_t;
/**@ingroup tnet_stun_group
*RFC 5389 - 15.6. ERROR-CODE
*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;
/**@ingroup tnet_stun_group
/**@ingroup tnet_stun_group
* RFC 5389 - 15.7. REALM. */
typedef struct tnet_stun_attribute_realm_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
typedef struct tnet_stun_attribute_realm_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_realm_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_realm_def_t;
/**@ingroup tnet_stun_group
/**@ingroup tnet_stun_group
* RFC 5389 - 15.8. NONCE. */
typedef struct tnet_stun_attribute_nonce_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
typedef struct tnet_stun_attribute_nonce_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char* value;
}
tnet_stun_attribute_nonce_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_nonce_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.9. UNKNOWN-ATTRIBUTES. */
typedef struct tnet_stun_attribute_unknowns_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_buffer_t *value;
typedef struct tnet_stun_attribute_unknowns_s {
TNET_STUN_DECLARE_ATTRIBUTE;
tsk_buffer_t *value;
}
tnet_stun_attribute_unknowns_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_unknowns_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.10. SOFTWARE. */
typedef struct tnet_stun_attribute_software_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
char *value;
typedef struct tnet_stun_attribute_software_s {
TNET_STUN_DECLARE_ATTRIBUTE;
char *value;
}
tnet_stun_attribute_software_t;
TINYNET_GEXTERN const tsk_object_def_t *tnet_stun_attribute_software_def_t;
/**@ingroup tnet_stun_group
* RFC 5389 - 15.11. ALTERNATE-SERVER. */
typedef struct tnet_stun_attribute_altserver_s
{
TNET_STUN_DECLARE_ATTRIBUTE;
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

@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@ -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;
if(!self){
goto bail;
}
output = tsk_buffer_create_null();
tsk_buffer_t *output = 0;
tnet_stun_attribute_t *attribute;
unsigned compute_integrity = self->integrity;
/* RFC 5389 - 6. STUN Message Structure
0 1 2 3
if(!self) {
goto bail;
}
output = tsk_buffer_create_null();
/* RFC 5389 - 6. STUN Message Structure
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0 0| STUN Message Type | Message Length |
@ -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);
}
/* Message Length ==> Will be updated after attributes have been added. */
{
static const uint16_t length = 0;
tsk_buffer_append(output, &(length), 2);
}
/* STUN Message Type
*/
{
uint16_t type = tnet_htons(self->type);
tsk_buffer_append(output, &(type), 2);
}
/* Magic Cookie
*/
{
uint32_t cookie = tnet_htonl(self->cookie);
tsk_buffer_append(output, &(cookie), 4);
}
/* Message Length ==> Will be updated after attributes have been added. */
{
static const uint16_t length = 0;
tsk_buffer_append(output, &(length), 2);
}
/* Magic Cookie
*/
{
uint32_t cookie = tnet_htonl(self->cookie);
tsk_buffer_append(output, &(cookie), 4);
}
/* Transaction ID (96 bits==>16bytes)
*/
tsk_buffer_append(output, self->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));
compute_integrity = !self->nointegrity;
}
else if(self->password){ // short term
compute_integrity = !self->nointegrity;
}
/* 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));
if(compute_integrity && self->username){
SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
}
compute_integrity = !self->nointegrity;
}
else if(self->password) { // short term
compute_integrity = !self->nointegrity;
}
/*=== 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);
}
}
if(compute_integrity && self->username) {
SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username));
}
/* 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;
/*=== 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;
#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*/);
*(((uint16_t*)output->data)+1) = tnet_htons(length);
}
if(compute_integrity) {
length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/);
}
/* MESSAGE-INTEGRITY */
if(compute_integrity){
/* RFC 5389 - 15.4. MESSAGE-INTEGRITY
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
*(((uint16_t*)output->data)+1) = tnet_htons(length);
}
For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
For short-term credentials ==> key = SASLprep(password)
*/
tsk_sha1digest_t hmac;
if(self->username && self->realm && self->password){ // long term
char* keystr = tsk_null;
tsk_md5digest_t md5;
tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
TSK_FREE(keystr);
}
else{ // short term
hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
}
/* MESSAGE-INTEGRITY */
if(compute_integrity) {
/* RFC 5389 - 15.4. MESSAGE-INTEGRITY
The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message.
SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
}
For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password))
For short-term credentials ==> key = SASLprep(password)
*/
// LENGTH
*(((uint16_t*)output->data) + 1) = tnet_htons((output->size - TNET_STUN_HEADER_SIZE + (self->fingerprint ? 8 : 0)));
tsk_sha1digest_t hmac;
/* 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);
}
if(self->username && self->realm && self->password) { // long term
char* keystr = tsk_null;
tsk_md5digest_t md5;
tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password);
TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5);
hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac);
TSK_FREE(keystr);
}
else { // short term
hmac_sha1digest_compute(output->data, output->size, self->password, tsk_strlen(self->password), hmac);
}
SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE);
}
// LENGTH
*(((uint16_t*)output->data) + 1) = tnet_htons((output->size - 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);
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;
}
@ -243,81 +244,80 @@ bail:
*
* Deserializes a STUN message from binary data.
*
* @param [in,out] data A pointer to the binary data.
* @param size The size of the binary data.
* @param [in,out] data A pointer to the binary data.
* @param size The size of the binary data.
*
* @retval A STUN message if deserialization succeed or NULL otherwise.
**/
tnet_stun_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;
}
dataPtr = (uint8_t*)data;
dataEnd = (dataPtr + size);
if(!data || (size < TNET_STUN_HEADER_SIZE) || !TNET_IS_STUN2_MSG(data, size)) {
goto bail;
}
message = tnet_stun_message_create_null();
dataPtr = (uint8_t*)data;
dataEnd = (dataPtr + size);
/* Message Type
*/
message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr);
dataPtr += 2;
message = tnet_stun_message_create_null();
/* Message Length
*/
message->length = tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Message Type
*/
message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Check message validity
*/
if((message->length + TNET_STUN_HEADER_SIZE) != size)
{
TSK_OBJECT_SAFE_FREE(message);
goto bail;
}
/* Message Length
*/
message->length = tnet_ntohs_2(dataPtr);
dataPtr += 2;
/* Magic Cookie
==> already set by the constructor and checked by @ref TNET_IS_STUN2
*/
dataPtr += 4;
/* Check message validity
*/
if((message->length + TNET_STUN_HEADER_SIZE) != size) {
TSK_OBJECT_SAFE_FREE(message);
goto bail;
}
/* Transaction ID
*/
memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
dataPtr += TNET_STUN_TRANSACID_SIZE;
/* Magic Cookie
==> already set by the constructor and checked by @ref TNET_IS_STUN2
*/
dataPtr += 4;
/* == 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.
/* Transaction ID
*/
memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE);
dataPtr += TNET_STUN_TRANSACID_SIZE;
dataPtr += att_size;
tsk_list_push_back_data(message->attributes, (void**)&attribute);
continue;
}
else{
continue;
}
}
/* == 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);
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;
{ // 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;
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;
}
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);
}
return self;
TSK_OBJECT_SAFE_FREE(message->attributes);
}
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

@ -2,19 +2,19 @@
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
@ -95,87 +95,84 @@ 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;
/**@ingroup tnet_stun_group
* List of all supported STUN methods.
* List of all supported STUN methods.
* RFC 5389 only define one method(Bining). All other methods have been defined
* by TURN (draft-ietf-behave-turn-16 and draft-ietf-behave-turn-tcp-05).
* by TURN (draft-ietf-behave-turn-16 and draft-ietf-behave-turn-tcp-05).
**/
typedef enum tnet_stun_method_type_e
{
stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
typedef enum tnet_stun_method_type_e {
stun_method_binding = 0x0001, /**< RFC 5389 - Binding method: 0b000000000001 */
stun_method_allocate = 0x0003, /**< draft-ietf-behave-turn-16 - Allocate (only request/response semantics defined) */
stun_method_refresh = 0x0004, /**< draft-ietf-behave-turn-16 - Refresh (only request/response semantics defined) */
stun_method_send = 0x0006, /**< draft-ietf-behave-turn-16 - Send (only indication semantics defined) */
stun_method_data = 0x0007, /**< draft-ietf-behave-turn-16 - Data (only indication semantics defined) */
stun_method_createpermission = 0x0008, /**< draft-ietf-behave-turn-16 - CreatePermission (only request/response semantics defined */
stun_method_channelbind = 0x0009, /**< draft-ietf-behave-turn-16 - ChannelBind (only request/response semantics defined) */
}
tnet_stun_method_type_t;
/**@ingroup tnet_stun_group
* List of all supported STUN types.
*/
typedef enum tnet_stun_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.
typedef enum tnet_stun_message_type_e {
/* RFC 5389 - 6. STUN Message Structure
The message type field is decomposed further into the following
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.
0 1
The message type field is decomposed further into the following
structure:
0 1
2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
|M |M |M|M|M|C|M|M|M|C|M|M|M|M|
|11|10|9|8|7|1|6|5|4|0|3|2|1|0|
+--+--+-+-+-+-+-+-+-+-+-+-+-+-+
*/
stun_binding_request = (stun_method_binding | TNET_STUN_CLASS_REQUEST_MASK),
stun_binding_indication = (stun_method_binding | TNET_STUN_CLASS_INDICATION_MASK),
stun_binding_success_response = (stun_method_binding | TNET_STUN_CLASS_SUCCESS_MASK),
stun_binding_error_response = (stun_method_binding | TNET_STUN_CLASS_ERROR_MASK),
*/
stun_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;
*/
unsigned fingerprint:1;
unsigned integrity:1;
unsigned dontfrag:1;
unsigned nointegrity:1;
tnet_stun_message_type_t type;
uint16_t length;
uint32_t cookie;
tnet_stun_transacid_t transaction_id;
char* username;
char* password;
char* realm;
char* nonce;
unsigned fingerprint:1;
unsigned integrity:1;
unsigned dontfrag:1;
unsigned nointegrity:1;
tnet_stun_attributes_L_t *attributes; /**< List of all attributes associated to this message */
char* username;
char* password;
char* realm;
char* nonce;
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

@ -1,63 +1,63 @@
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tinynet.h
* @brief API functions.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TINYNET_H
#define TNET_TINYNET_H
/* === tinySAK === */
#include "tsk.h"
/* === tinyNET === */
#include "tnet.h"
#include "tnet_endianness.h"
#include "tnet_nat.h"
#include "tnet_socket.h"
#include "tnet_transport.h"
#include "stun/tnet_stun.h"
#include "ice/tnet_ice_event.h"
#include "ice/tnet_ice_candidate.h"
#include "ice/tnet_ice_ctx.h"
#include "dns/tnet_dns.h"
#include "dns/tnet_dns_naptr.h"
#include "dns/tnet_dns_regexp.h"
#include "dns/tnet_dns_resolvconf.h"
#include "dhcp/tnet_dhcp.h"
#include "dhcp/tnet_dhcp_option_sip.h"
#include "dhcp6/tnet_dhcp6.h"
#include "dhcp6/tnet_dhcp6_option.h"
#endif /* TNET_TINYNET_H */
/*
* Copyright (C) 2010-2011 Mamadou Diop.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
/**@file tinynet.h
* @brief API functions.
*
* @author Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
*/
#ifndef TNET_TINYNET_H
#define TNET_TINYNET_H
/* === tinySAK === */
#include "tsk.h"
/* === tinyNET === */
#include "tnet.h"
#include "tnet_endianness.h"
#include "tnet_nat.h"
#include "tnet_socket.h"
#include "tnet_transport.h"
#include "stun/tnet_stun.h"
#include "ice/tnet_ice_event.h"
#include "ice/tnet_ice_candidate.h"
#include "ice/tnet_ice_ctx.h"
#include "dns/tnet_dns.h"
#include "dns/tnet_dns_naptr.h"
#include "dns/tnet_dns_regexp.h"
#include "dns/tnet_dns_resolvconf.h"
#include "dhcp/tnet_dhcp.h"
#include "dhcp/tnet_dhcp_option_sip.h"
#include "dhcp6/tnet_dhcp6.h"
#include "dhcp6/tnet_dhcp6_option.h"
#endif /* TNET_TINYNET_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,26 +1,23 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
*/
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

View File

@ -1,38 +1,35 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#ifndef TEST_TNET_STDAFX_H
#define TEST_TNET_STDAFX_H
#ifdef WIN32
#include "targetver.h"
#endif
#include <stdio.h>
#include <string.h>
//#include <tchar.h>
// TODO: reference additional headers your program requires here
#endif /* TEST_TNET_STDAFX_H */
*/
#ifndef TEST_TNET_STDAFX_H
#define TEST_TNET_STDAFX_H
#ifdef WIN32
#include "targetver.h"
#endif
#include <stdio.h>
#include <string.h>
//#include <tchar.h>
// TODO: reference additional headers your program requires here
#endif /* TEST_TNET_STDAFX_H */

View File

@ -1,15 +1,33 @@
#ifndef TNET_TEST_TARGETVER_H
#define TNET_TEST_TARGETVER_H
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
/* 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
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#endif /* TNET_TEST_TARGETVER_H */

View File

@ -1,122 +1,121 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with DOUBANGO.
*
*/
#include "stdafx.h"
#include "tsk.h"
#include "tinynet.h"
#include "test_sockets.h"
#include "test_transport.h"
#include "test_auth.h"
#include "test_stun.h"
#include "test_nat.h"
#include "test_ifaces.h"
#include "test_dns.h"
#include "test_ice.h"
#include "test_dhcp.h"
#include "test_dhcp6.h"
#include "test_tls.h"
#define RUN_TEST_LOOP 0
#define RUN_TEST_ALL 0
#define RUN_TEST_SOCKETS 0 /* FIXME: Android */
#define RUN_TEST_TRANSPORT 0
#define RUN_TEST_AUTH 0
#define RUN_TEST_STUN 1
#define RUN_TEST_ICE 0
#define RUN_TEST_NAT 0
#define RUN_TEST_IFACES 0
#define RUN_TEST_DNS 0
#define RUN_TEST_DHCP 0
#define RUN_TEST_DHCP6 0
#define RUN_TEST_TLS 0
#ifdef _WIN32_WCE
int _tmain(int argc, _TCHAR* argv[])
#else
int main()
#endif
{
/* Startup the network stack. */
if(tnet_startup()){
return -1;
}
#if RUN_TEST_LOOP
for(;;)
#endif
{
#if RUN_TEST_ALL || RUN_TEST_SOCKETS
test_sockets();
#endif
#if RUN_TEST_ALL || RUN_TEST_TRANSPORT
test_transport();
#endif
#if RUN_TEST_ALL || RUN_TEST_AUTH
test_auth();
#endif
#if RUN_TEST_ALL || RUN_TEST_STUN
test_stun();
#endif
#if RUN_TEST_ALL || RUN_TEST_ICE
test_ice();
#endif
#if RUN_TEST_ALL || RUN_TEST_NAT
test_nat();
#endif
#if RUN_TEST_ALL || RUN_TEST_IFACES
test_ifaces();
#endif
#if RUN_TEST_ALL || RUN_TEST_DNS
test_dns();
#endif
#if RUN_TEST_ALL || RUN_TEST_DHCP
test_dhcp();
#endif
#if RUN_TEST_ALL || RUN_TEST_DHCP6
test_dhcp6();
#endif
#if RUN_TEST_ALL || RUN_TEST_TLS
test_tls();
#endif
}
/* Cleanup the network stack */
tnet_cleanup();
return 0;
}
*/
#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"
#include "test_sockets.h"
#include "test_transport.h"
#include "test_auth.h"
#include "test_stun.h"
#include "test_nat.h"
#include "test_ifaces.h"
#include "test_dns.h"
#include "test_ice.h"
#include "test_dhcp.h"
#include "test_dhcp6.h"
#include "test_tls.h"
#define RUN_TEST_LOOP 0
#define RUN_TEST_ALL 0
#define RUN_TEST_SOCKETS 0 /* FIXME: Android */
#define RUN_TEST_TRANSPORT 0
#define RUN_TEST_AUTH 0
#define RUN_TEST_STUN 1
#define RUN_TEST_ICE 0
#define RUN_TEST_NAT 0
#define RUN_TEST_IFACES 0
#define RUN_TEST_DNS 0
#define RUN_TEST_DHCP 0
#define RUN_TEST_DHCP6 0
#define RUN_TEST_TLS 0
#ifdef _WIN32_WCE
int _tmain(int argc, _TCHAR* argv[])
#else
int main()
#endif
{
/* Startup the network stack. */
if(tnet_startup()){
return -1;
}
#if RUN_TEST_LOOP
for(;;)
#endif
{
#if RUN_TEST_ALL || RUN_TEST_SOCKETS
test_sockets();
#endif
#if RUN_TEST_ALL || RUN_TEST_TRANSPORT
test_transport();
#endif
#if RUN_TEST_ALL || RUN_TEST_AUTH
test_auth();
#endif
#if RUN_TEST_ALL || RUN_TEST_STUN
test_stun();
#endif
#if RUN_TEST_ALL || RUN_TEST_ICE
test_ice();
#endif
#if RUN_TEST_ALL || RUN_TEST_NAT
test_nat();
#endif
#if RUN_TEST_ALL || RUN_TEST_IFACES
test_ifaces();
#endif
#if RUN_TEST_ALL || RUN_TEST_DNS
test_dns();
#endif
#if RUN_TEST_ALL || RUN_TEST_DHCP
test_dhcp();
#endif
#if RUN_TEST_ALL || RUN_TEST_DHCP6
test_dhcp6();
#endif
#if RUN_TEST_ALL || RUN_TEST_TLS
test_tls();
#endif
}
/* Cleanup the network stack */
tnet_cleanup();
return 0;
}

View File

@ -1,31 +1,28 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_AUTH_H
#define TNET_TEST_AUTH_H
void test_auth()
{
}
#endif /* TNET_TEST_AUTH_H */
*/
#ifndef TNET_TEST_AUTH_H
#define TNET_TEST_AUTH_H
void test_auth()
{
}
#endif /* TNET_TEST_AUTH_H */

View File

@ -1,121 +1,118 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_DHCP_H
#define TNET_TEST_DHCP_H
void test_dhcp_discover(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_offer(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_request(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_inform(tnet_dhcp_ctx_t *ctx)
{
tnet_dhcp_params_t *params = tsk_null;
tnet_dhcp_reply_t *reply = tsk_null;
params = tnet_dhcp_params_create();
tnet_dhcp_params_add_code(params, dhcp_code_SIP_Servers_DHCP_Option); /* SIP Servers */
tnet_dhcp_params_add_code(params, dhcp_code_Domain_Server); /* DNS Server */
reply = tnet_dhcp_query_inform(ctx, params);
if(reply && !TNET_DHCP_MESSAGE_IS_REPLY(reply)){
TSK_DEBUG_ERROR("DHCP request is not expected in response to a request.");
goto bail;
}
if(reply){
switch(reply->type)
{
case dhcp_type_ack:
{
tsk_list_item_t *item;
TSK_DEBUG_INFO("DHCP response type ==> ACK.");
tsk_list_foreach(item, reply->options)
{
const tnet_dhcp_option_t *option = item->data;
/* SIP SERVERS */
if(option->code == dhcp_code_SIP_Servers_DHCP_Option)
{
tsk_list_item_t *item2;
const tnet_dhcp_option_sip_t *option_sip4 = (const tnet_dhcp_option_sip_t*)option;;
tsk_list_foreach(item2, option_sip4->servers)
{
const tsk_string_t *str = item2->data;
TSK_DEBUG_INFO("DHCP-SIP_SERVER ==>%s", str->value);
}
}
/* DNS SERVERS */
if(option->code == dhcp_code_Domain_Server)
{
tsk_list_item_t *item2;
const tnet_dhcp_option_dns_t *option_dns = (const tnet_dhcp_option_dns_t*)option;;
tsk_list_foreach(item2, option_dns->servers)
{
const tsk_string_t *str = item2->data;
TSK_DEBUG_INFO("DHCP-DNS_SERVER ==>%s", str->value);
}
}
}
break;
}
default:
{
break;
}
}
}
else
{
TSK_DEBUG_ERROR("DHCP reply is NULL.");
goto bail;
}
bail:
TSK_OBJECT_SAFE_FREE(reply);
TSK_OBJECT_SAFE_FREE(params);
//tsk_thread_sleep(1000);
}
void test_dhcp()
{
tnet_dhcp_ctx_t *ctx = tnet_dhcp_ctx_create();
test_dhcp_inform(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_DHCP_H */
*/
#ifndef TNET_TEST_DHCP_H
#define TNET_TEST_DHCP_H
void test_dhcp_discover(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_offer(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_request(tnet_dhcp_ctx_t *ctx)
{
}
void test_dhcp_inform(tnet_dhcp_ctx_t *ctx)
{
tnet_dhcp_params_t *params = tsk_null;
tnet_dhcp_reply_t *reply = tsk_null;
params = tnet_dhcp_params_create();
tnet_dhcp_params_add_code(params, dhcp_code_SIP_Servers_DHCP_Option); /* SIP Servers */
tnet_dhcp_params_add_code(params, dhcp_code_Domain_Server); /* DNS Server */
reply = tnet_dhcp_query_inform(ctx, params);
if(reply && !TNET_DHCP_MESSAGE_IS_REPLY(reply)){
TSK_DEBUG_ERROR("DHCP request is not expected in response to a request.");
goto bail;
}
if(reply){
switch(reply->type)
{
case dhcp_type_ack:
{
tsk_list_item_t *item;
TSK_DEBUG_INFO("DHCP response type ==> ACK.");
tsk_list_foreach(item, reply->options)
{
const tnet_dhcp_option_t *option = item->data;
/* SIP SERVERS */
if(option->code == dhcp_code_SIP_Servers_DHCP_Option)
{
tsk_list_item_t *item2;
const tnet_dhcp_option_sip_t *option_sip4 = (const tnet_dhcp_option_sip_t*)option;;
tsk_list_foreach(item2, option_sip4->servers)
{
const tsk_string_t *str = item2->data;
TSK_DEBUG_INFO("DHCP-SIP_SERVER ==>%s", str->value);
}
}
/* DNS SERVERS */
if(option->code == dhcp_code_Domain_Server)
{
tsk_list_item_t *item2;
const tnet_dhcp_option_dns_t *option_dns = (const tnet_dhcp_option_dns_t*)option;;
tsk_list_foreach(item2, option_dns->servers)
{
const tsk_string_t *str = item2->data;
TSK_DEBUG_INFO("DHCP-DNS_SERVER ==>%s", str->value);
}
}
}
break;
}
default:
{
break;
}
}
}
else
{
TSK_DEBUG_ERROR("DHCP reply is NULL.");
goto bail;
}
bail:
TSK_OBJECT_SAFE_FREE(reply);
TSK_OBJECT_SAFE_FREE(params);
//tsk_thread_sleep(1000);
}
void test_dhcp()
{
tnet_dhcp_ctx_t *ctx = tnet_dhcp_ctx_create();
test_dhcp_inform(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_DHCP_H */

View File

@ -1,51 +1,48 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_DHCP6_H
#define TNET_TEST_DHCP6_H
void test_dhcp6_requestinfo(tnet_dhcp6_ctx_t *ctx)
{
tnet_dhcp6_option_orequest_t *orequest = tnet_dhcp6_option_orequest_create_null();
tnet_dhcp6_reply_t* reply = 0;
tnet_dhcp6_option_orequest_add_code(orequest, 24);
tnet_dhcp6_option_orequest_add_code(orequest, 23);
tnet_dhcp6_option_orequest_add_code(orequest, 21); /* SIP Servers Domain Name List */
tnet_dhcp6_option_orequest_add_code(orequest, 22); /* SIP Servers IPv6 Address List */
reply = tnet_dhcp6_requestinfo(ctx, orequest);
TSK_OBJECT_SAFE_FREE(orequest);
TSK_OBJECT_SAFE_FREE(reply);
}
void test_dhcp6()
{
tnet_dhcp6_ctx_t *ctx = tnet_dhcp6_ctx_create();
test_dhcp6_requestinfo(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_DHCP6_H */
*/
#ifndef TNET_TEST_DHCP6_H
#define TNET_TEST_DHCP6_H
void test_dhcp6_requestinfo(tnet_dhcp6_ctx_t *ctx)
{
tnet_dhcp6_option_orequest_t *orequest = tnet_dhcp6_option_orequest_create_null();
tnet_dhcp6_reply_t* reply = 0;
tnet_dhcp6_option_orequest_add_code(orequest, 24);
tnet_dhcp6_option_orequest_add_code(orequest, 23);
tnet_dhcp6_option_orequest_add_code(orequest, 21); /* SIP Servers Domain Name List */
tnet_dhcp6_option_orequest_add_code(orequest, 22); /* SIP Servers IPv6 Address List */
reply = tnet_dhcp6_requestinfo(ctx, orequest);
TSK_OBJECT_SAFE_FREE(orequest);
TSK_OBJECT_SAFE_FREE(reply);
}
void test_dhcp6()
{
tnet_dhcp6_ctx_t *ctx = tnet_dhcp6_ctx_create();
test_dhcp6_requestinfo(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_DHCP6_H */

View File

@ -1,227 +1,224 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_DNS_H
#define TNET_TEST_DNS_H
//#include "tnet_utils.h" /* tnet_address_t */
void test_dns_query()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
tnet_dns_response_t *response = tsk_null;
const tsk_list_item_t* item;
const tnet_dns_rr_t* rr;
//if((response = tnet_dns_resolve(ctx, "_sip._udp.sip2sip.info", qclass_in, qtype_srv)))
if((response = tnet_dns_resolve(ctx, "sip2sip.info", qclass_in, qtype_naptr)))
{
if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
TSK_DEBUG_INFO("We got a success response from the DNS server.");
// loop through the answers
tsk_list_foreach(item, response->Answers){
rr = item->data;
if(rr->qtype == qtype_naptr){
const tnet_dns_naptr_t *naptr = (const tnet_dns_naptr_t*)rr;
TSK_DEBUG_INFO("order=%u pref=%u flags=%s services=%s regexp=%s replacement=%s",
naptr->order,
naptr->preference,
naptr->flags,
naptr->services,
naptr->regexp,
naptr->replacement);
}
}
}
else{
TSK_DEBUG_ERROR("We got an error response from the DNS server. Erro code: %u", response->Header.RCODE);
}
}
tnet_dns_cache_clear(ctx);
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_dns_srv()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
char* hostname = 0;
tnet_port_t port = 0;
if(!tnet_dns_query_srv(ctx, "_sip._udp.sip2sip.info", &hostname, &port)){
TSK_DEBUG_INFO("DNS SRV succeed ==> hostname=%s and port=%u", hostname, port);
}
TSK_FREE(hostname);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_dns_naptr_srv()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
char* hostname = tsk_null;
tnet_port_t port = 0;
if(!tnet_dns_query_naptr_srv(ctx, "sip2sip.info", "SIP+D2U", &hostname, &port)){
TSK_DEBUG_INFO("DNS NAPTR+SRV succeed ==> hostname=%s and port=%u", hostname, port);
}
TSK_FREE(hostname);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_enum()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
tnet_dns_response_t* response = tsk_null;
// const tsk_list_item_t* item;
// const tnet_dns_naptr_t* record;
char* uri = tsk_null;
const char* e164num = "+1-800-555-5555";
//const char* e164num = "+33660188661";
//tnet_dns_add_server(ctx, "192.168.16.9");
//if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
TSK_DEBUG_INFO("URI=%s", uri);
TSK_FREE(uri);
}
else{
TSK_DEBUG_ERROR("ENUM(%s) failed", e164num);
}
/*if((response = tnet_dns_enum(ctx, "+1-800-555-5555", "e164.org"))){
if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
TSK_DEBUG_INFO("We got a success response from the DNS server.");
// loop through the answers
tsk_list_foreach(item, response->Answers){
record = item->data;
TSK_DEBUG_INFO("order=%u pref=%u flags=%s services=%s regexp=%s replacement=%s",
record->order,
record->preference,
record->flags,
record->services,
record->regexp,
record->replacement);
}
}
else{
TSK_DEBUG_ERROR("We got an error response from the DNS server. Erro code: %u", response->Header.RCODE);
}
}*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
typedef struct regexp_test_s{
const char* e164num;
const char* regexp;
const char* xres;
}
regexp_test_t;
regexp_test_t regexp_tests[] = {
"+18005551234", "!^.*$!sip:customer-service@example.com!i", "sip:customer-service@example.com",
"+18005551234", "!^.*$!mailto:information@example.com!i", "mailto:information@example.com",
"+18005555555", "!^\\+1800(.*)$!sip:1641641800\\1@tollfree.sip-happens.com!", "sip:16416418005555555@tollfree.sip-happens.com",
"+18005555555", "!^\\+1800(.*)$!sip:1641641800\\1@sip.tollfreegateway.com!", "sip:16416418005555555@sip.tollfreegateway.com",
"+468971234", "!^+46(.*)$!ldap://ldap.telco.se/cn=0\\1!", "ldap://ldap.telco.se/cn=08971234",
"+468971234", "!^+46(.*)$!mailto:spam@paf.se!", "mailto:spam@paf.se",
"urn:cid:199606121851.1@bar.example.com", "!!^urn:cid:.+@([^\\.]+\\.)(.*)$!\\2!i", "example.com",
};
void test_regex()
{
char* ret;
size_t i;
for(i=0; i< sizeof(regexp_tests)/sizeof(regexp_test_t); i++)
{
if((ret = tnet_dns_regex_parse(regexp_tests[i].e164num, regexp_tests[i].regexp))){
TSK_DEBUG_INFO("ENUM(%s) = %s", regexp_tests[i].e164num, ret);
if(!tsk_strequals(ret, regexp_tests[i].xres)){
TSK_DEBUG_ERROR("Failed to match ENUM(%s)", regexp_tests[i].e164num);
}
TSK_FREE(ret);
}
else{
TSK_DEBUG_ERROR("Failed to parse ENUM(%s)", regexp_tests[i].e164num);
}
TSK_DEBUG_INFO("---------");
}
}
void test_resolvconf()
{
tnet_addresses_L_t * servers;
const tnet_address_t* address;
const tsk_list_item_t* item;
const char* path = "C:\\tmp\\resolv32.conf";
//const char* path = "C:\\tmp\\resolv.conf";
//const char* path = "/etc/resolv.conf";
if((servers = tnet_dns_resolvconf_parse(path))){
tsk_list_foreach(item, servers){
address = item->data;
TSK_DEBUG_INFO("DNS Server host=%s Family=%d", address->ip, address->family);
}
TSK_OBJECT_SAFE_FREE(servers);
}
else{
TSK_DEBUG_ERROR("Failed to parse DNS servers from %s.", path);
}
}
void test_dns()
{
test_dns_naptr_srv();
//test_dns_srv();
//test_dns_query();
//test_enum();
//test_regex();
//test_resolvconf();
}
#endif /* TNET_TEST_DNS_H */
*/
#ifndef TNET_TEST_DNS_H
#define TNET_TEST_DNS_H
//#include "tnet_utils.h" /* tnet_address_t */
void test_dns_query()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
tnet_dns_response_t *response = tsk_null;
const tsk_list_item_t* item;
const tnet_dns_rr_t* rr;
//if((response = tnet_dns_resolve(ctx, "_sip._udp.sip2sip.info", qclass_in, qtype_srv)))
if((response = tnet_dns_resolve(ctx, "sip2sip.info", qclass_in, qtype_naptr)))
{
if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
TSK_DEBUG_INFO("We got a success response from the DNS server.");
// loop through the answers
tsk_list_foreach(item, response->Answers){
rr = item->data;
if(rr->qtype == qtype_naptr){
const tnet_dns_naptr_t *naptr = (const tnet_dns_naptr_t*)rr;
TSK_DEBUG_INFO("order=%u pref=%u flags=%s services=%s regexp=%s replacement=%s",
naptr->order,
naptr->preference,
naptr->flags,
naptr->services,
naptr->regexp,
naptr->replacement);
}
}
}
else{
TSK_DEBUG_ERROR("We got an error response from the DNS server. Erro code: %u", response->Header.RCODE);
}
}
tnet_dns_cache_clear(ctx);
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_dns_srv()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
char* hostname = 0;
tnet_port_t port = 0;
if(!tnet_dns_query_srv(ctx, "_sip._udp.sip2sip.info", &hostname, &port)){
TSK_DEBUG_INFO("DNS SRV succeed ==> hostname=%s and port=%u", hostname, port);
}
TSK_FREE(hostname);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_dns_naptr_srv()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
char* hostname = tsk_null;
tnet_port_t port = 0;
if(!tnet_dns_query_naptr_srv(ctx, "sip2sip.info", "SIP+D2U", &hostname, &port)){
TSK_DEBUG_INFO("DNS NAPTR+SRV succeed ==> hostname=%s and port=%u", hostname, port);
}
TSK_FREE(hostname);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
void test_enum()
{
tnet_dns_ctx_t *ctx = tnet_dns_ctx_create();
tnet_dns_response_t* response = tsk_null;
// const tsk_list_item_t* item;
// const tnet_dns_naptr_t* record;
char* uri = tsk_null;
const char* e164num = "+1-800-555-5555";
//const char* e164num = "+33660188661";
//tnet_dns_add_server(ctx, "192.168.16.9");
//if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
if((uri = tnet_dns_enum_2(ctx, "E2U+SIP", e164num, "e164.org"))){
TSK_DEBUG_INFO("URI=%s", uri);
TSK_FREE(uri);
}
else{
TSK_DEBUG_ERROR("ENUM(%s) failed", e164num);
}
/*if((response = tnet_dns_enum(ctx, "+1-800-555-5555", "e164.org"))){
if(TNET_DNS_RESPONSE_IS_SUCCESS(response)){
TSK_DEBUG_INFO("We got a success response from the DNS server.");
// loop through the answers
tsk_list_foreach(item, response->Answers){
record = item->data;
TSK_DEBUG_INFO("order=%u pref=%u flags=%s services=%s regexp=%s replacement=%s",
record->order,
record->preference,
record->flags,
record->services,
record->regexp,
record->replacement);
}
}
else{
TSK_DEBUG_ERROR("We got an error response from the DNS server. Erro code: %u", response->Header.RCODE);
}
}*/
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(ctx);
tsk_thread_sleep(2000);
}
typedef struct regexp_test_s{
const char* e164num;
const char* regexp;
const char* xres;
}
regexp_test_t;
regexp_test_t regexp_tests[] = {
"+18005551234", "!^.*$!sip:customer-service@example.com!i", "sip:customer-service@example.com",
"+18005551234", "!^.*$!mailto:information@example.com!i", "mailto:information@example.com",
"+18005555555", "!^\\+1800(.*)$!sip:1641641800\\1@tollfree.sip-happens.com!", "sip:16416418005555555@tollfree.sip-happens.com",
"+18005555555", "!^\\+1800(.*)$!sip:1641641800\\1@sip.tollfreegateway.com!", "sip:16416418005555555@sip.tollfreegateway.com",
"+468971234", "!^+46(.*)$!ldap://ldap.telco.se/cn=0\\1!", "ldap://ldap.telco.se/cn=08971234",
"+468971234", "!^+46(.*)$!mailto:spam@paf.se!", "mailto:spam@paf.se",
"urn:cid:199606121851.1@bar.example.com", "!!^urn:cid:.+@([^\\.]+\\.)(.*)$!\\2!i", "example.com",
};
void test_regex()
{
char* ret;
size_t i;
for(i=0; i< sizeof(regexp_tests)/sizeof(regexp_test_t); i++)
{
if((ret = tnet_dns_regex_parse(regexp_tests[i].e164num, regexp_tests[i].regexp))){
TSK_DEBUG_INFO("ENUM(%s) = %s", regexp_tests[i].e164num, ret);
if(!tsk_strequals(ret, regexp_tests[i].xres)){
TSK_DEBUG_ERROR("Failed to match ENUM(%s)", regexp_tests[i].e164num);
}
TSK_FREE(ret);
}
else{
TSK_DEBUG_ERROR("Failed to parse ENUM(%s)", regexp_tests[i].e164num);
}
TSK_DEBUG_INFO("---------");
}
}
void test_resolvconf()
{
tnet_addresses_L_t * servers;
const tnet_address_t* address;
const tsk_list_item_t* item;
const char* path = "C:\\tmp\\resolv32.conf";
//const char* path = "C:\\tmp\\resolv.conf";
//const char* path = "/etc/resolv.conf";
if((servers = tnet_dns_resolvconf_parse(path))){
tsk_list_foreach(item, servers){
address = item->data;
TSK_DEBUG_INFO("DNS Server host=%s Family=%d", address->ip, address->family);
}
TSK_OBJECT_SAFE_FREE(servers);
}
else{
TSK_DEBUG_ERROR("Failed to parse DNS servers from %s.", path);
}
}
void test_dns()
{
test_dns_naptr_srv();
//test_dns_srv();
//test_dns_query();
//test_enum();
//test_regex();
//test_resolvconf();
}
#endif /* TNET_TEST_DNS_H */

View File

@ -1,146 +1,144 @@
/*
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
static int tnet_ice_callback(const tnet_ice_event_t *e)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES, "ice-ufrag", "ice-pwd", tsk_true, tsk_false);
}
break;
}
}
return 0;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
static const tsk_bool_t use_ice_jingle = tsk_false;
static const tsk_bool_t use_video = tsk_false;
long a = tnet_htonl(0x6b0c76a7);
long b = tnet_htonl(0x034aa76b);
long c = tnet_htonl(0x510da598);
ctx = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_set_stun(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
getchar();
ret = tnet_ice_ctx_stop(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_ICE_H */
/*
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
static int tnet_ice_callback(const tnet_ice_event_t *e)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
}
break;
}
}
return 0;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
ctx = tnet_ice_ctx_create(use_ipv6, use_rtcp, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_stun_configure(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
getchar();
ret = tnet_ice_ctx_stop(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_ICE_H */
*/
#ifndef TNET_TEST_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
static int tnet_ice_callback(const tnet_ice_event_t *e)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES, "ice-ufrag", "ice-pwd", tsk_true, tsk_false);
}
break;
}
}
return 0;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
static const tsk_bool_t use_ice_jingle = tsk_false;
static const tsk_bool_t use_video = tsk_false;
long a = tnet_htonl(0x6b0c76a7);
long b = tnet_htonl(0x034aa76b);
long c = tnet_htonl(0x510da598);
ctx = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_set_stun(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
getchar();
ret = tnet_ice_ctx_stop(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_ICE_H */
/*
* Copyright (C) 2012 Doubango Telecom <http://www.doubango.org>
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_ICE_H
#define TNET_TEST_ICE_H
#define ICE_CANDIDATES "1 1 udp 1 192.168.196.1 57806 typ host name video_rtcp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username StFEVThMK2DHThkv password qkhKUDr4WqKRwZTo generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57808 typ srflx name video_rtcp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username 9ONjPsYvSFh0JvAc password rDHSkokdvp9dyXqQ generation 0\r\n" \
"1 1 udp 1 192.168.196.1 57809 typ prflx name video_rtp network_name {0C0137CC-DB78-46B6-9B6C-7E097FFA79FE} username S1vDZTVVky3r0pT+ password XgLb+H9uofxuWg7G generation 0\r\n" \
"1 2 udp 1 192.168.211.1 57811 typ relay name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n" \
"1 1 udp 1 192.168.211.1 57811 typ token name video_rtp network_name {F53974D9-C92C-4644-AF7A-EA09D29BD5A5} username x64BhO4BXjBFkpz2 password ZwHhRhu0KU9R6iWd generation 0\r\n"
static int tnet_ice_callback(const tnet_ice_event_t *e)
{
TSK_DEBUG_INFO("ICE callback: %s", e->phrase);
switch(e->type)
{
case tnet_ice_event_type_gathering_completed:
{
struct tnet_ice_ctx_s *ctx;
if((ctx = (struct tnet_ice_ctx_s *)e->userdata)){
tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
}
break;
}
}
return 0;
}
void test_ice()
{
struct tnet_ice_ctx_s *ctx;
int ret;
static const tsk_bool_t use_ipv6 = tsk_false;
static const tsk_bool_t use_rtcp = tsk_true;
ctx = tnet_ice_ctx_create(use_ipv6, use_rtcp, tnet_ice_callback, tsk_null);
tnet_ice_ctx_set_userdata(ctx, ctx);
ret = tnet_ice_ctx_stun_configure(ctx, "numb.viagenie.ca", 3478, "Doubango", "bossiel@yahoo.fr", "stun-password");
ret = tnet_ice_ctx_start(ctx);
// ret = tnet_ice_ctx_set_remote_candidates(ctx, ICE_CANDIDATES);
getchar();
ret = tnet_ice_ctx_stop(ctx);
TSK_OBJECT_SAFE_FREE(ctx);
}
#endif /* TNET_TEST_ICE_H */

View File

@ -1,102 +1,99 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_IFACES_H
#define TNET_TEST_IFACES_H
void test_faces_bestsource()
{
tnet_ip_t source;
// IPv6
if(!tnet_getbestsource("fe80::fe4c:3ea1", 5060, tnet_socket_type_udp_ipv6, &source)){
TSK_DEBUG_INFO("Best IPv6 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv6 source.");
}
// IPv6
if(!tnet_getbestsource("2a01:e35:8b32:7050:212:f0ff:fe4c:3ea1", 5060, tnet_socket_type_udp_ipv6, &source)){
TSK_DEBUG_INFO("Best IPv6 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv6 source.");
}
// IPv4
if(!tnet_getbestsource("192.168.0.11", 5060, tnet_socket_type_udp_ipv4, &source)){
TSK_DEBUG_INFO("Best IPv4 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv4 source.");
}
}
void test_ifaces_dump_ifaces()
{
tnet_interfaces_L_t* ifaces = tnet_get_interfaces();
tsk_list_item_t *item;
tsk_list_foreach(item, ifaces)
{
const tnet_interface_t *iface = item->data;
TSK_DEBUG_INFO("Interface: %s", iface->description);
}
TSK_OBJECT_SAFE_FREE(ifaces);
}
void test_ifaces_dump_addresses()
{
tnet_addresses_L_t* addresses = tnet_get_addresses_all();
tsk_list_item_t *item;
tsk_list_foreach(item, addresses)
{
const tnet_address_t *address = item->data;
if(address->anycast)
{
TSK_DEBUG_INFO("ANYCAST address: %s", address->ip);
}
else if(address->unicast)
{
TSK_DEBUG_INFO("UNICAST address: %s", address->ip);
}
else if(address->multicast)
{
TSK_DEBUG_INFO("MULTICAST address: %s", address->ip);
}
else if(address->dnsserver)
{
TSK_DEBUG_INFO("DNSSERVER address: %s", address->ip);
}
}
TSK_OBJECT_SAFE_FREE(addresses);
}
void test_ifaces()
{
test_faces_bestsource();
test_ifaces_dump_ifaces();
test_ifaces_dump_addresses();
}
#endif /* TNET_TEST_IFACES_H */
*/
#ifndef TNET_TEST_IFACES_H
#define TNET_TEST_IFACES_H
void test_faces_bestsource()
{
tnet_ip_t source;
// IPv6
if(!tnet_getbestsource("fe80::fe4c:3ea1", 5060, tnet_socket_type_udp_ipv6, &source)){
TSK_DEBUG_INFO("Best IPv6 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv6 source.");
}
// IPv6
if(!tnet_getbestsource("2a01:e35:8b32:7050:212:f0ff:fe4c:3ea1", 5060, tnet_socket_type_udp_ipv6, &source)){
TSK_DEBUG_INFO("Best IPv6 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv6 source.");
}
// IPv4
if(!tnet_getbestsource("192.168.0.11", 5060, tnet_socket_type_udp_ipv4, &source)){
TSK_DEBUG_INFO("Best IPv4 source is [%s]", source);
}
else{
TSK_DEBUG_ERROR("Failed to get best IPv4 source.");
}
}
void test_ifaces_dump_ifaces()
{
tnet_interfaces_L_t* ifaces = tnet_get_interfaces();
tsk_list_item_t *item;
tsk_list_foreach(item, ifaces)
{
const tnet_interface_t *iface = item->data;
TSK_DEBUG_INFO("Interface: %s", iface->description);
}
TSK_OBJECT_SAFE_FREE(ifaces);
}
void test_ifaces_dump_addresses()
{
tnet_addresses_L_t* addresses = tnet_get_addresses_all();
tsk_list_item_t *item;
tsk_list_foreach(item, addresses)
{
const tnet_address_t *address = item->data;
if(address->anycast)
{
TSK_DEBUG_INFO("ANYCAST address: %s", address->ip);
}
else if(address->unicast)
{
TSK_DEBUG_INFO("UNICAST address: %s", address->ip);
}
else if(address->multicast)
{
TSK_DEBUG_INFO("MULTICAST address: %s", address->ip);
}
else if(address->dnsserver)
{
TSK_DEBUG_INFO("DNSSERVER address: %s", address->ip);
}
}
TSK_OBJECT_SAFE_FREE(addresses);
}
void test_ifaces()
{
test_faces_bestsource();
test_ifaces_dump_ifaces();
test_ifaces_dump_addresses();
}
#endif /* TNET_TEST_IFACES_H */

View File

@ -1,219 +1,216 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_NAT_H
#define TNET_TEST_NAT_H
//stun.ekiga.net
//#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_USERNAME "xxxxx"
#define STUN_PASSWORD "xxxxx"
#define STUN_SERVER_PORT TNET_STUN_TCP_UDP_DEFAULT_PORT
#define STUN_SERVER_PROTO tnet_socket_type_udp_ipv4
void test_nat_stun()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
tnet_stun_binding_id_t bind_id1, bind_id2;
char* public_ip1 = 0, *public_ip2 = 0;
tnet_port_t public_port1 = 0, public_port2 = 0;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == BIND
*/
bind_id1 = tnet_nat_stun_bind(context, socket1->fd);
bind_id2 = tnet_nat_stun_bind(context, socket2->fd);
if(!TNET_STUN_IS_VALID_BINDING_ID(bind_id1) ||!TNET_STUN_IS_VALID_BINDING_ID(bind_id2))
{
TSK_DEBUG_ERROR("Failed to get public IP/port using stun");
goto bail;
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1))
{
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2))
{
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == UNBIND
*/
tnet_nat_stun_unbind(context, bind_id1);
tnet_nat_stun_unbind(context, bind_id2);
bail:
TSK_OBJECT_SAFE_FREE(socket1);
TSK_OBJECT_SAFE_FREE(socket2);
TSK_FREE(public_ip1);
TSK_FREE(public_ip1);
TSK_OBJECT_SAFE_FREE(context);
}
void test_nat_turn()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
tnet_turn_allocation_id_t alloc_id1, alloc_id2;
char* public_ip1 = 0, *public_ip2 = 0;
tnet_port_t public_port1 = 0, public_port2 = 0;
tnet_turn_channel_binding_id_t channel_id;
int ret;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == ALLOC
*/
alloc_id1 = tnet_nat_turn_allocate(context, socket1->fd);
alloc_id2 = tnet_nat_turn_allocate(context, socket2->fd);
if(!TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id1) || !TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id2))
{
TSK_DEBUG_ERROR("TURN allocation failed.");
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN allocation succeeded and id1=%llu and id2=%llu", alloc_id1, alloc_id2);
}
tsk_thread_sleep(2000);
/* == RETRIEVE STUN SERVER REFLEXIVE ADDRESSES
*/
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id1, &public_ip1, &public_port1))
{
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id2, &public_ip2, &public_port2))
{
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == CREATE PERMISSION
*/
//tnet_nat_turn_add_permission(context, alloc_id1, "192.168.0.11", 300);
/* == CHANNEL BINDING
*/
{
/* Try to bind (channel binding) to the socket1 to socket2 */
struct sockaddr_storage peer;
if((ret = tnet_sockaddr_init(public_ip2, public_port2, STUN_SERVER_PROTO, &peer)))
{
TSK_DEBUG_ERROR("Failed to init peer with error code %d.", ret);
}
else
{
channel_id = tnet_nat_turn_channel_bind(context, alloc_id1,&peer);
if(TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(channel_id))
{
TSK_DEBUG_INFO("TURN channel binding succeeded.");
/* Try to send data using the newly create channel */
if(tnet_nat_turn_channel_senddata(context, channel_id, "Doubango", strlen("Doubango")))
{
TSK_DEBUG_ERROR("Failed to send data using channel id [%u].", channel_id);
}
else
{
TSK_DEBUG_INFO("Data successfuly sent using channel if[%u].", channel_id);
}
}
else
{
TSK_DEBUG_ERROR("TURN channel binding failed.");
}
}
}
tsk_thread_sleep(2000);
/* == UNALLOC
*/
if((ret = tnet_nat_turn_unallocate(context, alloc_id1)) || (ret = tnet_nat_turn_unallocate(context, alloc_id2)))
{
TSK_DEBUG_ERROR("TURN unallocation failed with error code: %d.", ret);
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN unallocation succeeded.");
}
bail:
TSK_OBJECT_SAFE_FREE(socket1);
TSK_OBJECT_SAFE_FREE(socket2);
TSK_FREE(public_ip1);
TSK_FREE(public_ip1);
TSK_OBJECT_SAFE_FREE(context);
}
void test_nat()
{
test_nat_stun();
//test_nat_turn();
//tsk_thread_sleep(1000);
}
#endif /* TNET_TEST_NAT_H */
*/
#ifndef TNET_TEST_NAT_H
#define TNET_TEST_NAT_H
//stun.ekiga.net
//#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_SERVER_IP "numb.viagenie.ca"
#define STUN_USERNAME "xxxxx"
#define STUN_PASSWORD "xxxxx"
#define STUN_SERVER_PORT TNET_STUN_TCP_UDP_DEFAULT_PORT
#define STUN_SERVER_PROTO tnet_socket_type_udp_ipv4
void test_nat_stun()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
tnet_stun_binding_id_t bind_id1, bind_id2;
char* public_ip1 = 0, *public_ip2 = 0;
tnet_port_t public_port1 = 0, public_port2 = 0;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == BIND
*/
bind_id1 = tnet_nat_stun_bind(context, socket1->fd);
bind_id2 = tnet_nat_stun_bind(context, socket2->fd);
if(!TNET_STUN_IS_VALID_BINDING_ID(bind_id1) ||!TNET_STUN_IS_VALID_BINDING_ID(bind_id2))
{
TSK_DEBUG_ERROR("Failed to get public IP/port using stun");
goto bail;
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1))
{
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2))
{
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == UNBIND
*/
tnet_nat_stun_unbind(context, bind_id1);
tnet_nat_stun_unbind(context, bind_id2);
bail:
TSK_OBJECT_SAFE_FREE(socket1);
TSK_OBJECT_SAFE_FREE(socket2);
TSK_FREE(public_ip1);
TSK_FREE(public_ip1);
TSK_OBJECT_SAFE_FREE(context);
}
void test_nat_turn()
{
tnet_socket_t *socket1 = 0, *socket2 = 0;
tnet_nat_context_handle_t *context = 0;
tnet_turn_allocation_id_t alloc_id1, alloc_id2;
char* public_ip1 = 0, *public_ip2 = 0;
tnet_port_t public_port1 = 0, public_port2 = 0;
tnet_turn_channel_binding_id_t channel_id;
int ret;
if(!(socket1 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO))
|| !(socket2 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO)))
{
goto bail;
}
context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD);
if(tnet_nat_set_server_address(context, STUN_SERVER_IP))
{
TSK_DEBUG_ERROR("Failed to set STUN/TURN address.");
goto bail;
}
/* == ALLOC
*/
alloc_id1 = tnet_nat_turn_allocate(context, socket1->fd);
alloc_id2 = tnet_nat_turn_allocate(context, socket2->fd);
if(!TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id1) || !TNET_TURN_IS_VALID_ALLOCATION_ID(alloc_id2))
{
TSK_DEBUG_ERROR("TURN allocation failed.");
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN allocation succeeded and id1=%llu and id2=%llu", alloc_id1, alloc_id2);
}
tsk_thread_sleep(2000);
/* == RETRIEVE STUN SERVER REFLEXIVE ADDRESSES
*/
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id1, &public_ip1, &public_port1))
{
TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1);
}
if(!tnet_nat_turn_get_reflexive_address(context, alloc_id2, &public_ip2, &public_port2))
{
TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2);
}
/* == CREATE PERMISSION
*/
//tnet_nat_turn_add_permission(context, alloc_id1, "192.168.0.11", 300);
/* == CHANNEL BINDING
*/
{
/* Try to bind (channel binding) to the socket1 to socket2 */
struct sockaddr_storage peer;
if((ret = tnet_sockaddr_init(public_ip2, public_port2, STUN_SERVER_PROTO, &peer)))
{
TSK_DEBUG_ERROR("Failed to init peer with error code %d.", ret);
}
else
{
channel_id = tnet_nat_turn_channel_bind(context, alloc_id1,&peer);
if(TNET_TURN_IS_VALID_CHANNEL_BINDING_ID(channel_id))
{
TSK_DEBUG_INFO("TURN channel binding succeeded.");
/* Try to send data using the newly create channel */
if(tnet_nat_turn_channel_senddata(context, channel_id, "Doubango", strlen("Doubango")))
{
TSK_DEBUG_ERROR("Failed to send data using channel id [%u].", channel_id);
}
else
{
TSK_DEBUG_INFO("Data successfuly sent using channel if[%u].", channel_id);
}
}
else
{
TSK_DEBUG_ERROR("TURN channel binding failed.");
}
}
}
tsk_thread_sleep(2000);
/* == UNALLOC
*/
if((ret = tnet_nat_turn_unallocate(context, alloc_id1)) || (ret = tnet_nat_turn_unallocate(context, alloc_id2)))
{
TSK_DEBUG_ERROR("TURN unallocation failed with error code: %d.", ret);
goto bail;
}
else
{
TSK_DEBUG_INFO("TURN unallocation succeeded.");
}
bail:
TSK_OBJECT_SAFE_FREE(socket1);
TSK_OBJECT_SAFE_FREE(socket2);
TSK_FREE(public_ip1);
TSK_FREE(public_ip1);
TSK_OBJECT_SAFE_FREE(context);
}
void test_nat()
{
test_nat_stun();
//test_nat_turn();
//tsk_thread_sleep(1000);
}
#endif /* TNET_TEST_NAT_H */

View File

@ -1,64 +1,61 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_SOCKETS_H
#define TNET_TEST_SOCKETS_H
void test_sockets()
{
int test;
tnet_socket_tcp_t * tcp_socket;
tnet_socket_type_t type = tnet_socket_type_udp_ipv4;
struct sockaddr_storage to;
TNET_SOCKET_TYPE_SET_IPV4(type);
TNET_SOCKET_TYPE_SET_IPV6(type);
TNET_SOCKET_TYPE_SET_IPV4Only(type);
TNET_SOCKET_TYPE_SET_IPV6Only(type);
TNET_SOCKET_TYPE_SET_IPV6Only(type);
TNET_SOCKET_TYPE_SET_IPV4(type);
TNET_SOCKET_TYPE_SET_IPV6(type);
TNET_SOCKET_TYPE_SET_TLS(type);
TNET_SOCKET_TYPE_SET_UDP(type);
TNET_SOCKET_TYPE_SET_SCTP(type);
TNET_SOCKET_TYPE_SET_TCP(type);
tcp_socket = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, type);
if(!TNET_SOCKET_IS_VALID(tcp_socket))
{
TSK_OBJECT_SAFE_FREE(tcp_socket);
return;
}
//if(!(test = tnet_sockaddr_init("www.google.com", 80, type, &to))){
// test = tnet_sockfd_connetto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
//}
if(!(test = tnet_sockaddr_init("ipv6.google.com", 80, type, &to))){
test = tnet_sockfd_connectto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
}
TSK_OBJECT_SAFE_FREE(tcp_socket);
}
#endif /* TNET_TEST_SOCKETS_H */
*/
#ifndef TNET_TEST_SOCKETS_H
#define TNET_TEST_SOCKETS_H
void test_sockets()
{
int test;
tnet_socket_tcp_t * tcp_socket;
tnet_socket_type_t type = tnet_socket_type_udp_ipv4;
struct sockaddr_storage to;
TNET_SOCKET_TYPE_SET_IPV4(type);
TNET_SOCKET_TYPE_SET_IPV6(type);
TNET_SOCKET_TYPE_SET_IPV4Only(type);
TNET_SOCKET_TYPE_SET_IPV6Only(type);
TNET_SOCKET_TYPE_SET_IPV6Only(type);
TNET_SOCKET_TYPE_SET_IPV4(type);
TNET_SOCKET_TYPE_SET_IPV6(type);
TNET_SOCKET_TYPE_SET_TLS(type);
TNET_SOCKET_TYPE_SET_UDP(type);
TNET_SOCKET_TYPE_SET_SCTP(type);
TNET_SOCKET_TYPE_SET_TCP(type);
tcp_socket = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, type);
if(!TNET_SOCKET_IS_VALID(tcp_socket))
{
TSK_OBJECT_SAFE_FREE(tcp_socket);
return;
}
//if(!(test = tnet_sockaddr_init("www.google.com", 80, type, &to))){
// test = tnet_sockfd_connetto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
//}
if(!(test = tnet_sockaddr_init("ipv6.google.com", 80, type, &to))){
test = tnet_sockfd_connectto(tcp_socket->fd, (const struct sockaddr_storage *)&to);
}
TSK_OBJECT_SAFE_FREE(tcp_socket);
}
#endif /* TNET_TEST_SOCKETS_H */

View File

@ -1,124 +1,159 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_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
// http://tools.ietf.org/html/draft-ietf-behave-stun-test-vectors-04
void test_stun_dump_transacid(tnet_stun_transacid_t transcid)
*/
#ifndef TNET_TEST_STUN_H
#define TNET_TEST_STUN_H
#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
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)
{
char transac_idstriing[TNET_STUN_TRANSACID_SIZE*2+1];
tsk_str_from_hex(transcid, TNET_STUN_TRANSACID_SIZE, transac_idstriing);
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);
transac_idstriing[sizeof(transac_idstriing)-1] = '\0';
TSK_DEBUG_INFO("STUN transac id:%s", transac_idstriing);
}
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;
transac_idstriing[sizeof(transac_idstriing)-1] = '\0';
TSK_DEBUG_INFO("STUN transac id:%s", transac_idstriing);
}
void test_sun_sendMessage()
{
tnet_stun_message_t *message = tsk_null;
tsk_buffer_t *buffer = tsk_null;
tnet_socket_t *socket = tsk_null;
struct sockaddr_storage to;
tnet_stun_attribute_t* stun_att;
// iWHr7ZwbQ1F4wmtk6scSEz0n (INVITE)
// HAfDCVGhskSe63eww0F3Y (200: audio)
// TN1KUcINJorcx8PISekSL (200: video)
message = tnet_stun_message_create("mI5gMSVZWlt6oZ7:wqQxm4bcpPM6cUTd", "HAfDCVGhskSe63eww0F3Y");
message->type = stun_binding_request;
// ICE-CONTROLLING
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlling_create(11131939471334912422))){
tnet_stun_message_add_attribute(message, &stun_att);
}
// USE-CANDIDATE
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_use_candidate_create())){
tnet_stun_message_add_attribute(message, &stun_att);
}
// PRIORITY
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_priority_create(1845501695))){
tnet_stun_message_add_attribute(message, &stun_att);
}
if(!(buffer = tnet_stun_message_serialize(message))){
goto bail;
}
// Create blocking socket and bind it
socket = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, STUN_SERVER_PROTO);
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)){
goto bail;
}
tnet_sockfd_sendto(socket->fd, (struct sockaddr*)&to, buffer->data, buffer->size);
bail:
TSK_OBJECT_SAFE_FREE(message);
TSK_OBJECT_SAFE_FREE(socket);
TSK_OBJECT_SAFE_FREE(buffer);
}
void test_stun_context()
{
// 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();
}
#endif /* TNET_TEST_STUN_H */
(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;
struct sockaddr_storage to;
tnet_stun_attribute_t* stun_att;
// iWHr7ZwbQ1F4wmtk6scSEz0n (INVITE)
// HAfDCVGhskSe63eww0F3Y (200: audio)
// TN1KUcINJorcx8PISekSL (200: video)
message = tnet_stun_message_create("mI5gMSVZWlt6oZ7:wqQxm4bcpPM6cUTd", "HAfDCVGhskSe63eww0F3Y");
message->type = stun_binding_request;
// ICE-CONTROLLING
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_controlling_create(11131939471334912422))){
tnet_stun_message_add_attribute(message, &stun_att);
}
// USE-CANDIDATE
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_use_candidate_create())){
tnet_stun_message_add_attribute(message, &stun_att);
}
// PRIORITY
if((stun_att = (tnet_stun_attribute_t*)tnet_stun_attribute_ice_priority_create(1845501695))){
tnet_stun_message_add_attribute(message, &stun_att);
}
if(!(buffer = tnet_stun_message_serialize(message))){
goto bail;
}
// Create blocking socket and bind it
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(kStunServerIP, kStunServerPort, kStunServerProto, &to)){
goto bail;
}
tnet_sockfd_sendto(socket->fd, (struct sockaddr*)&to, buffer->data, buffer->size);
bail:
TSK_OBJECT_SAFE_FREE(message);
TSK_OBJECT_SAFE_FREE(socket);
TSK_OBJECT_SAFE_FREE(buffer);
#endif
}
static void test_stun()
{
test_sun_parser();
}
#endif /* TNET_TEST_STUN_H */

View File

@ -1,108 +1,105 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_TLS_H
#define TNET_TEST_TLS_H
#define TEST_TLS_REMOTE_IP "192.168.16.225"
#define TEST_TLS_REMOTE_PORT 4061
#define TLS_TEST_SIP_MESSAGE \
"REGISTER sip:micromethod.com SIP/2.0\r\n" \
"Via: SIP/2.0/%s %s:%d;rport;branch=z9hG4bK1245420841406%d\r\n" \
"From: <sip:mamadou@micromethod.com>;tag=29358\r\n" \
"To: <sip:mamadou@micromethod.com>\r\n" \
"Call-ID: M-fa53180346f7f55ceb8d8670f9223dbb\r\n" \
"CSeq: 201 REGISTER\r\n" \
"Max-Forwards: 70\r\n" \
"Contact: <sip:mamadou@%s:%d;transport=%s>\r\n" \
"Expires: 10\r\n" \
"\r\n"
static int tnet_tls_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- TLS ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default:
{
break;
}
}
return 0;
}
void test_tls()
{
tnet_transport_handle_t *transport = tnet_transport_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_tls_ipv4, "TLS/IPV4 TRANSPORT");
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return;
}
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_tls_cb, "callbackdata");
/* Connect to the SIP Registrar */
if((fd = tnet_transport_connectto_2(transport, TEST_TLS_REMOTE_IP, TEST_TLS_REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
return;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return;
}
/* Send our SIP message */
{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, TLS_TEST_SIP_MESSAGE, "TLS", ip, port, port, ip, port, "tls");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using TCP/IPv4 transport.");
TSK_FREE(message);
return;
}
TSK_FREE(message);
}
TSK_OBJECT_SAFE_FREE(transport);
}
#endif /* TNET_TEST_TLS_H */
*/
#ifndef TNET_TEST_TLS_H
#define TNET_TEST_TLS_H
#define TEST_TLS_REMOTE_IP "192.168.16.225"
#define TEST_TLS_REMOTE_PORT 4061
#define TLS_TEST_SIP_MESSAGE \
"REGISTER sip:micromethod.com SIP/2.0\r\n" \
"Via: SIP/2.0/%s %s:%d;rport;branch=z9hG4bK1245420841406%d\r\n" \
"From: <sip:mamadou@micromethod.com>;tag=29358\r\n" \
"To: <sip:mamadou@micromethod.com>\r\n" \
"Call-ID: M-fa53180346f7f55ceb8d8670f9223dbb\r\n" \
"CSeq: 201 REGISTER\r\n" \
"Max-Forwards: 70\r\n" \
"Contact: <sip:mamadou@%s:%d;transport=%s>\r\n" \
"Expires: 10\r\n" \
"\r\n"
static int tnet_tls_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- TLS ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default:
{
break;
}
}
return 0;
}
void test_tls()
{
tnet_transport_handle_t *transport = tnet_transport_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_tls_ipv4, "TLS/IPV4 TRANSPORT");
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return;
}
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_tls_cb, "callbackdata");
/* Connect to the SIP Registrar */
if((fd = tnet_transport_connectto_2(transport, TEST_TLS_REMOTE_IP, TEST_TLS_REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
return;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return;
}
/* Send our SIP message */
{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, TLS_TEST_SIP_MESSAGE, "TLS", ip, port, port, ip, port, "tls");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using TCP/IPv4 transport.");
TSK_FREE(message);
return;
}
TSK_FREE(message);
}
TSK_OBJECT_SAFE_FREE(transport);
}
#endif /* TNET_TEST_TLS_H */

View File

@ -1,220 +1,217 @@
/*
* Copyright (C) 2009 Mamadou Diop.
/* Copyright (C) 2014 Mamadou DIOP.
*
* Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org>
*
* This file is part of Open Source Doubango Framework.
*
* DOUBANGO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* DOUBANGO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU 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_TRANSPORT_H
#define TNET_TEST_TRANSPORT_H
//#define REMOTE_IP4 "proxy.sipthor.net"//"192.168.0.15"
#define REMOTE_IP4 "192.168.0.13"
#define REMOTE_IP6 "2a01:e35:8632:7050:6122:2706:2124:32cb"
#define REMOTE_IP REMOTE_IP4
#define REMOTE_PORT 5083
#if defined(ANDROID) /* FIXME */
# define LOCAL_IP4 "10.0.2.15"
#else
# define LOCAL_IP4 TNET_SOCKET_HOST_ANY
#endif
#define LOCAL_IP6 TNET_SOCKET_HOST_ANY
#if defined(ANDROID)
# define LOCAL_PORT 5060
#else
# define LOCAL_PORT TNET_SOCKET_PORT_ANY
#endif
#define SIP_MESSAGE \
"REGISTER sip:micromethod.com SIP/2.0\r\n" \
"Via: SIP/2.0/%s %s:%d;rport;branch=z9hG4bK1245420841406%d\r\n" \
"From: <sip:mamadou@micromethod.com>;tag=29358\r\n" \
"To: <sip:mamadou@micromethod.com>\r\n" \
"Call-ID: M-fa53180346f7f55ceb8d8670f9223dbb\r\n" \
"CSeq: 201 REGISTER\r\n" \
"Max-Forwards: 70\r\n" \
"Contact: <sip:mamadou@%s:%d;transport=%s>\r\n" \
"Expires: 10\r\n" \
"\r\n"
static int tnet_tcp_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- TCP ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default:
{
break;
}
}
return 0;
}
static int tnet_udp_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- UDP ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default: break;
}
return 0;
}
void test_transport_tcp_ipv4(tnet_transport_handle_t *transport)
{
//tnet_socket_type_t type = tnet_socket_type_tcp_ipv4;
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_tcp_cb, "callbackdata");
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return;
}
/* Connect to the SIP Registrar */
if((fd = tnet_transport_connectto_2(transport, REMOTE_IP, REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
return;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return;
}
/* Send our SIP message */
{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, SIP_MESSAGE, "TCP", ip, port, port, ip, port, "tcp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using %s.", tnet_transport_get_description(transport));
TSK_FREE(message);
return;
}
TSK_FREE(message);
}
}
int test_transport_udp_ipv4(tnet_transport_handle_t *transport)
{
//tnet_socket_type_t type = tnet_socket_type_udp_ipv4;
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_udp_cb, "callbackdata");
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return -1;
}
/* Connect to our SIP REGISTRAR */
if((fd = tnet_transport_connectto_2(transport, REMOTE_IP, REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
//tnet_transport_shutdown(transport);
return -2;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return -3;
}
//tsk_thread_sleep(2000);
/* Send our SIP message */
/*while(1)*/{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
//memset(ip, 0, sizeof(ip));
//memcpy(ip, "192.168.0.12", 12);
tsk_sprintf(&message, SIP_MESSAGE, "UDP", ip, port, port, ip, port, "udp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using %s.", tnet_transport_get_description(transport));
//tnet_transport_shutdown(transport);
TSK_FREE(message);
return -4;
}
TSK_FREE(message);
}
return 0;
}
void test_transport()
{
#define TEST_TCP 1
#define TEST_UDP 0
#if TEST_UDP
tnet_transport_handle_t *udp = tnet_transport_create(LOCAL_IP4, LOCAL_PORT, tnet_socket_type_udp_ipv4, "UDP/IPV4 TRANSPORT");
test_transport_udp_ipv4(udp);
#endif
#if TEST_TCP
tnet_transport_handle_t *tcp = tnet_transport_create(LOCAL_IP4, LOCAL_PORT, tnet_socket_type_tcp_ipv4, "TCP/IPV4 TRANSPORT");
test_transport_tcp_ipv4(tcp);
#endif
//#if defined(ANDROID)
tsk_thread_sleep(1000000);
//#else
getchar();
//#endif
#if TEST_UDP
TSK_OBJECT_SAFE_FREE(udp);
#endif
#if TEST_TCP
TSK_OBJECT_SAFE_FREE(tcp);
#endif
}
#endif /* TNET_TEST_TRANSPORT_H*/
*/
#ifndef TNET_TEST_TRANSPORT_H
#define TNET_TEST_TRANSPORT_H
//#define REMOTE_IP4 "proxy.sipthor.net"//"192.168.0.15"
#define REMOTE_IP4 "192.168.0.13"
#define REMOTE_IP6 "2a01:e35:8632:7050:6122:2706:2124:32cb"
#define REMOTE_IP REMOTE_IP4
#define REMOTE_PORT 5083
#if defined(ANDROID) /* FIXME */
# define LOCAL_IP4 "10.0.2.15"
#else
# define LOCAL_IP4 TNET_SOCKET_HOST_ANY
#endif
#define LOCAL_IP6 TNET_SOCKET_HOST_ANY
#if defined(ANDROID)
# define LOCAL_PORT 5060
#else
# define LOCAL_PORT TNET_SOCKET_PORT_ANY
#endif
#define SIP_MESSAGE \
"REGISTER sip:micromethod.com SIP/2.0\r\n" \
"Via: SIP/2.0/%s %s:%d;rport;branch=z9hG4bK1245420841406%d\r\n" \
"From: <sip:mamadou@micromethod.com>;tag=29358\r\n" \
"To: <sip:mamadou@micromethod.com>\r\n" \
"Call-ID: M-fa53180346f7f55ceb8d8670f9223dbb\r\n" \
"CSeq: 201 REGISTER\r\n" \
"Max-Forwards: 70\r\n" \
"Contact: <sip:mamadou@%s:%d;transport=%s>\r\n" \
"Expires: 10\r\n" \
"\r\n"
static int tnet_tcp_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- TCP ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default:
{
break;
}
}
return 0;
}
static int tnet_udp_cb(const tnet_transport_event_t* e)
{
switch(e->type){
case event_data:
{
TSK_DEBUG_INFO("--- UDP ---\n%s\n", (const char*)e->data);
break;
}
case event_closed:
case event_connected:
default: break;
}
return 0;
}
void test_transport_tcp_ipv4(tnet_transport_handle_t *transport)
{
//tnet_socket_type_t type = tnet_socket_type_tcp_ipv4;
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_tcp_cb, "callbackdata");
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return;
}
/* Connect to the SIP Registrar */
if((fd = tnet_transport_connectto_2(transport, REMOTE_IP, REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
return;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return;
}
/* Send our SIP message */
{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
tsk_sprintf(&message, SIP_MESSAGE, "TCP", ip, port, port, ip, port, "tcp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using %s.", tnet_transport_get_description(transport));
TSK_FREE(message);
return;
}
TSK_FREE(message);
}
}
int test_transport_udp_ipv4(tnet_transport_handle_t *transport)
{
//tnet_socket_type_t type = tnet_socket_type_udp_ipv4;
tnet_ip_t ip;
tnet_port_t port;
tnet_fd_t fd = TNET_INVALID_FD;
/* Set our callback function */
tnet_transport_set_callback(transport, tnet_udp_cb, "callbackdata");
if(tnet_transport_start(transport)){
TSK_DEBUG_ERROR("Failed to create %s.", tnet_transport_get_description(transport));
return -1;
}
/* Connect to our SIP REGISTRAR */
if((fd = tnet_transport_connectto_2(transport, REMOTE_IP, REMOTE_PORT)) == TNET_INVALID_FD){
TSK_DEBUG_ERROR("Failed to connect %s.", tnet_transport_get_description(transport));
//tnet_transport_shutdown(transport);
return -2;
}
if(tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT)){
TSK_DEBUG_ERROR("%d milliseconds elapsed and the socket is still not connected.", TNET_CONNECT_TIMEOUT);
tnet_transport_remove_socket(transport, &fd);
return -3;
}
//tsk_thread_sleep(2000);
/* Send our SIP message */
/*while(1)*/{
char* message = 0;
tnet_transport_get_ip_n_port(transport, fd, &ip, &port);
//memset(ip, 0, sizeof(ip));
//memcpy(ip, "192.168.0.12", 12);
tsk_sprintf(&message, SIP_MESSAGE, "UDP", ip, port, port, ip, port, "udp");
if(!tnet_transport_send(transport, fd, message, strlen(message)))
{
TSK_DEBUG_ERROR("Failed to send data using %s.", tnet_transport_get_description(transport));
//tnet_transport_shutdown(transport);
TSK_FREE(message);
return -4;
}
TSK_FREE(message);
}
return 0;
}
void test_transport()
{
#define TEST_TCP 1
#define TEST_UDP 0
#if TEST_UDP
tnet_transport_handle_t *udp = tnet_transport_create(LOCAL_IP4, LOCAL_PORT, tnet_socket_type_udp_ipv4, "UDP/IPV4 TRANSPORT");
test_transport_udp_ipv4(udp);
#endif
#if TEST_TCP
tnet_transport_handle_t *tcp = tnet_transport_create(LOCAL_IP4, LOCAL_PORT, tnet_socket_type_tcp_ipv4, "TCP/IPV4 TRANSPORT");
test_transport_tcp_ipv4(tcp);
#endif
//#if defined(ANDROID)
tsk_thread_sleep(1000000);
//#else
getchar();
//#endif
#if TEST_UDP
TSK_OBJECT_SAFE_FREE(udp);
#endif
#if TEST_TCP
TSK_OBJECT_SAFE_FREE(tcp);
#endif
}
#endif /* TNET_TEST_TRANSPORT_H*/

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"