diff options
author | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
---|---|---|
committer | Mamadou DIOP <bossiel@yahoo.fr> | 2016-02-23 22:00:35 +0100 |
commit | 50dfb4359619563012997bc3ddafb7667741066c (patch) | |
tree | db234c1edc3240a653363b5735fc4077af4b8720 /tinyNET | |
parent | 94b2219209038e05dd26395f6fb700be4d1062c0 (diff) | |
download | doubango-50dfb4359619563012997bc3ddafb7667741066c.zip doubango-50dfb4359619563012997bc3ddafb7667741066c.tar.gz |
Add new QoS implementation
Code formatting
Diffstat (limited to 'tinyNET')
116 files changed, 13934 insertions, 14017 deletions
diff --git a/tinyNET/src/dhcp/tnet_dhcp.c b/tinyNET/src/dhcp/tnet_dhcp.c index efd57c5..80a1150 100755 --- a/tinyNET/src/dhcp/tnet_dhcp.c +++ b/tinyNET/src/dhcp/tnet_dhcp.c @@ -47,7 +47,7 @@ */ tnet_dhcp_ctx_t* tnet_dhcp_ctx_create() { - return tsk_object_new(tnet_dhcp_ctx_def_t); + return tsk_object_new(tnet_dhcp_ctx_def_t); } /**@ingroup tnet_dhcp_group @@ -55,7 +55,7 @@ tnet_dhcp_ctx_t* tnet_dhcp_ctx_create() */ tnet_dhcp_params_t* tnet_dhcp_params_create() { - return tsk_object_new(tnet_dhcp_params_def_t); + return tsk_object_new(tnet_dhcp_params_def_t); } /* FIXME: USE retransmission mech (*2*2...) @@ -64,189 +64,191 @@ tnet_dhcp_params_t* tnet_dhcp_params_create() */ tnet_dhcp_reply_t* tnet_dhcp_send_request(tnet_dhcp_ctx_t* ctx, tnet_dhcp_request_t* request) { - tsk_buffer_t *output; - tnet_dhcp_reply_t* reply = tsk_null; - int ret; - struct timeval tv; - fd_set set; - uint64_t timeout = 0; - tsk_list_item_t *item; - const tnet_interface_t *iface; - - tnet_socket_t *localsocket4 = tsk_null; - struct sockaddr_storage server; - - if (!ctx || !request){ - goto bail; - } - - localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, ctx->port_client, tnet_socket_type_udp_ipv4); - if (!TNET_SOCKET_IS_VALID(localsocket4)){ - TSK_DEBUG_ERROR("Failed to create/bind DHCP client socket."); - goto bail; - } - - /* Always wait for 200ms before retransmission */ - tv.tv_sec = 0; - tv.tv_usec = (200 * 1000); - - if (tnet_sockaddr_init("255.255.255.255", ctx->server_port, tnet_socket_type_udp_ipv4, &server)){ - TNET_PRINT_LAST_ERROR("Failed to initialize the DHCP server address"); - goto bail; - } - - /* ENABLE BROADCASTING */ - { + tsk_buffer_t *output; + tnet_dhcp_reply_t* reply = tsk_null; + int ret; + struct timeval tv; + fd_set set; + uint64_t timeout = 0; + tsk_list_item_t *item; + const tnet_interface_t *iface; + + tnet_socket_t *localsocket4 = tsk_null; + struct sockaddr_storage server; + + if (!ctx || !request) { + goto bail; + } + + localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, ctx->port_client, tnet_socket_type_udp_ipv4); + if (!TNET_SOCKET_IS_VALID(localsocket4)) { + TSK_DEBUG_ERROR("Failed to create/bind DHCP client socket."); + goto bail; + } + + /* Always wait for 200ms before retransmission */ + tv.tv_sec = 0; + tv.tv_usec = (200 * 1000); + + if (tnet_sockaddr_init("255.255.255.255", ctx->server_port, tnet_socket_type_udp_ipv4, &server)) { + TNET_PRINT_LAST_ERROR("Failed to initialize the DHCP server address"); + goto bail; + } + + /* ENABLE BROADCASTING */ + { #if defined(SOLARIS) - char yes = '1'; + char yes = '1'; #else - int yes = 1; + int yes = 1; #endif - if (setsockopt(localsocket4->fd, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(int))){ - TNET_PRINT_LAST_ERROR("Failed to enable broadcast option"); - goto bail; - } - } - - /* Set timeout */ - timeout = tsk_time_now() + ctx->timeout; - - do - { - /* RFC 2131 - 3.6 Use of DHCP in clients with multiple interfaces - A client with multiple network interfaces must use DHCP through each - interface independently to obtain configuration information - parameters for those separate interfaces. - */ - - tsk_list_foreach(item, ctx->interfaces){ - iface = item->data; - - /* Set FD */ - FD_ZERO(&set); - FD_SET(localsocket4->fd, &set); - - /* ciaddr */ - if (request->type == dhcp_type_inform){ - struct sockaddr_storage ss; - if (!tnet_getsockname(localsocket4->fd, &ss)){ - uint32_t addr = (uint32_t)tnet_htonl_2(&((struct sockaddr_in*)&ss)->sin_addr); - memcpy(&request->ciaddr, &addr, 4); - } - } - - /* chaddr */ - memset(request->chaddr, 0, sizeof(request->chaddr)); - request->hlen = (uint8_t)(iface->mac_address_length > sizeof(request->chaddr) ? sizeof(request->chaddr) : iface->mac_address_length); - memcpy(request->chaddr, iface->mac_address, request->hlen); - - /* Serialize and send to the server. */ - if (!(output = tnet_dhcp_message_serialize(ctx, request))){ - TSK_DEBUG_ERROR("Failed to serialize the DHCP message."); - goto next_iface; - } - /* Send the request to the DHCP server */ - if ((ret = tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size)) < 0){ - TNET_PRINT_LAST_ERROR("Failed to send DHCP request"); - - tsk_thread_sleep(150); // wait 150ms before trying the next iface. - goto next_iface; - } - /* wait for response */ - if ((ret = select(localsocket4->fd + 1, &set, NULL, NULL, &tv)) < 0){ /* Error */ - TNET_PRINT_LAST_ERROR("select have failed."); - tsk_thread_sleep(150); // wait 150ms before trying the next iface. - goto next_iface; - } - else if (ret == 0) - { /* timeout ==> do nothing */ - } - else - { /* there is data to read */ - unsigned int len = 0; - void* data = tsk_null; - - /* Check how how many bytes are pending */ - if ((ret = tnet_ioctlt(localsocket4->fd, FIONREAD, &len)) < 0){ - goto next_iface; - } - - /* Receive pending data */ - data = tsk_calloc(len, sizeof(uint8_t)); - if ((ret = tnet_sockfd_recv(localsocket4->fd, data, len, 0)) < 0){ - TSK_FREE(data); - - TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams."); - goto next_iface; - } - - /* Parse the incoming response. */ - reply = tnet_dhcp_message_deserialize(ctx, data, (tsk_size_t)ret); - TSK_FREE(data); - - if (reply) - { /* response successfuly parsed */ - if (request->xid != reply->xid) - { /* Not same transaction id ==> continue*/ - TSK_OBJECT_SAFE_FREE(reply); - } - } - } - - next_iface: - TSK_OBJECT_SAFE_FREE(output); - if (reply){ - goto bail; - } - } - //break;//FIXME - } while (timeout > tsk_time_epoch()); + if (setsockopt(localsocket4->fd, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(int))) { + TNET_PRINT_LAST_ERROR("Failed to enable broadcast option"); + goto bail; + } + } + + /* Set timeout */ + timeout = tsk_time_now() + ctx->timeout; + + do { + /* RFC 2131 - 3.6 Use of DHCP in clients with multiple interfaces + A client with multiple network interfaces must use DHCP through each + interface independently to obtain configuration information + parameters for those separate interfaces. + */ + + tsk_list_foreach(item, ctx->interfaces) { + iface = item->data; + + /* Set FD */ + FD_ZERO(&set); + FD_SET(localsocket4->fd, &set); + + /* ciaddr */ + if (request->type == dhcp_type_inform) { + struct sockaddr_storage ss; + if (!tnet_getsockname(localsocket4->fd, &ss)) { + uint32_t addr = (uint32_t)tnet_htonl_2(&((struct sockaddr_in*)&ss)->sin_addr); + memcpy(&request->ciaddr, &addr, 4); + } + } + + /* chaddr */ + memset(request->chaddr, 0, sizeof(request->chaddr)); + request->hlen = (uint8_t)(iface->mac_address_length > sizeof(request->chaddr) ? sizeof(request->chaddr) : iface->mac_address_length); + memcpy(request->chaddr, iface->mac_address, request->hlen); + + /* Serialize and send to the server. */ + if (!(output = tnet_dhcp_message_serialize(ctx, request))) { + TSK_DEBUG_ERROR("Failed to serialize the DHCP message."); + goto next_iface; + } + /* Send the request to the DHCP server */ + if ((ret = tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size)) < 0) { + TNET_PRINT_LAST_ERROR("Failed to send DHCP request"); + + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + /* wait for response */ + if ((ret = select(localsocket4->fd + 1, &set, NULL, NULL, &tv)) < 0) { /* Error */ + TNET_PRINT_LAST_ERROR("select have failed."); + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + else if (ret == 0) { + /* timeout ==> do nothing */ + } + else { + /* there is data to read */ + unsigned int len = 0; + void* data = tsk_null; + + /* Check how how many bytes are pending */ + if ((ret = tnet_ioctlt(localsocket4->fd, FIONREAD, &len)) < 0) { + goto next_iface; + } + + /* Receive pending data */ + data = tsk_calloc(len, sizeof(uint8_t)); + if ((ret = tnet_sockfd_recv(localsocket4->fd, data, len, 0)) < 0) { + TSK_FREE(data); + + TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams."); + goto next_iface; + } + + /* Parse the incoming response. */ + reply = tnet_dhcp_message_deserialize(ctx, data, (tsk_size_t)ret); + TSK_FREE(data); + + if (reply) { + /* response successfuly parsed */ + if (request->xid != reply->xid) { + /* Not same transaction id ==> continue*/ + TSK_OBJECT_SAFE_FREE(reply); + } + } + } + +next_iface: + TSK_OBJECT_SAFE_FREE(output); + if (reply) { + goto bail; + } + } + //break;//FIXME + } + while (timeout > tsk_time_epoch()); bail: - TSK_OBJECT_SAFE_FREE(localsocket4); + TSK_OBJECT_SAFE_FREE(localsocket4); - return reply; + return reply; } /**@ingroup tnet_dhcp_group */ tnet_dhcp_reply_t* tnet_dhcp_query(tnet_dhcp_ctx_t* ctx, tnet_dhcp_message_type_t type, tnet_dhcp_params_t* params) { - tnet_dhcp_reply_t* reply = tsk_null; - tnet_dhcp_request_t* request = tnet_dhcp_request_create(); + tnet_dhcp_reply_t* reply = tsk_null; + tnet_dhcp_request_t* request = tnet_dhcp_request_create(); - if (!ctx || !params || !request){ - goto bail; - } + if (!ctx || !params || !request) { + goto bail; + } - request->type = type; - tnet_dhcp_message_add_codes(request, params->codes, params->codes_count); + request->type = type; + tnet_dhcp_message_add_codes(request, params->codes, params->codes_count); - reply = tnet_dhcp_send_request(ctx, request); + reply = tnet_dhcp_send_request(ctx, request); bail: - TSK_OBJECT_SAFE_FREE(request); + TSK_OBJECT_SAFE_FREE(request); - return reply; + return reply; } /**@ingroup tnet_dhcp_group */ int tnet_dhcp_params_add_code(tnet_dhcp_params_t* params, tnet_dhcp_option_code_t code) { - if (params){ - if (params->codes_count < TNET_DHCP_MAX_CODES){ - unsigned i; - for (i = 0; i < params->codes_count; i++){ - if (params->codes[i] == code){ - return -3; - } - } - params->codes[params->codes_count++] = code; - } - else return -2; - } - return -1; + if (params) { + if (params->codes_count < TNET_DHCP_MAX_CODES) { + unsigned i; + for (i = 0; i < params->codes_count; i++) { + if (params->codes[i] == code) { + return -3; + } + } + params->codes[params->codes_count++] = code; + } + else { + return -2; + } + } + return -1; } @@ -256,49 +258,48 @@ int tnet_dhcp_params_add_code(tnet_dhcp_params_t* params, tnet_dhcp_option_code_ // static tsk_object_t* tnet_dhcp_ctx_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_ctx_t *ctx = self; - if (ctx){ - tnet_host_t host; - - ctx->vendor_id = tsk_strdup(TNET_DHCP_VENDOR_ID_DEFAULT); - if (!tnet_gethostname(&host)){ - ctx->hostname = tsk_strndup(host, tsk_strlen(host)); - } - ctx->timeout = TNET_DHCP_TIMEOUT_DEFAULT; - ctx->max_msg_size = TNET_DHCP_MAX_MSG_SIZE; - ctx->port_client = TNET_DHCP_CLIENT_PORT; - ctx->server_port = TNET_DHCP_SERVER_PORT; - ctx->interfaces = tnet_get_interfaces(); - - if (!ctx->interfaces || TSK_LIST_IS_EMPTY(ctx->interfaces)){ - TSK_DEBUG_ERROR("Failed to retrieve network interfaces."); - } - - tsk_safeobj_init(ctx); - } - return self; + tnet_dhcp_ctx_t *ctx = self; + if (ctx) { + tnet_host_t host; + + ctx->vendor_id = tsk_strdup(TNET_DHCP_VENDOR_ID_DEFAULT); + if (!tnet_gethostname(&host)) { + ctx->hostname = tsk_strndup(host, tsk_strlen(host)); + } + ctx->timeout = TNET_DHCP_TIMEOUT_DEFAULT; + ctx->max_msg_size = TNET_DHCP_MAX_MSG_SIZE; + ctx->port_client = TNET_DHCP_CLIENT_PORT; + ctx->server_port = TNET_DHCP_SERVER_PORT; + ctx->interfaces = tnet_get_interfaces(); + + if (!ctx->interfaces || TSK_LIST_IS_EMPTY(ctx->interfaces)) { + TSK_DEBUG_ERROR("Failed to retrieve network interfaces."); + } + + tsk_safeobj_init(ctx); + } + return self; } static tsk_object_t* tnet_dhcp_ctx_dtor(tsk_object_t * self) { - tnet_dhcp_ctx_t *ctx = self; - if (ctx){ - tsk_safeobj_deinit(ctx); + tnet_dhcp_ctx_t *ctx = self; + if (ctx) { + tsk_safeobj_deinit(ctx); - TSK_FREE(ctx->vendor_id); - TSK_FREE(ctx->hostname); + TSK_FREE(ctx->vendor_id); + TSK_FREE(ctx->hostname); - TSK_OBJECT_SAFE_FREE(ctx->interfaces); - } - return self; + TSK_OBJECT_SAFE_FREE(ctx->interfaces); + } + return self; } -static const tsk_object_def_t tnet_dhcp_ctx_def_s = -{ - sizeof(tnet_dhcp_ctx_t), - tnet_dhcp_ctx_ctor, - tnet_dhcp_ctx_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_ctx_def_s = { + sizeof(tnet_dhcp_ctx_t), + tnet_dhcp_ctx_ctor, + tnet_dhcp_ctx_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_ctx_def_t = &tnet_dhcp_ctx_def_s; @@ -307,25 +308,24 @@ const tsk_object_def_t *tnet_dhcp_ctx_def_t = &tnet_dhcp_ctx_def_s; // static tsk_object_t* tnet_dhcp_params_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_params_t *params = self; - if (params){ - } - return self; + tnet_dhcp_params_t *params = self; + if (params) { + } + return self; } static tsk_object_t* tnet_dhcp_params_dtor(tsk_object_t * self) { - tnet_dhcp_params_t *params = self; - if (params){ - } - return self; + tnet_dhcp_params_t *params = self; + if (params) { + } + return self; } -static const tsk_object_def_t tnet_dhcp_params_def_s = -{ - sizeof(tnet_dhcp_params_t), - tnet_dhcp_params_ctor, - tnet_dhcp_params_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_params_def_s = { + sizeof(tnet_dhcp_params_t), + tnet_dhcp_params_ctor, + tnet_dhcp_params_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_params_def_t = &tnet_dhcp_params_def_s; diff --git a/tinyNET/src/dhcp/tnet_dhcp.h b/tinyNET/src/dhcp/tnet_dhcp.h index 9572641..0751914 100755 --- a/tinyNET/src/dhcp/tnet_dhcp.h +++ b/tinyNET/src/dhcp/tnet_dhcp.h @@ -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. * @@ -42,8 +42,8 @@ TNET_BEGIN_DECLS -/**@ingroup tnet_dhcp_group -* Default timeout (in milliseconds) value for DHCP requests. +/**@ingroup tnet_dhcp_group +* Default timeout (in milliseconds) value for DHCP requests. */ #define TNET_DHCP_TIMEOUT_DEFAULT 2000 @@ -70,32 +70,30 @@ TNET_BEGIN_DECLS /**@ingroup tnet_dhcp_group * Parameter Request List (55) */ -typedef struct tnet_dhcp_params_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_dhcp_params_s { + TSK_DECLARE_OBJECT; - tnet_dhcp_option_code_t codes[TNET_DHCP_MAX_CODES]; - unsigned codes_count; + tnet_dhcp_option_code_t codes[TNET_DHCP_MAX_CODES]; + unsigned codes_count; } tnet_dhcp_params_t; /**@ingroup tnet_dhcp_group */ -typedef struct tnet_dhcp_ctx_s -{ - TSK_DECLARE_OBJECT; - - char* vendor_id; - char* hostname; - uint16_t max_msg_size; /**< Option code 57. */ - - uint64_t timeout; - - tnet_port_t port_client; /**< Local port to bind to for incloming DHCP messages. Default: 68 */ - tnet_port_t server_port; /**< Destination port for outgoing DHCP messages. Default: 64 */ - tnet_interfaces_L_t *interfaces; - - TSK_DECLARE_SAFEOBJ; +typedef struct tnet_dhcp_ctx_s { + TSK_DECLARE_OBJECT; + + char* vendor_id; + char* hostname; + uint16_t max_msg_size; /**< Option code 57. */ + + uint64_t timeout; + + tnet_port_t port_client; /**< Local port to bind to for incloming DHCP messages. Default: 68 */ + tnet_port_t server_port; /**< Destination port for outgoing DHCP messages. Default: 64 */ + tnet_interfaces_L_t *interfaces; + + TSK_DECLARE_SAFEOBJ; } tnet_dhcp_ctx_t; diff --git a/tinyNET/src/dhcp/tnet_dhcp_message.c b/tinyNET/src/dhcp/tnet_dhcp_message.c index 005327d..3e24474 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_message.c +++ b/tinyNET/src/dhcp/tnet_dhcp_message.c @@ -35,278 +35,276 @@ tnet_dhcp_message_t* tnet_dhcp_message_create(tnet_dhcp_message_op_t opcode) { - return tsk_object_new(tnet_dhcp_message_def_t, opcode); + return tsk_object_new(tnet_dhcp_message_def_t, opcode); } tnet_dhcp_request_t* tnet_dhcp_request_create() { - return tnet_dhcp_message_create(dhcp_op_bootrequest); + return tnet_dhcp_message_create(dhcp_op_bootrequest); } tnet_dhcp_message_t* tnet_dhcp_reply_create() { - return tnet_dhcp_message_create(dhcp_op_bootreply); + return tnet_dhcp_message_create(dhcp_op_bootreply); } tsk_buffer_t* tnet_dhcp_message_serialize(const tnet_dhcp_ctx_t *ctx, const tnet_dhcp_message_t *message) { - tsk_buffer_t* output = 0; - uint8_t _1byte; - uint16_t _2bytes; - uint32_t _4bytes; - - /* Check message validity */ - if (!message){ - goto bail; - } - - output = tsk_buffer_create_null(); - - /*== OP HTYPE HLEN HOPS */ - _4bytes = (((uint32_t)(message->op)) << 24) | - (((uint32_t)(message->htype)) << 16) | - (((uint16_t)(message->hlen)) << 8) | message->hops; - _4bytes = (uint32_t)tnet_ntohl(_4bytes); - tsk_buffer_append(output, &(_4bytes), 4); - - /*== XID */ - _4bytes = (uint32_t)tnet_ntohl(message->xid); - tsk_buffer_append(output, &(_4bytes), 4); - /*== SECS */ - _2bytes = tnet_ntohs(message->secs); - tsk_buffer_append(output, &(_2bytes), 2); - /*== FLAGS */ - _2bytes = tnet_ntohs(message->flags); - tsk_buffer_append(output, &(_2bytes), 2); - /*== CIADDR */ - _4bytes = (uint32_t)tnet_ntohl(message->ciaddr); - tsk_buffer_append(output, &(_4bytes), 4); - /*== YIADDR */ - _4bytes = (uint32_t)tnet_ntohl(message->yiaddr); - tsk_buffer_append(output, &(_4bytes), 4); - /*== SIADDR */ - _4bytes = (uint32_t)tnet_ntohl(message->siaddr); - tsk_buffer_append(output, &(_4bytes), 4); - /*== GIADDR */ - _4bytes = (uint32_t)tnet_ntohl(message->giaddr); - tsk_buffer_append(output, &(_4bytes), 4); - /*== CHADDR */ - tsk_buffer_append(output, message->chaddr, sizeof(message->chaddr)); - /*== sname (unused) */ - tsk_buffer_append(output, message->sname, sizeof(message->sname)); - /*== file (unused) */ - tsk_buffer_append(output, message->file, sizeof(message->file)); - /*== Magic Cookie */ - _4bytes = (uint32_t)tnet_ntohl(TNET_DHCP_MAGIC_COOKIE); - tsk_buffer_append(output, &(_4bytes), 4); - - /*== Message Type (option 53) - */ - tnet_dhcp_option_serializeex(dhcp_code_DHCP_Msg_Type, 1, &message->type, output); - - /*== Client Identifier (option 61) ==> RFC 2132 - 9.14. Client-identifier - Code Len Type Client-Identifier - +-----+-----+-----+-----+-----+--- - | 61 | n | t1 | i1 | i2 | ... - +-----+-----+-----+-----+-----+--- - */ - if (message->hlen){ - uint8_t client_id[17]; // 16 /*sizeof(chaddr)*/+ 1/*htype*/ - /*if(client_id)*/{ - client_id[0] = message->htype; - memcpy(&client_id[1], message->chaddr, message->hlen); - tnet_dhcp_option_serializeex(dhcp_code_Client_Id, (message->hlen + 1), client_id, output); - } - } - /*== Host name(10) ==> RFC 2132 - 3.14. Host Name Option - Code Len Host Name - +-----+-----+-----+-----+-----+-----+-----+-----+-- - | 12 | n | h1 | h2 | h3 | h4 | h5 | h6 | ... - +-----+-----+-----+-----+-----+-----+-----+-----+-- - */ - if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->hostname){ - tnet_dhcp_option_serializeex(dhcp_code_Hostname, (uint8_t)tsk_strlen(ctx->hostname), ctx->hostname, output); - } - /*== Vendor classId(60) ==> RFC 2132 - 9.13. Vendor class identifier - Code Len Vendor class Identifier - +-----+-----+-----+-----+--- - | 60 | n | i1 | i2 | ... - +-----+-----+-----+-----+--- - */ - if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->vendor_id){ - tnet_dhcp_option_serializeex(dhcp_code_Class_Id, (uint8_t)tsk_strlen(ctx->vendor_id), ctx->vendor_id, output); - } - - /*== RFC 2132 - 9.10. Maximum DHCP Message Size (57) - Code Len Length - +-----+-----+-----+-----+ - | 57 | 2 | l1 | l2 | - +-----+-----+-----+-----+ - */ - if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->max_msg_size){ - _2bytes = tnet_ntohs(ctx->max_msg_size); - tnet_dhcp_option_serializeex(dhcp_code_DHCP_Max_Msg_Size, 2, &_2bytes, output); - } - - /*== DHCP Options - */ - { - tsk_list_item_t *item; - tnet_dhcp_option_t* option; - tsk_list_foreach(item, message->options) - { - option = (tnet_dhcp_option_t*)item->data; - if (tnet_dhcp_option_serialize(option, output)){ - TSK_DEBUG_WARN("Failed to serialize DHCP OPTION (%u)", option->code); - } - } - } - - /* RFC 2131 - 4.1 Constructing and sending DHCP messages - The last option must always be the 'end' option. - */ - _1byte = dhcp_code_End; - tsk_buffer_append(output, &(_1byte), 1); + tsk_buffer_t* output = 0; + uint8_t _1byte; + uint16_t _2bytes; + uint32_t _4bytes; + + /* Check message validity */ + if (!message) { + goto bail; + } + + output = tsk_buffer_create_null(); + + /*== OP HTYPE HLEN HOPS */ + _4bytes = (((uint32_t)(message->op)) << 24) | + (((uint32_t)(message->htype)) << 16) | + (((uint16_t)(message->hlen)) << 8) | message->hops; + _4bytes = (uint32_t)tnet_ntohl(_4bytes); + tsk_buffer_append(output, &(_4bytes), 4); + + /*== XID */ + _4bytes = (uint32_t)tnet_ntohl(message->xid); + tsk_buffer_append(output, &(_4bytes), 4); + /*== SECS */ + _2bytes = tnet_ntohs(message->secs); + tsk_buffer_append(output, &(_2bytes), 2); + /*== FLAGS */ + _2bytes = tnet_ntohs(message->flags); + tsk_buffer_append(output, &(_2bytes), 2); + /*== CIADDR */ + _4bytes = (uint32_t)tnet_ntohl(message->ciaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== YIADDR */ + _4bytes = (uint32_t)tnet_ntohl(message->yiaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== SIADDR */ + _4bytes = (uint32_t)tnet_ntohl(message->siaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== GIADDR */ + _4bytes = (uint32_t)tnet_ntohl(message->giaddr); + tsk_buffer_append(output, &(_4bytes), 4); + /*== CHADDR */ + tsk_buffer_append(output, message->chaddr, sizeof(message->chaddr)); + /*== sname (unused) */ + tsk_buffer_append(output, message->sname, sizeof(message->sname)); + /*== file (unused) */ + tsk_buffer_append(output, message->file, sizeof(message->file)); + /*== Magic Cookie */ + _4bytes = (uint32_t)tnet_ntohl(TNET_DHCP_MAGIC_COOKIE); + tsk_buffer_append(output, &(_4bytes), 4); + + /*== Message Type (option 53) + */ + tnet_dhcp_option_serializeex(dhcp_code_DHCP_Msg_Type, 1, &message->type, output); + + /*== Client Identifier (option 61) ==> RFC 2132 - 9.14. Client-identifier + Code Len Type Client-Identifier + +-----+-----+-----+-----+-----+--- + | 61 | n | t1 | i1 | i2 | ... + +-----+-----+-----+-----+-----+--- + */ + if (message->hlen) { + uint8_t client_id[17]; // 16 /*sizeof(chaddr)*/+ 1/*htype*/ + /*if(client_id)*/{ + client_id[0] = message->htype; + memcpy(&client_id[1], message->chaddr, message->hlen); + tnet_dhcp_option_serializeex(dhcp_code_Client_Id, (message->hlen + 1), client_id, output); + } + } + /*== Host name(10) ==> RFC 2132 - 3.14. Host Name Option + Code Len Host Name + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 12 | n | h1 | h2 | h3 | h4 | h5 | h6 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->hostname) { + tnet_dhcp_option_serializeex(dhcp_code_Hostname, (uint8_t)tsk_strlen(ctx->hostname), ctx->hostname, output); + } + /*== Vendor classId(60) ==> RFC 2132 - 9.13. Vendor class identifier + Code Len Vendor class Identifier + +-----+-----+-----+-----+--- + | 60 | n | i1 | i2 | ... + +-----+-----+-----+-----+--- + */ + if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->vendor_id) { + tnet_dhcp_option_serializeex(dhcp_code_Class_Id, (uint8_t)tsk_strlen(ctx->vendor_id), ctx->vendor_id, output); + } + + /*== RFC 2132 - 9.10. Maximum DHCP Message Size (57) + Code Len Length + +-----+-----+-----+-----+ + | 57 | 2 | l1 | l2 | + +-----+-----+-----+-----+ + */ + if (TNET_DHCP_MESSAGE_IS_REQUEST(message) && ctx->max_msg_size) { + _2bytes = tnet_ntohs(ctx->max_msg_size); + tnet_dhcp_option_serializeex(dhcp_code_DHCP_Max_Msg_Size, 2, &_2bytes, output); + } + + /*== DHCP Options + */ + { + tsk_list_item_t *item; + tnet_dhcp_option_t* option; + tsk_list_foreach(item, message->options) { + option = (tnet_dhcp_option_t*)item->data; + if (tnet_dhcp_option_serialize(option, output)) { + TSK_DEBUG_WARN("Failed to serialize DHCP OPTION (%u)", option->code); + } + } + } + + /* RFC 2131 - 4.1 Constructing and sending DHCP messages + The last option must always be the 'end' option. + */ + _1byte = dhcp_code_End; + tsk_buffer_append(output, &(_1byte), 1); bail: - return output; + return output; } tnet_dhcp_message_t* tnet_dhcp_message_deserialize(const struct tnet_dhcp_ctx_s *ctx, const uint8_t *data, tsk_size_t size) { - tnet_dhcp_message_t *message = 0; - uint8_t *dataPtr, *dataEnd, *dataStart; - - if (!data || !size) - { - goto bail; - } - - if (size < TNET_DHCP_MESSAGE_MIN_SIZE){ - TSK_DEBUG_ERROR("DHCP message too short."); - goto bail; - } - - if (!(message = tnet_dhcp_reply_create())){ /* If REQUEST OP will be overridedden */ - TSK_DEBUG_ERROR("Failed to create new DHCP message."); - goto bail; - } - - dataPtr = (uint8_t*)data; - dataStart = dataPtr; - dataEnd = (dataStart + size); - - /*== op (1)*/ - message->op = *(dataPtr++); - /*== htype (1) */ - message->htype = *(dataPtr++); - /*== hlen (1) */ - message->hlen = *(dataPtr++); - /*== htype (1) */ - message->hops = *(dataPtr++); - /*== xid (4) */ - message->xid = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4; - /*== secs (2) */ - message->secs = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /*== flags (2) */ - message->flags = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /*== ciaddr (4) */ - message->ciaddr = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4; - /*== yiaddr (4) */ - message->yiaddr = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4; - /*== siaddr (4) */ - message->siaddr = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4; - /*== giaddr (4) */ - message->giaddr = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4; - /*== chaddr (16[max]) */ - memcpy(message->chaddr, dataPtr, message->hlen > 16 ? 16 : message->hlen); - dataPtr += 16; - /*== sname (64) */ - memcpy(message->sname, dataPtr, 64); - dataPtr += 64; - /*== file (128) */ - memcpy(message->file, dataPtr, 128); - dataPtr += 128; - /*== Magic Cookie (4) */ - if (tnet_htonl_2(dataPtr) != TNET_DHCP_MAGIC_COOKIE){ - TSK_DEBUG_ERROR("Invalid DHCP magic cookie."); - // Do not exit ==> continue parsing. - } - dataPtr += 4; - - /*== options (variable) */ - while (dataPtr < dataEnd && *dataPtr != dhcp_code_End) - { - tnet_dhcp_option_t* option = tnet_dhcp_option_deserialize(dataPtr, (tsk_size_t)(dataEnd - dataPtr)); - if (option && option->value){ - - if (option->code == dhcp_code_DHCP_Msg_Type){ - message->type = (tnet_dhcp_message_type_t)*TSK_BUFFER_TO_U8(option->value); - } - - dataPtr += option->value->size + 2/*Code Len*/; - tsk_list_push_back_data(message->options, (void**)&option); - } - else break; - } + tnet_dhcp_message_t *message = 0; + uint8_t *dataPtr, *dataEnd, *dataStart; + + if (!data || !size) { + goto bail; + } + + if (size < TNET_DHCP_MESSAGE_MIN_SIZE) { + TSK_DEBUG_ERROR("DHCP message too short."); + goto bail; + } + + if (!(message = tnet_dhcp_reply_create())) { /* If REQUEST OP will be overridedden */ + TSK_DEBUG_ERROR("Failed to create new DHCP message."); + goto bail; + } + + dataPtr = (uint8_t*)data; + dataStart = dataPtr; + dataEnd = (dataStart + size); + + /*== op (1)*/ + message->op = *(dataPtr++); + /*== htype (1) */ + message->htype = *(dataPtr++); + /*== hlen (1) */ + message->hlen = *(dataPtr++); + /*== htype (1) */ + message->hops = *(dataPtr++); + /*== xid (4) */ + message->xid = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== secs (2) */ + message->secs = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /*== flags (2) */ + message->flags = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /*== ciaddr (4) */ + message->ciaddr = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== yiaddr (4) */ + message->yiaddr = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== siaddr (4) */ + message->siaddr = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== giaddr (4) */ + message->giaddr = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4; + /*== chaddr (16[max]) */ + memcpy(message->chaddr, dataPtr, message->hlen > 16 ? 16 : message->hlen); + dataPtr += 16; + /*== sname (64) */ + memcpy(message->sname, dataPtr, 64); + dataPtr += 64; + /*== file (128) */ + memcpy(message->file, dataPtr, 128); + dataPtr += 128; + /*== Magic Cookie (4) */ + if (tnet_htonl_2(dataPtr) != TNET_DHCP_MAGIC_COOKIE) { + TSK_DEBUG_ERROR("Invalid DHCP magic cookie."); + // Do not exit ==> continue parsing. + } + dataPtr += 4; + + /*== options (variable) */ + while (dataPtr < dataEnd && *dataPtr != dhcp_code_End) { + tnet_dhcp_option_t* option = tnet_dhcp_option_deserialize(dataPtr, (tsk_size_t)(dataEnd - dataPtr)); + if (option && option->value) { + + if (option->code == dhcp_code_DHCP_Msg_Type) { + message->type = (tnet_dhcp_message_type_t)*TSK_BUFFER_TO_U8(option->value); + } + + dataPtr += option->value->size + 2/*Code Len*/; + tsk_list_push_back_data(message->options, (void**)&option); + } + else { + break; + } + } bail: - return message; + return message; } const tnet_dhcp_option_t* tnet_dhcp_message_find_option(const tnet_dhcp_message_t *message, tnet_dhcp_option_code_t code) { - tsk_list_item_t *item; + tsk_list_item_t *item; - if (!message){ - goto bail; - } + if (!message) { + goto bail; + } - tsk_list_foreach(item, message->options) - { - if (((tnet_dhcp_option_t*)item->data)->code == code){ - return ((tnet_dhcp_option_t*)item->data); - } - } + tsk_list_foreach(item, message->options) { + if (((tnet_dhcp_option_t*)item->data)->code == code) { + return ((tnet_dhcp_option_t*)item->data); + } + } bail: - return 0; + return 0; } int tnet_dhcp_message_add_codes(tnet_dhcp_message_t *self, tnet_dhcp_option_code_t codes[], unsigned codes_count) { - int ret = -1; - - if (!self){ - goto bail; - } - if (codes_count){ - unsigned i; - - tnet_dhcp_option_paramslist_t* option = (tnet_dhcp_option_paramslist_t*)tnet_dhcp_message_find_option(self, dhcp_code_Parameter_List); - if (!option){ - tnet_dhcp_option_paramslist_t *option_paramslist = tnet_dhcp_option_paramslist_create(); - option = option_paramslist; - tsk_list_push_back_data(self->options, (void**)&option_paramslist); - } - - for (i = 0; i < codes_count; i++){ - if ((ret = tnet_dhcp_option_paramslist_add_code(option, codes[i]))){ - break; - } - } - } + int ret = -1; + + if (!self) { + goto bail; + } + if (codes_count) { + unsigned i; + + tnet_dhcp_option_paramslist_t* option = (tnet_dhcp_option_paramslist_t*)tnet_dhcp_message_find_option(self, dhcp_code_Parameter_List); + if (!option) { + tnet_dhcp_option_paramslist_t *option_paramslist = tnet_dhcp_option_paramslist_create(); + option = option_paramslist; + tsk_list_push_back_data(self->options, (void**)&option_paramslist); + } + + for (i = 0; i < codes_count; i++) { + if ((ret = tnet_dhcp_option_paramslist_add_code(option, codes[i]))) { + break; + } + } + } bail: - return ret; + return ret; } @@ -315,35 +313,34 @@ bail: // static tsk_object_t* tnet_dhcp_message_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_message_t *message = self; - if (message){ - static uint32_t __dhcpmessage_unique_xid = 0;//(uint32_t)tsk_time_epoch(); - - message->op = va_arg(*app, tnet_dhcp_message_op_t); - message->htype = tnet_htype_Ethernet_10Mb; - message->hlen = 0x06; - - message->xid = ++(__dhcpmessage_unique_xid); - message->options = tsk_list_create(); - } - return self; + tnet_dhcp_message_t *message = self; + if (message) { + static uint32_t __dhcpmessage_unique_xid = 0;//(uint32_t)tsk_time_epoch(); + + message->op = va_arg(*app, tnet_dhcp_message_op_t); + message->htype = tnet_htype_Ethernet_10Mb; + message->hlen = 0x06; + + message->xid = ++(__dhcpmessage_unique_xid); + message->options = tsk_list_create(); + } + return self; } static tsk_object_t* tnet_dhcp_message_dtor(tsk_object_t * self) { - tnet_dhcp_message_t *message = self; - if (message){ - TSK_OBJECT_SAFE_FREE(message->options); - } - return self; + tnet_dhcp_message_t *message = self; + if (message) { + TSK_OBJECT_SAFE_FREE(message->options); + } + return self; } -static const tsk_object_def_t tnet_dhcp_message_def_s = -{ - sizeof(tnet_dhcp_message_t), - tnet_dhcp_message_ctor, - tnet_dhcp_message_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_message_def_s = { + sizeof(tnet_dhcp_message_t), + tnet_dhcp_message_ctor, + tnet_dhcp_message_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_message_def_t = &tnet_dhcp_message_def_s; diff --git a/tinyNET/src/dhcp/tnet_dhcp_message.h b/tinyNET/src/dhcp/tnet_dhcp_message.h index c7005fa..53ead75 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_message.h +++ b/tinyNET/src/dhcp/tnet_dhcp_message.h @@ -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. * @@ -50,158 +50,155 @@ struct tnet_dhcp_ctx_s; /** List of all supported DHCP message (see RFC 2131). */ -typedef enum tnet_dhcp_message_type_e -{ - /**< DHCPDISCOVER - Client broadcast to locate available servers. - */ - dhcp_type_discover = 1, - - /**< DHCPOFFER - Server to client in response to DHCPDISCOVER with - offer of configuration parameters. - */ - dhcp_type_offer = 2, - - /**< DHCPREQUEST - Client message to servers either (a) requesting - offered parameters from one server and implicitly - declining offers from all others, (b) confirming - correctness of previously allocated address after, - e.g., system reboot, or (c) extending the lease on a - particular network address. - */ - dhcp_type_request = 3, - - /**< DHCPDECLINE - Client to server indicating network address is already +typedef enum tnet_dhcp_message_type_e { + /**< DHCPDISCOVER - Client broadcast to locate available servers. + */ + dhcp_type_discover = 1, + + /**< DHCPOFFER - Server to client in response to DHCPDISCOVER with + offer of configuration parameters. + */ + dhcp_type_offer = 2, + + /**< DHCPREQUEST - Client message to servers either (a) requesting + offered parameters from one server and implicitly + declining offers from all others, (b) confirming + correctness of previously allocated address after, + e.g., system reboot, or (c) extending the lease on a + particular network address. + */ + dhcp_type_request = 3, + + /**< DHCPDECLINE - Client to server indicating network address is already in use. - */ - dhcp_type_decline = 4, - - /**< DHCPACK - Server to client with configuration parameters, - including committed network address. - */ - dhcp_type_ack = 5, - - /**< DHCPNAK - Server to client indicating client's notion of network - address is incorrect (e.g., client has moved to new - subnet) or client's lease as expired - */ - dhcp_type_nack = 6, - - /**< DHCPRELEASE - Client to server relinquishing network address and - cancelling remaining lease. - */ - dhcp_type_release = 7, - - /**< DHCPINFORM - Client to server, asking only for local configuration - parameters; client already has externally configured - network address. - */ - dhcp_type_inform = 8, + */ + dhcp_type_decline = 4, + + /**< DHCPACK - Server to client with configuration parameters, + including committed network address. + */ + dhcp_type_ack = 5, + + /**< DHCPNAK - Server to client indicating client's notion of network + address is incorrect (e.g., client has moved to new + subnet) or client's lease as expired + */ + dhcp_type_nack = 6, + + /**< DHCPRELEASE - Client to server relinquishing network address and + cancelling remaining lease. + */ + dhcp_type_release = 7, + + /**< DHCPINFORM - Client to server, asking only for local configuration + parameters; client already has externally configured + network address. + */ + dhcp_type_inform = 8, } tnet_dhcp_message_type_t; /** DHCP message OP code / message type. */ -typedef enum tnet_dhcp_message_op_e -{ - dhcp_op_bootrequest = 1, - dhcp_op_bootreply = 2 +typedef enum tnet_dhcp_message_op_e { + dhcp_op_bootrequest = 1, + dhcp_op_bootreply = 2 } tnet_dhcp_message_op_t; /** BOOTP/DHCP message as per RFC 2131 subclause 2. */ -typedef struct tnet_dhcp_message_s -{ - TSK_DECLARE_OBJECT; - - /**< DHCP message type. Mandatory. - */ - tnet_dhcp_message_type_t type; - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | op (1) | htype (1) | hlen (1) | hops (1) | - +---------------+---------------+---------------+---------------+ - | xid (4) | - +-------------------------------+-------------------------------+ - | secs (2) | flags (2) | - +-------------------------------+-------------------------------+ - | ciaddr (4) | - +---------------------------------------------------------------+ - | yiaddr (4) | - +---------------------------------------------------------------+ - | siaddr (4) | - +---------------------------------------------------------------+ - | giaddr (4) | - +---------------------------------------------------------------+ - | | - | chaddr (16) | - | | - | | - +---------------------------------------------------------------+ - | | - | sname (64) | - +---------------------------------------------------------------+ - | | - | file (128) | - +---------------------------------------------------------------+ - | | - | options (variable) | - +---------------------------------------------------------------+ - */ - - /**< Message op code / message type (1-byte). +typedef struct tnet_dhcp_message_s { + TSK_DECLARE_OBJECT; + + /**< DHCP message type. Mandatory. + */ + tnet_dhcp_message_type_t type; + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | op (1) | htype (1) | hlen (1) | hops (1) | + +---------------+---------------+---------------+---------------+ + | xid (4) | + +-------------------------------+-------------------------------+ + | secs (2) | flags (2) | + +-------------------------------+-------------------------------+ + | ciaddr (4) | + +---------------------------------------------------------------+ + | yiaddr (4) | + +---------------------------------------------------------------+ + | siaddr (4) | + +---------------------------------------------------------------+ + | giaddr (4) | + +---------------------------------------------------------------+ + | | + | chaddr (16) | + | | + | | + +---------------------------------------------------------------+ + | | + | sname (64) | + +---------------------------------------------------------------+ + | | + | file (128) | + +---------------------------------------------------------------+ + | | + | options (variable) | + +---------------------------------------------------------------+ + */ + + /**< Message op code / message type (1-byte). 1 = BOOTREQUEST, 2 = BOOTREPLY - */ - tnet_dhcp_message_op_t op; - /**< Hardware address type, see ARP section in "Assigned Numbers" RFC; e.g., '1' = 10mb ethernet. - For more information see RFC 1340. - */ + */ + tnet_dhcp_message_op_t op; + /**< Hardware address type, see ARP section in "Assigned Numbers" RFC; e.g., '1' = 10mb ethernet. + For more information see RFC 1340. + */ tnet_hardware_type_t htype; - /**< Hardware address length (e.g. '6' for 10mb ethernet). tsk_strlen(chaddr). - */ + /**< Hardware address length (e.g. '6' for 10mb ethernet). tsk_strlen(chaddr). + */ uint8_t hlen; - /**< Client sets to zero, optionally used by relay agents when booting via a relay agent. - */ + /**< Client sets to zero, optionally used by relay agents when booting via a relay agent. + */ uint8_t hops; - /**< Transaction ID, a random number chosen by the client, used by the client - and server to associate messages and responses between a client and a server. - */ + /**< Transaction ID, a random number chosen by the client, used by the client + and server to associate messages and responses between a client and a server. + */ uint32_t xid; - /**< Filled in by client, seconds elapsed since client began address acquisition or renewal process. - */ + /**< Filled in by client, seconds elapsed since client began address acquisition or renewal process. + */ uint16_t secs; - /**< Flags (see figure 2) - */ + /**< Flags (see figure 2) + */ uint16_t flags; - /**< Client IP address; only filled in if client is in BOUND, RENEW or REBINDING - state and can respond to ARP requests. - */ + /**< Client IP address; only filled in if client is in BOUND, RENEW or REBINDING + state and can respond to ARP requests. + */ uint32_t ciaddr; - /**< 'your' (client) IP address. - */ + /**< 'your' (client) IP address. + */ uint32_t yiaddr; - /**< IP address of next server to use in bootstrap; - returned in DHCPOFFER, DHCPACK by server. - */ + /**< IP address of next server to use in bootstrap; + returned in DHCPOFFER, DHCPACK by server. + */ uint32_t siaddr; - /**< Relay agent IP address, used in booting via a relay agent. - */ + /**< Relay agent IP address, used in booting via a relay agent. + */ uint32_t giaddr; - /**< Client hardware address. - */ + /**< Client hardware address. + */ uint8_t chaddr[16]; - /**< Optional server host name, null terminated string. - */ + /**< Optional server host name, null terminated string. + */ uint8_t sname[64]; - /**<Boot file name, null terminated string; "generic" name or null in DHCPDISCOVER, - fully qualifieddirectory-path name in DHCPOFFER. - */ + /**<Boot file name, null terminated string; "generic" name or null in DHCPDISCOVER, + fully qualifieddirectory-path name in DHCPOFFER. + */ uint8_t file[128]; - /**Optional parameters field. See the options documents for a list of defined options. - For more information please refer to RFC 2132, 1497 and 1533. - */ + /**Optional parameters field. See the options documents for a list of defined options. + For more information please refer to RFC 2132, 1497 and 1533. + */ tnet_dhcp_options_L_t *options; } tnet_dhcp_message_t; diff --git a/tinyNET/src/dhcp/tnet_dhcp_option.c b/tinyNET/src/dhcp/tnet_dhcp_option.c index 3679a62..037d65a 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_option.c +++ b/tinyNET/src/dhcp/tnet_dhcp_option.c @@ -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. * @@ -38,140 +38,132 @@ tnet_dhcp_option_t* tnet_dhcp_option_create(tnet_dhcp_option_code_t code) { - return tsk_object_new(tnet_dhcp_option_def_t, code); + return tsk_object_new(tnet_dhcp_option_def_t, code); } tnet_dhcp_option_paramslist_t* tnet_dhcp_option_paramslist_create() { - return tsk_object_new(tnet_dhcp_option_paramslist_def_t); + return tsk_object_new(tnet_dhcp_option_paramslist_def_t); } tnet_dhcp_option_dns_t* tnet_dhcp_option_dns_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp_option_dns_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp_option_dns_def_t, payload, payload_size); } -/** Initializes DHCPv4 option. +/** Initializes DHCPv4 option. * - * @param [in,out] self The option to initialize. - * @param code The code of the option to initialize. + * @param [in,out] self The option to initialize. + * @param code The code of the option to initialize. * * @return Zero if succeed and non-zero error code otherwise. **/ int tnet_dhcp_option_init(tnet_dhcp_option_t *self, tnet_dhcp_option_code_t code) { - if(self) - { - if(!self->initialized) - { - self->code = code; - //option->value = tsk_buffer_create_null(); - - self->initialized = tsk_true; - return 0; - } - return -2; - } - return -1; + if(self) { + if(!self->initialized) { + self->code = code; + //option->value = tsk_buffer_create_null(); + + self->initialized = tsk_true; + return 0; + } + return -2; + } + return -1; } int tnet_dhcp_option_deinit(tnet_dhcp_option_t *self) { - if(self) - { - if(self->initialized) - { - TSK_OBJECT_SAFE_FREE(self->value); - - self->initialized = tsk_false; - return 0; - } - return -2; - } - return -1; + if(self) { + if(self->initialized) { + TSK_OBJECT_SAFE_FREE(self->value); + + self->initialized = tsk_false; + return 0; + } + return -2; + } + return -1; } tnet_dhcp_option_t* tnet_dhcp_option_deserialize(const void* data, tsk_size_t size) { - tnet_dhcp_option_t *option = 0; - uint8_t* dataPtr = ((uint8_t*)data); - //uint8_t* dataEnd = (dataPtr+size); - - tnet_dhcp_option_code_t code; - uint8_t len; - - /* Check validity */ - if(!dataPtr || size<2/*Code Len*/){ - goto bail; - } - - code = (tnet_dhcp_option_code_t)*dataPtr++; - len = *dataPtr++; - - switch(code) - { - case dhcp_code_SIP_Servers_DHCP_Option: - { - option = (tnet_dhcp_option_t *)tnet_dhcp_option_sip_create(dataPtr, len); - break; - } - - case dhcp_code_Domain_Server: - { - option = (tnet_dhcp_option_t *)tnet_dhcp_option_dns_create(dataPtr, len); - break; - } - - default: - { - option = tnet_dhcp_option_create(code); - } - } - - /* In all case */ - if(option && !option->value && len){ - option->value = tsk_buffer_create((((uint8_t*)data) + 2/*Code Len*/), len); - } + tnet_dhcp_option_t *option = 0; + uint8_t* dataPtr = ((uint8_t*)data); + //uint8_t* dataEnd = (dataPtr+size); + + tnet_dhcp_option_code_t code; + uint8_t len; + + /* Check validity */ + if(!dataPtr || size<2/*Code Len*/) { + goto bail; + } + + code = (tnet_dhcp_option_code_t)*dataPtr++; + len = *dataPtr++; + + switch(code) { + case dhcp_code_SIP_Servers_DHCP_Option: { + option = (tnet_dhcp_option_t *)tnet_dhcp_option_sip_create(dataPtr, len); + break; + } + + case dhcp_code_Domain_Server: { + option = (tnet_dhcp_option_t *)tnet_dhcp_option_dns_create(dataPtr, len); + break; + } + + default: { + option = tnet_dhcp_option_create(code); + } + } + + /* In all case */ + if(option && !option->value && len) { + option->value = tsk_buffer_create((((uint8_t*)data) + 2/*Code Len*/), len); + } bail: - return option; + return option; } int tnet_dhcp_option_serialize(const tnet_dhcp_option_t* self, tsk_buffer_t *output) { - if(!self || !output){ - return -1; - } - - /* Code */ - tsk_buffer_append(output, &(self->code), 1); - - if(self->value){ - /* Length */ - tsk_buffer_append(output, &(self->value->size), 1); - - /* Value */ - tsk_buffer_append(output, self->value->data, self->value->size); - } - else{ - /* Length */ - static uint8_t zero = 0x00; - tsk_buffer_append(output, &zero, 1); - } - - return 0; + if(!self || !output) { + return -1; + } + + /* Code */ + tsk_buffer_append(output, &(self->code), 1); + + if(self->value) { + /* Length */ + tsk_buffer_append(output, &(self->value->size), 1); + + /* Value */ + tsk_buffer_append(output, self->value->data, self->value->size); + } + else { + /* Length */ + static uint8_t zero = 0x00; + tsk_buffer_append(output, &zero, 1); + } + + return 0; } int tnet_dhcp_option_serializeex(tnet_dhcp_option_code_t code, uint8_t length, const void* value, tsk_buffer_t *output) { - if(value && length && output){ - tsk_buffer_append(output, &(code), 1); - tsk_buffer_append(output, &(length), 1); - tsk_buffer_append(output, value, length); - - return 0; - } - return -1; + if(value && length && output) { + tsk_buffer_append(output, &(code), 1); + tsk_buffer_append(output, &(length), 1); + tsk_buffer_append(output, value, length); + + return 0; + } + return -1; } // @@ -179,28 +171,27 @@ int tnet_dhcp_option_serializeex(tnet_dhcp_option_code_t code, uint8_t length, c // static tsk_object_t* tnet_dhcp_option_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_option_t *option = self; - if(option){ - tnet_dhcp_option_init(option, va_arg(*app, tnet_dhcp_option_code_t)); - } - return self; + tnet_dhcp_option_t *option = self; + if(option) { + tnet_dhcp_option_init(option, va_arg(*app, tnet_dhcp_option_code_t)); + } + return self; } -static tsk_object_t* tnet_dhcp_option_dtor(tsk_object_t * self) -{ - tnet_dhcp_option_t *option = self; - if(option){ - tnet_dhcp_option_deinit(option); - } - return self; +static tsk_object_t* tnet_dhcp_option_dtor(tsk_object_t * self) +{ + tnet_dhcp_option_t *option = self; + if(option) { + tnet_dhcp_option_deinit(option); + } + return self; } -static const tsk_object_def_t tnet_dhcp_option_def_s = -{ - sizeof(tnet_dhcp_option_t), - tnet_dhcp_option_ctor, - tnet_dhcp_option_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_option_def_s = { + sizeof(tnet_dhcp_option_t), + tnet_dhcp_option_ctor, + tnet_dhcp_option_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_option_def_t = &tnet_dhcp_option_def_s; @@ -211,13 +202,13 @@ const tsk_object_def_t *tnet_dhcp_option_def_t = &tnet_dhcp_option_def_s; *=======================================================================================*/ int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tnet_dhcp_option_code_t code) { - if(self){ - if(!TNET_DHCP_OPTION(self)->value){ - TNET_DHCP_OPTION(self)->value = tsk_buffer_create_null(); - } - return tsk_buffer_append(TNET_DHCP_OPTION(self)->value, &code, 1); - } - return -1; + if(self) { + if(!TNET_DHCP_OPTION(self)->value) { + TNET_DHCP_OPTION(self)->value = tsk_buffer_create_null(); + } + return tsk_buffer_append(TNET_DHCP_OPTION(self)->value, &code, 1); + } + return -1; } // @@ -225,30 +216,29 @@ int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tn // static tsk_object_t* tnet_dhcp_option_paramslist_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_option_paramslist_t *option = self; - if(option){ - /* init base */ - tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Parameter_List); - } - return self; + tnet_dhcp_option_paramslist_t *option = self; + if(option) { + /* init base */ + tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Parameter_List); + } + return self; } -static tsk_object_t* tnet_dhcp_option_paramslist_dtor(tsk_object_t * self) -{ - tnet_dhcp_option_paramslist_t *option = self; - if(option){ - /* deinit base */ - tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); - } - return self; +static tsk_object_t* tnet_dhcp_option_paramslist_dtor(tsk_object_t * self) +{ + tnet_dhcp_option_paramslist_t *option = self; + if(option) { + /* deinit base */ + tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); + } + return self; } -static const tsk_object_def_t tnet_dhcp_option_paramslist_def_s = -{ - sizeof(tnet_dhcp_option_paramslist_t), - tnet_dhcp_option_paramslist_ctor, - tnet_dhcp_option_paramslist_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_option_paramslist_def_s = { + sizeof(tnet_dhcp_option_paramslist_t), + tnet_dhcp_option_paramslist_ctor, + tnet_dhcp_option_paramslist_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_option_paramslist_def_t = &tnet_dhcp_option_paramslist_def_s; @@ -261,66 +251,65 @@ const tsk_object_def_t *tnet_dhcp_option_paramslist_def_t = &tnet_dhcp_option_pa // static tsk_object_t* tnet_dhcp_option_dns_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_option_dns_t *option = self; - if(option){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - const uint8_t* payloadPtr = (const uint8_t*)payload; - const uint8_t* payloadEnd = (payloadPtr + payload_size); - - /* init base */ - tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Domain_Server); - - option->servers = tsk_list_create(); - - if(payload_size<4 || payload_size%4){ - TSK_DEBUG_ERROR("DHCP - The minimum length for this option is 4 octets, and the length MUST always be a multiple of 4."); - } - else{ - tsk_size_t i; - char* ip4 = 0; - uint32_t address; - tsk_string_t* addrstring; - - for(i=0; i<payload_size && (payloadPtr< payloadEnd); i+=4){ - /* - Code Len Address 1 Address 2 - +-----+-----+-----+-----+-----+-----+-----+-----+-- - | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... - +-----+-----+-----+-----+-----+-----+-----+-----+-- - */ - address = (uint32_t)tnet_htonl_2(payloadPtr); - tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); - - addrstring = tsk_string_create(ip4); - tsk_list_push_back_data(option->servers, (void*)&addrstring); - - TSK_FREE(ip4); - payloadPtr+= 4; - } - } - } - return self; + tnet_dhcp_option_dns_t *option = self; + if(option) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + const uint8_t* payloadPtr = (const uint8_t*)payload; + const uint8_t* payloadEnd = (payloadPtr + payload_size); + + /* init base */ + tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_Domain_Server); + + option->servers = tsk_list_create(); + + if(payload_size<4 || payload_size%4) { + TSK_DEBUG_ERROR("DHCP - The minimum length for this option is 4 octets, and the length MUST always be a multiple of 4."); + } + else { + tsk_size_t i; + char* ip4 = 0; + uint32_t address; + tsk_string_t* addrstring; + + for(i=0; i<payload_size && (payloadPtr< payloadEnd); i+=4) { + /* + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + address = (uint32_t)tnet_htonl_2(payloadPtr); + tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); + + addrstring = tsk_string_create(ip4); + tsk_list_push_back_data(option->servers, (void*)&addrstring); + + TSK_FREE(ip4); + payloadPtr+= 4; + } + } + } + return self; } -static tsk_object_t* tnet_dhcp_option_dns_dtor(tsk_object_t * self) -{ - tnet_dhcp_option_dns_t *option = self; - if(option){ - /* deinit base */ - tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); - - TSK_OBJECT_SAFE_FREE(option->servers); - } - return self; +static tsk_object_t* tnet_dhcp_option_dns_dtor(tsk_object_t * self) +{ + tnet_dhcp_option_dns_t *option = self; + if(option) { + /* deinit base */ + tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); + + TSK_OBJECT_SAFE_FREE(option->servers); + } + return self; } -static const tsk_object_def_t tnet_dhcp_option_dns_def_s = -{ - sizeof(tnet_dhcp_option_dns_t), - tnet_dhcp_option_dns_ctor, - tnet_dhcp_option_dns_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp_option_dns_def_s = { + sizeof(tnet_dhcp_option_dns_t), + tnet_dhcp_option_dns_ctor, + tnet_dhcp_option_dns_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_option_dns_def_t = &tnet_dhcp_option_dns_def_s; diff --git a/tinyNET/src/dhcp/tnet_dhcp_option.h b/tinyNET/src/dhcp/tnet_dhcp_option.h index 0d16ac1..db3ac16 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_option.h +++ b/tinyNET/src/dhcp/tnet_dhcp_option.h @@ -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. * @@ -39,191 +39,189 @@ TNET_BEGIN_DECLS #define TNET_DHCP_OPTION(self) ((tnet_dhcp_option_t*)(self)) -typedef enum tnet_dhcp_option_code_e -{ - dhcp_code_Pad= 0 ,/**< Pad 0 None [RFC2132] */ - dhcp_code_Subnet_Mask= 1 ,/**< Subnet Mask 4 Subnet Mask Value [RFC2132] */ - dhcp_code_Time_Offset= 2 ,/**< Time Offset 4 Time Offset in Seconds from UTC [RFC2132] (note: deprecated by 100 and 101) */ - dhcp_code_Router= 3 ,/**< Router N N/4 Router addresses [RFC2132] */ - dhcp_code_Time_Server= 4 ,/**< Time Server N N/4 Timeserver addresses [RFC2132] */ - dhcp_code_Name_Server= 5 ,/**< Name Server N N/4 IEN-116 Server addresses [RFC2132] */ - dhcp_code_Domain_Server= 6 ,/**< Domain Server N N/4 DNS Server addresses [RFC2132] */ - dhcp_code_Log_Server= 7 ,/**< Log Server N N/4 Logging Server addresses [RFC2132] */ - dhcp_code_Quotes_Server= 8 ,/**< Quotes Server N N/4 Quotes Server addresses [RFC2132] */ - dhcp_code_LPR_Server= 9 ,/**< LPR Server N N/4 Printer Server addresses [RFC2132] */ - dhcp_code_Impress_Server= 10 ,/**< Impress Server N N/4 Impress Server addresses [RFC2132] */ - dhcp_code_RLP_Server= 11 ,/**< RLP Server N N/4 RLP Server addresses [RFC2132] */ - dhcp_code_Hostname= 12 ,/**< Hostname N Hostname string [RFC2132] */ - dhcp_code_Boot_File_Size= 13 ,/**< Boot File Size 2 Size of boot file in 512 byte chunks [RFC2132] */ - dhcp_code_Merit_Dump_File= 14 ,/**< Merit Dump File N Client to dump and name the file to dump it to [RFC2132] */ - dhcp_code_Domain_Name= 15 ,/**< Domain Name N The DNS domain name of the client [RFC2132] */ - dhcp_code_Swap_Server= 16 ,/**< Swap Server N Swap Server address [RFC2132] */ - dhcp_code_Root_Path= 17 ,/**< Root Path N Path name for root disk [RFC2132] */ - dhcp_code_Extension_File= 18 ,/**< Extension File N Path name for more BOOTP info [RFC2132] */ - dhcp_code_Forward_On_Off= 19 ,/**< Forward On/Off 1 Enable/Disable IP Forwarding [RFC2132] */ - dhcp_code_SrcRte_On_Off = 20 ,/**< SrcRte On/Off 1 Enable/Disable Source Routing [RFC2132] */ - dhcp_code_Policy_Filter= 21 ,/**< Policy Filter N Routing Policy Filters [RFC2132] */ - dhcp_code_Max_DG_Assembly= 22 ,/**< Max DG Assembly 2 Max Datagram Reassembly Size [RFC2132] */ - dhcp_code_Default_IP_TTL= 23 ,/**< Default IP TTL 1 Default IP Time to Live [RFC2132] */ - dhcp_code_MTU_Timeout= 24 ,/**< MTU Timeout 4 Path MTU Aging Timeout [RFC2132] */ - dhcp_code_MTU_Plateau= 25 ,/**< MTU Plateau N Path MTU Plateau Table [RFC2132] */ - dhcp_code_MTU_Interface= 26 ,/**< MTU Interface 2 Interface MTU Size [RFC2132] */ - dhcp_code_MTU_Subnet= 27 ,/**< MTU Subnet 1 All Subnets are Local [RFC2132] */ - dhcp_code_Broadcast_Address= 28 ,/**< Broadcast Address 4 Broadcast Address [RFC2132] */ - dhcp_code_Mask_Discovery= 29 ,/**< Mask Discovery 1 Perform Mask Discovery [RFC2132] */ - dhcp_code_Mask_Supplier= 30 ,/**< Mask Supplier 1 Provide Mask to Others [RFC2132] */ - dhcp_code_Router_Discovery= 31 ,/**< Router Discovery 1 Perform Router Discovery [RFC2132] */ - dhcp_code_Router_Request= 32 ,/**< Router Request 4 Router Solicitation Address [RFC2132] */ - dhcp_code_Static_Route= 33 ,/**< Static Route N Static Routing Table [RFC2132] */ - dhcp_code_Trailers= 34 ,/**< Trailers 1 Trailer Encapsulation [RFC2132] */ - dhcp_code_ARP_Timeout= 35 ,/**< ARP Timeout 4 ARP Cache Timeout [RFC2132] */ - dhcp_code_Ethernet= 36 ,/**< Ethernet 1 Ethernet Encapsulation [RFC2132] */ - dhcp_code_Default_TCP_TTL= 37 ,/**< Default TCP TTL 1 Default TCP Time to Live [RFC2132] */ - dhcp_code_Keepalive_Time= 38 ,/**< Keepalive Time 4 TCP Keepalive Interval [RFC2132] */ - dhcp_code_Keepalive_Data= 39 ,/**< Keepalive Data 1 TCP Keepalive Garbage [RFC2132] */ - dhcp_code_NIS_Domain= 40 ,/**< NIS Domain N NIS Domain Name [RFC2132] */ - dhcp_code_NIS_Servers= 41 ,/**< NIS Servers N NIS Server Addresses [RFC2132] */ - dhcp_code_NTP_Servers= 42 ,/**< NTP Servers N NTP Server Addresses [RFC2132] */ - dhcp_code_Vendor_Specific= 43 ,/**< Vendor Specific N Vendor Specific Information [RFC2132] */ - dhcp_code_NETBIOS_Name_Srv= 44 ,/**< NETBIOS Name Srv N NETBIOS Name Servers [RFC2132] */ - dhcp_code_NETBIOS_Dist_Srv= 45 ,/**< NETBIOS Dist Srv N NETBIOS Datagram Distribution [RFC2132] */ - dhcp_code_NETBIOS_Node_Type= 46 ,/**< NETBIOS Node Type 1 NETBIOS Node Type [RFC2132] */ - dhcp_code_NETBIOS_Scope= 47 ,/**< NETBIOS Scope N NETBIOS Scope [RFC2132] */ - dhcp_code_X_Window_Font= 48 ,/**< X Window Font N X Window Font Server [RFC2132] */ - dhcp_code_X_Window_Manager= 49 ,/**< X Window Manager N X Window Display Manager [RFC2132] */ - dhcp_code_Address_Request= 50 ,/**< Address Request 4 Requested IP Address [RFC2132] */ - dhcp_code_Address_Time= 51 ,/**< Address Time 4 IP Address Lease Time [RFC2132] */ - dhcp_code_Overload= 52 ,/**< Overload 1 Overload "sname" or "file" [RFC2132] */ - dhcp_code_DHCP_Msg_Type= 53 ,/**< DHCP Msg Type 1 DHCP Message Type [RFC2132] */ - dhcp_code_DHCP_Server_Id= 54 ,/**< DHCP Server Id 4 DHCP Server Identification [RFC2132] */ - dhcp_code_Parameter_List= 55 ,/**< Parameter List N Parameter Request List [RFC2132] */ - dhcp_code_DHCP_Error_Message= 56 ,/**< DHCP Message N DHCP Error Message [RFC2132] */ - dhcp_code_DHCP_Max_Msg_Size= 57 ,/**< DHCP Max Msg Size 2 DHCP Maximum Message Size [RFC2132] */ - dhcp_code_Renewal_Time= 58 ,/**< Renewal Time 4 DHCP Renewal (T1) Time [RFC2132] */ - dhcp_code_Rebinding_Time= 59 ,/**< Rebinding Time 4 DHCP Rebinding (T2) Time [RFC2132] */ - dhcp_code_Class_Id= 60 ,/**< Class Id N Class Identifier [RFC2132] */ - dhcp_code_Client_Id= 61 ,/**< Client Id N Client Identifier [RFC2132] */ - dhcp_code_NetWare_IP_Domain= 62 ,/**< NetWare/IP Domain N NetWare/IP Domain Name [RFC2242] */ - dhcp_code_NetWare_IP_Option= 63 ,/**< NetWare/IP Option N NetWare/IP sub Options [RFC2242] */ - dhcp_code_NIS_Domain_Name= 64 ,/**< NIS-Domain-Name N NIS+ v3 Client Domain Name [RFC2132] */ - dhcp_code_NIS_Server_Addr = 65 ,/**< NIS-Server-Addr N NIS+ v3 Server Addresses [RFC2132] */ - dhcp_code_Server_Name= 66 ,/**< Server-Name N TFTP Server Name [RFC2132] */ - dhcp_code_Bootfile_Name= 67 ,/**< Bootfile-Name N Boot File Name [RFC2132] */ - dhcp_code_Home_Agent_Addrs= 68 ,/**< Home-Agent-Addrs N Home Agent Addresses [RFC2132] */ - dhcp_code_SMTP_Server= 69 ,/**< SMTP-Server N Simple Mail Server Addresses [RFC2132] */ - dhcp_code_POP3_Server= 70 ,/**< POP3-Server N Post Office Server Addresses [RFC2132] */ - dhcp_code_NNTP_Server= 71 ,/**< NNTP-Server N Network News Server Addresses [RFC2132] */ - dhcp_code_WWW_Server= 72 ,/**< WWW-Server N WWW Server Addresses [RFC2132] */ - dhcp_code_Finger_Server= 73 ,/**< Finger-Server N Finger Server Addresses [RFC2132] */ - dhcp_code_IRC_Server= 74 ,/**< IRC-Server N Chat Server Addresses [RFC2132] */ - dhcp_code_StreetTalk_Server= 75 ,/**< StreetTalk-Server N StreetTalk Server Addresses [RFC2132] */ - dhcp_code_STDA_Server= 76 ,/**< STDA-Server N ST Directory Assist. Addresses [RFC2132] */ - dhcp_code_User_Class= 77 ,/**< User-Class N User Class Information [RFC3004] */ - dhcp_code_Directory_Agent = 78 ,/**< Directory Agent N directory agent information [RFC2610] */ - dhcp_code_Service_Scope = 79 ,/**< Service Scope N service location agent scope [RFC2610] */ - dhcp_code_Rapid_Commit= 80 ,/**< Rapid Commit 0 Rapid Commit [RFC4039] */ - dhcp_code_Client_FQDN = 81 ,/**< Client FQDN N Fully Qualified Domain Name [RFC4702] */ - dhcp_code_Relay_Agent_Information= 82 ,/**< Relay Agent Information N Relay Agent Information [RFC3046] */ - dhcp_code_iSNS= 83 ,/**< iSNS N Internet Storage Name Service [RFC4174] */ - //84 REMOVED/Unassigned [RFC3679] */ - dhcp_code_NDS_Servers= 85 ,/**< NDS Servers N Novell Directory Services [RFC2241] */ - dhcp_code_NDS_Tree_Name= 86 ,/**< NDS Tree Name N Novell Directory Services [RFC2241] */ - dhcp_code_NDS_Context= 87 ,/**< NDS Context N Novell Directory Services [RFC2241] */ - dhcp_code_BCMCS_Controller_Domain_Name_list= 88 ,/**< BCMCS Controller Domain Name list [RFC4280] */ - dhcp_code_BCMCS_Controller_IPv4_address_option= 89 ,/**< BCMCS Controller IPv4 address option [RFC4280] */ - dhcp_code_Authentication= 90 ,/**< Authentication N Authentication [RFC3118] */ - dhcp_code_client_last_transaction_time= 91 ,/**< client-last-transaction-time option [RFC4388] */ - dhcp_code_associated_ip= 92 ,/**< associated-ip option [RFC4388] */ - dhcp_code_Client_System = 93 ,/**< Client System N Client System Architecture [RFC4578] */ - dhcp_code_Client_NDI = 94 ,/**< Client NDI N Client Network Device Interface [RFC4578] */ - dhcp_code_LDAP= 95 ,/**< LDAP N Lightweight Directory Access Protocol [RFC3679] */ - dhcp_code_REMOVED_Unassigned= 96 ,/**< REMOVED/Unassigned [RFC3679] */ - dhcp_code_UUID_GUID= 97 ,/**< UUID/GUID N UUID/GUID-based Client Identifier [RFC4578] */ - dhcp_code_User_Auth= 98 ,/**< User-Auth N Open Group's User Authentication [RFC2485] */ - dhcp_code_GEOCONF_CIVIC= 99 ,/**< GEOCONF_CIVIC [RFC4776] */ - dhcp_code_PCode= 100 ,/**< PCode N IEEE 1003.1 TZ String [RFC4833] */ - dhcp_code_TCode= 101 ,/**< TCode N Reference to the TZ Database [RFC4833] */ - //102-107 REMOVED/Unassigned [RFC3679] - //108 REMOVED/Unassigned [RFC3679] - //109 Unassigned [RFC3679] - //110 REMOVED/Unassigned [RFC3679] - //111 Unassigned [RFC3679] - dhcp_code_Netinfo_Address= 112 ,/**< Netinfo Address N NetInfo Parent Server Address [RFC3679] */ - dhcp_code_Netinfo_Tag= 113 ,/**< Netinfo Tag N NetInfo Parent Server Tag [RFC3679] */ - dhcp_code_= 114 ,/**< URL N URL [RFC3679] */ - //115 REMOVED/Unassigned [RFC3679] - dhcp_code_Auto_Config= 116 ,/**< Auto-Config N DHCP Auto-Configuration [RFC2563] */ - dhcp_code_Name_Service_Search= 117 ,/**< Name Service Search N Name Service Search [RFC2937] */ - dhcp_code_Subnet_Selection_Option= 118 ,/**< Subnet Selection Option 4 Subnet Selection Option [RFC3011] */ - dhcp_code_Domain_Search= 119 ,/**< Domain Search N DNS domain search list [RFC3397] */ - dhcp_code_SIP_Servers_DHCP_Option= 120 ,/**< SIP Servers DHCP Option N SIP Servers DHCP Option [RFC3361] */ - dhcp_code_Classless_Static_Route_Option= 121 ,/**< Classless Static Route Option N Classless Static Route Option [RFC3442] */ - dhcp_code_CCC= 122 ,/**< CCC N CableLabs Client Configuration [RFC3495] */ - dhcp_code_GeoConf_Option= 123 ,/**< GeoConf Option 16 GeoConf Option [RFC3825] */ - dhcp_code_V_I_Vendor_Class= 124 ,/**< V-I Vendor Class Vendor-Identifying Vendor Class [RFC3925] */ - dhcp_code_V_I_Vendor_Specific_Information= 125 ,/**< V-I Vendor-Specific Information Vendor-Identifying Vendor-Specific Information [RFC3925] */ - //dhcp_code_= 126 ,/**< Removed/Unassigned [RFC3679] */ - //dhcp_code_= 127 ,/**< Removed/Unassigned [RFC3679] */ - //dhcp_code_PXE - undefined= 128 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_Etherboot_signature= 128 ,/**< Etherboot signature. 6 bytes: E4:45:74:68:00:00 */ - dhcp_code_DOCSIS= 128 ,/**< DOCSIS "full security" server IP address */ - dhcp_code_TFTP_Server_IP= 128 ,/**< TFTP Server IP address (for IP Phone software load) */ - //dhcp_code_= 129 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_Kernel_options= 129 ,/**< Kernel options. Variable length string */ - dhcp_code_Call_Server_IP= 129 ,/**< Call Server IP address */ - //dhcp_code_= 130 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_Ethernet_interface= 130 ,/**< Ethernet interface. Variable length string. */ - dhcp_code_Discrimination= 130 ,/**< Discrimination string (to identify vendor) */ - //dhcp_code_= 131 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_Remote_statistics_server_IP= 131 ,/**< Remote statistics server IP address */ - //dhcp_code_= 132 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_IEEE_802_1Q_VLAN_ID= 132 ,/**< IEEE 802.1Q VLAN ID */ - //dhcp_code_= 133 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_IEEE_802_1D_p= 133 ,/**< IEEE 802.1D/p Layer 2 Priority */ - //dhcp_code_= 134 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_DSCP= 134 ,/**< Diffserv Code Point (DSCP) for VoIP signalling and media streams */ - //dhcp_code_= 135 ,/**< PXE - undefined (vendor specific) [RFC4578] */ - dhcp_code_HTTP_Proxy= 135 ,/**< HTTP Proxy for phone-specific applications */ - dhcp_code_OPTION_PANA_AGENT= 136 ,/**< OPTION_PANA_AGENT [RFC5192] */ - dhcp_code_OPTION_V4_LOST= 137 ,/**< OPTION_V4_LOST [RFC5223] */ - dhcp_code_OPTION_CAPWAP_AC_V4= 138 ,/**< OPTION_CAPWAP_AC_V4 N CAPWAP Access Controller addresses [RFC5417] */ - dhcp_code_OPTION_IPv4_Address_MoS= 139 ,/**< OPTION-IPv4_Address-MoS N a series of suboptions [RFC5678] */ - dhcp_code_OPTION_IPv4_FQDN_MoS= 140 ,/**< OPTION-IPv4_FQDN-MoS N a series of suboptions [RFC5678] */ - //141-149 Unassigned [RFC3942] */ - dhcp_code_TFTP_server_address= 150 ,/**< TFTP server address (Tentatively Assigned - 2005-06-23) */ - dhcp_code_Etherboot= 150 ,/**< Etherboot */ - dhcp_code_GRUB_configuration_path_name= 150 ,/**< GRUB configuration path name */ - //151-174 Unassigned [RFC3942] - //dhcp_code_Etherboot= 175 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */ - dhcp_code_IP_Telephone= 176 ,/**< IP Telephone (Tentatively Assigned - 2005-06-23) */ - //dhcp_code_Etherboot= 177 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */ - dhcp_code_PacketCable_and_CableHome= 177 ,/**< PacketCable and CableHome (replaced by 122) */ - //178-207 Unassigned [RFC3942] - dhcp_code_PXELINUX_Magic= 208 ,/**< PXELINUX Magic 4 magic string = F1:00:74:7E [RFC5071] Deprecated */ - dhcp_code_Configuration_File= 209 ,/**< Configuration File N Configuration file [RFC5071] */ - dhcp_code_Path_Prefix= 210 ,/**< Path Prefix N Path Prefix Option [RFC5071] */ - dhcp_code_Reboot_Time = 211 ,/**< Reboot Time 4 Reboot Time [RFC5071] */ - // 212-219 Unassigned - dhcp_code_Subnet_Allocation= 220 ,/**< Subnet Allocation Option (Tentatively Assigned - 2005-06-23) */ - dhcp_code_Virtual_Subnet= 221 ,/**< Virtual Subnet Selection Option (Tentatively Assigned - 2005-06-23) */ - // 222-223 Unassigned [RFC3942] - //224-254 Reserved (Private Use) - dhcp_code_null=224 , - dhcp_code_End= 255 ,/**< End 0 None [RFC2132] */ +typedef enum tnet_dhcp_option_code_e { + dhcp_code_Pad= 0 ,/**< Pad 0 None [RFC2132] */ + dhcp_code_Subnet_Mask= 1 ,/**< Subnet Mask 4 Subnet Mask Value [RFC2132] */ + dhcp_code_Time_Offset= 2 ,/**< Time Offset 4 Time Offset in Seconds from UTC [RFC2132] (note: deprecated by 100 and 101) */ + dhcp_code_Router= 3 ,/**< Router N N/4 Router addresses [RFC2132] */ + dhcp_code_Time_Server= 4 ,/**< Time Server N N/4 Timeserver addresses [RFC2132] */ + dhcp_code_Name_Server= 5 ,/**< Name Server N N/4 IEN-116 Server addresses [RFC2132] */ + dhcp_code_Domain_Server= 6 ,/**< Domain Server N N/4 DNS Server addresses [RFC2132] */ + dhcp_code_Log_Server= 7 ,/**< Log Server N N/4 Logging Server addresses [RFC2132] */ + dhcp_code_Quotes_Server= 8 ,/**< Quotes Server N N/4 Quotes Server addresses [RFC2132] */ + dhcp_code_LPR_Server= 9 ,/**< LPR Server N N/4 Printer Server addresses [RFC2132] */ + dhcp_code_Impress_Server= 10 ,/**< Impress Server N N/4 Impress Server addresses [RFC2132] */ + dhcp_code_RLP_Server= 11 ,/**< RLP Server N N/4 RLP Server addresses [RFC2132] */ + dhcp_code_Hostname= 12 ,/**< Hostname N Hostname string [RFC2132] */ + dhcp_code_Boot_File_Size= 13 ,/**< Boot File Size 2 Size of boot file in 512 byte chunks [RFC2132] */ + dhcp_code_Merit_Dump_File= 14 ,/**< Merit Dump File N Client to dump and name the file to dump it to [RFC2132] */ + dhcp_code_Domain_Name= 15 ,/**< Domain Name N The DNS domain name of the client [RFC2132] */ + dhcp_code_Swap_Server= 16 ,/**< Swap Server N Swap Server address [RFC2132] */ + dhcp_code_Root_Path= 17 ,/**< Root Path N Path name for root disk [RFC2132] */ + dhcp_code_Extension_File= 18 ,/**< Extension File N Path name for more BOOTP info [RFC2132] */ + dhcp_code_Forward_On_Off= 19 ,/**< Forward On/Off 1 Enable/Disable IP Forwarding [RFC2132] */ + dhcp_code_SrcRte_On_Off = 20 ,/**< SrcRte On/Off 1 Enable/Disable Source Routing [RFC2132] */ + dhcp_code_Policy_Filter= 21 ,/**< Policy Filter N Routing Policy Filters [RFC2132] */ + dhcp_code_Max_DG_Assembly= 22 ,/**< Max DG Assembly 2 Max Datagram Reassembly Size [RFC2132] */ + dhcp_code_Default_IP_TTL= 23 ,/**< Default IP TTL 1 Default IP Time to Live [RFC2132] */ + dhcp_code_MTU_Timeout= 24 ,/**< MTU Timeout 4 Path MTU Aging Timeout [RFC2132] */ + dhcp_code_MTU_Plateau= 25 ,/**< MTU Plateau N Path MTU Plateau Table [RFC2132] */ + dhcp_code_MTU_Interface= 26 ,/**< MTU Interface 2 Interface MTU Size [RFC2132] */ + dhcp_code_MTU_Subnet= 27 ,/**< MTU Subnet 1 All Subnets are Local [RFC2132] */ + dhcp_code_Broadcast_Address= 28 ,/**< Broadcast Address 4 Broadcast Address [RFC2132] */ + dhcp_code_Mask_Discovery= 29 ,/**< Mask Discovery 1 Perform Mask Discovery [RFC2132] */ + dhcp_code_Mask_Supplier= 30 ,/**< Mask Supplier 1 Provide Mask to Others [RFC2132] */ + dhcp_code_Router_Discovery= 31 ,/**< Router Discovery 1 Perform Router Discovery [RFC2132] */ + dhcp_code_Router_Request= 32 ,/**< Router Request 4 Router Solicitation Address [RFC2132] */ + dhcp_code_Static_Route= 33 ,/**< Static Route N Static Routing Table [RFC2132] */ + dhcp_code_Trailers= 34 ,/**< Trailers 1 Trailer Encapsulation [RFC2132] */ + dhcp_code_ARP_Timeout= 35 ,/**< ARP Timeout 4 ARP Cache Timeout [RFC2132] */ + dhcp_code_Ethernet= 36 ,/**< Ethernet 1 Ethernet Encapsulation [RFC2132] */ + dhcp_code_Default_TCP_TTL= 37 ,/**< Default TCP TTL 1 Default TCP Time to Live [RFC2132] */ + dhcp_code_Keepalive_Time= 38 ,/**< Keepalive Time 4 TCP Keepalive Interval [RFC2132] */ + dhcp_code_Keepalive_Data= 39 ,/**< Keepalive Data 1 TCP Keepalive Garbage [RFC2132] */ + dhcp_code_NIS_Domain= 40 ,/**< NIS Domain N NIS Domain Name [RFC2132] */ + dhcp_code_NIS_Servers= 41 ,/**< NIS Servers N NIS Server Addresses [RFC2132] */ + dhcp_code_NTP_Servers= 42 ,/**< NTP Servers N NTP Server Addresses [RFC2132] */ + dhcp_code_Vendor_Specific= 43 ,/**< Vendor Specific N Vendor Specific Information [RFC2132] */ + dhcp_code_NETBIOS_Name_Srv= 44 ,/**< NETBIOS Name Srv N NETBIOS Name Servers [RFC2132] */ + dhcp_code_NETBIOS_Dist_Srv= 45 ,/**< NETBIOS Dist Srv N NETBIOS Datagram Distribution [RFC2132] */ + dhcp_code_NETBIOS_Node_Type= 46 ,/**< NETBIOS Node Type 1 NETBIOS Node Type [RFC2132] */ + dhcp_code_NETBIOS_Scope= 47 ,/**< NETBIOS Scope N NETBIOS Scope [RFC2132] */ + dhcp_code_X_Window_Font= 48 ,/**< X Window Font N X Window Font Server [RFC2132] */ + dhcp_code_X_Window_Manager= 49 ,/**< X Window Manager N X Window Display Manager [RFC2132] */ + dhcp_code_Address_Request= 50 ,/**< Address Request 4 Requested IP Address [RFC2132] */ + dhcp_code_Address_Time= 51 ,/**< Address Time 4 IP Address Lease Time [RFC2132] */ + dhcp_code_Overload= 52 ,/**< Overload 1 Overload "sname" or "file" [RFC2132] */ + dhcp_code_DHCP_Msg_Type= 53 ,/**< DHCP Msg Type 1 DHCP Message Type [RFC2132] */ + dhcp_code_DHCP_Server_Id= 54 ,/**< DHCP Server Id 4 DHCP Server Identification [RFC2132] */ + dhcp_code_Parameter_List= 55 ,/**< Parameter List N Parameter Request List [RFC2132] */ + dhcp_code_DHCP_Error_Message= 56 ,/**< DHCP Message N DHCP Error Message [RFC2132] */ + dhcp_code_DHCP_Max_Msg_Size= 57 ,/**< DHCP Max Msg Size 2 DHCP Maximum Message Size [RFC2132] */ + dhcp_code_Renewal_Time= 58 ,/**< Renewal Time 4 DHCP Renewal (T1) Time [RFC2132] */ + dhcp_code_Rebinding_Time= 59 ,/**< Rebinding Time 4 DHCP Rebinding (T2) Time [RFC2132] */ + dhcp_code_Class_Id= 60 ,/**< Class Id N Class Identifier [RFC2132] */ + dhcp_code_Client_Id= 61 ,/**< Client Id N Client Identifier [RFC2132] */ + dhcp_code_NetWare_IP_Domain= 62 ,/**< NetWare/IP Domain N NetWare/IP Domain Name [RFC2242] */ + dhcp_code_NetWare_IP_Option= 63 ,/**< NetWare/IP Option N NetWare/IP sub Options [RFC2242] */ + dhcp_code_NIS_Domain_Name= 64 ,/**< NIS-Domain-Name N NIS+ v3 Client Domain Name [RFC2132] */ + dhcp_code_NIS_Server_Addr = 65 ,/**< NIS-Server-Addr N NIS+ v3 Server Addresses [RFC2132] */ + dhcp_code_Server_Name= 66 ,/**< Server-Name N TFTP Server Name [RFC2132] */ + dhcp_code_Bootfile_Name= 67 ,/**< Bootfile-Name N Boot File Name [RFC2132] */ + dhcp_code_Home_Agent_Addrs= 68 ,/**< Home-Agent-Addrs N Home Agent Addresses [RFC2132] */ + dhcp_code_SMTP_Server= 69 ,/**< SMTP-Server N Simple Mail Server Addresses [RFC2132] */ + dhcp_code_POP3_Server= 70 ,/**< POP3-Server N Post Office Server Addresses [RFC2132] */ + dhcp_code_NNTP_Server= 71 ,/**< NNTP-Server N Network News Server Addresses [RFC2132] */ + dhcp_code_WWW_Server= 72 ,/**< WWW-Server N WWW Server Addresses [RFC2132] */ + dhcp_code_Finger_Server= 73 ,/**< Finger-Server N Finger Server Addresses [RFC2132] */ + dhcp_code_IRC_Server= 74 ,/**< IRC-Server N Chat Server Addresses [RFC2132] */ + dhcp_code_StreetTalk_Server= 75 ,/**< StreetTalk-Server N StreetTalk Server Addresses [RFC2132] */ + dhcp_code_STDA_Server= 76 ,/**< STDA-Server N ST Directory Assist. Addresses [RFC2132] */ + dhcp_code_User_Class= 77 ,/**< User-Class N User Class Information [RFC3004] */ + dhcp_code_Directory_Agent = 78 ,/**< Directory Agent N directory agent information [RFC2610] */ + dhcp_code_Service_Scope = 79 ,/**< Service Scope N service location agent scope [RFC2610] */ + dhcp_code_Rapid_Commit= 80 ,/**< Rapid Commit 0 Rapid Commit [RFC4039] */ + dhcp_code_Client_FQDN = 81 ,/**< Client FQDN N Fully Qualified Domain Name [RFC4702] */ + dhcp_code_Relay_Agent_Information= 82 ,/**< Relay Agent Information N Relay Agent Information [RFC3046] */ + dhcp_code_iSNS= 83 ,/**< iSNS N Internet Storage Name Service [RFC4174] */ + //84 REMOVED/Unassigned [RFC3679] */ + dhcp_code_NDS_Servers= 85 ,/**< NDS Servers N Novell Directory Services [RFC2241] */ + dhcp_code_NDS_Tree_Name= 86 ,/**< NDS Tree Name N Novell Directory Services [RFC2241] */ + dhcp_code_NDS_Context= 87 ,/**< NDS Context N Novell Directory Services [RFC2241] */ + dhcp_code_BCMCS_Controller_Domain_Name_list= 88 ,/**< BCMCS Controller Domain Name list [RFC4280] */ + dhcp_code_BCMCS_Controller_IPv4_address_option= 89 ,/**< BCMCS Controller IPv4 address option [RFC4280] */ + dhcp_code_Authentication= 90 ,/**< Authentication N Authentication [RFC3118] */ + dhcp_code_client_last_transaction_time= 91 ,/**< client-last-transaction-time option [RFC4388] */ + dhcp_code_associated_ip= 92 ,/**< associated-ip option [RFC4388] */ + dhcp_code_Client_System = 93 ,/**< Client System N Client System Architecture [RFC4578] */ + dhcp_code_Client_NDI = 94 ,/**< Client NDI N Client Network Device Interface [RFC4578] */ + dhcp_code_LDAP= 95 ,/**< LDAP N Lightweight Directory Access Protocol [RFC3679] */ + dhcp_code_REMOVED_Unassigned= 96 ,/**< REMOVED/Unassigned [RFC3679] */ + dhcp_code_UUID_GUID= 97 ,/**< UUID/GUID N UUID/GUID-based Client Identifier [RFC4578] */ + dhcp_code_User_Auth= 98 ,/**< User-Auth N Open Group's User Authentication [RFC2485] */ + dhcp_code_GEOCONF_CIVIC= 99 ,/**< GEOCONF_CIVIC [RFC4776] */ + dhcp_code_PCode= 100 ,/**< PCode N IEEE 1003.1 TZ String [RFC4833] */ + dhcp_code_TCode= 101 ,/**< TCode N Reference to the TZ Database [RFC4833] */ + //102-107 REMOVED/Unassigned [RFC3679] + //108 REMOVED/Unassigned [RFC3679] + //109 Unassigned [RFC3679] + //110 REMOVED/Unassigned [RFC3679] + //111 Unassigned [RFC3679] + dhcp_code_Netinfo_Address= 112 ,/**< Netinfo Address N NetInfo Parent Server Address [RFC3679] */ + dhcp_code_Netinfo_Tag= 113 ,/**< Netinfo Tag N NetInfo Parent Server Tag [RFC3679] */ + dhcp_code_= 114 ,/**< URL N URL [RFC3679] */ + //115 REMOVED/Unassigned [RFC3679] + dhcp_code_Auto_Config= 116 ,/**< Auto-Config N DHCP Auto-Configuration [RFC2563] */ + dhcp_code_Name_Service_Search= 117 ,/**< Name Service Search N Name Service Search [RFC2937] */ + dhcp_code_Subnet_Selection_Option= 118 ,/**< Subnet Selection Option 4 Subnet Selection Option [RFC3011] */ + dhcp_code_Domain_Search= 119 ,/**< Domain Search N DNS domain search list [RFC3397] */ + dhcp_code_SIP_Servers_DHCP_Option= 120 ,/**< SIP Servers DHCP Option N SIP Servers DHCP Option [RFC3361] */ + dhcp_code_Classless_Static_Route_Option= 121 ,/**< Classless Static Route Option N Classless Static Route Option [RFC3442] */ + dhcp_code_CCC= 122 ,/**< CCC N CableLabs Client Configuration [RFC3495] */ + dhcp_code_GeoConf_Option= 123 ,/**< GeoConf Option 16 GeoConf Option [RFC3825] */ + dhcp_code_V_I_Vendor_Class= 124 ,/**< V-I Vendor Class Vendor-Identifying Vendor Class [RFC3925] */ + dhcp_code_V_I_Vendor_Specific_Information= 125 ,/**< V-I Vendor-Specific Information Vendor-Identifying Vendor-Specific Information [RFC3925] */ + //dhcp_code_= 126 ,/**< Removed/Unassigned [RFC3679] */ + //dhcp_code_= 127 ,/**< Removed/Unassigned [RFC3679] */ + //dhcp_code_PXE - undefined= 128 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_Etherboot_signature= 128 ,/**< Etherboot signature. 6 bytes: E4:45:74:68:00:00 */ + dhcp_code_DOCSIS= 128 ,/**< DOCSIS "full security" server IP address */ + dhcp_code_TFTP_Server_IP= 128 ,/**< TFTP Server IP address (for IP Phone software load) */ + //dhcp_code_= 129 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_Kernel_options= 129 ,/**< Kernel options. Variable length string */ + dhcp_code_Call_Server_IP= 129 ,/**< Call Server IP address */ + //dhcp_code_= 130 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_Ethernet_interface= 130 ,/**< Ethernet interface. Variable length string. */ + dhcp_code_Discrimination= 130 ,/**< Discrimination string (to identify vendor) */ + //dhcp_code_= 131 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_Remote_statistics_server_IP= 131 ,/**< Remote statistics server IP address */ + //dhcp_code_= 132 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_IEEE_802_1Q_VLAN_ID= 132 ,/**< IEEE 802.1Q VLAN ID */ + //dhcp_code_= 133 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_IEEE_802_1D_p= 133 ,/**< IEEE 802.1D/p Layer 2 Priority */ + //dhcp_code_= 134 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_DSCP= 134 ,/**< Diffserv Code Point (DSCP) for VoIP signalling and media streams */ + //dhcp_code_= 135 ,/**< PXE - undefined (vendor specific) [RFC4578] */ + dhcp_code_HTTP_Proxy= 135 ,/**< HTTP Proxy for phone-specific applications */ + dhcp_code_OPTION_PANA_AGENT= 136 ,/**< OPTION_PANA_AGENT [RFC5192] */ + dhcp_code_OPTION_V4_LOST= 137 ,/**< OPTION_V4_LOST [RFC5223] */ + dhcp_code_OPTION_CAPWAP_AC_V4= 138 ,/**< OPTION_CAPWAP_AC_V4 N CAPWAP Access Controller addresses [RFC5417] */ + dhcp_code_OPTION_IPv4_Address_MoS= 139 ,/**< OPTION-IPv4_Address-MoS N a series of suboptions [RFC5678] */ + dhcp_code_OPTION_IPv4_FQDN_MoS= 140 ,/**< OPTION-IPv4_FQDN-MoS N a series of suboptions [RFC5678] */ + //141-149 Unassigned [RFC3942] */ + dhcp_code_TFTP_server_address= 150 ,/**< TFTP server address (Tentatively Assigned - 2005-06-23) */ + dhcp_code_Etherboot= 150 ,/**< Etherboot */ + dhcp_code_GRUB_configuration_path_name= 150 ,/**< GRUB configuration path name */ + //151-174 Unassigned [RFC3942] + //dhcp_code_Etherboot= 175 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */ + dhcp_code_IP_Telephone= 176 ,/**< IP Telephone (Tentatively Assigned - 2005-06-23) */ + //dhcp_code_Etherboot= 177 ,/**< Etherboot (Tentatively Assigned - 2005-06-23) */ + dhcp_code_PacketCable_and_CableHome= 177 ,/**< PacketCable and CableHome (replaced by 122) */ + //178-207 Unassigned [RFC3942] + dhcp_code_PXELINUX_Magic= 208 ,/**< PXELINUX Magic 4 magic string = F1:00:74:7E [RFC5071] Deprecated */ + dhcp_code_Configuration_File= 209 ,/**< Configuration File N Configuration file [RFC5071] */ + dhcp_code_Path_Prefix= 210 ,/**< Path Prefix N Path Prefix Option [RFC5071] */ + dhcp_code_Reboot_Time = 211 ,/**< Reboot Time 4 Reboot Time [RFC5071] */ + // 212-219 Unassigned + dhcp_code_Subnet_Allocation= 220 ,/**< Subnet Allocation Option (Tentatively Assigned - 2005-06-23) */ + dhcp_code_Virtual_Subnet= 221 ,/**< Virtual Subnet Selection Option (Tentatively Assigned - 2005-06-23) */ + // 222-223 Unassigned [RFC3942] + //224-254 Reserved (Private Use) + dhcp_code_null=224 , + dhcp_code_End= 255 ,/**< End 0 None [RFC2132] */ } tnet_dhcp_option_code_t; /** DHCP/BOOTP option as per RFC 2132. * Format ==> subclause 2. */ -typedef struct tnet_dhcp_option_s -{ - TSK_DECLARE_OBJECT; - - tsk_bool_t initialized; - - tnet_dhcp_option_code_t code; /**< 1-byte option-code. */ - tsk_buffer_t *value; +typedef struct tnet_dhcp_option_s { + TSK_DECLARE_OBJECT; + + tsk_bool_t initialized; + + tnet_dhcp_option_code_t code; /**< 1-byte option-code. */ + tsk_buffer_t *value; } tnet_dhcp_option_t; @@ -243,16 +241,15 @@ int tnet_dhcp_option_serializeex(tnet_dhcp_option_code_t code, uint8_t length, c *=======================================================================================*/ /** Parameter Request List Option */ -typedef struct tnet_dhcp_option_paramslist_s -{ - TNET_DECLARE_DHCP_OPTION; +typedef struct tnet_dhcp_option_paramslist_s { + TNET_DECLARE_DHCP_OPTION; - /* RFC 2132 - 9.8. Parameter Request List - Code Len Option Codes - +-----+-----+-----+-----+--- - | 55 | n | c1 | c2 | ... - +-----+-----+-----+-----+--- - */ + /* RFC 2132 - 9.8. Parameter Request List + Code Len Option Codes + +-----+-----+-----+-----+--- + | 55 | n | c1 | c2 | ... + +-----+-----+-----+-----+--- + */ } tnet_dhcp_option_paramslist_t; int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tnet_dhcp_option_code_t code); @@ -262,17 +259,16 @@ int tnet_dhcp_option_paramslist_add_code(tnet_dhcp_option_paramslist_t* self, tn *=======================================================================================*/ /** Domain Name Server Option */ -typedef struct tnet_dhcp_option_dns_s -{ - TNET_DECLARE_DHCP_OPTION; +typedef struct tnet_dhcp_option_dns_s { + TNET_DECLARE_DHCP_OPTION; - /* RFC 2132 - 3.8. Domain Name Server Option - Code Len Address 1 Address 2 - +-----+-----+-----+-----+-----+-----+-----+-----+-- - | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... - +-----+-----+-----+-----+-----+-----+-----+-----+-- - */ - tsk_strings_L_t *servers; + /* RFC 2132 - 3.8. Domain Name Server Option + Code Len Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 6 | n | a1 | a2 | a3 | a4 | a1 | a2 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + tsk_strings_L_t *servers; } tnet_dhcp_option_dns_t; diff --git a/tinyNET/src/dhcp/tnet_dhcp_option_sip.c b/tinyNET/src/dhcp/tnet_dhcp_option_sip.c index 0c763fb..bbfd39a 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_option_sip.c +++ b/tinyNET/src/dhcp/tnet_dhcp_option_sip.c @@ -2,25 +2,25 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * */ /**@file tnet_dhcp_option_sip.c - * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for + * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for * Session Initiation Protocol (SIP) Servers as per RFC 3361. * * @author Mamadou Diop <diopmamadou(at)doubango[dot]org> @@ -39,7 +39,7 @@ tnet_dhcp_option_sip_t* tnet_dhcp_option_sip_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp_option_sip_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp_option_sip_def_t, payload, payload_size); } // @@ -47,85 +47,84 @@ tnet_dhcp_option_sip_t* tnet_dhcp_option_sip_create(const void* payload, tsk_siz // static tsk_object_t* tnet_dhcp_option_sip_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp_option_sip_t *option = self; - if(option){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - const uint8_t* payloadPtr = (const uint8_t*)payload; - const uint8_t* payloadEnd = (payloadPtr + payload_size); - - /* init base */ - tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_SIP_Servers_DHCP_Option); - - option->servers = tsk_list_create(); - - /* Set values as per RFC 3361. */ - if(*payloadPtr == 0){ /* enc=0 */ - /* - +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - |120|27 | 0 | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'c'|'o'|'m'| 0 | - +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ - +---+---+---+---+---+---+---+---+---+---+---+---+---+ | 7 - |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'n'|'e'|'t'| 0 | +---+---+--- - +---+---+---+---+---+---+---+---+---+---+ - */ - tsk_size_t offset = 1; - char* server = 0; - payloadPtr++; - while((payloadPtr < payloadEnd) && !tnet_dns_rr_qname_deserialize(payload, &server, &offset)){ - tsk_string_t* string = tsk_string_create(server); - tsk_list_push_back_data(option->servers, (void*)&string); - TSK_FREE(server); - payloadPtr += offset; - } - } - else{ - /* - Code Len enc Address 1 Address 2 - +-----+-----+-----+-----+-----+-----+-----+-----+-- - | 120 | n | 1 | a1 | a2 | a3 | a4 | a1 | ... - +-----+-----+-----+-----+-----+-----+-----+-----+-- - */ - uint32_t address; - tsk_string_t* addrstring; - char* ip4 = 0; - - while(payloadPtr < payloadEnd){ - ++payloadPtr; - address = (uint32_t)tnet_htonl_2(payloadPtr); - - tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); - - addrstring = tsk_string_create(ip4); - tsk_list_push_back_data(option->servers, (void*)&addrstring); - - TSK_FREE(ip4); - - payloadPtr+= 4; - } - } - } - return self; -} + tnet_dhcp_option_sip_t *option = self; + if(option) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + const uint8_t* payloadPtr = (const uint8_t*)payload; + const uint8_t* payloadEnd = (payloadPtr + payload_size); + + /* init base */ + tnet_dhcp_option_init(TNET_DHCP_OPTION(option), dhcp_code_SIP_Servers_DHCP_Option); + + option->servers = tsk_list_create(); -static tsk_object_t* tnet_dhcp_option_sip_dtor(tsk_object_t * self) -{ - tnet_dhcp_option_sip_t *option = self; - if(option){ - /* deinit base */ - tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); + /* Set values as per RFC 3361. */ + if(*payloadPtr == 0) { /* enc=0 */ + /* + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + |120|27 | 0 | 7 |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'c'|'o'|'m'| 0 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +---+---+---+---+---+---+---+---+---+---+---+---+---+ | 7 + |'e'|'x'|'a'|'m'|'p'|'l'|'e'| 3 |'n'|'e'|'t'| 0 | +---+---+--- + +---+---+---+---+---+---+---+---+---+---+ + */ + tsk_size_t offset = 1; + char* server = 0; + payloadPtr++; + while((payloadPtr < payloadEnd) && !tnet_dns_rr_qname_deserialize(payload, &server, &offset)) { + tsk_string_t* string = tsk_string_create(server); + tsk_list_push_back_data(option->servers, (void*)&string); + TSK_FREE(server); + payloadPtr += offset; + } + } + else { + /* + Code Len enc Address 1 Address 2 + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 120 | n | 1 | a1 | a2 | a3 | a4 | a1 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + uint32_t address; + tsk_string_t* addrstring; + char* ip4 = 0; - TSK_OBJECT_SAFE_FREE(option->servers); - } - return self; + while(payloadPtr < payloadEnd) { + ++payloadPtr; + address = (uint32_t)tnet_htonl_2(payloadPtr); + + tsk_sprintf(&ip4, "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); + + addrstring = tsk_string_create(ip4); + tsk_list_push_back_data(option->servers, (void*)&addrstring); + + TSK_FREE(ip4); + + payloadPtr+= 4; + } + } + } + return self; } -static const tsk_object_def_t tnet_dhcp_option_sip_def_s = +static tsk_object_t* tnet_dhcp_option_sip_dtor(tsk_object_t * self) { - sizeof(tnet_dhcp_option_sip_t), - tnet_dhcp_option_sip_ctor, - tnet_dhcp_option_sip_dtor, - tsk_null, + tnet_dhcp_option_sip_t *option = self; + if(option) { + /* deinit base */ + tnet_dhcp_option_deinit(TNET_DHCP_OPTION(option)); + + TSK_OBJECT_SAFE_FREE(option->servers); + } + return self; +} + +static const tsk_object_def_t tnet_dhcp_option_sip_def_s = { + sizeof(tnet_dhcp_option_sip_t), + tnet_dhcp_option_sip_ctor, + tnet_dhcp_option_sip_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp_option_sip_def_t = &tnet_dhcp_option_sip_def_s; diff --git a/tinyNET/src/dhcp/tnet_dhcp_option_sip.h b/tinyNET/src/dhcp/tnet_dhcp_option_sip.h index 2e35bf5..f08c2e6 100755 --- a/tinyNET/src/dhcp/tnet_dhcp_option_sip.h +++ b/tinyNET/src/dhcp/tnet_dhcp_option_sip.h @@ -2,25 +2,25 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * */ /**@file tnet_dhcp_option_sip.h - * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for + * @brief Dynamic Host Configuration Protocol (DHCP-for-IPv4) Option for * Session Initiation Protocol (SIP) Servers as per RFC 3361. * * @author Mamadou Diop <diopmamadou(at)doubango[dot]org> @@ -39,17 +39,16 @@ TNET_BEGIN_DECLS -typedef struct tnet_dhcp_option_sip_s -{ - TNET_DECLARE_DHCP_OPTION; - - /* RFC 3361 subclause 3.1 - Code Len enc DNS name of SIP server - +-----+-----+-----+-----+-----+-----+-----+-----+-- - | 120 | n | 0 | s1 | s2 | s3 | s4 | s5 | ... - +-----+-----+-----+-----+-----+-----+-----+-----+-- - */ - tsk_strings_L_t *servers; +typedef struct tnet_dhcp_option_sip_s { + TNET_DECLARE_DHCP_OPTION; + + /* RFC 3361 subclause 3.1 + Code Len enc DNS name of SIP server + +-----+-----+-----+-----+-----+-----+-----+-----+-- + | 120 | n | 0 | s1 | s2 | s3 | s4 | s5 | ... + +-----+-----+-----+-----+-----+-----+-----+-----+-- + */ + tsk_strings_L_t *servers; } tnet_dhcp_option_sip_t; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6.c b/tinyNET/src/dhcp6/tnet_dhcp6.c index 8e2fdb7..94bf8cc 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6.c +++ b/tinyNET/src/dhcp6/tnet_dhcp6.c @@ -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. * @@ -43,145 +43,144 @@ tnet_dhcp6_ctx_t* tnet_dhcp6_ctx_create() { - return tsk_object_new(tnet_dhcp6_ctx_def_t); + return tsk_object_new(tnet_dhcp6_ctx_def_t); } /**@ingroup tnet_dhcp6_group */ tnet_dhcp6_reply_t* tnet_dhcp6_send_request(const tnet_dhcp6_ctx_t* ctx, tnet_dhcp6_request_t* request) { - tsk_buffer_t *output; - tnet_dhcp6_reply_t* reply = 0; - int ret; - struct timeval tv; - fd_set set; - uint64_t timeout = 0; - tsk_list_item_t *item; - const tnet_interface_t *iface; - tnet_ip_t bestsource; - - tnet_socket_t *localsocket6 = 0; - struct sockaddr_storage server; - - if(!ctx || !request){ - goto bail; - } - - if((ret = tnet_getbestsource(TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port, tnet_socket_type_udp_ipv6, &bestsource))){ - TSK_DEBUG_WARN("Failed to get best source for [%s]:%u.", TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port); - //fe80::21b:63ff:fea9:c14e%4 - localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, ctx->port_client, tnet_socket_type_udp_ipv6); - } - else{ - localsocket6 = tnet_socket_create(bestsource, ctx->port_client, tnet_socket_type_udp_ipv6); - } - - /* Check local socket. */ - if(!TNET_SOCKET_IS_VALID(localsocket6)){ - TSK_DEBUG_ERROR("Failed to create/bind DHCPv6 client socket."); - goto bail; - } - - /* Always wait for 200ms before retransmission */ - tv.tv_sec = 0; - tv.tv_usec = (200 * 1000); - - if(tnet_sockaddr_init(TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port, tnet_socket_type_udp_ipv6, &server)){ - TNET_PRINT_LAST_ERROR("Failed to initialize the DHCPv6 server address."); - goto bail; - } - - /* Set timeout */ - timeout = tsk_time_epoch() + ctx->timeout; - - do - { - tsk_list_foreach(item, ctx->interfaces){ - iface = item->data; - - /* Set FD */ - FD_ZERO(&set); - FD_SET(localsocket6->fd, &set); - - ///* ciaddr */ - //if(request->type == dhcp_type_inform){ - // struct sockaddr_storage ss; - // if(!tnet_get_sockaddr(localsocket4->fd, &ss)){ - // uint32_t addr = tnet_htonl_2(&((struct sockaddr_in*)&ss)->sin_addr); - // memcpy(&request->ciaddr, &addr, 4); - // } - //} - - ///* chaddr */ - //memset(request->chaddr, 0, sizeof(request->chaddr)); - //request->hlen = iface->mac_address_length > sizeof(request->chaddr) ? sizeof(request->chaddr) : iface->mac_address_length; - //memcpy(request->chaddr, iface->mac_address, request->hlen); - - /* Serialize and send to the server. */ - if(!(output = tnet_dhcp6_message_serialize(ctx, request))){ - TSK_DEBUG_ERROR("Failed to serialize the DHCPv6 message."); - goto next_iface; - } - /* Send the request to the DHCP server */ - if((ret =tnet_sockfd_sendto(localsocket6->fd, (const struct sockaddr*)&server, output->data, output->size))<0){ - TNET_PRINT_LAST_ERROR("Failed to send DHCPv6 request."); - - tsk_thread_sleep(150); // wait 150ms before trying the next iface. - goto next_iface; - } - /* wait for response */ - if((ret = select(localsocket6->fd+1, &set, NULL, NULL, &tv))<0){ /* Error */ - TNET_PRINT_LAST_ERROR("select have failed."); - tsk_thread_sleep(150); // wait 150ms before trying the next iface. - goto next_iface; - } - else if(ret == 0){ /* timeout ==> do nothing */ - } - else{ /* there is data to read. */ - unsigned int len = 0; - void* data = 0; - - /* Check how how many bytes are pending */ - if((ret = tnet_ioctlt(localsocket6->fd, FIONREAD, &len))<0){ - goto next_iface; - } - - /* Receive pending data */ - data = tsk_calloc(len, sizeof(uint8_t)); - if((ret = tnet_sockfd_recv(localsocket6->fd, data, len, 0))<0){ - TSK_FREE(data); - - TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams."); - goto next_iface; - } - - /* Parse the incoming response. */ - reply = tnet_dhcp6_message_deserialize(ctx, data, (tsk_size_t)ret); - TSK_FREE(data); - - if(reply) - { /* response successfuly parsed */ - if(request->transaction_id != reply->transaction_id) - { /* Not same transaction id ==> continue*/ - TSK_OBJECT_SAFE_FREE(reply); - } - } - } - - next_iface: - TSK_OBJECT_SAFE_FREE(output); - if(reply){ - goto bail; - } - } - break;//FIXME - } - while(timeout > tsk_time_epoch()); + tsk_buffer_t *output; + tnet_dhcp6_reply_t* reply = 0; + int ret; + struct timeval tv; + fd_set set; + uint64_t timeout = 0; + tsk_list_item_t *item; + const tnet_interface_t *iface; + tnet_ip_t bestsource; + + tnet_socket_t *localsocket6 = 0; + struct sockaddr_storage server; + + if(!ctx || !request) { + goto bail; + } + + if((ret = tnet_getbestsource(TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port, tnet_socket_type_udp_ipv6, &bestsource))) { + TSK_DEBUG_WARN("Failed to get best source for [%s]:%u.", TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port); + //fe80::21b:63ff:fea9:c14e%4 + localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, ctx->port_client, tnet_socket_type_udp_ipv6); + } + else { + localsocket6 = tnet_socket_create(bestsource, ctx->port_client, tnet_socket_type_udp_ipv6); + } + + /* Check local socket. */ + if(!TNET_SOCKET_IS_VALID(localsocket6)) { + TSK_DEBUG_ERROR("Failed to create/bind DHCPv6 client socket."); + goto bail; + } + + /* Always wait for 200ms before retransmission */ + tv.tv_sec = 0; + tv.tv_usec = (200 * 1000); + + if(tnet_sockaddr_init(TNET_DHCP6_All_DHCP_Relay_Agents_and_Servers, ctx->server_port, tnet_socket_type_udp_ipv6, &server)) { + TNET_PRINT_LAST_ERROR("Failed to initialize the DHCPv6 server address."); + goto bail; + } + + /* Set timeout */ + timeout = tsk_time_epoch() + ctx->timeout; + + do { + tsk_list_foreach(item, ctx->interfaces) { + iface = item->data; + + /* Set FD */ + FD_ZERO(&set); + FD_SET(localsocket6->fd, &set); + + ///* ciaddr */ + //if(request->type == dhcp_type_inform){ + // struct sockaddr_storage ss; + // if(!tnet_get_sockaddr(localsocket4->fd, &ss)){ + // uint32_t addr = tnet_htonl_2(&((struct sockaddr_in*)&ss)->sin_addr); + // memcpy(&request->ciaddr, &addr, 4); + // } + //} + + ///* chaddr */ + //memset(request->chaddr, 0, sizeof(request->chaddr)); + //request->hlen = iface->mac_address_length > sizeof(request->chaddr) ? sizeof(request->chaddr) : iface->mac_address_length; + //memcpy(request->chaddr, iface->mac_address, request->hlen); + + /* Serialize and send to the server. */ + if(!(output = tnet_dhcp6_message_serialize(ctx, request))) { + TSK_DEBUG_ERROR("Failed to serialize the DHCPv6 message."); + goto next_iface; + } + /* Send the request to the DHCP server */ + if((ret =tnet_sockfd_sendto(localsocket6->fd, (const struct sockaddr*)&server, output->data, output->size))<0) { + TNET_PRINT_LAST_ERROR("Failed to send DHCPv6 request."); + + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + /* wait for response */ + if((ret = select(localsocket6->fd+1, &set, NULL, NULL, &tv))<0) { /* Error */ + TNET_PRINT_LAST_ERROR("select have failed."); + tsk_thread_sleep(150); // wait 150ms before trying the next iface. + goto next_iface; + } + else if(ret == 0) { /* timeout ==> do nothing */ + } + else { /* there is data to read. */ + unsigned int len = 0; + void* data = 0; + + /* Check how how many bytes are pending */ + if((ret = tnet_ioctlt(localsocket6->fd, FIONREAD, &len))<0) { + goto next_iface; + } + + /* Receive pending data */ + data = tsk_calloc(len, sizeof(uint8_t)); + if((ret = tnet_sockfd_recv(localsocket6->fd, data, len, 0))<0) { + TSK_FREE(data); + + TNET_PRINT_LAST_ERROR("Failed to receive DHCP dgrams."); + goto next_iface; + } + + /* Parse the incoming response. */ + reply = tnet_dhcp6_message_deserialize(ctx, data, (tsk_size_t)ret); + TSK_FREE(data); + + if(reply) { + /* response successfuly parsed */ + if(request->transaction_id != reply->transaction_id) { + /* Not same transaction id ==> continue*/ + TSK_OBJECT_SAFE_FREE(reply); + } + } + } + +next_iface: + TSK_OBJECT_SAFE_FREE(output); + if(reply) { + goto bail; + } + } + break;//FIXME + } + while(timeout > tsk_time_epoch()); bail: - TSK_OBJECT_SAFE_FREE(localsocket6); + TSK_OBJECT_SAFE_FREE(localsocket6); - return reply; + return reply; } @@ -193,28 +192,28 @@ bail: */ tnet_dhcp6_reply_t* tnet_dhcp6_requestinfo(const tnet_dhcp6_ctx_t* ctx, const tnet_dhcp6_option_orequest_t *orequest) { - tnet_dhcp6_reply_t* reply = 0; - tnet_dhcp6_request_t* request = tnet_dhcp6_request_create(dhcp6_type_information_request); - tnet_dhcp6_option_t* option = 0; + tnet_dhcp6_reply_t* reply = 0; + tnet_dhcp6_request_t* request = tnet_dhcp6_request_create(dhcp6_type_information_request); + tnet_dhcp6_option_t* option = 0; - if(!ctx || !orequest || !request){ - goto bail; - } + if(!ctx || !orequest || !request) { + goto bail; + } - if((option = tnet_dhcp6_option_create(dhcp6_code_oro, orequest, sizeof(*orequest)))){ - tsk_list_push_back_data(request->options, (void**)&option); - } + if((option = tnet_dhcp6_option_create(dhcp6_code_oro, orequest, sizeof(*orequest)))) { + tsk_list_push_back_data(request->options, (void**)&option); + } - /* Vendor class */ - { - - } + /* Vendor class */ + { - reply = tnet_dhcp6_send_request(ctx, request); + } + + reply = tnet_dhcp6_send_request(ctx, request); bail: - return reply; + return reply; } @@ -226,44 +225,43 @@ bail: // static tsk_object_t* tnet_dhcp6_ctx_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_ctx_t *ctx = self; - if(ctx){ - ctx->pen = TNET_IANA_PEN; - ctx->vendor_class_data = tsk_strdup(TNET_DHCP6_VENDOR_CLASS_DATA_DEFAULT); - - ctx->port_client = TNET_DHCP6_CLIENT_PORT; - ctx->server_port = TNET_DHCP6_SERVER_PORT; - ctx->interfaces = tnet_get_interfaces(); - - ctx->timeout = 0xffff; /* FIXME */ - - if(!ctx->interfaces || TSK_LIST_IS_EMPTY(ctx->interfaces)){ - TSK_DEBUG_ERROR("Failed to retrieve network interfaces."); - } - - tsk_safeobj_init(ctx); - } - return self; -} + tnet_dhcp6_ctx_t *ctx = self; + if(ctx) { + ctx->pen = TNET_IANA_PEN; + ctx->vendor_class_data = tsk_strdup(TNET_DHCP6_VENDOR_CLASS_DATA_DEFAULT); + + ctx->port_client = TNET_DHCP6_CLIENT_PORT; + ctx->server_port = TNET_DHCP6_SERVER_PORT; + ctx->interfaces = tnet_get_interfaces(); -static tsk_object_t* tnet_dhcp6_ctx_dtor(tsk_object_t * self) -{ - tnet_dhcp6_ctx_t *ctx = self; - if(ctx){ - tsk_safeobj_deinit(ctx); - - TSK_FREE(ctx->vendor_class_data); - - TSK_OBJECT_SAFE_FREE(ctx->interfaces); - } - return self; + ctx->timeout = 0xffff; /* FIXME */ + + if(!ctx->interfaces || TSK_LIST_IS_EMPTY(ctx->interfaces)) { + TSK_DEBUG_ERROR("Failed to retrieve network interfaces."); + } + + tsk_safeobj_init(ctx); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_ctx_def_s = +static tsk_object_t* tnet_dhcp6_ctx_dtor(tsk_object_t * self) { - sizeof(tnet_dhcp6_ctx_t), - tnet_dhcp6_ctx_ctor, - tnet_dhcp6_ctx_dtor, - tsk_null, + tnet_dhcp6_ctx_t *ctx = self; + if(ctx) { + tsk_safeobj_deinit(ctx); + + TSK_FREE(ctx->vendor_class_data); + + TSK_OBJECT_SAFE_FREE(ctx->interfaces); + } + return self; +} + +static const tsk_object_def_t tnet_dhcp6_ctx_def_s = { + sizeof(tnet_dhcp6_ctx_t), + tnet_dhcp6_ctx_ctor, + tnet_dhcp6_ctx_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_ctx_def_t = &tnet_dhcp6_ctx_def_s; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6.h b/tinyNET/src/dhcp6/tnet_dhcp6.h index 156f5a9..fa556f8 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6.h +++ b/tinyNET/src/dhcp6/tnet_dhcp6.h @@ -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. * @@ -61,7 +61,7 @@ TNET_BEGIN_DECLS #define TNET_DHCP6_All_DHCP_Servers "FF05::1:3" /*== RFC 3315 - 5.5. Transmission and Retransmission Parameters - * This section presents a table of values used to describe the message + * This section presents a table of values used to describe the message * transmission behavior of clients and servers. */ #define TNET_DHCP6_RT_SOL_MAX_DELAY 1 /**< 1 sec Max delay of first Solicit */ @@ -100,20 +100,19 @@ TNET_BEGIN_DECLS /**@ingroup tnet_dhcpv_group * DHCPv6 context. */ -typedef struct tnet_dhcp6_ctx_s -{ - TSK_DECLARE_OBJECT; - - uint16_t pen; /**< Private Enterprise Number assigned by the IANA. Default= @ref TNET_IANA_PEN.*/ - char* vendor_class_data; - - uint64_t timeout; - - tnet_port_t port_client; /**< Local port to bind to for incloming DHCPv6 messages. Default: 546 */ - tnet_port_t server_port; /**< Destination port for outgoing DHCPv6 messages. Default: 547 */ - tnet_interfaces_L_t *interfaces; - - TSK_DECLARE_SAFEOBJ; +typedef struct tnet_dhcp6_ctx_s { + TSK_DECLARE_OBJECT; + + uint16_t pen; /**< Private Enterprise Number assigned by the IANA. Default= @ref TNET_IANA_PEN.*/ + char* vendor_class_data; + + uint64_t timeout; + + tnet_port_t port_client; /**< Local port to bind to for incloming DHCPv6 messages. Default: 546 */ + tnet_port_t server_port; /**< Destination port for outgoing DHCPv6 messages. Default: 547 */ + tnet_interfaces_L_t *interfaces; + + TSK_DECLARE_SAFEOBJ; } tnet_dhcp6_ctx_t; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_duid.c b/tinyNET/src/dhcp6/tnet_dhcp6_duid.c index 38f2a52..3bec2f4 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_duid.c +++ b/tinyNET/src/dhcp6/tnet_dhcp6_duid.c @@ -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. * @@ -38,101 +38,97 @@ int tnet_dhcp6_duid_ll_serialize(const tnet_dhcp6_duid_ll_t* self, tsk_buffer_t tnet_dhcp6_duid_llt_t* tnet_dhcp6_duid_llt_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_duid_llt_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp6_duid_llt_def_t, payload, payload_size); } tnet_dhcp6_duid_en_t* tnet_dhcp6_duid_en_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_duid_en_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp6_duid_en_def_t, payload, payload_size); } tnet_dhcp6_duid_ll_t* tnet_dhcp6_duid_ll_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_duid_ll_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp6_duid_ll_def_t, payload, payload_size); } int tnet_dhcp6_duid_init(tnet_dhcp6_duid_t *self, tnet_dhcp6_duid_type_t type) { - if(self){ - if(!self->initialized){ - self->type = type; - self->initialized = tsk_true; - return 0; - } - return -2; - } - return -1; + if(self) { + if(!self->initialized) { + self->type = type; + self->initialized = tsk_true; + return 0; + } + return -2; + } + return -1; } int tnet_dhcp6_duid_deinit(tnet_dhcp6_duid_t *self) { - if(self){ - if(self->initialized){ - self->initialized = tsk_true; - return 0; - } - return -2; - } - return -1; + if(self) { + if(self->initialized) { + self->initialized = tsk_true; + return 0; + } + return -2; + } + return -1; } tnet_dhcp6_duid_t* tnet_dhcp6_duid_deserialize(const void* data, tsk_size_t size) { - tnet_dhcp6_duid_t *duid = 0; - uint8_t* dataPtr = ((uint8_t*)data); - //uint8_t* dataEnd = (dataPtr+size); + tnet_dhcp6_duid_t *duid = 0; + uint8_t* dataPtr = ((uint8_t*)data); + //uint8_t* dataEnd = (dataPtr+size); - tnet_dhcp6_duid_type_t type; - //uint8_t len = 0; + tnet_dhcp6_duid_type_t type; + //uint8_t len = 0; - /* Check validity */ - if(!dataPtr || size<2/*Type*/){ - goto bail; - } + /* Check validity */ + if(!dataPtr || size<2/*Type*/) { + goto bail; + } - type = (tnet_dhcp6_duid_type_t) tnet_ntohs_2(dataPtr); - dataPtr += 2; + type = (tnet_dhcp6_duid_type_t) tnet_ntohs_2(dataPtr); + dataPtr += 2; bail: - return duid; + return duid; } int tnet_dhcp6_duid_serialize(const tnet_dhcp6_duid_t* self, tsk_buffer_t *output) { - int ret = -1; - - if(!self || !output){ - return ret; - } - - switch(self->type){ - case dhcp6_duid_linklayer_plus_time: - { - ret = tnet_dhcp6_duid_llt_serialize(TNET_DHCP6_DUID_LLT(self), output); - break; - } - - case dhcp6_duid_Vendor_assigned_id: - { - ret = tnet_dhcp6_duid_en_serialize(TNET_DHCP6_DUID_EN(self), output); - break; - } - - case dhcp6_duid_linklayer: - { - ret = tnet_dhcp6_duid_ll_serialize(TNET_DHCP6_DUID_LL(self), output); - break; - } - - default: - { - ret = -2; - goto bail; - } - } + int ret = -1; + + if(!self || !output) { + return ret; + } + + switch(self->type) { + case dhcp6_duid_linklayer_plus_time: { + ret = tnet_dhcp6_duid_llt_serialize(TNET_DHCP6_DUID_LLT(self), output); + break; + } + + case dhcp6_duid_Vendor_assigned_id: { + ret = tnet_dhcp6_duid_en_serialize(TNET_DHCP6_DUID_EN(self), output); + break; + } + + case dhcp6_duid_linklayer: { + ret = tnet_dhcp6_duid_ll_serialize(TNET_DHCP6_DUID_LL(self), output); + break; + } + + default: { + ret = -2; + goto bail; + } + } bail: - return ret; + return ret; } /*======================================================================================= @@ -141,7 +137,7 @@ bail: int tnet_dhcp6_duid_llt_serialize(const tnet_dhcp6_duid_llt_t* self, tsk_buffer_t *output) { - return -1; + return -1; } // @@ -149,39 +145,38 @@ int tnet_dhcp6_duid_llt_serialize(const tnet_dhcp6_duid_llt_t* self, tsk_buffer_ // static tsk_object_t* tnet_dhcp6_duid_llt_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_duid_llt_t *duid = self; - if(duid){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - /* init base */ - tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_linklayer_plus_time); - - if(payload && payload_size){ - /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_duid_llt_t *duid = self; + if(duid) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + /* init base */ + tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_linklayer_plus_time); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_duid_llt_dtor(tsk_object_t * self) -{ - tnet_dhcp6_duid_llt_t *duid = self; - if(duid){ - /* deinit base */ - tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); - - TSK_OBJECT_SAFE_FREE(duid->address); - } - return self; +static tsk_object_t* tnet_dhcp6_duid_llt_dtor(tsk_object_t * self) +{ + tnet_dhcp6_duid_llt_t *duid = self; + if(duid) { + /* deinit base */ + tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); + + TSK_OBJECT_SAFE_FREE(duid->address); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_duid_llt_def_s = -{ - sizeof(tnet_dhcp6_duid_llt_t), - tnet_dhcp6_duid_llt_ctor, - tnet_dhcp6_duid_llt_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_duid_llt_def_s = { + sizeof(tnet_dhcp6_duid_llt_t), + tnet_dhcp6_duid_llt_ctor, + tnet_dhcp6_duid_llt_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_duid_llt_def_t = &tnet_dhcp6_duid_llt_def_s; @@ -192,7 +187,7 @@ const tsk_object_def_t *tnet_dhcp6_duid_llt_def_t = &tnet_dhcp6_duid_llt_def_s; int tnet_dhcp6_duid_en_serialize(const tnet_dhcp6_duid_en_t* self, tsk_buffer_t *output) { - return -1; + return -1; } // @@ -200,39 +195,38 @@ int tnet_dhcp6_duid_en_serialize(const tnet_dhcp6_duid_en_t* self, tsk_buffer_t // static tsk_object_t* tnet_dhcp6_duid_en_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_duid_en_t *duid = self; - if(duid){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - /* init base */ - tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_Vendor_assigned_id); - - if(payload && payload_size){ - /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_duid_en_t *duid = self; + if(duid) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + /* init base */ + tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_Vendor_assigned_id); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_duid_en_dtor(tsk_object_t * self) -{ - tnet_dhcp6_duid_en_t *duid = self; - if(duid){ - /* deinit base */ - tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); - - TSK_OBJECT_SAFE_FREE(duid->indentifier); - } - return self; +static tsk_object_t* tnet_dhcp6_duid_en_dtor(tsk_object_t * self) +{ + tnet_dhcp6_duid_en_t *duid = self; + if(duid) { + /* deinit base */ + tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); + + TSK_OBJECT_SAFE_FREE(duid->indentifier); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_duid_en_def_s = -{ - sizeof(tnet_dhcp6_duid_en_t), - tnet_dhcp6_duid_en_ctor, - tnet_dhcp6_duid_en_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_duid_en_def_s = { + sizeof(tnet_dhcp6_duid_en_t), + tnet_dhcp6_duid_en_ctor, + tnet_dhcp6_duid_en_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_duid_en_def_t = &tnet_dhcp6_duid_en_def_s; @@ -243,7 +237,7 @@ const tsk_object_def_t *tnet_dhcp6_duid_en_def_t = &tnet_dhcp6_duid_en_def_s; int tnet_dhcp6_duid_ll_serialize(const tnet_dhcp6_duid_ll_t* self, tsk_buffer_t *output) { - return -1; + return -1; } // @@ -251,38 +245,37 @@ int tnet_dhcp6_duid_ll_serialize(const tnet_dhcp6_duid_ll_t* self, tsk_buffer_t // static tsk_object_t* tnet_dhcp6_duid_ll_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_duid_ll_t *duid = self; - if(duid){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - /* init base */ - tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_linklayer); - - if(payload && payload_size){ - /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_duid_ll_t *duid = self; + if(duid) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + /* init base */ + tnet_dhcp6_duid_init(TNET_DHCP6_DUID(duid), dhcp6_duid_linklayer); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_duid_ll_dtor(tsk_object_t * self) -{ - tnet_dhcp6_duid_ll_t *duid = self; - if(duid){ - /* deinit base */ - tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); - - TSK_OBJECT_SAFE_FREE(duid->address); - } - return self; +static tsk_object_t* tnet_dhcp6_duid_ll_dtor(tsk_object_t * self) +{ + tnet_dhcp6_duid_ll_t *duid = self; + if(duid) { + /* deinit base */ + tnet_dhcp6_duid_deinit(TNET_DHCP6_DUID(duid)); + + TSK_OBJECT_SAFE_FREE(duid->address); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_duid_ll_def_s = -{ - sizeof(tnet_dhcp6_duid_ll_t), - tnet_dhcp6_duid_ll_ctor, - tnet_dhcp6_duid_ll_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_duid_ll_def_s = { + sizeof(tnet_dhcp6_duid_ll_t), + tnet_dhcp6_duid_ll_ctor, + tnet_dhcp6_duid_ll_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_duid_ll_def_t = &tnet_dhcp6_duid_ll_def_s; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_duid.h b/tinyNET/src/dhcp6/tnet_dhcp6_duid.h index 34383fa..94c2b32 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_duid.h +++ b/tinyNET/src/dhcp6/tnet_dhcp6_duid.h @@ -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,23 +44,21 @@ TNET_BEGIN_DECLS /** List of DHCPv6 DUIDs types as per RFC 3315 subclause 9.1. */ -typedef enum tnet_dhcp6_duid_type_e -{ - dhcp6_duid_linklayer_plus_time = 1, /**< Link-layer address plus time. */ - dhcp6_duid_Vendor_assigned_id = 2, /**< Vendor-assigned unique ID based on Enterprise Number. */ - dhcp6_duid_linklayer = 3, /**< Link-layer address. */ +typedef enum tnet_dhcp6_duid_type_e { + dhcp6_duid_linklayer_plus_time = 1, /**< Link-layer address plus time. */ + dhcp6_duid_Vendor_assigned_id = 2, /**< Vendor-assigned unique ID based on Enterprise Number. */ + dhcp6_duid_linklayer = 3, /**< Link-layer address. */ } tnet_dhcp6_duid_type_t; /** DHCP Unique Identifier (DUID) base class (subclause 9). */ -typedef struct tnet_dhcp6_duid_s -{ - TSK_DECLARE_OBJECT; - - tsk_bool_t initialized; +typedef struct tnet_dhcp6_duid_s { + TSK_DECLARE_OBJECT; + + tsk_bool_t initialized; - tnet_dhcp6_duid_type_t type; /* DUID type. 2-bytes value. */ + tnet_dhcp6_duid_type_t type; /* DUID type. 2-bytes value. */ } tnet_dhcp6_duid_t; @@ -80,29 +78,28 @@ int tnet_dhcp6_duid_serialize(const tnet_dhcp6_duid_t* self, tsk_buffer_t *outpu /** DUID Based on Link-layer Address Plus Time [DUID-LLT] */ -typedef struct tnet_dhcp6_duid_llt_s -{ - TNET_DECLARE_DHCP6_DUID; - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 1 | hardware type (16 bits) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | time (32 bits) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - . . - . link-layer address (variable length) . - . . - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - /* The hardware type code as maintained by IANA. */ - tnet_hardware_type_t htype; - /* The time value is the time that the DUID is generated represented in seconds - since midnight (UTC), January 1, 2000, modulo 2^32. */ - uint32_t time; - /* The link-layer address. */ - tsk_buffer_t *address; +typedef struct tnet_dhcp6_duid_llt_s { + TNET_DECLARE_DHCP6_DUID; + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 1 | hardware type (16 bits) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time (32 bits) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . link-layer address (variable length) . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + /* The hardware type code as maintained by IANA. */ + tnet_hardware_type_t htype; + /* The time value is the time that the DUID is generated represented in seconds + since midnight (UTC), January 1, 2000, modulo 2^32. */ + uint32_t time; + /* The link-layer address. */ + tsk_buffer_t *address; } tnet_dhcp6_duid_llt_t; @@ -113,27 +110,26 @@ tnet_dhcp6_duid_llt_t; /** DUID Assigned by Vendor Based on Enterprise Number [DUID-EN] */ -typedef struct tnet_dhcp6_duid_en_s -{ - TNET_DECLARE_DHCP6_DUID; - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | 2 | enterprise-number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | enterprise-number (contd) | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | - . identifier . - . (variable length) . - . . - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - /* Tthe vendor's registered Private Enterprise Number as maintained by IANA. - For more information: http://www.iana.org/assignments/enterprise-numbers. */ - uint32_t en; - /* The link-layer address. */ - tsk_buffer_t *indentifier; +typedef struct tnet_dhcp6_duid_en_s { + TNET_DECLARE_DHCP6_DUID; + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | 2 | enterprise-number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | enterprise-number (contd) | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | + . identifier . + . (variable length) . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + /* Tthe vendor's registered Private Enterprise Number as maintained by IANA. + For more information: http://www.iana.org/assignments/enterprise-numbers. */ + uint32_t en; + /* The link-layer address. */ + tsk_buffer_t *indentifier; } tnet_dhcp6_duid_en_t; @@ -143,11 +139,10 @@ tnet_dhcp6_duid_en_t; /** DUID Based on Link-layer Address [DUID-LL] */ -typedef struct tnet_dhcp6_duid_ll_s -{ - TNET_DECLARE_DHCP6_DUID; - /* - 0 1 2 3 +typedef struct tnet_dhcp6_duid_ll_s { + TNET_DECLARE_DHCP6_DUID; + /* + 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 3 | hardware type (16 bits) | @@ -156,11 +151,11 @@ typedef struct tnet_dhcp6_duid_ll_s . link-layer address (variable length) . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - /* The hardware type code as maintained by IANA. */ - tnet_hardware_type_t htype; - /* The link-layer address. */ - tsk_buffer_t *address; + */ + /* The hardware type code as maintained by IANA. */ + tnet_hardware_type_t htype; + /* The link-layer address. */ + tsk_buffer_t *address; } tnet_dhcp6_duid_ll_t; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_message.c b/tinyNET/src/dhcp6/tnet_dhcp6_message.c index 4691714..9979335 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_message.c +++ b/tinyNET/src/dhcp6/tnet_dhcp6_message.c @@ -32,65 +32,64 @@ tnet_dhcp6_message_t* tnet_dhcp6_message_create(tnet_dhcp6_message_type_t type) { - return tsk_object_new(tnet_dhcp6_message_def_t, type); + return tsk_object_new(tnet_dhcp6_message_def_t, type); } tnet_dhcp6_request_t* tnet_dhcp6_request_create(tnet_dhcp6_message_type_t type) { - return tnet_dhcp6_message_create(type); + return tnet_dhcp6_message_create(type); } tsk_buffer_t* tnet_dhcp6_message_serialize(const tnet_dhcp6_ctx_t *ctx, const tnet_dhcp6_message_t *self) { - tsk_buffer_t* output = 0; - //uint8_t _1byte; - uint16_t _2bytes; - uint32_t _4bytes; - - /* Check message validity */ - if (!self){ - goto bail; - } - - output = tsk_buffer_create_null(); - - /*== msg-type + transaction-id */ - _4bytes = (((uint32_t)(self->type)) << 24) | (self->transaction_id & 0xFFFFFF); - _4bytes = tnet_ntohl(_4bytes); - tsk_buffer_append(output, &(_4bytes), 4); - - /*== Vendor class - */ - { - _2bytes = tnet_htons(dhcp6_code_vendor_class); - tsk_buffer_append(output, &(_2bytes), 2); - _2bytes = tnet_htons((unsigned short)(4 + tsk_strlen(ctx->vendor_class_data))); - tsk_buffer_append(output, &(_2bytes), 2); - _4bytes = tnet_ntohl(ctx->pen); - tsk_buffer_append(output, &(_4bytes), 4); - tsk_buffer_append(output, ctx->vendor_class_data, tsk_strlen(ctx->vendor_class_data)); - } - - /*== DHCP Options - */ - { - tsk_list_item_t *item; - tnet_dhcp6_option_t* option; - tsk_list_foreach(item, self->options) - { - option = (tnet_dhcp6_option_t*)item->data; - if (tnet_dhcp6_option_serialize(option, output)){ - TSK_DEBUG_WARN("Failed to serialize DHCPv6 OPTION (%u)", option->code); - } - } - } + tsk_buffer_t* output = 0; + //uint8_t _1byte; + uint16_t _2bytes; + uint32_t _4bytes; + + /* Check message validity */ + if (!self) { + goto bail; + } + + output = tsk_buffer_create_null(); + + /*== msg-type + transaction-id */ + _4bytes = (((uint32_t)(self->type)) << 24) | (self->transaction_id & 0xFFFFFF); + _4bytes = tnet_ntohl(_4bytes); + tsk_buffer_append(output, &(_4bytes), 4); + + /*== Vendor class + */ + { + _2bytes = tnet_htons(dhcp6_code_vendor_class); + tsk_buffer_append(output, &(_2bytes), 2); + _2bytes = tnet_htons((unsigned short)(4 + tsk_strlen(ctx->vendor_class_data))); + tsk_buffer_append(output, &(_2bytes), 2); + _4bytes = tnet_ntohl(ctx->pen); + tsk_buffer_append(output, &(_4bytes), 4); + tsk_buffer_append(output, ctx->vendor_class_data, tsk_strlen(ctx->vendor_class_data)); + } + + /*== DHCP Options + */ + { + tsk_list_item_t *item; + tnet_dhcp6_option_t* option; + tsk_list_foreach(item, self->options) { + option = (tnet_dhcp6_option_t*)item->data; + if (tnet_dhcp6_option_serialize(option, output)) { + TSK_DEBUG_WARN("Failed to serialize DHCPv6 OPTION (%u)", option->code); + } + } + } bail: - return output; + return output; } tnet_dhcp6_message_t* tnet_dhcp6_message_deserialize(const tnet_dhcp6_ctx_t *ctx, const uint8_t *data, tsk_size_t size) { - return 0; + return 0; } @@ -100,32 +99,31 @@ tnet_dhcp6_message_t* tnet_dhcp6_message_deserialize(const tnet_dhcp6_ctx_t *ctx // static tsk_object_t* tnet_dhcp6_message_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_message_t *message = self; - if (message){ - static uint16_t __dhcp6message_unique_tid = 0;//(uint32_t)tsk_time_epoch(); - - message->type = va_arg(*app, tnet_dhcp6_message_type_t); - message->transaction_id = ++__dhcp6message_unique_tid; - message->options = tsk_list_create(); - } - return self; + tnet_dhcp6_message_t *message = self; + if (message) { + static uint16_t __dhcp6message_unique_tid = 0;//(uint32_t)tsk_time_epoch(); + + message->type = va_arg(*app, tnet_dhcp6_message_type_t); + message->transaction_id = ++__dhcp6message_unique_tid; + message->options = tsk_list_create(); + } + return self; } static tsk_object_t* tnet_dhcp6_message_dtor(tsk_object_t * self) { - tnet_dhcp6_message_t *message = self; - if (message){ - TSK_OBJECT_SAFE_FREE(message->options); - } - return self; + tnet_dhcp6_message_t *message = self; + if (message) { + TSK_OBJECT_SAFE_FREE(message->options); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_message_def_s = -{ - sizeof(tnet_dhcp6_message_t), - tnet_dhcp6_message_ctor, - tnet_dhcp6_message_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_message_def_s = { + sizeof(tnet_dhcp6_message_t), + tnet_dhcp6_message_ctor, + tnet_dhcp6_message_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_message_def_t = &tnet_dhcp6_message_def_s; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_message.h b/tinyNET/src/dhcp6/tnet_dhcp6_message.h index dc5d9d2..3dfd6c6 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_message.h +++ b/tinyNET/src/dhcp6/tnet_dhcp6_message.h @@ -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. * @@ -42,86 +42,84 @@ struct tnet_dhcp6_ctx_s; /** List of all supported DHCPv6 messages. * For more info: RFC 3315 - 5.3. DHCP Message Types */ -typedef enum tnet_dhcp6_message_type_e -{ - /* A client sends a Solicit message to locate servers. */ - dhcp6_type_solicit = 1, - /* A server sends an Advertise message to indicate that it is available for DHCP service, in - response to a Solicit message received from a client. */ - dhcp6_type_advertise = 2, - /* A client sends a Request message to request configuration parameters, including IP - addresses, from a specific server. */ - dhcp6_type_request = 3, - /* A client sends a Confirm message to any available server to determine whether the - addresses it was assigned are still appropriate to the link to which the client is connected. */ - dhcp6_type_confirm = 4, - /* A client sends a Renew message to the server that originally provided the client's addresses - and configuration parameters to extend the lifetimes on the addresses assigned to the - client and to update other configurationparameters. */ - dhcp6_type_renew = 5, - /* A client sends a Rebind message to any available server to extend the lifetimes on the - addresses assigned to the client and to update other configuration parameters; this message is - sent after a client receives no response to a Renew message.*/ - dhcp6_type_rebind = 6, - /* A server sends a Reply message containing assigned addresses and configuration parameters - in response to a Solicit, Request, Renew, Rebind message received from a client. A - server sends a Reply message containing configuration parameters in response to an - Information-request message. A server sends a Reply message in response to a Confirm message - confirming or denying that the addresses assigned to the client are appropriate to the - link to which the client is connected. A server sends a Reply message to acknowledge - receipt of a Release or Decline message.*/ - dhcp6_type_reply = 7, - /* A client sends a Release message to the server that assigned addresses to the client to - indicate that the client will no longer use one or more of the assigned addresses.*/ - dhcp6_type_release = 8, - /* A client sends a Decline message to a server to indicate that the client has determined that - one or more addresses assigned by the server are already in use on the link to which the - client is connected.*/ - dhcp6_type_decline = 9, - /*A server sends a Reconfigure message to a client to inform the client that the server has - new or updated configuration parameters, and that the client is to initiate a Renew/Reply - or Information-request/Reply transaction with the server in order to receive the updatedinformation. */ - dhcp6_type_reconfigure = 10, - /* A client sends an Information-request message to a server to request configuration - parameters without the assignment of any IP addresses to the client.*/ - dhcp6_type_information_request = 11, - /* A relay agent sends a Relay-forward message to relay messages to servers, either directly - or through another relay agent. The received message, either a client message or a - Relay-forward message from another relay agent, is encapsulated in an option in the Relay-forward message.*/ - dhcp6_type_relay_forw = 12, - /* A server sends a Relay-reply message to a relay agent containing a message that the relay - agent delivers to a client. The Relay-reply message may be relayed by other relay agents - for delivery to the destination relay agent. - The server encapsulates the client message as an option in the Relay-reply message, which the - relay agent extracts and relays to the client.*/ - dhcp6_type_relay_repl = 13, +typedef enum tnet_dhcp6_message_type_e { + /* A client sends a Solicit message to locate servers. */ + dhcp6_type_solicit = 1, + /* A server sends an Advertise message to indicate that it is available for DHCP service, in + response to a Solicit message received from a client. */ + dhcp6_type_advertise = 2, + /* A client sends a Request message to request configuration parameters, including IP + addresses, from a specific server. */ + dhcp6_type_request = 3, + /* A client sends a Confirm message to any available server to determine whether the + addresses it was assigned are still appropriate to the link to which the client is connected. */ + dhcp6_type_confirm = 4, + /* A client sends a Renew message to the server that originally provided the client's addresses + and configuration parameters to extend the lifetimes on the addresses assigned to the + client and to update other configurationparameters. */ + dhcp6_type_renew = 5, + /* A client sends a Rebind message to any available server to extend the lifetimes on the + addresses assigned to the client and to update other configuration parameters; this message is + sent after a client receives no response to a Renew message.*/ + dhcp6_type_rebind = 6, + /* A server sends a Reply message containing assigned addresses and configuration parameters + in response to a Solicit, Request, Renew, Rebind message received from a client. A + server sends a Reply message containing configuration parameters in response to an + Information-request message. A server sends a Reply message in response to a Confirm message + confirming or denying that the addresses assigned to the client are appropriate to the + link to which the client is connected. A server sends a Reply message to acknowledge + receipt of a Release or Decline message.*/ + dhcp6_type_reply = 7, + /* A client sends a Release message to the server that assigned addresses to the client to + indicate that the client will no longer use one or more of the assigned addresses.*/ + dhcp6_type_release = 8, + /* A client sends a Decline message to a server to indicate that the client has determined that + one or more addresses assigned by the server are already in use on the link to which the + client is connected.*/ + dhcp6_type_decline = 9, + /*A server sends a Reconfigure message to a client to inform the client that the server has + new or updated configuration parameters, and that the client is to initiate a Renew/Reply + or Information-request/Reply transaction with the server in order to receive the updatedinformation. */ + dhcp6_type_reconfigure = 10, + /* A client sends an Information-request message to a server to request configuration + parameters without the assignment of any IP addresses to the client.*/ + dhcp6_type_information_request = 11, + /* A relay agent sends a Relay-forward message to relay messages to servers, either directly + or through another relay agent. The received message, either a client message or a + Relay-forward message from another relay agent, is encapsulated in an option in the Relay-forward message.*/ + dhcp6_type_relay_forw = 12, + /* A server sends a Relay-reply message to a relay agent containing a message that the relay + agent delivers to a client. The Relay-reply message may be relayed by other relay agents + for delivery to the destination relay agent. + The server encapsulates the client message as an option in the Relay-reply message, which the + relay agent extracts and relays to the client.*/ + dhcp6_type_relay_repl = 13, } tnet_dhcp6_message_type_t; /** DHCPv6 message (common fields) as per RFC 3315 subclause 6. */ -typedef struct tnet_dhcp6_message_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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | msg-type | transaction-id | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . options . - . (variable) . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - /* Identifies the DHCP message type. 1-byte value. */ - tnet_dhcp6_message_type_t type; - /* The transaction ID for this message exchange. 3-bytes value. */ - uint32_t transaction_id; - /* Options carried in this message. */ - tnet_dhcp6_options_L_t *options; +typedef struct tnet_dhcp6_message_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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | msg-type | transaction-id | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . options . + . (variable) . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + /* Identifies the DHCP message type. 1-byte value. */ + tnet_dhcp6_message_type_t type; + /* The transaction ID for this message exchange. 3-bytes value. */ + uint32_t transaction_id; + /* Options carried in this message. */ + tnet_dhcp6_options_L_t *options; } tnet_dhcp6_message_t; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_option.c b/tinyNET/src/dhcp6/tnet_dhcp6_option.c index 91ec16a..58107c6 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_option.c +++ b/tinyNET/src/dhcp6/tnet_dhcp6_option.c @@ -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. * @@ -37,125 +37,120 @@ tnet_dhcp6_option_t* tnet_dhcp6_option_create(tnet_dhcp6_option_code_t code, const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_option_def_t, code, payload, payload_size); + return tsk_object_new(tnet_dhcp6_option_def_t, code, payload, payload_size); } tnet_dhcp6_option_identifier_t* tnet_dhcp6_option_indentifer_create(tnet_dhcp6_option_code_t code, const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_option_identifier_def_t, code, payload, payload_size); + return tsk_object_new(tnet_dhcp6_option_identifier_def_t, code, payload, payload_size); } tnet_dhcp6_option_identifier_t* tnet_dhcp6_option_clientid_create(const void* payload, tsk_size_t payload_size) { - return tnet_dhcp6_option_indentifer_create(dhcp6_code_clientid, payload, payload_size); + return tnet_dhcp6_option_indentifer_create(dhcp6_code_clientid, payload, payload_size); } tnet_dhcp6_option_identifier_t* tnet_dhcp6_option_serverid_create(const void* payload, tsk_size_t payload_size) { - return tnet_dhcp6_option_indentifer_create(dhcp6_code_serverid, payload, payload_size); + return tnet_dhcp6_option_indentifer_create(dhcp6_code_serverid, payload, payload_size); } tnet_dhcp6_option_orequest_t* tnet_dhcp6_option_orequest_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_option_orequest_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp6_option_orequest_def_t, payload, payload_size); } tnet_dhcp6_option_orequest_t* tnet_dhcp6_option_orequest_create_null() { - return tnet_dhcp6_option_orequest_create(tsk_null, 0); + return tnet_dhcp6_option_orequest_create(tsk_null, 0); } tnet_dhcp6_option_vendorclass_t* tnet_dhcp6_option_vendorclass_create(const void* payload, tsk_size_t payload_size) { - return tsk_object_new(tnet_dhcp6_option_vendorclass_def_t, payload, payload_size); + return tsk_object_new(tnet_dhcp6_option_vendorclass_def_t, payload, payload_size); } tnet_dhcp6_option_vendorclass_t* tnet_dhcp6_option_vendorclass_create_null() { - return tnet_dhcp6_option_vendorclass_create(tsk_null, 0); + return tnet_dhcp6_option_vendorclass_create(tsk_null, 0); } tnet_dhcp6_option_t* tnet_dhcp6_option_deserialize(const void* data, tsk_size_t size) { - tnet_dhcp6_option_t *option = 0; - uint8_t* dataPtr = ((uint8_t*)data); - //uint8_t* dataEnd = (dataPtr+size); - - tnet_dhcp6_option_code_t code; - uint16_t len; - - /* Check validity */ - if(!dataPtr || size<4/*Code Len*/){ - goto bail; - } - - code = (tnet_dhcp6_option_code_t) tnet_ntohs_2(dataPtr); - dataPtr += 2; - - len = tnet_ntohs_2(dataPtr); - dataPtr += 2; - - switch(code){ - case dhcp6_code_clientid: - case dhcp6_code_serverid: - { - break; - } - - default: - { - break; - } - } + tnet_dhcp6_option_t *option = 0; + uint8_t* dataPtr = ((uint8_t*)data); + //uint8_t* dataEnd = (dataPtr+size); + + tnet_dhcp6_option_code_t code; + uint16_t len; + + /* Check validity */ + if(!dataPtr || size<4/*Code Len*/) { + goto bail; + } + + code = (tnet_dhcp6_option_code_t) tnet_ntohs_2(dataPtr); + dataPtr += 2; + + len = tnet_ntohs_2(dataPtr); + dataPtr += 2; + + switch(code) { + case dhcp6_code_clientid: + case dhcp6_code_serverid: { + break; + } + + default: { + break; + } + } bail: - return option; + return option; } int tnet_dhcp6_option_serialize(const tnet_dhcp6_option_t* self, tsk_buffer_t *output) { - uint16_t _2bytes; - int ret = -1; - - if(!self || !output){ - goto bail; - } - - /*== Code */ - _2bytes = tnet_htons(self->code); - tsk_buffer_append(output, &(_2bytes), 2); - - switch(self->code){ - case dhcp6_code_clientid: - case dhcp6_code_serverid: - { - break; - } - - case dhcp6_code_oro: - default: - { - if(self->data) - { - const tnet_dhcp6_option_orequest_t* opt = (const tnet_dhcp6_option_orequest_t*)self->data; - if(opt->codes){ - /* option-len */ - _2bytes = tnet_htons((unsigned short)opt->codes->size); - tsk_buffer_append(output, &(_2bytes), 2); - /* option-data */ - ret = tsk_buffer_append(output, opt->codes->data, opt->codes->size); - } - - } - break; - } - } + uint16_t _2bytes; + int ret = -1; + + if(!self || !output) { + goto bail; + } + + /*== Code */ + _2bytes = tnet_htons(self->code); + tsk_buffer_append(output, &(_2bytes), 2); + + switch(self->code) { + case dhcp6_code_clientid: + case dhcp6_code_serverid: { + break; + } + + case dhcp6_code_oro: + default: { + if(self->data) { + const tnet_dhcp6_option_orequest_t* opt = (const tnet_dhcp6_option_orequest_t*)self->data; + if(opt->codes) { + /* option-len */ + _2bytes = tnet_htons((unsigned short)opt->codes->size); + tsk_buffer_append(output, &(_2bytes), 2); + /* option-data */ + ret = tsk_buffer_append(output, opt->codes->data, opt->codes->size); + } + + } + break; + } + } bail: - return ret; + return ret; } int tnet_dhcp6_option_serializeex(tnet_dhcp6_option_code_t code, uint8_t length, const void* value, tsk_buffer_t *output) { - return -1; + return -1; } // @@ -163,43 +158,42 @@ int tnet_dhcp6_option_serializeex(tnet_dhcp6_option_code_t code, uint8_t length, // static tsk_object_t* tnet_dhcp6_option_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_option_t *option = self; - if(option){ - tnet_dhcp6_option_code_t code = va_arg(*app, tnet_dhcp6_option_code_t); - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - option->code = code; - if(payload && payload_size){ - if((option->data = (tnet_dhcp6_option_data_t*)tsk_calloc(payload_size, sizeof(uint8_t)))){ - memcpy(option->data, payload, payload_size); - option->len = (uint16_t)payload_size; - } - } - } - return self; + tnet_dhcp6_option_t *option = self; + if(option) { + tnet_dhcp6_option_code_t code = va_arg(*app, tnet_dhcp6_option_code_t); + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + option->code = code; + if(payload && payload_size) { + if((option->data = (tnet_dhcp6_option_data_t*)tsk_calloc(payload_size, sizeof(uint8_t)))) { + memcpy(option->data, payload, payload_size); + option->len = (uint16_t)payload_size; + } + } + } + return self; } -static tsk_object_t* tnet_dhcp6_option_dtor(tsk_object_t * self) -{ - tnet_dhcp6_option_t *option = self; - if(option){ - TSK_OBJECT_SAFE_FREE(option->data); - } - return self; +static tsk_object_t* tnet_dhcp6_option_dtor(tsk_object_t * self) +{ + tnet_dhcp6_option_t *option = self; + if(option) { + TSK_OBJECT_SAFE_FREE(option->data); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_option_def_s = -{ - sizeof(tnet_dhcp6_option_t), - tnet_dhcp6_option_ctor, - tnet_dhcp6_option_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_option_def_s = { + sizeof(tnet_dhcp6_option_t), + tnet_dhcp6_option_ctor, + tnet_dhcp6_option_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_option_def_t = &tnet_dhcp6_option_def_s; /*====================================================================================== -* RFC 3315 - +* RFC 3315 - 22.2. Client Identifier Option 22.3. Server Identifier Option *=======================================================================================*/ @@ -208,34 +202,33 @@ const tsk_object_def_t *tnet_dhcp6_option_def_t = &tnet_dhcp6_option_def_s; // static tsk_object_t* tnet_dhcp6_option_identifier_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_option_identifier_t *option = self; - if(option){ - //tnet_dhcp6_option_code_t code = va_arg(*app, tnet_dhcp6_option_code_t); - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - if(payload && payload_size){ - /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_option_identifier_t *option = self; + if(option) { + //tnet_dhcp6_option_code_t code = va_arg(*app, tnet_dhcp6_option_code_t); + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_option_identifier_dtor(tsk_object_t * self) -{ - tnet_dhcp6_option_identifier_t *option = self; - if(option){ - TSK_OBJECT_SAFE_FREE(option->duid); - } - return self; +static tsk_object_t* tnet_dhcp6_option_identifier_dtor(tsk_object_t * self) +{ + tnet_dhcp6_option_identifier_t *option = self; + if(option) { + TSK_OBJECT_SAFE_FREE(option->duid); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_option_identifier_def_s = -{ - sizeof(tnet_dhcp6_option_identifier_t), - tnet_dhcp6_option_identifier_ctor, - tnet_dhcp6_option_identifier_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_option_identifier_def_s = { + sizeof(tnet_dhcp6_option_identifier_t), + tnet_dhcp6_option_identifier_ctor, + tnet_dhcp6_option_identifier_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_option_identifier_def_t = &tnet_dhcp6_option_identifier_def_s; @@ -245,20 +238,20 @@ const tsk_object_def_t *tnet_dhcp6_option_identifier_def_t = &tnet_dhcp6_option_ int tnet_dhcp6_option_orequest_add_code(tnet_dhcp6_option_orequest_t* self, uint16_t code) { - uint16_t _2bytes; - int ret = -1; - if(self){ - if(!self->codes){ - if(!(self->codes = tsk_buffer_create_null())){ - return -3; - } - } - _2bytes = tnet_ntohs(code); - if(!(ret = tsk_buffer_append(self->codes, &_2bytes, 2))){ - TNET_DHCP6_OPTION(self)->len += 2; - } - } - return ret; + uint16_t _2bytes; + int ret = -1; + if(self) { + if(!self->codes) { + if(!(self->codes = tsk_buffer_create_null())) { + return -3; + } + } + _2bytes = tnet_ntohs(code); + if(!(ret = tsk_buffer_append(self->codes, &_2bytes, 2))) { + TNET_DHCP6_OPTION(self)->len += 2; + } + } + return ret; } // @@ -266,33 +259,32 @@ int tnet_dhcp6_option_orequest_add_code(tnet_dhcp6_option_orequest_t* self, uint // static tsk_object_t* tnet_dhcp6_option_orequest_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_option_orequest_t *option = self; - if(option){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - if(payload && payload_size) - { /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_option_orequest_t *option = self; + if(option) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_option_orequest_dtor(tsk_object_t * self) -{ - tnet_dhcp6_option_orequest_t *option = self; - if(option){ - TSK_OBJECT_SAFE_FREE(option->codes); - } - return self; +static tsk_object_t* tnet_dhcp6_option_orequest_dtor(tsk_object_t * self) +{ + tnet_dhcp6_option_orequest_t *option = self; + if(option) { + TSK_OBJECT_SAFE_FREE(option->codes); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_option_orequest_def_s = -{ - sizeof(tnet_dhcp6_option_orequest_t), - tnet_dhcp6_option_orequest_ctor, - tnet_dhcp6_option_orequest_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_option_orequest_def_s = { + sizeof(tnet_dhcp6_option_orequest_t), + tnet_dhcp6_option_orequest_ctor, + tnet_dhcp6_option_orequest_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_option_orequest_def_t = &tnet_dhcp6_option_orequest_def_s; @@ -305,32 +297,31 @@ const tsk_object_def_t *tnet_dhcp6_option_orequest_def_t = &tnet_dhcp6_option_or // static tsk_object_t* tnet_dhcp6_option_vendorclass_ctor(tsk_object_t * self, va_list * app) { - tnet_dhcp6_option_vendorclass_t *option = self; - if(option){ - const void* payload = va_arg(*app, const void*); - tsk_size_t payload_size = va_arg(*app, tsk_size_t); - - if(payload && payload_size){ - /* DESERIALIZATION */ - } - } - return self; + tnet_dhcp6_option_vendorclass_t *option = self; + if(option) { + const void* payload = va_arg(*app, const void*); + tsk_size_t payload_size = va_arg(*app, tsk_size_t); + + if(payload && payload_size) { + /* DESERIALIZATION */ + } + } + return self; } -static tsk_object_t* tnet_dhcp6_option_vendorclass_dtor(tsk_object_t * self) -{ - tnet_dhcp6_option_vendorclass_t *option = self; - if(option){ - TSK_OBJECT_SAFE_FREE(option->vendor_class_data); - } - return self; +static tsk_object_t* tnet_dhcp6_option_vendorclass_dtor(tsk_object_t * self) +{ + tnet_dhcp6_option_vendorclass_t *option = self; + if(option) { + TSK_OBJECT_SAFE_FREE(option->vendor_class_data); + } + return self; } -static const tsk_object_def_t tnet_dhcp6_option_vendorclass_def_s = -{ - sizeof(tnet_dhcp6_option_vendorclass_t), - tnet_dhcp6_option_vendorclass_ctor, - tnet_dhcp6_option_vendorclass_dtor, - tsk_null, +static const tsk_object_def_t tnet_dhcp6_option_vendorclass_def_s = { + sizeof(tnet_dhcp6_option_vendorclass_t), + tnet_dhcp6_option_vendorclass_ctor, + tnet_dhcp6_option_vendorclass_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dhcp6_option_vendorclass_def_t = &tnet_dhcp6_option_vendorclass_def_s; diff --git a/tinyNET/src/dhcp6/tnet_dhcp6_option.h b/tinyNET/src/dhcp6/tnet_dhcp6_option.h index 71241b9..56ec83e 100755 --- a/tinyNET/src/dhcp6/tnet_dhcp6_option.h +++ b/tinyNET/src/dhcp6/tnet_dhcp6_option.h @@ -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. * @@ -42,47 +42,45 @@ TNET_BEGIN_DECLS #define TNET_DHCP6_OPTION(self) ((tnet_dhcp6_option_t*)(self)) /** List of DHCPv6 option as registered by IANA (RFC 3315 subcaluse 24.3)*/ -typedef enum tnet_dhcp6_option_code_e -{ - dhcp6_code_clientid = 1, /**< Client Identifier Option. */ - dhcp6_code_serverid = 2, /**< Server Identifier Option. */ - dhcp6_code_ia_na = 3, /**< Identity Association for Non-temporary Addresses Option. */ - dhcp6_code_ia_ta = 4, /**< Identity Association for Temporary Addresses Option. */ - dhcp6_code_iaaddr = 5, /**< IA Address Option. */ - dhcp6_code_oro = 6, /**< Option Request Option. */ - dhcp6_code_preference = 7, /**< Preference Option. */ - dhcp6_code_elapsed_time = 8, /**< Elapsed Time Option. */ - dhcp6_code_relay_msg = 9, /**< Relay Message Option. */ - dhcp6_code_auth = 11, /**< Authentication Option. */ - dhcp6_code_unicast = 12, /**< Server Unicast Option. */ - dhcp6_code_status_code = 13, /**< Status Code Option. */ - dhcp6_code_rapid_commit = 14, /**< Rapid Commit Option. */ - dhcp6_code_user_class = 15, /**< User Class Option. */ - dhcp6_code_vendor_class = 16, /**< Vendor Class Option. */ - dhcp6_code_vendor_opts = 17, /**< Vendor-specific Information Option. */ - dhcp6_code_interface_id = 18, /**< Interface-Id Option. */ - dhcp6_code_reconf_msg = 19, /**< Reconfigure Message Option. */ - dhcp6_code_reconf_accept = 20, /**< Reconfigure Accept Option. */ +typedef enum tnet_dhcp6_option_code_e { + dhcp6_code_clientid = 1, /**< Client Identifier Option. */ + dhcp6_code_serverid = 2, /**< Server Identifier Option. */ + dhcp6_code_ia_na = 3, /**< Identity Association for Non-temporary Addresses Option. */ + dhcp6_code_ia_ta = 4, /**< Identity Association for Temporary Addresses Option. */ + dhcp6_code_iaaddr = 5, /**< IA Address Option. */ + dhcp6_code_oro = 6, /**< Option Request Option. */ + dhcp6_code_preference = 7, /**< Preference Option. */ + dhcp6_code_elapsed_time = 8, /**< Elapsed Time Option. */ + dhcp6_code_relay_msg = 9, /**< Relay Message Option. */ + dhcp6_code_auth = 11, /**< Authentication Option. */ + dhcp6_code_unicast = 12, /**< Server Unicast Option. */ + dhcp6_code_status_code = 13, /**< Status Code Option. */ + dhcp6_code_rapid_commit = 14, /**< Rapid Commit Option. */ + dhcp6_code_user_class = 15, /**< User Class Option. */ + dhcp6_code_vendor_class = 16, /**< Vendor Class Option. */ + dhcp6_code_vendor_opts = 17, /**< Vendor-specific Information Option. */ + dhcp6_code_interface_id = 18, /**< Interface-Id Option. */ + dhcp6_code_reconf_msg = 19, /**< Reconfigure Message Option. */ + dhcp6_code_reconf_accept = 20, /**< Reconfigure Accept Option. */ } tnet_dhcp6_option_code_t; /** List of DHCPv6 status codes as registered by IANA (RFC 3315 subclause 24.4) */ -typedef enum tnet_dhcp6_statuscode_e -{ - /* Success */ - dhcp6_statuscode_Success = 0, - /* Failure, reason unspecified; this status code is sent by either a client - or a server to indicate a failure not explicitly specified in this document (RFC 3315). */ - dhcp6_statuscode_UnspecFail = 1, - /* Server has no addresses available to assign to the IA(s). */ - dhcp6_statuscode_NoAddrsAvail = 2, - /* Client record (binding) unavailable. */ - dhcp6_statuscode_NoBinding = 3, - /* The prefix for the address is not appropriate for the link to which the client is attached. */ - dhcp6_statuscode_NotOnLink = 4, - /* Sent by a server to a client to force the client to send messages to the server. - using the All_DHCP_Relay_Agents_and_Servers address.*/ - dhcp6_statuscode_UseMulticast = 5 +typedef enum tnet_dhcp6_statuscode_e { + /* Success */ + dhcp6_statuscode_Success = 0, + /* Failure, reason unspecified; this status code is sent by either a client + or a server to indicate a failure not explicitly specified in this document (RFC 3315). */ + dhcp6_statuscode_UnspecFail = 1, + /* Server has no addresses available to assign to the IA(s). */ + dhcp6_statuscode_NoAddrsAvail = 2, + /* Client record (binding) unavailable. */ + dhcp6_statuscode_NoBinding = 3, + /* The prefix for the address is not appropriate for the link to which the client is attached. */ + dhcp6_statuscode_NotOnLink = 4, + /* Sent by a server to a client to force the client to send messages to the server. + using the All_DHCP_Relay_Agents_and_Servers address.*/ + dhcp6_statuscode_UseMulticast = 5 } tnet_dhcp6_statuscode_t; @@ -93,34 +91,32 @@ tnet_dhcp6_statuscode_t; /**@ingroup tnet_dhcpv_group * DHCPv6 option-data. */ -typedef struct tnet_dhcp6_option_data_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_dhcp6_option_data_s { + TSK_DECLARE_OBJECT; } tnet_dhcp6_option_data_t; #define TNET_DECLARE_DHCP6_OPTION_DATA tnet_dhcp6_option_data_t dhcp6_option_data -typedef struct tnet_dhcp6_option_s -{ - TSK_DECLARE_OBJECT; - - /* RFC 3315 - 22.1. Format of DHCP Options - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | option-code(2) | option-len(2) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | option-data | - | (option-len octets) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - /* An unsigned integer identifying the specific option type carried in this option.*/ - tnet_dhcp6_option_code_t code; - /* Option length. Same as tsk_strlen(data buffer)*/ - uint16_t len; - /* opton-data */ - tnet_dhcp6_option_data_t *data; +typedef struct tnet_dhcp6_option_s { + TSK_DECLARE_OBJECT; + + /* RFC 3315 - 22.1. Format of DHCP Options + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | option-code(2) | option-len(2) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | option-data | + | (option-len octets) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + /* An unsigned integer identifying the specific option type carried in this option.*/ + tnet_dhcp6_option_code_t code; + /* Option length. Same as tsk_strlen(data buffer)*/ + uint16_t len; + /* opton-data */ + tnet_dhcp6_option_data_t *data; } tnet_dhcp6_option_t; @@ -136,29 +132,28 @@ int tnet_dhcp6_option_serializeex(tnet_dhcp6_option_code_t code, uint8_t length, /*====================================================================================== -* RFC 3315 - +* RFC 3315 - 22.2. Client Identifier Option 22.3. Server Identifier Option *=======================================================================================*/ /** DHCPv6 Client /server Identifier Option (subclause 22.2 and 22.3). */ -typedef struct tnet_dhcp6_option_identifier_s -{ - TNET_DECLARE_DHCP6_OPTION_DATA; - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | OPTION_XXXXXXID | option-len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - . . - . DUID . - . (variable length) . - . . - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - OPTION_XXXXXXID = OPTION_CLIENTID or OPTION_SERVERID - */ - tnet_dhcp6_duid_t *duid; +typedef struct tnet_dhcp6_option_identifier_s { + TNET_DECLARE_DHCP6_OPTION_DATA; + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | OPTION_XXXXXXID | option-len | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + . . + . DUID . + . (variable length) . + . . + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + OPTION_XXXXXXID = OPTION_CLIENTID or OPTION_SERVERID + */ + tnet_dhcp6_duid_t *duid; } tnet_dhcp6_option_identifier_t; typedef tnet_dhcp6_option_identifier_t tnet_dhcp6_option_clientid_t; @@ -175,21 +170,20 @@ typedef tnet_dhcp6_option_identifier_t tnet_dhcp6_option_serverid_t; /** DHCPv6 Option Request Option (subclause 22.7). */ -typedef struct tnet_dhcp6_option_orequest_s -{ - TNET_DECLARE_DHCP6_OPTION_DATA; - /* - 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 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | OPTION_ORO | option-len | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | requested-option-code-1 | requested-option-code-2 | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | ... | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - tsk_buffer_t* codes; +typedef struct tnet_dhcp6_option_orequest_s { + TNET_DECLARE_DHCP6_OPTION_DATA; + /* + 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 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | OPTION_ORO | option-len | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | requested-option-code-1 | requested-option-code-2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | ... | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + tsk_buffer_t* codes; } tnet_dhcp6_option_orequest_t; @@ -201,11 +195,10 @@ TINYNET_API int tnet_dhcp6_option_orequest_add_code(tnet_dhcp6_option_orequest_t /** DHCPv6 Vendor Class Option (subclause 22.16). */ -typedef struct tnet_dhcp6_option_vendorclass_s -{ - TNET_DECLARE_DHCP6_OPTION_DATA; - /* - 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 +typedef struct tnet_dhcp6_option_vendorclass_s { + TNET_DECLARE_DHCP6_OPTION_DATA; + /* + 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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OPTION_VENDOR_CLASS | option-len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -215,14 +208,14 @@ typedef struct tnet_dhcp6_option_vendorclass_s . vendor-class-data . . . . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - uint32_t enterprise_number; - /* - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+ + */ + uint32_t enterprise_number; + /* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+ | vendor-class-len | opaque-data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+ - */ - tsk_buffer_t* vendor_class_data; + */ + tsk_buffer_t* vendor_class_data; } tnet_dhcp6_option_vendorclass_t; diff --git a/tinyNET/src/dns/tnet_dns.c b/tinyNET/src/dns/tnet_dns.c index 87cd9b5..e131c4d 100755 --- a/tinyNET/src/dns/tnet_dns.c +++ b/tinyNET/src/dns/tnet_dns.c @@ -158,7 +158,7 @@ TSK_OBJECT_SAFE_FREE(ctx); */ tnet_dns_ctx_t* tnet_dns_ctx_create() { - return tsk_object_new(tnet_dns_ctx_def_t); + return tsk_object_new(tnet_dns_ctx_def_t); } /**@ingroup tnet_dns_group @@ -166,7 +166,7 @@ tnet_dns_ctx_t* tnet_dns_ctx_create() */ tnet_dns_cache_entry_t* tnet_dns_cache_entry_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tnet_dns_response_t* answer) { - return tsk_object_new(tnet_dns_cache_entry_def_t, qname, qclass, qtype, answer); + return tsk_object_new(tnet_dns_cache_entry_def_t, qname, qclass, qtype, answer); } @@ -178,14 +178,14 @@ tnet_dns_cache_entry_t* tnet_dns_cache_entry_create(const char* qname, tnet_dns_ */ int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx) { - if (ctx){ - tsk_safeobj_lock(ctx); - tsk_list_clear_items(ctx->cache); - tsk_safeobj_unlock(ctx); - - return 0; - } - return -1; + if (ctx) { + tsk_safeobj_lock(ctx); + tsk_list_clear_items(ctx->cache); + tsk_safeobj_unlock(ctx); + + return 0; + } + return -1; } /**@ingroup tnet_dns_group @@ -208,274 +208,275 @@ int tnet_dns_cache_clear(tnet_dns_ctx_t* ctx) tnet_dns_response_t *tnet_dns_resolve(tnet_dns_ctx_t* ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype) { #if HAVE_DNS_H - struct sockaddr_storage result; - struct sockaddr *from; - uint32_t fromlen; - char buf[TNET_DNS_DGRAM_SIZE_DEFAULT]; - int32_t ret; - - tnet_dns_response_t *response = tsk_null; - - tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4); - tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6); - - tsk_safeobj_lock(ctx); - - // First, try with IPv4 - if(TNET_SOCKET_IS_VALID(localsocket4)){ - if((ret = tnet_getsockname(localsocket4->fd, &result))){ - TNET_PRINT_LAST_ERROR("tnet_getsockname() failed."); - goto ipv6; - } - from = (struct sockaddr *) &result; - fromlen = tnet_get_sockaddr_size(from); - - if ((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0) { - response = tnet_dns_message_deserialize((uint8_t *) buf, ret); - goto done; - } - else{ - TNET_PRINT_LAST_ERROR("dns_search_v4()"); - } - } + struct sockaddr_storage result; + struct sockaddr *from; + uint32_t fromlen; + char buf[TNET_DNS_DGRAM_SIZE_DEFAULT]; + int32_t ret; + + tnet_dns_response_t *response = tsk_null; + + tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4); + tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6); + + tsk_safeobj_lock(ctx); + + // First, try with IPv4 + if(TNET_SOCKET_IS_VALID(localsocket4)) { + if((ret = tnet_getsockname(localsocket4->fd, &result))) { + TNET_PRINT_LAST_ERROR("tnet_getsockname() failed."); + goto ipv6; + } + from = (struct sockaddr *) &result; + fromlen = tnet_get_sockaddr_size(from); + + if ((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0) { + response = tnet_dns_message_deserialize((uint8_t *) buf, ret); + goto done; + } + else { + TNET_PRINT_LAST_ERROR("dns_search_v4()"); + } + } ipv6: - // Then, try with IPv6 - if(TNET_SOCKET_IS_VALID(localsocket6)){ - if((ret = tnet_getsockname(localsocket6->fd, &result))){ - TNET_PRINT_LAST_ERROR("tnet_getsockname() failed."); - goto done; - } - from = (struct sockaddr *) &result; - fromlen = tnet_get_sockaddr_size(from); - - if((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0){ - response = tnet_dns_message_deserialize((uint8_t *) buf, ret); - goto done; - } - else{ - TNET_PRINT_LAST_ERROR("dns_search_v6()"); - } - } + // Then, try with IPv6 + if(TNET_SOCKET_IS_VALID(localsocket6)) { + if((ret = tnet_getsockname(localsocket6->fd, &result))) { + TNET_PRINT_LAST_ERROR("tnet_getsockname() failed."); + goto done; + } + from = (struct sockaddr *) &result; + fromlen = tnet_get_sockaddr_size(from); + + if((ret = dns_search(ctx->resolv_handle, qname, qclass, qtype, buf, TNET_DNS_DGRAM_SIZE_DEFAULT, from, &fromlen)) > 0) { + response = tnet_dns_message_deserialize((uint8_t *) buf, ret); + goto done; + } + else { + TNET_PRINT_LAST_ERROR("dns_search_v6()"); + } + } done: - tsk_safeobj_unlock(ctx); + tsk_safeobj_unlock(ctx); - TSK_OBJECT_SAFE_FREE(localsocket4); - TSK_OBJECT_SAFE_FREE(localsocket6); + TSK_OBJECT_SAFE_FREE(localsocket4); + TSK_OBJECT_SAFE_FREE(localsocket6); - return response; + return response; #else - tsk_buffer_t *output = tsk_null; - tnet_dns_query_t* query = tnet_dns_query_create(qname, qclass, qtype); - tnet_dns_response_t *response = tsk_null; - tsk_bool_t from_cache = tsk_false; - - /* Check validity */ - if (!ctx || !query){ - goto bail; - } - - /* Is there any DNS Server? */ - if (TSK_LIST_IS_EMPTY(ctx->servers)){ - TSK_DEBUG_ERROR("Failed to load DNS Servers. You can add new DNS servers by using \"tnet_dns_add_server\"."); - goto bail; - } - - /* Cache maintenance */ - if (!TSK_LIST_IS_EMPTY(ctx->cache)){ - /* Only do maintenance if the cache is not empty */ - tnet_dns_cache_maintenance(ctx); - } - - /* Retrieve data from cache. */ - if (ctx->caching){ - const tnet_dns_cache_entry_t *entry = tnet_dns_cache_entry_get(ctx, qname, qclass, qtype); - if (entry){ - response = tsk_object_ref(((tnet_dns_cache_entry_t*)entry)->response); - from_cache = tsk_true; - goto bail; - } - } - - /* Set user preference */ - query->Header.RD = ctx->recursion; - - /* EDNS0 */ - if (ctx->edns0){ - tnet_dns_opt_t *rr_opt = tnet_dns_opt_create(TNET_DNS_DGRAM_SIZE_DEFAULT); - if (!query->Additionals){ - query->Additionals = tsk_list_create(); - } - tsk_list_push_back_data(query->Additionals, (void**)&rr_opt); - query->Header.ARCOUNT++; - } - - /* Serialize and send to the server. */ - if (!(output = tnet_dns_message_serialize(query))){ - TSK_DEBUG_ERROR("Failed to serialize the DNS message."); - goto bail; - } - - /* ============================ */ - // Send and Recaive data - /* ============================ */ - { - int ret = -1; - struct timeval tv; - fd_set set; - tnet_fd_t maxFD; - uint64_t timeout = 0; - tsk_list_item_t *item; - const tnet_address_t *address; - struct sockaddr_storage server; - tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4); - tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6); - tsk_bool_t useIPv6 = TNET_SOCKET_IS_VALID(localsocket6); - - tsk_safeobj_lock(ctx); - - /* Check socket validity */ - if (!TNET_SOCKET_IS_VALID(localsocket4)){ - goto done; - } - - /* Always wait 500ms before retransmission */ - tv.tv_sec = 0; - tv.tv_usec = (500 * 1000); - - do - { - // - // Send data (loop through all intefaces) - // - tsk_list_foreach(item, ctx->servers) - { - address = item->data; - if (!address->ip || - (address->family != AF_INET && address->family != AF_INET6) || - (address->family == AF_INET6 && !TNET_SOCKET_IS_VALID(localsocket6))){ - continue; - } - - if (tnet_sockaddr_init(address->ip, ctx->server_port, (address->family == AF_INET ? tnet_socket_type_udp_ipv4 : tnet_socket_type_udp_ipv6), &server)){ - TSK_DEBUG_ERROR("Failed to initialize the DNS server address: \"%s\"", address->ip); - continue; - } - - TSK_DEBUG_INFO("Sending DNS query to \"%s\"", address->ip); - - if (address->family == AF_INET6){ - if ((ret = tnet_sockfd_sendto(localsocket6->fd, (const struct sockaddr*)&server, output->data, output->size))){ - // succeed? - break; - } - } - else{ - if ((ret = tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size))){ - // succeed? - break; - } - } - } - - // - // Received data - // - /* First time? ==> set timeout value */ - if (!timeout){ - timeout = tsk_time_epoch() + ctx->timeout; - } - - /* Set FDs */ - FD_ZERO(&set); - FD_SET(localsocket4->fd, &set); - if (useIPv6){ - FD_SET(localsocket6->fd, &set); - maxFD = TSK_MAX(localsocket4->fd, localsocket6->fd); - } - else{ - maxFD = localsocket4->fd; - } - - /* wait for response */ - if ((ret = select(maxFD + 1, &set, NULL, NULL, &tv)) < 0){ /* Error */ - TNET_PRINT_LAST_ERROR("Select failed."); - goto done; - } - else if (ret == 0){ /* timeout ==> do nothing */ - - } - else{ /* there is data to read */ - unsigned int len = 0; - void* data = 0; - tnet_fd_t active_fd; - - /* Find active file descriptor */ - if (FD_ISSET(localsocket4->fd, &set)){ - active_fd = localsocket4->fd; - } - else if (FD_ISSET(localsocket6->fd, &set)){ - active_fd = localsocket4->fd; - } - else{ - TSK_DEBUG_ERROR("FD_ISSET ==> Invalid file descriptor."); - continue; - } - - /* Check how how many bytes are pending */ - if ((ret = tnet_ioctlt(active_fd, FIONREAD, &len)) < 0){ - TSK_DEBUG_ERROR("tnet_ioctlt failed with error code:%d", tnet_geterrno()); - goto done; - } - - /* Receive pending data */ - data = tsk_calloc(len, sizeof(uint8_t)); - if ((ret = tnet_sockfd_recv(active_fd, data, len, 0)) < 0){ - TSK_FREE(data); - - TSK_DEBUG_ERROR("tnet_sockfd_recv failed with error code:%d", tnet_geterrno()); - goto done; - } - - /* Parse the incoming response. */ - response = tnet_dns_message_deserialize(data, (tsk_size_t)ret); - TSK_FREE(data); - - if (response) - { /* response successfuly parsed */ - if (query->Header.ID != response->Header.ID || !TNET_DNS_MESSAGE_IS_RESPONSE(response)){ - /* Not same transaction id ==> continue*/ - TSK_OBJECT_SAFE_FREE(response); - } - else goto done; - } - } - } while (timeout > tsk_time_epoch()); - - done: - tsk_safeobj_unlock(ctx); - - TSK_OBJECT_SAFE_FREE(localsocket4); - TSK_OBJECT_SAFE_FREE(localsocket6); - goto bail; - } + tsk_buffer_t *output = tsk_null; + tnet_dns_query_t* query = tnet_dns_query_create(qname, qclass, qtype); + tnet_dns_response_t *response = tsk_null; + tsk_bool_t from_cache = tsk_false; + + /* Check validity */ + if (!ctx || !query) { + goto bail; + } + + /* Is there any DNS Server? */ + if (TSK_LIST_IS_EMPTY(ctx->servers)) { + TSK_DEBUG_ERROR("Failed to load DNS Servers. You can add new DNS servers by using \"tnet_dns_add_server\"."); + goto bail; + } + + /* Cache maintenance */ + if (!TSK_LIST_IS_EMPTY(ctx->cache)) { + /* Only do maintenance if the cache is not empty */ + tnet_dns_cache_maintenance(ctx); + } + + /* Retrieve data from cache. */ + if (ctx->caching) { + const tnet_dns_cache_entry_t *entry = tnet_dns_cache_entry_get(ctx, qname, qclass, qtype); + if (entry) { + response = tsk_object_ref(((tnet_dns_cache_entry_t*)entry)->response); + from_cache = tsk_true; + goto bail; + } + } + + /* Set user preference */ + query->Header.RD = ctx->recursion; + + /* EDNS0 */ + if (ctx->edns0) { + tnet_dns_opt_t *rr_opt = tnet_dns_opt_create(TNET_DNS_DGRAM_SIZE_DEFAULT); + if (!query->Additionals) { + query->Additionals = tsk_list_create(); + } + tsk_list_push_back_data(query->Additionals, (void**)&rr_opt); + query->Header.ARCOUNT++; + } + + /* Serialize and send to the server. */ + if (!(output = tnet_dns_message_serialize(query))) { + TSK_DEBUG_ERROR("Failed to serialize the DNS message."); + goto bail; + } + + /* ============================ */ + // Send and Recaive data + /* ============================ */ + { + int ret = -1; + struct timeval tv; + fd_set set; + tnet_fd_t maxFD; + uint64_t timeout = 0; + tsk_list_item_t *item; + const tnet_address_t *address; + struct sockaddr_storage server; + tnet_socket_t *localsocket4 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv4); + tnet_socket_t *localsocket6 = tnet_socket_create(TNET_SOCKET_HOST_ANY, TNET_SOCKET_PORT_ANY, tnet_socket_type_udp_ipv6); + tsk_bool_t useIPv6 = TNET_SOCKET_IS_VALID(localsocket6); + + tsk_safeobj_lock(ctx); + + /* Check socket validity */ + if (!TNET_SOCKET_IS_VALID(localsocket4)) { + goto done; + } + + /* Always wait 500ms before retransmission */ + tv.tv_sec = 0; + tv.tv_usec = (500 * 1000); + + do { + // + // Send data (loop through all intefaces) + // + tsk_list_foreach(item, ctx->servers) { + address = item->data; + if (!address->ip || + (address->family != AF_INET && address->family != AF_INET6) || + (address->family == AF_INET6 && !TNET_SOCKET_IS_VALID(localsocket6))) { + continue; + } + + if (tnet_sockaddr_init(address->ip, ctx->server_port, (address->family == AF_INET ? tnet_socket_type_udp_ipv4 : tnet_socket_type_udp_ipv6), &server)) { + TSK_DEBUG_ERROR("Failed to initialize the DNS server address: \"%s\"", address->ip); + continue; + } + + TSK_DEBUG_INFO("Sending DNS query to \"%s\"", address->ip); + + if (address->family == AF_INET6) { + if ((ret = tnet_sockfd_sendto(localsocket6->fd, (const struct sockaddr*)&server, output->data, output->size))) { + // succeed? + break; + } + } + else { + if ((ret = tnet_sockfd_sendto(localsocket4->fd, (const struct sockaddr*)&server, output->data, output->size))) { + // succeed? + break; + } + } + } + + // + // Received data + // + /* First time? ==> set timeout value */ + if (!timeout) { + timeout = tsk_time_epoch() + ctx->timeout; + } + + /* Set FDs */ + FD_ZERO(&set); + FD_SET(localsocket4->fd, &set); + if (useIPv6) { + FD_SET(localsocket6->fd, &set); + maxFD = TSK_MAX(localsocket4->fd, localsocket6->fd); + } + else { + maxFD = localsocket4->fd; + } + + /* wait for response */ + if ((ret = select(maxFD + 1, &set, NULL, NULL, &tv)) < 0) { /* Error */ + TNET_PRINT_LAST_ERROR("Select failed."); + goto done; + } + else if (ret == 0) { /* timeout ==> do nothing */ + + } + else { /* there is data to read */ + unsigned int len = 0; + void* data = 0; + tnet_fd_t active_fd; + + /* Find active file descriptor */ + if (FD_ISSET(localsocket4->fd, &set)) { + active_fd = localsocket4->fd; + } + else if (FD_ISSET(localsocket6->fd, &set)) { + active_fd = localsocket4->fd; + } + else { + TSK_DEBUG_ERROR("FD_ISSET ==> Invalid file descriptor."); + continue; + } + + /* Check how how many bytes are pending */ + if ((ret = tnet_ioctlt(active_fd, FIONREAD, &len)) < 0) { + TSK_DEBUG_ERROR("tnet_ioctlt failed with error code:%d", tnet_geterrno()); + goto done; + } + + /* Receive pending data */ + data = tsk_calloc(len, sizeof(uint8_t)); + if ((ret = tnet_sockfd_recv(active_fd, data, len, 0)) < 0) { + TSK_FREE(data); + + TSK_DEBUG_ERROR("tnet_sockfd_recv failed with error code:%d", tnet_geterrno()); + goto done; + } + + /* Parse the incoming response. */ + response = tnet_dns_message_deserialize(data, (tsk_size_t)ret); + TSK_FREE(data); + + if (response) { + /* response successfuly parsed */ + if (query->Header.ID != response->Header.ID || !TNET_DNS_MESSAGE_IS_RESPONSE(response)) { + /* Not same transaction id ==> continue*/ + TSK_OBJECT_SAFE_FREE(response); + } + else { + goto done; + } + } + } + } + while (timeout > tsk_time_epoch()); + +done: + tsk_safeobj_unlock(ctx); + + TSK_OBJECT_SAFE_FREE(localsocket4); + TSK_OBJECT_SAFE_FREE(localsocket6); + goto bail; + } bail: - TSK_OBJECT_SAFE_FREE(query); - TSK_OBJECT_SAFE_FREE(output); - - /* Add the result to the cache. */ - if (response){ - if (!from_cache && ctx->caching){ - tnet_dns_cache_entry_add(ctx, qname, qclass, qtype, response); - } - } - else{ - TSK_DEBUG_ERROR("Failed to contact the DNS server."); - } - - return response; + TSK_OBJECT_SAFE_FREE(query); + TSK_OBJECT_SAFE_FREE(output); + + /* Add the result to the cache. */ + if (response) { + if (!from_cache && ctx->caching) { + tnet_dns_cache_entry_add(ctx, qname, qclass, qtype, response); + } + } + else { + TSK_DEBUG_ERROR("Failed to contact the DNS server."); + } + + return response; #endif } @@ -491,65 +492,65 @@ bail: */ tnet_dns_response_t* tnet_dns_enum(tnet_dns_ctx_t* ctx, const char* e164num, const char* domain) { - char e164domain[255]; - tnet_dns_response_t* ret = tsk_null; - int e164size; - int i, j; // must be signed - - e164size = (int)tsk_strlen(e164num); - - if (!ctx || !e164num || !e164size){ - goto bail; - } - - if (e164size /* max=15 digits + ".e164.arpa" + '+' */ >= (sizeof(e164domain) - 1)){ - TSK_DEBUG_ERROR("%s is an invalid E.164 number.", e164num); - goto bail; - } - - memset(e164domain, '\0', sizeof(e164domain)); - - /* RFC 3761 - 2.4. Valid Databases - 1. Remove all characters with the exception of the digits. For - example, the First Well Known Rule produced the Key - "+442079460148". This step would simply remove the leading "+", - producing "442079460148". - - 2. Put dots (".") between each digit. Example: - 4.4.2.0.7.9.4.6.0.1.4.8 - - 3. Reverse the order of the digits. Example: - 8.4.1.0.6.4.9.7.0.2.4.4 - - 4. Append the string ".e164.arpa" to the end. Example: - 8.4.1.0.6.4.9.7.0.2.4.4.e164.arpa - - This domain-name is used to request NAPTR records which may contain - the end result or, if the flags field is blank, produces new keys in - the form of domain-names from the DNS. - */ - for (i = e164size - 1, j = 0; i >= 0; i--){ - if (!isdigit(e164num[i])){ - continue; - } - e164domain[j++] = e164num[i]; - e164domain[j++] = '.'; - } - - // append domain name - if (domain){ - memcpy(&e164domain[j], domain, ((tsk_strlen(domain) + j) >= sizeof(e164domain) - 1) ? (sizeof(e164domain) - j - 1) : tsk_strlen(domain)); - } - else{ - memcpy(&e164domain[j], "e164.arpa", 9); - } - - /* == Performs DNS (NAPTR) lookup == */ - ret = tnet_dns_resolve(ctx, e164domain, qclass_in, qtype_naptr); + char e164domain[255]; + tnet_dns_response_t* ret = tsk_null; + int e164size; + int i, j; // must be signed + + e164size = (int)tsk_strlen(e164num); + + if (!ctx || !e164num || !e164size) { + goto bail; + } + + if (e164size /* max=15 digits + ".e164.arpa" + '+' */ >= (sizeof(e164domain) - 1)) { + TSK_DEBUG_ERROR("%s is an invalid E.164 number.", e164num); + goto bail; + } + + memset(e164domain, '\0', sizeof(e164domain)); + + /* RFC 3761 - 2.4. Valid Databases + 1. Remove all characters with the exception of the digits. For + example, the First Well Known Rule produced the Key + "+442079460148". This step would simply remove the leading "+", + producing "442079460148". + + 2. Put dots (".") between each digit. Example: + 4.4.2.0.7.9.4.6.0.1.4.8 + + 3. Reverse the order of the digits. Example: + 8.4.1.0.6.4.9.7.0.2.4.4 + + 4. Append the string ".e164.arpa" to the end. Example: + 8.4.1.0.6.4.9.7.0.2.4.4.e164.arpa + + This domain-name is used to request NAPTR records which may contain + the end result or, if the flags field is blank, produces new keys in + the form of domain-names from the DNS. + */ + for (i = e164size - 1, j = 0; i >= 0; i--) { + if (!isdigit(e164num[i])) { + continue; + } + e164domain[j++] = e164num[i]; + e164domain[j++] = '.'; + } + + // append domain name + if (domain) { + memcpy(&e164domain[j], domain, ((tsk_strlen(domain) + j) >= sizeof(e164domain) - 1) ? (sizeof(e164domain) - j - 1) : tsk_strlen(domain)); + } + else { + memcpy(&e164domain[j], "e164.arpa", 9); + } + + /* == Performs DNS (NAPTR) lookup == */ + ret = tnet_dns_resolve(ctx, e164domain, qclass_in, qtype_naptr); bail: - return ret; + return ret; } /**@ingroup tnet_dns_group @@ -568,48 +569,48 @@ bail: */ char* tnet_dns_enum_2(tnet_dns_ctx_t* ctx, const char* service, const char* e164num, const char* domain) { - tnet_dns_response_t* response; - const tsk_list_item_t* item; - char* ret = tsk_null; - const tnet_dns_rr_t* rr; - - if ((response = tnet_dns_enum(ctx, e164num, domain))){ - if (TNET_DNS_RESPONSE_IS_SUCCESS(response)){ - 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; - /* RFC 3403 - 6.2 E164 Example - Both the ENUM [18] and URI Resolution [4] Applications use the 'u' - flag. This flag states that the Rule is terminal and that the output - is a URI which contains the information needed to contact that - telephone service. - */ - if (tsk_striequals(naptr->flags, "u") && tsk_striequals(naptr->services, service)){ - /* RFC 3403 - 4.1 Packet Format - The fields (replacement and regexp) are also mutually exclusive. If a record is - returned that has values for both fields then it is considered to - be in error and SHOULD be either ignored or an error returned. - */ - if (naptr->regexp && naptr->replacement){ - continue; - } - - if ((ret = tnet_dns_regex_parse(e164num, naptr->regexp))){ - break; - } - } - } - } - } - else{ - TSK_DEBUG_ERROR("We got an error response from the DNS server. Error code: %u", response->Header.RCODE); - } - - TSK_OBJECT_SAFE_FREE(response); - } - - return ret; + tnet_dns_response_t* response; + const tsk_list_item_t* item; + char* ret = tsk_null; + const tnet_dns_rr_t* rr; + + if ((response = tnet_dns_enum(ctx, e164num, domain))) { + if (TNET_DNS_RESPONSE_IS_SUCCESS(response)) { + 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; + /* RFC 3403 - 6.2 E164 Example + Both the ENUM [18] and URI Resolution [4] Applications use the 'u' + flag. This flag states that the Rule is terminal and that the output + is a URI which contains the information needed to contact that + telephone service. + */ + if (tsk_striequals(naptr->flags, "u") && tsk_striequals(naptr->services, service)) { + /* RFC 3403 - 4.1 Packet Format + The fields (replacement and regexp) are also mutually exclusive. If a record is + returned that has values for both fields then it is considered to + be in error and SHOULD be either ignored or an error returned. + */ + if (naptr->regexp && naptr->replacement) { + continue; + } + + if ((ret = tnet_dns_regex_parse(e164num, naptr->regexp))) { + break; + } + } + } + } + } + else { + TSK_DEBUG_ERROR("We got an error response from the DNS server. Error code: %u", response->Header.RCODE); + } + + TSK_OBJECT_SAFE_FREE(response); + } + + return ret; } /**@ingroup tnet_dns_group @@ -637,33 +638,31 @@ char* tnet_dns_enum_2(tnet_dns_ctx_t* ctx, const char* service, const char* e164 */ int tnet_dns_query_srv(tnet_dns_ctx_t *ctx, const char* service, char** hostname, tnet_port_t* port) { - tnet_dns_response_t *response; - - if (!ctx){ - return -1; - } - - // tnet_dns_resolve is thread-safe - if ((response = tnet_dns_resolve(ctx, service, qclass_in, qtype_srv))) - { - const tsk_list_item_t *item; - const tnet_dns_rr_t* rr; - tsk_list_foreach(item, response->Answers) /* Already Filtered ==> Peek the first One */ - { - rr = item->data; - if (rr->qtype == qtype_srv){ - const tnet_dns_srv_t *srv = (const tnet_dns_srv_t*)rr; - - tsk_strupdate(hostname, srv->target); - *port = srv->port; - break; - } - } - } - - TSK_OBJECT_SAFE_FREE(response); - - return (hostname && !tsk_strnullORempty(*hostname)) ? 0 : -2; + tnet_dns_response_t *response; + + if (!ctx) { + return -1; + } + + // tnet_dns_resolve is thread-safe + if ((response = tnet_dns_resolve(ctx, service, qclass_in, qtype_srv))) { + const tsk_list_item_t *item; + const tnet_dns_rr_t* rr; + tsk_list_foreach(item, response->Answers) { /* Already Filtered ==> Peek the first One */ + rr = item->data; + if (rr->qtype == qtype_srv) { + const tnet_dns_srv_t *srv = (const tnet_dns_srv_t*)rr; + + tsk_strupdate(hostname, srv->target); + *port = srv->port; + break; + } + } + } + + TSK_OBJECT_SAFE_FREE(response); + + return (hostname && !tsk_strnullORempty(*hostname)) ? 0 : -2; } /**@ingroup tnet_dns_group @@ -692,157 +691,152 @@ int tnet_dns_query_srv(tnet_dns_ctx_t *ctx, const char* service, char** hostname */ int tnet_dns_query_naptr_srv(tnet_dns_ctx_t *ctx, const char* domain, const char* service, char** hostname, tnet_port_t* port) { - tnet_dns_response_t *response; - - if (!ctx || !hostname){ - TSK_DEBUG_ERROR("Invalid parameters."); - return -1; - } - - /* reset (do not free the user supplied value). trying to free dummy value will cause access violation error ==> zero. */ - *hostname = tsk_null; - - // tnet_dns_resolve is thread-safe - if ((response = tnet_dns_resolve(ctx, domain, qclass_in, qtype_naptr))){ - const tsk_list_item_t *item; - const tnet_dns_rr_t* rr; - - char* replacement = tsk_null; /* e.g. _sip._udp.example.com */ - char* flags = tsk_null;/* e.g. S, A, AAAA, A6, U, P ... */ - - tsk_list_foreach(item, response->Answers) /* Already Filtered ==> Peek the first One */ - { - rr = item->data; - if (rr->qtype == qtype_naptr){ - tnet_dns_naptr_t *naptr = (tnet_dns_naptr_t*)rr; - - if (tsk_striequals(service, naptr->services)){ - tsk_strupdate(&replacement, naptr->replacement); - tsk_strupdate(&flags, naptr->flags); - - break; - } - } - } - - if (flags && replacement){ - if (tsk_striequals(flags, "S")){ - tnet_dns_query_srv(ctx, replacement, hostname, port); - } - else if (tsk_striequals(flags, "A") || tsk_striequals(flags, "AAAA") || tsk_striequals(flags, "A6")){ - TSK_DEBUG_WARN("Defaulting port value."); - tsk_strupdate(hostname, replacement); - *port = 5060; - } - else{ - TSK_DEBUG_ERROR("DNS NAPTR query returned invalid flags"); - } - } - else{ - TSK_DEBUG_INFO("DNS NAPTR (%s) query returned zero result", domain); - } - - TSK_FREE(flags); - TSK_FREE(replacement); - } - - TSK_OBJECT_SAFE_FREE(response); - - return (hostname && *hostname && !tsk_strempty(*hostname)) ? 0 : -2; + tnet_dns_response_t *response; + + if (!ctx || !hostname) { + TSK_DEBUG_ERROR("Invalid parameters."); + return -1; + } + + /* reset (do not free the user supplied value). trying to free dummy value will cause access violation error ==> zero. */ + *hostname = tsk_null; + + // tnet_dns_resolve is thread-safe + if ((response = tnet_dns_resolve(ctx, domain, qclass_in, qtype_naptr))) { + const tsk_list_item_t *item; + const tnet_dns_rr_t* rr; + + char* replacement = tsk_null; /* e.g. _sip._udp.example.com */ + char* flags = tsk_null;/* e.g. S, A, AAAA, A6, U, P ... */ + + tsk_list_foreach(item, response->Answers) { /* Already Filtered ==> Peek the first One */ + rr = item->data; + if (rr->qtype == qtype_naptr) { + tnet_dns_naptr_t *naptr = (tnet_dns_naptr_t*)rr; + + if (tsk_striequals(service, naptr->services)) { + tsk_strupdate(&replacement, naptr->replacement); + tsk_strupdate(&flags, naptr->flags); + + break; + } + } + } + + if (flags && replacement) { + if (tsk_striequals(flags, "S")) { + tnet_dns_query_srv(ctx, replacement, hostname, port); + } + else if (tsk_striequals(flags, "A") || tsk_striequals(flags, "AAAA") || tsk_striequals(flags, "A6")) { + TSK_DEBUG_WARN("Defaulting port value."); + tsk_strupdate(hostname, replacement); + *port = 5060; + } + else { + TSK_DEBUG_ERROR("DNS NAPTR query returned invalid flags"); + } + } + else { + TSK_DEBUG_INFO("DNS NAPTR (%s) query returned zero result", domain); + } + + TSK_FREE(flags); + TSK_FREE(replacement); + } + + TSK_OBJECT_SAFE_FREE(response); + + return (hostname && *hostname && !tsk_strempty(*hostname)) ? 0 : -2; } // remove timedout entries int tnet_dns_cache_maintenance(tnet_dns_ctx_t *ctx) { - if (ctx) - { - tsk_list_item_t *item; - tsk_safeobj_lock(ctx); - again: - - tsk_list_foreach(item, ctx->cache) - { - // FIXME: ttl should be from RR::ttl - tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data; - if ((entry->epoch + ctx->cache_ttl) < tsk_time_epoch()){ - tsk_list_remove_item_by_data(ctx->cache, entry); - goto again; /* Do not delete data while looping */ - } - } - - tsk_safeobj_unlock(ctx); - - return 0; - } - return -1; + if (ctx) { + tsk_list_item_t *item; + tsk_safeobj_lock(ctx); +again: + + tsk_list_foreach(item, ctx->cache) { + // FIXME: ttl should be from RR::ttl + tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data; + if ((entry->epoch + ctx->cache_ttl) < tsk_time_epoch()) { + tsk_list_remove_item_by_data(ctx->cache, entry); + goto again; /* Do not delete data while looping */ + } + } + + tsk_safeobj_unlock(ctx); + + return 0; + } + return -1; } // add an entry to the cache int tnet_dns_cache_entry_add(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tnet_dns_response_t* response) { - int ret = -1; - - if (ctx) - { - tnet_dns_cache_entry_t *entry; - - tsk_safeobj_lock(ctx); - - entry = 0; - - /* Retrieve from cache */ - entry = (tnet_dns_cache_entry_t*)tnet_dns_cache_entry_get(ctx, qname, qclass, qtype); - - if (entry){ - /* UPDATE */ - TSK_OBJECT_SAFE_FREE(entry->response); - entry->response = tsk_object_ref(response); - entry->epoch = tsk_time_epoch(); - ret = 0; - goto done; - } - else{ - /* CREATE */ - entry = tnet_dns_cache_entry_create(qname, qclass, qtype, response); - if (entry){ - tsk_list_push_back_data(ctx->cache, (void**)&entry); - ret = 0; - goto done; - } - else{ - ret = -2; - goto done; - } - } - done: - tsk_safeobj_unlock(ctx); - } - return ret; + int ret = -1; + + if (ctx) { + tnet_dns_cache_entry_t *entry; + + tsk_safeobj_lock(ctx); + + entry = 0; + + /* Retrieve from cache */ + entry = (tnet_dns_cache_entry_t*)tnet_dns_cache_entry_get(ctx, qname, qclass, qtype); + + if (entry) { + /* UPDATE */ + TSK_OBJECT_SAFE_FREE(entry->response); + entry->response = tsk_object_ref(response); + entry->epoch = tsk_time_epoch(); + ret = 0; + goto done; + } + else { + /* CREATE */ + entry = tnet_dns_cache_entry_create(qname, qclass, qtype, response); + if (entry) { + tsk_list_push_back_data(ctx->cache, (void**)&entry); + ret = 0; + goto done; + } + else { + ret = -2; + goto done; + } + } +done: + tsk_safeobj_unlock(ctx); + } + return ret; } // get an entry from the cache const tnet_dns_cache_entry_t* tnet_dns_cache_entry_get(tnet_dns_ctx_t *ctx, const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype) { - tnet_dns_cache_entry_t *ret = tsk_null; - if (ctx) - { - tsk_list_item_t *item; + tnet_dns_cache_entry_t *ret = tsk_null; + if (ctx) { + tsk_list_item_t *item; - tsk_safeobj_lock(ctx); + tsk_safeobj_lock(ctx); - tsk_list_foreach(item, ctx->cache){ - tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data; - if (entry->qtype == qtype && entry->qclass == qclass && tsk_strequals(entry->qname, qname)){ - ret = entry; - break; - } - } + tsk_list_foreach(item, ctx->cache) { + tnet_dns_cache_entry_t *entry = (tnet_dns_cache_entry_t*)item->data; + if (entry->qtype == qtype && entry->qclass == qclass && tsk_strequals(entry->qname, qname)) { + ret = entry; + break; + } + } - tsk_safeobj_unlock(ctx); - } + tsk_safeobj_unlock(ctx); + } - return ret; + return ret; } @@ -854,25 +848,25 @@ const tnet_dns_cache_entry_t* tnet_dns_cache_entry_get(tnet_dns_ctx_t *ctx, cons */ int tnet_dns_add_server(tnet_dns_ctx_t *ctx, const char* host) { - tnet_address_t *address; + tnet_address_t *address; - if (!ctx || !host){ - return -1; - } + if (!ctx || !host) { + return -1; + } - if (!ctx->servers){ - ctx->servers = tsk_list_create(); - } + if (!ctx->servers) { + ctx->servers = tsk_list_create(); + } - if ((address = tnet_address_create(host))){ - address->family = tnet_get_family(host, TNET_DNS_SERVER_PORT_DEFAULT); - address->dnsserver = 1; - tsk_list_push_ascending_data(ctx->servers, (void**)&address); + if ((address = tnet_address_create(host))) { + address->family = tnet_get_family(host, TNET_DNS_SERVER_PORT_DEFAULT); + address->dnsserver = 1; + tsk_list_push_ascending_data(ctx->servers, (void**)&address); - return 0; - } + return 0; + } - return -2; + return -2; } //================================================================================================= @@ -880,33 +874,32 @@ int tnet_dns_add_server(tnet_dns_ctx_t *ctx, const char* host) // static tsk_object_t* tnet_dns_cache_entry_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_cache_entry_t *entry = self; - if (entry){ - entry->qname = tsk_strdup(va_arg(*app, const char*)); - entry->qclass = va_arg(*app, tnet_dns_qclass_t); - entry->qtype = va_arg(*app, tnet_dns_qtype_t); - entry->response = tsk_object_ref(va_arg(*app, tnet_dns_response_t*)); - - entry->epoch = tsk_time_epoch(); - } - return self; + tnet_dns_cache_entry_t *entry = self; + if (entry) { + entry->qname = tsk_strdup(va_arg(*app, const char*)); + entry->qclass = va_arg(*app, tnet_dns_qclass_t); + entry->qtype = va_arg(*app, tnet_dns_qtype_t); + entry->response = tsk_object_ref(va_arg(*app, tnet_dns_response_t*)); + + entry->epoch = tsk_time_epoch(); + } + return self; } static tsk_object_t* tnet_dns_cache_entry_dtor(tsk_object_t * self) { - tnet_dns_cache_entry_t *entry = self; - if (entry){ - TSK_OBJECT_SAFE_FREE(entry->response); - } - return self; + tnet_dns_cache_entry_t *entry = self; + if (entry) { + TSK_OBJECT_SAFE_FREE(entry->response); + } + return self; } -static const tsk_object_def_t tnet_dns_cache_entry_def_s = -{ - sizeof(tnet_dns_cache_entry_t), - tnet_dns_cache_entry_ctor, - tnet_dns_cache_entry_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_cache_entry_def_s = { + sizeof(tnet_dns_cache_entry_t), + tnet_dns_cache_entry_ctor, + tnet_dns_cache_entry_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_cache_entry_def_t = &tnet_dns_cache_entry_def_s; @@ -916,52 +909,51 @@ const tsk_object_def_t *tnet_dns_cache_entry_def_t = &tnet_dns_cache_entry_def_s // static tsk_object_t* tnet_dns_ctx_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_ctx_t *ctx = self; - if (ctx){ - ctx->timeout = TNET_DNS_TIMEOUT_DEFAULT; - ctx->recursion = tsk_true; - ctx->edns0 = tsk_true; - ctx->caching = tsk_false; + tnet_dns_ctx_t *ctx = self; + if (ctx) { + ctx->timeout = TNET_DNS_TIMEOUT_DEFAULT; + ctx->recursion = tsk_true; + ctx->edns0 = tsk_true; + ctx->caching = tsk_false; - ctx->cache_ttl = TNET_DNS_CACHE_TTL; + ctx->cache_ttl = TNET_DNS_CACHE_TTL; - ctx->server_port = TNET_DNS_SERVER_PORT_DEFAULT; + ctx->server_port = TNET_DNS_SERVER_PORT_DEFAULT; - /* Gets all dns servers. */ - ctx->servers = tnet_get_addresses_all_dnsservers(); - /* Creates empty cache. */ - ctx->cache = tsk_list_create(); + /* Gets all dns servers. */ + ctx->servers = tnet_get_addresses_all_dnsservers(); + /* Creates empty cache. */ + ctx->cache = tsk_list_create(); #if HAVE_DNS_H - ctx->resolv_handle = dns_open(NULL); + ctx->resolv_handle = dns_open(NULL); #endif - tsk_safeobj_init(ctx); - } - return self; - } + tsk_safeobj_init(ctx); + } + return self; +} static tsk_object_t* tnet_dns_ctx_dtor(tsk_object_t * self) { - tnet_dns_ctx_t *ctx = self; - if (ctx){ - tsk_safeobj_deinit(ctx); + tnet_dns_ctx_t *ctx = self; + if (ctx) { + tsk_safeobj_deinit(ctx); - TSK_OBJECT_SAFE_FREE(ctx->servers); - TSK_OBJECT_SAFE_FREE(ctx->cache); + TSK_OBJECT_SAFE_FREE(ctx->servers); + TSK_OBJECT_SAFE_FREE(ctx->cache); #if HAVE_DNS_H - dns_free(ctx->resolv_handle); + dns_free(ctx->resolv_handle); #endif - } - return self; + } + return self; } -static const tsk_object_def_t tnet_dns_ctx_def_s = -{ - sizeof(tnet_dns_ctx_t), - tnet_dns_ctx_ctor, - tnet_dns_ctx_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_ctx_def_s = { + sizeof(tnet_dns_ctx_t), + tnet_dns_ctx_ctor, + tnet_dns_ctx_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_ctx_def_t = &tnet_dns_ctx_def_s; diff --git a/tinyNET/src/dns/tnet_dns.h b/tinyNET/src/dns/tnet_dns.h index d4c2e6d..6d17356 100755 --- a/tinyNET/src/dns/tnet_dns.h +++ b/tinyNET/src/dns/tnet_dns.h @@ -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,12 +49,12 @@ TNET_BEGIN_DECLS #define TNET_DNS_CACHE_TTL (15000 * 1000) /**@ingroup tnet_dns_group -* Default timeout (in milliseconds) value for DNS queries. +* Default timeout (in milliseconds) value for DNS queries. */ #define TNET_DNS_TIMEOUT_DEFAULT 5000 //(5 seconds) /**@ingroup tnet_dns_group -* Maximum supported Dgram size to advertise using EDNS0. +* Maximum supported Dgram size to advertise using EDNS0. */ #define TNET_DNS_DGRAM_SIZE_DEFAULT 4096 @@ -64,17 +64,16 @@ TNET_BEGIN_DECLS /**DNS cache entry. */ -typedef struct tnet_dns_cache_entry_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_dns_cache_entry_s { + TSK_DECLARE_OBJECT; - char* qname; - tnet_dns_qclass_t qclass; - tnet_dns_qtype_t qtype; + char* qname; + tnet_dns_qclass_t qclass; + tnet_dns_qtype_t qtype; - uint64_t epoch; + uint64_t epoch; - tnet_dns_response_t *response; + tnet_dns_response_t *response; } tnet_dns_cache_entry_t; typedef tsk_list_t tnet_dns_cache_entries_L_t; @@ -82,23 +81,22 @@ typedef tnet_dns_cache_entries_L_t tnet_dns_cache_t; /**DNS context. */ -typedef struct tnet_dns_ctx_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_dns_ctx_s { + TSK_DECLARE_OBJECT; + + uint64_t timeout; /**< In milliseconds. Default: @ref TNET_DNS_TIMEOUT_DEFAULT. */ + tsk_bool_t recursion; /**< Indicates whether to direct the name server to pursue the query recursively. Default: enabled.*/ + tsk_bool_t edns0; /**< Indicates whether to enable EDNS0 (Extension Mechanisms for DNS) or not. This option will allow you to send DNS packet larger than 512 bytes. Default: enabled. */ + tsk_bool_t caching; /**< Indicates whether to enable the DNS cache or not. Default: no. */ - uint64_t timeout; /**< In milliseconds. Default: @ref TNET_DNS_TIMEOUT_DEFAULT. */ - tsk_bool_t recursion; /**< Indicates whether to direct the name server to pursue the query recursively. Default: enabled.*/ - tsk_bool_t edns0; /**< Indicates whether to enable EDNS0 (Extension Mechanisms for DNS) or not. This option will allow you to send DNS packet larger than 512 bytes. Default: enabled. */ - tsk_bool_t caching; /**< Indicates whether to enable the DNS cache or not. Default: no. */ + int32_t cache_ttl; - int32_t cache_ttl; + tnet_port_t server_port; /**< Default port (@a TNET_DNS_SERVER_PORT_DEFAULT)) */ - tnet_port_t server_port; /**< Default port (@a TNET_DNS_SERVER_PORT_DEFAULT)) */ + tnet_dns_cache_t *cache; + tnet_addresses_L_t *servers; - tnet_dns_cache_t *cache; - tnet_addresses_L_t *servers; - - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; #if HAVE_DNS_H dns_handle_t resolv_handle; diff --git a/tinyNET/src/dns/tnet_dns_a.c b/tinyNET/src/dns/tnet_dns_a.c index 27a3603..b08d056 100755 --- a/tinyNET/src/dns/tnet_dns_a.c +++ b/tinyNET/src/dns/tnet_dns_a.c @@ -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. * @@ -39,7 +39,7 @@ */ tnet_dns_a_t* tnet_dns_a_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_a_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_a_def_t, name, qclass, ttl, rdlength, data, offset); } @@ -48,55 +48,54 @@ tnet_dns_a_t* tnet_dns_a_create(const char* name, tnet_dns_qclass_t qclass, uint // static tsk_object_t* tnet_dns_a_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_a_t *a = self; - if(a){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_a_t *a = self; + if(a) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - const uint8_t* rddata = (((uint8_t*)data) + offset); - //const uint8_t* dataEnd = (rddata + rdlength); + const uint8_t* rddata = (((uint8_t*)data) + offset); + //const uint8_t* dataEnd = (rddata + rdlength); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(a), qtype_a, qclass); - TNET_DNS_RR(a)->name = tsk_strdup(name); - TNET_DNS_RR(a)->rdlength = rdlength; - TNET_DNS_RR(a)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(a), qtype_a, qclass); + TNET_DNS_RR(a)->name = tsk_strdup(name); + TNET_DNS_RR(a)->rdlength = rdlength; + TNET_DNS_RR(a)->ttl = ttl; - if(rddata && rdlength && (rdlength == 4/* 32bits */)){ - // ==> DESERIALIZATION - /* ADDRESS */ - uint32_t address = (uint32_t)tnet_htonl_2(rddata); - tsk_sprintf(&(a->address), "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); - } - else{ - TSK_DEBUG_ERROR("Invalid IPv4 address."); - } + if(rddata && rdlength && (rdlength == 4/* 32bits */)) { + // ==> DESERIALIZATION + /* ADDRESS */ + uint32_t address = (uint32_t)tnet_htonl_2(rddata); + tsk_sprintf(&(a->address), "%u.%u.%u.%u", (address>>24)&0xFF, (address>>16)&0xFF, (address>>8)&0xFF, (address>>0)&0xFF); + } + else { + TSK_DEBUG_ERROR("Invalid IPv4 address."); + } - } - return self; + } + return self; } -static tsk_object_t* tnet_dns_a_dtor(tsk_object_t * self) -{ - tnet_dns_a_t *a = self; - if(a){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(a)); +static tsk_object_t* tnet_dns_a_dtor(tsk_object_t * self) +{ + tnet_dns_a_t *a = self; + if(a) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(a)); - TSK_FREE(a->address); - } - return self; + TSK_FREE(a->address); + } + return self; } -static const tsk_object_def_t tnet_dns_a_def_s = -{ - sizeof(tnet_dns_a_t), - tnet_dns_a_ctor, - tnet_dns_a_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_a_def_s = { + sizeof(tnet_dns_a_t), + tnet_dns_a_ctor, + tnet_dns_a_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_a_def_t = &tnet_dns_a_def_s; diff --git a/tinyNET/src/dns/tnet_dns_a.h b/tinyNET/src/dns/tnet_dns_a.h index e5db962..066fe3b 100755 --- a/tinyNET/src/dns/tnet_dns_a.h +++ b/tinyNET/src/dns/tnet_dns_a.h @@ -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. * @@ -38,16 +38,15 @@ TNET_BEGIN_DECLS /**DNS A Resource Record. */ -typedef struct tnet_dns_a_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_a_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.4.1. A RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.4.1. A RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ADDRESS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* address; + */ + char* address; } tnet_dns_a_t; diff --git a/tinyNET/src/dns/tnet_dns_aaaa.c b/tinyNET/src/dns/tnet_dns_aaaa.c index 4855827..90cae5b 100755 --- a/tinyNET/src/dns/tnet_dns_aaaa.c +++ b/tinyNET/src/dns/tnet_dns_aaaa.c @@ -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. * @@ -40,7 +40,7 @@ tnet_dns_aaaa_t* tnet_dns_aaaa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_aaaa_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_aaaa_def_t, name, qclass, ttl, rdlength, data, offset); } @@ -49,56 +49,55 @@ tnet_dns_aaaa_t* tnet_dns_aaaa_create(const char* name, tnet_dns_qclass_t qclass // static tsk_object_t* tnet_dns_aaaa_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_aaaa_t *aaaa = self; - if(aaaa){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_aaaa_t *aaaa = self; + if(aaaa) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - const uint8_t* rddata = (((uint8_t*)data) + offset); - //const uint8_t* dataEnd = (rddata + rdlength); + const uint8_t* rddata = (((uint8_t*)data) + offset); + //const uint8_t* dataEnd = (rddata + rdlength); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(aaaa), qtype_aaaa, qclass); - TNET_DNS_RR(aaaa)->name = tsk_strdup(name); - TNET_DNS_RR(aaaa)->rdlength = rdlength; - TNET_DNS_RR(aaaa)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(aaaa), qtype_aaaa, qclass); + TNET_DNS_RR(aaaa)->name = tsk_strdup(name); + TNET_DNS_RR(aaaa)->rdlength = rdlength; + TNET_DNS_RR(aaaa)->ttl = ttl; - if(rddata && rdlength && (rdlength == 16/* 128bits */)){ - // ==> DESERIALIZATION - /* ADDRESS */ - tsk_sprintf(&(aaaa->address), "%x:%x:%x:%x:%x:%x:%x:%x", - tnet_ntohs_2(&rddata[0]), tnet_ntohs_2(&rddata[2]), tnet_ntohs_2(&rddata[4]), tnet_ntohs_2(&rddata[6]), - tnet_ntohs_2(&rddata[8]), tnet_ntohs_2(&rddata[10]), tnet_ntohs_2(&rddata[12]), tnet_ntohs_2(&rddata[14])); - } - else{ - TSK_DEBUG_ERROR("Invalid IPv6 address."); - } + if(rddata && rdlength && (rdlength == 16/* 128bits */)) { + // ==> DESERIALIZATION + /* ADDRESS */ + tsk_sprintf(&(aaaa->address), "%x:%x:%x:%x:%x:%x:%x:%x", + tnet_ntohs_2(&rddata[0]), tnet_ntohs_2(&rddata[2]), tnet_ntohs_2(&rddata[4]), tnet_ntohs_2(&rddata[6]), + tnet_ntohs_2(&rddata[8]), tnet_ntohs_2(&rddata[10]), tnet_ntohs_2(&rddata[12]), tnet_ntohs_2(&rddata[14])); + } + else { + TSK_DEBUG_ERROR("Invalid IPv6 address."); + } - } - return self; + } + return self; } -static tsk_object_t* tnet_dns_aaaa_dtor(tsk_object_t * self) -{ - tnet_dns_aaaa_t *aaaa = self; - if(aaaa){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(aaaa)); +static tsk_object_t* tnet_dns_aaaa_dtor(tsk_object_t * self) +{ + tnet_dns_aaaa_t *aaaa = self; + if(aaaa) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(aaaa)); - TSK_FREE(aaaa->address); - } - return self; + TSK_FREE(aaaa->address); + } + return self; } -static const tsk_object_def_t tnet_dns_aaaa_def_s = -{ - sizeof(tnet_dns_aaaa_t), - tnet_dns_aaaa_ctor, - tnet_dns_aaaa_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_aaaa_def_s = { + sizeof(tnet_dns_aaaa_t), + tnet_dns_aaaa_ctor, + tnet_dns_aaaa_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_aaaa_def_t = &tnet_dns_aaaa_def_s; diff --git a/tinyNET/src/dns/tnet_dns_aaaa.h b/tinyNET/src/dns/tnet_dns_aaaa.h index 759adf1..7fdd018 100755 --- a/tinyNET/src/dns/tnet_dns_aaaa.h +++ b/tinyNET/src/dns/tnet_dns_aaaa.h @@ -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. * @@ -38,13 +38,12 @@ TNET_BEGIN_DECLS /**DNS AAAA Resource Record. */ -typedef struct tnet_dns_aaaa_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_aaaa_s { + TNET_DECLARE_DNS_RR; - /* RFC 3596 - - */ - char* address; + /* RFC 3596 - + */ + char* address; } tnet_dns_aaaa_t; diff --git a/tinyNET/src/dns/tnet_dns_cname.c b/tinyNET/src/dns/tnet_dns_cname.c index 8bec3e8..e64d515 100755 --- a/tinyNET/src/dns/tnet_dns_cname.c +++ b/tinyNET/src/dns/tnet_dns_cname.c @@ -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. * @@ -38,7 +38,7 @@ tnet_dns_cname_t* tnet_dns_cname_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_cname_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_cname_def_t, name, qclass, ttl, rdlength, data, offset); } @@ -47,47 +47,46 @@ tnet_dns_cname_t* tnet_dns_cname_create(const char* name, tnet_dns_qclass_t qcla // static tsk_object_t* tnet_dns_cname_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_cname_t *cname = self; - if(cname){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_cname_t *cname = self; + if(cname) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(cname), qtype_cname, qclass); - TNET_DNS_RR(cname)->name = tsk_strdup(name); - TNET_DNS_RR(cname)->rdlength = rdlength; - TNET_DNS_RR(cname)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(cname), qtype_cname, qclass); + TNET_DNS_RR(cname)->name = tsk_strdup(name); + TNET_DNS_RR(cname)->rdlength = rdlength; + TNET_DNS_RR(cname)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* CNAME */ - tnet_dns_rr_qname_deserialize(data, &(cname->cname), &offset); - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* CNAME */ + tnet_dns_rr_qname_deserialize(data, &(cname->cname), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_cname_dtor(tsk_object_t * self) -{ - tnet_dns_cname_t *cname = self; - if(cname){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(cname)); +static tsk_object_t* tnet_dns_cname_dtor(tsk_object_t * self) +{ + tnet_dns_cname_t *cname = self; + if(cname) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(cname)); - TSK_FREE(cname->cname); - } - return self; + TSK_FREE(cname->cname); + } + return self; } -static const tsk_object_def_t tnet_dns_cname_def_s = -{ - sizeof(tnet_dns_cname_t), - tnet_dns_cname_ctor, - tnet_dns_cname_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_cname_def_s = { + sizeof(tnet_dns_cname_t), + tnet_dns_cname_ctor, + tnet_dns_cname_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_cname_def_t = &tnet_dns_cname_def_s; diff --git a/tinyNET/src/dns/tnet_dns_cname.h b/tinyNET/src/dns/tnet_dns_cname.h index f97087d..8d8b658 100755 --- a/tinyNET/src/dns/tnet_dns_cname.h +++ b/tinyNET/src/dns/tnet_dns_cname.h @@ -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. * @@ -39,17 +39,16 @@ TNET_BEGIN_DECLS /** DNS CNAME Resource Record */ -typedef struct tnet_dns_cname_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_cname_s { + TNET_DECLARE_DNS_RR; - /* 3.3.1. CNAME RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* 3.3.1. CNAME RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / CNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* cname; + */ + char* cname; } tnet_dns_cname_t; diff --git a/tinyNET/src/dns/tnet_dns_message.c b/tinyNET/src/dns/tnet_dns_message.c index 594f499..4c1ef76 100755 --- a/tinyNET/src/dns/tnet_dns_message.c +++ b/tinyNET/src/dns/tnet_dns_message.c @@ -38,7 +38,7 @@ */ tnet_dns_message_t* tnet_dns_message_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype, tsk_bool_t isquery) { - return tsk_object_new(tnet_dns_message_def_t, qname, qclass, qtype, isquery); + return tsk_object_new(tnet_dns_message_def_t, qname, qclass, qtype, isquery); } /**@ingroup tnet_dns_group @@ -47,7 +47,7 @@ tnet_dns_message_t* tnet_dns_message_create(const char* qname, tnet_dns_qclass_t */ tnet_dns_message_t* tnet_dns_message_create_null() { - return tnet_dns_message_create(tsk_null, qclass_any, qtype_any, tsk_false); + return tnet_dns_message_create(tsk_null, qclass_any, qtype_any, tsk_false); } /**@ingroup tnet_dns_group @@ -56,7 +56,7 @@ tnet_dns_message_t* tnet_dns_message_create_null() */ tnet_dns_response_t* tnet_dns_response_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype) { - return tnet_dns_message_create(qname, qclass, qtype, tsk_false); + return tnet_dns_message_create(qname, qclass, qtype, tsk_false); } /**@ingroup tnet_dns_group @@ -65,7 +65,7 @@ tnet_dns_response_t* tnet_dns_response_create(const char* qname, tnet_dns_qclass */ tnet_dns_query_t* tnet_dns_query_create(const char* qname, tnet_dns_qclass_t qclass, tnet_dns_qtype_t qtype) { - return tnet_dns_message_create(qname, qclass, qtype, tsk_true); + return tnet_dns_message_create(qname, qclass, qtype, tsk_true); } /**@ingroup tnet_dns_group @@ -76,113 +76,109 @@ tnet_dns_query_t* tnet_dns_query_create(const char* qname, tnet_dns_qclass_t qcl */ tsk_buffer_t* tnet_dns_message_serialize(const tnet_dns_message_t *message) { - tsk_buffer_t* output = tsk_null; - uint16_t _2bytes; - tsk_list_item_t *item; - - /* Check message validity */ - if (!message){ - goto bail; - } - - /* Creates empty buffer */ - output = tsk_buffer_create_null(); - - /* ============================== - * HEADER - */ - //tsk_buffer_append(output, &(message->Header), sizeof(message->Header)); - - /* ID */ - _2bytes = tnet_ntohs(message->Header.ID); - tsk_buffer_append(output, &(_2bytes), 2); - /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */ - { - uint16_t temp, _2bytes = 0; - - temp = message->Header.QR, temp <<= 15; - _2bytes |= temp; - - temp = message->Header.OPCODE, temp <<= 11; - _2bytes |= temp; - - temp = message->Header.AA, temp <<= 10; - _2bytes |= temp; - - temp = message->Header.TC, temp <<= 9; - _2bytes |= temp; - - temp = message->Header.RD, temp <<= 8; - _2bytes |= temp; - - temp = message->Header.RA, temp <<= 7; - _2bytes |= temp; - - temp = message->Header.Z, temp <<= 4; - _2bytes |= temp; - - temp = message->Header.RCODE, temp <<= 4; - _2bytes |= temp; - - _2bytes = tnet_ntohs(_2bytes); - tsk_buffer_append(output, &(_2bytes), 2); - } - /* QDCOUNT */ - _2bytes = tnet_ntohs(message->Header.QDCOUNT); - tsk_buffer_append(output, &(_2bytes), 2); - /* ANCOUNT */ - _2bytes = tnet_ntohs(message->Header.ANCOUNT); - tsk_buffer_append(output, &(_2bytes), 2); - /* NSCOUNT */ - _2bytes = tnet_ntohs(message->Header.NSCOUNT); - tsk_buffer_append(output, &(_2bytes), 2); - /* ARCOUNT */ - _2bytes = tnet_ntohs(message->Header.ARCOUNT); - tsk_buffer_append(output, &(_2bytes), 2); - - - /* ============================== - * QUESTION - */ - if (TNET_DNS_MESSAGE_IS_QUERY(message)) - { - /* QNAME */ - tnet_dns_rr_qname_serialize(message->Question.QNAME, output); - /* QTYPE */ - _2bytes = tnet_ntohs(message->Question.QTYPE); - tsk_buffer_append(output, &(_2bytes), 2); - /* QCLASS */ - _2bytes = tnet_ntohs(message->Question.QCLASS); - tsk_buffer_append(output, &(_2bytes), 2); - } - - /* ============================== - * ANSWERS - */ - tsk_list_foreach(item, message->Answers) - { - tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); - } - - /* ============================== - * AUTHORITIES - */ - tsk_list_foreach(item, message->Authorities) - { - tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); - } - - /* ============================== - * ADDITIONALS - */ - tsk_list_foreach(item, message->Additionals) - { - tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); - } + tsk_buffer_t* output = tsk_null; + uint16_t _2bytes; + tsk_list_item_t *item; + + /* Check message validity */ + if (!message) { + goto bail; + } + + /* Creates empty buffer */ + output = tsk_buffer_create_null(); + + /* ============================== + * HEADER + */ + //tsk_buffer_append(output, &(message->Header), sizeof(message->Header)); + + /* ID */ + _2bytes = tnet_ntohs(message->Header.ID); + tsk_buffer_append(output, &(_2bytes), 2); + /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */ + { + uint16_t temp, _2bytes = 0; + + temp = message->Header.QR, temp <<= 15; + _2bytes |= temp; + + temp = message->Header.OPCODE, temp <<= 11; + _2bytes |= temp; + + temp = message->Header.AA, temp <<= 10; + _2bytes |= temp; + + temp = message->Header.TC, temp <<= 9; + _2bytes |= temp; + + temp = message->Header.RD, temp <<= 8; + _2bytes |= temp; + + temp = message->Header.RA, temp <<= 7; + _2bytes |= temp; + + temp = message->Header.Z, temp <<= 4; + _2bytes |= temp; + + temp = message->Header.RCODE, temp <<= 4; + _2bytes |= temp; + + _2bytes = tnet_ntohs(_2bytes); + tsk_buffer_append(output, &(_2bytes), 2); + } + /* QDCOUNT */ + _2bytes = tnet_ntohs(message->Header.QDCOUNT); + tsk_buffer_append(output, &(_2bytes), 2); + /* ANCOUNT */ + _2bytes = tnet_ntohs(message->Header.ANCOUNT); + tsk_buffer_append(output, &(_2bytes), 2); + /* NSCOUNT */ + _2bytes = tnet_ntohs(message->Header.NSCOUNT); + tsk_buffer_append(output, &(_2bytes), 2); + /* ARCOUNT */ + _2bytes = tnet_ntohs(message->Header.ARCOUNT); + tsk_buffer_append(output, &(_2bytes), 2); + + + /* ============================== + * QUESTION + */ + if (TNET_DNS_MESSAGE_IS_QUERY(message)) { + /* QNAME */ + tnet_dns_rr_qname_serialize(message->Question.QNAME, output); + /* QTYPE */ + _2bytes = tnet_ntohs(message->Question.QTYPE); + tsk_buffer_append(output, &(_2bytes), 2); + /* QCLASS */ + _2bytes = tnet_ntohs(message->Question.QCLASS); + tsk_buffer_append(output, &(_2bytes), 2); + } + + /* ============================== + * ANSWERS + */ + tsk_list_foreach(item, message->Answers) { + tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); + } + + /* ============================== + * AUTHORITIES + */ + tsk_list_foreach(item, message->Authorities) { + tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); + } + + /* ============================== + * ADDITIONALS + */ + tsk_list_foreach(item, message->Additionals) { + tnet_dns_rr_serialize((tnet_dns_rr_t *)item->data, output); + } bail: - return output; + return output; } /**@ingroup tnet_dns_group @@ -194,112 +190,108 @@ bail: */ tnet_dns_message_t* tnet_dns_message_deserialize(const uint8_t *data, tsk_size_t size) { - tnet_dns_message_t *message = 0; - uint8_t *dataPtr, *dataEnd, *dataStart; - uint16_t i; - tsk_size_t offset = 0; - - if (!data || !size){ - goto bail; - } - - dataPtr = (uint8_t*)data; - dataStart = dataPtr; - dataEnd = (dataStart + size); - - message = tnet_dns_message_create_null(); - - /* === HEADER ===*/ - /* ID */ - message->Header.ID = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */ - { - uint16_t flags = tnet_ntohs_2(dataPtr); - - message->Header.QR = (flags >> 15); - message->Header.OPCODE = ((flags >> 11) & 0x000F); - message->Header.AA = ((flags >> 10) & 0x0001); - message->Header.TC = ((flags >> 9) & 0x0001); - message->Header.RD = ((flags >> 8) & 0x0001); - message->Header.RA = ((flags >> 7) & 0x0001); - message->Header.Z = ((flags >> 4) & 0x0007); - message->Header.RCODE = (flags & 0x000F); - - dataPtr += 2; - } - /* QDCOUNT */ - message->Header.QDCOUNT = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /* ANCOUNT */ - message->Header.ANCOUNT = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /* NSCOUNT */ - message->Header.NSCOUNT = tnet_ntohs_2(dataPtr); - dataPtr += 2; - /* ARCOUNT */ - message->Header.ARCOUNT = tnet_ntohs_2(dataPtr); - dataPtr += 2; - - /* === Queries ===*/ - offset = (tsk_size_t)(dataPtr - dataStart); - for (i = 0; i < message->Header.QDCOUNT; i++) - { - /* Do not need to parse queries in the response ==> silently ignore */ - char* name = 0; - tnet_dns_rr_qname_deserialize(dataStart, &name, &offset); /* QNAME */ - dataPtr += offset; - dataPtr += 4, offset += 4; /* QTYPE + QCLASS */ - TSK_FREE(name); - } - dataPtr = (dataStart + offset); /* TODO: remove ==> obly for debug tests */ - - /* === Answers ===*/ - offset = (tsk_size_t)(dataPtr - dataStart); - for (i = 0; i < message->Header.ANCOUNT; i++) - { - tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); - if (rr){ - if (!message->Answers){ - message->Answers = tsk_list_create(); - } - /* Push in descending order (useful for NAPTR and SRV records). */ - tsk_list_push_descending_data(message->Answers, (void**)&rr); - } - } - dataPtr = (dataStart + offset); - - /* === Authorities ===*/ - offset = (tsk_size_t)(dataPtr - dataStart); - for (i = 0; i < message->Header.NSCOUNT; i++) - { - tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); - if (rr){ - if (!message->Authorities){ - message->Authorities = tsk_list_create(); - } - tsk_list_push_back_data(message->Authorities, (void**)&rr); - } - } - dataPtr = (dataStart + offset); - - /* === Additionals ===*/ - offset = (tsk_size_t)(dataPtr - dataStart); - for (i = 0; i < message->Header.ARCOUNT; i++) - { - tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); - if (rr){ - if (!message->Additionals){ - message->Additionals = tsk_list_create(); - } - tsk_list_push_back_data(message->Additionals, (void**)&rr); - } - } - dataPtr = (dataStart + offset); + tnet_dns_message_t *message = 0; + uint8_t *dataPtr, *dataEnd, *dataStart; + uint16_t i; + tsk_size_t offset = 0; + + if (!data || !size) { + goto bail; + } + + dataPtr = (uint8_t*)data; + dataStart = dataPtr; + dataEnd = (dataStart + size); + + message = tnet_dns_message_create_null(); + + /* === HEADER ===*/ + /* ID */ + message->Header.ID = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /* |QR| Opcode |AA|TC|RD|RA| Z | RCODE | */ + { + uint16_t flags = tnet_ntohs_2(dataPtr); + + message->Header.QR = (flags >> 15); + message->Header.OPCODE = ((flags >> 11) & 0x000F); + message->Header.AA = ((flags >> 10) & 0x0001); + message->Header.TC = ((flags >> 9) & 0x0001); + message->Header.RD = ((flags >> 8) & 0x0001); + message->Header.RA = ((flags >> 7) & 0x0001); + message->Header.Z = ((flags >> 4) & 0x0007); + message->Header.RCODE = (flags & 0x000F); + + dataPtr += 2; + } + /* QDCOUNT */ + message->Header.QDCOUNT = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /* ANCOUNT */ + message->Header.ANCOUNT = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /* NSCOUNT */ + message->Header.NSCOUNT = tnet_ntohs_2(dataPtr); + dataPtr += 2; + /* ARCOUNT */ + message->Header.ARCOUNT = tnet_ntohs_2(dataPtr); + dataPtr += 2; + + /* === Queries ===*/ + offset = (tsk_size_t)(dataPtr - dataStart); + for (i = 0; i < message->Header.QDCOUNT; i++) { + /* Do not need to parse queries in the response ==> silently ignore */ + char* name = 0; + tnet_dns_rr_qname_deserialize(dataStart, &name, &offset); /* QNAME */ + dataPtr += offset; + dataPtr += 4, offset += 4; /* QTYPE + QCLASS */ + TSK_FREE(name); + } + dataPtr = (dataStart + offset); /* TODO: remove ==> obly for debug tests */ + + /* === Answers ===*/ + offset = (tsk_size_t)(dataPtr - dataStart); + for (i = 0; i < message->Header.ANCOUNT; i++) { + tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); + if (rr) { + if (!message->Answers) { + message->Answers = tsk_list_create(); + } + /* Push in descending order (useful for NAPTR and SRV records). */ + tsk_list_push_descending_data(message->Answers, (void**)&rr); + } + } + dataPtr = (dataStart + offset); + + /* === Authorities ===*/ + offset = (tsk_size_t)(dataPtr - dataStart); + for (i = 0; i < message->Header.NSCOUNT; i++) { + tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); + if (rr) { + if (!message->Authorities) { + message->Authorities = tsk_list_create(); + } + tsk_list_push_back_data(message->Authorities, (void**)&rr); + } + } + dataPtr = (dataStart + offset); + + /* === Additionals ===*/ + offset = (tsk_size_t)(dataPtr - dataStart); + for (i = 0; i < message->Header.ARCOUNT; i++) { + tnet_dns_rr_t* rr = tnet_dns_rr_deserialize(dataStart, (tsk_size_t)(dataEnd - dataPtr), &offset); + if (rr) { + if (!message->Additionals) { + message->Additionals = tsk_list_create(); + } + tsk_list_push_back_data(message->Additionals, (void**)&rr); + } + } + dataPtr = (dataStart + offset); bail: - return message; + return message; } //================================================================================================= @@ -307,53 +299,52 @@ bail: // static tsk_object_t* tnet_dns_message_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_message_t *message = self; - if (message){ - static uint16_t __dnsmessage_unique_id = 0; - - const char* qname = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - tnet_dns_qtype_t qtype = va_arg(*app, tnet_dns_qtype_t); - tsk_bool_t isquery = va_arg(*app, tsk_bool_t); - - /* Create random ID. */ - message->Header.ID = ++__dnsmessage_unique_id; - - /* QR field ==> query (0) - response (1) */ - message->Header.QR = isquery ? 0 : 1; - - if (isquery){ - /* QDCOUNT field ==> at least one question */ - message->Header.QDCOUNT = 1; - } - - if (qname){ - message->Question.QNAME = tsk_strdup(qname); - message->Question.QTYPE = qtype; - message->Question.QCLASS = qclass; - } - } - return self; + tnet_dns_message_t *message = self; + if (message) { + static uint16_t __dnsmessage_unique_id = 0; + + const char* qname = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + tnet_dns_qtype_t qtype = va_arg(*app, tnet_dns_qtype_t); + tsk_bool_t isquery = va_arg(*app, tsk_bool_t); + + /* Create random ID. */ + message->Header.ID = ++__dnsmessage_unique_id; + + /* QR field ==> query (0) - response (1) */ + message->Header.QR = isquery ? 0 : 1; + + if (isquery) { + /* QDCOUNT field ==> at least one question */ + message->Header.QDCOUNT = 1; + } + + if (qname) { + message->Question.QNAME = tsk_strdup(qname); + message->Question.QTYPE = qtype; + message->Question.QCLASS = qclass; + } + } + return self; } static tsk_object_t* tnet_dns_message_dtor(tsk_object_t * self) { - tnet_dns_message_t *message = self; - if (message){ - TSK_FREE(message->Question.QNAME); - - TSK_OBJECT_SAFE_FREE(message->Answers); - TSK_OBJECT_SAFE_FREE(message->Authorities); - TSK_OBJECT_SAFE_FREE(message->Additionals); - } - return self; + tnet_dns_message_t *message = self; + if (message) { + TSK_FREE(message->Question.QNAME); + + TSK_OBJECT_SAFE_FREE(message->Answers); + TSK_OBJECT_SAFE_FREE(message->Authorities); + TSK_OBJECT_SAFE_FREE(message->Additionals); + } + return self; } -static const tsk_object_def_t tnet_dns_message_def_s = -{ - sizeof(tnet_dns_message_t), - tnet_dns_message_ctor, - tnet_dns_message_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_message_def_s = { + sizeof(tnet_dns_message_t), + tnet_dns_message_ctor, + tnet_dns_message_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_message_def_t = &tnet_dns_message_def_s; diff --git a/tinyNET/src/dns/tnet_dns_message.h b/tinyNET/src/dns/tnet_dns_message.h index 8506ff8..bea318a 100755 --- a/tinyNET/src/dns/tnet_dns_message.h +++ b/tinyNET/src/dns/tnet_dns_message.h @@ -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. * @@ -68,22 +68,20 @@ TNET_BEGIN_DECLS /**Response codes as per RFC 1035 subclause 4.1.1. */ -typedef enum tnet_dns_rcode_e -{ - rcode_noerror = 0, - rcode_error_format = 1, - rcode_server_failure = 2, - rcode_error_name = 3, - rcode_notimplemented = 4, - rcode_refused = 5 +typedef enum tnet_dns_rcode_e { + rcode_noerror = 0, + rcode_error_format = 1, + rcode_server_failure = 2, + rcode_error_name = 3, + rcode_notimplemented = 4, + rcode_refused = 5 } tnet_dns_rcode_t; /**OPCODE defining the kind of query as per RFC 1035 subclause 4.1.1. */ -typedef enum tnet_dns_opcode_e -{ - opcode_query = 0, /**< 0 a standard query (QUERY) */ +typedef enum tnet_dns_opcode_e { + opcode_query = 0, /**< 0 a standard query (QUERY) */ opcode_iquery = 1, /**< 1 an inverse query (IQUERY) */ opcode_status = 2, /**< 2 a server status request (STATUS) */ } @@ -91,12 +89,11 @@ tnet_dns_opcode_t; /** DNS message as per RFC 1035 subclause 4. */ -typedef struct tnet_dns_message_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_dns_message_s { + TSK_DECLARE_OBJECT; - /* RFC 1035 - 4.1. Format - +---------------------+ + /* RFC 1035 - 4.1. Format + +---------------------+ | Header | +---------------------+ | Question | the question for the name server @@ -107,10 +104,10 @@ typedef struct tnet_dns_message_s +---------------------+ | Additional | RRs holding additional information +---------------------+ - */ + */ - /* RFC 1035 - 4.1.1. Header section format - 1 1 1 1 1 1 + /* RFC 1035 - 4.1.1. Header section format + 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | @@ -125,27 +122,26 @@ typedef struct tnet_dns_message_s +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - struct - { - uint16_t ID; - unsigned QR:1; - unsigned OPCODE:4; /* see @ref tnet_dns_opcode_t */ - unsigned AA:1; - unsigned TC:1; - unsigned RD:1; - unsigned RA:1; - unsigned Z:3; - unsigned RCODE:4; /* see @ref tnet_dns_rcode_t */ - uint16_t QDCOUNT; - uint16_t ANCOUNT; - uint16_t NSCOUNT; - uint16_t ARCOUNT; - } - Header; - - /* RFc 1035 - 4.1.2. Question section format - 1 1 1 1 1 1 + */ + struct { + uint16_t ID; + unsigned QR:1; + unsigned OPCODE:4; /* see @ref tnet_dns_opcode_t */ + unsigned AA:1; + unsigned TC:1; + unsigned RD:1; + unsigned RA:1; + unsigned Z:3; + unsigned RCODE:4; /* see @ref tnet_dns_rcode_t */ + uint16_t QDCOUNT; + uint16_t ANCOUNT; + uint16_t NSCOUNT; + uint16_t ARCOUNT; + } + Header; + + /* RFc 1035 - 4.1.2. Question section format + 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | @@ -156,34 +152,33 @@ typedef struct tnet_dns_message_s +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - struct - { - /** RFC 1035 - 4.1.2. Question section format - a domain name represented as a sequence of labels, where - each label consists of a length octet followed by that - number of octets. The domain name terminates with the - zero length octet for the null label of the root. Note - that this field may be an odd number of octets; no - padding is used.*/ - void* QNAME; - /** RFC 1035 - 4.1.2. Question section format - a two octet code which specifies the type of the query. - The values for this field include all codes valid for a - TYPE field, together with some more general codes which - can match more than one type of RR.*/ - tnet_dns_qtype_t QTYPE; - /* RFC 1035 - 4.1.2. Question section format - a two octet code that specifies the class of the query. - For example, the QCLASS field is IN for the Internet. - */ - tnet_dns_qclass_t QCLASS; - } - Question; - - tnet_dns_rrs_L_t *Answers; /**< Filtered answers by priority. */ - tnet_dns_rrs_L_t *Authorities; - tnet_dns_rrs_L_t *Additionals; + */ + struct { + /** RFC 1035 - 4.1.2. Question section format + a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used.*/ + void* QNAME; + /** RFC 1035 - 4.1.2. Question section format + a two octet code which specifies the type of the query. + The values for this field include all codes valid for a + TYPE field, together with some more general codes which + can match more than one type of RR.*/ + tnet_dns_qtype_t QTYPE; + /* RFC 1035 - 4.1.2. Question section format + a two octet code that specifies the class of the query. + For example, the QCLASS field is IN for the Internet. + */ + tnet_dns_qclass_t QCLASS; + } + Question; + + tnet_dns_rrs_L_t *Answers; /**< Filtered answers by priority. */ + tnet_dns_rrs_L_t *Authorities; + tnet_dns_rrs_L_t *Additionals; } tnet_dns_message_t; diff --git a/tinyNET/src/dns/tnet_dns_mx.c b/tinyNET/src/dns/tnet_dns_mx.c index edc59b1..5b8b801 100755 --- a/tinyNET/src/dns/tnet_dns_mx.c +++ b/tinyNET/src/dns/tnet_dns_mx.c @@ -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. * @@ -38,7 +38,7 @@ */ tnet_dns_mx_t* tnet_dns_mx_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_mx_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_mx_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -46,50 +46,49 @@ tnet_dns_mx_t* tnet_dns_mx_create(const char* name, tnet_dns_qclass_t qclass, ui // static tsk_object_t* tnet_dns_mx_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_mx_t *mx = self; - if(mx){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_mx_t *mx = self; + if(mx) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(mx), qtype_mx, qclass); - TNET_DNS_RR(mx)->name = tsk_strdup(name); - TNET_DNS_RR(mx)->rdlength = rdlength; - TNET_DNS_RR(mx)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(mx), qtype_mx, qclass); + TNET_DNS_RR(mx)->name = tsk_strdup(name); + TNET_DNS_RR(mx)->rdlength = rdlength; + TNET_DNS_RR(mx)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* PREFERENCE */ - mx->preference = tnet_ntohs_2(((uint8_t*)data) + offset); - offset += 2; - /* EXCHANGE */ - tnet_dns_rr_qname_deserialize(data, &(mx->exchange), &offset); - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* PREFERENCE */ + mx->preference = tnet_ntohs_2(((uint8_t*)data) + offset); + offset += 2; + /* EXCHANGE */ + tnet_dns_rr_qname_deserialize(data, &(mx->exchange), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_mx_dtor(tsk_object_t * self) -{ - tnet_dns_mx_t *mx = self; - if(mx){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(mx)); +static tsk_object_t* tnet_dns_mx_dtor(tsk_object_t * self) +{ + tnet_dns_mx_t *mx = self; + if(mx) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(mx)); - TSK_FREE(mx->exchange); - } - return self; + TSK_FREE(mx->exchange); + } + return self; } -static const tsk_object_def_t tnet_dns_mx_def_s = -{ - sizeof(tnet_dns_mx_t), - tnet_dns_mx_ctor, - tnet_dns_mx_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_mx_def_s = { + sizeof(tnet_dns_mx_t), + tnet_dns_mx_ctor, + tnet_dns_mx_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_mx_def_t = &tnet_dns_mx_def_s; diff --git a/tinyNET/src/dns/tnet_dns_mx.h b/tinyNET/src/dns/tnet_dns_mx.h index 98a00f1..6c0b999 100755 --- a/tinyNET/src/dns/tnet_dns_mx.h +++ b/tinyNET/src/dns/tnet_dns_mx.h @@ -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. * @@ -39,20 +39,19 @@ TNET_BEGIN_DECLS /** DNS MX Resource Record */ -typedef struct tnet_dns_mx_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_mx_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.3.9. MX RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.3.9. MX RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | PREFERENCE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / EXCHANGE / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - uint16_t preference; - char* exchange; + */ + uint16_t preference; + char* exchange; } tnet_dns_mx_t; diff --git a/tinyNET/src/dns/tnet_dns_naptr.c b/tinyNET/src/dns/tnet_dns_naptr.c index 79d7f70..c69f168 100755 --- a/tinyNET/src/dns/tnet_dns_naptr.c +++ b/tinyNET/src/dns/tnet_dns_naptr.c @@ -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. * @@ -39,7 +39,7 @@ */ tnet_dns_naptr_t* tnet_dns_naptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_naptr_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_naptr_def_t, name, qclass, ttl, rdlength, data, offset); } @@ -49,94 +49,93 @@ tnet_dns_naptr_t* tnet_dns_naptr_create(const char* name, tnet_dns_qclass_t qcla // static tsk_object_t* tnet_dns_naptr_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_naptr_t *naptr = self; - if(naptr){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); - - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(naptr), qtype_naptr, qclass); - TNET_DNS_RR(naptr)->name = tsk_strdup(name); - TNET_DNS_RR(naptr)->rdlength = rdlength; - TNET_DNS_RR(naptr)->ttl = ttl; - - if(rdlength){ - // ==> DESERIALIZATION - /* ORDER */ - naptr->order = tnet_ntohs_2(((uint8_t*)data) + offset); - offset += 2; - /* PREFERENCE */ - naptr->preference = tnet_ntohs_2(((uint8_t*)data) + offset); - offset += 2; - /* FLAGS */ - tnet_dns_rr_charstring_deserialize(data, &(naptr->flags), &offset); - /* SERVICES */ - tnet_dns_rr_charstring_deserialize(data, &(naptr->services), &offset); - /* REGEXP */ - tnet_dns_rr_charstring_deserialize(data, &(naptr->regexp), &offset); - /* REPLACEMENT */ - tnet_dns_rr_qname_deserialize(data, &(naptr->replacement), &offset); - } - } - return self; + tnet_dns_naptr_t *naptr = self; + if(naptr) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); + + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(naptr), qtype_naptr, qclass); + TNET_DNS_RR(naptr)->name = tsk_strdup(name); + TNET_DNS_RR(naptr)->rdlength = rdlength; + TNET_DNS_RR(naptr)->ttl = ttl; + + if(rdlength) { + // ==> DESERIALIZATION + /* ORDER */ + naptr->order = tnet_ntohs_2(((uint8_t*)data) + offset); + offset += 2; + /* PREFERENCE */ + naptr->preference = tnet_ntohs_2(((uint8_t*)data) + offset); + offset += 2; + /* FLAGS */ + tnet_dns_rr_charstring_deserialize(data, &(naptr->flags), &offset); + /* SERVICES */ + tnet_dns_rr_charstring_deserialize(data, &(naptr->services), &offset); + /* REGEXP */ + tnet_dns_rr_charstring_deserialize(data, &(naptr->regexp), &offset); + /* REPLACEMENT */ + tnet_dns_rr_qname_deserialize(data, &(naptr->replacement), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_naptr_dtor(tsk_object_t * self) -{ - tnet_dns_naptr_t *naptr = self; - if(naptr){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(naptr)); - - TSK_FREE(naptr->flags); - TSK_FREE(naptr->services); - TSK_FREE(naptr->regexp); - TSK_FREE(naptr->replacement); - } - return self; +static tsk_object_t* tnet_dns_naptr_dtor(tsk_object_t * self) +{ + tnet_dns_naptr_t *naptr = self; + if(naptr) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(naptr)); + + TSK_FREE(naptr->flags); + TSK_FREE(naptr->services); + TSK_FREE(naptr->regexp); + TSK_FREE(naptr->replacement); + } + return self; } static int tnet_dns_naptr_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2) -{ - const tnet_dns_rr_t* rr1 = obj1; - const tnet_dns_rr_t* rr2 = obj2; - - if(rr1 && rr2 && (rr1->qtype==qtype_naptr) && (rr2->qtype==qtype_naptr)){ - const tnet_dns_naptr_t* naptr1 = (tnet_dns_naptr_t*)rr1; - const tnet_dns_naptr_t* naptr2 = (tnet_dns_naptr_t*)rr2; - - /* Compare orders. */ - if(naptr1->order < naptr2->order){ /* Lowest order is tried first. */ - return 1; - } - else if(naptr1->order > naptr2->order){ - return -1; - } - - /* Compare preference */ - if(naptr1->order < naptr2->order){ /* Lowest preference is tried first. */ - return 1; - } - else if(naptr1->order > naptr2->order){ - return -1; - } - - return 0; - } - else{ - return -1; - } +{ + const tnet_dns_rr_t* rr1 = obj1; + const tnet_dns_rr_t* rr2 = obj2; + + if(rr1 && rr2 && (rr1->qtype==qtype_naptr) && (rr2->qtype==qtype_naptr)) { + const tnet_dns_naptr_t* naptr1 = (tnet_dns_naptr_t*)rr1; + const tnet_dns_naptr_t* naptr2 = (tnet_dns_naptr_t*)rr2; + + /* Compare orders. */ + if(naptr1->order < naptr2->order) { /* Lowest order is tried first. */ + return 1; + } + else if(naptr1->order > naptr2->order) { + return -1; + } + + /* Compare preference */ + if(naptr1->order < naptr2->order) { /* Lowest preference is tried first. */ + return 1; + } + else if(naptr1->order > naptr2->order) { + return -1; + } + + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_dns_naptr_def_s = -{ - sizeof(tnet_dns_naptr_t), - tnet_dns_naptr_ctor, - tnet_dns_naptr_dtor, - tnet_dns_naptr_cmp, +static const tsk_object_def_t tnet_dns_naptr_def_s = { + sizeof(tnet_dns_naptr_t), + tnet_dns_naptr_ctor, + tnet_dns_naptr_dtor, + tnet_dns_naptr_cmp, }; const tsk_object_def_t *tnet_dns_naptr_def_t = &tnet_dns_naptr_def_s; diff --git a/tinyNET/src/dns/tnet_dns_naptr.h b/tinyNET/src/dns/tnet_dns_naptr.h index b960809..f11b970 100755 --- a/tinyNET/src/dns/tnet_dns_naptr.h +++ b/tinyNET/src/dns/tnet_dns_naptr.h @@ -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. * @@ -37,13 +37,12 @@ TNET_BEGIN_DECLS /** DNS NAPTR Resource Record */ -typedef struct tnet_dns_naptr_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_naptr_s { + TNET_DECLARE_DNS_RR; - /* RFC 3403 - 4.1 Packet Format + /* RFC 3403 - 4.1 Packet Format - The packet format for the NAPTR record is as follows + The packet format for the NAPTR record is as follows 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -60,14 +59,14 @@ typedef struct tnet_dns_naptr_s / REPLACEMENT / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - <character-string> and <domain-name> as used here are defined in RFC 1035. - */ - uint16_t order; - uint16_t preference; - char* flags; - char* services; - char* regexp; - char* replacement; + <character-string> and <domain-name> as used here are defined in RFC 1035. + */ + uint16_t order; + uint16_t preference; + char* flags; + char* services; + char* regexp; + char* replacement; } tnet_dns_naptr_t; diff --git a/tinyNET/src/dns/tnet_dns_ns.c b/tinyNET/src/dns/tnet_dns_ns.c index a23426c..64d348b 100755 --- a/tinyNET/src/dns/tnet_dns_ns.c +++ b/tinyNET/src/dns/tnet_dns_ns.c @@ -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. * @@ -37,7 +37,7 @@ */ tnet_dns_ns_t* tnet_dns_ns_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_ns_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_ns_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -45,48 +45,47 @@ tnet_dns_ns_t* tnet_dns_ns_create(const char* name, tnet_dns_qclass_t qclass, ui // static tsk_object_t* tnet_dns_ns_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_ns_t *ns = self; - if(ns){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_ns_t *ns = self; + if(ns) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(ns), qtype_ns, qclass); - TNET_DNS_RR(ns)->name = tsk_strdup(name); - TNET_DNS_RR(ns)->rdlength = rdlength; - TNET_DNS_RR(ns)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(ns), qtype_ns, qclass); + TNET_DNS_RR(ns)->name = tsk_strdup(name); + TNET_DNS_RR(ns)->rdlength = rdlength; + TNET_DNS_RR(ns)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* NSDNAME */ - tnet_dns_rr_qname_deserialize(data, &(ns->nsdname), &offset); - } + if(rdlength) { + // ==> DESERIALIZATION + /* NSDNAME */ + tnet_dns_rr_qname_deserialize(data, &(ns->nsdname), &offset); + } - } - return self; + } + return self; } -static tsk_object_t* tnet_dns_ns_dtor(tsk_object_t * self) -{ - tnet_dns_ns_t *ns = self; - if(ns){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(ns)); +static tsk_object_t* tnet_dns_ns_dtor(tsk_object_t * self) +{ + tnet_dns_ns_t *ns = self; + if(ns) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(ns)); - TSK_FREE(ns->nsdname); - } - return self; + TSK_FREE(ns->nsdname); + } + return self; } -static const tsk_object_def_t tnet_dns_ns_def_s = -{ - sizeof(tnet_dns_ns_t), - tnet_dns_ns_ctor, - tnet_dns_ns_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_ns_def_s = { + sizeof(tnet_dns_ns_t), + tnet_dns_ns_ctor, + tnet_dns_ns_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_ns_def_t = &tnet_dns_ns_def_s; diff --git a/tinyNET/src/dns/tnet_dns_ns.h b/tinyNET/src/dns/tnet_dns_ns.h index 9a77f26..22b3bf0 100755 --- a/tinyNET/src/dns/tnet_dns_ns.h +++ b/tinyNET/src/dns/tnet_dns_ns.h @@ -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. * @@ -39,17 +39,16 @@ TNET_BEGIN_DECLS /** DNS NS Resource Record. */ -typedef struct tnet_dns_ns_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_ns_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.3.11. NS RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.3.11. NS RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / NSDNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* nsdname; + */ + char* nsdname; } tnet_dns_ns_t; diff --git a/tinyNET/src/dns/tnet_dns_opt.c b/tinyNET/src/dns/tnet_dns_opt.c index dab4fea..9ee2421 100755 --- a/tinyNET/src/dns/tnet_dns_opt.c +++ b/tinyNET/src/dns/tnet_dns_opt.c @@ -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. * @@ -34,7 +34,7 @@ */ tnet_dns_opt_t* tnet_dns_opt_create(tsk_size_t payload_size) { - return tsk_object_new(tnet_dns_opt_def_t, payload_size); + return tsk_object_new(tnet_dns_opt_def_t, payload_size); } @@ -50,42 +50,41 @@ tnet_dns_opt_t* tnet_dns_opt_create(tsk_size_t payload_size) // static tsk_object_t* tnet_dns_opt_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_opt_t *rr_opt = self; - if(rr_opt){ - uint16_t payload_size = (uint16_t)va_arg(*app, tsk_size_t); - - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(rr_opt), qtype_opt, qclass_any); - - /* - NAME domain name empty (root domain) - TYPE u_int16_t OPT - CLASS u_int16_t sender's UDP payload size - TTL u_int32_t extended RCODE and flags - RDLEN u_int16_t describes RDATA - RDATA octet stream {attribute,value} pairs - - */ - TNET_DNS_RR(rr_opt)->qclass = payload_size; - } - return self; + tnet_dns_opt_t *rr_opt = self; + if(rr_opt) { + uint16_t payload_size = (uint16_t)va_arg(*app, tsk_size_t); + + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(rr_opt), qtype_opt, qclass_any); + + /* + NAME domain name empty (root domain) + TYPE u_int16_t OPT + CLASS u_int16_t sender's UDP payload size + TTL u_int32_t extended RCODE and flags + RDLEN u_int16_t describes RDATA + RDATA octet stream {attribute,value} pairs + + */ + TNET_DNS_RR(rr_opt)->qclass = payload_size; + } + return self; } -static tsk_object_t* tnet_dns_opt_dtor(tsk_object_t * self) -{ - tnet_dns_opt_t *rr_opt = self; - if(rr_opt){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(rr_opt)); - } - return self; +static tsk_object_t* tnet_dns_opt_dtor(tsk_object_t * self) +{ + tnet_dns_opt_t *rr_opt = self; + if(rr_opt) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(rr_opt)); + } + return self; } -static const tsk_object_def_t tnet_dns_opt_def_s = -{ - sizeof(tnet_dns_opt_t), - tnet_dns_opt_ctor, - tnet_dns_opt_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_opt_def_s = { + sizeof(tnet_dns_opt_t), + tnet_dns_opt_ctor, + tnet_dns_opt_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_opt_def_t = &tnet_dns_opt_def_s; diff --git a/tinyNET/src/dns/tnet_dns_opt.h b/tinyNET/src/dns/tnet_dns_opt.h index 24485b9..ea6bd1d 100755 --- a/tinyNET/src/dns/tnet_dns_opt.h +++ b/tinyNET/src/dns/tnet_dns_opt.h @@ -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. * @@ -38,9 +38,8 @@ TNET_BEGIN_DECLS /** DNS OPT Resource Record */ -typedef struct tnet_dns_opt_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_opt_s { + TNET_DECLARE_DNS_RR; } tnet_dns_opt_t; diff --git a/tinyNET/src/dns/tnet_dns_ptr.c b/tinyNET/src/dns/tnet_dns_ptr.c index 23b7733..494fd57 100755 --- a/tinyNET/src/dns/tnet_dns_ptr.c +++ b/tinyNET/src/dns/tnet_dns_ptr.c @@ -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. * @@ -39,7 +39,7 @@ tnet_dns_ptr_t* tnet_dns_ptr_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void*data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_ptr_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_ptr_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -47,47 +47,46 @@ tnet_dns_ptr_t* tnet_dns_ptr_create(const char* name, tnet_dns_qclass_t qclass, // static tsk_object_t* tnet_dns_ptr_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_ptr_t *ptr = self; - if(ptr){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_ptr_t *ptr = self; + if(ptr) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(ptr), qtype_ptr, qclass); - TNET_DNS_RR(ptr)->name = tsk_strdup(name); - TNET_DNS_RR(ptr)->rdlength = rdlength; - TNET_DNS_RR(ptr)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(ptr), qtype_ptr, qclass); + TNET_DNS_RR(ptr)->name = tsk_strdup(name); + TNET_DNS_RR(ptr)->rdlength = rdlength; + TNET_DNS_RR(ptr)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* PTRDNAME */ - tnet_dns_rr_qname_deserialize(data, &(ptr->ptrdname), &offset); - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* PTRDNAME */ + tnet_dns_rr_qname_deserialize(data, &(ptr->ptrdname), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_ptr_dtor(tsk_object_t * self) -{ - tnet_dns_ptr_t *ptr = self; - if(ptr){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(ptr)); +static tsk_object_t* tnet_dns_ptr_dtor(tsk_object_t * self) +{ + tnet_dns_ptr_t *ptr = self; + if(ptr) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(ptr)); - TSK_FREE(ptr->ptrdname); - } - return self; + TSK_FREE(ptr->ptrdname); + } + return self; } -static const tsk_object_def_t tnet_dns_ptr_def_s = -{ - sizeof(tnet_dns_ptr_t), - tnet_dns_ptr_ctor, - tnet_dns_ptr_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_ptr_def_s = { + sizeof(tnet_dns_ptr_t), + tnet_dns_ptr_ctor, + tnet_dns_ptr_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_ptr_def_t = &tnet_dns_ptr_def_s; diff --git a/tinyNET/src/dns/tnet_dns_ptr.h b/tinyNET/src/dns/tnet_dns_ptr.h index fc2cbdc..778366c 100755 --- a/tinyNET/src/dns/tnet_dns_ptr.h +++ b/tinyNET/src/dns/tnet_dns_ptr.h @@ -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. * @@ -38,16 +38,15 @@ TNET_BEGIN_DECLS /** DNS PTR Resource Record */ -typedef struct tnet_dns_ptr_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_ptr_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.3.12. PTR RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.3.12. PTR RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / PTRDNAME / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* ptrdname; + */ + char* ptrdname; } tnet_dns_ptr_t; diff --git a/tinyNET/src/dns/tnet_dns_regexp.c b/tinyNET/src/dns/tnet_dns_regexp.c index 5cafeb8..ea2f5d8 100755 --- a/tinyNET/src/dns/tnet_dns_regexp.c +++ b/tinyNET/src/dns/tnet_dns_regexp.c @@ -2,19 +2,19 @@ /* #line 1 "./ragel/tnet_dns_regexp.rl" */ /* * Copyright (C) 2010-2015 Mamadou DIOP. -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -46,241 +46,252 @@ */ char* tnet_dns_regex_parse(const char* e164num, const char* regexp) { - char* ret = tsk_null; - char* prefix = tsk_null; - const char* tag_start; - tsk_size_t e164len; - - // Ragel - int cs = 0; - const char *p = tag_start = regexp; - const char *pe; - const char *eof; - - TSK_RAGEL_DISABLE_WARNINGS_BEGIN() - -/* #line 63 "./src/dns/tnet_dns_regexp.c" */ -static const char _tdns_machine_regexp_actions[] = { - 0, 1, 0, 1, 1, 1, 2, 2, - 0, 1, 2, 0, 2, 2, 2, 0, - 2, 3, 0, 3, 3, 0, 2 -}; - -static const char _tdns_machine_regexp_key_offsets[] = { - 0, 0, 1, 2, 5, 6, 7, 8, - 9, 10, 11, 13, 15, 17, 19, 21, - 23, 25, 26, 27 -}; - -static const char _tdns_machine_regexp_trans_keys[] = { - 33, 94, 40, 46, 92, 40, 46, 42, - 41, 36, 33, 33, 92, 33, 92, 48, - 57, 33, 92, 33, 92, 40, 42, 36, - 40, 40, 105, 0 -}; - -static const char _tdns_machine_regexp_single_lengths[] = { - 0, 1, 1, 3, 1, 1, 1, 1, - 1, 1, 2, 2, 0, 2, 2, 2, - 2, 1, 1, 0 -}; - -static const char _tdns_machine_regexp_range_lengths[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0 -}; - -static const char _tdns_machine_regexp_index_offsets[] = { - 0, 0, 2, 4, 8, 10, 12, 14, - 16, 18, 20, 23, 26, 28, 31, 34, - 37, 40, 42, 44 -}; - -static const char _tdns_machine_regexp_trans_targs[] = { - 2, 0, 3, 0, 5, 15, 17, 4, - 5, 4, 6, 0, 7, 0, 8, 0, - 9, 0, 10, 0, 18, 12, 11, 18, - 12, 11, 13, 0, 18, 0, 14, 18, - 0, 14, 5, 16, 4, 9, 5, 4, - 5, 4, 19, 0, 0, 0 -}; - -static const char _tdns_machine_regexp_trans_actions[] = { - 0, 0, 0, 0, 7, 1, 0, 1, - 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10, 10, 10, 13, - 13, 13, 0, 0, 19, 0, 16, 5, - 0, 0, 3, 0, 0, 0, 3, 0, - 7, 1, 0, 0, 0, 0 -}; - -static const int tdns_machine_regexp_start = 1; -static const int tdns_machine_regexp_first_final = 18; -static const int tdns_machine_regexp_error = 0; - -static const int tdns_machine_regexp_en_main = 1; - - -/* #line 96 "./ragel/tnet_dns_regexp.rl" */ - TSK_RAGEL_DISABLE_WARNINGS_END() - (void)(eof); - (void)(tdns_machine_regexp_first_final); - (void)(tdns_machine_regexp_error); - (void)(tdns_machine_regexp_en_main); - - if (!e164num) { - goto bail; - } - - if (!regexp) { - ret = tsk_strdup(e164num); - goto bail; - } - - e164len = (tsk_size_t)tsk_strlen(e164num); - pe = p + tsk_strlen(regexp); - eof = pe; - - TSK_RAGEL_DISABLE_WARNINGS_BEGIN() - -/* #line 148 "./src/dns/tnet_dns_regexp.c" */ - { - cs = tdns_machine_regexp_start; - } - -/* #line 117 "./ragel/tnet_dns_regexp.rl" */ - -/* #line 155 "./src/dns/tnet_dns_regexp.c" */ - { - int _klen; - unsigned int _trans; - const char *_acts; - unsigned int _nacts; - const char *_keys; - - if ( p == pe ) - goto _test_eof; - if ( cs == 0 ) - goto _out; + char* ret = tsk_null; + char* prefix = tsk_null; + const char* tag_start; + tsk_size_t e164len; + + // Ragel + int cs = 0; + const char *p = tag_start = regexp; + const char *pe; + const char *eof; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + + /* #line 63 "./src/dns/tnet_dns_regexp.c" */ + static const char _tdns_machine_regexp_actions[] = { + 0, 1, 0, 1, 1, 1, 2, 2, + 0, 1, 2, 0, 2, 2, 2, 0, + 2, 3, 0, 3, 3, 0, 2 + }; + + static const char _tdns_machine_regexp_key_offsets[] = { + 0, 0, 1, 2, 5, 6, 7, 8, + 9, 10, 11, 13, 15, 17, 19, 21, + 23, 25, 26, 27 + }; + + static const char _tdns_machine_regexp_trans_keys[] = { + 33, 94, 40, 46, 92, 40, 46, 42, + 41, 36, 33, 33, 92, 33, 92, 48, + 57, 33, 92, 33, 92, 40, 42, 36, + 40, 40, 105, 0 + }; + + static const char _tdns_machine_regexp_single_lengths[] = { + 0, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 2, 2, 0, 2, 2, 2, + 2, 1, 1, 0 + }; + + static const char _tdns_machine_regexp_range_lengths[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0 + }; + + static const char _tdns_machine_regexp_index_offsets[] = { + 0, 0, 2, 4, 8, 10, 12, 14, + 16, 18, 20, 23, 26, 28, 31, 34, + 37, 40, 42, 44 + }; + + static const char _tdns_machine_regexp_trans_targs[] = { + 2, 0, 3, 0, 5, 15, 17, 4, + 5, 4, 6, 0, 7, 0, 8, 0, + 9, 0, 10, 0, 18, 12, 11, 18, + 12, 11, 13, 0, 18, 0, 14, 18, + 0, 14, 5, 16, 4, 9, 5, 4, + 5, 4, 19, 0, 0, 0 + }; + + static const char _tdns_machine_regexp_trans_actions[] = { + 0, 0, 0, 0, 7, 1, 0, 1, + 3, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 10, 10, 13, + 13, 13, 0, 0, 19, 0, 16, 5, + 0, 0, 3, 0, 0, 0, 3, 0, + 7, 1, 0, 0, 0, 0 + }; + + static const int tdns_machine_regexp_start = 1; + static const int tdns_machine_regexp_first_final = 18; + static const int tdns_machine_regexp_error = 0; + + static const int tdns_machine_regexp_en_main = 1; + + + /* #line 96 "./ragel/tnet_dns_regexp.rl" */ + TSK_RAGEL_DISABLE_WARNINGS_END() + (void)(eof); + (void)(tdns_machine_regexp_first_final); + (void)(tdns_machine_regexp_error); + (void)(tdns_machine_regexp_en_main); + + if (!e164num) { + goto bail; + } + + if (!regexp) { + ret = tsk_strdup(e164num); + goto bail; + } + + e164len = (tsk_size_t)tsk_strlen(e164num); + pe = p + tsk_strlen(regexp); + eof = pe; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + + /* #line 148 "./src/dns/tnet_dns_regexp.c" */ + { + cs = tdns_machine_regexp_start; + } + + /* #line 117 "./ragel/tnet_dns_regexp.rl" */ + + /* #line 155 "./src/dns/tnet_dns_regexp.c" */ + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( p == pe ) { + goto _test_eof; + } + if ( cs == 0 ) { + goto _out; + } _resume: - _keys = _tdns_machine_regexp_trans_keys + _tdns_machine_regexp_key_offsets[cs]; - _trans = _tdns_machine_regexp_index_offsets[cs]; - - _klen = _tdns_machine_regexp_single_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + _klen - 1; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + ((_upper-_lower) >> 1); - if ( (*p) < *_mid ) - _upper = _mid - 1; - else if ( (*p) > *_mid ) - _lower = _mid + 1; - else { - _trans += (_mid - _keys); - goto _match; - } - } - _keys += _klen; - _trans += _klen; - } - - _klen = _tdns_machine_regexp_range_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + (_klen<<1) - 2; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( (*p) < _mid[0] ) - _upper = _mid - 2; - else if ( (*p) > _mid[1] ) - _lower = _mid + 2; - else { - _trans += ((_mid - _keys)>>1); - goto _match; - } - } - _trans += _klen; - } + _keys = _tdns_machine_regexp_trans_keys + _tdns_machine_regexp_key_offsets[cs]; + _trans = _tdns_machine_regexp_index_offsets[cs]; + + _klen = _tdns_machine_regexp_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) { + break; + } + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) { + _upper = _mid - 1; + } + else if ( (*p) > *_mid ) { + _lower = _mid + 1; + } + else { + _trans += (_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _tdns_machine_regexp_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) { + break; + } + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) { + _upper = _mid - 2; + } + else if ( (*p) > _mid[1] ) { + _lower = _mid + 2; + } + else { + _trans += ((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } _match: - cs = _tdns_machine_regexp_trans_targs[_trans]; - - if ( _tdns_machine_regexp_trans_actions[_trans] == 0 ) - goto _again; - - _acts = _tdns_machine_regexp_actions + _tdns_machine_regexp_trans_actions[_trans]; - _nacts = (unsigned int) *_acts++; - while ( _nacts-- > 0 ) - { - switch ( *_acts++ ) - { - case 0: -/* #line 36 "./ragel/tnet_dns_regexp.rl" */ - { - tag_start = p; - } - break; - case 1: -/* #line 40 "./ragel/tnet_dns_regexp.rl" */ - { - TSK_PARSER_SET_STRING(prefix); - } - break; - case 2: -/* #line 44 "./ragel/tnet_dns_regexp.rl" */ - { - int len = (int)(p - tag_start); - if (len) { - tsk_strncat(&ret, tag_start, len); - } - } - break; - case 3: -/* #line 51 "./ragel/tnet_dns_regexp.rl" */ - { - if (prefix) { - int prefixlen = (int)tsk_strlen(prefix); - tsk_strncat(&ret, e164num + prefixlen, (e164len - prefixlen)); - } - } - break; -/* #line 258 "./src/dns/tnet_dns_regexp.c" */ - } - } + cs = _tdns_machine_regexp_trans_targs[_trans]; + + if ( _tdns_machine_regexp_trans_actions[_trans] == 0 ) { + goto _again; + } + + _acts = _tdns_machine_regexp_actions + _tdns_machine_regexp_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: + /* #line 36 "./ragel/tnet_dns_regexp.rl" */ + { + tag_start = p; + } + break; + case 1: + /* #line 40 "./ragel/tnet_dns_regexp.rl" */ + { + TSK_PARSER_SET_STRING(prefix); + } + break; + case 2: + /* #line 44 "./ragel/tnet_dns_regexp.rl" */ + { + int len = (int)(p - tag_start); + if (len) { + tsk_strncat(&ret, tag_start, len); + } + } + break; + case 3: + /* #line 51 "./ragel/tnet_dns_regexp.rl" */ + { + if (prefix) { + int prefixlen = (int)tsk_strlen(prefix); + tsk_strncat(&ret, e164num + prefixlen, (e164len - prefixlen)); + } + } + break; + /* #line 258 "./src/dns/tnet_dns_regexp.c" */ + } + } _again: - if ( cs == 0 ) - goto _out; - if ( ++p != pe ) - goto _resume; - _test_eof: {} - _out: {} - } - -/* #line 118 "./ragel/tnet_dns_regexp.rl" */ - TSK_RAGEL_DISABLE_WARNINGS_END() - - if (cs < -/* #line 275 "./src/dns/tnet_dns_regexp.c" */ -18 -/* #line 120 "./ragel/tnet_dns_regexp.rl" */ - ){ - TSK_DEBUG_ERROR("regexp substitition failed."); - TSK_FREE(ret); - } + if ( cs == 0 ) { + goto _out; + } + if ( ++p != pe ) { + goto _resume; + } +_test_eof: { + } +_out: { + } + } + + /* #line 118 "./ragel/tnet_dns_regexp.rl" */ + TSK_RAGEL_DISABLE_WARNINGS_END() + + if (cs < + /* #line 275 "./src/dns/tnet_dns_regexp.c" */ + 18 + /* #line 120 "./ragel/tnet_dns_regexp.rl" */ + ) { + TSK_DEBUG_ERROR("regexp substitition failed."); + TSK_FREE(ret); + } bail: - TSK_FREE(prefix); - - return ret; + TSK_FREE(prefix); + + return ret; } diff --git a/tinyNET/src/dns/tnet_dns_regexp.h b/tinyNET/src/dns/tnet_dns_regexp.h index d40abce..6fab026 100755 --- a/tinyNET/src/dns/tnet_dns_regexp.h +++ b/tinyNET/src/dns/tnet_dns_regexp.h @@ -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. * diff --git a/tinyNET/src/dns/tnet_dns_resolvconf.c b/tinyNET/src/dns/tnet_dns_resolvconf.c index a4a0fbf..b77ba8f 100755 --- a/tinyNET/src/dns/tnet_dns_resolvconf.c +++ b/tinyNET/src/dns/tnet_dns_resolvconf.c @@ -9,12 +9,12 @@ * 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. * @@ -50,265 +50,273 @@ */ tnet_addresses_L_t * tnet_dns_resolvconf_parse(const char* path) { - tnet_addresses_L_t* servers = tsk_null; - tnet_ip_t ip; - const char* fullpath = path; - const char* tag_start = tsk_null; - FILE* fd; - char* buf = tsk_null; - - // Ragel - int cs = 0; - const char *p; - const char *pe; - const char *eof; - - TSK_RAGEL_DISABLE_WARNINGS_BEGIN() - -/* #line 69 "./src/dns/tnet_dns_resolvconf.c" */ -static const char _tdns_machine_resolvconf_actions[] = { - 0, 1, 0, 1, 1 -}; - -static const char _tdns_machine_resolvconf_key_offsets[] = { - 0, 7, 8, 9, 12, 15, 15, 22, - 24, 27, 30, 33, 36, 39, 42, 45, - 48, 51, 52, 53, 56 -}; - -static const char _tdns_machine_resolvconf_trans_keys[] = { - 10, 13, 32, 35, 59, 78, 110, 32, - 32, 10, 13, 32, 10, 13, 32, 10, - 13, 32, 35, 59, 78, 110, 10, 13, - 32, 65, 97, 32, 77, 109, 32, 69, - 101, 32, 83, 115, 32, 69, 101, 32, - 82, 114, 32, 86, 118, 32, 69, 101, - 32, 82, 114, 32, 32, 10, 13, 32, - 32, 35, 59, 78, 110, 0 -}; - -static const char _tdns_machine_resolvconf_single_lengths[] = { - 7, 1, 1, 3, 3, 0, 7, 2, - 3, 3, 3, 3, 3, 3, 3, 3, - 3, 1, 1, 3, 5 -}; - -static const char _tdns_machine_resolvconf_range_lengths[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - -static const char _tdns_machine_resolvconf_index_offsets[] = { - 0, 8, 10, 12, 16, 20, 21, 29, - 32, 36, 40, 44, 48, 52, 56, 60, - 64, 68, 70, 72, 76 -}; - -static const char _tdns_machine_resolvconf_indicies[] = { - 1, 1, 2, 3, 3, 4, 4, 0, - 5, 0, 5, 6, 7, 7, 8, 6, - 7, 7, 8, 9, 9, 1, 1, 5, - 3, 3, 4, 4, 0, 7, 7, 3, - 5, 10, 10, 0, 5, 11, 11, 0, - 5, 12, 12, 0, 5, 13, 13, 0, - 5, 14, 14, 0, 5, 15, 15, 0, - 5, 16, 16, 0, 5, 17, 17, 0, - 5, 18, 18, 0, 19, 0, 19, 20, - 22, 22, 23, 21, 2, 3, 3, 4, - 4, 0, 0 -}; - -static const char _tdns_machine_resolvconf_trans_targs[] = { - 1, 6, 20, 7, 8, 2, 3, 0, - 4, 5, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 19, 0, 4 -}; - -static const char _tdns_machine_resolvconf_trans_actions[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 3, 3 -}; - -static const int tdns_machine_resolvconf_start = 0; -static const int tdns_machine_resolvconf_first_final = 0; -static const int tdns_machine_resolvconf_error = -1; - -static const int tdns_machine_resolvconf_en_main = 0; - - -/* #line 101 "./ragel/tnet_dns_resolvconf.rl" */ - TSK_RAGEL_DISABLE_WARNINGS_END() - (void)(eof); - (void)(tdns_machine_resolvconf_first_final); - (void)(tdns_machine_resolvconf_error); - (void)(tdns_machine_resolvconf_en_main); - - if(tsk_strnullORempty(fullpath)){ - fullpath = TNET_RESOLV_CONF_PATH; - } - - /* Open the file and read all data */ - if((fd = fopen(fullpath, "r"))){ - long len; - fseek(fd, 0L, SEEK_END); - len = ftell(fd); - fseek(fd, 0L, SEEK_SET); - if (!(buf = (char*)tsk_calloc(len + 1, 1))) { - TSK_DEBUG_ERROR("Failed to allocate buffer with size = %ld", (len + 1)); - goto bail; - } - fread(buf, 1, len, fd); - p = &buf[0]; - pe = p + len + 1/*hack*/; - eof = pe; - fclose(fd); - - buf[len] = '\n'; // hack to have perfect lines - - servers = tsk_list_create(); - } - else { + tnet_addresses_L_t* servers = tsk_null; + tnet_ip_t ip; + const char* fullpath = path; + const char* tag_start = tsk_null; + FILE* fd; + char* buf = tsk_null; + + // Ragel + int cs = 0; + const char *p; + const char *pe; + const char *eof; + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + + /* #line 69 "./src/dns/tnet_dns_resolvconf.c" */ + static const char _tdns_machine_resolvconf_actions[] = { + 0, 1, 0, 1, 1 + }; + + static const char _tdns_machine_resolvconf_key_offsets[] = { + 0, 7, 8, 9, 12, 15, 15, 22, + 24, 27, 30, 33, 36, 39, 42, 45, + 48, 51, 52, 53, 56 + }; + + static const char _tdns_machine_resolvconf_trans_keys[] = { + 10, 13, 32, 35, 59, 78, 110, 32, + 32, 10, 13, 32, 10, 13, 32, 10, + 13, 32, 35, 59, 78, 110, 10, 13, + 32, 65, 97, 32, 77, 109, 32, 69, + 101, 32, 83, 115, 32, 69, 101, 32, + 82, 114, 32, 86, 118, 32, 69, 101, + 32, 82, 114, 32, 32, 10, 13, 32, + 32, 35, 59, 78, 110, 0 + }; + + static const char _tdns_machine_resolvconf_single_lengths[] = { + 7, 1, 1, 3, 3, 0, 7, 2, + 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 3, 5 + }; + + static const char _tdns_machine_resolvconf_range_lengths[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + }; + + static const char _tdns_machine_resolvconf_index_offsets[] = { + 0, 8, 10, 12, 16, 20, 21, 29, + 32, 36, 40, 44, 48, 52, 56, 60, + 64, 68, 70, 72, 76 + }; + + static const char _tdns_machine_resolvconf_indicies[] = { + 1, 1, 2, 3, 3, 4, 4, 0, + 5, 0, 5, 6, 7, 7, 8, 6, + 7, 7, 8, 9, 9, 1, 1, 5, + 3, 3, 4, 4, 0, 7, 7, 3, + 5, 10, 10, 0, 5, 11, 11, 0, + 5, 12, 12, 0, 5, 13, 13, 0, + 5, 14, 14, 0, 5, 15, 15, 0, + 5, 16, 16, 0, 5, 17, 17, 0, + 5, 18, 18, 0, 19, 0, 19, 20, + 22, 22, 23, 21, 2, 3, 3, 4, + 4, 0, 0 + }; + + static const char _tdns_machine_resolvconf_trans_targs[] = { + 1, 6, 20, 7, 8, 2, 3, 0, + 4, 5, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 19, 0, 4 + }; + + static const char _tdns_machine_resolvconf_trans_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 3, 3 + }; + + static const int tdns_machine_resolvconf_start = 0; + static const int tdns_machine_resolvconf_first_final = 0; + static const int tdns_machine_resolvconf_error = -1; + + static const int tdns_machine_resolvconf_en_main = 0; + + + /* #line 101 "./ragel/tnet_dns_resolvconf.rl" */ + TSK_RAGEL_DISABLE_WARNINGS_END() + (void)(eof); + (void)(tdns_machine_resolvconf_first_final); + (void)(tdns_machine_resolvconf_error); + (void)(tdns_machine_resolvconf_en_main); + + if(tsk_strnullORempty(fullpath)) { + fullpath = TNET_RESOLV_CONF_PATH; + } + + /* Open the file and read all data */ + if((fd = fopen(fullpath, "r"))) { + long len; + fseek(fd, 0L, SEEK_END); + len = ftell(fd); + fseek(fd, 0L, SEEK_SET); + if (!(buf = (char*)tsk_calloc(len + 1, 1))) { + TSK_DEBUG_ERROR("Failed to allocate buffer with size = %ld", (len + 1)); + goto bail; + } + fread(buf, 1, len, fd); + p = &buf[0]; + pe = p + len + 1/*hack*/; + eof = pe; + fclose(fd); + + buf[len] = '\n'; // hack to have perfect lines + + servers = tsk_list_create(); + } + else { #if ANDROID || defined(__APPLE__) /* TARGET_OS_IPHONE not defined for bsd libraries */ - TSK_DEBUG_INFO("Failed to open [%s]. But don't panic, we have detected that you are using Google Android/iOS Systems.\n" - "You should look at the Progammer's Guide for more information.\n If you are not using DNS functions, don't worry about this warning.", - fullpath); + TSK_DEBUG_INFO("Failed to open [%s]. But don't panic, we have detected that you are using Google Android/iOS Systems.\n" + "You should look at the Progammer's Guide for more information.\n If you are not using DNS functions, don't worry about this warning.", + fullpath); #else - TSK_DEBUG_ERROR("Failed to open %s.", fullpath); + TSK_DEBUG_ERROR("Failed to open %s.", fullpath); #endif - goto bail; - } - - TSK_RAGEL_DISABLE_WARNINGS_BEGIN() - -/* #line 186 "./src/dns/tnet_dns_resolvconf.c" */ - { - cs = tdns_machine_resolvconf_start; - } - -/* #line 144 "./ragel/tnet_dns_resolvconf.rl" */ - -/* #line 193 "./src/dns/tnet_dns_resolvconf.c" */ - { - int _klen; - unsigned int _trans; - const char *_acts; - unsigned int _nacts; - const char *_keys; - - if ( p == pe ) - goto _test_eof; + goto bail; + } + + TSK_RAGEL_DISABLE_WARNINGS_BEGIN() + + /* #line 186 "./src/dns/tnet_dns_resolvconf.c" */ + { + cs = tdns_machine_resolvconf_start; + } + + /* #line 144 "./ragel/tnet_dns_resolvconf.rl" */ + + /* #line 193 "./src/dns/tnet_dns_resolvconf.c" */ + { + int _klen; + unsigned int _trans; + const char *_acts; + unsigned int _nacts; + const char *_keys; + + if ( p == pe ) { + goto _test_eof; + } _resume: - _keys = _tdns_machine_resolvconf_trans_keys + _tdns_machine_resolvconf_key_offsets[cs]; - _trans = _tdns_machine_resolvconf_index_offsets[cs]; - - _klen = _tdns_machine_resolvconf_single_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + _klen - 1; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + ((_upper-_lower) >> 1); - if ( (*p) < *_mid ) - _upper = _mid - 1; - else if ( (*p) > *_mid ) - _lower = _mid + 1; - else { - _trans += (_mid - _keys); - goto _match; - } - } - _keys += _klen; - _trans += _klen; - } - - _klen = _tdns_machine_resolvconf_range_lengths[cs]; - if ( _klen > 0 ) { - const char *_lower = _keys; - const char *_mid; - const char *_upper = _keys + (_klen<<1) - 2; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( (*p) < _mid[0] ) - _upper = _mid - 2; - else if ( (*p) > _mid[1] ) - _lower = _mid + 2; - else { - _trans += ((_mid - _keys)>>1); - goto _match; - } - } - _trans += _klen; - } + _keys = _tdns_machine_resolvconf_trans_keys + _tdns_machine_resolvconf_key_offsets[cs]; + _trans = _tdns_machine_resolvconf_index_offsets[cs]; + + _klen = _tdns_machine_resolvconf_single_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + _klen - 1; + while (1) { + if ( _upper < _lower ) { + break; + } + + _mid = _lower + ((_upper-_lower) >> 1); + if ( (*p) < *_mid ) { + _upper = _mid - 1; + } + else if ( (*p) > *_mid ) { + _lower = _mid + 1; + } + else { + _trans += (_mid - _keys); + goto _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _tdns_machine_resolvconf_range_lengths[cs]; + if ( _klen > 0 ) { + const char *_lower = _keys; + const char *_mid; + const char *_upper = _keys + (_klen<<1) - 2; + while (1) { + if ( _upper < _lower ) { + break; + } + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( (*p) < _mid[0] ) { + _upper = _mid - 2; + } + else if ( (*p) > _mid[1] ) { + _lower = _mid + 2; + } + else { + _trans += ((_mid - _keys)>>1); + goto _match; + } + } + _trans += _klen; + } _match: - _trans = _tdns_machine_resolvconf_indicies[_trans]; - cs = _tdns_machine_resolvconf_trans_targs[_trans]; - - if ( _tdns_machine_resolvconf_trans_actions[_trans] == 0 ) - goto _again; - - _acts = _tdns_machine_resolvconf_actions + _tdns_machine_resolvconf_trans_actions[_trans]; - _nacts = (unsigned int) *_acts++; - while ( _nacts-- > 0 ) - { - switch ( *_acts++ ) - { - case 0: -/* #line 41 "./ragel/tnet_dns_resolvconf.rl" */ - { - tag_start = p; - } - break; - case 1: -/* #line 45 "./ragel/tnet_dns_resolvconf.rl" */ - { - int len = (int)(p - tag_start); - if(len && len<=sizeof(ip)){ - tnet_address_t *address; - memset(ip, '\0', sizeof(ip)); - memcpy(ip, tag_start, len); - TSK_DEBUG_INFO("Adding DNS server = %s:%d", ip, TNET_DNS_SERVER_PORT_DEFAULT); - - address = tnet_address_create(ip); - address->family = tnet_get_family(ip, TNET_DNS_SERVER_PORT_DEFAULT); - address->dnsserver = 1; - tsk_list_push_ascending_data(servers, (void**)&address); - } - } - break; -/* #line 288 "./src/dns/tnet_dns_resolvconf.c" */ - } - } + _trans = _tdns_machine_resolvconf_indicies[_trans]; + cs = _tdns_machine_resolvconf_trans_targs[_trans]; + + if ( _tdns_machine_resolvconf_trans_actions[_trans] == 0 ) { + goto _again; + } + + _acts = _tdns_machine_resolvconf_actions + _tdns_machine_resolvconf_trans_actions[_trans]; + _nacts = (unsigned int) *_acts++; + while ( _nacts-- > 0 ) { + switch ( *_acts++ ) { + case 0: + /* #line 41 "./ragel/tnet_dns_resolvconf.rl" */ + { + tag_start = p; + } + break; + case 1: + /* #line 45 "./ragel/tnet_dns_resolvconf.rl" */ + { + int len = (int)(p - tag_start); + if(len && len<=sizeof(ip)) { + tnet_address_t *address; + memset(ip, '\0', sizeof(ip)); + memcpy(ip, tag_start, len); + TSK_DEBUG_INFO("Adding DNS server = %s:%d", ip, TNET_DNS_SERVER_PORT_DEFAULT); + + address = tnet_address_create(ip); + address->family = tnet_get_family(ip, TNET_DNS_SERVER_PORT_DEFAULT); + address->dnsserver = 1; + tsk_list_push_ascending_data(servers, (void**)&address); + } + } + break; + /* #line 288 "./src/dns/tnet_dns_resolvconf.c" */ + } + } _again: - if ( ++p != pe ) - goto _resume; - _test_eof: {} - } - -/* #line 145 "./ragel/tnet_dns_resolvconf.rl" */ - TSK_RAGEL_DISABLE_WARNINGS_END() - - if (cs < -/* #line 302 "./src/dns/tnet_dns_resolvconf.c" */ -0 -/* #line 147 "./ragel/tnet_dns_resolvconf.rl" */ - ) { - TSK_DEBUG_ERROR("Failed to parse %s.", fullpath); - TSK_OBJECT_SAFE_FREE(servers); - } + if ( ++p != pe ) { + goto _resume; + } +_test_eof: { + } + } + + /* #line 145 "./ragel/tnet_dns_resolvconf.rl" */ + TSK_RAGEL_DISABLE_WARNINGS_END() + + if (cs < + /* #line 302 "./src/dns/tnet_dns_resolvconf.c" */ + 0 + /* #line 147 "./ragel/tnet_dns_resolvconf.rl" */ + ) { + TSK_DEBUG_ERROR("Failed to parse %s.", fullpath); + TSK_OBJECT_SAFE_FREE(servers); + } bail: - TSK_FREE(buf); - return servers; + TSK_FREE(buf); + return servers; } diff --git a/tinyNET/src/dns/tnet_dns_resolvconf.h b/tinyNET/src/dns/tnet_dns_resolvconf.h index 5290c41..53c5b70 100755 --- a/tinyNET/src/dns/tnet_dns_resolvconf.h +++ b/tinyNET/src/dns/tnet_dns_resolvconf.h @@ -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. * diff --git a/tinyNET/src/dns/tnet_dns_rr.c b/tinyNET/src/dns/tnet_dns_rr.c index b74a31d..eb5125a 100755 --- a/tinyNET/src/dns/tnet_dns_rr.c +++ b/tinyNET/src/dns/tnet_dns_rr.c @@ -50,7 +50,7 @@ tnet_dns_rr_t* tnet_dns_rr_create() { - return tsk_object_new(tnet_dns_rr_def_t); + return tsk_object_new(tnet_dns_rr_def_t); } /** Initializes any DNS RR (either NAPTR or SRV ...). @@ -61,17 +61,17 @@ tnet_dns_rr_t* tnet_dns_rr_create() */ int tnet_dns_rr_init(tnet_dns_rr_t *rr, tnet_dns_qtype_t qtype, tnet_dns_qclass_t qclass) { - if (rr){ - if (!rr->initialized){ - rr->qtype = qtype; - rr->qclass = qclass; - - rr->initialized = tsk_true; - return 0; - } - return -2; - } - return -1; + if (rr) { + if (!rr->initialized) { + rr->qtype = qtype; + rr->qclass = qclass; + + rr->initialized = tsk_true; + return 0; + } + return -2; + } + return -1; } /** Deinitializes any DNS RR (either NAPTR or SRV ...). @@ -80,79 +80,79 @@ int tnet_dns_rr_init(tnet_dns_rr_t *rr, tnet_dns_qtype_t qtype, tnet_dns_qclass_ */ int tnet_dns_rr_deinit(tnet_dns_rr_t *rr) { - if (rr){ - if (rr->initialized){ - TSK_FREE(rr->name); - TSK_FREE(rr->rpdata); - - rr->initialized = tsk_false; - return 0; - } - return -2; - } - return -1; + if (rr) { + if (rr->initialized) { + TSK_FREE(rr->name); + TSK_FREE(rr->rpdata); + + rr->initialized = tsk_false; + return 0; + } + return -2; + } + return -1; } /** Deserialize <character-string>. */ int tnet_dns_rr_charstring_deserialize(const void* data, char** charstring, tsk_size_t *offset) { - /* RFC 1035 - 3.3. Standard RRs - <character-string> is a single length octet followed by that number of characters. - <character-string> is treated as binary information, and can be up to 256 characters in - length (including the length octet). - */ - uint8_t* dataPtr = (((uint8_t*)data) + *offset); - uint8_t length = *dataPtr; - - *charstring = tsk_strndup((const char*)(dataPtr + 1), length); - *offset += (1 + length); - - return 0; + /* RFC 1035 - 3.3. Standard RRs + <character-string> is a single length octet followed by that number of characters. + <character-string> is treated as binary information, and can be up to 256 characters in + length (including the length octet). + */ + uint8_t* dataPtr = (((uint8_t*)data) + *offset); + uint8_t length = *dataPtr; + + *charstring = tsk_strndup((const char*)(dataPtr + 1), length); + *offset += (1 + length); + + return 0; } /** Deserializes a QName. */ int tnet_dns_rr_qname_deserialize(const void* data, char** name, tsk_size_t *offset) { - /* RFC 1035 - 4.1.4. Message compression + /* RFC 1035 - 4.1.4. Message compression - The pointer takes the form of a two octet sequence: - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | 1 1| OFFSET | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - uint8_t* dataPtr = (((uint8_t*)data) + *offset); - unsigned usingPtr = 0; /* Do not change. */ + The pointer takes the form of a two octet sequence: + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ + uint8_t* dataPtr = (((uint8_t*)data) + *offset); + unsigned usingPtr = 0; /* Do not change. */ - while (*dataPtr){ - usingPtr = ((*dataPtr & 0xC0) == 0xC0); + while (*dataPtr) { + usingPtr = ((*dataPtr & 0xC0) == 0xC0); - if (usingPtr){ - tsk_size_t ptr_offset = (*dataPtr & 0x3F); - ptr_offset = ptr_offset << 8 | *(dataPtr + 1); + if (usingPtr) { + tsk_size_t ptr_offset = (*dataPtr & 0x3F); + ptr_offset = ptr_offset << 8 | *(dataPtr + 1); - *offset += 2; - return tnet_dns_rr_qname_deserialize(data, name, &ptr_offset); - } - else{ - uint8_t length; + *offset += 2; + return tnet_dns_rr_qname_deserialize(data, name, &ptr_offset); + } + else { + uint8_t length; - if (*name){ - tsk_strcat(name, "."); - } + if (*name) { + tsk_strcat(name, "."); + } - length = *dataPtr; - *offset += 1, dataPtr++; + length = *dataPtr; + *offset += 1, dataPtr++; - tsk_strncat(name, (const char*)dataPtr, length); - *offset += length, dataPtr += length; - } - } + tsk_strncat(name, (const char*)dataPtr, length); + *offset += length, dataPtr += length; + } + } - *offset += 1; + *offset += 1; - return 0; + return 0; } //int tnet_dns_rr_qname_deserialize(const void* data, tsk_size_t size, char** name, tsk_size_t *offset) @@ -179,7 +179,7 @@ int tnet_dns_rr_qname_deserialize(const void* data, char** name, tsk_size_t *off // uint16_t ptr_offset = (*dataPtr & 0x3F); // ptr_offset = ptr_offset << 8 | *(dataPtr+1); // Ptr = ((uint8_t*)data) + ptr_offset; -// +// // tnet_qname_label_parse(Ptr, (dataEnd - Ptr), name, &islast); // *offset += 2, dataPtr += 2; // } @@ -199,221 +199,208 @@ int tnet_dns_rr_qname_deserialize(const void* data, char** name, tsk_size_t *off */ int tnet_dns_rr_qname_serialize(const char* qname, tsk_buffer_t* output) { - /* - QNAME a domain name represented as a sequence of labels, where - each label consists of a length octet followed by that - number of octets. The domain name terminates with the - zero length octet for the null label of the root. Note - that this field may be an odd number of octets; no - padding is used. - - Example: "doubango.com" ==> 8doubango3comNULL - */ - static uint8_t null = 0; - - if (qname){ - char* saveptr; - char* _qname = tsk_strdup(qname); - char* label = tsk_strtok_r(_qname, ".", &saveptr); - - while (label){ - uint8_t length = (uint8_t)tsk_strlen(label); - tsk_buffer_append(output, &length, 1); - tsk_buffer_append(output, label, tsk_strlen(label)); - - label = tsk_strtok_r(tsk_null, ".", &saveptr); - } - - TSK_FREE(_qname); - } - - /* terminates domain name */ - tsk_buffer_append(output, &null, 1); - - return 0; + /* + QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. + + Example: "doubango.com" ==> 8doubango3comNULL + */ + static uint8_t null = 0; + + if (qname) { + char* saveptr; + char* _qname = tsk_strdup(qname); + char* label = tsk_strtok_r(_qname, ".", &saveptr); + + while (label) { + uint8_t length = (uint8_t)tsk_strlen(label); + tsk_buffer_append(output, &length, 1); + tsk_buffer_append(output, label, tsk_strlen(label)); + + label = tsk_strtok_r(tsk_null, ".", &saveptr); + } + + TSK_FREE(_qname); + } + + /* terminates domain name */ + tsk_buffer_append(output, &null, 1); + + return 0; } /** Deserializes a DNS RR. */ tnet_dns_rr_t* tnet_dns_rr_deserialize(const void* data, tsk_size_t size, tsk_size_t* offset) { - tnet_dns_rr_t *rr = tsk_null; - uint8_t* dataStart = (uint8_t*)data; - uint8_t* dataPtr = (dataStart + *offset); - //uint8_t* dataEnd = (dataPtr+size); - tnet_dns_qtype_t qtype; - tnet_dns_qclass_t qclass; - uint32_t ttl; - uint16_t rdlength; - char* qname = tsk_null; - - /* Check validity */ - if (!dataPtr || !size){ - goto bail; - } - - /* == Parse QNAME == */ - tnet_dns_rr_qname_deserialize(dataStart, &qname, offset); - dataPtr = (dataStart + *offset); - /* == Parse QTYPE == */ - qtype = (tnet_dns_qtype_t)tnet_ntohs_2(dataPtr); - dataPtr += 2, *offset += 2; - /* == Parse QCLASS == */ - qclass = (tnet_dns_qclass_t)tnet_ntohs_2(dataPtr); - dataPtr += 2, *offset += 2; - /* == Parse TTL == */ - ttl = (uint32_t)tnet_htonl_2(dataPtr); - dataPtr += 4, *offset += 4; - /* == Parse RDLENGTH == */ - rdlength = tnet_ntohs_2(dataPtr); - dataPtr += 2, *offset += 2; - - switch (qtype){ - case qtype_a: - { - rr = (tnet_dns_rr_t *)tnet_dns_a_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_aaaa: - { - rr = (tnet_dns_rr_t *)tnet_dns_aaaa_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_cname: - { - rr = (tnet_dns_rr_t *)tnet_dns_cname_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_mx: - { - rr = (tnet_dns_rr_t *)tnet_dns_mx_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_naptr: - { - rr = (tnet_dns_rr_t *)tnet_dns_naptr_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_ns: - { - rr = (tnet_dns_rr_t *)tnet_dns_ns_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_opt: - { - unsigned payload_size = qclass; - rr = (tnet_dns_rr_t *)tnet_dns_opt_create(payload_size); - break; - } - - case qtype_ptr: - { - rr = (tnet_dns_rr_t *)tnet_dns_ptr_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_soa: - { - rr = (tnet_dns_rr_t *)tnet_dns_soa_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_srv: - { - rr = (tnet_dns_rr_t *)tnet_dns_srv_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - case qtype_txt: - { - rr = (tnet_dns_rr_t *)tnet_dns_txt_create(qname, qclass, ttl, rdlength, dataStart, *offset); - break; - } - - default: - { - TSK_DEBUG_ERROR("NOT IMPLEMENTED"); - break; - } - } + tnet_dns_rr_t *rr = tsk_null; + uint8_t* dataStart = (uint8_t*)data; + uint8_t* dataPtr = (dataStart + *offset); + //uint8_t* dataEnd = (dataPtr+size); + tnet_dns_qtype_t qtype; + tnet_dns_qclass_t qclass; + uint32_t ttl; + uint16_t rdlength; + char* qname = tsk_null; + + /* Check validity */ + if (!dataPtr || !size) { + goto bail; + } + + /* == Parse QNAME == */ + tnet_dns_rr_qname_deserialize(dataStart, &qname, offset); + dataPtr = (dataStart + *offset); + /* == Parse QTYPE == */ + qtype = (tnet_dns_qtype_t)tnet_ntohs_2(dataPtr); + dataPtr += 2, *offset += 2; + /* == Parse QCLASS == */ + qclass = (tnet_dns_qclass_t)tnet_ntohs_2(dataPtr); + dataPtr += 2, *offset += 2; + /* == Parse TTL == */ + ttl = (uint32_t)tnet_htonl_2(dataPtr); + dataPtr += 4, *offset += 4; + /* == Parse RDLENGTH == */ + rdlength = tnet_ntohs_2(dataPtr); + dataPtr += 2, *offset += 2; + + switch (qtype) { + case qtype_a: { + rr = (tnet_dns_rr_t *)tnet_dns_a_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_aaaa: { + rr = (tnet_dns_rr_t *)tnet_dns_aaaa_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_cname: { + rr = (tnet_dns_rr_t *)tnet_dns_cname_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_mx: { + rr = (tnet_dns_rr_t *)tnet_dns_mx_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_naptr: { + rr = (tnet_dns_rr_t *)tnet_dns_naptr_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_ns: { + rr = (tnet_dns_rr_t *)tnet_dns_ns_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_opt: { + unsigned payload_size = qclass; + rr = (tnet_dns_rr_t *)tnet_dns_opt_create(payload_size); + break; + } + + case qtype_ptr: { + rr = (tnet_dns_rr_t *)tnet_dns_ptr_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_soa: { + rr = (tnet_dns_rr_t *)tnet_dns_soa_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_srv: { + rr = (tnet_dns_rr_t *)tnet_dns_srv_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + case qtype_txt: { + rr = (tnet_dns_rr_t *)tnet_dns_txt_create(qname, qclass, ttl, rdlength, dataStart, *offset); + break; + } + + default: { + TSK_DEBUG_ERROR("NOT IMPLEMENTED"); + break; + } + } bail: - TSK_FREE(qname); + TSK_FREE(qname); - *offset += rdlength; - return rr; + *offset += rdlength; + return rr; } /** Serializes a DNS RR. */ int tnet_dns_rr_serialize(const tnet_dns_rr_t* rr, tsk_buffer_t *output) { - if (!rr || !output){ - return -1; - } - - /*=== NAME ===*/ - { - tnet_dns_rr_qname_serialize(rr->name, output); - } - - /*=== TYPE ===*/ - { - uint16_t qtype = tnet_htons(rr->qtype); - tsk_buffer_append(output, &(qtype), 2); - } - - /*=== CLASS ===*/ - { - uint16_t qclass = tnet_htons(rr->qclass); - tsk_buffer_append(output, &(qclass), 2); - } - - /*=== TTL ===*/ - { - uint32_t ttl = (uint32_t)tnet_htonl(rr->ttl); - tsk_buffer_append(output, &(ttl), 4); - } - - /*=== RDLENGTH ===*/ - { - uint16_t length = tnet_htons(rr->rdlength); - tsk_buffer_append(output, &(length), 2); - } - - /*=== RDATA : Request never contains data - ===*/ - if (!rr->rpdata){ - goto done; - } - - switch (rr->qtype){ - case qtype_a: - case qtype_aaaa: - case qtype_cname: - case qtype_mx: - case qtype_naptr: - case qtype_ns: - case qtype_opt: - case qtype_ptr: - case qtype_soa: - case qtype_srv: - case qtype_txt: - default: - { - TSK_DEBUG_WARN("DNS Request should not contains RDATA (not supported)."); - break; - } - } + if (!rr || !output) { + return -1; + } + + /*=== NAME ===*/ + { + tnet_dns_rr_qname_serialize(rr->name, output); + } + + /*=== TYPE ===*/ + { + uint16_t qtype = tnet_htons(rr->qtype); + tsk_buffer_append(output, &(qtype), 2); + } + + /*=== CLASS ===*/ + { + uint16_t qclass = tnet_htons(rr->qclass); + tsk_buffer_append(output, &(qclass), 2); + } + + /*=== TTL ===*/ + { + uint32_t ttl = (uint32_t)tnet_htonl(rr->ttl); + tsk_buffer_append(output, &(ttl), 4); + } + + /*=== RDLENGTH ===*/ + { + uint16_t length = tnet_htons(rr->rdlength); + tsk_buffer_append(output, &(length), 2); + } + + /*=== RDATA : Request never contains data + ===*/ + if (!rr->rpdata) { + goto done; + } + + switch (rr->qtype) { + case qtype_a: + case qtype_aaaa: + case qtype_cname: + case qtype_mx: + case qtype_naptr: + case qtype_ns: + case qtype_opt: + case qtype_ptr: + case qtype_soa: + case qtype_srv: + case qtype_txt: + default: { + TSK_DEBUG_WARN("DNS Request should not contains RDATA (not supported)."); + break; + } + } done: - return 0; + return 0; } @@ -422,27 +409,26 @@ done: // static tsk_object_t* tnet_dns_rr_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_rr_t *rr = self; - if (rr){ - tnet_dns_rr_init(rr, qtype_any, qclass_any); - } - return self; + tnet_dns_rr_t *rr = self; + if (rr) { + tnet_dns_rr_init(rr, qtype_any, qclass_any); + } + return self; } static tsk_object_t* tnet_dns_rr_dtor(tsk_object_t * self) { - tnet_dns_rr_t *rr = self; - if (rr){ - tnet_dns_rr_deinit(rr); - } - return self; + tnet_dns_rr_t *rr = self; + if (rr) { + tnet_dns_rr_deinit(rr); + } + return self; } -static const tsk_object_def_t tnet_dns_rr_def_s = -{ - sizeof(tnet_dns_rr_t), - tnet_dns_rr_ctor, - tnet_dns_rr_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_rr_def_s = { + sizeof(tnet_dns_rr_t), + tnet_dns_rr_ctor, + tnet_dns_rr_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_rr_def_t = &tnet_dns_rr_def_s; diff --git a/tinyNET/src/dns/tnet_dns_rr.h b/tinyNET/src/dns/tnet_dns_rr.h index f4a1b6b..895c648 100755 --- a/tinyNET/src/dns/tnet_dns_rr.h +++ b/tinyNET/src/dns/tnet_dns_rr.h @@ -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. * @@ -46,106 +46,103 @@ TNET_BEGIN_DECLS /** RFC 1035 - 3.2.2. TYPE values * @sa http://en.wikipedia.org/wiki/List_of_DNS_record_types */ -typedef enum tnet_dns_qtype_e -{ - qtype_a = 1, /**< A 1 a host address */ - qtype_ns = 2, /**< NS 2 an authoritative name server */ - qtype_md = 3, /**< MD 3 a mail destination (Obsolete - use MX) */ - qtype_mf = 4, /**< MF 4 a mail forwarder (Obsolete - use MX) */ - qtype_cname = 5, /**< CNAME 5 the canonical name for an alias */ - qtype_soa = 6, /**< SOA 6 marks the start of a zone of authority */ - qtype_mb = 7, /**< MB 7 a mailbox domain name (EXPERIMENTAL) */ - qtype_mg = 8, /**< MG 8 a mail group member (EXPERIMENTAL) */ - qtype_mr = 9, /**< MR 9 a mail rename domain name (EXPERIMENTAL) */ - qtype_null = 10, /**< NULL 10 a null RR (EXPERIMENTAL) */ - qtype_wks = 11, /**< WKS 11 a well known service description */ - qtype_ptr = 12, /**< PTR 12 a domain name pointer */ - qtype_hinfo = 13, /**< HINFO 13 host information */ - qtype_minfo = 14, /**< MINFO 14 mailbox or mail list information */ - qtype_mx = 15, /**< MX 15 mail exchange */ - qtype_txt = 16, /**< TXT 16 text strings */ - - qtype_aaaa = 28, /**< AAAA 28 IPv6 host address */ - - qtype_srv = 33, /**< SRV 33 Service locator */ - - qtype_naptr = 35, /**< NAPTR 35 Naming Authority Pointer */ - - qtype_opt = 41, /**< OPT 41 Option */ - - qtype_ipseckey = 45,/**< IPSECKEY 45 IPSEC Key */ - - qtype_spf = 99, /**< SPF 99 SPF record */ - - qtype_any = 255 /**< * 255 A request for all records (3.2.3. QTYPE values)*/ +typedef enum tnet_dns_qtype_e { + qtype_a = 1, /**< A 1 a host address */ + qtype_ns = 2, /**< NS 2 an authoritative name server */ + qtype_md = 3, /**< MD 3 a mail destination (Obsolete - use MX) */ + qtype_mf = 4, /**< MF 4 a mail forwarder (Obsolete - use MX) */ + qtype_cname = 5, /**< CNAME 5 the canonical name for an alias */ + qtype_soa = 6, /**< SOA 6 marks the start of a zone of authority */ + qtype_mb = 7, /**< MB 7 a mailbox domain name (EXPERIMENTAL) */ + qtype_mg = 8, /**< MG 8 a mail group member (EXPERIMENTAL) */ + qtype_mr = 9, /**< MR 9 a mail rename domain name (EXPERIMENTAL) */ + qtype_null = 10, /**< NULL 10 a null RR (EXPERIMENTAL) */ + qtype_wks = 11, /**< WKS 11 a well known service description */ + qtype_ptr = 12, /**< PTR 12 a domain name pointer */ + qtype_hinfo = 13, /**< HINFO 13 host information */ + qtype_minfo = 14, /**< MINFO 14 mailbox or mail list information */ + qtype_mx = 15, /**< MX 15 mail exchange */ + qtype_txt = 16, /**< TXT 16 text strings */ + + qtype_aaaa = 28, /**< AAAA 28 IPv6 host address */ + + qtype_srv = 33, /**< SRV 33 Service locator */ + + qtype_naptr = 35, /**< NAPTR 35 Naming Authority Pointer */ + + qtype_opt = 41, /**< OPT 41 Option */ + + qtype_ipseckey = 45,/**< IPSECKEY 45 IPSEC Key */ + + qtype_spf = 99, /**< SPF 99 SPF record */ + + qtype_any = 255 /**< * 255 A request for all records (3.2.3. QTYPE values)*/ } tnet_dns_qtype_t; /** RFC 1035 - 3.2.4. CLASS values */ -typedef enum tnet_dns_qclass_e -{ - qclass_in = 1, /**< IN 1 the Internet */ - qclass_ics = 2, /**< CS 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ - qclass_ch = 3, /**< CH 3 the CHAOS class */ - qclass_hs = 4, /**< HS 4 Hesiod [Dyer 87] */ - - qclass_any = 255 /**< * 255 any class (3.2.5. QCLASS values) */ +typedef enum tnet_dns_qclass_e { + qclass_in = 1, /**< IN 1 the Internet */ + qclass_ics = 2, /**< CS 2 the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ + qclass_ch = 3, /**< CH 3 the CHAOS class */ + qclass_hs = 4, /**< HS 4 Hesiod [Dyer 87] */ + + qclass_any = 255 /**< * 255 any class (3.2.5. QCLASS values) */ } tnet_dns_qclass_t; -/** RFC 1034 (3.6. Resource Records) and 1035 (3.2.1. Format) +/** RFC 1034 (3.6. Resource Records) and 1035 (3.2.1. Format) */ -typedef struct tnet_dns_rr_s -{ - TSK_DECLARE_OBJECT; - - /* RFC 1035 - 3.2.1. Format - 1 1 1 1 1 1 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | | - / / - / NAME / - | | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | TYPE | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | CLASS | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | TTL | - | | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - | RDLENGTH | - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| - / RDATA / - / / - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - - tsk_bool_t initialized; - - /** An owner name, i.e., the name of the node to which this resource record pertains. */ - char* name; - - /** Two octets containing one of the RR TYPE codes. */ - tnet_dns_qtype_t qtype; - - /** Two octets containing one of the RR CLASS codes. */ - tnet_dns_qclass_t qclass; - - /** A 32 bit signed integer that specifies the time interval (seconds) that the resource record may be cached before the source - of the information should again be consulted. - Zero values are interpreted to mean that the RR can only be used for the transaction in progress, and should not be cached. - For example, SOA records are always distributed with a zero TTL to prohibit caching. Zero values can also be used for extremely volatile data. */ - int32_t ttl; - - /** An unsigned 16 bit integer that specifies the length in octets of the RDATA field. */ - uint16_t rdlength; - - /** A variable length string of octets that describes the resource. - The format of this information varies according to the TYPE and CLASS of the resource record.*/ - void *rpdata; +typedef struct tnet_dns_rr_s { + TSK_DECLARE_OBJECT; + + /* RFC 1035 - 3.2.1. Format + 1 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | | + / / + / NAME / + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + */ + + tsk_bool_t initialized; + + /** An owner name, i.e., the name of the node to which this resource record pertains. */ + char* name; + + /** Two octets containing one of the RR TYPE codes. */ + tnet_dns_qtype_t qtype; + + /** Two octets containing one of the RR CLASS codes. */ + tnet_dns_qclass_t qclass; + + /** A 32 bit signed integer that specifies the time interval (seconds) that the resource record may be cached before the source + of the information should again be consulted. + Zero values are interpreted to mean that the RR can only be used for the transaction in progress, and should not be cached. + For example, SOA records are always distributed with a zero TTL to prohibit caching. Zero values can also be used for extremely volatile data. */ + int32_t ttl; + + /** An unsigned 16 bit integer that specifies the length in octets of the RDATA field. */ + uint16_t rdlength; + + /** A variable length string of octets that describes the resource. + The format of this information varies according to the TYPE and CLASS of the resource record.*/ + void *rpdata; } tnet_dns_rr_t; diff --git a/tinyNET/src/dns/tnet_dns_soa.c b/tinyNET/src/dns/tnet_dns_soa.c index a1844f4..8aefc5f 100755 --- a/tinyNET/src/dns/tnet_dns_soa.c +++ b/tinyNET/src/dns/tnet_dns_soa.c @@ -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. * @@ -36,7 +36,7 @@ tnet_dns_soa_t* tnet_dns_soa_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_soa_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_soa_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -44,65 +44,64 @@ tnet_dns_soa_t* tnet_dns_soa_create(const char* name, tnet_dns_qclass_t qclass, // static tsk_object_t* tnet_dns_soa_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_soa_t *soa = self; - if(soa){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_soa_t *soa = self; + if(soa) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(soa), qtype_soa, qclass); - TNET_DNS_RR(soa)->name = tsk_strdup(name); - TNET_DNS_RR(soa)->rdlength = rdlength; - TNET_DNS_RR(soa)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(soa), qtype_soa, qclass); + TNET_DNS_RR(soa)->name = tsk_strdup(name); + TNET_DNS_RR(soa)->rdlength = rdlength; + TNET_DNS_RR(soa)->ttl = ttl; - if(rdlength) - { // ==> DESERIALIZATION - /* MNAME */ - tnet_dns_rr_qname_deserialize(data, &(soa->mname), &offset); - /* RNAME */ - tnet_dns_rr_qname_deserialize(data, &(soa->rname), &offset); - /* SERIAL */ - soa->serial = tnet_htonl_2(((uint8_t*)data) + offset), - offset += 2; - /* REFRESH */ - soa->refresh = tnet_htonl_2(((uint8_t*)data) + offset), - offset += 2; - /* RETRY */ - soa->retry = tnet_htonl_2(((uint8_t*)data) + offset), - offset += 2; - /* EXPIRE */ - soa->expire = tnet_htonl_2(((uint8_t*)data) + offset), - offset += 2; - /* MINIMUM */ - soa->minimum = tnet_htonl_2(((uint8_t*)data) + offset), - offset += 2; - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* MNAME */ + tnet_dns_rr_qname_deserialize(data, &(soa->mname), &offset); + /* RNAME */ + tnet_dns_rr_qname_deserialize(data, &(soa->rname), &offset); + /* SERIAL */ + soa->serial = tnet_htonl_2(((uint8_t*)data) + offset), + offset += 2; + /* REFRESH */ + soa->refresh = tnet_htonl_2(((uint8_t*)data) + offset), + offset += 2; + /* RETRY */ + soa->retry = tnet_htonl_2(((uint8_t*)data) + offset), + offset += 2; + /* EXPIRE */ + soa->expire = tnet_htonl_2(((uint8_t*)data) + offset), + offset += 2; + /* MINIMUM */ + soa->minimum = tnet_htonl_2(((uint8_t*)data) + offset), + offset += 2; + } + } + return self; } -static tsk_object_t* tnet_dns_soa_dtor(tsk_object_t * self) -{ - tnet_dns_soa_t *soa = self; - if(soa){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(soa)); +static tsk_object_t* tnet_dns_soa_dtor(tsk_object_t * self) +{ + tnet_dns_soa_t *soa = self; + if(soa) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(soa)); - TSK_FREE(soa->mname); - TSK_FREE(soa->rname); - } - return self; + TSK_FREE(soa->mname); + TSK_FREE(soa->rname); + } + return self; } -static const tsk_object_def_t tnet_dns_soa_def_s = -{ - sizeof(tnet_dns_soa_t), - tnet_dns_soa_ctor, - tnet_dns_soa_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_soa_def_s = { + sizeof(tnet_dns_soa_t), + tnet_dns_soa_ctor, + tnet_dns_soa_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_soa_def_t = &tnet_dns_soa_def_s; diff --git a/tinyNET/src/dns/tnet_dns_soa.h b/tinyNET/src/dns/tnet_dns_soa.h index 298e907..9faea75 100755 --- a/tinyNET/src/dns/tnet_dns_soa.h +++ b/tinyNET/src/dns/tnet_dns_soa.h @@ -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. * @@ -35,12 +35,11 @@ TNET_BEGIN_DECLS -typedef struct tnet_dns_soa_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_soa_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.3.13. SOA RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.3.13. SOA RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / MNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ @@ -61,14 +60,14 @@ typedef struct tnet_dns_soa_s | MINIMUM | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* mname; - char* rname; - uint32_t serial; - uint32_t refresh; - uint32_t retry; - uint32_t expire; - uint32_t minimum; + */ + char* mname; + char* rname; + uint32_t serial; + uint32_t refresh; + uint32_t retry; + uint32_t expire; + uint32_t minimum; } tnet_dns_soa_t; diff --git a/tinyNET/src/dns/tnet_dns_srv.c b/tinyNET/src/dns/tnet_dns_srv.c index 4625d68..852bda0 100755 --- a/tinyNET/src/dns/tnet_dns_srv.c +++ b/tinyNET/src/dns/tnet_dns_srv.c @@ -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. * @@ -38,7 +38,7 @@ */ tnet_dns_srv_t* tnet_dns_srv_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_srv_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_srv_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -46,88 +46,87 @@ tnet_dns_srv_t* tnet_dns_srv_create(const char* name, tnet_dns_qclass_t qclass, // static tsk_object_t* tnet_dns_srv_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_srv_t *srv = self; - if(srv){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_srv_t *srv = self; + if(srv) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(srv), qtype_srv, qclass); - TNET_DNS_RR(srv)->name = tsk_strdup(name); - TNET_DNS_RR(srv)->rdlength = rdlength; - TNET_DNS_RR(srv)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(srv), qtype_srv, qclass); + TNET_DNS_RR(srv)->name = tsk_strdup(name); + TNET_DNS_RR(srv)->rdlength = rdlength; + TNET_DNS_RR(srv)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* Priority */ - srv->priority = tnet_ntohs_2(((uint8_t*)data) + offset), - offset += 2; - /* Weight */ - srv->weight = tnet_ntohs_2(((uint8_t*)data) + offset), - offset += 2; - /* Port */ - srv->port = tnet_ntohs_2(((uint8_t*)data) + offset), - offset += 2; - /* Target */ - tnet_dns_rr_qname_deserialize(data, &(srv->target), &offset); - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* Priority */ + srv->priority = tnet_ntohs_2(((uint8_t*)data) + offset), + offset += 2; + /* Weight */ + srv->weight = tnet_ntohs_2(((uint8_t*)data) + offset), + offset += 2; + /* Port */ + srv->port = tnet_ntohs_2(((uint8_t*)data) + offset), + offset += 2; + /* Target */ + tnet_dns_rr_qname_deserialize(data, &(srv->target), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_srv_dtor(tsk_object_t * self) -{ - tnet_dns_srv_t *srv = self; - if(srv){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(srv)); +static tsk_object_t* tnet_dns_srv_dtor(tsk_object_t * self) +{ + tnet_dns_srv_t *srv = self; + if(srv) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(srv)); - TSK_FREE(srv->target); - } - return self; + TSK_FREE(srv->target); + } + return self; } static int tnet_dns_srv_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2) -{ - const tnet_dns_rr_t* rr1 = obj1; - const tnet_dns_rr_t* rr2 = obj2; +{ + const tnet_dns_rr_t* rr1 = obj1; + const tnet_dns_rr_t* rr2 = obj2; + + if(rr1 && rr2 && (rr1->qtype==qtype_srv) && (rr2->qtype==qtype_srv)) { + const tnet_dns_srv_t* srv1 = (tnet_dns_srv_t*)rr1; + const tnet_dns_srv_t* srv2 = (tnet_dns_srv_t*)rr2; - if(rr1 && rr2 && (rr1->qtype==qtype_srv) && (rr2->qtype==qtype_srv)){ - const tnet_dns_srv_t* srv1 = (tnet_dns_srv_t*)rr1; - const tnet_dns_srv_t* srv2 = (tnet_dns_srv_t*)rr2; + /* Compare priorities. */ + if(srv1->priority < srv2->priority) { /* Lowest priority is tried first. */ + return 1; + } + else if(srv1->priority > srv2->priority) { + return -1; + } - /* Compare priorities. */ - if(srv1->priority < srv2->priority){ /* Lowest priority is tried first. */ - return 1; - } - else if(srv1->priority > srv2->priority){ - return -1; - } + /* Compare weight */ + if(srv1->weight > srv2->weight) { + return 1; + } + else if(srv1->weight < srv2->weight) { + return -1; + } - /* Compare weight */ - if(srv1->weight > srv2->weight){ - return 1; - } - else if(srv1->weight < srv2->weight){ - return -1; - } - - return 0; - } - else{ - return -1; - } + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_dns_srv_def_s = -{ - sizeof(tnet_dns_srv_t), - tnet_dns_srv_ctor, - tnet_dns_srv_dtor, - tnet_dns_srv_cmp, +static const tsk_object_def_t tnet_dns_srv_def_s = { + sizeof(tnet_dns_srv_t), + tnet_dns_srv_ctor, + tnet_dns_srv_dtor, + tnet_dns_srv_cmp, }; const tsk_object_def_t *tnet_dns_srv_def_t = &tnet_dns_srv_def_s; diff --git a/tinyNET/src/dns/tnet_dns_srv.h b/tinyNET/src/dns/tnet_dns_srv.h index c8cc94d..7a3dc83 100755 --- a/tinyNET/src/dns/tnet_dns_srv.h +++ b/tinyNET/src/dns/tnet_dns_srv.h @@ -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. * @@ -38,14 +38,13 @@ TNET_BEGIN_DECLS /** DNS SRV Resource Record */ -typedef struct tnet_dns_srv_s -{ - TNET_DECLARE_DNS_RR; - - uint16_t priority; - uint16_t weight; - uint16_t port; - char* target; +typedef struct tnet_dns_srv_s { + TNET_DECLARE_DNS_RR; + + uint16_t priority; + uint16_t weight; + uint16_t port; + char* target; } tnet_dns_srv_t; diff --git a/tinyNET/src/dns/tnet_dns_txt.c b/tinyNET/src/dns/tnet_dns_txt.c index 9d152e9..3a76d9b 100755 --- a/tinyNET/src/dns/tnet_dns_txt.c +++ b/tinyNET/src/dns/tnet_dns_txt.c @@ -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. * @@ -38,7 +38,7 @@ tnet_dns_txt_t* tnet_dns_txt_create(const char* name, tnet_dns_qclass_t qclass, uint32_t ttl, uint16_t rdlength, const void* data, tsk_size_t offset) { - return tsk_object_new(tnet_dns_txt_def_t, name, qclass, ttl, rdlength, data, offset); + return tsk_object_new(tnet_dns_txt_def_t, name, qclass, ttl, rdlength, data, offset); } //================================================================================================= @@ -46,47 +46,46 @@ tnet_dns_txt_t* tnet_dns_txt_create(const char* name, tnet_dns_qclass_t qclass, // static tsk_object_t* tnet_dns_txt_ctor(tsk_object_t * self, va_list * app) { - tnet_dns_txt_t *txt = self; - if(txt){ - const char* name = va_arg(*app, const char*); - tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); - uint32_t ttl = va_arg(*app, uint32_t); - uint16_t rdlength = tsk_va_arg_u16(*app); - const void* data = va_arg(*app, const void*); - tsk_size_t offset = va_arg(*app, tsk_size_t); + tnet_dns_txt_t *txt = self; + if(txt) { + const char* name = va_arg(*app, const char*); + tnet_dns_qclass_t qclass = va_arg(*app, tnet_dns_qclass_t); + uint32_t ttl = va_arg(*app, uint32_t); + uint16_t rdlength = tsk_va_arg_u16(*app); + const void* data = va_arg(*app, const void*); + tsk_size_t offset = va_arg(*app, tsk_size_t); - /* init base */ - tnet_dns_rr_init(TNET_DNS_RR(txt), qtype_txt, qclass); - TNET_DNS_RR(txt)->name = tsk_strdup(name); - TNET_DNS_RR(txt)->rdlength = rdlength; - TNET_DNS_RR(txt)->ttl = ttl; + /* init base */ + tnet_dns_rr_init(TNET_DNS_RR(txt), qtype_txt, qclass); + TNET_DNS_RR(txt)->name = tsk_strdup(name); + TNET_DNS_RR(txt)->rdlength = rdlength; + TNET_DNS_RR(txt)->ttl = ttl; - if(rdlength){ - // ==> DESERIALIZATION - /* TXT-DATA */ - tnet_dns_rr_charstring_deserialize(data, &(txt->txt_data), &offset); - } - } - return self; + if(rdlength) { + // ==> DESERIALIZATION + /* TXT-DATA */ + tnet_dns_rr_charstring_deserialize(data, &(txt->txt_data), &offset); + } + } + return self; } -static tsk_object_t* tnet_dns_txt_dtor(tsk_object_t * self) -{ - tnet_dns_txt_t *txt = self; - if(txt){ - /* deinit base */ - tnet_dns_rr_deinit(TNET_DNS_RR(txt)); +static tsk_object_t* tnet_dns_txt_dtor(tsk_object_t * self) +{ + tnet_dns_txt_t *txt = self; + if(txt) { + /* deinit base */ + tnet_dns_rr_deinit(TNET_DNS_RR(txt)); - TSK_FREE(txt->txt_data); - } - return self; + TSK_FREE(txt->txt_data); + } + return self; } -static const tsk_object_def_t tnet_dns_txt_def_s = -{ - sizeof(tnet_dns_txt_t), - tnet_dns_txt_ctor, - tnet_dns_txt_dtor, - tsk_null, +static const tsk_object_def_t tnet_dns_txt_def_s = { + sizeof(tnet_dns_txt_t), + tnet_dns_txt_ctor, + tnet_dns_txt_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dns_txt_def_t = &tnet_dns_txt_def_s; diff --git a/tinyNET/src/dns/tnet_dns_txt.h b/tinyNET/src/dns/tnet_dns_txt.h index 05f54d9..0bac6c7 100755 --- a/tinyNET/src/dns/tnet_dns_txt.h +++ b/tinyNET/src/dns/tnet_dns_txt.h @@ -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. * @@ -38,16 +38,15 @@ TNET_BEGIN_DECLS /** DNS TXT Resource Record */ -typedef struct tnet_dns_txt_s -{ - TNET_DECLARE_DNS_RR; +typedef struct tnet_dns_txt_s { + TNET_DECLARE_DNS_RR; - /* RFC 1035 - 3.3.14. TXT RDATA format - +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + /* RFC 1035 - 3.3.14. TXT RDATA format + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ / TXT-DATA / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ - */ - char* txt_data; + */ + char* txt_data; } tnet_dns_txt_t; diff --git a/tinyNET/src/ice/tnet_ice.c b/tinyNET/src/ice/tnet_ice.c index 196009b..1252ff6 100755 --- a/tinyNET/src/ice/tnet_ice.c +++ b/tinyNET/src/ice/tnet_ice.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2010-2015 Mamadou DIOP -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyNET/src/ice/tnet_ice.h b/tinyNET/src/ice/tnet_ice.h index daffd08..53f9d22 100755 --- a/tinyNET/src/ice/tnet_ice.h +++ b/tinyNET/src/ice/tnet_ice.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2010-2015 Mamadou DIOP -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyNET/src/ice/tnet_ice_candidate.c b/tinyNET/src/ice/tnet_ice_candidate.c index bb75b33..7900933 100755 --- a/tinyNET/src/ice/tnet_ice_candidate.c +++ b/tinyNET/src/ice/tnet_ice_candidate.c @@ -34,15 +34,15 @@ #include <ctype.h> static int _tnet_ice_candidate_tostring( - uint8_t* foundation, - uint32_t comp_id, - const char* transport_str, - uint32_t priority, - const char* connection_addr, - tnet_port_t port, - const char* cand_type_str, - const tsk_params_L_t *extension_att_list, - char** output); + uint8_t* foundation, + uint32_t comp_id, + const char* transport_str, + uint32_t priority, + const char* connection_addr, + tnet_port_t port, + const char* cand_type_str, + const tsk_params_L_t *extension_att_list, + char** output); static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type); static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_candidate_t* self, const char* username, const char* password); static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_transac_id_t id1, const tnet_stun_transac_id_t id2); @@ -54,7 +54,7 @@ static tnet_ice_cand_type_t _tnet_ice_candtype_get_transport_type(const char* ca static tsk_object_t* tnet_ice_candidate_ctor(tsk_object_t * self, va_list * app) { tnet_ice_candidate_t *candidate = self; - if (candidate){ + if (candidate) { candidate->extension_att_list = tsk_list_create(); } return self; @@ -63,23 +63,23 @@ static tsk_object_t* tnet_ice_candidate_ctor(tsk_object_t * self, va_list * app) static tsk_object_t* tnet_ice_candidate_dtor(tsk_object_t * self) { tnet_ice_candidate_t *candidate = self; - if (candidate){ + if (candidate) { TSK_SAFE_FREE(candidate->transport_str); TSK_SAFE_FREE(candidate->cand_type_str); TSK_OBJECT_SAFE_FREE(candidate->extension_att_list); TSK_OBJECT_SAFE_FREE(candidate->socket); - - + + TSK_SAFE_FREE(candidate->stun.nonce); TSK_SAFE_FREE(candidate->stun.realm); TSK_SAFE_FREE(candidate->stun.srflx_addr); - + TSK_SAFE_FREE(candidate->turn.relay_addr); TSK_OBJECT_SAFE_FREE(candidate->turn.ss); - + TSK_SAFE_FREE(candidate->ufrag); TSK_SAFE_FREE(candidate->pwd); - + TSK_SAFE_FREE(candidate->tostring); } return self; @@ -89,16 +89,19 @@ static int tnet_ice_candidate_cmp(const tsk_object_t *_s1, const tsk_object_t *_ { const tnet_ice_candidate_t *c1 = _s1; const tnet_ice_candidate_t *c2 = _s2; - - if (c1 && c2){ + + if (c1 && c2) { return (int)(c1->priority - c2->priority); } - else if (!c1 && !c2) return 0; - else return -1; + else if (!c1 && !c2) { + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_ice_candidate_def_s = -{ +static const tsk_object_def_t tnet_ice_candidate_def_s = { sizeof(tnet_ice_candidate_t), tnet_ice_candidate_ctor, tnet_ice_candidate_dtor, @@ -108,12 +111,12 @@ static const tsk_object_def_t tnet_ice_candidate_def_s = tnet_ice_candidate_t* tnet_ice_candidate_create(tnet_ice_cand_type_t type_e, tnet_socket_t* socket, tsk_bool_t is_ice_jingle, tsk_bool_t is_rtp, tsk_bool_t is_video, const char* ufrag, const char* pwd, const char *foundation) { tnet_ice_candidate_t* candidate; - - if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))){ + + if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))) { TSK_DEBUG_ERROR("Failed to create candidate"); return tsk_null; } - + candidate->type_e = type_e; candidate->socket = tsk_object_ref(socket); candidate->local_pref = 0xFFFF; @@ -121,20 +124,20 @@ tnet_ice_candidate_t* tnet_ice_candidate_create(tnet_ice_cand_type_t type_e, tne candidate->is_rtp = is_rtp; candidate->is_video = is_video; candidate->comp_id = is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP; - if (foundation){ + if (foundation) { memcpy(candidate->foundation, foundation, TSK_MIN(tsk_strlen(foundation), TNET_ICE_CANDIDATE_FOUND_SIZE_PREF)); } - else{ + else { tnet_ice_utils_compute_foundation((char*)candidate->foundation, TSK_MIN(sizeof(candidate->foundation), TNET_ICE_CANDIDATE_FOUND_SIZE_PREF)); } candidate->priority = tnet_ice_utils_get_priority(candidate->type_e, candidate->local_pref, candidate->is_rtp); - if (candidate->socket){ + if (candidate->socket) { memcpy(candidate->connection_addr, candidate->socket->ip, sizeof(candidate->socket->ip)); candidate->port = candidate->socket->port; candidate->transport_e = socket->type; } tnet_ice_candidate_set_credential(candidate, ufrag, pwd); - + return candidate; } @@ -144,104 +147,96 @@ tnet_ice_candidate_t* tnet_ice_candidate_parse(const char* str) char *v, *copy, *saveptr; int32_t k; tnet_ice_candidate_t* candidate; - - if (tsk_strnullORempty(str)){ + + if (tsk_strnullORempty(str)) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - - if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))){ + + if (!(candidate = tsk_object_new(&tnet_ice_candidate_def_s))) { TSK_DEBUG_ERROR("Failed to create candidate"); return tsk_null; } - + k = 0; copy = tsk_strdup(str); v = tsk_strtok_r(copy, " ", &saveptr); - - while (v){ - switch (k){ - case 0: - { - memcpy(candidate->foundation, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->foundation))); - break; - } - case 1: - { - candidate->comp_id = atoi(v); - break; - } - case 2: - { - candidate->transport_str = tsk_strdup(v); - break; - } - case 3: - { - candidate->priority = atoi(v); - break; - } - case 4: - { - memcpy(candidate->connection_addr, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->connection_addr))); - break; - } - case 5: - { - tnet_family_t family; - candidate->port = atoi(v); - family = tnet_get_family(candidate->connection_addr, candidate->port); - candidate->transport_e = _tnet_ice_candidate_get_transport_type((family == AF_INET6), candidate->transport_str); - break; - } - case 6: - { - v = tsk_strtok_r(tsk_null, " ", &saveptr); - tsk_strupdate(&candidate->cand_type_str, v); - candidate->type_e = _tnet_ice_candtype_get_transport_type(v); - break; - } - default: - { - const char* name = v; - const char* value = (v = tsk_strtok_r(tsk_null, " ", &saveptr)); - tsk_param_t* param = tsk_param_create(name, value); - if (param){ - tsk_list_push_back_data(candidate->extension_att_list, (void**)¶m); - } - break; + + while (v) { + switch (k) { + case 0: { + memcpy(candidate->foundation, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->foundation))); + break; + } + case 1: { + candidate->comp_id = atoi(v); + break; + } + case 2: { + candidate->transport_str = tsk_strdup(v); + break; + } + case 3: { + candidate->priority = atoi(v); + break; + } + case 4: { + memcpy(candidate->connection_addr, v, TSK_MIN(tsk_strlen(v), sizeof(candidate->connection_addr))); + break; + } + case 5: { + tnet_family_t family; + candidate->port = atoi(v); + family = tnet_get_family(candidate->connection_addr, candidate->port); + candidate->transport_e = _tnet_ice_candidate_get_transport_type((family == AF_INET6), candidate->transport_str); + break; + } + case 6: { + v = tsk_strtok_r(tsk_null, " ", &saveptr); + tsk_strupdate(&candidate->cand_type_str, v); + candidate->type_e = _tnet_ice_candtype_get_transport_type(v); + break; + } + default: { + const char* name = v; + const char* value = (v = tsk_strtok_r(tsk_null, " ", &saveptr)); + tsk_param_t* param = tsk_param_create(name, value); + if (param) { + tsk_list_push_back_data(candidate->extension_att_list, (void**)¶m); } + break; + } } - + ++k; v = tsk_strtok_r(tsk_null, " ", &saveptr); } - - if (k < 6){ + + if (k < 6) { TSK_DEBUG_ERROR("Failed to parse: %s", str); TSK_OBJECT_SAFE_FREE(candidate); } TSK_FREE(copy); - + return candidate; } int tnet_ice_candidate_set_credential(tnet_ice_candidate_t* self, const char* ufrag, const char* pwd) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + tsk_strupdate(&self->ufrag, ufrag); tsk_strupdate(&self->pwd, pwd); - + return 0; } int tnet_ice_candidate_set_rflx_addr(tnet_ice_candidate_t* self, const char* addr, tnet_port_t port) { - if (!self || !addr || !port){ + if (!self || !addr || !port) { TSK_DEBUG_ERROR("Invalid argument"); return -1; } @@ -253,7 +248,7 @@ int tnet_ice_candidate_set_rflx_addr(tnet_ice_candidate_t* self, const char* add const char* tnet_ice_candidate_get_att_value(const tnet_ice_candidate_t* self, const char* att_name) { - if (!self || !att_name){ + if (!self || !att_name) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } @@ -262,7 +257,7 @@ const char* tnet_ice_candidate_get_att_value(const tnet_ice_candidate_t* self, c int tnet_ice_candidate_set_local_pref(tnet_ice_candidate_t* self, uint16_t local_pref) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -275,12 +270,12 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self) { const char* _transport_str; char __str[255]; // always allocated: bad idea :( - - if (!self){ + + if (!self) { TSK_DEBUG_ERROR("Invalid argument"); return tsk_null; } - + if (self->type_e == tnet_ice_cand_type_relay && self->turn.ss) { enum tnet_turn_transport_e e_req_transport = tnet_turn_transport_udp; tnet_turn_session_get_req_transport(self->turn.ss, &e_req_transport); @@ -288,47 +283,45 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self) } else { _transport_str = self->transport_str ? self->transport_str : _tnet_ice_candidate_get_transport_str(self->transport_e); - if (self->is_ice_jingle){ + if (self->is_ice_jingle) { tsk_size_t i, s = tsk_strlen(_transport_str); memset(__str, 0, sizeof(__str)); - for (i = 0; i < s && i < sizeof(__str) / sizeof(__str[0]); ++i){ + for (i = 0; i < s && i < sizeof(__str) / sizeof(__str[0]); ++i) { __str[i] = tolower(_transport_str[i]); } _transport_str = &__str[0]; } } - + _tnet_ice_candidate_tostring( - self->foundation, - self->comp_id, - _transport_str, - self->priority, - (tsk_strnullORempty(self->connection_addr) && self->socket) ? self->socket->ip : self->connection_addr, - (self->port <= 0 && self->socket) ? self->socket->port : self->port, - self->cand_type_str ? self->cand_type_str : _tnet_ice_candidate_get_candtype_str(self->type_e), - self->extension_att_list, - &self->tostring); - + self->foundation, + self->comp_id, + _transport_str, + self->priority, + (tsk_strnullORempty(self->connection_addr) && self->socket) ? self->socket->ip : self->connection_addr, + (self->port <= 0 && self->socket) ? self->socket->port : self->port, + self->cand_type_str ? self->cand_type_str : _tnet_ice_candidate_get_candtype_str(self->type_e), + self->extension_att_list, + &self->tostring); + /* <rel-addr> and <rel-port>: convey transport addresses related to the candidate, useful for diagnostics and other purposes. <rel-addr> and <rel-port> MUST be present for server reflexive, peer reflexive, and relayed candidates. */ - switch (self->type_e){ - case tnet_ice_cand_type_srflx: - case tnet_ice_cand_type_prflx: - case tnet_ice_cand_type_relay: - { - if (self->socket){ // when called from the browser(IE, Safari, Opera or Firefox) webrtc4all - tsk_strcat_2(&self->tostring, " raddr %s rport %d", self->socket->ip, self->socket->port); - } - break; - } - default: - { - break; + switch (self->type_e) { + case tnet_ice_cand_type_srflx: + case tnet_ice_cand_type_prflx: + case tnet_ice_cand_type_relay: { + if (self->socket) { // when called from the browser(IE, Safari, Opera or Firefox) webrtc4all + tsk_strcat_2(&self->tostring, " raddr %s rport %d", self->socket->ip, self->socket->port); } + break; } - + default: { + break; + } + } + // To ease debugging if (self->socket) { tsk_strcat_2(&self->tostring, " tr %s", _tnet_ice_candidate_get_transport_str(self->socket->type)); @@ -343,26 +336,26 @@ const char* tnet_ice_candidate_tostring(tnet_ice_candidate_t* self) tsk_strcat_2(&self->tostring, " fd %d", self->socket->fd); } } - + // WebRTC (Chrome) specific if (self->is_ice_jingle) { - if (!tsk_params_have_param(self->extension_att_list, "name")){ + if (!tsk_params_have_param(self->extension_att_list, "name")) { tsk_strcat_2(&self->tostring, " name %s", self->is_rtp ? (self->is_video ? "video_rtp" : "rtp") : (self->is_video ? "video_rtcp" : "rtcp")); } - if (!tsk_params_have_param(self->extension_att_list, "username")){ + if (!tsk_params_have_param(self->extension_att_list, "username")) { tsk_strcat_2(&self->tostring, " username %s", self->ufrag); } - if (!tsk_params_have_param(self->extension_att_list, "password")){ + if (!tsk_params_have_param(self->extension_att_list, "password")) { tsk_strcat_2(&self->tostring, " password %s", self->pwd); } - if (!tsk_params_have_param(self->extension_att_list, "network_name")){ + if (!tsk_params_have_param(self->extension_att_list, "network_name")) { tsk_strcat_2(&self->tostring, " network_name %s", "{9EBBE687-CCE6-42D3-87F5-B57BB30DEE23}"); } - if (!tsk_params_have_param(self->extension_att_list, "generation")){ + if (!tsk_params_have_param(self->extension_att_list, "generation")) { tsk_strcat_2(&self->tostring, " generation %s", "0"); } } - + return self->tostring; } @@ -371,56 +364,56 @@ int tnet_ice_candidate_send_stun_bind_request(tnet_ice_candidate_t* self, const tnet_stun_pkt_t *request = tsk_null; tsk_buffer_t *buffer = tsk_null; int ret, sendBytes; - - if (!self || !server_addr || !TNET_SOCKET_IS_VALID(self->socket)){ + + if (!self || !server_addr || !TNET_SOCKET_IS_VALID(self->socket)) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + request = _tnet_ice_candidate_stun_create_bind_request(self, username, password); - if (!request){ + if (!request) { TSK_DEBUG_ERROR("Failed to create STUN request"); ret = -2; goto bail; } - - if ((ret = tnet_stun_pkt_write_with_padding_2(request, &buffer))){ + + if ((ret = tnet_stun_pkt_write_with_padding_2(request, &buffer))) { TSK_DEBUG_ERROR("Failed to serialize STUN request"); goto bail; } - + sendBytes = tnet_sockfd_sendto(self->socket->fd, (const struct sockaddr*)server_addr, buffer->data, buffer->size);// return number of sent bytes - if (sendBytes == buffer->size){ + if (sendBytes == buffer->size) { memcpy(self->stun.transac_id, request->transac_id, sizeof(tnet_stun_transac_id_t)); ret = 0; } - else{ + else { TSK_DEBUG_ERROR("Only %d bytes sent", sendBytes); ret = -4; goto bail; } - + bail: TSK_OBJECT_SAFE_FREE(request); TSK_OBJECT_SAFE_FREE(buffer); - + return 0; } int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const tnet_stun_pkt_resp_t* response, tnet_fd_t fd) { int ret = 0; - - if (!self || !response){ + + if (!self || !response) { TSK_DEBUG_ERROR("Inavlid parameter"); return -1; } - + //if(!(_tnet_ice_candidate_stun_transac_id_equals(response->transac_id, self->stun.transac_id))){ // TSK_DEBUG_ERROR("Transaction id mismatch"); // return -2; //} - + if (TNET_STUN_PKT_RESP_IS_ERROR(response)) { uint16_t u_code; if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code))) { @@ -452,7 +445,7 @@ int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const t else if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) { const tnet_stun_attr_address_t* pc_attr_addr; if (((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr) - || ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)) { + || ((ret = tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr)) { tnet_ip_t ip; if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip))) { return ret; @@ -461,7 +454,7 @@ int tnet_ice_candidate_process_stun_response(tnet_ice_candidate_t* self, const t self->stun.srflx_port = pc_attr_addr->u_port; } } - + return ret; } @@ -470,7 +463,7 @@ const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_ if (candidates) { const tsk_list_item_t *item; const tnet_ice_candidate_t* candidate; - + tsk_list_lock(candidates); tsk_list_foreach(item, candidates) { if (!(candidate = item->data)) { @@ -482,13 +475,13 @@ const tnet_ice_candidate_t* tnet_ice_candidate_find_by_fd(tnet_ice_candidates_L_ } } } - + return tsk_null; } const char* tnet_ice_candidate_get_ufrag(const tnet_ice_candidate_t* self) { - if (self){ + if (self) { return self->ufrag ? self->ufrag : tnet_ice_candidate_get_att_value(self, "username"); } return tsk_null; @@ -496,22 +489,22 @@ const char* tnet_ice_candidate_get_ufrag(const tnet_ice_candidate_t* self) const char* tnet_ice_candidate_get_pwd(const tnet_ice_candidate_t* self) { - if (self){ + if (self) { return self->pwd ? self->pwd : tnet_ice_candidate_get_att_value(self, "password"); } return tsk_null; } static int _tnet_ice_candidate_tostring( - uint8_t* foundation, - uint32_t comp_id, - const char* transport_str, - uint32_t priority, - const char* connection_addr, - tnet_port_t port, - const char* cand_type_str, - const tsk_params_L_t *extension_att_list, - char** output) + uint8_t* foundation, + uint32_t comp_id, + const char* transport_str, + uint32_t priority, + const char* connection_addr, + tnet_port_t port, + const char* cand_type_str, + const tsk_params_L_t *extension_att_list, + char** output) { if (!output) { TSK_DEBUG_ERROR("Invalid argument"); @@ -525,10 +518,10 @@ static int _tnet_ice_candidate_tostring( connection_addr, port, cand_type_str); - + if (extension_att_list) { const tsk_list_item_t *item; - tsk_list_foreach(item, extension_att_list){ + tsk_list_foreach(item, extension_att_list) { tsk_strcat_2(output, " %s %s", TSK_PARAM(item->data)->name, TSK_PARAM(item->data)->value); } } @@ -537,11 +530,16 @@ static int _tnet_ice_candidate_tostring( static const char* _tnet_ice_candidate_get_foundation(tnet_ice_cand_type_t type) { - switch (type){ - case tnet_ice_cand_type_host: return TNET_ICE_CANDIDATE_FOUNDATION_HOST; - case tnet_ice_cand_type_srflx: return TNET_ICE_CANDIDATE_FOUNDATION_SRFLX; - case tnet_ice_cand_type_prflx: return TNET_ICE_CANDIDATE_FOUNDATION_PRFLX; - case tnet_ice_cand_type_relay: default: return TNET_ICE_CANDIDATE_FOUNDATION_RELAY; + switch (type) { + case tnet_ice_cand_type_host: + return TNET_ICE_CANDIDATE_FOUNDATION_HOST; + case tnet_ice_cand_type_srflx: + return TNET_ICE_CANDIDATE_FOUNDATION_SRFLX; + case tnet_ice_cand_type_prflx: + return TNET_ICE_CANDIDATE_FOUNDATION_PRFLX; + case tnet_ice_cand_type_relay: + default: + return TNET_ICE_CANDIDATE_FOUNDATION_RELAY; } } @@ -550,8 +548,8 @@ static tsk_bool_t _tnet_ice_candidate_stun_transac_id_equals(const tnet_stun_tra { tsk_size_t i; static const tsk_size_t size = sizeof(tnet_stun_transac_id_t); - for (i = 0; i < size; i++){ - if (id1[i] != id2[i]){ + for (i = 0; i < size; i++) { + if (id1[i] != id2[i]) { return tsk_false; } } @@ -562,12 +560,12 @@ static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_c { tnet_stun_pkt_t *request = tsk_null; int ret; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &request))) { TSK_DEBUG_ERROR("Failed to create STUN Bind request"); goto bail; @@ -585,7 +583,7 @@ static tnet_stun_pkt_t * _tnet_ice_candidate_stun_create_bind_request(tnet_ice_c goto bail; } } - + bail: if (ret) { TSK_OBJECT_SAFE_FREE(request); @@ -606,7 +604,7 @@ return TNET_ICE_CANDIDATE_TRANSPORT_##STR; \ TRANSPORT_GET(WS); TRANSPORT_GET(WSS); return "UNKNOWN"; - + #undef TRANSPORT_GET } @@ -616,7 +614,7 @@ static tnet_socket_type_t _tnet_ice_candidate_get_transport_type(tsk_bool_t ipv6 if(tsk_striequals(TNET_ICE_CANDIDATE_TRANSPORT_##STR, transport_str)){ \ return tnet_socket_type_##str##_ipv4; \ } - + TRANSPORT_GET(UDP, udp); TRANSPORT_GET(TCP, tcp); TRANSPORT_GET(TLS, tls); @@ -624,37 +622,42 @@ return tnet_socket_type_##str##_ipv4; \ TRANSPORT_GET(WS, ws); TRANSPORT_GET(WSS, wss); return tnet_socket_type_invalid; - + #undef TRANSPORT_GET } static const char* _tnet_ice_candidate_get_candtype_str(tnet_ice_cand_type_t candtype_e) { - switch (candtype_e){ - case tnet_ice_cand_type_unknown: - default: return "unknown"; - case tnet_ice_cand_type_host: return TNET_ICE_CANDIDATE_TYPE_HOST; - case tnet_ice_cand_type_srflx: return TNET_ICE_CANDIDATE_TYPE_SRFLX; - case tnet_ice_cand_type_prflx: return TNET_ICE_CANDIDATE_TYPE_PRFLX; - case tnet_ice_cand_type_relay: return TNET_ICE_CANDIDATE_TYPE_RELAY; + switch (candtype_e) { + case tnet_ice_cand_type_unknown: + default: + return "unknown"; + case tnet_ice_cand_type_host: + return TNET_ICE_CANDIDATE_TYPE_HOST; + case tnet_ice_cand_type_srflx: + return TNET_ICE_CANDIDATE_TYPE_SRFLX; + case tnet_ice_cand_type_prflx: + return TNET_ICE_CANDIDATE_TYPE_PRFLX; + case tnet_ice_cand_type_relay: + return TNET_ICE_CANDIDATE_TYPE_RELAY; } } static tnet_ice_cand_type_t _tnet_ice_candtype_get_transport_type(const char* candtype_str) { - if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_HOST, candtype_str)){ + if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_HOST, candtype_str)) { return tnet_ice_cand_type_host; } - else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_SRFLX, candtype_str)){ + else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_SRFLX, candtype_str)) { return tnet_ice_cand_type_srflx; } - else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_PRFLX, candtype_str)){ + else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_PRFLX, candtype_str)) { return tnet_ice_cand_type_prflx; } - else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_RELAY, candtype_str)){ + else if (tsk_striequals(TNET_ICE_CANDIDATE_TYPE_RELAY, candtype_str)) { return tnet_ice_cand_type_relay; } - else{ + else { return tnet_ice_cand_type_unknown; } } diff --git a/tinyNET/src/ice/tnet_ice_candidate.h b/tinyNET/src/ice/tnet_ice_candidate.h index d2cb126..749192d 100755 --- a/tinyNET/src/ice/tnet_ice_candidate.h +++ b/tinyNET/src/ice/tnet_ice_candidate.h @@ -8,12 +8,12 @@ * 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. * @@ -59,54 +59,52 @@ TNET_BEGIN_DECLS #define TNET_ICE_CANDIDATE_FOUND_SIZE_PREF 15 -typedef enum tnet_ice_cand_type_e -{ - tnet_ice_cand_type_unknown, - tnet_ice_cand_type_host, - tnet_ice_cand_type_srflx, - tnet_ice_cand_type_prflx, - tnet_ice_cand_type_relay +typedef enum tnet_ice_cand_type_e { + tnet_ice_cand_type_unknown, + tnet_ice_cand_type_host, + tnet_ice_cand_type_srflx, + tnet_ice_cand_type_prflx, + tnet_ice_cand_type_relay } tnet_ice_cand_type_t; -typedef struct tnet_ice_candidate_s -{ - TSK_DECLARE_OBJECT; - - tnet_ice_cand_type_t type_e; - uint8_t foundation[33]; // 1*32ice-char - uint32_t comp_id; // 1*5DIGIT - char* transport_str; // "UP" / token - enum tnet_socket_type_e transport_e; - uint32_t priority; // 1*10DIGIST [1 - (2**31 - 1)] - char* cand_type_str; // "host" / "srflx" / "prflx" / "relay" / "token" - tnet_ip_t connection_addr; - tnet_port_t port; - tsk_params_L_t *extension_att_list; - - tsk_bool_t is_ice_jingle; - tsk_bool_t is_rtp; - tsk_bool_t is_video; - uint16_t local_pref; // [0 - 65535] - - char* ufrag; - char* pwd; - - struct tnet_socket_s* socket; - struct{ - char* nonce; - char* realm; - char* srflx_addr; - tnet_stun_transac_id_t transac_id; - tnet_port_t srflx_port; - } stun; - struct { - struct tnet_turn_session_s* ss; - char* relay_addr; - tnet_port_t relay_port; - } turn; - - char *tostring; +typedef struct tnet_ice_candidate_s { + TSK_DECLARE_OBJECT; + + tnet_ice_cand_type_t type_e; + uint8_t foundation[33]; // 1*32ice-char + uint32_t comp_id; // 1*5DIGIT + char* transport_str; // "UP" / token + enum tnet_socket_type_e transport_e; + uint32_t priority; // 1*10DIGIST [1 - (2**31 - 1)] + char* cand_type_str; // "host" / "srflx" / "prflx" / "relay" / "token" + tnet_ip_t connection_addr; + tnet_port_t port; + tsk_params_L_t *extension_att_list; + + tsk_bool_t is_ice_jingle; + tsk_bool_t is_rtp; + tsk_bool_t is_video; + uint16_t local_pref; // [0 - 65535] + + char* ufrag; + char* pwd; + + struct tnet_socket_s* socket; + struct { + char* nonce; + char* realm; + char* srflx_addr; + tnet_stun_transac_id_t transac_id; + tnet_port_t srflx_port; + } stun; + struct { + struct tnet_turn_session_s* ss; + char* relay_addr; + tnet_port_t relay_port; + } turn; + + char *tostring; } tnet_ice_candidate_t; diff --git a/tinyNET/src/ice/tnet_ice_ctx.c b/tinyNET/src/ice/tnet_ice_ctx.c index 94d3042..6e5e5be 100755 --- a/tinyNET/src/ice/tnet_ice_ctx.c +++ b/tinyNET/src/ice/tnet_ice_ctx.c @@ -84,8 +84,7 @@ typedef tsk_list_t tnet_ice_servers_L_t; static const char* foundation_default = tsk_null; -typedef enum tnet_ice_server_proto_e -{ +typedef enum tnet_ice_server_proto_e { tnet_ice_server_proto_none = 0x00, tnet_ice_server_proto_stun = (0x01 << 0), tnet_ice_server_proto_turn = (0x01 << 1), @@ -134,10 +133,9 @@ static int _tnet_ice_ctx_fsm_OnTerminated(struct tnet_ice_ctx_s* self); static tsk_bool_t _tnet_ice_ctx_fsm_cond_NotStarted(struct tnet_ice_ctx_s* self, const void* _any); static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs *e); -typedef struct tnet_ice_server_s -{ +typedef struct tnet_ice_server_s { TSK_DECLARE_OBJECT; - + enum tnet_socket_type_e e_transport; tnet_ice_server_proto_t e_proto; char* str_server_addr; @@ -165,13 +163,12 @@ static tsk_object_t* tnet_ice_server_dtor(tsk_object_t * self) TSK_FREE(ice_server->str_software); TSK_FREE(ice_server->str_username); TSK_FREE(ice_server->str_password); - + TSK_DEBUG_INFO("*** ICE server destroyed ***"); } return self; } -static const tsk_object_def_t tnet_ice_server_def_s = -{ +static const tsk_object_def_t tnet_ice_server_def_s = { sizeof(tnet_ice_server_t), tnet_ice_server_ctor, tnet_ice_server_dtor, @@ -179,25 +176,25 @@ static const tsk_object_def_t tnet_ice_server_def_s = }; static tnet_ice_server_t* tnet_ice_server_create( - enum tnet_ice_server_proto_e e_proto, - enum tnet_socket_type_e e_transport, - const char* str_server_addr, uint16_t u_server_port, - const char* str_software, - const char* str_username, const char* str_password) + enum tnet_ice_server_proto_e e_proto, + enum tnet_socket_type_e e_transport, + const char* str_server_addr, uint16_t u_server_port, + const char* str_software, + const char* str_username, const char* str_password) { tnet_ice_server_t *ice_server; struct sockaddr_storage obj_server_addr; - + if (tsk_strnullORempty(str_server_addr) || !u_server_port) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - + if (tnet_sockaddr_init(str_server_addr, u_server_port, e_transport, &obj_server_addr) != 0) { TSK_DEBUG_ERROR("Invalid server address (host=%s, port=%d, transport=%d)", str_server_addr, u_server_port, e_transport); return tsk_null; } - + if ((ice_server = tsk_object_new(&tnet_ice_server_def_s))) { ice_server->e_proto = e_proto; ice_server->e_transport = e_transport; @@ -211,10 +208,9 @@ static tnet_ice_server_t* tnet_ice_server_create( return ice_server; } -typedef struct tnet_ice_ctx_s -{ +typedef struct tnet_ice_ctx_s { TSK_DECLARE_RUNNABLE; - + tsk_bool_t is_started; tsk_bool_t is_active; tsk_bool_t is_sync_mode; @@ -229,7 +225,7 @@ typedef struct tnet_ice_ctx_s tsk_bool_t unicast; tsk_bool_t anycast; tsk_bool_t multicast; - + tsk_bool_t is_connchecking; tsk_bool_t is_controlling; tsk_bool_t is_ice_jingle; @@ -237,19 +233,19 @@ typedef struct tnet_ice_ctx_s tsk_bool_t is_stun_enabled; uint64_t tie_breaker; uint64_t concheck_timeout; - + const void* rtp_callback_data; tnet_ice_rtp_callback_f rtp_callback; - + tnet_ice_servers_L_t *servers; - + char* ufrag; char* pwd; - + tsk_timer_manager_handle_t* h_timer_mgr; - + tsk_fsm_t* fsm; - + tsk_condwait_handle_t* condwait_pairs; tnet_ice_candidates_L_t* candidates_local; tnet_ice_candidates_L_t* candidates_remote; @@ -257,23 +253,23 @@ typedef struct tnet_ice_ctx_s tsk_bool_t have_nominated_offer; tsk_bool_t have_nominated_answer; tsk_bool_t have_nominated_symetric; /**< Whether symetic RTP has been negotiated */ - + uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond */ uint16_t Rc; /**< Number of retransmissions for UDP in millisecond */ - + struct { char* path_priv; char* path_pub; char* path_ca; tsk_bool_t verify; } ssl; - + struct { tsk_bool_t auto_detect; struct tnet_proxyinfo_s* info; } proxy; - + struct { tsk_condwait_handle_t* condwait; struct tnet_turn_session_s* ss_nominated_rtp; @@ -281,21 +277,19 @@ typedef struct tnet_ice_ctx_s struct tnet_turn_session_s* ss_nominated_rtcp; tnet_turn_peer_id_t peer_id_rtcp; } turn; - + TSK_DECLARE_SAFEOBJ; } tnet_ice_ctx_t; -typedef struct tnet_ice_action_s -{ +typedef struct tnet_ice_action_s { TSK_DECLARE_OBJECT; - + tsk_fsm_action_id id; } tnet_ice_action_t; -typedef enum _fsm_state_e -{ +typedef enum _fsm_state_e { _fsm_state_Started, _fsm_state_GatheringHostCandidates, _fsm_state_GatheringHostCandidatesDone, @@ -310,8 +304,7 @@ typedef enum _fsm_state_e } _fsm_state_t; -typedef enum _fsm_action_e -{ +typedef enum _fsm_action_e { _fsm_action_Success, _fsm_action_Failure, _fsm_action_GatherHostCandidates, @@ -327,19 +320,18 @@ _fsm_action_t; static tsk_object_t* tnet_ice_action_ctor(tsk_object_t * self, va_list * app) { tnet_ice_action_t *action = self; - if (action){ + if (action) { } return self; } static tsk_object_t* tnet_ice_action_dtor(tsk_object_t * self) { tnet_ice_action_t *action = self; - if (action){ + if (action) { } return self; } -static const tsk_object_def_t tnet_ice_action_def_s = -{ +static const tsk_object_def_t tnet_ice_action_def_s = { sizeof(tnet_ice_action_t), tnet_ice_action_ctor, tnet_ice_action_dtor, @@ -348,7 +340,7 @@ static const tsk_object_def_t tnet_ice_action_def_s = static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id) { tnet_ice_action_t *action = tsk_object_new(&tnet_ice_action_def_s); - if (action){ + if (action) { action->id = id; } return action; @@ -360,59 +352,59 @@ static tnet_ice_action_t* tnet_ice_action_create(tsk_fsm_action_id id) static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app) { tnet_ice_ctx_t *ctx = self; - if (ctx){ + if (ctx) { tsk_safeobj_init(ctx); - - if (!(ctx->h_timer_mgr = tsk_timer_manager_create())){ + + if (!(ctx->h_timer_mgr = tsk_timer_manager_create())) { TSK_DEBUG_ERROR("Failed to create timer manager"); return tsk_null; } - if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))){ + if (!(ctx->fsm = tsk_fsm_create(_fsm_state_Started, _fsm_state_Terminated))) { TSK_DEBUG_ERROR("Failed to create state machine"); return tsk_null; } - if (!(ctx->candidates_local = tsk_list_create())){ + if (!(ctx->candidates_local = tsk_list_create())) { TSK_DEBUG_ERROR("Failed to create candidates list"); return tsk_null; } - if (!(ctx->candidates_remote = tsk_list_create())){ + if (!(ctx->candidates_remote = tsk_list_create())) { TSK_DEBUG_ERROR("Failed to create candidates list"); return tsk_null; } - if (!(ctx->candidates_pairs = tsk_list_create())){ + if (!(ctx->candidates_pairs = tsk_list_create())) { TSK_DEBUG_ERROR("Failed to create candidates list"); return tsk_null; } - + // Create condwait for pairs if (!(ctx->condwait_pairs = tsk_condwait_create())) { TSK_DEBUG_ERROR("Failed to create condwait for pairs"); return tsk_null; } - + // Create list objects to hold the servers - if (!(ctx->servers = tsk_list_create())){ + if (!(ctx->servers = tsk_list_create())) { TSK_DEBUG_ERROR("Failed to create server list"); return tsk_null; } - + tsk_runnable_set_important(TSK_RUNNABLE(self), tsk_false); - + /* 7.2.1. Sending over UDP In fixed-line access links, a value of 500 ms is RECOMMENDED. */ ctx->RTO = kIceDefaultRTO; - + /* 7.2.1. Sending over UDP Rc SHOULD be configurable and SHOULD have a default of 7. */ ctx->Rc = kIceDefaultRC; - + ctx->tie_breaker = ((tsk_time_now() << 32) ^ tsk_time_now()); ctx->is_ice_jingle = tsk_false; ctx->is_stun_enabled = kIceDefaultStunEnabled; ctx->is_turn_enabled = kIceDefaultTurnEnabled; - + ctx->concheck_timeout = LONG_MAX; } return self; @@ -420,17 +412,17 @@ static tsk_object_t* tnet_ice_ctx_ctor(tsk_object_t * self, va_list * app) static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self) { tnet_ice_ctx_t *ctx = self; - if (ctx){ + if (ctx) { tnet_ice_ctx_stop(ctx); - if (ctx->h_timer_mgr){ + if (ctx->h_timer_mgr) { tsk_timer_manager_destroy(&ctx->h_timer_mgr); } - + TSK_OBJECT_SAFE_FREE(ctx->fsm); TSK_OBJECT_SAFE_FREE(ctx->candidates_local); TSK_OBJECT_SAFE_FREE(ctx->candidates_remote); TSK_OBJECT_SAFE_FREE(ctx->candidates_pairs); - + TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp); TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp); if (ctx->turn.condwait) { @@ -440,20 +432,19 @@ static tsk_object_t* tnet_ice_ctx_dtor(tsk_object_t * self) tsk_condwait_destroy(&ctx->condwait_pairs); } TSK_OBJECT_SAFE_FREE(ctx->servers); - + TSK_OBJECT_SAFE_FREE(ctx->proxy.info); - + TSK_FREE(ctx->ssl.path_priv); TSK_FREE(ctx->ssl.path_pub); TSK_FREE(ctx->ssl.path_ca); - + tsk_safeobj_deinit(ctx); } TSK_DEBUG_INFO("*** ICE context destroyed ***"); return self; } -static const tsk_object_def_t tnet_ice_ctx_def_s = -{ +static const tsk_object_def_t tnet_ice_ctx_def_s = { sizeof(tnet_ice_ctx_t), tnet_ice_ctx_ctor, tnet_ice_ctx_dtor, @@ -464,12 +455,12 @@ static const tsk_object_def_t tnet_ice_ctx_def_s = tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv6, tsk_bool_t use_rtcp, tsk_bool_t is_video, tnet_ice_callback_f callback, const void* userdata) { tnet_ice_ctx_t* ctx; - - if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))){ + + if (!(ctx = tsk_object_new(&tnet_ice_ctx_def_s))) { TSK_DEBUG_ERROR("Failed to create ICE context object"); return tsk_null; } - + ctx->is_ice_jingle = is_ice_jingle; ctx->use_ipv6 = use_ipv6; ctx->use_rtcp = use_rtcp; @@ -479,10 +470,10 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv ctx->unicast = tsk_true; ctx->anycast = tsk_false; ctx->multicast = tsk_false; - + tnet_ice_utils_set_ufrag(&ctx->ufrag); tnet_ice_utils_set_pwd(&ctx->pwd); - + ctx->fsm->debug = TNET_ICE_DEBUG_STATE_MACHINE; tsk_fsm_set_callback_terminated(ctx->fsm, TSK_FSM_ONTERMINATED_F(_tnet_ice_ctx_fsm_OnTerminated), (const void*)ctx); tsk_fsm_set(ctx->fsm, @@ -492,14 +483,14 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Success, _fsm_state_GatheringHostCandidatesDone, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success, "ICE_GatheringHostCandidates_2_GatheringHostCandidatesDone_X_Success"), // (GatheringHostCandidates) -> (Failure) -> (Terminated) TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure, "ICE_GatheringHostCandidates_2_Terminated_X_Failure"), - + // (GatheringHostCandidatesDone) -> (GatherReflexiveCandidates) -> (GatheringReflexiveCandidates) TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringHostCandidatesDone, _fsm_action_GatherReflexiveCandidates, _fsm_state_GatheringReflexiveCandidates, _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates, "ICE_GatheringHostCandidatesDone_2_GatheringReflexiveCandidates_X_GatherReflexiveCandidates"), // (GatheringReflexiveCandidates) -> (Success) -> GatheringReflexiveCandidatesDone TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Success, _fsm_state_GatheringReflexiveCandidatesDone, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success, "ICE_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success"), // (GatheringReflexiveCandidates) -> (Failure) -> Terminated TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_Terminated_X_Failure, "ICE_GatheringReflexiveCandidates_2_Terminated_X_Failure"), - + // (GatheringReflexiveCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates) TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringReflexiveCandidatesDone, _fsm_action_GatherRelayCandidates, _fsm_state_GatheringRelayCandidates, _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates, "ICE_GatheringReflexiveCandidatesDone_2_GatheringRelayCandidates_X_GatherRelayCandidates"), // (GatheringHostCandidatesDone) -> (GatherRelayCandidates) -> (GatheringRelayCandidates) @@ -508,28 +499,28 @@ tnet_ice_ctx_t* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, tsk_bool_t use_ipv TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Success, _fsm_state_GatheringRelayCandidatesDone, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success, "ICE_fsm_GatheringRelayCandidates_2_GatheringRelayCandidatesDone_X_Success"), // (GatheringRelayCandidates) -> (Failure) -> Terminated TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringRelayCandidates, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_GatheringRelayCandidates_2_Terminated_X_Failure, "ICE_GatheringRelayCandidates_2_Terminated_X_Failure"), - + // (GatheringComplet) -> (ConnCheck) -> ConnChecking TSK_FSM_ADD_ALWAYS(_fsm_state_GatheringCompleted, _fsm_action_ConnCheck, _fsm_state_ConnChecking, _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck, "ICE_GatheringCompleted_2_ConnChecking_X_ConnCheck"), // (ConnChecking) -> (Success) -> ConnCheckingCompleted TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Success, _fsm_state_ConnCheckingCompleted, _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success, "ICE_ConnChecking_2_ConnCheckingCompleted_X_Success"), // (ConnChecking) -> (Failure) -> Terminated TSK_FSM_ADD_ALWAYS(_fsm_state_ConnChecking, _fsm_action_Failure, _fsm_state_Terminated, _tnet_ice_ctx_fsm_ConnChecking_2_Terminated_X_Failure, "ICE_ConnChecking_2_Terminated_X_Failure"), - + // (Any) -> (GatheringComplet) -> GatheringCompleted TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_GatheringComplet, _fsm_state_GatheringCompleted, _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet, "ICE_Any_2_GatheringCompleted_X_GatheringComplet"), // (Any) -> (Cancel) -> Started TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_Cancel, _fsm_state_Started, _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel, "ICE_Any_2_Started_X_Cancel"), // (Any) -> (AnyNotStarted) -> Terminated TSK_FSM_ADD(tsk_fsm_state_any, tsk_fsm_action_any, _tnet_ice_ctx_fsm_cond_NotStarted, _fsm_state_Terminated, _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted, "ICE_fsm_Any_2_Terminated_X_AnyNotStarted") - ); - + ); + return ctx; } int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -539,34 +530,34 @@ int tnet_ice_ctx_set_userdata(tnet_ice_ctx_t* self, const void* userdata) // @deprecated: use "tnet_ice_ctx_add_server()" int tnet_ice_ctx_set_stun( - tnet_ice_ctx_t* self, - const char* server_addr, - uint16_t server_port, - const char* software, - const char* username, - const char* password) + tnet_ice_ctx_t* self, + const char* server_addr, + uint16_t server_port, + const char* software, + const char* username, + const char* password) { _tnet_ice_ctx_servers_clear(self); return tnet_ice_ctx_add_server( - self, - "udp", - server_addr, - server_port, - (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/ - tsk_true, /* use_stun*/ - username, - password); + self, + "udp", + server_addr, + server_port, + (!tsk_strnullORempty(username) && !tsk_strnullORempty(password)), /* use_turn*/ + tsk_true, /* use_stun*/ + username, + password); } int tnet_ice_ctx_add_server( - struct tnet_ice_ctx_s* self, - const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss" - const char* server_addr, - uint16_t server_port, - tsk_bool_t use_turn, - tsk_bool_t use_stun, - const char* username, - const char* password) + struct tnet_ice_ctx_s* self, + const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss" + const char* server_addr, + uint16_t server_port, + tsk_bool_t use_turn, + tsk_bool_t use_stun, + const char* username, + const char* password) { tnet_socket_type_t socket_type; tnet_ice_server_proto_t e_proto = tnet_ice_server_proto_none; @@ -584,7 +575,7 @@ int tnet_ice_ctx_add_server( if (use_turn) { e_proto |= tnet_ice_server_proto_turn; } - + if (tsk_striequals(transport_proto, "udp")) { socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4; } @@ -612,7 +603,7 @@ int tnet_ice_ctx_add_server( int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -622,7 +613,7 @@ int tnet_ice_ctx_set_sync_mode(tnet_ice_ctx_t* self, tsk_bool_t sync_mode) int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_mode) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -633,7 +624,7 @@ int tnet_ice_ctx_set_silent_mode(struct tnet_ice_ctx_s* self, tsk_bool_t silent_ // Whether to gather reflexive candidates int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_enabled) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -644,7 +635,7 @@ int tnet_ice_ctx_set_stun_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t stun_e // Whether to gather relay candidates int tnet_ice_ctx_set_turn_enabled(struct tnet_ice_ctx_s* self, tsk_bool_t turn_enabled) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -658,19 +649,19 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self) tsk_bool_t timer_mgr_started = tsk_false; tsk_bool_t runnable_started = tsk_false; const char* err = tsk_null; - - if (!self){ + + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + tsk_safeobj_lock(self); - + TSK_DEBUG_INFO("tnet_ice_ctx_start"); - - if (self->is_started){ + + if (self->is_started) { ret = 0; - if (!self->is_active){ + if (!self->is_active) { TSK_DEBUG_INFO("ICE restart"); ret = _tnet_ice_ctx_restart(self); } @@ -678,42 +669,42 @@ int tnet_ice_ctx_start(tnet_ice_ctx_t* self) tsk_safeobj_unlock(self); return ret; } - + /* === Timer manager === */ - if ((ret = tsk_timer_manager_start(self->h_timer_mgr))){ + if ((ret = tsk_timer_manager_start(self->h_timer_mgr))) { err = "Failed to start timer manager"; TSK_DEBUG_ERROR("%s", err); goto bail; } timer_mgr_started = tsk_true; - + /* === Runnable === */ TSK_RUNNABLE(self)->run = _tnet_ice_ctx_run; - if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))){ + if ((ret = tsk_runnable_start(TSK_RUNNABLE(self), tnet_ice_event_def_t))) { err = "Failed to start runnable"; TSK_DEBUG_ERROR("%s", err); goto bail; } runnable_started = tsk_true; - + self->is_started = tsk_true; // needed by FSM -> "Must" be before fsm_ast() self->is_active = tsk_true; - - if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))){ + + if ((ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates))) { err = "FSM execution failed"; TSK_DEBUG_ERROR("%s", err); goto bail; } - + bail: tsk_safeobj_unlock(self); - - if (ret){ + + if (ret) { _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_start_failed, err); - if (timer_mgr_started){ + if (timer_mgr_started) { tsk_timer_manager_stop(self->h_timer_mgr); } - if (runnable_started){ + if (runnable_started) { tsk_runnable_stop(TSK_RUNNABLE(self)); } self->is_started = tsk_false; @@ -725,11 +716,11 @@ bail: // register callback to call when we receive early RTP packets while negotaiating ICE pairs int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_callback, const void* rtp_callback_data) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + self->rtp_callback_data = rtp_callback_data; self->rtp_callback = rtp_callback; return 0; @@ -738,13 +729,13 @@ int tnet_ice_ctx_rtp_callback(tnet_ice_ctx_t* self, tnet_ice_rtp_callback_f rtp_ // timeout (millis): <=0 to disable int tnet_ice_ctx_set_concheck_timeout(tnet_ice_ctx_t* self, int64_t timeout) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + self->concheck_timeout = (timeout <= 0 ? LONG_MAX : timeout); - + return 0; } @@ -761,34 +752,34 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + self->is_controlling = is_controlling; self->is_ice_jingle = is_ice_jingle; tnet_ice_ctx_set_rtcpmux(self, use_rtcpmux); - + if (tsk_strnullORempty(candidates)) { // remote party is ICE-lite or doesn't support ICE return tnet_ice_ctx_cancel(self); } - + TSK_DEBUG_INFO("tnet_ice_ctx_set_remote_candidates(ufrag=%s, pwd=%s, is_controlling=%d, is_ice_jingle=%d, use_rtcpmux=%d)", ufrag, pwd, is_controlling, is_ice_jingle, use_rtcpmux); - + tsk_list_lock(self->candidates_pairs); if (!TSK_LIST_IS_EMPTY(self->candidates_pairs)) { TSK_DEBUG_WARN("Adding Remote ICE candidates after pairs building"); } tsk_list_unlock(self->candidates_pairs); - + // active if remote is full-ICE // in all case we are always full-ICE // self->is_active = tsk_true; - + tsk_list_lock(self->candidates_remote); - + // clear old candidates tsk_list_clear_items(self->candidates_remote); - + copy = tsk_strdup(candidates); size = (tsk_size_t)tsk_strlen(copy); do { @@ -819,13 +810,14 @@ int tnet_ice_ctx_set_remote_candidates_2(struct tnet_ice_ctx_s* self, const char } TSK_OBJECT_SAFE_FREE(candidate); } - } while (v && (idx < size)); - + } + while (v && (idx < size)); + tsk_list_unlock(self->candidates_remote); - + TSK_FREE(copy); TSK_OBJECT_SAFE_FREE(added_candidates); - + if (!tnet_ice_ctx_is_connected(self) && tnet_ice_ctx_got_local_candidates(self) && !TSK_LIST_IS_EMPTY(self->candidates_remote)) { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck); } @@ -866,7 +858,7 @@ int tnet_ice_ctx_set_ssl_certs(struct tnet_ice_ctx_s* self, const char* path_pri tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return 0; } @@ -876,16 +868,16 @@ tsk_size_t tnet_ice_ctx_count_local_candidates(const tnet_ice_ctx_t* self) tsk_bool_t tnet_ice_ctx_got_local_candidates(const tnet_ice_ctx_t* self) { tsk_fsm_state_id curr_state; - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_false; } - if (!self->is_started){ + if (!self->is_started) { return tsk_false; } - + curr_state = tsk_fsm_get_current_state(self->fsm); - + return (curr_state >= _fsm_state_GatheringCompleted && curr_state < _fsm_state_Terminated); } @@ -893,13 +885,13 @@ const tnet_ice_candidate_t* tnet_ice_ctx_get_local_candidate_at(const tnet_ice_c { const tsk_list_item_t *item; tsk_size_t pos = 0; - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - - tsk_list_foreach(item, self->candidates_local){ - if (pos++ == index){ + + tsk_list_foreach(item, self->candidates_local) { + if (pos++ == index) { return (const tnet_ice_candidate_t*)item->data; } } @@ -922,9 +914,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtp_active(const struct tnet_ice_ctx_s* self) { tsk_bool_t b_active; return tnet_ice_ctx_is_active(self) - && self->turn.ss_nominated_rtp - && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0 - && b_active; + && self->turn.ss_nominated_rtp + && tnet_turn_session_is_active(self->turn.ss_nominated_rtp, self->turn.peer_id_rtp, &b_active) == 0 + && b_active; } tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self) @@ -935,9 +927,9 @@ tsk_bool_t tnet_ice_ctx_is_turn_rtcp_active(const struct tnet_ice_ctx_s* self) else { tsk_bool_t b_active; return tnet_ice_ctx_is_active(self) - && self->turn.ss_nominated_rtcp - && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0 - && b_active; + && self->turn.ss_nominated_rtcp + && tnet_turn_session_is_active(self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, &b_active) == 0 + && b_active; } } @@ -968,11 +960,11 @@ tsk_bool_t tnet_ice_ctx_use_rtcp(const tnet_ice_ctx_t* self) } int tnet_ice_ctx_get_nominated_symetric_candidates(const tnet_ice_ctx_t* self, uint32_t comp_id, - const tnet_ice_candidate_t** candidate_offer, - const tnet_ice_candidate_t** candidate_answer_src, - const tnet_ice_candidate_t** candidate_answer_dest) + const tnet_ice_candidate_t** candidate_offer, + const tnet_ice_candidate_t** candidate_answer_src, + const tnet_ice_candidate_t** candidate_answer_dest) { - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -993,14 +985,14 @@ int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, ts int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size) { return self->use_rtcpmux - ? tnet_ice_ctx_send_turn_rtp(self, data, size) - : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size); + ? tnet_ice_ctx_send_turn_rtp(self, data, size) + : _tnet_ice_ctx_send_turn_raw(self, self->turn.ss_nominated_rtcp, self->turn.peer_id_rtcp, data, size); } int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_t* bytes_in, uint64_t* bytes_out) { int ret; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1010,8 +1002,12 @@ int tnet_ice_ctx_turn_get_bytes_count(const struct tnet_ice_ctx_s* self, uint64_ uint64_t _bytes_in, _bytes_out; ret = tnet_turn_session_get_bytes_count(self->turn.ss_nominated_rtcp, &_bytes_in, &_bytes_out); if (ret == 0) { - if (bytes_in) *bytes_in += _bytes_in; - if (bytes_out) *bytes_out += _bytes_out; + if (bytes_in) { + *bytes_in += _bytes_in; + } + if (bytes_out) { + *bytes_out += _bytes_out; + } } } return ret; @@ -1058,19 +1054,19 @@ int tnet_ice_ctx_set_proxy_info(struct tnet_ice_ctx_s* self, enum tnet_proxy_typ int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self) { int ret; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + tsk_safeobj_lock(self); if (tsk_fsm_get_current_state(self->fsm) == _fsm_state_Started) { // Do nothing if already in the "started" state ret = 0; goto bail; } - + self->is_active = tsk_false; self->have_nominated_symetric = tsk_false; self->have_nominated_answer = tsk_false; @@ -1080,7 +1076,7 @@ int tnet_ice_ctx_cancel(tnet_ice_ctx_t* self) ret = tsk_condwait_broadcast(self->turn.condwait); } ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Cancel); - + bail: tsk_safeobj_unlock(self); return ret; @@ -1089,18 +1085,18 @@ bail: int tnet_ice_ctx_stop(tnet_ice_ctx_t* self) { int ret; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + tsk_safeobj_lock(self); if (!self->is_started) { ret = 0; goto bail; } - + self->is_started = tsk_false; tsk_condwait_broadcast(self->condwait_pairs); if (self->turn.condwait) { @@ -1108,7 +1104,7 @@ int tnet_ice_ctx_stop(tnet_ice_ctx_t* self) } ret = tsk_timer_manager_stop(self->h_timer_mgr); ret = tsk_runnable_stop(TSK_RUNNABLE(self)); - + bail: tsk_safeobj_unlock(self); return ret; @@ -1136,92 +1132,92 @@ static int _tnet_ice_ctx_fsm_Started_2_GatheringHostCandidates_X_GatherHostCandi static const tsk_bool_t dnsserver = tsk_false; static const long if_index_any = -1; // any interface static const char* destination = "doubango.org"; - + self = va_arg(*app, tnet_ice_ctx_t *); socket_type = self->use_ipv6 ? tnet_socket_type_udp_ipv6 : tnet_socket_type_udp_ipv4; - + addresses = tnet_get_addresses((self->use_ipv6 ? AF_INET6 : AF_INET), self->unicast, self->anycast, self->multicast, dnsserver, if_index_any); - if (!addresses || TSK_LIST_IS_EMPTY(addresses)){ + if (!addresses || TSK_LIST_IS_EMPTY(addresses)) { TSK_DEBUG_ERROR("Failed to get addresses"); ret = -1; goto bail; } - - + + check_best_local_ip = (tnet_getbestsource(destination, 5060, socket_type, &best_local_ip) == 0); curr_local_pref = local_pref = check_best_local_ip ? 0xFFFE : 0xFFFF; - + // lock-list tsk_list_lock(self->candidates_local); // clear-list tsk_list_clear_items(self->candidates_local); - - tsk_list_foreach(item, addresses){ - if (!(address = item->data)){ + + tsk_list_foreach(item, addresses) { + if (!(address = item->data)) { continue; } - + // Skip loopback address to avoid problems :) - if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))){ + if ((address->family == AF_INET && tsk_striequals(address->ip, "127.0.0.1")) || (address->family == AF_INET6 && tsk_striequals(address->ip, "::1"))) { continue; } - + // host candidates ret = tnet_ice_utils_create_sockets(socket_type, address->ip, &socket_rtp, self->use_rtcp ? &socket_rtcp : tsk_null); - if (ret == 0){ + if (ret == 0) { const char* foundation_rtp = foundation_default; tsk_list_lock(self->candidates_local); - if (socket_rtp){ - if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))){ + if (socket_rtp) { + if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtp, self->is_ice_jingle, tsk_true, self->is_video, self->ufrag, self->pwd, foundation_default))) { foundation_rtp = (const char*)candidate->foundation; - if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))){ + if (check_best_local_ip && (candidate->socket && (tsk_striequals(candidate->socket->ip, best_local_ip)))) { curr_local_pref = 0xFFFF; check_best_local_ip = tsk_false; tnet_ice_candidate_set_local_pref(candidate, curr_local_pref); tsk_list_push_front_data(self->candidates_local, (void**)&candidate); } - else{ + else { curr_local_pref = local_pref--; tnet_ice_candidate_set_local_pref(candidate, curr_local_pref); tsk_list_push_back_data(self->candidates_local, (void**)&candidate); } } } - if (socket_rtcp){ - if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))){ + if (socket_rtcp) { + if ((candidate = tnet_ice_candidate_create(tnet_ice_cand_type_host, socket_rtcp, self->is_ice_jingle, tsk_false, self->is_video, self->ufrag, self->pwd, foundation_rtp))) { tnet_ice_candidate_set_local_pref(candidate, curr_local_pref); tsk_list_push_back_data(self->candidates_local, (void**)&candidate); } } tsk_list_unlock(self->candidates_local); } - + TSK_OBJECT_SAFE_FREE(socket_rtp); TSK_OBJECT_SAFE_FREE(socket_rtcp); - + // break if no longer running - if (!self->is_started){ + if (!self->is_started) { break; } - + TSK_DEBUG_INFO("local ip address = %s", address->ip); } - + // unlock-list tsk_list_unlock(self->candidates_local); - + bail: - if (self->is_started){ - if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)){ + if (self->is_started) { + if (ret == 0 && !TSK_LIST_IS_EMPTY(self->candidates_local)) { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success); } - else{ + else { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure); } } - + TSK_OBJECT_SAFE_FREE(addresses); return ret; } @@ -1231,9 +1227,9 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo { int ret; tnet_ice_ctx_t* self; - + self = va_arg(*app, tnet_ice_ctx_t *); - + ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_succeed, "Gathering host candidates succeed"); if (ret == 0) { if (self->is_stun_enabled && _tnet_ice_ctx_servers_count_by_proto(self, tnet_ice_server_proto_stun) > 0) { @@ -1251,7 +1247,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo } } } - + return ret; } @@ -1259,7 +1255,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_GatheringHostCandidatesDo static int _tnet_ice_ctx_fsm_GatheringHostCandidates_2_Terminated_X_Failure(va_list *app) { tnet_ice_ctx_t* self; - + self = va_arg(*app, tnet_ice_ctx_t *); return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_host_candidates_failed, "Gathering host candidates failed"); } @@ -1287,16 +1283,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan fd_set set; tsk_size_t srflx_addr_count_added = 0, srflx_addr_count_skipped = 0, host_addr_count = 0; long tv_sec, tv_usec; //very important to save these values as timeval could be modified by select() - happens on iOS - - + self = va_arg(*app, tnet_ice_ctx_t *); - + // Get ICE servers to use to gather reflexive candidates ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_stun); if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) { // not expected to be null or empty because we checked the number of such servers before calling this transition TSK_DEBUG_WARN("No valid STUN server could be used to gather reflexive candidates"); goto bail; } - + // set all default values to -1 // = {{ -1 }} will only set the first element for (i = 0; i < sizeof(fds) / sizeof(fds[0]); ++i) { @@ -1305,17 +1301,17 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan for (i = 0; i < sizeof(fds_skipped) / sizeof(fds_skipped[0]); ++i) { fds_skipped[i] = TNET_INVALID_FD; } - + rc = self->Rc; tv.tv_sec = tv_sec = 0; tv.tv_usec = tv_usec = 0; - + // load fds for both rtp and rtcp sockets tsk_list_foreach(item, self->candidates_local) { if (!(candidate = item->data)) { continue; } - + ++host_addr_count; if ((fds_count < sizeof(fds) / sizeof(fds[0])) && candidate->socket) { fds[fds_count++] = candidate->socket->fd; @@ -1324,13 +1320,13 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan } } } - - + + /* 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 && self->is_started && ((srflx_addr_count_added + srflx_addr_count_skipped) < host_addr_count)); ++i) { @@ -1362,16 +1358,16 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan #else tv.tv_usec = tv_usec; #endif - + TSK_DEBUG_INFO("ICE reflexive candidates gathering ...srv_addr=%s,srv_port=%u,tv_sec=%lu,tv_usec=%lu,rto=%d", ice_server->str_server_addr, ice_server->u_server_port, tv_sec, tv_usec, ice_server->rto); - + FD_ZERO(&set); for (k = 0; k < fds_count; ++k) { FD_SET(fds[k], &set); } - + // sends STUN binding requets - tsk_list_foreach(item, self->candidates_local){ + tsk_list_foreach(item, self->candidates_local) { if (!(candidate = (tnet_ice_candidate_t*)item->data)) { continue; } @@ -1379,7 +1375,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan ret = tnet_ice_candidate_send_stun_bind_request(candidate, &ice_server->obj_server_addr, ice_server->str_username, ice_server->str_password); } } - + if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) { TSK_DEBUG_ERROR("select() failed with error code = %d", tnet_geterrno()); goto bail; @@ -1398,27 +1394,27 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan unsigned int len = 0; void* data = 0; const tnet_ice_candidate_t* candidate_curr; - + // Check how many bytes are pending if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) { TSK_DEBUG_ERROR("tnet_ioctlt() failed"); continue; } - + if (len == 0) { TSK_DEBUG_INFO("tnet_ioctlt() retured zero bytes"); continue; } - + // Receive pending data data = tsk_calloc(len, sizeof(uint8_t)); if ((ret = tnet_sockfd_recv(fd, data, len, 0)) < 0) { TSK_FREE(data); - + TSK_DEBUG_ERROR("Recving STUN dgrams failed with error code:%d", tnet_geterrno()); continue; } - + // Parse the incoming response if ((ret = tnet_stun_pkt_read(data, (tsk_size_t)ret, &response))) { TSK_FREE(data); @@ -1435,7 +1431,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan tsk_size_t j; tsk_bool_t already_skipped = tsk_false; /* refc 5245- 4.1.3. Eliminating Redundant Candidates - + Next, the agent eliminates redundant candidates. A candidate is redundant if its transport address equals another candidate, and its base equals the base of that other candidate. Note that two @@ -1450,7 +1446,7 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan break; } } - + if (!already_skipped) { ++srflx_addr_count_skipped; fds_skipped[j] = fd; @@ -1488,19 +1484,21 @@ static int _tnet_ice_ctx_fsm_GatheringHostCandidatesDone_2_GatheringReflexiveCan } } // tsk_list_foreach (item, ice_servers)... } // for (i = 0; (i < rc.... - + bail: TSK_DEBUG_INFO("srflx_addr_count_added=%u, srflx_addr_count_skipped=%u", (unsigned)srflx_addr_count_added, (unsigned)srflx_addr_count_skipped); - if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) ret = 0; // Hack the returned value if we have at least one success (happens when timeouts) + if ((srflx_addr_count_added + srflx_addr_count_skipped) > 0) { + ret = 0; // Hack the returned value if we have at least one success (happens when timeouts) + } if (self->is_started) { if (ret == 0) { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Success); } - else{ + else { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure); } } - + tsk_list_foreach(item, self->candidates_local) { if (!(candidate = (tnet_ice_candidate_t*)item->data)) { continue; @@ -1515,9 +1513,9 @@ bail: static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidates_2_GatheringReflexiveCandidatesDone_X_Success(va_list *app) { tnet_ice_ctx_t* self; - + self = va_arg(*app, tnet_ice_ctx_t *); - + if (self->is_started) { int ret = _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_reflexive_candidates_succeed, "Gathering reflexive candidates succeed"); if (ret == 0) { @@ -1560,19 +1558,19 @@ static int _tnet_ice_ctx_fsm_GatheringReflexiveCandidatesDone_2_GatheringRelayCa tnet_ice_servers_L_t* ice_servers = tsk_null; tnet_ice_server_t* ice_server; tnet_ice_candidates_L_t* candidates_local_copy = tsk_null;; - + // Create TURN condwait handle if not already done if (!self->turn.condwait && !(self->turn.condwait = tsk_condwait_create())) { TSK_DEBUG_ERROR("Failed to create TURN condwait handle"); ret = -2; goto bail; } - + // Copy local ICE candidates tsk_list_lock(self->candidates_local); candidates_local_copy = tsk_list_clone(self->candidates_local); tsk_list_unlock(self->candidates_local); - + // Take reference to the TURN servers ice_servers = _tnet_ice_ctx_servers_copy(self, tnet_ice_server_proto_turn); if (!ice_servers || TSK_LIST_IS_EMPTY(ice_servers)) { @@ -1595,14 +1593,14 @@ next_server: goto bail; } ice_server = (tnet_ice_server_t*)item_server->data; - + // Create TURN sessions for each local host candidate tsk_list_foreach(item, candidates_local_copy) { if (!(candidate = item->data)) { continue; } TSK_DEBUG_INFO("Gathering relay candidate: local addr=%s=%d, TURN server=%s:%d", candidate->connection_addr, candidate->port, ice_server->str_server_addr, ice_server->u_server_port); - + // Destroy previvious TURN session (if exist) TSK_OBJECT_SAFE_FREE(candidate->turn.ss); if (candidate->type_e == tnet_ice_cand_type_host && candidate->socket) { // do not create TURN session for reflexive candidates @@ -1648,16 +1646,16 @@ next_server: ++host_addr_count; } } // tsk_list_foreach(item, self->candidates_local) { - + rto = self->RTO; rc = self->Rc; - + for (i = 0; (i < rc && self->is_started && ((relay_addr_count_ok + relay_addr_count_nok) < host_addr_count));) { if (!self->is_started || !self->is_active) { TSK_DEBUG_INFO("ICE context stopped/cancelled while gathering TURN candidates"); goto bail; } - + u_t0 = tsk_time_now(); tsk_condwait_timedwait(self->turn.condwait, rto); u_t1 = tsk_time_now(); @@ -1666,7 +1664,7 @@ next_server: rto <<= 1; ++i; } - + // count the number of TURN sessions with alloc() = ok/nok and ignore ones without response relay_addr_count_ok = 0; tsk_list_foreach(item, candidates_local_copy) { @@ -1685,7 +1683,7 @@ next_server: } } } - + // add/delete TURN candidates tsk_list_foreach(item, candidates_local_copy) { if (!(candidate = item->data) || !candidate->turn.ss) { @@ -1701,7 +1699,7 @@ next_server: tnet_port_t relay_port; tnet_ice_candidate_t* new_cand = tsk_null; struct tnet_socket_s* p_lcl_sock = tsk_null; - + if ((ret = tnet_turn_session_get_relayed_addr(candidate->turn.ss, &relay_addr, &relay_port, &__b_ipv6))) { goto bail; } @@ -1733,12 +1731,12 @@ next_server: TSK_OBJECT_SAFE_FREE(candidate->turn.ss); } } - + // Try next TURN server if (self->is_started && item_server && relay_addr_count_added == 0) { goto next_server; } - + bail: if (self->is_started) { if (ret == 0) { @@ -1778,34 +1776,34 @@ static int _tnet_ice_ctx_fsm_Any_2_Started_X_Cancel(va_list *app) { tnet_ice_ctx_t* self; self = va_arg(*app, tnet_ice_ctx_t *); - + tsk_list_lock(self->candidates_remote); tsk_list_clear_items(self->candidates_remote); tsk_list_unlock(self->candidates_remote); - + tsk_list_lock(self->candidates_pairs); tsk_list_clear_items(self->candidates_pairs); tsk_list_unlock(self->candidates_pairs); - + TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp); TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp); - + // Do not clear local candidates because then will be used as fallback if the remote peer is an ICE-lite // These candidates will be cleared before the next local gathering // tsk_list_lock(self->candidates_local); // tsk_list_clear_items(self->candidates_local); // tsk_list_unlock(self->candidates_local); - + // restore "is_cancelled" until next cancel // set "is_active" to false to allow ICE re-start // self->is_cancelled = tsk_false; // self->is_active = tsk_false; - + // alert user _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_cancelled, "Cancelled"); - + return 0; - + } // Any -> (GatheringComplet) -> GatheringCompleted @@ -1814,25 +1812,25 @@ static int _tnet_ice_ctx_fsm_Any_2_GatheringCompleted_X_GatheringComplet(va_list int ret = 0; tnet_ice_ctx_t* self; tsk_bool_t has_remote_candidates; - + self = va_arg(*app, tnet_ice_ctx_t *); - + // alert user _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_gathering_completed, "Gathering candidates completed"); - - if (self->is_started){ + + if (self->is_started) { tsk_list_lock(self->candidates_remote); has_remote_candidates = !TSK_LIST_IS_EMPTY(self->candidates_remote); tsk_list_unlock(self->candidates_remote); - - if (has_remote_candidates){ + + if (has_remote_candidates) { ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_ConnCheck); } } - else{ + else { return -1; } - + return ret; } @@ -1861,42 +1859,42 @@ static int _tnet_ice_ctx_fsm_GatheringCompleted_2_ConnChecking_X_ConnCheck(va_li void* recvfrom_buff_ptr = tsk_null; tsk_size_t recvfrom_buff_size = 0, tries_count = 0, tries_count_min = kIceConnCheckMinTriesMin; enum tnet_stun_state_e e_state; - + self = va_arg(*app, tnet_ice_ctx_t *); - + self->is_connchecking = tsk_true; - + // "tries_count" and "tries_count_min" // The connection checks to to the "relay", "prflx", "srflx" and "host" candidates are sent at the same time. // Because the requests are sent at the same time it's possible to have success check for "relay" (or "srflx") candidates before the "host" candidates. // "tries_count_min" is the minimum (if success check is not for "host" candidates) tries before giving up. // The pairs are already sorted ("host"->"srflx"->"prflx", "relay") to make sure to choose the best candidates when there are more than one success conncheck. - + start_conneck: role_conflict = tsk_false; restart_conneck = tsk_false; - + tsk_list_lock(self->candidates_pairs); tsk_list_clear_items(self->candidates_pairs); tsk_list_unlock(self->candidates_pairs); - + TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp); TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp); - + if ((ret = _tnet_ice_ctx_build_pairs(self, self->candidates_local, self->candidates_remote, self->candidates_pairs, self->is_controlling, self->tie_breaker, self->is_ice_jingle, self->use_rtcpmux))) { TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed"); goto bail; } - + #define _FD_ISSET(_fds, _fds_count, _fd, _isset) { uint16_t __i; *_isset = 0; for (__i = 0; __i < _fds_count; ++__i) { if (_fds[__i] == _fd) { *_isset = 1; break; } } } - + // load fds for both rtp and rtcp sockets / create TURN permissions tsk_list_lock(self->candidates_pairs); - tsk_list_foreach(item, self->candidates_pairs){ - if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket){ + tsk_list_foreach(item, self->candidates_pairs) { + if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket) { continue; } - + if ((fds_count < sizeof(fds) / sizeof(fds[0])) && pair->candidate_offer->socket) { if (pair->candidate_offer->turn.ss && (ret = tnet_turn_session_get_state_createperm(pair->candidate_offer->turn.ss, pair->turn_peer_id, &e_state)) == 0) { if (e_state == tnet_stun_state_none) { @@ -1924,21 +1922,21 @@ start_conneck: } } tsk_list_unlock(self->candidates_pairs); - + concheck_timeout = self->concheck_timeout; time_start = time_curr = tsk_time_now(); time_end = (time_start + concheck_timeout); tries_count_min = fds_turn_count > 0 ? kIceConnCheckMinTriesMax : kIceConnCheckMinTriesMin; - + while (self->is_started && self->is_active && (time_curr < time_end) && !self->have_nominated_symetric) { tv.tv_sec = 0; tv.tv_usec = (rto * 1000); - + FD_ZERO(&set); for (k = 0; k < fds_count; ++k) { FD_SET(fds[k], &set); } - + // set new current time here to avoid "continue" skips // ignore already ellapsed time if new timeout value is defined time_curr = tsk_time_now(); @@ -1947,7 +1945,7 @@ start_conneck: time_start = time_curr; time_end = (time_start + concheck_timeout); } - + // Send ConnCheck requests // the pairs are already sorted by priority (from high to low) if (!self->have_nominated_symetric) { @@ -1956,21 +1954,22 @@ start_conneck: continue; } switch (pair->state_offer) { - case tnet_ice_pair_state_failed: - case tnet_ice_pair_state_succeed: - continue; - default: break; + case tnet_ice_pair_state_failed: + case tnet_ice_pair_state_succeed: + continue; + default: + break; } - + ret = tnet_ice_pair_send_conncheck((tnet_ice_pair_t *)pair); } } - + if (fds_count == 0) { tsk_thread_sleep(10); goto check_nomination; } - + if ((ret = select(fd_max + 1, &set, NULL, NULL, &tv)) < 0) { TNET_PRINT_LAST_ERROR("select() failed"); goto bail; @@ -1986,30 +1985,30 @@ start_conneck: tnet_fd_t fd = fds[k]; unsigned int len = 0; tsk_size_t read = 0; - + if (!FD_ISSET(fd, &set)) { continue; } - + // Check how many bytes are pending if ((ret = tnet_ioctlt(fd, FIONREAD, &len)) < 0) { continue; } - - if (len == 0){ + + if (len == 0) { // TSK_DEBUG_INFO("tnet_ioctlt() returent zero bytes"); continue; } - + // Receive pending data - if (recvfrom_buff_size < len){ - if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))){ + if (recvfrom_buff_size < len) { + if (!(recvfrom_buff_ptr = tsk_realloc(recvfrom_buff_ptr, len))) { recvfrom_buff_size = 0; goto bail; } recvfrom_buff_size = len; } - + // receive all messages while (self->is_started && self->is_active && read < len && ret == 0) { if ((ret = tnet_sockfd_recvfrom(fd, recvfrom_buff_ptr, recvfrom_buff_size, 0, (struct sockaddr *)&remote_addr)) < 0) { @@ -2024,13 +2023,13 @@ start_conneck: len = 0; continue; } - + TNET_PRINT_LAST_ERROR("Receiving STUN dgrams failed with errno=%d", err); goto bail; } - + read += ret; - + // recv() STUN message (request / response) ret = tnet_ice_ctx_recv_stun_message(self, recvfrom_buff_ptr, (tsk_size_t)ret, fd, &remote_addr, &role_conflict); if (ret == 0 && role_conflict) { @@ -2041,13 +2040,13 @@ start_conneck: } } } - - check_nomination: + +check_nomination: // check whether we need to re-start connection checking if (restart_conneck) { goto start_conneck; } - + check_rtcp = (self->use_rtcp && !self->use_rtcpmux); if (!self->have_nominated_offer) { self->have_nominated_offer = tnet_ice_pairs_have_nominated_offer(self->candidates_pairs, check_rtcp); @@ -2060,11 +2059,11 @@ start_conneck: self->have_nominated_symetric &= (got_hosts || ((tries_count++) >= tries_count_min)); } } // while (self->is_started... - + // "ret" could be "<>0" if last function used was "select()", "recvfrom()", "ioctlt()"...this is why we set the value to #0. // if there was an error then, we'll jump to "bail:" and next code is skipped ret = 0; - + bail: // move to the next state depending on the conncheck result if (self->is_started) { @@ -2081,11 +2080,11 @@ bail: ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_Failure); } } - + TSK_FREE(recvfrom_buff_ptr); - + self->is_connchecking = tsk_false; - + return ret; } @@ -2099,19 +2098,19 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l const tnet_ice_candidate_t *candidate; tsk_list_t* sessions = tsk_list_create(); // for lock-free TURN sessions destroying int ret; - + // When destroying TURN sessions the transport is locked by shutdown() // This function locks "self->candidates_pairs" // TURN callback locks "self->candidates_pairs" // TURN callback locks the transport // => We must not lock the candidates when destroying the TURN session // Test with WES8 if you want to reproduce the issue - + TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtp); TSK_OBJECT_SAFE_FREE(self->turn.ss_nominated_rtcp); - + tsk_list_lock(self->candidates_pairs); - + // take a reference to the negotiated TURN sessions ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &pair_offer, &pair_answer_src, &pair_answer_dest); if (ret == 0) { @@ -2123,8 +2122,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l TSK_DEBUG_INFO("ICE: nominated symetric RTP pairs: offer:%llu, answer-src:%llu, answser-dest:%llu", pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0); } - if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled - + if (ret == 0 && pair_offer) { + ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled + } + ret = tnet_ice_pairs_get_nominated_symetric_pairs(self->candidates_pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &pair_offer, &pair_answer_src, &pair_answer_dest); if (ret == 0) { if (pair_offer && pair_offer->candidate_offer && pair_offer->candidate_offer->type_e == tnet_ice_cand_type_relay && pair_offer->candidate_offer->turn.ss) { @@ -2136,8 +2137,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l self->use_rtcp ? 1 : 0, self->use_rtcpmux ? 1 : 0, pair_offer ? pair_offer->id : 0, pair_answer_src ? pair_answer_src->id : 0, pair_answer_dest ? pair_answer_dest->id : 0); } - if (ret == 0 && pair_offer) { ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; } // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled - + if (ret == 0 && pair_offer) { + ((tnet_ice_pair_t *)pair_offer)->is_nominated = tsk_true; // "is_nominated" is used do decide whether to include "USE-CANDIDATE" attribute when aggressive mode is disabled + } + // collect all useless TURN sessions (pairs) tsk_list_foreach(item, self->candidates_pairs) { if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->turn.ss) { @@ -2148,9 +2151,9 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l TSK_OBJECT_SAFE_FREE(pair->candidate_offer->turn.ss); } } - + tsk_list_unlock(self->candidates_pairs); - + // collect all useless TURN sessions (local candidates) tsk_list_lock(self->candidates_local); tsk_list_foreach(item, self->candidates_local) { @@ -2163,7 +2166,7 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l } } tsk_list_unlock(self->candidates_local); - + // collect all useless TURN sessions (remote candidates) tsk_list_lock(self->candidates_remote); tsk_list_foreach(item, self->candidates_remote) { @@ -2176,10 +2179,10 @@ static int _tnet_ice_ctx_fsm_ConnChecking_2_ConnCheckingCompleted_X_Success(va_l } } tsk_list_unlock(self->candidates_remote); - + // lock-free destruction TSK_OBJECT_SAFE_FREE(sessions); - + return _tnet_ice_ctx_signal_async(self, tnet_ice_event_type_conncheck_succeed, "ConnCheck succeed"); } @@ -2203,15 +2206,15 @@ static int _tnet_ice_ctx_fsm_Any_2_Terminated_X_AnyNotStarted(va_list *app) static int _tnet_ice_ctx_fsm_OnTerminated(tnet_ice_ctx_t* self) { TSK_DEBUG_INFO("=== ICE CTX SM Terminated ==="); - - if (!self){ + + if (!self) { TSK_DEBUG_ERROR("Invalid parameter."); return -1; } - + // still started but no longer active self->is_active = tsk_false; - + return 0; } @@ -2227,10 +2230,10 @@ static int _tnet_ice_ctx_restart(tnet_ice_ctx_t* self) TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + ret = tsk_fsm_set_current_state(self->fsm, _fsm_state_Started); ret = _tnet_ice_ctx_fsm_act(self, _fsm_action_GatherHostCandidates); - + self->is_active = (ret == 0); return ret; } @@ -2243,9 +2246,9 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + *role_conflict = tsk_false; - + if (!TNET_STUN_BUFF_IS_STUN2(((uint8_t*)data), size)) { if (self->rtp_callback) { return self->rtp_callback(self->rtp_callback_data, data, size, local_fd, remote_addr); @@ -2253,12 +2256,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const TSK_DEBUG_INFO("Not STUN message"); return 0; } - + if (!self->is_active) { TSK_DEBUG_INFO("ICE context not active yet"); return 0; } - + if ((ret = tnet_stun_pkt_read(data, size, &message)) == 0 && message) { if (message->e_type == tnet_stun_pkt_type_binding_request) { tsk_bool_t is_local_conncheck_started; @@ -2278,7 +2281,7 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const if (!pair && is_local_conncheck_started) { pair = tnet_ice_pairs_find_by_fd_and_addr(self->candidates_pairs, local_fd, remote_addr); } - if (!pair && !self->have_nominated_symetric && is_local_conncheck_started){ // pair not found and we're still negotiating + if (!pair && !self->have_nominated_symetric && is_local_conncheck_started) { // pair not found and we're still negotiating // rfc 5245 - 7.1.3.2.1. Discovering Peer Reflexive Candidates tnet_ice_pair_t* pair_peer = tnet_ice_pair_prflx_create(self->candidates_pairs, local_fd, remote_addr); if (pair_peer) { @@ -2292,12 +2295,12 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const char* resp_phrase = tsk_null; // authenticate the request tnet_ice_pair_auth_conncheck(pair, message, data, size, &resp_code, &resp_phrase); - if (resp_code > 0 && resp_phrase){ - if (resp_code >= 200 && resp_code <= 299){ + if (resp_code > 0 && resp_phrase) { + if (resp_code >= 200 && resp_code <= 299) { // Before sending the success response check that there are no role conflict - if (self->is_controlling){ // I'm ICE-CONTROLLING + if (self->is_controlling) { // I'm ICE-CONTROLLING const tnet_stun_attr_vdata_t* stun_att_ice_controlling; - if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling){ + if ((ret = tnet_stun_pkt_attr_find_first(message, tnet_stun_attr_type_ice_controlling, (const tnet_stun_attr_t**)&stun_att_ice_controlling)) == 0 && stun_att_ice_controlling) { TSK_DEBUG_WARN("Role conflicts (SEND)"); if (self->tie_breaker >= *((uint64_t*)stun_att_ice_controlling->p_data_ptr)) { resp_code = kStunErrCodeIceConflict; @@ -2363,13 +2366,13 @@ static int _tnet_ice_ctx_recv_stun_message_for_pair(tnet_ice_ctx_t* self, const } } TSK_OBJECT_SAFE_FREE(message); - + return ret; } static int _tnet_ice_ctx_send_turn_raw(struct tnet_ice_ctx_s* self, struct tnet_turn_session_s* turn_ss, tnet_turn_peer_id_t turn_peer_id, const void* data, tsk_size_t size) { - if (!self || !turn_ss || !data || !size){ + if (!self || !turn_ss || !data || !size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -2386,21 +2389,21 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi tnet_ice_pair_t *pair; enum tnet_turn_transport_e e_req_transport; tnet_family_t addr_family_local, addr_family_remote; - + if (!self || TSK_LIST_IS_EMPTY(local_candidates) || TSK_LIST_IS_EMPTY(remote_candidates) || !result_pairs) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + self->is_building_pairs = tsk_true; TSK_DEBUG_INFO("ICE: begin building pairs(is_rtcpmuxed=%d)", is_rtcpmuxed); - + tsk_list_clear_items(result_pairs); - + tsk_list_lock(local_candidates); tsk_list_lock(remote_candidates); tsk_list_lock(result_pairs); - + tsk_list_foreach(item_local, local_candidates) { if (!(cand_local = item_local->data)) { continue; @@ -2413,7 +2416,7 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi continue; } #endif - + tsk_list_foreach(item_remote, remote_candidates) { if (!(cand_remote = item_remote->data)) { continue; @@ -2423,9 +2426,9 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi TSK_DEBUG_INFO("Skipping remote ICE candidate with port = 0"); continue; } - + // CompIds(1=RTP, 2=RTCP) must match - if ((cand_remote->comp_id != cand_local->comp_id)){ + if ((cand_remote->comp_id != cand_local->comp_id)) { continue; } // IP versions must match. Cannot use IPv4 socket to send/recv to IPv6 address. @@ -2453,18 +2456,18 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi continue; } } - + if ((pair = tnet_ice_pair_create(cand_local, cand_remote, is_controlling, tie_breaker, is_ice_jingle))) { TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %u %s %d] -> [%s %u %u %s %d]", pair->id, pair->priority, - + cand_local->foundation, cand_local->priority, cand_local->comp_id, cand_local->connection_addr, cand_local->port, - + cand_remote->foundation, cand_remote->priority, cand_remote->comp_id, @@ -2479,31 +2482,31 @@ static int _tnet_ice_ctx_build_pairs(struct tnet_ice_ctx_s* self, tnet_ice_candi if (!(pair = item_local->data)) { continue; } - + TSK_DEBUG_INFO("ICE Pair(%llu, %llu): [%s %u %s %d] -> [%s %u %s %d]", pair->id, pair->priority, - + pair->candidate_offer->foundation, pair->candidate_offer->comp_id, pair->candidate_offer->connection_addr, pair->candidate_offer->port, - + pair->candidate_answer->foundation, pair->candidate_answer->comp_id, pair->candidate_answer->connection_addr, pair->candidate_answer->port); } #endif - + tsk_list_unlock(local_candidates); tsk_list_unlock(remote_candidates); tsk_list_unlock(result_pairs); - + self->is_building_pairs = tsk_false; tsk_condwait_broadcast(self->condwait_pairs); TSK_DEBUG_INFO("ICE: end building pairs"); - + return 0; } @@ -2514,32 +2517,32 @@ static int _tnet_ice_ctx_fsm_act(tnet_ice_ctx_t* self, tsk_fsm_action_id action_ tnet_ice_event_t* e = tsk_null; static const char* phrase = "$action$"; int ret = 0; - - if (!self || !self->fsm){ + + if (!self || !self->fsm) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (!(action = tnet_ice_action_create(action_id))){ + if (!(action = tnet_ice_action_create(action_id))) { TSK_DEBUG_ERROR("Failed to create action"); return -2; } - + if (self->is_sync_mode) { ret = tsk_fsm_act(self->fsm, action->id, self, action, self, action); } else { - if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))){ + if ((e = tnet_ice_event_create(self, tnet_ice_event_type_action, phrase, self->userdata))) { tnet_ice_event_set_action(e, action); TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e); goto bail; } - else{ + else { TSK_DEBUG_ERROR("Failed to create ICE event"); ret = -2; goto bail; } } - + bail: TSK_OBJECT_SAFE_FREE(e); TSK_OBJECT_SAFE_FREE(action); @@ -2549,21 +2552,21 @@ bail: static int _tnet_ice_ctx_signal_async(tnet_ice_ctx_t* self, tnet_ice_event_type_t type, const char* phrase) { tnet_ice_event_t* e; - if (!self){ + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (self->is_silent_mode && type != tnet_ice_event_type_action) { // silent mode ON and not action to move the FSM TSK_DEBUG_INFO("ICE silent mode ON...to not notify '%d:%s'", type, phrase); return 0; } - - if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))){ + + if ((e = tnet_ice_event_create(self, type, phrase, self->userdata))) { TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(self), e); return 0; } - else{ + else { TSK_DEBUG_ERROR("Failed to create ICE event"); return -2; } @@ -2574,114 +2577,110 @@ static int _tnet_ice_ctx_turn_callback(const struct tnet_turn_session_event_xs * tnet_ice_ctx_t *ctx = tsk_object_ref(TSK_OBJECT(e->pc_usr_data)); struct tnet_turn_session_s* session = tsk_object_ref(TSK_OBJECT(e->pc_session)); int ret = 0; - + if (!ctx) { // the ICE context is being destroyed but TURN session not freed yet goto bail; } - + switch (e->e_type) { - case tnet_turn_session_event_type_alloc_ok: - case tnet_turn_session_event_type_refresh_ok: - case tnet_turn_session_event_type_chanbind_ok: - case tnet_turn_session_event_type_connect_ok: - default: - { - break; - } - - case tnet_turn_session_event_type_alloc_nok: - case tnet_turn_session_event_type_refresh_nok: - case tnet_turn_session_event_type_perm_nok: - case tnet_turn_session_event_type_chanbind_nok: - case tnet_turn_session_event_type_connect_nok: - { - // Do not raise error event if no nominated candidate because - // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case. - if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) { - TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id); - if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) { - goto bail; - } + case tnet_turn_session_event_type_alloc_ok: + case tnet_turn_session_event_type_refresh_ok: + case tnet_turn_session_event_type_chanbind_ok: + case tnet_turn_session_event_type_connect_ok: + default: { + break; + } + + case tnet_turn_session_event_type_alloc_nok: + case tnet_turn_session_event_type_refresh_nok: + case tnet_turn_session_event_type_perm_nok: + case tnet_turn_session_event_type_chanbind_nok: + case tnet_turn_session_event_type_connect_nok: { + // Do not raise error event if no nominated candidate because + // TURN error could be raised by the session when we're in "conncheck" state and this is a normal case. + if (ctx->is_active && ctx->is_started && ctx->turn.ss_nominated_rtp && ctx->turn.peer_id_rtp == e->u_peer_id) { + TSK_DEBUG_ERROR("TURN connection broken (peer-id=%ld)", e->u_peer_id); + if ((ret = _tnet_ice_ctx_signal_async(ctx, tnet_ice_event_type_turn_connection_broken, "TURN connection is broken"))) { + goto bail; } - break; } - - case tnet_turn_session_event_type_perm_ok: - { - enum tnet_turn_transport_e e_req_transport; - if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) { + break; + } + + case tnet_turn_session_event_type_perm_ok: { + enum tnet_turn_transport_e e_req_transport; + if ((ret = tnet_turn_session_get_req_transport(session, &e_req_transport))) { + goto bail; + } + + if (e_req_transport == tnet_turn_transport_tcp) { + // TCP-Connect: rfc6062 - 4.3. Initiating a Connection + if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) { goto bail; } - - if (e_req_transport == tnet_turn_transport_tcp) { - // TCP-Connect: rfc6062 - 4.3. Initiating a Connection - if ((ret = tnet_turn_session_connect(session, e->u_peer_id))) { - goto bail; - } + } + else { + // Bind a channel (not required). If succeed, will be used to save bandwidth usage. + // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed. + if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) { + goto bail; } - else { - // Bind a channel (not required). If succeed, will be used to save bandwidth usage. - // TODO: should be done only if first "get_state(chanbind)==none". Not an issue, if it already exists then, will be refreshed. - if ((ret = tnet_turn_session_chanbind(session, e->u_peer_id))) { - goto bail; + } + break; + } + + case tnet_turn_session_event_type_recv_data: { + tsk_bool_t role_conflict; + tnet_ice_pair_t* pair = tsk_null; + if (e->u_peer_id != kTurnPeerIdInvalid) { + const tsk_list_item_t *item; + tsk_list_lock(ctx->candidates_pairs); + tsk_list_foreach(item, ctx->candidates_pairs) { + if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) { + pair = tsk_object_ref((void*)item->data); + break; } } - break; + tsk_list_unlock(ctx->candidates_pairs); } - - case tnet_turn_session_event_type_recv_data: - { - tsk_bool_t role_conflict; - tnet_ice_pair_t* pair = tsk_null; - if (e->u_peer_id != kTurnPeerIdInvalid) { - const tsk_list_item_t *item; - tsk_list_lock(ctx->candidates_pairs); - tsk_list_foreach(item, ctx->candidates_pairs) { - if (((const tnet_ice_pair_t*)item->data)->turn_peer_id == e->u_peer_id) { - pair = tsk_object_ref((void*)item->data); - break; - } - } - tsk_list_unlock(ctx->candidates_pairs); - } - - ret = _tnet_ice_ctx_recv_stun_message_for_pair( - ctx, - pair, - e->data.pc_data_ptr, e->data.u_data_size, - e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD, - e->pc_enet ? &e->pc_enet->remote_addr : tsk_null, - &role_conflict); - TSK_OBJECT_SAFE_FREE(pair); - if (ret) { + + ret = _tnet_ice_ctx_recv_stun_message_for_pair( + ctx, + pair, + e->data.pc_data_ptr, e->data.u_data_size, + e->pc_enet ? e->pc_enet->local_fd : TNET_INVALID_FD, + e->pc_enet ? &e->pc_enet->remote_addr : tsk_null, + &role_conflict); + TSK_OBJECT_SAFE_FREE(pair); + if (ret) { + goto bail; + } + + // rebuild candidates if role conflict + if (role_conflict) { + tsk_list_lock(ctx->candidates_pairs); + tsk_list_clear_items(ctx->candidates_pairs); + tsk_list_unlock(ctx->candidates_pairs); + + TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp); + TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp); + + if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) { + TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed"); goto bail; } - - // rebuild candidates if role conflict - if (role_conflict) { - tsk_list_lock(ctx->candidates_pairs); - tsk_list_clear_items(ctx->candidates_pairs); - tsk_list_unlock(ctx->candidates_pairs); - - TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtp); - TSK_OBJECT_SAFE_FREE(ctx->turn.ss_nominated_rtcp); - - if ((ret = _tnet_ice_ctx_build_pairs(ctx, ctx->candidates_local, ctx->candidates_remote, ctx->candidates_pairs, ctx->is_controlling, ctx->tie_breaker, ctx->is_ice_jingle, ctx->use_rtcpmux))) { - TSK_DEBUG_ERROR("_tnet_ice_ctx_build_pairs() failed"); - goto bail; - } - } - - break; } + + break; } - + } + // alert() waiting threads if ((ret = tsk_condwait_broadcast(ctx->turn.condwait))) { goto bail; } - + bail: tsk_object_unref(ctx); tsk_object_unref(session); @@ -2694,42 +2693,40 @@ static void* TSK_STDCALL _tnet_ice_ctx_run(void* self) tsk_list_item_t *curr; tnet_ice_ctx_t *ctx = (tnet_ice_ctx_t *)(self); tnet_ice_event_t *e; - + TSK_DEBUG_INFO("ICE CTX::run -- START"); - + TSK_RUNNABLE_RUN_BEGIN(ctx); - + // must because "ctx->callback(e);" could call a function trying to free "ctx" // do not move before "TSK_RUNNABLE_RUN_BEGIN(ctx)", otherwise it'll be required to stop the "runnable" to have "ctx->refCount==0" ctx = tsk_object_ref(ctx); - + if (ctx->is_started && (curr = TSK_RUNNABLE_POP_FIRST(ctx))) { e = (tnet_ice_event_t*)curr->data; switch (e->type) { - case tnet_ice_event_type_action: - { - if (e->action) { - tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action); - } - break; + case tnet_ice_event_type_action: { + if (e->action) { + tsk_fsm_act(ctx->fsm, e->action->id, ctx, e->action, ctx, e->action); } - default: - { - if (ctx->callback){ - ctx->callback(e); - } - break; + break; + } + default: { + if (ctx->callback) { + ctx->callback(e); } + break; + } } tsk_object_unref(curr); } - + if (!(ctx = tsk_object_unref(ctx))) { goto exit; } - + TSK_RUNNABLE_RUN_END(ctx); - + exit: if (ctx) { tsk_list_clear_items(ctx->candidates_local); @@ -2738,9 +2735,9 @@ exit: tsk_list_clear_items(ctx->candidates_pairs); tsk_list_unlock(ctx->candidates_pairs); } - + TSK_DEBUG_INFO("ICE CTX::run -- STOP"); - + return 0; } @@ -2768,7 +2765,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + // TURN requires credentials if ((e_proto & tnet_ice_server_proto_turn) == tnet_ice_server_proto_turn && (tsk_strnullORempty(str_username) || tsk_strnullORempty(str_password))) { /* rfc5766 - 4. General Behavior @@ -2791,7 +2788,7 @@ static int _tnet_ice_ctx_server_add(struct tnet_ice_ctx_s* self, enum tnet_ice_s } tsk_list_push_back_data(self->servers, (void**)&ice_server); TSK_OBJECT_SAFE_FREE(ice_server); - + ret = 0; bail: tsk_list_unlock(self->servers); diff --git a/tinyNET/src/ice/tnet_ice_ctx.h b/tinyNET/src/ice/tnet_ice_ctx.h index 015fdcf..8be8164 100755 --- a/tinyNET/src/ice/tnet_ice_ctx.h +++ b/tinyNET/src/ice/tnet_ice_ctx.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2012-2015 Doubango Telecom <http://www.doubango.org>. -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -46,21 +46,21 @@ TINYNET_API struct tnet_ice_ctx_s* tnet_ice_ctx_create(tsk_bool_t is_ice_jingle, TINYNET_API int tnet_ice_ctx_set_userdata(struct tnet_ice_ctx_s* self, const void* userdata); //@deprecated: Use "tnet_ice_ctx_add_server()" TNET_DEPRECATED(TINYNET_API int tnet_ice_ctx_set_stun( - struct tnet_ice_ctx_s* self, - const char* server_addr, - uint16_t server_port, - const char* software, - const char* username, - const char* password)); + struct tnet_ice_ctx_s* self, + const char* server_addr, + uint16_t server_port, + const char* software, + const char* username, + const char* password)); TINYNET_API int tnet_ice_ctx_add_server( - struct tnet_ice_ctx_s* self, - const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"... - const char* server_addr, - uint16_t server_port, - tsk_bool_t use_turn, - tsk_bool_t use_stun, - const char* username, - const char* password); + struct tnet_ice_ctx_s* self, + const char* transport_proto, // "udp", "tcp", "tls", "ws", "wss"... + const char* server_addr, + uint16_t server_port, + tsk_bool_t use_turn, + tsk_bool_t use_stun, + const char* username, + const char* password); #define tnet_ice_ctx_add_server_turn(self, transport_proto, server_addr, server_port, username, password) \ tnet_ice_ctx_add_server((self), (transport_proto), (server_addr), (server_port), tsk_true/*use_turn*/, tsk_false/*use_stun*/, (username), (password)) #define tnet_ice_ctx_add_server_stun(self, transport_proto, server_addr, server_port, username, password) \ @@ -90,9 +90,9 @@ TINYNET_API tsk_bool_t tnet_ice_ctx_is_can_recv(const struct tnet_ice_ctx_s* sel TINYNET_API tsk_bool_t tnet_ice_ctx_use_ipv6(const struct tnet_ice_ctx_s* self); TINYNET_API tsk_bool_t tnet_ice_ctx_use_rtcp(const struct tnet_ice_ctx_s* self); TINYNET_API int tnet_ice_ctx_get_nominated_symetric_candidates(const struct tnet_ice_ctx_s* self, uint32_t comp_id, - const struct tnet_ice_candidate_s** candidate_offer, - const struct tnet_ice_candidate_s** candidate_answer_src, - const struct tnet_ice_candidate_s** candidate_answer_dest); + const struct tnet_ice_candidate_s** candidate_offer, + const struct tnet_ice_candidate_s** candidate_answer_src, + const struct tnet_ice_candidate_s** candidate_answer_dest); TINYNET_API int tnet_ice_ctx_recv_stun_message(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr, tsk_bool_t *role_conflict); TINYNET_API int tnet_ice_ctx_send_turn_rtp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size); TINYNET_API int tnet_ice_ctx_send_turn_rtcp(struct tnet_ice_ctx_s* self, const void* data, tsk_size_t size); diff --git a/tinyNET/src/ice/tnet_ice_event.c b/tinyNET/src/ice/tnet_ice_event.c index 480202f..1826c3b 100755 --- a/tinyNET/src/ice/tnet_ice_event.c +++ b/tinyNET/src/ice/tnet_ice_event.c @@ -27,24 +27,23 @@ static tsk_object_t* tnet_ice_event_ctor(tsk_object_t * self, va_list * app) { tnet_ice_event_t *e = self; - if(e){ - + if(e) { + } return self; } static tsk_object_t* tnet_ice_event_dtor(tsk_object_t * self) { tnet_ice_event_t *e = self; - if(e){ + if(e) { TSK_SAFE_FREE(e->phrase); TSK_OBJECT_SAFE_FREE(e->action); e->ctx = tsk_null; // not the owner (const) } - + return self; } -static const tsk_object_def_t tnet_ice_event_def_s = -{ +static const tsk_object_def_t tnet_ice_event_def_s = { sizeof(tnet_ice_event_t), tnet_ice_event_ctor, tnet_ice_event_dtor, @@ -56,29 +55,29 @@ const tsk_object_def_t *tnet_ice_event_def_t = &tnet_ice_event_def_s; tnet_ice_event_t* tnet_ice_event_create(const struct tnet_ice_ctx_s* ctx, tnet_ice_event_type_t type, const char* phrase, const void* userdata) { tnet_ice_event_t* e; - - if((e = tsk_object_new(tnet_ice_event_def_t))){ + + if((e = tsk_object_new(tnet_ice_event_def_t))) { e->ctx = ctx; e->type = type; e->phrase = tsk_strdup(phrase); e->userdata = userdata; } - else{ + else { TSK_DEBUG_ERROR("Failed to create ICE event"); } - + return e; } int tnet_ice_event_set_action(tnet_ice_event_t* self, struct tnet_ice_action_s* action) { - if(!self){ + if(!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } self->type = tnet_ice_event_type_action; TSK_OBJECT_SAFE_FREE(self->action); - if(action){ + if(action) { self->action = tsk_object_ref(action); } return 0; diff --git a/tinyNET/src/ice/tnet_ice_event.h b/tinyNET/src/ice/tnet_ice_event.h index 8f2f72e..404f765 100755 --- a/tinyNET/src/ice/tnet_ice_event.h +++ b/tinyNET/src/ice/tnet_ice_event.h @@ -8,12 +8,12 @@ * 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. * @@ -28,40 +28,38 @@ TNET_BEGIN_DECLS -typedef enum tnet_ice_event_type_e -{ - // Public events - tnet_ice_event_type_started, - tnet_ice_event_type_start_failed, - tnet_ice_event_type_stopped, - tnet_ice_event_type_stop_failed, - tnet_ice_event_type_gathering_host_candidates_failed, - tnet_ice_event_type_gathering_host_candidates_succeed, - tnet_ice_event_type_gathering_reflexive_candidates_failed, - tnet_ice_event_type_gathering_reflexive_candidates_succeed, - tnet_ice_event_type_gathering_relay_candidates_failed, - tnet_ice_event_type_gathering_relay_candidates_succeed, - tnet_ice_event_type_gathering_completed, - tnet_ice_event_type_conncheck_succeed, - tnet_ice_event_type_conncheck_failed, - tnet_ice_event_type_cancelled, - tnet_ice_event_type_turn_connection_broken, +typedef enum tnet_ice_event_type_e { + // Public events + tnet_ice_event_type_started, + tnet_ice_event_type_start_failed, + tnet_ice_event_type_stopped, + tnet_ice_event_type_stop_failed, + tnet_ice_event_type_gathering_host_candidates_failed, + tnet_ice_event_type_gathering_host_candidates_succeed, + tnet_ice_event_type_gathering_reflexive_candidates_failed, + tnet_ice_event_type_gathering_reflexive_candidates_succeed, + tnet_ice_event_type_gathering_relay_candidates_failed, + tnet_ice_event_type_gathering_relay_candidates_succeed, + tnet_ice_event_type_gathering_completed, + tnet_ice_event_type_conncheck_succeed, + tnet_ice_event_type_conncheck_failed, + tnet_ice_event_type_cancelled, + tnet_ice_event_type_turn_connection_broken, - // Private events - tnet_ice_event_type_action + // Private events + tnet_ice_event_type_action } tnet_ice_event_type_t; -typedef struct tnet_ice_event_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_ice_event_s { + TSK_DECLARE_OBJECT; - tnet_ice_event_type_t type; - char* phrase; - struct tnet_ice_action_s* action; - const struct tnet_ice_ctx_s* ctx; + tnet_ice_event_type_t type; + char* phrase; + struct tnet_ice_action_s* action; + const struct tnet_ice_ctx_s* ctx; - const void* userdata; + const void* userdata; } tnet_ice_event_t; diff --git a/tinyNET/src/ice/tnet_ice_pair.c b/tinyNET/src/ice/tnet_ice_pair.c index 33e71a5..f917ea2 100755 --- a/tinyNET/src/ice/tnet_ice_pair.c +++ b/tinyNET/src/ice/tnet_ice_pair.c @@ -58,7 +58,7 @@ static int __pred_find_by_pair(const tsk_list_item_t *item, const void *pair) { - if(item && item->data){ + if(item && item->data) { int ret; tsk_subsat_int32_ptr(item->data, pair, &ret); return ret; @@ -70,7 +70,7 @@ static int __pred_find_by_pair(const tsk_list_item_t *item, const void *pair) static tsk_object_t* tnet_ice_pair_ctor(tsk_object_t * self, va_list * app) { tnet_ice_pair_t *pair = self; - if(pair){ + if(pair) { pair->state_offer = tnet_ice_pair_state_frozen; pair->state_answer = tnet_ice_pair_state_frozen; } @@ -90,7 +90,7 @@ static int tnet_ice_pair_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2) { const tnet_ice_pair_t *p1 = _p1; const tnet_ice_pair_t *p2 = _p2; - + if (p1 && p2) { #if 0 // This is not correct and most differences (if not all) will be equal to "INT_MIN" or "INT_MAX" and this will produce invalid sorting. @@ -102,11 +102,14 @@ static int tnet_ice_pair_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2) return (p1->priority == p2->priority) ? 0 : (p1->priority > p2->priority ? 1 : -1); #endif } - else if (!p1 && !p2) return 0; - else return -1; + else if (!p1 && !p2) { + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_ice_pair_def_s = -{ +static const tsk_object_def_t tnet_ice_pair_def_s = { sizeof(tnet_ice_pair_t), tnet_ice_pair_ctor, tnet_ice_pair_dtor, @@ -117,11 +120,11 @@ tnet_ice_pair_t* tnet_ice_pair_create(const tnet_ice_candidate_t* candidate_offe { static uint64_t __unique_id = 0; tnet_ice_pair_t *pair; - if(!candidate_offer || !candidate_answer){ + if(!candidate_offer || !candidate_answer) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - + if ((pair = tsk_object_new(&tnet_ice_pair_def_s))) { uint64_t G, D; pair->id = ++__unique_id; // not part of the standard, used to ease debugging @@ -136,7 +139,7 @@ tnet_ice_pair_t* tnet_ice_pair_create(const tnet_ice_candidate_t* candidate_offe pair->priority = ((TSK_MIN(G, D)) << 32) + (TSK_MAX(G, D) << 1) + ((G > D) ? 1 : 0); pair->turn_peer_id = kTurnPeerIdInvalid; } - + return pair; } @@ -148,12 +151,12 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t const tnet_ice_pair_t *pair_local = tsk_null, *pair = tsk_null; tnet_ip_t remote_ip; tnet_port_t remote_port; - + if (!pairs || !remote_addr) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - + tsk_list_foreach(item, pairs) { if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_answer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) { continue; @@ -161,12 +164,12 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t pair_local = pair; break; } - + if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))) { TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed"); return tsk_null; } - + if (!pair_local) { TSK_DEBUG_ERROR("Cannot create prflx candidate with remote ip = %s, remote port = %u and local_fd = %d", remote_ip, remote_port, local_fd); return tsk_null; @@ -182,42 +185,42 @@ tnet_ice_pair_t* tnet_ice_pair_prflx_create(tnet_ice_pairs_L_t* pairs, tnet_fd_t cand_remote->comp_id = pair_local->candidate_offer->comp_id; memcpy(cand_remote->connection_addr, remote_ip, sizeof(tnet_ip_t)); cand_remote->port = remote_port; - + TSK_DEBUG_INFO("ICE Pair Reflexive Candidate (%llu, %llu): [%s %u %u %s %d] -> [%s %u %u %s %d]", pair->id, pair->priority, - + cand_local->foundation, cand_local->priority, cand_local->comp_id, cand_local->connection_addr, cand_local->port, - + cand_remote->foundation, cand_remote->priority, cand_remote->comp_id, cand_remote->connection_addr, cand_remote->port); - + pair_peer = tnet_ice_pair_create(cand_local, cand_remote, pair_local->is_controlling, pair_local->tie_breaker, pair_local->is_ice_jingle); } TSK_OBJECT_SAFE_FREE(cand_local); TSK_OBJECT_SAFE_FREE(cand_remote); return pair_peer; } - + return tsk_null; } int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) { int ret; - - if(!self){ + + if(!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (self->candidate_offer->turn.ss) { enum tnet_stun_state_e e_state; enum tnet_turn_transport_e e_req_transport; @@ -228,7 +231,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN ConnCheck (peer-id=%ld)", self->turn_peer_id); goto bail; } - + if ((ret = tnet_turn_session_get_req_transport(self->candidate_offer->turn.ss, &e_req_transport))) { goto bail; } @@ -244,16 +247,16 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) } } } - + if (!self->last_request) { uint32_t priority; - + // Init remote address if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &self->remote_addr))) { TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port); goto bail; } - + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_binding_request, &self->last_request))) { goto bail; } @@ -266,7 +269,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) if (self->is_ice_jingle) { tsk_sprintf(&p_uname, "%s%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer)); } - else{ + else { tsk_sprintf(&p_uname, "%s:%s", tnet_ice_candidate_get_ufrag(self->candidate_answer), tnet_ice_candidate_get_ufrag(self->candidate_offer)); } pc_pwd = tnet_ice_candidate_get_pwd(self->candidate_answer); @@ -276,7 +279,7 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) goto bail; } } - + priority = tnet_ice_utils_get_priority(tnet_ice_cand_type_prflx, self->candidate_offer->local_pref, self->candidate_offer->is_rtp); // add attributes self->last_request->opt.dontfrag = 0; @@ -333,176 +336,176 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) #if TNET_ICE_AGGRESSIVE_NOMINATION if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) { #else - if (self->is_nominated && !tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) { + if (self->is_nominated && !tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_use_candidate)) { #endif - ret = tnet_stun_pkt_attrs_add(self->last_request, - TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(), + ret = tnet_stun_pkt_attrs_add(self->last_request, + TNET_STUN_PKT_ATTR_ADD_ICE_USE_CANDIDATE(), + TNET_STUN_PKT_ATTR_ADD_NULL()); + + if (ret) { + goto bail; + } + b_changed = tsk_true; + } + } + else { + tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_use_candidate); + tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlling); + if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlled)) { + ret = tnet_stun_pkt_attrs_add(self->last_request, + TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + b_changed = tsk_true; + } + } + // update transac-id if the request structure changed + if ((b_changed && (ret = tnet_stun_utils_transac_id_rand(&self->last_request->transac_id)))) { + goto bail; + } + } + + // Send request + { + tsk_buffer_t *req_buffer = tsk_null; + self->last_request->opt.fingerprint = !self->is_ice_jingle; + if ((ret = tnet_stun_pkt_write_with_padding_2(self->last_request, &req_buffer))) { + goto bail; + } + if (self->candidate_offer->turn.ss) { + // Send using TURN session. Above, we already checked that the TURN session is ready (Alloc=OK, Permission=OK) + ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size); + } + else { + int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&self->remote_addr, req_buffer->data, req_buffer->size); + ret = (sendBytes == req_buffer->size) ? 0 : -9; + } + TSK_OBJECT_SAFE_FREE(req_buffer); + if (ret) { + goto bail; + } + } + +bail: + if (ret == 0 && self->state_offer == tnet_ice_pair_state_frozen) { + self->state_offer = tnet_ice_pair_state_in_progress; + } + return ret; +} + +int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr) +{ + tnet_stun_pkt_t* message = tsk_null; + const char *password, *username; + int ret = -1; + tsk_bool_t is_error = ((code / 100) != 2); + + if(!self || !phrase || !request || !self->candidate_offer || !self->candidate_answer) { + TSK_DEBUG_ERROR("Invalid paramter"); + return -1; + } + + username = tsk_null; + password = tnet_ice_candidate_get_pwd(self->candidate_offer); + + if ((ret = tnet_stun_pkt_create_empty(is_error ? tnet_stun_pkt_type_binding_error_response : tnet_stun_pkt_type_binding_success_response, &message)) == 0) { + tsk_buffer_t *req_buffer = tsk_null; + memcpy(message->transac_id, request->transac_id, sizeof(request->transac_id)); + message->opt.fingerprint = !self->is_ice_jingle; + message->opt.dontfrag = 0; + + // SOFWARE + ret = tnet_stun_pkt_attrs_add(message, + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + // SHORT-TERM authentication even for responses + if ((ret = tnet_stun_pkt_auth_prepare_shortterm_2(message, password))) { + goto bail; + } + + // ERROR + if (is_error) { + ret = tnet_stun_pkt_attrs_add(message, + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(((code / 100) & 0x07), (code - ((code / 100) * 100)), phrase), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + else { + tnet_ip_t remote_ip; + tnet_port_t remote_port; + if (self->is_ice_jingle) { + const tnet_stun_attr_vdata_t *pc_attr_vdata; + // USERNAME + if ((ret = tnet_stun_pkt_attr_find_first(request, tnet_stun_attr_type_username, (const tnet_stun_attr_t **)&pc_attr_vdata)) == 0 && pc_attr_vdata) { + ret = tnet_stun_pkt_attrs_add(message, + TNET_STUN_PKT_ATTR_ADD_USERNAME(pc_attr_vdata->p_data_ptr, pc_attr_vdata->u_data_size), TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { goto bail; } - b_changed = tsk_true; } } - else { - tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_use_candidate); - tnet_stun_pkt_attr_remove(self->last_request, tnet_stun_attr_type_ice_controlling); - if (!tnet_stun_pkt_attr_exists(self->last_request, tnet_stun_attr_type_ice_controlled)) { - ret = tnet_stun_pkt_attrs_add(self->last_request, - TNET_STUN_PKT_ATTR_ADD_ICE_CONTROLLED(self->tie_breaker), + // MAPPED-ADDRESS and XOR-MAPPED-ADDRESS + if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port)) == 0) { + tnet_stun_addr_t _addr; + tnet_stun_address_family_t _familly = (remote_addr->ss_family == AF_INET6) ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4; + if ((ret = tnet_stun_utils_inet_pton((_familly == tnet_stun_address_family_ipv6), remote_ip, &_addr)) == 0) { + ret = tnet_stun_pkt_attrs_add(message, + TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(_familly, remote_port, &_addr), + TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(_familly, remote_port, &_addr), TNET_STUN_PKT_ATTR_ADD_NULL()); if (ret) { goto bail; } - b_changed = tsk_true; } } - // update transac-id if the request structure changed - if ((b_changed && (ret = tnet_stun_utils_transac_id_rand(&self->last_request->transac_id)))) { - goto bail; - } } - - // Send request - { - tsk_buffer_t *req_buffer = tsk_null; - self->last_request->opt.fingerprint = !self->is_ice_jingle; - if ((ret = tnet_stun_pkt_write_with_padding_2(self->last_request, &req_buffer))) { + + if (self->candidate_offer->turn.ss) { + enum tnet_stun_state_e e_state; + if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) { goto bail; } - if (self->candidate_offer->turn.ss) { - // Send using TURN session. Above, we already checked that the TURN session is ready (Alloc=OK, Permission=OK) - ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size); + if (e_state != tnet_stun_state_ok) { + TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN response (peer-id=%ld)", self->turn_peer_id); + goto bail; } - else { - int sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&self->remote_addr, req_buffer->data, req_buffer->size); - ret = (sendBytes == req_buffer->size) ? 0 : -9; + if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) { + goto bail; } - TSK_OBJECT_SAFE_FREE(req_buffer); - if (ret) { + if ((ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size))) { goto bail; } } - - bail: - if (ret == 0 && self->state_offer == tnet_ice_pair_state_frozen) { - self->state_offer = tnet_ice_pair_state_in_progress; - } - return ret; - } - - int tnet_ice_pair_send_response(tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const short code, const char* phrase, const struct sockaddr_storage *remote_addr) - { - tnet_stun_pkt_t* message = tsk_null; - const char *password, *username; - int ret = -1; - tsk_bool_t is_error = ((code / 100) != 2); - - if(!self || !phrase || !request || !self->candidate_offer || !self->candidate_answer){ - TSK_DEBUG_ERROR("Invalid paramter"); - return -1; - } - - username = tsk_null; - password = tnet_ice_candidate_get_pwd(self->candidate_offer); - - if ((ret = tnet_stun_pkt_create_empty(is_error ? tnet_stun_pkt_type_binding_error_response : tnet_stun_pkt_type_binding_success_response, &message)) == 0) { - tsk_buffer_t *req_buffer = tsk_null; - memcpy(message->transac_id, request->transac_id, sizeof(request->transac_id)); - message->opt.fingerprint = !self->is_ice_jingle; - message->opt.dontfrag = 0; - - // SOFWARE - ret = tnet_stun_pkt_attrs_add(message, - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { + else { + struct sockaddr_storage dest_addr; + int sendBytes; + if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))) { + TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port); goto bail; } - - // SHORT-TERM authentication even for responses - if ((ret = tnet_stun_pkt_auth_prepare_shortterm_2(message, password))) { + if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) { goto bail; } - - // ERROR - if (is_error) { - ret = tnet_stun_pkt_attrs_add(message, - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(((code / 100) & 0x07), (code - ((code / 100) * 100)), phrase), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - else { - tnet_ip_t remote_ip; - tnet_port_t remote_port; - if (self->is_ice_jingle) { - const tnet_stun_attr_vdata_t *pc_attr_vdata; - // USERNAME - if ((ret = tnet_stun_pkt_attr_find_first(request, tnet_stun_attr_type_username, (const tnet_stun_attr_t **)&pc_attr_vdata)) == 0 && pc_attr_vdata) { - ret = tnet_stun_pkt_attrs_add(message, - TNET_STUN_PKT_ATTR_ADD_USERNAME(pc_attr_vdata->p_data_ptr, pc_attr_vdata->u_data_size), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - } - // MAPPED-ADDRESS and XOR-MAPPED-ADDRESS - if ((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port)) == 0) { - tnet_stun_addr_t _addr; - tnet_stun_address_family_t _familly = (remote_addr->ss_family == AF_INET6) ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4; - if ((ret = tnet_stun_utils_inet_pton((_familly == tnet_stun_address_family_ipv6), remote_ip, &_addr)) == 0) { - ret = tnet_stun_pkt_attrs_add(message, - TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS(_familly, remote_port, &_addr), - TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS(_familly, remote_port, &_addr), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - } - } - - if (self->candidate_offer->turn.ss) { - enum tnet_stun_state_e e_state; - if ((ret = tnet_turn_session_get_state_createperm(self->candidate_offer->turn.ss, self->turn_peer_id, &e_state))) { - goto bail; - } - if (e_state != tnet_stun_state_ok) { - TSK_DEBUG_INFO("TURN CreatePerm not ready yet... to send STUN response (peer-id=%ld)", self->turn_peer_id); - goto bail; - } - if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) { - goto bail; - } - if ((ret = tnet_turn_session_send_data(self->candidate_offer->turn.ss, self->turn_peer_id, req_buffer->data, (uint16_t)req_buffer->size))) { - goto bail; - } - } - else { - struct sockaddr_storage dest_addr; - int sendBytes; - if ((ret = tnet_sockaddr_init(self->candidate_answer->connection_addr, self->candidate_answer->port, self->candidate_offer->socket->type, &dest_addr))) { - TNET_PRINT_LAST_ERROR("tnet_sockaddr_init(%s:%d) failed", self->candidate_answer->connection_addr, self->candidate_answer->port); - goto bail; - } - if ((ret = tnet_stun_pkt_write_with_padding_2(message, &req_buffer))) { - goto bail; - } - sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size); - TSK_OBJECT_SAFE_FREE(req_buffer); - ret = (sendBytes > 0) ? 0 : -2; - if (ret != 0) { - TSK_DEBUG_ERROR("ICE pair-answer: failed to send response"); - } + sendBytes = tnet_sockfd_sendto(self->candidate_offer->socket->fd, (const struct sockaddr*)&dest_addr, req_buffer->data, req_buffer->size); + TSK_OBJECT_SAFE_FREE(req_buffer); + ret = (sendBytes > 0) ? 0 : -2; + if (ret != 0) { + TSK_DEBUG_ERROR("ICE pair-answer: failed to send response"); } } - - if (ret == 0 && !is_error) { - tsk_bool_t change_state = + } + + if (ret == 0 && !is_error) { + tsk_bool_t change_state = self->is_ice_jingle // ICE-JINGLE don't have ICE-CONTROLLING/ICE-CONTROLLED attributes || (!self->is_controlling && tnet_stun_pkt_attr_exists(request, tnet_stun_attr_type_ice_use_candidate)) // Sender is controlling and uses "ICE-USE-CANDIDATE" attribute #if TNET_ICE_AGGRESSIVE_NOMINATION || 1 // This is not a typo but a *must*. We've to change the answer state regardless the nomination mode otherwise we'll never get a nominee. Only the offer state is controlled based on the mode and depends on "is_nominated". @@ -511,301 +514,300 @@ int tnet_ice_pair_send_conncheck(tnet_ice_pair_t *self) || (self->is_controlling && self->is_nominated) // We're controlling and using regular mode #endif ; - TNET_ICE_PAIR_DEBUG_INFO("ICE pair-answer changing state to 'succeed' ? %s, comp-id=%d, found=%s, addr=%s", - change_state?"yes":"no", - self->candidate_answer->comp_id, - self->candidate_answer->foundation, - self->candidate_answer->connection_addr - ); - if (change_state) { - self->state_answer = tnet_ice_pair_state_succeed; - } - } - - - bail: - TSK_OBJECT_SAFE_FREE(message); - return ret; + TNET_ICE_PAIR_DEBUG_INFO("ICE pair-answer changing state to 'succeed' ? %s, comp-id=%d, found=%s, addr=%s", + change_state?"yes":"no", + self->candidate_answer->comp_id, + self->candidate_answer->foundation, + self->candidate_answer->connection_addr + ); + if (change_state) { + self->state_answer = tnet_ice_pair_state_succeed; + } } - - int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase) - { - const uint8_t* _request_buff = (const uint8_t*)request_buff; - - const tnet_stun_attr_t* stun_att; - const tnet_stun_attr_vdata_t *stun_att_usr_name; - const tnet_stun_attr_vdata_t *stun_att_fingerprint; - const tnet_stun_attr_vdata_t *stun_att_integrity; - - const tsk_list_item_t *item; - tsk_sha1digest_t hmac; - const char* pwd; - - tsk_size_t msg_integrity_start = 0, length, i; - - if(!self || !request || !request_buff || !request_buff_size || !resp_code || !resp_phrase){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(!TNET_STUN_BUFF_IS_STUN2(_request_buff, request_buff_size)){ - TSK_DEBUG_ERROR("Not STUN buffer"); - return -1; - } - - pwd = tnet_ice_candidate_get_pwd(self->candidate_offer); - stun_att_usr_name = tsk_null; - stun_att_fingerprint = tsk_null; - stun_att_integrity = tsk_null; - - tsk_list_foreach(item, request->p_list_attrs) { - if ((!(stun_att = (const tnet_stun_attr_t*)item->data))) { - continue; - } - - switch (stun_att->hdr.e_type) { - case tnet_stun_attr_type_username: - { - stun_att_usr_name = (const tnet_stun_attr_vdata_t *)stun_att; - break; - } - case tnet_stun_attr_type_fingerprint: - { - stun_att_fingerprint = (const tnet_stun_attr_vdata_t *)stun_att; - break; - } - case tnet_stun_attr_type_message_integrity: - { - stun_att_integrity = (const tnet_stun_attr_vdata_t *)stun_att; - break; - } - default: break; - } - - if (!stun_att_integrity) { - if ((length = (kStunAttrHdrSizeInOctets + stun_att->hdr.u_length)) & 0x03) { - length += (4 - (length & 0x03)); - } - msg_integrity_start += length; - } + + +bail: + TSK_OBJECT_SAFE_FREE(message); + return ret; +} + +int tnet_ice_pair_auth_conncheck(const tnet_ice_pair_t *self, const tnet_stun_pkt_req_t* request, const void* request_buff, tsk_size_t request_buff_size, short* resp_code, char** resp_phrase) +{ + const uint8_t* _request_buff = (const uint8_t*)request_buff; + + const tnet_stun_attr_t* stun_att; + const tnet_stun_attr_vdata_t *stun_att_usr_name; + const tnet_stun_attr_vdata_t *stun_att_fingerprint; + const tnet_stun_attr_vdata_t *stun_att_integrity; + + const tsk_list_item_t *item; + tsk_sha1digest_t hmac; + const char* pwd; + + tsk_size_t msg_integrity_start = 0, length, i; + + if(!self || !request || !request_buff || !request_buff_size || !resp_code || !resp_phrase) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(!TNET_STUN_BUFF_IS_STUN2(_request_buff, request_buff_size)) { + TSK_DEBUG_ERROR("Not STUN buffer"); + return -1; + } + + pwd = tnet_ice_candidate_get_pwd(self->candidate_offer); + stun_att_usr_name = tsk_null; + stun_att_fingerprint = tsk_null; + stun_att_integrity = tsk_null; + + tsk_list_foreach(item, request->p_list_attrs) { + if ((!(stun_att = (const tnet_stun_attr_t*)item->data))) { + continue; } - - if (!stun_att_usr_name) { - TSK_DEBUG_ERROR("USERNAME is missing"); - *resp_code = 400; - tsk_strupdate(resp_phrase, "USERNAME is missing"); - return -2; - } - - if (!stun_att_integrity || stun_att_integrity->u_data_size != TSK_SHA1_DIGEST_SIZE) { - if (self->is_ice_jingle) { // Bug introduced in Chrome 20.0.1120.0 (Not security issue as ICE-JINGLE is deprecated and will never be ON) - *resp_code = 200; - tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing but accepted"); - return 0; - } - else { - TSK_DEBUG_ERROR("MESSAGE-INTEGRITY is missing"); - *resp_code = 400; - tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing"); - return -3; + + switch (stun_att->hdr.e_type) { + case tnet_stun_attr_type_username: { + stun_att_usr_name = (const tnet_stun_attr_vdata_t *)stun_att; + break; + } + case tnet_stun_attr_type_fingerprint: { + stun_att_fingerprint = (const tnet_stun_attr_vdata_t *)stun_att; + break; + } + case tnet_stun_attr_type_message_integrity: { + stun_att_integrity = (const tnet_stun_attr_vdata_t *)stun_att; + break; + } + default: + break; + } + + if (!stun_att_integrity) { + if ((length = (kStunAttrHdrSizeInOctets + stun_att->hdr.u_length)) & 0x03) { + length += (4 - (length & 0x03)); } + msg_integrity_start += length; } - - if ((kStunPktHdrSizeInOctets + msg_integrity_start) >= request_buff_size) { - TSK_DEBUG_ERROR("Invalid length"); - *resp_code = 400; - tsk_strupdate(resp_phrase, "Invalid length"); - return -20; - } - - if (request->u_length != msg_integrity_start) { - tsk_size_t size = (kStunPktHdrSizeInOctets + msg_integrity_start); - uint8_t* new_buffer = (uint8_t*)tsk_calloc(size, 1); - if (!new_buffer) { - TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)msg_integrity_start); - return -30; - } - memcpy(new_buffer, request_buff, size); - length = msg_integrity_start + (kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/); - new_buffer[2] = (length >> 8) & 0xFF; - new_buffer[3] = (length & 0xFF); - hmac_sha1digest_compute(new_buffer, size, pwd, tsk_strlen(pwd), hmac); - TSK_FREE(new_buffer); + } + + if (!stun_att_usr_name) { + TSK_DEBUG_ERROR("USERNAME is missing"); + *resp_code = 400; + tsk_strupdate(resp_phrase, "USERNAME is missing"); + return -2; + } + + if (!stun_att_integrity || stun_att_integrity->u_data_size != TSK_SHA1_DIGEST_SIZE) { + if (self->is_ice_jingle) { // Bug introduced in Chrome 20.0.1120.0 (Not security issue as ICE-JINGLE is deprecated and will never be ON) + *resp_code = 200; + tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing but accepted"); + return 0; } else { - // must never happen - hmac_sha1digest_compute(request_buff, request_buff_size, pwd, tsk_strlen(pwd), hmac); - } - - for (i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) { - if (hmac[i] != stun_att_integrity->p_data_ptr[i]) { - TSK_DEBUG_ERROR("MESSAGE-INTEGRITY mismatch"); - *resp_code = 401; - tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY mismatch"); - return -40; - } - } - - *resp_code = 200; - tsk_strupdate(resp_phrase, "Ok"); - - return 0; + TSK_DEBUG_ERROR("MESSAGE-INTEGRITY is missing"); + *resp_code = 400; + tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY is missing"); + return -3; + } } - - int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_pkt_resp_t* response, tsk_bool_t is_4conncheck) - { - if (self && response && TNET_STUN_PKT_IS_RESP(response)) { - if (self->last_request && tnet_stun_utils_transac_id_equals(self->last_request->transac_id, response->transac_id)){ - // ignore errors (e.g. STALE-CREDENTIALS) which could happen in some special cases before success - if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) { - if (is_4conncheck) { - self->state_offer = tnet_ice_pair_state_succeed; // we must not change the state after connection cheking to make sure another pair won't be picked as nominated - TNET_ICE_PAIR_DEBUG_INFO("ICE pair-offer changing state to 'succeed', comp-id=%d, found=%s, addr=%s", - self->candidate_offer->comp_id, - self->candidate_offer->foundation, - self->candidate_offer->connection_addr - ); - } + + if ((kStunPktHdrSizeInOctets + msg_integrity_start) >= request_buff_size) { + TSK_DEBUG_ERROR("Invalid length"); + *resp_code = 400; + tsk_strupdate(resp_phrase, "Invalid length"); + return -20; + } + + if (request->u_length != msg_integrity_start) { + tsk_size_t size = (kStunPktHdrSizeInOctets + msg_integrity_start); + uint8_t* new_buffer = (uint8_t*)tsk_calloc(size, 1); + if (!new_buffer) { + TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)msg_integrity_start); + return -30; + } + memcpy(new_buffer, request_buff, size); + length = msg_integrity_start + (kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/); + new_buffer[2] = (length >> 8) & 0xFF; + new_buffer[3] = (length & 0xFF); + hmac_sha1digest_compute(new_buffer, size, pwd, tsk_strlen(pwd), hmac); + TSK_FREE(new_buffer); + } + else { + // must never happen + hmac_sha1digest_compute(request_buff, request_buff_size, pwd, tsk_strlen(pwd), hmac); + } + + for (i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) { + if (hmac[i] != stun_att_integrity->p_data_ptr[i]) { + TSK_DEBUG_ERROR("MESSAGE-INTEGRITY mismatch"); + *resp_code = 401; + tsk_strupdate(resp_phrase, "MESSAGE-INTEGRITY mismatch"); + return -40; + } + } + + *resp_code = 200; + tsk_strupdate(resp_phrase, "Ok"); + + return 0; +} + +int tnet_ice_pair_recv_response(tnet_ice_pair_t *self, const tnet_stun_pkt_resp_t* response, tsk_bool_t is_4conncheck) +{ + if (self && response && TNET_STUN_PKT_IS_RESP(response)) { + if (self->last_request && tnet_stun_utils_transac_id_equals(self->last_request->transac_id, response->transac_id)) { + // ignore errors (e.g. STALE-CREDENTIALS) which could happen in some special cases before success + if (TNET_STUN_PKT_RESP_IS_SUCCESS(response)) { + if (is_4conncheck) { + self->state_offer = tnet_ice_pair_state_succeed; // we must not change the state after connection cheking to make sure another pair won't be picked as nominated + TNET_ICE_PAIR_DEBUG_INFO("ICE pair-offer changing state to 'succeed', comp-id=%d, found=%s, addr=%s", + self->candidate_offer->comp_id, + self->candidate_offer->foundation, + self->candidate_offer->connection_addr + ); } - else { - // The response is an error - uint16_t u_code; - int ret; - if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code)) == 0 && u_code == kStunErrCodeIceConflict) { - TSK_DEBUG_INFO("ICE Pair %llu received conflict error message", self->id); - // If this code is called this means that we have lower tie-breaker and we must toggle our role - self->is_controlling = !self->is_controlling; - TSK_OBJECT_SAFE_FREE(self->last_request); // delete the "last_request" to make sure a new one will be created with right attributes - } + } + else { + // The response is an error + uint16_t u_code; + int ret; + if ((ret = tnet_stun_pkt_get_errorcode(response, &u_code)) == 0 && u_code == kStunErrCodeIceConflict) { + TSK_DEBUG_INFO("ICE Pair %llu received conflict error message", self->id); + // If this code is called this means that we have lower tie-breaker and we must toggle our role + self->is_controlling = !self->is_controlling; + TSK_OBJECT_SAFE_FREE(self->last_request); // delete the "last_request" to make sure a new one will be created with right attributes } } } - return 0; } - - const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_pkt_t* response) - { - if(pairs && response){ - const tsk_list_item_t *item; - const tnet_ice_pair_t *pair; - tnet_port_t mapped_port; - tnet_ip_t mapped_ip; - tsk_list_foreach(item, pairs){ - if(!(pair = item->data) || !pair->candidate_answer || !pair->candidate_offer){ - continue; + return 0; +} + +const tnet_ice_pair_t* tnet_ice_pairs_find_by_response(tnet_ice_pairs_L_t* pairs, const tnet_stun_pkt_t* response) +{ + if(pairs && response) { + const tsk_list_item_t *item; + const tnet_ice_pair_t *pair; + tnet_port_t mapped_port; + tnet_ip_t mapped_ip; + tsk_list_foreach(item, pairs) { + if(!(pair = item->data) || !pair->candidate_answer || !pair->candidate_offer) { + continue; + } + if(pair->last_request && tnet_stun_utils_transac_id_equals(pair->last_request->transac_id, response->transac_id)) { + // check that mapped/xmapped address match destination + const tnet_stun_attr_address_t *xmapped_addr = tsk_null; + const tnet_stun_attr_address_t* mapped_addr = tsk_null; + const tnet_stun_attr_address_t* _addr; + + tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t **)&xmapped_addr); + tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t **)&mapped_addr); + _addr = xmapped_addr ? xmapped_addr : mapped_addr; + + if (!_addr) { + return pair; // do nothing if the client doesn't return mapped address STUN attribute } - if(pair->last_request && tnet_stun_utils_transac_id_equals(pair->last_request->transac_id, response->transac_id)){ - // check that mapped/xmapped address match destination - const tnet_stun_attr_address_t *xmapped_addr = tsk_null; - const tnet_stun_attr_address_t* mapped_addr = tsk_null; - const tnet_stun_attr_address_t* _addr; - - tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t **)&xmapped_addr); - tnet_stun_pkt_attr_find_first(response, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t **)&mapped_addr); - _addr = xmapped_addr ? xmapped_addr : mapped_addr; - - if (!_addr) { - return pair; // do nothing if the client doesn't return mapped address STUN attribute - } - /* rfc 5245 7.1.3.2.1. Discovering Peer Reflexive Candidates - - The agent checks the mapped address from the STUN response. If the - transport address does not match any of the local candidates that the - agent knows about, the mapped address represents a new candidate -- a - peer reflexive candidate. Like other candidates, it has a type, - base, priority, and foundation. They are computed as follows: - - o Its type is equal to peer reflexive. - - o Its base is set equal to the local candidate of the candidate pair - from which the STUN check was sent. - - o Its priority is set equal to the value of the PRIORITY attribute - in the Binding request. - - o Its foundation is selected as described in Section 4.1.1.3. - - This peer reflexive candidate is then added to the list of local - candidates for the media stream. Its username fragment and password - are the same as all other local candidates for that media stream. - */ - - tnet_stun_utils_inet_ntop((_addr->e_family == tnet_stun_address_family_ipv6), &_addr->address, &mapped_ip); - mapped_port = _addr->u_port; - if (pair->candidate_offer->type_e != tnet_ice_cand_type_host && (mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_ip, pair->candidate_offer->connection_addr))) { - TSK_DEBUG_INFO("Mapped address different than local connection address...probably symetric NAT: %s#%s or %u#%u", - pair->candidate_offer->connection_addr, mapped_ip, - pair->candidate_offer->port, mapped_port); - // do we really need to add new local candidate? - // continue; - } - return pair; + /* rfc 5245 7.1.3.2.1. Discovering Peer Reflexive Candidates + + The agent checks the mapped address from the STUN response. If the + transport address does not match any of the local candidates that the + agent knows about, the mapped address represents a new candidate -- a + peer reflexive candidate. Like other candidates, it has a type, + base, priority, and foundation. They are computed as follows: + + o Its type is equal to peer reflexive. + + o Its base is set equal to the local candidate of the candidate pair + from which the STUN check was sent. + + o Its priority is set equal to the value of the PRIORITY attribute + in the Binding request. + + o Its foundation is selected as described in Section 4.1.1.3. + + This peer reflexive candidate is then added to the list of local + candidates for the media stream. Its username fragment and password + are the same as all other local candidates for that media stream. + */ + + tnet_stun_utils_inet_ntop((_addr->e_family == tnet_stun_address_family_ipv6), &_addr->address, &mapped_ip); + mapped_port = _addr->u_port; + if (pair->candidate_offer->type_e != tnet_ice_cand_type_host && (mapped_port != pair->candidate_offer->port || !tsk_striequals(mapped_ip, pair->candidate_offer->connection_addr))) { + TSK_DEBUG_INFO("Mapped address different than local connection address...probably symetric NAT: %s#%s or %u#%u", + pair->candidate_offer->connection_addr, mapped_ip, + pair->candidate_offer->port, mapped_port); + // do we really need to add new local candidate? + // continue; } + return pair; } } + } + return tsk_null; +} + +const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pairs, tnet_fd_t local_fd, const struct sockaddr_storage *remote_addr) +{ + int ret; + const tsk_list_item_t *item; + const tnet_ice_pair_t *pair; + tnet_ip_t remote_ip; + tnet_port_t remote_port; + + if(!pairs || !remote_addr) { + TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - - const tnet_ice_pair_t* tnet_ice_pairs_find_by_fd_and_addr(tnet_ice_pairs_L_t* pairs, tnet_fd_t local_fd, const struct sockaddr_storage *remote_addr) - { - int ret; + + if((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))) { + TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed"); + return tsk_null; + } + + tsk_list_foreach(item, pairs) { + if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) { + continue; + } + if (!tsk_striequals(pair->candidate_answer->connection_addr, remote_ip) || pair->candidate_answer->port != remote_port) { + continue; + } + + return pair; + } + + TSK_DEBUG_INFO("No ICE candidate with remote ip = %s, port = %u and local_fd = %d could be found...probably symetric NAT", remote_ip, remote_port, local_fd); + + return tsk_null; +} + + +static tsk_bool_t _tnet_ice_pairs_none_succeed(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, const char* foundation, tsk_bool_t answer) +{ + if(pairs && foundation) { const tsk_list_item_t *item; const tnet_ice_pair_t *pair; - tnet_ip_t remote_ip; - tnet_port_t remote_port; - - if(!pairs || !remote_addr){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - - if((ret = tnet_get_sockip_n_port((const struct sockaddr*)remote_addr, &remote_ip, &remote_port))){ - TNET_PRINT_LAST_ERROR("tnet_get_sockip_n_port() failed"); - return tsk_null; - } - - tsk_list_foreach(item, pairs){ - if (!(pair = item->data) || !pair->candidate_offer || !pair->candidate_offer->socket || pair->candidate_offer->socket->fd != local_fd) { + const tnet_ice_candidate_t* candidate; + tsk_list_foreach(item, pairs) { + if(!(pair = item->data) || !(candidate = (answer ? pair->candidate_answer : pair->candidate_offer))) { continue; } - if (!tsk_striequals(pair->candidate_answer->connection_addr, remote_ip) || pair->candidate_answer->port != remote_port) { + if(candidate->comp_id != comp_id || !tsk_striequals(candidate->foundation, foundation)) { continue; } - - return pair; - } - - TSK_DEBUG_INFO("No ICE candidate with remote ip = %s, port = %u and local_fd = %d could be found...probably symetric NAT", remote_ip, remote_port, local_fd); - - return tsk_null; - } - - - static tsk_bool_t _tnet_ice_pairs_none_succeed(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, const char* foundation, tsk_bool_t answer){ - if(pairs && foundation){ - const tsk_list_item_t *item; - const tnet_ice_pair_t *pair; - const tnet_ice_candidate_t* candidate; - tsk_list_foreach(item, pairs){ - if(!(pair = item->data) || !(candidate = (answer ? pair->candidate_answer : pair->candidate_offer))){ - continue; - } - if(candidate->comp_id != comp_id || !tsk_striequals(candidate->foundation, foundation)){ - continue; - } - if((answer ? pair->state_answer : pair->state_offer) == tnet_ice_pair_state_succeed){ - TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):false", answer?"anwser":"offer", comp_id, foundation); - return tsk_false; - } + if((answer ? pair->state_answer : pair->state_offer) == tnet_ice_pair_state_succeed) { + TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):false", answer?"anwser":"offer", comp_id, foundation); + return tsk_false; } } - TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):true", answer?"anwser":"offer", comp_id, foundation); - return tsk_true; } + TNET_ICE_PAIR_DEBUG_INFO("_tnet_ice_pairs_none_succeed_%s(%u, %s):true", answer?"anwser":"offer", comp_id, foundation); + return tsk_true; +} #define _tnet_ice_pairs_none_succeed_answer(pairs, comp_id, foundation) _tnet_ice_pairs_none_succeed((pairs), (comp_id), (foundation), tsk_true) #define _tnet_ice_pairs_none_succeed_offer(pairs, comp_id, foundation) _tnet_ice_pairs_none_succeed((pairs), (comp_id), (foundation), tsk_false) - - // both RTP and RTCP have succeeded + +// both RTP and RTCP have succeeded #define _tnet_ice_pairs_get_nominated_offer_at(pairs, index, comp_id, check_fullness, ret) _tnet_ice_pairs_get_nominated_at((pairs), offer, answer, (index), (comp_id), (check_fullness), (ret)) #define _tnet_ice_pairs_get_nominated_answer_at(pairs, index, comp_id, check_fullness, ret) _tnet_ice_pairs_get_nominated_at((pairs), answer, offer, (index), (comp_id), (check_fullness), (ret)) #define _tnet_ice_pairs_get_nominated_at(pairs, dir_1, dir_2, index, _comp_id, check_fullness, ret) \ @@ -851,138 +853,146 @@ break; \ } \ } \ } \ + +// true only if both RTP and RTCP are nominated +tsk_bool_t tnet_ice_pairs_have_nominated_offer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) +{ + const tnet_ice_pair_t *pair_ = tsk_null; + tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; + TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_offer()"); + _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_)); + if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp) { + _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_)); + is_nominated_rtcp =(pair_ != tsk_null); + } + TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_offer=%s, is_nominated_rtcp_offer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no"); + return (is_nominated_rtp && is_nominated_rtcp); +} - // true only if both RTP and RTCP are nominated - tsk_bool_t tnet_ice_pairs_have_nominated_offer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) - { - const tnet_ice_pair_t *pair_ = tsk_null; - tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; - TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_offer()"); - _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_)); - if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp){ - _tnet_ice_pairs_get_nominated_offer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_)); - is_nominated_rtcp =(pair_ != tsk_null); - } - TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_offer=%s, is_nominated_rtcp_offer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no"); - return (is_nominated_rtp && is_nominated_rtcp); - } - - // true only if both RTP and RTCP are nominated - tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) - { - const tnet_ice_pair_t *pair_ = tsk_null; - tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; - TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_answer()"); - _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_)); - if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp){ - _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_)); - is_nominated_rtcp =(pair_ != tsk_null); - } - TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_answer=%s, is_nominated_rtcp_answer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no"); - return (is_nominated_rtp && is_nominated_rtcp); - } - - // true only if both RTP and RTCP are nominated in symetric way - tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts) - { - const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; - tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; - int ret; - - if (got_hosts) { - *got_hosts = tsk_false; - } - ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - if ((is_nominated_rtp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) { - *got_hosts = (candidate_offer->type_e == tnet_ice_cand_type_host - && candidate_answer_src->type_e == tnet_ice_cand_type_host - && candidate_answer_dest->type_e == tnet_ice_cand_type_host); - } - if(is_nominated_rtp && check_rtcp){ - ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - if ((is_nominated_rtcp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) { - *got_hosts &= (candidate_offer->type_e == tnet_ice_cand_type_host - && candidate_answer_src->type_e == tnet_ice_cand_type_host - && candidate_answer_dest->type_e == tnet_ice_cand_type_host); - } +// true only if both RTP and RTCP are nominated +tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) +{ + const tnet_ice_pair_t *pair_ = tsk_null; + tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; + TNET_ICE_PAIR_DEBUG_INFO("tnet_ice_pairs_have_nominated_answer()"); + _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTP, check_rtcp, (pair_)); + if((is_nominated_rtp = (pair_ != tsk_null)) && check_rtcp) { + _tnet_ice_pairs_get_nominated_answer_at((pairs), 0, TNET_ICE_CANDIDATE_COMPID_RTCP, check_rtcp, (pair_)); + is_nominated_rtcp =(pair_ != tsk_null); + } + TNET_ICE_PAIR_DEBUG_INFO("is_nominated_rtp_answer=%s, is_nominated_rtcp_answer=%s", is_nominated_rtp?"yes":"no", is_nominated_rtcp?"yes":"no"); + return (is_nominated_rtp && is_nominated_rtcp); +} + +// true only if both RTP and RTCP are nominated in symetric way +tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts) +{ + const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; + tsk_bool_t is_nominated_rtp, is_nominated_rtcp = tsk_true; + int ret; + + if (got_hosts) { + *got_hosts = tsk_false; + } + ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + if ((is_nominated_rtp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) { + *got_hosts = (candidate_offer->type_e == tnet_ice_cand_type_host + && candidate_answer_src->type_e == tnet_ice_cand_type_host + && candidate_answer_dest->type_e == tnet_ice_cand_type_host); + } + if(is_nominated_rtp && check_rtcp) { + ret = tnet_ice_pairs_get_nominated_symetric_candidates(pairs, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + if ((is_nominated_rtcp = (ret == 0 && candidate_offer && candidate_answer_src && candidate_answer_dest)) && got_hosts) { + *got_hosts &= (candidate_offer->type_e == tnet_ice_cand_type_host + && candidate_answer_src->type_e == tnet_ice_cand_type_host + && candidate_answer_dest->type_e == tnet_ice_cand_type_host); } - return (is_nominated_rtp && is_nominated_rtcp); } - - // true only if both RTP and RTCP are nominated in symetric way - tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) - { + return (is_nominated_rtp && is_nominated_rtcp); +} + +// true only if both RTP and RTCP are nominated in symetric way +tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp) +{ #define got_hosts tsk_null - return tnet_ice_pairs_have_nominated_symetric_2(pairs, check_rtcp, got_hosts); - } - - // gets symetric nominated candidates with the highest priority - // will succeed only if both RTP and RTCP are ok - int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, - const tnet_ice_candidate_t** candidate_offer, - const tnet_ice_candidate_t** candidate_answer_src, - const tnet_ice_candidate_t** candidate_answer_dest) - { - int ret; - const tnet_ice_pair_t *pair_offer = tsk_null, *pair_answer_src = tsk_null, *pair_answer_dest = tsk_null; - if (!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - *candidate_offer = tsk_null; - *candidate_answer_src = tsk_null; - *candidate_answer_dest = tsk_null; - - if ((ret = tnet_ice_pairs_get_nominated_symetric_pairs(pairs, comp_id, &pair_offer, &pair_answer_src, &pair_answer_dest)) == 0) { - *candidate_offer = pair_offer ? pair_offer->candidate_offer : tsk_null; - *candidate_answer_src = pair_answer_src ? pair_answer_src->candidate_answer : tsk_null; - *candidate_answer_dest = pair_answer_dest ? pair_answer_dest->candidate_answer : tsk_null; - } - return ret; + return tnet_ice_pairs_have_nominated_symetric_2(pairs, check_rtcp, got_hosts); +} + +// gets symetric nominated candidates with the highest priority +// will succeed only if both RTP and RTCP are ok +int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, + const tnet_ice_candidate_t** candidate_offer, + const tnet_ice_candidate_t** candidate_answer_src, + const tnet_ice_candidate_t** candidate_answer_dest) +{ + int ret; + const tnet_ice_pair_t *pair_offer = tsk_null, *pair_answer_src = tsk_null, *pair_answer_dest = tsk_null; + if (!pairs || !candidate_offer || !candidate_answer_src || !candidate_answer_dest) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; } - - int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, - const struct tnet_ice_pair_s** _pair_offer, - const struct tnet_ice_pair_s** _pair_answer_src, - const struct tnet_ice_pair_s** _pair_answer_dest) - { - const tnet_ice_pair_t *pair_offer = tsk_null; - const tnet_ice_pair_t *pair_answer = tsk_null; - tsk_size_t i_offer, i_answer; - static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly - - if (!pairs || !_pair_offer || !_pair_answer_src || !_pair_answer_dest) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - *_pair_offer = tsk_null; - *_pair_answer_src = tsk_null; - *_pair_answer_dest = tsk_null; - - i_offer = 0; + + *candidate_offer = tsk_null; + *candidate_answer_src = tsk_null; + *candidate_answer_dest = tsk_null; + + if ((ret = tnet_ice_pairs_get_nominated_symetric_pairs(pairs, comp_id, &pair_offer, &pair_answer_src, &pair_answer_dest)) == 0) { + *candidate_offer = pair_offer ? pair_offer->candidate_offer : tsk_null; + *candidate_answer_src = pair_answer_src ? pair_answer_src->candidate_answer : tsk_null; + *candidate_answer_dest = pair_answer_dest ? pair_answer_dest->candidate_answer : tsk_null; + } + return ret; +} + +int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, + const struct tnet_ice_pair_s** _pair_offer, + const struct tnet_ice_pair_s** _pair_answer_src, + const struct tnet_ice_pair_s** _pair_answer_dest) +{ + const tnet_ice_pair_t *pair_offer = tsk_null; + const tnet_ice_pair_t *pair_answer = tsk_null; + tsk_size_t i_offer, i_answer; + static const tsk_bool_t __check_fullness = tsk_false; // pairs will be checked seperatly + + if (!pairs || !_pair_offer || !_pair_answer_src || !_pair_answer_dest) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + *_pair_offer = tsk_null; + *_pair_answer_src = tsk_null; + *_pair_answer_dest = tsk_null; + + i_offer = 0; + while (1) { + _tnet_ice_pairs_get_nominated_offer_at((pairs), i_offer, comp_id, __check_fullness, (pair_offer)); // pair with socket SO as sender + if(!pair_offer) { + return 0; + } + ++i_offer; + if (pair_offer->candidate_offer->comp_id != comp_id) { + continue; + } + // find another pair with socket SO as receiver + + i_answer = 0; while (1) { - _tnet_ice_pairs_get_nominated_offer_at((pairs), i_offer, comp_id, __check_fullness, (pair_offer)); // pair with socket SO as sender - if(!pair_offer) return 0; - ++i_offer; - if (pair_offer->candidate_offer->comp_id != comp_id) continue; - // find another pair with socket SO as receiver - - i_answer = 0; - while (1) { - _tnet_ice_pairs_get_nominated_answer_at((pairs), i_answer, comp_id, __check_fullness, (pair_answer)); - if (!pair_answer) break; - ++i_answer; - if (pair_answer->candidate_offer->comp_id != comp_id) continue; - if (pair_answer->candidate_offer == pair_offer->candidate_offer) { - *_pair_offer = pair_offer; - *_pair_answer_src = pair_answer; - *_pair_answer_dest = pair_offer; - return 0; - } + _tnet_ice_pairs_get_nominated_answer_at((pairs), i_answer, comp_id, __check_fullness, (pair_answer)); + if (!pair_answer) { + break; + } + ++i_answer; + if (pair_answer->candidate_offer->comp_id != comp_id) { + continue; + } + if (pair_answer->candidate_offer == pair_offer->candidate_offer) { + *_pair_offer = pair_offer; + *_pair_answer_src = pair_answer; + *_pair_answer_dest = pair_offer; + return 0; } } - return 0; - } + return 0; + +} diff --git a/tinyNET/src/ice/tnet_ice_pair.h b/tinyNET/src/ice/tnet_ice_pair.h index 7e40eb8..f3fb73d 100755 --- a/tinyNET/src/ice/tnet_ice_pair.h +++ b/tinyNET/src/ice/tnet_ice_pair.h @@ -8,12 +8,12 @@ * 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. * @@ -32,33 +32,31 @@ typedef tsk_list_t tnet_ice_pairs_L_t; struct tnet_ice_candidate_s; -typedef enum tnet_ice_pair_state_e -{ - tnet_ice_pair_state_frozen, - tnet_ice_pair_state_waiting, - tnet_ice_pair_state_in_progress, - tnet_ice_pair_state_succeed, - tnet_ice_pair_state_failed +typedef enum tnet_ice_pair_state_e { + tnet_ice_pair_state_frozen, + tnet_ice_pair_state_waiting, + tnet_ice_pair_state_in_progress, + tnet_ice_pair_state_succeed, + tnet_ice_pair_state_failed } tnet_ice_pair_state_t; -typedef struct tnet_ice_pair_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_ice_pair_s { + TSK_DECLARE_OBJECT; - uint64_t id; - uint64_t priority; - tnet_ice_pair_state_t state_offer; - tnet_ice_pair_state_t state_answer; - tsk_bool_t is_ice_jingle; - tsk_bool_t is_controlling; - tsk_bool_t is_nominated; - uint64_t tie_breaker; - struct tnet_ice_candidate_s* candidate_offer; - struct tnet_ice_candidate_s* candidate_answer; - struct tnet_stun_pkt_s* last_request; - struct sockaddr_storage remote_addr; - tnet_turn_peer_id_t turn_peer_id; + uint64_t id; + uint64_t priority; + tnet_ice_pair_state_t state_offer; + tnet_ice_pair_state_t state_answer; + tsk_bool_t is_ice_jingle; + tsk_bool_t is_controlling; + tsk_bool_t is_nominated; + uint64_t tie_breaker; + struct tnet_ice_candidate_s* candidate_offer; + struct tnet_ice_candidate_s* candidate_answer; + struct tnet_stun_pkt_s* last_request; + struct sockaddr_storage remote_addr; + tnet_turn_peer_id_t turn_peer_id; } tnet_ice_pair_t; @@ -75,12 +73,12 @@ tsk_bool_t tnet_ice_pairs_have_nominated_answer(const tnet_ice_pairs_L_t* pairs, tsk_bool_t tnet_ice_pairs_have_nominated_symetric(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp); tsk_bool_t tnet_ice_pairs_have_nominated_symetric_2(const tnet_ice_pairs_L_t* pairs, tsk_bool_t check_rtcp, tsk_bool_t *got_hosts); int tnet_ice_pairs_get_nominated_symetric_candidates(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, - const struct tnet_ice_candidate_s** candidate_offer, - const struct tnet_ice_candidate_s** candidate_answer_src, - const struct tnet_ice_candidate_s** candidate_answer_dest); + const struct tnet_ice_candidate_s** candidate_offer, + const struct tnet_ice_candidate_s** candidate_answer_src, + const struct tnet_ice_candidate_s** candidate_answer_dest); int tnet_ice_pairs_get_nominated_symetric_pairs(const tnet_ice_pairs_L_t* pairs, uint32_t comp_id, - const struct tnet_ice_pair_s** pair_offer, - const struct tnet_ice_pair_s** pair_answer_src, - const struct tnet_ice_pair_s** pair_answer_dest); + const struct tnet_ice_pair_s** pair_offer, + const struct tnet_ice_pair_s** pair_answer_src, + const struct tnet_ice_pair_s** pair_answer_dest); #endif /* TNET_ICE_PAIR_H */ diff --git a/tinyNET/src/ice/tnet_ice_utils.c b/tinyNET/src/ice/tnet_ice_utils.c index d4ba8a7..eae514e 100755 --- a/tinyNET/src/ice/tnet_ice_utils.c +++ b/tinyNET/src/ice/tnet_ice_utils.c @@ -8,12 +8,12 @@ * 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. * @@ -29,132 +29,144 @@ #include <stdlib.h> -static const char ice_chars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'k', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'K', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - '0','1', '2', '3', '4', '5', '6', '7', '8', '9'}; // /!\do not add '/' and '+' because of WebRTC password +static const char ice_chars[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'k', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'K', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + '0','1', '2', '3', '4', '5', '6', '7', '8', '9' + }; // /!\do not add '/' and '+' because of WebRTC password static const tsk_size_t ice_chars_count = sizeof(ice_chars); uint32_t tnet_ice_utils_get_priority(tnet_ice_cand_type_t type, uint16_t local_pref, tsk_bool_t is_rtp) { - uint32_t pref; - switch(type){ - case tnet_ice_cand_type_host: pref = TNET_ICE_CANDIDATE_PREF_HOST; break; - case tnet_ice_cand_type_srflx: pref = TNET_ICE_CANDIDATE_PREF_SRFLX; break; - case tnet_ice_cand_type_prflx: pref = TNET_ICE_CANDIDATE_PREF_PRFLX; break; - case tnet_ice_cand_type_relay: default: pref = TNET_ICE_CANDIDATE_PREF_RELAY; break; - } - return (pref << 24) + - (local_pref << 8) + - ((256 - (is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP)) << 0); + uint32_t pref; + switch(type) { + case tnet_ice_cand_type_host: + pref = TNET_ICE_CANDIDATE_PREF_HOST; + break; + case tnet_ice_cand_type_srflx: + pref = TNET_ICE_CANDIDATE_PREF_SRFLX; + break; + case tnet_ice_cand_type_prflx: + pref = TNET_ICE_CANDIDATE_PREF_PRFLX; + break; + case tnet_ice_cand_type_relay: + default: + pref = TNET_ICE_CANDIDATE_PREF_RELAY; + break; + } + return (pref << 24) + + (local_pref << 8) + + ((256 - (is_rtp ? TNET_ICE_CANDIDATE_COMPID_RTP : TNET_ICE_CANDIDATE_COMPID_RTCP)) << 0); } int tnet_ice_utils_compute_foundation(char* foundation, tsk_size_t size) { - - tsk_size_t i; - - if(!foundation || !size){ - TSK_DEBUG_ERROR("Invalid argument"); - return -1; - } - for( - i = 0; i < size; ++i){ - foundation[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; - } - - return 0; + + tsk_size_t i; + + if(!foundation || !size) { + TSK_DEBUG_ERROR("Invalid argument"); + return -1; + } + for( + i = 0; i < size; ++i) { + foundation[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; + } + + return 0; } int tnet_ice_utils_create_sockets(tnet_socket_type_t socket_type, const char* local_ip, tnet_socket_t** socket_rtp, tnet_socket_t** socket_rtcp) { - tsk_bool_t look4_rtp = (socket_rtp != tsk_null); - tsk_bool_t look4_rtcp = (socket_rtcp != tsk_null); - uint8_t retry_count = 10; - tnet_port_t local_port; - static const uint64_t port_range_start = 1024; - static const uint64_t port_range_stop = (65535 - 1/* to be sure rtcp port will be valid */); - static uint64_t counter = 0; - - /* Creates local rtp and rtcp sockets */ - while(retry_count--){ - if(look4_rtp && look4_rtcp){ - tnet_socket_t* socket_fake = tnet_socket_create(local_ip, TNET_SOCKET_PORT_ANY, socket_type); - if(!socket_fake){ - continue; - } - if(!(socket_fake->port & 0x01)){ // even number ? - *socket_rtp = socket_fake; - } - else{ - *socket_rtcp = socket_fake; - } - local_port = (socket_fake->port & ~1); - } - else{ - local_port = (tnet_port_t)((((tsk_time_epoch() + rand() ) ^ ++counter) % (port_range_stop - port_range_start)) + port_range_start); - local_port = (local_port & 0xFFFE); /* turn to even number */ - } - - /* beacuse failure will cause errors in the log, print a message to alert that there is - * nothing to worry about */ - TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports [%s:%d]", local_ip, local_port); - - if(look4_rtp){ - if(!*socket_rtp && !(*socket_rtp = tnet_socket_create(local_ip, local_port, socket_type))){ - TSK_DEBUG_INFO("Failed to bind to %d", local_port); - continue; - } - } - - if(look4_rtcp){ - if(!*socket_rtcp && !(*socket_rtcp = tnet_socket_create(local_ip, (local_port + 1), socket_type))){ - TSK_DEBUG_INFO("Failed to bind to %d", (local_port + 1)); - if(look4_rtp){ - TSK_OBJECT_SAFE_FREE((*socket_rtp)); - } - continue; - } - } - - TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports"); - return 0; - } - - TSK_DEBUG_ERROR("Failed to bind sockets"); - return -1; + tsk_bool_t look4_rtp = (socket_rtp != tsk_null); + tsk_bool_t look4_rtcp = (socket_rtcp != tsk_null); + uint8_t retry_count = 10; + tnet_port_t local_port; + static const uint64_t port_range_start = 1024; + static const uint64_t port_range_stop = (65535 - 1/* to be sure rtcp port will be valid */); + static uint64_t counter = 0; + + /* Creates local rtp and rtcp sockets */ + while(retry_count--) { + if(look4_rtp && look4_rtcp) { + tnet_socket_t* socket_fake = tnet_socket_create(local_ip, TNET_SOCKET_PORT_ANY, socket_type); + if(!socket_fake) { + continue; + } + if(!(socket_fake->port & 0x01)) { // even number ? + *socket_rtp = socket_fake; + } + else { + *socket_rtcp = socket_fake; + } + local_port = (socket_fake->port & ~1); + } + else { + local_port = (tnet_port_t)((((tsk_time_epoch() + rand() ) ^ ++counter) % (port_range_stop - port_range_start)) + port_range_start); + local_port = (local_port & 0xFFFE); /* turn to even number */ + } + + /* beacuse failure will cause errors in the log, print a message to alert that there is + * nothing to worry about */ + TSK_DEBUG_INFO("RTP/RTCP manager[Begin]: Trying to bind to random ports [%s:%d]", local_ip, local_port); + + if(look4_rtp) { + if(!*socket_rtp && !(*socket_rtp = tnet_socket_create(local_ip, local_port, socket_type))) { + TSK_DEBUG_INFO("Failed to bind to %d", local_port); + continue; + } + } + + if(look4_rtcp) { + if(!*socket_rtcp && !(*socket_rtcp = tnet_socket_create(local_ip, (local_port + 1), socket_type))) { + TSK_DEBUG_INFO("Failed to bind to %d", (local_port + 1)); + if(look4_rtp) { + TSK_OBJECT_SAFE_FREE((*socket_rtp)); + } + continue; + } + } + + TSK_DEBUG_INFO("RTP/RTCP manager[End]: Trying to bind to random ports"); + return 0; + } + + TSK_DEBUG_ERROR("Failed to bind sockets"); + return -1; } int tnet_ice_utils_set_ufrag(char** ufrag) { - if(ufrag){ - char tmp[16]; int i; - for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i){ - tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; - } - tmp[i] = '\0'; - tsk_strupdate(ufrag, tmp); - return 0; - } - else{ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(ufrag) { + char tmp[16]; + int i; + for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i) { + tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; + } + tmp[i] = '\0'; + tsk_strupdate(ufrag, tmp); + return 0; + } + else { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } } int tnet_ice_utils_set_pwd(char** pwd) { - if(pwd){ - char tmp[23]; int i; - for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i){ - tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; - } - tmp[i] = '\0'; - tsk_strupdate(pwd, tmp); - return 0; - } - else{ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(pwd) { + char tmp[23]; + int i; + for(i = 0; i < (sizeof(tmp)/sizeof(tmp[0])) - 1; ++i) { + tmp[i] = ice_chars[(rand() ^ rand()) % ice_chars_count]; + } + tmp[i] = '\0'; + tsk_strupdate(pwd, tmp); + return 0; + } + else { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } }
\ No newline at end of file diff --git a/tinyNET/src/ice/tnet_ice_utils.h b/tinyNET/src/ice/tnet_ice_utils.h index 8e53915..541bb9a 100755 --- a/tinyNET/src/ice/tnet_ice_utils.h +++ b/tinyNET/src/ice/tnet_ice_utils.h @@ -8,12 +8,12 @@ * 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. * diff --git a/tinyNET/src/stun/tnet_stun_attr.c b/tinyNET/src/stun/tnet_stun_attr.c index 4c31c05..25ad6c7 100755 --- a/tinyNET/src/stun/tnet_stun_attr.c +++ b/tinyNET/src/stun/tnet_stun_attr.c @@ -53,479 +53,479 @@ 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; + 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); + return (int)(pc_att1 - pc_att2); } static int _tnet_stun_attr_get_size_in_octetunits(const tnet_stun_attr_t* pc_self, tsk_bool_t with_padding, tsk_size_t* p_size) { - if (!pc_self || !p_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - switch (pc_self->hdr.e_type) { - case tnet_stun_attr_type_mapped_address: - case tnet_stun_attr_type_alternate_server: - case tnet_stun_attr_type_xor_mapped_address: - case tnet_stun_attr_type_xor_peer_address: - case tnet_stun_attr_type_xor_relayed_address: { - extern const tsk_object_def_t *tnet_stun_attr_address_def_t; - const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self; - if (pc_self->__def__ != tnet_stun_attr_address_def_t) { - TSK_DEBUG_ERROR("Invalid base type"); - return -2; - } - *p_size = (kStunAttrHdrSizeInOctets + 1/*Ignored*/ + 1/*Family*/ + 2/*Port*/ + ((_pc_self->e_family == tnet_stun_address_family_ipv6) ? 16 : 4)); - if (with_padding) { - ALIGN_ON_32BITS(*p_size); - } - return 0; - } - case tnet_stun_attr_type_data: - case tnet_stun_attr_type_unknown_attrs: - case tnet_stun_attr_type_dont_fragment: - case tnet_stun_attr_type_software: - case tnet_stun_attr_type_nonce: - case tnet_stun_attr_type_realm: - case tnet_stun_attr_type_username: - case tnet_stun_attr_type_password: - case tnet_stun_attr_type_channel_number: - case tnet_stun_attr_type_message_integrity: - case tnet_stun_attr_type_fingerprint: - case tnet_stun_attr_type_lifetime: - case tnet_stun_attr_type_requested_transport: - case tnet_stun_attr_type_ice_use_candidate: - case tnet_stun_attr_type_ice_priority: - case tnet_stun_attr_type_ice_controlled: - case tnet_stun_attr_type_ice_controlling: - case tnet_stun_attr_type_connection_id: { - extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; - const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self; - if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) { - TSK_DEBUG_ERROR("Invalid base type"); - return -2; - } - *p_size = (kStunAttrHdrSizeInOctets + _pc_self->u_data_size); - if (with_padding) { - ALIGN_ON_32BITS(*p_size); - } - return 0; - } - case tnet_stun_attr_type_error_code: { - const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self; - *p_size = (kStunAttrHdrSizeInOctets + 4 + (tsk_size_t)tsk_strlen(_pc_self->p_reason_phrase)); - if (with_padding) { - ALIGN_ON_32BITS(*p_size); - } - return 0; - } - default: { - TSK_DEBUG_WARN("Attribute type=%d is unknown. Don't be surprised if something goes wrong.", pc_self->hdr.e_type); - *p_size = (kStunAttrHdrSizeInOctets + pc_self->hdr.u_length); - if (with_padding) { - ALIGN_ON_32BITS(*p_size); - } - return 0; - } - } + if (!pc_self || !p_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + switch (pc_self->hdr.e_type) { + case tnet_stun_attr_type_mapped_address: + case tnet_stun_attr_type_alternate_server: + case tnet_stun_attr_type_xor_mapped_address: + case tnet_stun_attr_type_xor_peer_address: + case tnet_stun_attr_type_xor_relayed_address: { + extern const tsk_object_def_t *tnet_stun_attr_address_def_t; + const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self; + if (pc_self->__def__ != tnet_stun_attr_address_def_t) { + TSK_DEBUG_ERROR("Invalid base type"); + return -2; + } + *p_size = (kStunAttrHdrSizeInOctets + 1/*Ignored*/ + 1/*Family*/ + 2/*Port*/ + ((_pc_self->e_family == tnet_stun_address_family_ipv6) ? 16 : 4)); + if (with_padding) { + ALIGN_ON_32BITS(*p_size); + } + return 0; + } + case tnet_stun_attr_type_data: + case tnet_stun_attr_type_unknown_attrs: + case tnet_stun_attr_type_dont_fragment: + case tnet_stun_attr_type_software: + case tnet_stun_attr_type_nonce: + case tnet_stun_attr_type_realm: + case tnet_stun_attr_type_username: + case tnet_stun_attr_type_password: + case tnet_stun_attr_type_channel_number: + case tnet_stun_attr_type_message_integrity: + case tnet_stun_attr_type_fingerprint: + case tnet_stun_attr_type_lifetime: + case tnet_stun_attr_type_requested_transport: + case tnet_stun_attr_type_ice_use_candidate: + case tnet_stun_attr_type_ice_priority: + case tnet_stun_attr_type_ice_controlled: + case tnet_stun_attr_type_ice_controlling: + case tnet_stun_attr_type_connection_id: { + extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; + const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self; + if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) { + TSK_DEBUG_ERROR("Invalid base type"); + return -2; + } + *p_size = (kStunAttrHdrSizeInOctets + _pc_self->u_data_size); + if (with_padding) { + ALIGN_ON_32BITS(*p_size); + } + return 0; + } + case tnet_stun_attr_type_error_code: { + const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self; + *p_size = (kStunAttrHdrSizeInOctets + 4 + (tsk_size_t)tsk_strlen(_pc_self->p_reason_phrase)); + if (with_padding) { + ALIGN_ON_32BITS(*p_size); + } + return 0; + } + default: { + TSK_DEBUG_WARN("Attribute type=%d is unknown. Don't be surprised if something goes wrong.", pc_self->hdr.e_type); + *p_size = (kStunAttrHdrSizeInOctets + pc_self->hdr.u_length); + if (with_padding) { + ALIGN_ON_32BITS(*p_size); + } + return 0; + } + } } static int _tnet_stun_attr_write(const tnet_stun_transac_id_t* pc_transac_id, const tnet_stun_attr_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t with_padding, tsk_size_t *p_written) { - tsk_size_t n_min_req_size; - int ret; - if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if ((ret = _tnet_stun_attr_get_size_in_octetunits(pc_self, with_padding, &n_min_req_size))) { - return ret; - } - if (n_min_req_size > n_buff_size) { - TSK_DEBUG_ERROR("Buffer too short %u<%u", (unsigned)n_buff_size, (unsigned)n_min_req_size); - return -2; - } - - *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->hdr.e_type); - // *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)pc_self->hdr.u_length); - *p_written = kStunAttrHdrSizeInOctets; - - switch (pc_self->hdr.e_type) { - case tnet_stun_attr_type_mapped_address: - case tnet_stun_attr_type_alternate_server: - case tnet_stun_attr_type_xor_mapped_address: - case tnet_stun_attr_type_xor_peer_address: - case tnet_stun_attr_type_xor_relayed_address: { - tsk_size_t u_addr_size; - extern const tsk_object_def_t *tnet_stun_attr_address_def_t; - const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self; - tsk_bool_t b_xor = IS_ADDRESS_XOR(pc_self->hdr.e_type); - if (pc_self->__def__ != tnet_stun_attr_address_def_t) { - TSK_DEBUG_ERROR("Invalid base type"); - return -2; - } - p_buff_ptr[*p_written] = 0x00; // Reserved - p_buff_ptr[*p_written + 1] = _pc_self->e_family; - u_addr_size = (_pc_self->e_family == tnet_stun_address_family_ipv6 ? 16 : 4); - if (b_xor) { - tsk_size_t u; - *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port ^ kStunMagicCookieShort); - *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[0])) ^ kStunMagicCookieLong); - for (u = 4; u < u_addr_size; u += 4) { - if (pc_transac_id) { - *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ tnet_ntohl(*((uint32_t*)(*pc_transac_id + u - 4)))); - } - else { - *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ 0); - } - } - } - else { - *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port); - memcpy(&p_buff_ptr[*p_written + 4], _pc_self->address, u_addr_size); - } - - *p_written += 4 + u_addr_size; - *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); - if (with_padding) { - ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); - } - return 0; - } - - case tnet_stun_attr_type_data: - case tnet_stun_attr_type_unknown_attrs: - case tnet_stun_attr_type_dont_fragment: - case tnet_stun_attr_type_software: - case tnet_stun_attr_type_nonce: - case tnet_stun_attr_type_realm: - case tnet_stun_attr_type_username: - case tnet_stun_attr_type_password: - case tnet_stun_attr_type_channel_number: - case tnet_stun_attr_type_message_integrity: - case tnet_stun_attr_type_fingerprint: - case tnet_stun_attr_type_lifetime: - case tnet_stun_attr_type_requested_transport: - case tnet_stun_attr_type_ice_use_candidate: - case tnet_stun_attr_type_ice_priority: - case tnet_stun_attr_type_ice_controlled: - case tnet_stun_attr_type_ice_controlling: - case tnet_stun_attr_type_connection_id: { - extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; - const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self; - if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) { - TSK_DEBUG_ERROR("Invalid base type"); - return -2; - } - if (_pc_self->p_data_ptr && _pc_self->u_data_size) { - if (IS_VDATA_UINT16(pc_self->hdr.e_type) && _pc_self->u_data_size == 2) { - *((uint16_t*)&p_buff_ptr[*p_written]) = tnet_htons_2(&_pc_self->p_data_ptr[0]); - } - else if (IS_VDATA_UINT32(pc_self->hdr.e_type) && _pc_self->u_data_size == 4) { - *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]); - } - else if (IS_VDATA_UINT64(pc_self->hdr.e_type) && _pc_self->u_data_size == 8) { - *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]); - *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[4]); - } - else if (pc_self->hdr.e_type == tnet_stun_attr_type_unknown_attrs && _pc_self->u_data_size && !(_pc_self->u_data_size & 1)) { - uint16_t u; - for (u = 0; u < _pc_self->u_data_size; u += 2) { - *((uint16_t*)&p_buff_ptr[*p_written + u]) = tnet_htons_2(&_pc_self->p_data_ptr[u]); - } - } - else { - memcpy(&p_buff_ptr[*p_written], _pc_self->p_data_ptr, _pc_self->u_data_size); - } - *p_written += _pc_self->u_data_size; - } - if (with_padding) { - ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); - } - *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); - return 0; - } - case tnet_stun_attr_type_error_code: { - const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self; - *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl(((_pc_self->u_class & 0x07) << 8) | _pc_self->u_number); - if (_pc_self->p_reason_phrase) { - memcpy(&p_buff_ptr[*p_written + 4], _pc_self->p_reason_phrase, tsk_strlen(_pc_self->p_reason_phrase)); - } - *p_written += 4 + tsk_strlen(_pc_self->p_reason_phrase); - if (with_padding) { - ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); - } - *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); - return 0; - } - default: { - TSK_DEBUG_ERROR("Attribute type=%d is unknown.", pc_self->hdr.e_type); - return -2; - } - } + tsk_size_t n_min_req_size; + int ret; + if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if ((ret = _tnet_stun_attr_get_size_in_octetunits(pc_self, with_padding, &n_min_req_size))) { + return ret; + } + if (n_min_req_size > n_buff_size) { + TSK_DEBUG_ERROR("Buffer too short %u<%u", (unsigned)n_buff_size, (unsigned)n_min_req_size); + return -2; + } + + *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->hdr.e_type); + // *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)pc_self->hdr.u_length); + *p_written = kStunAttrHdrSizeInOctets; + + switch (pc_self->hdr.e_type) { + case tnet_stun_attr_type_mapped_address: + case tnet_stun_attr_type_alternate_server: + case tnet_stun_attr_type_xor_mapped_address: + case tnet_stun_attr_type_xor_peer_address: + case tnet_stun_attr_type_xor_relayed_address: { + tsk_size_t u_addr_size; + extern const tsk_object_def_t *tnet_stun_attr_address_def_t; + const tnet_stun_attr_address_t* _pc_self = (const tnet_stun_attr_address_t*)pc_self; + tsk_bool_t b_xor = IS_ADDRESS_XOR(pc_self->hdr.e_type); + if (pc_self->__def__ != tnet_stun_attr_address_def_t) { + TSK_DEBUG_ERROR("Invalid base type"); + return -2; + } + p_buff_ptr[*p_written] = 0x00; // Reserved + p_buff_ptr[*p_written + 1] = _pc_self->e_family; + u_addr_size = (_pc_self->e_family == tnet_stun_address_family_ipv6 ? 16 : 4); + if (b_xor) { + tsk_size_t u; + *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port ^ kStunMagicCookieShort); + *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[0])) ^ kStunMagicCookieLong); + for (u = 4; u < u_addr_size; u += 4) { + if (pc_transac_id) { + *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ tnet_ntohl(*((uint32_t*)(*pc_transac_id + u - 4)))); + } + else { + *((uint32_t*)&p_buff_ptr[*p_written + 4 + u]) = (uint32_t)tnet_htonl(tnet_ntohl(*((uint32_t*)&_pc_self->address[u])) ^ 0); + } + } + } + else { + *((uint16_t*)&p_buff_ptr[*p_written + 2]) = tnet_htons(_pc_self->u_port); + memcpy(&p_buff_ptr[*p_written + 4], _pc_self->address, u_addr_size); + } + + *p_written += 4 + u_addr_size; + *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); + if (with_padding) { + ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); + } + return 0; + } + + case tnet_stun_attr_type_data: + case tnet_stun_attr_type_unknown_attrs: + case tnet_stun_attr_type_dont_fragment: + case tnet_stun_attr_type_software: + case tnet_stun_attr_type_nonce: + case tnet_stun_attr_type_realm: + case tnet_stun_attr_type_username: + case tnet_stun_attr_type_password: + case tnet_stun_attr_type_channel_number: + case tnet_stun_attr_type_message_integrity: + case tnet_stun_attr_type_fingerprint: + case tnet_stun_attr_type_lifetime: + case tnet_stun_attr_type_requested_transport: + case tnet_stun_attr_type_ice_use_candidate: + case tnet_stun_attr_type_ice_priority: + case tnet_stun_attr_type_ice_controlled: + case tnet_stun_attr_type_ice_controlling: + case tnet_stun_attr_type_connection_id: { + extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; + const tnet_stun_attr_vdata_t* _pc_self = (const tnet_stun_attr_vdata_t*)pc_self; + if (pc_self->__def__ != tnet_stun_attr_vdata_def_t) { + TSK_DEBUG_ERROR("Invalid base type"); + return -2; + } + if (_pc_self->p_data_ptr && _pc_self->u_data_size) { + if (IS_VDATA_UINT16(pc_self->hdr.e_type) && _pc_self->u_data_size == 2) { + *((uint16_t*)&p_buff_ptr[*p_written]) = tnet_htons_2(&_pc_self->p_data_ptr[0]); + } + else if (IS_VDATA_UINT32(pc_self->hdr.e_type) && _pc_self->u_data_size == 4) { + *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]); + } + else if (IS_VDATA_UINT64(pc_self->hdr.e_type) && _pc_self->u_data_size == 8) { + *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[0]); + *((uint32_t*)&p_buff_ptr[*p_written + 4]) = (uint32_t)tnet_htonl_2(&_pc_self->p_data_ptr[4]); + } + else if (pc_self->hdr.e_type == tnet_stun_attr_type_unknown_attrs && _pc_self->u_data_size && !(_pc_self->u_data_size & 1)) { + uint16_t u; + for (u = 0; u < _pc_self->u_data_size; u += 2) { + *((uint16_t*)&p_buff_ptr[*p_written + u]) = tnet_htons_2(&_pc_self->p_data_ptr[u]); + } + } + else { + memcpy(&p_buff_ptr[*p_written], _pc_self->p_data_ptr, _pc_self->u_data_size); + } + *p_written += _pc_self->u_data_size; + } + if (with_padding) { + ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); + } + *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); + return 0; + } + case tnet_stun_attr_type_error_code: { + const tnet_stun_attr_error_code_t* _pc_self = (const tnet_stun_attr_error_code_t*)pc_self; + *((uint32_t*)&p_buff_ptr[*p_written]) = (uint32_t)tnet_htonl(((_pc_self->u_class & 0x07) << 8) | _pc_self->u_number); + if (_pc_self->p_reason_phrase) { + memcpy(&p_buff_ptr[*p_written + 4], _pc_self->p_reason_phrase, tsk_strlen(_pc_self->p_reason_phrase)); + } + *p_written += 4 + tsk_strlen(_pc_self->p_reason_phrase); + if (with_padding) { + ALIGN_ON_32BITS_AND_SET_PADDING_ZEROS(&p_buff_ptr[*p_written], *p_written); + } + *((uint16_t*)&p_buff_ptr[2]) = tnet_htons((unsigned short)*p_written - kStunAttrHdrSizeInOctets); + return 0; + } + default: { + TSK_DEBUG_ERROR("Attribute type=%d is unknown.", pc_self->hdr.e_type); + return -2; + } + } } int tnet_stun_attr_init(tnet_stun_attr_t* p_self, tnet_stun_attr_type_t e_type, uint16_t u_length) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - p_self->hdr.e_type = e_type; - p_self->hdr.u_length = u_length; - return 0; + 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); + 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); + 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); + 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); + return _tnet_stun_attr_write(pc_transac_id, pc_self, p_buff_ptr, n_buff_size, kWithPadding, p_written); } int tnet_stun_attr_read(const tnet_stun_transac_id_t* pc_transac_id, const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_consumed_octets, tnet_stun_attr_t** pp_attr) { - tnet_stun_attr_type_t Type; - uint16_t Length, PadLength; - int ret = -1; - static const void* kNullBuffPtr = tsk_null; - if (!pc_buff_ptr || !n_buff_size || !pp_attr || !p_consumed_octets) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (n_buff_size < kStunAttrHdrSizeInOctets) { - TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size); - return -2; - } - - Type = tnet_ntohs_2(&pc_buff_ptr[0]); - Length = tnet_ntohs_2(&pc_buff_ptr[2]); - if (Length > n_buff_size) { - TSK_DEBUG_ERROR("Buffer too short(%u). Length=%u", (unsigned)n_buff_size, (unsigned)Length); - return -3; - } - - PadLength = (Length & 0x03) ? (4 - (Length & 0x03)) : 0; - - *pp_attr = tsk_null; - *p_consumed_octets = kStunAttrHdrSizeInOctets + Length + PadLength; - - switch (Type) { - case tnet_stun_attr_type_mapped_address: - case tnet_stun_attr_type_alternate_server: - case tnet_stun_attr_type_xor_mapped_address: - case tnet_stun_attr_type_xor_peer_address: - case tnet_stun_attr_type_xor_relayed_address: { - // First 8bits must be ignored - tnet_stun_address_family_t e_family = pc_buff_ptr[5]; - uint16_t u_port = tnet_ntohs_2(&pc_buff_ptr[6]); - tnet_stun_attr_address_t* p_attr; - tsk_bool_t b_xor = IS_ADDRESS_XOR(Type); - uint16_t u, u_addr_size = (e_family == tnet_stun_address_family_ipv6) ? 16 : 4; - - if (b_xor) { - u_port ^= kStunMagicCookieShort; - } - if ((ret = tnet_stun_attr_address_create(Type, e_family, u_port, (const tnet_stun_addr_t*)kNullBuffPtr, &p_attr))) { - return ret; - } - if (b_xor) { - *((uint32_t*)&p_attr->address[0]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8]) ^ kStunMagicCookieLong); - for (u = 4; u < u_addr_size; u += 4) { - if (pc_transac_id) { - *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ tnet_ntohl_2(((uint32_t*)(*pc_transac_id + u - 4)))); - } - else { - *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ 0); - } - } - } - else { - memcpy(p_attr->address, &pc_buff_ptr[8], u_addr_size); - } - *pp_attr = TNET_STUN_ATTR(p_attr); - break; - } - - case tnet_stun_attr_type_error_code: { - // First 21bits must be ignored - uint8_t Class = pc_buff_ptr[6] & 0x07; - uint8_t Number = pc_buff_ptr[7] & 0xff; - tnet_stun_attr_error_code_t* p_attr; - if ((ret = tnet_stun_attr_error_code_create(Class, Number, &pc_buff_ptr[8], (Length - 4), &p_attr))) { - return ret; - } - *pp_attr = TNET_STUN_ATTR(p_attr); - break; - } - - case tnet_stun_attr_type_data: - case tnet_stun_attr_type_unknown_attrs: - case tnet_stun_attr_type_dont_fragment: - case tnet_stun_attr_type_software: - case tnet_stun_attr_type_nonce: - case tnet_stun_attr_type_realm: - case tnet_stun_attr_type_username: - case tnet_stun_attr_type_password: - case tnet_stun_attr_type_channel_number: - case tnet_stun_attr_type_message_integrity: - case tnet_stun_attr_type_fingerprint: - case tnet_stun_attr_type_lifetime: - case tnet_stun_attr_type_requested_transport: - case tnet_stun_attr_type_ice_use_candidate: - case tnet_stun_attr_type_ice_priority: - case tnet_stun_attr_type_ice_controlled: - case tnet_stun_attr_type_ice_controlling: - case tnet_stun_attr_type_connection_id: - default: { - tnet_stun_attr_vdata_t* p_attr; - if (IS_VDATA_UINT16(Type) && Length == 2) { - uint16_t u16 = tnet_ntohs_2(&pc_buff_ptr[4]); - if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u16, 2, &p_attr))) { - return ret; - } - } - else if (IS_VDATA_UINT32(Type) && Length == 4) { - uint32_t u32 = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]); - if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u32, 4, &p_attr))) { - return ret; - } - } - else if (IS_VDATA_UINT64(Type) && Length == 8) { - uint64_t u64 = ((uint64_t)tnet_ntohl_2(&pc_buff_ptr[4])) << 32; - u64 |= tnet_ntohl_2(&pc_buff_ptr[8]); - if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u64, 8, &p_attr))) { - return ret; - } - } - else if (Type == tnet_stun_attr_type_unknown_attrs && Length && !(Length & 1)) { - uint16_t u; - uint8_t *_p_data_ptr = tsk_malloc(Length); - if (!_p_data_ptr) { - TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", Length); - return -4; - } - memcpy(_p_data_ptr, &pc_buff_ptr[4], Length); - for (u = 0; u < Length; u += 2) { - *((uint16_t*)&_p_data_ptr[u]) = tnet_htons_2(&_p_data_ptr[u]); - } - if ((ret = tnet_stun_attr_vdata_create(Type, _p_data_ptr, Length, &p_attr))) { - TSK_FREE(_p_data_ptr); - return ret; - } - TSK_FREE(_p_data_ptr); - } - else { - if ((ret = tnet_stun_attr_vdata_create(Type, &pc_buff_ptr[4], Length, &p_attr))) { - return ret; - } - } - *pp_attr = TNET_STUN_ATTR(p_attr); - break; - } - } - return ret; + tnet_stun_attr_type_t Type; + uint16_t Length, PadLength; + int ret = -1; + static const void* kNullBuffPtr = tsk_null; + if (!pc_buff_ptr || !n_buff_size || !pp_attr || !p_consumed_octets) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (n_buff_size < kStunAttrHdrSizeInOctets) { + TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size); + return -2; + } + + Type = tnet_ntohs_2(&pc_buff_ptr[0]); + Length = tnet_ntohs_2(&pc_buff_ptr[2]); + if (Length > n_buff_size) { + TSK_DEBUG_ERROR("Buffer too short(%u). Length=%u", (unsigned)n_buff_size, (unsigned)Length); + return -3; + } + + PadLength = (Length & 0x03) ? (4 - (Length & 0x03)) : 0; + + *pp_attr = tsk_null; + *p_consumed_octets = kStunAttrHdrSizeInOctets + Length + PadLength; + + switch (Type) { + case tnet_stun_attr_type_mapped_address: + case tnet_stun_attr_type_alternate_server: + case tnet_stun_attr_type_xor_mapped_address: + case tnet_stun_attr_type_xor_peer_address: + case tnet_stun_attr_type_xor_relayed_address: { + // First 8bits must be ignored + tnet_stun_address_family_t e_family = pc_buff_ptr[5]; + uint16_t u_port = tnet_ntohs_2(&pc_buff_ptr[6]); + tnet_stun_attr_address_t* p_attr; + tsk_bool_t b_xor = IS_ADDRESS_XOR(Type); + uint16_t u, u_addr_size = (e_family == tnet_stun_address_family_ipv6) ? 16 : 4; + + if (b_xor) { + u_port ^= kStunMagicCookieShort; + } + if ((ret = tnet_stun_attr_address_create(Type, e_family, u_port, (const tnet_stun_addr_t*)kNullBuffPtr, &p_attr))) { + return ret; + } + if (b_xor) { + *((uint32_t*)&p_attr->address[0]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8]) ^ kStunMagicCookieLong); + for (u = 4; u < u_addr_size; u += 4) { + if (pc_transac_id) { + *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ tnet_ntohl_2(((uint32_t*)(*pc_transac_id + u - 4)))); + } + else { + *((uint32_t*)&p_attr->address[u]) = (uint32_t)tnet_htonl(tnet_ntohl_2(&pc_buff_ptr[8 + u]) ^ 0); + } + } + } + else { + memcpy(p_attr->address, &pc_buff_ptr[8], u_addr_size); + } + *pp_attr = TNET_STUN_ATTR(p_attr); + break; + } + + case tnet_stun_attr_type_error_code: { + // First 21bits must be ignored + uint8_t Class = pc_buff_ptr[6] & 0x07; + uint8_t Number = pc_buff_ptr[7] & 0xff; + tnet_stun_attr_error_code_t* p_attr; + if ((ret = tnet_stun_attr_error_code_create(Class, Number, &pc_buff_ptr[8], (Length - 4), &p_attr))) { + return ret; + } + *pp_attr = TNET_STUN_ATTR(p_attr); + break; + } + + case tnet_stun_attr_type_data: + case tnet_stun_attr_type_unknown_attrs: + case tnet_stun_attr_type_dont_fragment: + case tnet_stun_attr_type_software: + case tnet_stun_attr_type_nonce: + case tnet_stun_attr_type_realm: + case tnet_stun_attr_type_username: + case tnet_stun_attr_type_password: + case tnet_stun_attr_type_channel_number: + case tnet_stun_attr_type_message_integrity: + case tnet_stun_attr_type_fingerprint: + case tnet_stun_attr_type_lifetime: + case tnet_stun_attr_type_requested_transport: + case tnet_stun_attr_type_ice_use_candidate: + case tnet_stun_attr_type_ice_priority: + case tnet_stun_attr_type_ice_controlled: + case tnet_stun_attr_type_ice_controlling: + case tnet_stun_attr_type_connection_id: + default: { + tnet_stun_attr_vdata_t* p_attr; + if (IS_VDATA_UINT16(Type) && Length == 2) { + uint16_t u16 = tnet_ntohs_2(&pc_buff_ptr[4]); + if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u16, 2, &p_attr))) { + return ret; + } + } + else if (IS_VDATA_UINT32(Type) && Length == 4) { + uint32_t u32 = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]); + if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u32, 4, &p_attr))) { + return ret; + } + } + else if (IS_VDATA_UINT64(Type) && Length == 8) { + uint64_t u64 = ((uint64_t)tnet_ntohl_2(&pc_buff_ptr[4])) << 32; + u64 |= tnet_ntohl_2(&pc_buff_ptr[8]); + if ((ret = tnet_stun_attr_vdata_create(Type, (uint8_t*)&u64, 8, &p_attr))) { + return ret; + } + } + else if (Type == tnet_stun_attr_type_unknown_attrs && Length && !(Length & 1)) { + uint16_t u; + uint8_t *_p_data_ptr = tsk_malloc(Length); + if (!_p_data_ptr) { + TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", Length); + return -4; + } + memcpy(_p_data_ptr, &pc_buff_ptr[4], Length); + for (u = 0; u < Length; u += 2) { + *((uint16_t*)&_p_data_ptr[u]) = tnet_htons_2(&_p_data_ptr[u]); + } + if ((ret = tnet_stun_attr_vdata_create(Type, _p_data_ptr, Length, &p_attr))) { + TSK_FREE(_p_data_ptr); + return ret; + } + TSK_FREE(_p_data_ptr); + } + else { + if ((ret = tnet_stun_attr_vdata_create(Type, &pc_buff_ptr[4], Length, &p_attr))) { + return ret; + } + } + *pp_attr = TNET_STUN_ATTR(p_attr); + break; + } + } + return ret; } // ============== VDATA (USERNAME, MESSAGE-INTEGRITY, ...) ================ // int tnet_stun_attr_vdata_create(tnet_stun_attr_type_t e_type, const uint8_t* pc_data_ptr, uint16_t u_data_size, tnet_stun_attr_vdata_t** pp_attr) { - int ret = -1; - uint16_t u_length = pc_data_ptr ? u_data_size : 0; - tnet_stun_attr_vdata_t* p_attr = tsk_null; - extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; - if (!pp_attr) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (!(p_attr = tsk_object_new(tnet_stun_attr_vdata_def_t))) { - ret = -2; - goto bail; - } - if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), e_type, u_length))) { - goto bail; - } - if (u_length) { - if (!(p_attr->p_data_ptr = tsk_malloc(u_length + 1))) { - ret = -3; - goto bail; - } - memcpy(p_attr->p_data_ptr, pc_data_ptr, u_length); - p_attr->u_data_size = u_length; - p_attr->p_data_ptr[u_length] = '\0'; - } - *pp_attr = p_attr; + int ret = -1; + uint16_t u_length = pc_data_ptr ? u_data_size : 0; + tnet_stun_attr_vdata_t* p_attr = tsk_null; + extern const tsk_object_def_t *tnet_stun_attr_vdata_def_t; + if (!pp_attr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (!(p_attr = tsk_object_new(tnet_stun_attr_vdata_def_t))) { + ret = -2; + goto bail; + } + if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), e_type, u_length))) { + goto bail; + } + if (u_length) { + if (!(p_attr->p_data_ptr = tsk_malloc(u_length + 1))) { + ret = -3; + goto bail; + } + memcpy(p_attr->p_data_ptr, pc_data_ptr, u_length); + p_attr->u_data_size = u_length; + p_attr->p_data_ptr[u_length] = '\0'; + } + *pp_attr = p_attr; bail: - if (ret) { - TSK_OBJECT_SAFE_FREE(p_attr); - } - return ret; + if (ret) { + TSK_OBJECT_SAFE_FREE(p_attr); + } + return ret; } int tnet_stun_attr_vdata_update(tnet_stun_attr_vdata_t* p_self, const uint8_t* pc_data_ptr, uint16_t u_data_size) { - uint16_t _u_data_size = (pc_data_ptr && u_data_size) ? u_data_size : 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (_u_data_size) { - if (!(p_self->p_data_ptr = tsk_realloc(p_self->p_data_ptr, _u_data_size + 1))) { - p_self->u_data_size = 0; - ((tnet_stun_attr_t*)p_self)->hdr.u_length = 0; - return -3; - } - memcpy(p_self->p_data_ptr, pc_data_ptr, _u_data_size); - p_self->p_data_ptr[_u_data_size] = '\0'; - } - else { - TSK_FREE(p_self->p_data_ptr); - } - p_self->u_data_size = _u_data_size; - ((tnet_stun_attr_t*)p_self)->hdr.u_length = p_self->u_data_size; - return 0; + uint16_t _u_data_size = (pc_data_ptr && u_data_size) ? u_data_size : 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (_u_data_size) { + if (!(p_self->p_data_ptr = tsk_realloc(p_self->p_data_ptr, _u_data_size + 1))) { + p_self->u_data_size = 0; + ((tnet_stun_attr_t*)p_self)->hdr.u_length = 0; + return -3; + } + memcpy(p_self->p_data_ptr, pc_data_ptr, _u_data_size); + p_self->p_data_ptr[_u_data_size] = '\0'; + } + else { + TSK_FREE(p_self->p_data_ptr); + } + p_self->u_data_size = _u_data_size; + ((tnet_stun_attr_t*)p_self)->hdr.u_length = p_self->u_data_size; + return 0; } static tsk_object_t* tnet_stun_attr_vdata_ctor(tsk_object_t * self, va_list * app) { - tnet_stun_attr_vdata_t *p_vdata = (tnet_stun_attr_vdata_t *)self; - if (p_vdata) { - } - return self; + 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) { + tnet_stun_attr_vdata_t *p_vdata = (tnet_stun_attr_vdata_t *)self; + if (p_vdata) { #if PRINT_DESTROYED_MSG - TSK_DEBUG_INFO("*** STUN Attribute(VDATA) destroyed ***"); + TSK_DEBUG_INFO("*** STUN Attribute(VDATA) destroyed ***"); #endif - TSK_FREE(p_vdata->p_data_ptr); - } - return self; + 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, + 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; @@ -533,57 +533,57 @@ 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; + 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; + 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; + 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) { + tnet_stun_attr_address_t *p_addr = (tnet_stun_attr_address_t *)self; + if (p_addr) { #if PRINT_DESTROYED_MSG - TSK_DEBUG_INFO("*** STUN Attribute(ADDRESS) destroyed ***"); + TSK_DEBUG_INFO("*** STUN Attribute(ADDRESS) destroyed ***"); #endif - } - return self; + } + 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, + 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; @@ -592,60 +592,60 @@ const tsk_object_def_t *tnet_stun_attr_address_def_t = &tnet_stun_attr_address_d // ================ 15.6. ERROR-CODE ========== // int tnet_stun_attr_error_code_create(uint8_t u_class, uint8_t u_number, const void* pc_reason_phrase, uint16_t u_reason_phrase, struct tnet_stun_attr_error_code_s** pp_attr) { - int ret = -1; - extern const tsk_object_def_t *tnet_stun_attr_error_code_def_t; - tnet_stun_attr_error_code_t* p_attr = tsk_null; - uint16_t u_length = (uint16_t)(4 + tsk_strlen(pc_reason_phrase)); - if (!pp_attr) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!(p_attr = tsk_object_new(tnet_stun_attr_error_code_def_t))) { - ret = -2; - goto bail; - } - if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), tnet_stun_attr_type_error_code, u_length))) { - goto bail; - } - p_attr->u_class = u_class; - p_attr->u_number = u_number; - if (pc_reason_phrase && u_reason_phrase) { - if (!(p_attr->p_reason_phrase = tsk_strndup(pc_reason_phrase, u_reason_phrase))) { - ret = -3; - goto bail; - } - } - *pp_attr = p_attr; + int ret = -1; + extern const tsk_object_def_t *tnet_stun_attr_error_code_def_t; + tnet_stun_attr_error_code_t* p_attr = tsk_null; + uint16_t u_length = (uint16_t)(4 + tsk_strlen(pc_reason_phrase)); + if (!pp_attr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!(p_attr = tsk_object_new(tnet_stun_attr_error_code_def_t))) { + ret = -2; + goto bail; + } + if ((ret = tnet_stun_attr_init(TNET_STUN_ATTR(p_attr), tnet_stun_attr_type_error_code, u_length))) { + goto bail; + } + p_attr->u_class = u_class; + p_attr->u_number = u_number; + if (pc_reason_phrase && u_reason_phrase) { + if (!(p_attr->p_reason_phrase = tsk_strndup(pc_reason_phrase, u_reason_phrase))) { + ret = -3; + goto bail; + } + } + *pp_attr = p_attr; bail: - if (ret) { - TSK_OBJECT_SAFE_FREE(p_attr); - } - return ret; + if (ret) { + TSK_OBJECT_SAFE_FREE(p_attr); + } + return ret; } static tsk_object_t* tnet_stun_attr_error_code_ctor(tsk_object_t * self, va_list * app) { - tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self; - if (p_ec) { - } - return self; + tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self; + if (p_ec) { + } + return self; } static tsk_object_t* tnet_stun_attr_error_code_dtor(tsk_object_t * self) { - tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self; - if (p_ec) { + tnet_stun_attr_error_code_t *p_ec = (tnet_stun_attr_error_code_t *)self; + if (p_ec) { #if PRINT_DESTROYED_MSG - TSK_DEBUG_INFO("*** STUN Attribute(ERROR-CODE) destroyed ***"); + TSK_DEBUG_INFO("*** STUN Attribute(ERROR-CODE) destroyed ***"); #endif - TSK_FREE(p_ec->p_reason_phrase); - } - return self; + TSK_FREE(p_ec->p_reason_phrase); + } + return self; } static const tsk_object_def_t tnet_stun_attr_error_code_def_s = { - sizeof(tnet_stun_attr_error_code_t), - tnet_stun_attr_error_code_ctor, - tnet_stun_attr_error_code_dtor, - _tnet_stun_attr_cmp, + sizeof(tnet_stun_attr_error_code_t), + tnet_stun_attr_error_code_ctor, + tnet_stun_attr_error_code_dtor, + _tnet_stun_attr_cmp, }; const tsk_object_def_t *tnet_stun_attr_error_code_def_t = &tnet_stun_attr_error_code_def_s; diff --git a/tinyNET/src/stun/tnet_stun_pkt.c b/tinyNET/src/stun/tnet_stun_pkt.c index e4d559d..a996897 100755 --- a/tinyNET/src/stun/tnet_stun_pkt.c +++ b/tinyNET/src/stun/tnet_stun_pkt.c @@ -36,716 +36,717 @@ 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; + extern const tsk_object_def_t *tnet_stun_pkt_def_t; + if (!pp_attr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!(*pp_attr = tsk_object_new(tnet_stun_pkt_def_t))) { + TSK_DEBUG_ERROR("Failed to create STUN pkt object"); + return -2; + } + if (!((*pp_attr)->p_list_attrs = tsk_list_create())) { + TSK_OBJECT_SAFE_FREE(*pp_attr); + return -3; + } + if (pc_transac_id) { + memcpy((*pp_attr)->transac_id, *pc_transac_id, sizeof(tnet_stun_transac_id_t)); + } + else { + tnet_stun_utils_transac_id_rand(&(*pp_attr)->transac_id); + } + (*pp_attr)->e_type = e_type; + (*pp_attr)->u_length = u_length; + return 0; } int tnet_stun_pkt_attr_add(tnet_stun_pkt_t* p_self, tnet_stun_attr_t** pp_attr) { - if (!p_self || !pp_attr || !*pp_attr) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_list_push_back_data(p_self->p_list_attrs, (void**)pp_attr); - return 0; + if (!p_self || !pp_attr || !*pp_attr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_list_push_back_data(p_self->p_list_attrs, (void**)pp_attr); + return 0; } int tnet_stun_pkt_attrs_add(tnet_stun_pkt_t* p_self, ...) { - va_list ap; - int ret = 0; - tnet_stun_pkt_attr_add_t e_add_attr; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - va_start(ap, p_self); - - while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) { - switch (e_add_attr) { - case tnet_stun_pkt_attr_add_vdata: { - // (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE) - enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e); - const uint8_t* P_DATA_PTR = va_arg(ap, const uint8_t*); - uint16_t U_DATA_SIZE = tsk_va_arg_u16(ap); - tnet_stun_attr_vdata_t *p_attr; - if ((ret = tnet_stun_attr_vdata_create(E_TYPE, P_DATA_PTR, U_DATA_SIZE, &p_attr))) { - goto bail; - } - if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { - TSK_OBJECT_SAFE_FREE(p_attr); - goto bail; - } - break; - } - case tnet_stun_pkt_attr_add_address: { - // (enum tnet_stun_attr_type_e)(E_TYPE), (enum tnet_stun_address_family_e)(E_FAMILY), (uint16_t)(U_PORT), (const tnet_stun_addr_t*)PC_ADDR_PTR - enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e); - enum tnet_stun_address_family_e E_FAMILY = va_arg(ap, enum tnet_stun_address_family_e); - uint16_t U_PORT = tsk_va_arg_u16(ap); - const tnet_stun_addr_t* PC_ADDR_PTR = va_arg(ap, const tnet_stun_addr_t*); - tnet_stun_attr_address_t *p_attr; - if ((ret = tnet_stun_attr_address_create(E_TYPE, E_FAMILY, U_PORT, PC_ADDR_PTR, &p_attr))) { - goto bail; - } - if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { - TSK_OBJECT_SAFE_FREE(p_attr); - goto bail; - } - break; - } - case tnet_stun_pkt_attr_add_error_code: { - // (uint8_t)(U8_CLASS), (uint8_t)(U8_NUMBER), (const char*)(PC_REASON_STR) - uint8_t U8_CLASS = tsk_va_arg_u8(ap); - uint8_t U8_NUMBER = tsk_va_arg_u8(ap); - const char* PC_REASON_STR = va_arg(ap, const char*); - tnet_stun_attr_error_code_t *p_attr; - if ((ret = tnet_stun_attr_error_code_create(U8_CLASS, U8_NUMBER, PC_REASON_STR, (uint16_t)tsk_strlen(PC_REASON_STR), &p_attr))) { - goto bail; - } - if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { - TSK_OBJECT_SAFE_FREE(p_attr); - goto bail; - } - break; - } - case tnet_stun_pkt_attr_add_unknown_attrs: { - // (...) - tsk_buffer_t* p_buffer = tsk_buffer_create_null(); - tnet_stun_attr_vdata_t *p_attr; - uint16_t u_16; - if (!p_buffer) { - TSK_DEBUG_ERROR("Failed to create buffer"); - ret = -4; - goto bail; - } - while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) { - if (e_add_attr != tnet_stun_pkt_attr_add_unknown_attrs_val) { - TSK_OBJECT_SAFE_FREE(p_buffer); - TSK_DEBUG_ERROR("Arguments corrupted or invalid."); - ret = -3; - goto bail; - } - u_16 = tsk_va_arg_u16(ap); - tsk_buffer_append(p_buffer, &u_16, 2); - } - if ((ret = tnet_stun_attr_vdata_create(tnet_stun_attr_type_unknown_attrs, p_buffer->data, (uint16_t)p_buffer->size, &p_attr))) { - TSK_OBJECT_SAFE_FREE(p_buffer); - goto bail; - } - TSK_OBJECT_SAFE_FREE(p_buffer); - if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { - TSK_OBJECT_SAFE_FREE(p_attr); - goto bail; - } - break; - } - default: { - TSK_DEBUG_ERROR("Arguments corrupted or invalid."); - ret = -2; - goto bail; - } - } - } + va_list ap; + int ret = 0; + tnet_stun_pkt_attr_add_t e_add_attr; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + va_start(ap, p_self); + + while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) { + switch (e_add_attr) { + case tnet_stun_pkt_attr_add_vdata: { + // (enum tnet_stun_attr_type_e)(E_TYPE), (const uint8_t*)(P_DATA_PTR), (uint16_t)(U_DATA_SIZE) + enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e); + const uint8_t* P_DATA_PTR = va_arg(ap, const uint8_t*); + uint16_t U_DATA_SIZE = tsk_va_arg_u16(ap); + tnet_stun_attr_vdata_t *p_attr; + if ((ret = tnet_stun_attr_vdata_create(E_TYPE, P_DATA_PTR, U_DATA_SIZE, &p_attr))) { + goto bail; + } + if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { + TSK_OBJECT_SAFE_FREE(p_attr); + goto bail; + } + break; + } + case tnet_stun_pkt_attr_add_address: { + // (enum tnet_stun_attr_type_e)(E_TYPE), (enum tnet_stun_address_family_e)(E_FAMILY), (uint16_t)(U_PORT), (const tnet_stun_addr_t*)PC_ADDR_PTR + enum tnet_stun_attr_type_e E_TYPE = va_arg(ap, enum tnet_stun_attr_type_e); + enum tnet_stun_address_family_e E_FAMILY = va_arg(ap, enum tnet_stun_address_family_e); + uint16_t U_PORT = tsk_va_arg_u16(ap); + const tnet_stun_addr_t* PC_ADDR_PTR = va_arg(ap, const tnet_stun_addr_t*); + tnet_stun_attr_address_t *p_attr; + if ((ret = tnet_stun_attr_address_create(E_TYPE, E_FAMILY, U_PORT, PC_ADDR_PTR, &p_attr))) { + goto bail; + } + if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { + TSK_OBJECT_SAFE_FREE(p_attr); + goto bail; + } + break; + } + case tnet_stun_pkt_attr_add_error_code: { + // (uint8_t)(U8_CLASS), (uint8_t)(U8_NUMBER), (const char*)(PC_REASON_STR) + uint8_t U8_CLASS = tsk_va_arg_u8(ap); + uint8_t U8_NUMBER = tsk_va_arg_u8(ap); + const char* PC_REASON_STR = va_arg(ap, const char*); + tnet_stun_attr_error_code_t *p_attr; + if ((ret = tnet_stun_attr_error_code_create(U8_CLASS, U8_NUMBER, PC_REASON_STR, (uint16_t)tsk_strlen(PC_REASON_STR), &p_attr))) { + goto bail; + } + if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { + TSK_OBJECT_SAFE_FREE(p_attr); + goto bail; + } + break; + } + case tnet_stun_pkt_attr_add_unknown_attrs: { + // (...) + tsk_buffer_t* p_buffer = tsk_buffer_create_null(); + tnet_stun_attr_vdata_t *p_attr; + uint16_t u_16; + if (!p_buffer) { + TSK_DEBUG_ERROR("Failed to create buffer"); + ret = -4; + goto bail; + } + while ((e_add_attr = va_arg(ap, tnet_stun_pkt_attr_add_t)) != tnet_stun_pkt_attr_add_null) { + if (e_add_attr != tnet_stun_pkt_attr_add_unknown_attrs_val) { + TSK_OBJECT_SAFE_FREE(p_buffer); + TSK_DEBUG_ERROR("Arguments corrupted or invalid."); + ret = -3; + goto bail; + } + u_16 = tsk_va_arg_u16(ap); + tsk_buffer_append(p_buffer, &u_16, 2); + } + if ((ret = tnet_stun_attr_vdata_create(tnet_stun_attr_type_unknown_attrs, p_buffer->data, (uint16_t)p_buffer->size, &p_attr))) { + TSK_OBJECT_SAFE_FREE(p_buffer); + goto bail; + } + TSK_OBJECT_SAFE_FREE(p_buffer); + if ((ret = tnet_stun_pkt_attr_add(p_self, (tnet_stun_attr_t**)&p_attr))) { + TSK_OBJECT_SAFE_FREE(p_attr); + goto bail; + } + break; + } + default: { + TSK_DEBUG_ERROR("Arguments corrupted or invalid."); + ret = -2; + goto bail; + } + } + } bail: - va_end(ap); - return ret; + va_end(ap); + return ret; } int tnet_stun_pkt_attr_remove(struct tnet_stun_pkt_s* p_self, enum tnet_stun_attr_type_e e_type) { - tsk_list_item_t* pc_item; - tnet_stun_attr_t* pc_attr; - if (!p_self || !p_self->p_list_attrs) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + tsk_list_item_t* pc_item; + tnet_stun_attr_t* pc_attr; + if (!p_self || !p_self->p_list_attrs) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } again: - tsk_list_foreach(pc_item, p_self->p_list_attrs) { - if ((pc_attr = (tnet_stun_attr_t*)pc_item->data)) { - if (pc_attr->hdr.e_type == e_type) { - tsk_list_remove_item(p_self->p_list_attrs, pc_item); - goto again; - } - } - } - return 0; + tsk_list_foreach(pc_item, p_self->p_list_attrs) { + if ((pc_attr = (tnet_stun_attr_t*)pc_item->data)) { + if (pc_attr->hdr.e_type == e_type) { + tsk_list_remove_item(p_self->p_list_attrs, pc_item); + goto again; + } + } + } + return 0; } int tnet_stun_pkt_attr_find(const tnet_stun_pkt_t* pc_self, tnet_stun_attr_type_t e_type, tsk_size_t u_index, const tnet_stun_attr_t** ppc_attr) { - const tsk_list_item_t* pc_item; - const tnet_stun_attr_t* pc_attr; - if (!pc_self || !ppc_attr) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_attr = tsk_null; - tsk_list_foreach(pc_item, pc_self->p_list_attrs) { - if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { - if (pc_attr->hdr.e_type == e_type && !u_index--) { - *ppc_attr = pc_attr; - break; - } - } - } - return 0; + const tsk_list_item_t* pc_item; + const tnet_stun_attr_t* pc_attr; + if (!pc_self || !ppc_attr) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_attr = tsk_null; + tsk_list_foreach(pc_item, pc_self->p_list_attrs) { + if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { + if (pc_attr->hdr.e_type == e_type && !u_index--) { + *ppc_attr = pc_attr; + break; + } + } + } + return 0; } tsk_bool_t tnet_stun_pkt_attr_exists(const tnet_stun_pkt_t* pc_self, tnet_stun_attr_type_t e_type) { - const tnet_stun_attr_t* pc_attr; - int ret = tnet_stun_pkt_attr_find(pc_self, e_type, 0, &pc_attr); - return (pc_attr && (ret == 0)); + const tnet_stun_attr_t* pc_attr; + int ret = tnet_stun_pkt_attr_find(pc_self, e_type, 0, &pc_attr); + return (pc_attr && (ret == 0)); } int tnet_stun_pkt_get_size_in_octetunits_without_padding(const tnet_stun_pkt_t* pc_self, tsk_size_t* p_size) { - const tsk_list_item_t* pc_item; - const tnet_stun_attr_t* pc_attr; - tsk_size_t n_size; - int ret; - if (!pc_self || !p_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *p_size = kStunPktHdrSizeInOctets; - tsk_list_foreach(pc_item, pc_self->p_list_attrs) { - if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { - if ((ret = tnet_stun_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) { - return ret; - } - *p_size += n_size; - } - } - if (pc_self->opt.fingerprint) { - *p_size += kStunAttrHdrSizeInOctets + 4; - } - if (pc_self->opt.dontfrag) { - *p_size += kStunAttrHdrSizeInOctets; - } - return 0; + const tsk_list_item_t* pc_item; + const tnet_stun_attr_t* pc_attr; + tsk_size_t n_size; + int ret; + if (!pc_self || !p_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *p_size = kStunPktHdrSizeInOctets; + tsk_list_foreach(pc_item, pc_self->p_list_attrs) { + if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { + if ((ret = tnet_stun_attr_get_size_in_octetunits_without_padding(pc_attr, &n_size))) { + return ret; + } + *p_size += n_size; + } + } + if (pc_self->opt.fingerprint) { + *p_size += kStunAttrHdrSizeInOctets + 4; + } + if (pc_self->opt.dontfrag) { + *p_size += kStunAttrHdrSizeInOctets; + } + return 0; } int tnet_stun_pkt_get_size_in_octetunits_with_padding(const tnet_stun_pkt_t* pc_self, tsk_size_t* p_size) { - const tsk_list_item_t* pc_item; - const tnet_stun_attr_t* pc_attr; - tsk_size_t n_size; - int ret; - if (!pc_self || !p_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *p_size = kStunPktHdrSizeInOctets; - tsk_list_foreach(pc_item, pc_self->p_list_attrs) { - if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { - if ((ret = tnet_stun_attr_get_size_in_octetunits_with_padding(pc_attr, &n_size))) { - return ret; - } - *p_size += n_size; - } - } - if (pc_self->opt.fingerprint) { - *p_size += kStunAttrHdrSizeInOctets + 4; - } - if (pc_self->opt.dontfrag) { - *p_size += kStunAttrHdrSizeInOctets; - } - return 0; + const tsk_list_item_t* pc_item; + const tnet_stun_attr_t* pc_attr; + tsk_size_t n_size; + int ret; + if (!pc_self || !p_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *p_size = kStunPktHdrSizeInOctets; + tsk_list_foreach(pc_item, pc_self->p_list_attrs) { + if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { + if ((ret = tnet_stun_attr_get_size_in_octetunits_with_padding(pc_attr, &n_size))) { + return ret; + } + *p_size += n_size; + } + } + if (pc_self->opt.fingerprint) { + *p_size += kStunAttrHdrSizeInOctets + 4; + } + if (pc_self->opt.dontfrag) { + *p_size += kStunAttrHdrSizeInOctets; + } + return 0; } int tnet_stun_pkt_write_with_padding(const tnet_stun_pkt_t* pc_self, uint8_t* p_buff_ptr, tsk_size_t n_buff_size, tsk_size_t *p_written) { - const tsk_list_item_t* pc_item; - const tnet_stun_attr_t* pc_attr; - tsk_size_t n_size; - int ret; - uint8_t *_p_buff_ptr = p_buff_ptr, *_p_msg_int_start; - if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, p_written))) { - return ret; - } - if ((n_buff_size < *p_written)) { - TSK_DEBUG_ERROR("Buffer too short: %u<%u", (unsigned)n_buff_size, (unsigned)*p_written); - return -1; - } - - // write header - *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->e_type); - *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(kStunMagicCookie); - memcpy(&p_buff_ptr[8], pc_self->transac_id, sizeof(pc_self->transac_id)); - - p_buff_ptr += kStunPktHdrSizeInOctets; - n_buff_size -= kStunPktHdrSizeInOctets; - - // write attributes - tsk_list_foreach(pc_item, pc_self->p_list_attrs) { - if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { - if ((pc_attr->hdr.e_type == tnet_stun_attr_type_message_integrity)) { - continue; // because 'MESSAGE-INTEGRITY' must be the latest attribute - } - if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) { - return ret; - } - p_buff_ptr += n_size; - n_buff_size -= n_size; - } - } - - // DONT-FRAGMENT - if (pc_self->opt.dontfrag && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_dont_fragment, &pc_attr) == 0 && !pc_attr) { - *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_dont_fragment); // Type - *((uint16_t*)&p_buff_ptr[2]) = 0; // Length - p_buff_ptr += 4; - } - - // MESSAGE-INTEGRITY - if (!tsk_strnullORempty(pc_self->p_pwd) && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_message_integrity, &pc_attr) == 0 && pc_attr) { - /* RFC 5389 - 15.4. MESSAGE-INTEGRITY - The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message. - - For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password)) - For short-term credentials ==> key = SASLprep(password) - */ - - tsk_sha1digest_t hmac; - const tnet_stun_attr_vdata_t *pc_attr_username = tsk_null, *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null; - static const uint16_t kMsgIntTotalLength = kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE; - _p_msg_int_start = p_buff_ptr; - - // write attribute - if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) { - return ret; - } - p_buff_ptr += n_size; - n_buff_size -= n_size; - - // Length (must be correct before computing message integrity) - *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets)); - - if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_username, (const tnet_stun_attr_t**)&pc_attr_username))) { - return ret; - } - if (pc_attr_username) { - if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm))) { - return ret; - } - if (pc_attr_realm) { - if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce))) { - return ret; - } - } - } - if (pc_attr_username && pc_attr_realm && pc_attr_nonce) { - // LONG-TERM - char* p_keystr = tsk_null; - tsk_md5digest_t md5; - tsk_sprintf(&p_keystr, "%s:%s:%s", pc_attr_username->p_data_ptr, pc_attr_realm->p_data_ptr, pc_self->p_pwd); - TSK_MD5_DIGEST_CALC(p_keystr, (tsk_size_t)tsk_strlen(p_keystr), md5); - hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac); - TSK_FREE(p_keystr); - } - else { - // SHORT-TERM - hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), pc_self->p_pwd, (tsk_size_t)tsk_strlen(pc_self->p_pwd), hmac); - } - - // update MESSAGE-INTEGRITY attribute value - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, hmac, TSK_SHA1_DIGEST_SIZE))) { - return ret; - } - if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, _p_msg_int_start, kMsgIntTotalLength, &n_size))) { - return ret; - } - } - - // Length before computing FINGERPRINT - *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets + ((pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) ? 8 : 0))); - - if (pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) { - /* RFC 5389 - 15.5. FINGERPRINT - The FINGERPRINT attribute MAY be present in all STUN messages. The - value of the attribute is computed as the CRC-32 of the STUN message - up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with - the 32-bit value 0x5354554e - */ - uint32_t u_fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, _p_buff_ptr, (int32_t)(p_buff_ptr - _p_buff_ptr)) ^ kStunFingerprintXorConst; - *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_fingerprint); // Type - *((uint16_t*)&p_buff_ptr[2]) = tnet_htons(4); // Length - *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(u_fingerprint); - p_buff_ptr += 8; - } - - *p_written = (tsk_size_t)(p_buff_ptr - _p_buff_ptr); - return 0; + const tsk_list_item_t* pc_item; + const tnet_stun_attr_t* pc_attr; + tsk_size_t n_size; + int ret; + uint8_t *_p_buff_ptr = p_buff_ptr, *_p_msg_int_start; + if (!pc_self || !p_buff_ptr || !n_buff_size || !p_written) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, p_written))) { + return ret; + } + if ((n_buff_size < *p_written)) { + TSK_DEBUG_ERROR("Buffer too short: %u<%u", (unsigned)n_buff_size, (unsigned)*p_written); + return -1; + } + + // write header + *((uint16_t*)&p_buff_ptr[0]) = tnet_htons((unsigned short)pc_self->e_type); + *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(kStunMagicCookie); + memcpy(&p_buff_ptr[8], pc_self->transac_id, sizeof(pc_self->transac_id)); + + p_buff_ptr += kStunPktHdrSizeInOctets; + n_buff_size -= kStunPktHdrSizeInOctets; + + // write attributes + tsk_list_foreach(pc_item, pc_self->p_list_attrs) { + if ((pc_attr = (const tnet_stun_attr_t*)pc_item->data)) { + if ((pc_attr->hdr.e_type == tnet_stun_attr_type_message_integrity)) { + continue; // because 'MESSAGE-INTEGRITY' must be the latest attribute + } + if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) { + return ret; + } + p_buff_ptr += n_size; + n_buff_size -= n_size; + } + } + + // DONT-FRAGMENT + if (pc_self->opt.dontfrag && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_dont_fragment, &pc_attr) == 0 && !pc_attr) { + *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_dont_fragment); // Type + *((uint16_t*)&p_buff_ptr[2]) = 0; // Length + p_buff_ptr += 4; + } + + // MESSAGE-INTEGRITY + if (!tsk_strnullORempty(pc_self->p_pwd) && tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_message_integrity, &pc_attr) == 0 && pc_attr) { + /* RFC 5389 - 15.4. MESSAGE-INTEGRITY + The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message. + + For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password)) + For short-term credentials ==> key = SASLprep(password) + */ + + tsk_sha1digest_t hmac; + const tnet_stun_attr_vdata_t *pc_attr_username = tsk_null, *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null; + static const uint16_t kMsgIntTotalLength = kStunAttrHdrSizeInOctets + TSK_SHA1_DIGEST_SIZE; + _p_msg_int_start = p_buff_ptr; + + // write attribute + if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, p_buff_ptr, n_buff_size, &n_size))) { + return ret; + } + p_buff_ptr += n_size; + n_buff_size -= n_size; + + // Length (must be correct before computing message integrity) + *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets)); + + if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_username, (const tnet_stun_attr_t**)&pc_attr_username))) { + return ret; + } + if (pc_attr_username) { + if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm))) { + return ret; + } + if (pc_attr_realm) { + if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce))) { + return ret; + } + } + } + if (pc_attr_username && pc_attr_realm && pc_attr_nonce) { + // LONG-TERM + char* p_keystr = tsk_null; + tsk_md5digest_t md5; + tsk_sprintf(&p_keystr, "%s:%s:%s", pc_attr_username->p_data_ptr, pc_attr_realm->p_data_ptr, pc_self->p_pwd); + TSK_MD5_DIGEST_CALC(p_keystr, (tsk_size_t)tsk_strlen(p_keystr), md5); + hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac); + TSK_FREE(p_keystr); + } + else { + // SHORT-TERM + hmac_sha1digest_compute(_p_buff_ptr, (tsk_size_t)(_p_msg_int_start - _p_buff_ptr), pc_self->p_pwd, (tsk_size_t)tsk_strlen(pc_self->p_pwd), hmac); + } + + // update MESSAGE-INTEGRITY attribute value + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, hmac, TSK_SHA1_DIGEST_SIZE))) { + return ret; + } + if ((ret = tnet_stun_attr_write_with_padding(&pc_self->transac_id, pc_attr, _p_msg_int_start, kMsgIntTotalLength, &n_size))) { + return ret; + } + } + + // Length before computing FINGERPRINT + *((uint16_t*)&_p_buff_ptr[2]) = tnet_htons((unsigned short)((p_buff_ptr - _p_buff_ptr) - kStunPktHdrSizeInOctets + ((pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) ? 8 : 0))); + + if (pc_self->opt.fingerprint && (p_buff_ptr - _p_buff_ptr) >= 8) { + /* RFC 5389 - 15.5. FINGERPRINT + The FINGERPRINT attribute MAY be present in all STUN messages. The + value of the attribute is computed as the CRC-32 of the STUN message + up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with + the 32-bit value 0x5354554e + */ + uint32_t u_fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, _p_buff_ptr, (int32_t)(p_buff_ptr - _p_buff_ptr)) ^ kStunFingerprintXorConst; + *((uint16_t*)&p_buff_ptr[0]) = tnet_htons(tnet_stun_attr_type_fingerprint); // Type + *((uint16_t*)&p_buff_ptr[2]) = tnet_htons(4); // Length + *((uint32_t*)&p_buff_ptr[4]) = (uint32_t)tnet_htonl(u_fingerprint); + p_buff_ptr += 8; + } + + *p_written = (tsk_size_t)(p_buff_ptr - _p_buff_ptr); + return 0; } int tnet_stun_pkt_write_with_padding_2(const struct tnet_stun_pkt_s* pc_self, struct tsk_buffer_s** pp_buff) { - tsk_size_t u_buff_size; - int ret; - if (!pc_self || !pp_buff) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *pp_buff = tsk_null; - if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, &u_buff_size))) { - goto bail; - } - u_buff_size += kStunBuffMinPad; - if (!(*pp_buff = tsk_buffer_create(tsk_null, u_buff_size))) { - goto bail; - } - if ((ret = tnet_stun_pkt_write_with_padding(pc_self, (*pp_buff)->data, (*pp_buff)->size, &(*pp_buff)->size))) { - goto bail; - } + tsk_size_t u_buff_size; + int ret; + if (!pc_self || !pp_buff) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *pp_buff = tsk_null; + if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_self, &u_buff_size))) { + goto bail; + } + u_buff_size += kStunBuffMinPad; + if (!(*pp_buff = tsk_buffer_create(tsk_null, u_buff_size))) { + goto bail; + } + if ((ret = tnet_stun_pkt_write_with_padding(pc_self, (*pp_buff)->data, (*pp_buff)->size, &(*pp_buff)->size))) { + goto bail; + } bail: - if (ret) { - TSK_OBJECT_SAFE_FREE(*pp_buff); - } - return ret; + if (ret) { + TSK_OBJECT_SAFE_FREE(*pp_buff); + } + return ret; } int tnet_stun_pkt_is_complete(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tsk_bool_t *pb_is_complete) { - if (!pb_is_complete) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *pb_is_complete = tsk_false; - if (pc_buff_ptr && n_buff_size >= kStunPktHdrSizeInOctets) { - tsk_size_t n_paylen_in_octets = tnet_ntohs_2(&pc_buff_ptr[2]); - *pb_is_complete = ((n_buff_size - kStunPktHdrSizeInOctets) >= n_paylen_in_octets); - } - return 0; + if (!pb_is_complete) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *pb_is_complete = tsk_false; + if (pc_buff_ptr && n_buff_size >= kStunPktHdrSizeInOctets) { + tsk_size_t n_paylen_in_octets = tnet_ntohs_2(&pc_buff_ptr[2]); + *pb_is_complete = ((n_buff_size - kStunPktHdrSizeInOctets) >= n_paylen_in_octets); + } + return 0; } int tnet_stun_pkt_read(const uint8_t* pc_buff_ptr, tsk_size_t n_buff_size, tnet_stun_pkt_t** pp_pkt) { - tsk_bool_t b_is_complete; - uint16_t PayloadLengthInOctets; - tnet_stun_pkt_type_t Type; - tnet_stun_transac_id_t transac_id; - uint32_t MagicCookie; - int ret; - - if (!pc_buff_ptr || !n_buff_size || !pp_pkt) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!TNET_STUN_BUFF_IS_STUN2(pc_buff_ptr, n_buff_size)) { - TSK_DEBUG_ERROR("Buffer doesn't contain a valid STUN2 pkt"); - return -2; - } - if ((ret = tnet_stun_pkt_is_complete(pc_buff_ptr, n_buff_size, &b_is_complete))) { - return ret; - } - if (!b_is_complete) { - TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size); - return -3; - } - - // read the header - Type = tnet_ntohs_2(&pc_buff_ptr[0]); - PayloadLengthInOctets = tnet_ntohs_2(&pc_buff_ptr[2]); - MagicCookie = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]); - if (MagicCookie != kStunMagicCookieLong) { - TSK_DEBUG_ERROR("%x not a valid STUN2 magic cookie", MagicCookie); - return -4; - } - memcpy(transac_id, &pc_buff_ptr[8], sizeof(tnet_stun_transac_id_t)); - // create the pkt - if ((ret = tnet_stun_pkt_create(Type, PayloadLengthInOctets, (const tnet_stun_transac_id_t*)&transac_id, pp_pkt))) { - return ret; - } - - if (PayloadLengthInOctets > 0) { - tnet_stun_attr_t* p_attr; - tsk_size_t n_consumed_octets; - pc_buff_ptr += kStunPktHdrSizeInOctets; - do { - if ((ret = tnet_stun_attr_read((const tnet_stun_transac_id_t*)&(*pp_pkt)->transac_id, pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) { - return ret; - } - if ((ret = tnet_stun_pkt_attr_add((*pp_pkt), &p_attr))) { - TSK_OBJECT_SAFE_FREE((*pp_pkt)); - return ret; - } - PayloadLengthInOctets -= (uint16_t)n_consumed_octets; - pc_buff_ptr += n_consumed_octets; - } while (PayloadLengthInOctets >= kStunAttrHdrSizeInOctets); - } - - return 0; + tsk_bool_t b_is_complete; + uint16_t PayloadLengthInOctets; + tnet_stun_pkt_type_t Type; + tnet_stun_transac_id_t transac_id; + uint32_t MagicCookie; + int ret; + + if (!pc_buff_ptr || !n_buff_size || !pp_pkt) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!TNET_STUN_BUFF_IS_STUN2(pc_buff_ptr, n_buff_size)) { + TSK_DEBUG_ERROR("Buffer doesn't contain a valid STUN2 pkt"); + return -2; + } + if ((ret = tnet_stun_pkt_is_complete(pc_buff_ptr, n_buff_size, &b_is_complete))) { + return ret; + } + if (!b_is_complete) { + TSK_DEBUG_ERROR("Buffer too short(%u)", (unsigned)n_buff_size); + return -3; + } + + // read the header + Type = tnet_ntohs_2(&pc_buff_ptr[0]); + PayloadLengthInOctets = tnet_ntohs_2(&pc_buff_ptr[2]); + MagicCookie = (uint32_t)tnet_ntohl_2(&pc_buff_ptr[4]); + if (MagicCookie != kStunMagicCookieLong) { + TSK_DEBUG_ERROR("%x not a valid STUN2 magic cookie", MagicCookie); + return -4; + } + memcpy(transac_id, &pc_buff_ptr[8], sizeof(tnet_stun_transac_id_t)); + // create the pkt + if ((ret = tnet_stun_pkt_create(Type, PayloadLengthInOctets, (const tnet_stun_transac_id_t*)&transac_id, pp_pkt))) { + return ret; + } + + if (PayloadLengthInOctets > 0) { + tnet_stun_attr_t* p_attr; + tsk_size_t n_consumed_octets; + pc_buff_ptr += kStunPktHdrSizeInOctets; + do { + if ((ret = tnet_stun_attr_read((const tnet_stun_transac_id_t*)&(*pp_pkt)->transac_id, pc_buff_ptr, PayloadLengthInOctets, &n_consumed_octets, &p_attr))) { + return ret; + } + if ((ret = tnet_stun_pkt_attr_add((*pp_pkt), &p_attr))) { + TSK_OBJECT_SAFE_FREE((*pp_pkt)); + return ret; + } + PayloadLengthInOctets -= (uint16_t)n_consumed_octets; + pc_buff_ptr += n_consumed_octets; + } + while (PayloadLengthInOctets >= kStunAttrHdrSizeInOctets); + } + + return 0; } int tnet_stun_pkt_auth_prepare(tnet_stun_pkt_t* p_self, const char* pc_usr_name, const char* pc_pwd, const char* pc_realm, const char* pc_nonce) { - const tnet_stun_attr_t* pc_attr; - int ret; - static const tsk_sha1digest_t __pc_sha1digestEmpty = { 0 }; - static const uint16_t __u_sha1digestEmpty = sizeof(__pc_sha1digestEmpty); - if (!p_self /*|| !pc_usr_name*/ || !pc_pwd /*|| !pc_realm || !pc_nonce*/) { // "username", "realm" and "nonce" are null for short-term authentication - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - // USERNAME - if (pc_usr_name) { // LONG-TERM, optional for SHORT-TERM - if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_username, &pc_attr))) { - goto bail; - } - if (pc_attr) { - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_usr_name, (uint16_t)tsk_strlen(pc_usr_name)))) { - goto bail; - } - } - else { - ret = tnet_stun_pkt_attrs_add(p_self, - TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(pc_usr_name), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - } - // REALM - if (pc_realm) { // LONG-TERM - if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_realm, &pc_attr))) { - goto bail; - } - if (pc_attr) { - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_realm, (uint16_t)tsk_strlen(pc_realm)))) { - goto bail; - } - } - else { - ret = tnet_stun_pkt_attrs_add(p_self, - TNET_STUN_PKT_ATTR_ADD_REALM_ZT(pc_realm), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - } - // NONCE - if (pc_nonce) { // LONG-TERM - if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_nonce, &pc_attr))) { - goto bail; - } - if (pc_attr) { - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_nonce, (uint16_t)tsk_strlen(pc_nonce)))) { - goto bail; - } - } - else { - ret = tnet_stun_pkt_attrs_add(p_self, - TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(pc_nonce), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - } - // MESSAGE-INTEGRITY - if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_message_integrity, &pc_attr))) { - goto bail; - } - if (!pc_attr) { - ret = tnet_stun_pkt_attrs_add(p_self, - TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_sha1digestEmpty, __u_sha1digestEmpty), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - - // PASSWORD - tsk_strupdate(&p_self->p_pwd, pc_pwd); + const tnet_stun_attr_t* pc_attr; + int ret; + static const tsk_sha1digest_t __pc_sha1digestEmpty = { 0 }; + static const uint16_t __u_sha1digestEmpty = sizeof(__pc_sha1digestEmpty); + if (!p_self /*|| !pc_usr_name*/ || !pc_pwd /*|| !pc_realm || !pc_nonce*/) { // "username", "realm" and "nonce" are null for short-term authentication + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + // USERNAME + if (pc_usr_name) { // LONG-TERM, optional for SHORT-TERM + if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_username, &pc_attr))) { + goto bail; + } + if (pc_attr) { + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_usr_name, (uint16_t)tsk_strlen(pc_usr_name)))) { + goto bail; + } + } + else { + ret = tnet_stun_pkt_attrs_add(p_self, + TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(pc_usr_name), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + } + // REALM + if (pc_realm) { // LONG-TERM + if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_realm, &pc_attr))) { + goto bail; + } + if (pc_attr) { + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_realm, (uint16_t)tsk_strlen(pc_realm)))) { + goto bail; + } + } + else { + ret = tnet_stun_pkt_attrs_add(p_self, + TNET_STUN_PKT_ATTR_ADD_REALM_ZT(pc_realm), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + } + // NONCE + if (pc_nonce) { // LONG-TERM + if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_nonce, &pc_attr))) { + goto bail; + } + if (pc_attr) { + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr, (const uint8_t*)pc_nonce, (uint16_t)tsk_strlen(pc_nonce)))) { + goto bail; + } + } + else { + ret = tnet_stun_pkt_attrs_add(p_self, + TNET_STUN_PKT_ATTR_ADD_NONCE_ZT(pc_nonce), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + } + // MESSAGE-INTEGRITY + if ((ret = tnet_stun_pkt_attr_find_first(p_self, tnet_stun_attr_type_message_integrity, &pc_attr))) { + goto bail; + } + if (!pc_attr) { + ret = tnet_stun_pkt_attrs_add(p_self, + TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_sha1digestEmpty, __u_sha1digestEmpty), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + + // PASSWORD + tsk_strupdate(&p_self->p_pwd, pc_pwd); bail: - return ret; + return ret; } // pc_resp = 401 or 438 int tnet_stun_pkt_auth_prepare_2(struct tnet_stun_pkt_s* p_self, const char* pc_usr_name, const char* pc_pwd, const struct tnet_stun_pkt_s* pc_resp) { - const tnet_stun_attr_vdata_t* pc_attr; - const char *pc_nonce, *pc_realm; - int ret; - if (!p_self || !pc_usr_name || !pc_pwd || !pc_resp) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - // NONCE - if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr))) { - goto bail; - } - if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) { - TSK_DEBUG_ERROR("Invalid NONCE in 401"); - ret = -3; - goto bail; - } - pc_nonce = (const char*)pc_attr->p_data_ptr; - // REALM - if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr))) { - goto bail; - } - if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) { - TSK_DEBUG_ERROR("Invalid REALM in 401"); - ret = -3; - goto bail; - } - pc_realm = (const char*)pc_attr->p_data_ptr; - - if ((ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, pc_realm, pc_nonce))) { - goto bail; - } - - // TRANSACTION-ID - if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) { - goto bail; - } + const tnet_stun_attr_vdata_t* pc_attr; + const char *pc_nonce, *pc_realm; + int ret; + if (!p_self || !pc_usr_name || !pc_pwd || !pc_resp) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + // NONCE + if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr))) { + goto bail; + } + if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) { + TSK_DEBUG_ERROR("Invalid NONCE in 401"); + ret = -3; + goto bail; + } + pc_nonce = (const char*)pc_attr->p_data_ptr; + // REALM + if ((ret = tnet_stun_pkt_attr_find_first(pc_resp, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr))) { + goto bail; + } + if (!pc_attr || !pc_attr->p_data_ptr || !pc_attr->u_data_size) { + TSK_DEBUG_ERROR("Invalid REALM in 401"); + ret = -3; + goto bail; + } + pc_realm = (const char*)pc_attr->p_data_ptr; + + if ((ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, pc_realm, pc_nonce))) { + goto bail; + } + + // TRANSACTION-ID + if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) { + goto bail; + } bail: - return ret; + return ret; } int tnet_stun_pkt_auth_copy(tnet_stun_pkt_t* p_self, const char* pc_usr_name, const char* pc_pwd, const tnet_stun_pkt_t* pc_pkt) { - const tnet_stun_attr_vdata_t *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null; - int ret; - tsk_bool_t b_ok; - if (!p_self || !pc_pwd || !pc_usr_name || !pc_pkt) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - b_ok = - (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm)) == 0 && pc_attr_realm - && (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce)) == 0 && pc_attr_nonce; - - if (b_ok && (ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, (const char*)pc_attr_realm->p_data_ptr, (const char*)pc_attr_nonce->p_data_ptr))) { - goto bail; - } + const tnet_stun_attr_vdata_t *pc_attr_realm = tsk_null, *pc_attr_nonce = tsk_null; + int ret; + tsk_bool_t b_ok; + if (!p_self || !pc_pwd || !pc_usr_name || !pc_pkt) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + b_ok = + (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_realm, (const tnet_stun_attr_t**)&pc_attr_realm)) == 0 && pc_attr_realm + && (ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce)) == 0 && pc_attr_nonce; + + if (b_ok && (ret = tnet_stun_pkt_auth_prepare(p_self, pc_usr_name, pc_pwd, (const char*)pc_attr_realm->p_data_ptr, (const char*)pc_attr_nonce->p_data_ptr))) { + goto bail; + } bail: - return ret; + return ret; } int tnet_stun_pkt_get_errorcode(const struct tnet_stun_pkt_s* pc_self, uint16_t* pu_code) { - const tnet_stun_attr_error_code_t* pc_attr; - int ret; - if (!pc_self && !pu_code) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *pu_code = 0; - if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr))) { - return ret; - } - if (pc_attr) { - *pu_code = (pc_attr->u_class * 100) + pc_attr->u_number; - } - return 0; + const tnet_stun_attr_error_code_t* pc_attr; + int ret; + if (!pc_self && !pu_code) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *pu_code = 0; + if ((ret = tnet_stun_pkt_attr_find_first(pc_self, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr))) { + return ret; + } + if (pc_attr) { + *pu_code = (pc_attr->u_class * 100) + pc_attr->u_number; + } + return 0; } int tnet_stun_pkt_process_err420(struct tnet_stun_pkt_s *p_self, const struct tnet_stun_pkt_s *pc_pkt_resp420) { - const tnet_stun_attr_vdata_t* pc_attr; - uint16_t u16; - int ret; - tsk_bool_t b_done = tsk_false; - if (!p_self || !pc_pkt_resp420) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { - goto bail; - } - if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) { - TSK_DEBUG_ERROR("UNKNOWN-ATTRIBUTES missing in 420"); - ret = -3; - goto bail; - } - for (u16 = 0; u16 < pc_attr->u_data_size; u16 += 2) { - switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { - case tnet_stun_attr_type_dont_fragment: { - p_self->opt.dontfrag = 0; - b_done = tsk_true; - break; - } - case tnet_stun_attr_type_fingerprint: { - p_self->opt.fingerprint = 0; - b_done = tsk_true; - break; - } - } - } - - if (b_done) { - // TRANSACTION-ID - if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) { - goto bail; - } - } + const tnet_stun_attr_vdata_t* pc_attr; + uint16_t u16; + int ret; + tsk_bool_t b_done = tsk_false; + if (!p_self || !pc_pkt_resp420) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { + goto bail; + } + if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) { + TSK_DEBUG_ERROR("UNKNOWN-ATTRIBUTES missing in 420"); + ret = -3; + goto bail; + } + for (u16 = 0; u16 < pc_attr->u_data_size; u16 += 2) { + switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { + case tnet_stun_attr_type_dont_fragment: { + p_self->opt.dontfrag = 0; + b_done = tsk_true; + break; + } + case tnet_stun_attr_type_fingerprint: { + p_self->opt.fingerprint = 0; + b_done = tsk_true; + break; + } + } + } + + if (b_done) { + // TRANSACTION-ID + if ((ret = tnet_stun_utils_transac_id_rand(&p_self->transac_id))) { + goto bail; + } + } bail: - return ret; + return ret; } static tsk_object_t* tnet_stun_pkt_ctor(tsk_object_t * self, va_list * app) { - tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self; - if (p_pkt) { - p_pkt->opt.fingerprint = kStunOptFingerPrint; - p_pkt->opt.dontfrag = kStunOptDontFragment; - } - return self; + tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self; + if (p_pkt) { + p_pkt->opt.fingerprint = kStunOptFingerPrint; + p_pkt->opt.dontfrag = kStunOptDontFragment; + } + return self; } static tsk_object_t* tnet_stun_pkt_dtor(tsk_object_t * self) { - tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self; - if (p_pkt) { + tnet_stun_pkt_t *p_pkt = (tnet_stun_pkt_t *)self; + if (p_pkt) { #if PRINT_DESTROYED_MSG - TSK_DEBUG_INFO("*** STUN pkt destroyed ***"); + TSK_DEBUG_INFO("*** STUN pkt destroyed ***"); #endif - TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs); - TSK_FREE(p_pkt->p_pwd); - } - return self; + TSK_OBJECT_SAFE_FREE(p_pkt->p_list_attrs); + TSK_FREE(p_pkt->p_pwd); + } + return self; } static const tsk_object_def_t tnet_stun_pkt_def_s = { - sizeof(tnet_stun_pkt_t), - tnet_stun_pkt_ctor, - tnet_stun_pkt_dtor, - tsk_null, + sizeof(tnet_stun_pkt_t), + tnet_stun_pkt_ctor, + tnet_stun_pkt_dtor, + tsk_null, }; const tsk_object_def_t *tnet_stun_pkt_def_t = &tnet_stun_pkt_def_s; diff --git a/tinyNET/src/stun/tnet_stun_types.h b/tinyNET/src/stun/tnet_stun_types.h index 386f471..d09bf99 100755 --- a/tinyNET/src/stun/tnet_stun_types.h +++ b/tinyNET/src/stun/tnet_stun_types.h @@ -141,9 +141,9 @@ typedef enum tnet_stun_method_e { tnet_stun_method_data = 0x0007, /**< rfc5766 - Data (only indication semantics defined) */ tnet_stun_method_createpermission = 0x0008, /**< rfc5766 - CreatePermission (only request/response semantics defined */ tnet_stun_method_channelbind = 0x0009, /**< rfc5766 - ChannelBind (only request/response semantics defined) */ - tnet_stun_method_connect = 0x000a,/**< rfc6062 - Connect */ - tnet_stun_method_connectionbind = 0x000b,/**< rfc6062 - ConnectionBind */ - tnet_stun_method_connectionattempt = 0x000c,/**< rfc6062 - ConnectionAttempt */ + tnet_stun_method_connect = 0x000a,/**< rfc6062 - Connect */ + tnet_stun_method_connectionbind = 0x000b,/**< rfc6062 - ConnectionBind */ + tnet_stun_method_connectionattempt = 0x000c,/**< rfc6062 - ConnectionAttempt */ } tnet_stun_method_t; @@ -167,8 +167,8 @@ typedef enum tnet_stun_address_family_e { // rfc5766 - 14.7. REQUESTED-TRANSPORT typedef enum tnet_turn_transport_e { - tnet_turn_transport_udp = 17, - tnet_turn_transport_tcp = 6 + tnet_turn_transport_udp = 17, + tnet_turn_transport_tcp = 6 } tnet_turn_transport_t; @@ -257,8 +257,8 @@ typedef enum tnet_stun_attr_type_e { tnet_stun_attr_type_ice_controlled = 0x8029, /**< 21.2. STUN Attributes */ tnet_stun_attr_type_ice_controlling = 0x802A, /**< 21.2. STUN Attributes */ - /* rfc6062 */ - tnet_stun_attr_type_connection_id = 0x002a, /**< 6.2. New STUN Attributes */ + /* rfc6062 */ + tnet_stun_attr_type_connection_id = 0x002a, /**< 6.2. New STUN Attributes */ } tnet_stun_attr_type_t; @@ -316,17 +316,17 @@ typedef enum tnet_stun_pkt_type_e { tnet_stun_pkt_type_channelbind_success_response = (tnet_stun_method_channelbind | tnet_stun_mask_success), tnet_stun_pkt_type_channelbind_error_response = (tnet_stun_method_channelbind | tnet_stun_mask_error), - tnet_stun_pkt_type_connect_request = (tnet_stun_method_connect | tnet_stun_mask_request), + tnet_stun_pkt_type_connect_request = (tnet_stun_method_connect | tnet_stun_mask_request), tnet_stun_pkt_type_connect_indication = (tnet_stun_method_connect | tnet_stun_mask_indication), tnet_stun_pkt_type_connect_success_response = (tnet_stun_method_connect | tnet_stun_mask_success), tnet_stun_pkt_type_connect_error_response = (tnet_stun_method_connect | tnet_stun_mask_error), - tnet_stun_pkt_type_connectionbind_request = (tnet_stun_method_connectionbind | tnet_stun_mask_request), + tnet_stun_pkt_type_connectionbind_request = (tnet_stun_method_connectionbind | tnet_stun_mask_request), tnet_stun_pkt_type_connectionbind_indication = (tnet_stun_method_connectionbind | tnet_stun_mask_indication), tnet_stun_pkt_type_connectionbind_success_response = (tnet_stun_method_connectionbind | tnet_stun_mask_success), tnet_stun_pkt_type_connectionbind_error_response = (tnet_stun_method_connectionbind | tnet_stun_mask_error), - tnet_stun_pkt_type_connectionattempt_indication = (tnet_stun_method_connectionattempt | tnet_stun_mask_indication), + tnet_stun_pkt_type_connectionattempt_indication = (tnet_stun_method_connectionattempt | tnet_stun_mask_indication), } tnet_stun_pkt_type_t; diff --git a/tinyNET/src/tinynet.h b/tinyNET/src/tinynet.h index 63df285..b888c8e 100755 --- a/tinyNET/src/tinynet.h +++ b/tinyNET/src/tinynet.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2010-2015 Mamadou DIOP. -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyNET/src/tinynet_config.h b/tinyNET/src/tinynet_config.h index 813c2c0..2633d2f 100755 --- a/tinyNET/src/tinynet_config.h +++ b/tinyNET/src/tinynet_config.h @@ -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. * @@ -98,7 +98,7 @@ # define TNET_BEGIN_DECLS extern "C" { # define TNET_END_DECLS } #else -# define TNET_BEGIN_DECLS +# define TNET_BEGIN_DECLS # define TNET_END_DECLS #endif @@ -107,7 +107,7 @@ #elif defined(__GNUC__) && !defined(__APPLE__) # define TNET_INLINE __inline #else -# define TNET_INLINE +# define TNET_INLINE #endif /* have poll()? */ diff --git a/tinyNET/src/tls/tnet_dtls.c b/tinyNET/src/tls/tnet_dtls.c index 6420c9e..b49bd46 100755 --- a/tinyNET/src/tls/tnet_dtls.c +++ b/tinyNET/src/tls/tnet_dtls.c @@ -33,46 +33,45 @@ #include "tsk_safeobj.h" #include "tsk_debug.h" -typedef struct tnet_dtls_socket_s -{ - TSK_DECLARE_OBJECT; - - struct tnet_socket_s* wrapped_sock; /* not owner: do not try to close */ - tsk_bool_t verify_peer; - tsk_bool_t use_srtp; - tsk_bool_t handshake_completed; - tsk_bool_t handshake_started; - tsk_bool_t handshake_storedata; // whether to store handshaking data or to send it to the remote party - tnet_dtls_setup_t setup; - - struct { - void* ptr; - tsk_size_t size; - tsk_size_t count; - } handshake_data; - - struct{ - const void* usrdata; - tnet_dtls_socket_cb_f func; - } cb; - - struct{ - tnet_fingerprint_t fp; - tnet_dtls_hash_type_t hash; - struct sockaddr_storage addr; - } remote; - struct{ - tnet_fingerprint_t fp; - tnet_dtls_hash_type_t hash; - } local; +typedef struct tnet_dtls_socket_s { + TSK_DECLARE_OBJECT; + + struct tnet_socket_s* wrapped_sock; /* not owner: do not try to close */ + tsk_bool_t verify_peer; + tsk_bool_t use_srtp; + tsk_bool_t handshake_completed; + tsk_bool_t handshake_started; + tsk_bool_t handshake_storedata; // whether to store handshaking data or to send it to the remote party + tnet_dtls_setup_t setup; + + struct { + void* ptr; + tsk_size_t size; + tsk_size_t count; + } handshake_data; + + struct { + const void* usrdata; + tnet_dtls_socket_cb_f func; + } cb; + + struct { + tnet_fingerprint_t fp; + tnet_dtls_hash_type_t hash; + struct sockaddr_storage addr; + } remote; + struct { + tnet_fingerprint_t fp; + tnet_dtls_hash_type_t hash; + } local; #if HAVE_OPENSSL - SSL *ssl; - BIO* rbio; - BIO* wbio; + SSL *ssl; + BIO* rbio; + BIO* wbio; #endif - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } tnet_dtls_socket_t; @@ -83,18 +82,18 @@ tnet_dtls_socket_t; tsk_bool_t tnet_dtls_is_srtp_supported() { #if HAVE_OPENSSL_DTLS_SRTP - return tsk_true; + return tsk_true; #else - return tsk_false; + return tsk_false; #endif } tsk_bool_t tnet_dtls_is_supported() { #if HAVE_OPENSSL_DTLS - return tsk_true; + return tsk_true; #else - return tsk_false; + return tsk_false; #endif } @@ -105,298 +104,304 @@ static tsk_bool_t _tnet_dtls_is_fingerprint_matching(X509* cert, tnet_fingerprin static int _tnet_dtls_verify_cert(int preverify_ok, X509_STORE_CTX *ctx) { - SSL *ssl; - tnet_dtls_socket_t* socket; - - TSK_DEBUG_INFO("_tnet_dtls_verify_cert"); - - ssl = X509_STORE_CTX_get_app_data(ctx); - socket = (tnet_dtls_socket_t*)SSL_get_app_data(ssl); - if (!ssl || !socket){ - TSK_DEBUG_ERROR("Not expected"); - return 0; - } - tsk_safeobj_lock(socket); - if (_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false) { - TSK_DEBUG_ERROR("Failed to match fingerprint"); - tsk_safeobj_unlock(socket); - return 0; - } - tsk_safeobj_unlock(socket); - return 1; + SSL *ssl; + tnet_dtls_socket_t* socket; + + TSK_DEBUG_INFO("_tnet_dtls_verify_cert"); + + ssl = X509_STORE_CTX_get_app_data(ctx); + socket = (tnet_dtls_socket_t*)SSL_get_app_data(ssl); + if (!ssl || !socket) { + TSK_DEBUG_ERROR("Not expected"); + return 0; + } + tsk_safeobj_lock(socket); + if (_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false) { + TSK_DEBUG_ERROR("Failed to match fingerprint"); + tsk_safeobj_unlock(socket); + return 0; + } + tsk_safeobj_unlock(socket); + return 1; } static const EVP_MD *_tnet_dtls_get_hash_evp(tnet_dtls_hash_type_t hash) { - switch (hash){ - case tnet_dtls_hash_type_md5: return EVP_md5(); - case tnet_dtls_hash_type_sha1: return EVP_sha1(); - case tnet_dtls_hash_type_sha256: return EVP_sha256(); - case tnet_dtls_hash_type_sha512: return EVP_sha512(); - default: TSK_DEBUG_ERROR("Invalid parameter: %d not valid as hash type", hash); return tsk_null; - } + switch (hash) { + case tnet_dtls_hash_type_md5: + return EVP_md5(); + case tnet_dtls_hash_type_sha1: + return EVP_sha1(); + case tnet_dtls_hash_type_sha256: + return EVP_sha256(); + case tnet_dtls_hash_type_sha512: + return EVP_sha512(); + default: + TSK_DEBUG_ERROR("Invalid parameter: %d not valid as hash type", hash); + return tsk_null; + } } static int _tnet_dtls_get_fingerprint(X509* cert, const EVP_MD *evp, tnet_fingerprint_t* fingerprint) { - if (!cert || !evp || !fingerprint){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - else{ - unsigned len = 0, i, j; - tnet_fingerprint_t fp; - - if (X509_digest(cert, evp, fp, &len) != 1 || len <= 0){ - TSK_DEBUG_ERROR("X509_digest() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - return -2; - } - for (i = 0, j = 0; i < len; ++i, j += 3){ - sprintf((char*)&(*fingerprint)[j], (i == (len - 1)) ? "%.2X" : "%.2X:", fp[i]); - } - (*fingerprint)[len * 3] = '\0'; - return 0; - } + if (!cert || !evp || !fingerprint) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + else { + unsigned len = 0, i, j; + tnet_fingerprint_t fp; + + if (X509_digest(cert, evp, fp, &len) != 1 || len <= 0) { + TSK_DEBUG_ERROR("X509_digest() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + return -2; + } + for (i = 0, j = 0; i < len; ++i, j += 3) { + sprintf((char*)&(*fingerprint)[j], (i == (len - 1)) ? "%.2X" : "%.2X:", fp[i]); + } + (*fingerprint)[len * 3] = '\0'; + return 0; + } } static tsk_bool_t _tnet_dtls_is_fingerprint_matching(X509* cert, tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash) { - const EVP_MD* evp; - tnet_fingerprint_t fp; - int ret; - - if (!cert || !fingerprint){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - - if (!(evp = _tnet_dtls_get_hash_evp(hash))){ - return tsk_false; - } - if ((ret = _tnet_dtls_get_fingerprint(cert, evp, &fp))){ - return tsk_false; - } - if (!tsk_striequals(fp, fingerprint)){ - TSK_DEBUG_ERROR("DTLS certificate fingerprints mismatch: [%s]#[%s]", fp, *fingerprint); - return tsk_false; - } - return tsk_true; + const EVP_MD* evp; + tnet_fingerprint_t fp; + int ret; + + if (!cert || !fingerprint) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + + if (!(evp = _tnet_dtls_get_hash_evp(hash))) { + return tsk_false; + } + if ((ret = _tnet_dtls_get_fingerprint(cert, evp, &fp))) { + return tsk_false; + } + if (!tsk_striequals(fp, fingerprint)) { + TSK_DEBUG_ERROR("DTLS certificate fingerprints mismatch: [%s]#[%s]", fp, *fingerprint); + return tsk_false; + } + return tsk_true; } static tsk_bool_t _tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_t* socket) { - if (!socket){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_false; - } - else if (socket->verify_peer){ - X509* cert; - - if (!(cert = SSL_get_peer_certificate(socket->ssl))){ - if (socket->verify_peer){ // print error only if verify certs is enabled - TSK_DEBUG_ERROR("Failed to get peer certificate [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - } - return tsk_false; - } - if (!_tnet_dtls_is_fingerprint_matching(cert, &socket->remote.fp, socket->remote.hash)){ - X509_free(cert); - return tsk_false; - } - X509_free(cert); - - if (SSL_get_verify_result(socket->ssl) != X509_V_OK){ - TSK_DEBUG_ERROR("SSL_get_verify_result()#X509_V_OK [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - return tsk_false; - } - } - - return tsk_true; + if (!socket) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_false; + } + else if (socket->verify_peer) { + X509* cert; + + if (!(cert = SSL_get_peer_certificate(socket->ssl))) { + if (socket->verify_peer) { // print error only if verify certs is enabled + TSK_DEBUG_ERROR("Failed to get peer certificate [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + } + return tsk_false; + } + if (!_tnet_dtls_is_fingerprint_matching(cert, &socket->remote.fp, socket->remote.hash)) { + X509_free(cert); + return tsk_false; + } + X509_free(cert); + + if (SSL_get_verify_result(socket->ssl) != X509_V_OK) { + TSK_DEBUG_ERROR("SSL_get_verify_result()#X509_V_OK [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + return tsk_false; + } + } + + return tsk_true; } #endif /* HAVE_OPENSSL */ tnet_dtls_hash_type_t tnet_dtls_get_hash_from_string(const char* hash) { - if (hash){ - int32_t i; - for (i = 0; i < TNET_DTLS_HASH_TYPE_MAX; ++i){ - if (tsk_striequals(TNET_DTLS_HASH_NAMES[i], hash)){ - return (tnet_dtls_hash_type_t)i; - } - } - } - return tnet_dtls_hash_type_none; + if (hash) { + int32_t i; + for (i = 0; i < TNET_DTLS_HASH_TYPE_MAX; ++i) { + if (tsk_striequals(TNET_DTLS_HASH_NAMES[i], hash)) { + return (tnet_dtls_hash_type_t)i; + } + } + } + return tnet_dtls_hash_type_none; } tnet_dtls_setup_t tnet_dtls_get_setup_from_string(const char* setup) { - if (setup){ - int32_t i; - for (i = 0; i < TNET_DTLS_SETUP_MAX; ++i){ - if (tsk_striequals(TNET_DTLS_SETUP_NAMES[i], setup)){ - return (tnet_dtls_setup_t)i; - } - } - } - return tnet_dtls_setup_none; + if (setup) { + int32_t i; + for (i = 0; i < TNET_DTLS_SETUP_MAX; ++i) { + if (tsk_striequals(TNET_DTLS_SETUP_NAMES[i], setup)) { + return (tnet_dtls_setup_t)i; + } + } + } + return tnet_dtls_setup_none; } int tnet_dtls_get_fingerprint(const char* certfile, tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -200; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -200; #else - { - X509* x509; - BIO* bio; - int ret = 0; - const EVP_MD *evp; - - if (tsk_strnullORempty(certfile) || !fingerprint){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if (!(evp = _tnet_dtls_get_hash_evp(hash))){ - return -1; - } - - x509 = tsk_null; - bio = tsk_null; - - if (!(bio = BIO_new(BIO_s_file()))){ - TSK_DEBUG_ERROR("BIO_new(BIO_s_file()) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - ret = -3; - goto bail; - } - if (BIO_read_filename(bio, certfile) != 1){ - TSK_DEBUG_ERROR("BIO_read_filename(%s) failed [%s]", certfile, ERR_error_string(ERR_get_error(), tsk_null)); - ret = -4; - goto bail; - } - if (!(x509 = PEM_read_bio_X509(bio, tsk_null, 0, tsk_null))){ - TSK_DEBUG_ERROR("PEM_read_bio() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - ret = -5; - goto bail; - } - if ((ret = _tnet_dtls_get_fingerprint(x509, evp, fingerprint))){ - goto bail; - } - - bail: - if (bio){ - BIO_free_all(bio); - } - return ret; - } + { + X509* x509; + BIO* bio; + int ret = 0; + const EVP_MD *evp; + + if (tsk_strnullORempty(certfile) || !fingerprint) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if (!(evp = _tnet_dtls_get_hash_evp(hash))) { + return -1; + } + + x509 = tsk_null; + bio = tsk_null; + + if (!(bio = BIO_new(BIO_s_file()))) { + TSK_DEBUG_ERROR("BIO_new(BIO_s_file()) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + ret = -3; + goto bail; + } + if (BIO_read_filename(bio, certfile) != 1) { + TSK_DEBUG_ERROR("BIO_read_filename(%s) failed [%s]", certfile, ERR_error_string(ERR_get_error(), tsk_null)); + ret = -4; + goto bail; + } + if (!(x509 = PEM_read_bio_X509(bio, tsk_null, 0, tsk_null))) { + TSK_DEBUG_ERROR("PEM_read_bio() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + ret = -5; + goto bail; + } + if ((ret = _tnet_dtls_get_fingerprint(x509, evp, fingerprint))) { + goto bail; + } + +bail: + if (bio) { + BIO_free_all(bio); + } + return ret; + } #endif } tnet_dtls_socket_handle_t* tnet_dtls_socket_create(struct tnet_socket_s* wrapped_sock, struct ssl_ctx_st* ssl_ctx) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return tsk_null; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return tsk_null; #else - tnet_dtls_socket_t* socket; - - if (!wrapped_sock || !ssl_ctx){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) { - EC_KEY* ecdh; - const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP - socket->wrapped_sock = tsk_object_ref(wrapped_sock); - if (!(socket->ssl = SSL_new(ssl_ctx))) { - TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - if (set_mtu) { - SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU); - SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28); - socket->ssl->d1->mtu = TNET_DTLS_MTU - 28; - } - if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))){ - TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null)); - if (socket->rbio){ - BIO_free(socket->rbio); - } - if (socket->wbio){ - BIO_free(socket->wbio); - } - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - BIO_set_mem_eof_return(socket->rbio, -1); - BIO_set_mem_eof_return(socket->wbio, -1); - SSL_set_bio(socket->ssl, socket->rbio, socket->wbio); - SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY); - SSL_set_read_ahead(socket->ssl, 1); - // https://groups.google.com/forum/#!topic/doubango/Oo0t1e3tlL8 - if ((ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) { - SSL_set_options(socket->ssl, SSL_OP_SINGLE_ECDH_USE); - SSL_set_tmp_ecdh(socket->ssl, ecdh); - EC_KEY_free(ecdh); - } - - if (set_mtu) { - BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL); - } - - if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))){ - TSK_DEBUG_INFO("SSL cert verify: ON"); - socket->verify_peer = tsk_true; - SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert); - } - else { - TSK_DEBUG_ERROR("Verity not enabled"); - } - - SSL_set_app_data(socket->ssl, socket); - } - return socket; + tnet_dtls_socket_t* socket; + + if (!wrapped_sock || !ssl_ctx) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) { + EC_KEY* ecdh; + const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP + socket->wrapped_sock = tsk_object_ref(wrapped_sock); + if (!(socket->ssl = SSL_new(ssl_ctx))) { + TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + if (set_mtu) { + SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28); + socket->ssl->d1->mtu = TNET_DTLS_MTU - 28; + } + if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))) { + TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null)); + if (socket->rbio) { + BIO_free(socket->rbio); + } + if (socket->wbio) { + BIO_free(socket->wbio); + } + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + BIO_set_mem_eof_return(socket->rbio, -1); + BIO_set_mem_eof_return(socket->wbio, -1); + SSL_set_bio(socket->ssl, socket->rbio, socket->wbio); + SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY); + SSL_set_read_ahead(socket->ssl, 1); + // https://groups.google.com/forum/#!topic/doubango/Oo0t1e3tlL8 + if ((ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) { + SSL_set_options(socket->ssl, SSL_OP_SINGLE_ECDH_USE); + SSL_set_tmp_ecdh(socket->ssl, ecdh); + EC_KEY_free(ecdh); + } + + if (set_mtu) { + BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL); + } + + if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))) { + TSK_DEBUG_INFO("SSL cert verify: ON"); + socket->verify_peer = tsk_true; + SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert); + } + else { + TSK_DEBUG_ERROR("Verity not enabled"); + } + + SSL_set_app_data(socket->ssl, socket); + } + return socket; #endif } tnet_fd_t tnet_dtls_socket_get_fd(const tnet_dtls_socket_handle_t* handle) { - return handle ? ((const tnet_dtls_socket_t*)handle)->wrapped_sock->fd : TNET_INVALID_FD; + return handle ? ((const tnet_dtls_socket_t*)handle)->wrapped_sock->fd : TNET_INVALID_FD; } const struct sockaddr_storage* tnet_dtls_socket_get_remote_addr(const tnet_dtls_socket_handle_t* handle) { - return handle ? &((const tnet_dtls_socket_t*)handle)->remote.addr : tsk_null; + return handle ? &((const tnet_dtls_socket_t*)handle)->remote.addr : tsk_null; } int tnet_dtls_socket_set_callback(tnet_dtls_socket_handle_t* handle, const void* usrdata, tnet_dtls_socket_cb_f func) { - tnet_dtls_socket_t* socket = handle; + tnet_dtls_socket_t* socket = handle; - if (!socket){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!socket) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - socket->cb.usrdata = usrdata; - socket->cb.func = func; - return 0; + socket->cb.usrdata = usrdata; + socket->cb.func = func; + return 0; } int tnet_dtls_socket_set_remote_fingerprint(tnet_dtls_socket_handle_t* handle, const tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash) { - tnet_dtls_socket_t* socket = handle; + tnet_dtls_socket_t* socket = handle; - if (!socket || !fingerprint){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!socket || !fingerprint) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - memcpy(socket->remote.fp, &(*fingerprint)[0], sizeof(tnet_fingerprint_t)); - socket->remote.hash = hash; - return 0; + memcpy(socket->remote.fp, &(*fingerprint)[0], sizeof(tnet_fingerprint_t)); + socket->remote.hash = hash; + return 0; } /* @@ -405,267 +410,267 @@ rfc5764: 4.1. The use_srtp Extension int tnet_dtls_socket_use_srtp(tnet_dtls_socket_handle_t*handle) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS || !HAVE_OPENSSL_DTLS_SRTP - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -200; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -200; #else - tnet_dtls_socket_t* socket = handle; - if (!socket){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if ((socket->use_srtp = tsk_true)){ - if (!socket->verify_peer){ - socket->verify_peer = tsk_true; // DTLS-SRTP requires certtificates - SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert); - } - } - return 0; + tnet_dtls_socket_t* socket = handle; + if (!socket) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if ((socket->use_srtp = tsk_true)) { + if (!socket->verify_peer) { + socket->verify_peer = tsk_true; // DTLS-SRTP requires certtificates + SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert); + } + } + return 0; #endif } int tnet_dtls_socket_set_setup(tnet_dtls_socket_handle_t* handle, tnet_dtls_setup_t setup) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -200; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -200; #else - tnet_dtls_socket_t* socket = handle; - if (!socket){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - switch ((socket->setup = setup)){ - case tnet_dtls_setup_passive: - SSL_set_accept_state(socket->ssl); - break; - case tnet_dtls_setup_active: - case tnet_dtls_setup_actpass: - case tnet_dtls_setup_none: - if (setup != tnet_dtls_setup_active){ - TSK_DEBUG_WARN("using setup=%s is not a good idea", TNET_DTLS_SETUP_NAMES[setup]); - } - SSL_set_connect_state(socket->ssl); - break; - default: - TSK_DEBUG_ERROR("%d not valid value for DTLS setup", (int32_t)setup); - break; - } - return 0; + tnet_dtls_socket_t* socket = handle; + if (!socket) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + switch ((socket->setup = setup)) { + case tnet_dtls_setup_passive: + SSL_set_accept_state(socket->ssl); + break; + case tnet_dtls_setup_active: + case tnet_dtls_setup_actpass: + case tnet_dtls_setup_none: + if (setup != tnet_dtls_setup_active) { + TSK_DEBUG_WARN("using setup=%s is not a good idea", TNET_DTLS_SETUP_NAMES[setup]); + } + SSL_set_connect_state(socket->ssl); + break; + default: + TSK_DEBUG_ERROR("%d not valid value for DTLS setup", (int32_t)setup); + break; + } + return 0; #endif } int tnet_dtls_socket_set_store_handshakingdata(tnet_dtls_socket_handle_t* handle, tsk_bool_t handshake_storedata) { - if (!handle) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - ((tnet_dtls_socket_t*)handle)->handshake_storedata = handshake_storedata; - return 0; + if (!handle) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + ((tnet_dtls_socket_t*)handle)->handshake_storedata = handshake_storedata; + return 0; } int tnet_dtls_socket_get_handshakingdata(tnet_dtls_socket_handle_t* handle, const void** data, tsk_size_t *size) { - if (!handle || !data || !size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *data = ((tnet_dtls_socket_t*)handle)->handshake_data.ptr; - *size = ((tnet_dtls_socket_t*)handle)->handshake_data.count; - return 0; + if (!handle || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *data = ((tnet_dtls_socket_t*)handle)->handshake_data.ptr; + *size = ((tnet_dtls_socket_t*)handle)->handshake_data.count; + return 0; } // This function returns first DTLS record. It's useful to send handshaking data by records to avoid IP fragmentation int tnet_dtls_socket_get_record_first(const void* records, tsk_size_t records_size, const void** record, tsk_size_t* size) { - /* https://tools.ietf.org/html/rfc6347#section-3.2.3 - TLS and DTLS handshake messages can be quite large(in theory up to - 2 ^ 24 - 1 bytes, in practice many kilobytes).By contrast, UDP - datagrams are often limited to <1500 bytes if IP fragmentation is not - desired.In order to compensate for this limitation, each DTLS - handshake message may be fragmented over several DTLS records, each - of which is intended to fit in a single IP datagram.Each DTLS - handshake message contains both a fragment offset and a fragment - length.Thus, a recipient in possession of all bytes of a handshake - message can reassemble the original unfragmented message. */ - // 4.1. Record Layer - https://tools.ietf.org/html/rfc6347#section-4.1 + /* https://tools.ietf.org/html/rfc6347#section-3.2.3 + TLS and DTLS handshake messages can be quite large(in theory up to + 2 ^ 24 - 1 bytes, in practice many kilobytes).By contrast, UDP + datagrams are often limited to <1500 bytes if IP fragmentation is not + desired.In order to compensate for this limitation, each DTLS + handshake message may be fragmented over several DTLS records, each + of which is intended to fit in a single IP datagram.Each DTLS + handshake message contains both a fragment offset and a fragment + length.Thus, a recipient in possession of all bytes of a handshake + message can reassemble the original unfragmented message. */ + // 4.1. Record Layer - https://tools.ietf.org/html/rfc6347#section-4.1 #define kDTLSv1RecordHdrStartIndex 11 #define kDTLSv1RecordHdrLengthFieldLen 2 // uint16 #define kDTLSv1RecordHdrLen (kDTLSv1RecordHdrStartIndex + kDTLSv1RecordHdrLengthFieldLen) - - const uint8_t* pc_records; - tsk_size_t record_length; - if (!records || records_size < kDTLSv1RecordHdrLen || !record || !size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - pc_records = (const uint8_t*)records; - record_length = ((pc_records[kDTLSv1RecordHdrStartIndex] << 8) & 0xFF00) | (pc_records[kDTLSv1RecordHdrStartIndex + 1] & 0xFF); - *record = records; - *size = kDTLSv1RecordHdrLen + record_length; - if ((*size) > TNET_DTLS_MTU) { - TSK_DEBUG_WARN("DTLS record length(%u) > MTU(%u)", (unsigned)(*size), TNET_DTLS_MTU); - } - - return 0; + + const uint8_t* pc_records; + tsk_size_t record_length; + if (!records || records_size < kDTLSv1RecordHdrLen || !record || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + pc_records = (const uint8_t*)records; + record_length = ((pc_records[kDTLSv1RecordHdrStartIndex] << 8) & 0xFF00) | (pc_records[kDTLSv1RecordHdrStartIndex + 1] & 0xFF); + *record = records; + *size = kDTLSv1RecordHdrLen + record_length; + if ((*size) > TNET_DTLS_MTU) { + TSK_DEBUG_WARN("DTLS record length(%u) > MTU(%u)", (unsigned)(*size), TNET_DTLS_MTU); + } + + return 0; } tsk_bool_t tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_handle_t* handle) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -1; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -1; #else - return _tnet_dtls_socket_is_remote_cert_fp_match((tnet_dtls_socket_t*)handle); + return _tnet_dtls_socket_is_remote_cert_fp_match((tnet_dtls_socket_t*)handle); #endif } int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struct sockaddr_storage* remote_addr) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -1; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -1; #else - tnet_dtls_socket_t *socket = handle; - int ret = 0, len; - void* out_data; - - if (!socket) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(socket); - - // update remote address even if handshaking is completed - if (remote_addr) { - socket->remote.addr = *remote_addr; - } - - if (socket->handshake_completed) { - TSK_DEBUG_INFO("Handshake completed"); - ret = 0; - goto bail; - } - - if (!socket->handshake_started) { - if ((ret = SSL_do_handshake(socket->ssl)) != 1) { - switch ((ret = SSL_get_error(socket->ssl, ret))) { - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_NONE: - break; - default: - TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed); - ret = -2; - goto bail; - } - } - socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation - } - - if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) { - if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel - if ((int)socket->handshake_data.size < len) { - if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) { - socket->handshake_data.size = 0; - socket->handshake_data.count = 0; - ret = -5; - goto bail; - } - socket->handshake_data.size = len; - } - socket->handshake_data.count = len; - memcpy(socket->handshake_data.ptr, out_data, len); - } - else { - int sentlen = 0; - tnet_port_t port; - tnet_ip_t ip; - tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type); - const uint8_t *record_ptr, *records_ptr = out_data; - tsk_size_t record_size; - int records_len = len; - - tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port); - TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port); - - //!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP - while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, (const void**)&record_ptr, &record_size)) == 0) { - if (is_dgram) { - sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size); - } - else { - sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size); - } - records_len -= (int)record_size; - records_ptr += record_size; - } - TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen); - } - } - - BIO_reset(socket->rbio); - BIO_reset(socket->wbio); - - if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) { - TSK_DEBUG_INFO("DTLS handshake completed"); + tnet_dtls_socket_t *socket = handle; + int ret = 0, len; + void* out_data; + + if (!socket) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(socket); + + // update remote address even if handshaking is completed + if (remote_addr) { + socket->remote.addr = *remote_addr; + } + + if (socket->handshake_completed) { + TSK_DEBUG_INFO("Handshake completed"); + ret = 0; + goto bail; + } + + if (!socket->handshake_started) { + if ((ret = SSL_do_handshake(socket->ssl)) != 1) { + switch ((ret = SSL_get_error(socket->ssl, ret))) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_NONE: + break; + default: + TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed); + ret = -2; + goto bail; + } + } + socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation + } + + if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) { + if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel + if ((int)socket->handshake_data.size < len) { + if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) { + socket->handshake_data.size = 0; + socket->handshake_data.count = 0; + ret = -5; + goto bail; + } + socket->handshake_data.size = len; + } + socket->handshake_data.count = len; + memcpy(socket->handshake_data.ptr, out_data, len); + } + else { + int sentlen = 0; + tnet_port_t port; + tnet_ip_t ip; + tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type); + const uint8_t *record_ptr, *records_ptr = out_data; + tsk_size_t record_size; + int records_len = len; + + tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port); + TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port); + + //!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP + while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, (const void**)&record_ptr, &record_size)) == 0) { + if (is_dgram) { + sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size); + } + else { + sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size); + } + records_len -= (int)record_size; + records_ptr += record_size; + } + TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen); + } + } + + BIO_reset(socket->rbio); + BIO_reset(socket->wbio); + + if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) { + TSK_DEBUG_INFO("DTLS handshake completed"); #if HAVE_OPENSSL_DTLS_SRTP - if (socket->use_srtp){ + if (socket->use_srtp) { #if !defined(SRTP_MAX_KEY_LEN) # define cipher_key_length (128 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles # define cipher_salt_length (112 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles - // "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80) - // "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80) + // "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80) + // "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80) # define SRTP_MAX_KEY_LEN (cipher_key_length + cipher_salt_length) #endif /* SRTP_MAX_KEY_LEN */ #define EXTRACTOR_dtls_srtp_text "EXTRACTOR-dtls_srtp" #define EXTRACTOR_dtls_srtp_text_len 19 - uint8_t keying_material[SRTP_MAX_KEY_LEN << 1]; - static const tsk_size_t keying_material_size = sizeof(keying_material); - /*if(socket->use_srtp)*/{ - SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl); - if (!p) { - TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - ret = -2; - goto bail; - } - // alert user - _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name)); - - memset(keying_material, 0, sizeof(keying_material)); - - // rfc5764 - 4.2. Key Derivation - ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0); - if (ret != 1) { - // alert listener - _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error); - TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - ret = -2; - goto bail; - } - } - // alert listener - _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size); - } + uint8_t keying_material[SRTP_MAX_KEY_LEN << 1]; + static const tsk_size_t keying_material_size = sizeof(keying_material); + /*if(socket->use_srtp)*/{ + SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl); + if (!p) { + TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + ret = -2; + goto bail; + } + // alert user + _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name)); + + memset(keying_material, 0, sizeof(keying_material)); + + // rfc5764 - 4.2. Key Derivation + ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0); + if (ret != 1) { + // alert listener + _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error); + TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + ret = -2; + goto bail; + } + } + // alert listener + _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size); + } #endif /* HAVE_OPENSSL_DTLS_SRTP */ - _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed); - } - ret = 0; // clear "ret", error will directly jump to "bail:" + _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed); + } + ret = 0; // clear "ret", error will directly jump to "bail:" bail: - tsk_safeobj_unlock(socket); - return ret; + tsk_safeobj_unlock(socket); + return ret; #endif } tsk_bool_t tnet_dtls_socket_is_handshake_completed(const tnet_dtls_socket_handle_t* handle) { - return (handle && ((const tnet_dtls_socket_t *)handle)->handshake_completed); + return (handle && ((const tnet_dtls_socket_t *)handle)->handshake_completed); } /* @@ -678,79 +683,79 @@ Handles DTLS data received over the network using standard functions (e.g. recvf int tnet_dtls_socket_handle_incoming_data(tnet_dtls_socket_handle_t* handle, const void* data, tsk_size_t size) { #if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS - TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); - return -200; + TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled"); + return -200; #else - tnet_dtls_socket_t *socket = handle; - int ret = 0; - - if (!socket || !data || !size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(socket); - - TSK_DEBUG_INFO("Receive DTLS data: %lu", (unsigned long)size); - - // BIO_reset(socket->rbio); - // BIO_reset(socket->wbio); - - if (!socket->rbio || !socket->wbio) { - TSK_DEBUG_ERROR("BIO not initialized yet"); - ret = -2; - goto bail; - } - - if ((ret = _tnet_dtls_socket_do_handshake(socket))) { - goto bail; - } - - if ((ret = BIO_write(socket->rbio, data, (int)size)) != size) { - ret = SSL_get_error(socket->ssl, ret); - TSK_DEBUG_ERROR("BIO_write(rbio, %lu) failed [%s]", (unsigned long)size, ERR_error_string(ERR_get_error(), tsk_null)); - ret = -1; - goto bail; - } - - /*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){ - switch((ret = SSL_get_error(socket->ssl, ret))){ - case SSL_ERROR_WANT_READ: - case SSL_ERROR_WANT_WRITE: - case SSL_ERROR_NONE: - break; - default: - { - unsigned long sslErr = ERR_get_error(); - const uint8_t* pData = (const uint8_t*)data; - TSK_DEBUG_ERROR("%lu = SSL_read(rbio, %u) failed [%s]", sslErr, size, ERR_error_string(ret, tsk_null)); - // try to understand what's going on - // rfc6347 - 4.1. Record Layer - // rfc6347 - 4.2.2. Handshake Message Format - // rfc6347 - 4.3.2. Handshake Protocol - if(size > 14 && pData[0] == 0x16){ // content-type=='Handshake' - if(pData[13] == 0x01 && (socket->setup == tnet_dtls_setup_active || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='client Hello' - TSK_DEBUG_INFO("DTLS engine was in client mode but we are receiving 'Client Hello' messages. This is a bug in the remote peer: Re-negotiating!"); - tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_passive); - break; - } - else if(pData[13] == 0x02 && (socket->setup == tnet_dtls_setup_passive || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='server Hello' - TSK_DEBUG_INFO("DTLS engine was in server mode but we are receiving 'Server Hello' messages. This is a bug in the remote peer: Re-negotiating!"); - tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_active); - break; - } - } - //return -1; - break; - } - } - }*/ - - ret = _tnet_dtls_socket_do_handshake(socket); + tnet_dtls_socket_t *socket = handle; + int ret = 0; + + if (!socket || !data || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(socket); + + TSK_DEBUG_INFO("Receive DTLS data: %lu", (unsigned long)size); + + // BIO_reset(socket->rbio); + // BIO_reset(socket->wbio); + + if (!socket->rbio || !socket->wbio) { + TSK_DEBUG_ERROR("BIO not initialized yet"); + ret = -2; + goto bail; + } + + if ((ret = _tnet_dtls_socket_do_handshake(socket))) { + goto bail; + } + + if ((ret = BIO_write(socket->rbio, data, (int)size)) != size) { + ret = SSL_get_error(socket->ssl, ret); + TSK_DEBUG_ERROR("BIO_write(rbio, %lu) failed [%s]", (unsigned long)size, ERR_error_string(ERR_get_error(), tsk_null)); + ret = -1; + goto bail; + } + + /*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){ + switch((ret = SSL_get_error(socket->ssl, ret))){ + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_NONE: + break; + default: + { + unsigned long sslErr = ERR_get_error(); + const uint8_t* pData = (const uint8_t*)data; + TSK_DEBUG_ERROR("%lu = SSL_read(rbio, %u) failed [%s]", sslErr, size, ERR_error_string(ret, tsk_null)); + // try to understand what's going on + // rfc6347 - 4.1. Record Layer + // rfc6347 - 4.2.2. Handshake Message Format + // rfc6347 - 4.3.2. Handshake Protocol + if(size > 14 && pData[0] == 0x16){ // content-type=='Handshake' + if(pData[13] == 0x01 && (socket->setup == tnet_dtls_setup_active || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='client Hello' + TSK_DEBUG_INFO("DTLS engine was in client mode but we are receiving 'Client Hello' messages. This is a bug in the remote peer: Re-negotiating!"); + tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_passive); + break; + } + else if(pData[13] == 0x02 && (socket->setup == tnet_dtls_setup_passive || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='server Hello' + TSK_DEBUG_INFO("DTLS engine was in server mode but we are receiving 'Server Hello' messages. This is a bug in the remote peer: Re-negotiating!"); + tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_active); + break; + } + } + //return -1; + break; + } + } + }*/ + + ret = _tnet_dtls_socket_do_handshake(socket); bail: - tsk_safeobj_unlock(socket); - return ret; + tsk_safeobj_unlock(socket); + return ret; #endif } @@ -760,47 +765,46 @@ bail: // static tsk_object_t* tnet_dtls_socket_ctor(tsk_object_t * self, va_list * app) { - tnet_dtls_socket_t *socket = self; - if (socket){ - tsk_safeobj_init(socket); - } - return self; + tnet_dtls_socket_t *socket = self; + if (socket) { + tsk_safeobj_init(socket); + } + return self; } static tsk_object_t* tnet_dtls_socket_dtor(tsk_object_t * self) { - tnet_dtls_socket_t *socket = self; - if (socket){ + tnet_dtls_socket_t *socket = self; + if (socket) { #if HAVE_OPENSSL - if (socket->rbio) { - //BIO_free(socket->rbio); - socket->rbio = tsk_null; - } - if (socket->wbio) { - //BIO_free(socket->wbio); - socket->wbio = tsk_null; - } - if (socket->ssl) { - SSL_shutdown(socket->ssl); - // https://www.openssl.org/docs/crypto/BIO_s_bio.html - // implicitly frees internal_bio - SSL_free(socket->ssl); - } + if (socket->rbio) { + //BIO_free(socket->rbio); + socket->rbio = tsk_null; + } + if (socket->wbio) { + //BIO_free(socket->wbio); + socket->wbio = tsk_null; + } + if (socket->ssl) { + SSL_shutdown(socket->ssl); + // https://www.openssl.org/docs/crypto/BIO_s_bio.html + // implicitly frees internal_bio + SSL_free(socket->ssl); + } #endif - TSK_FREE(socket->handshake_data.ptr); - TSK_OBJECT_SAFE_FREE(socket->wrapped_sock); - tsk_safeobj_deinit(socket); + TSK_FREE(socket->handshake_data.ptr); + TSK_OBJECT_SAFE_FREE(socket->wrapped_sock); + tsk_safeobj_deinit(socket); - TSK_DEBUG_INFO("*** tnet_dtls_socket_t destroyed ***"); - } - return self; + TSK_DEBUG_INFO("*** tnet_dtls_socket_t destroyed ***"); + } + return self; } -static const tsk_object_def_t tnet_dtls_socket_def_s = -{ - sizeof(tnet_dtls_socket_t), - tnet_dtls_socket_ctor, - tnet_dtls_socket_dtor, - tsk_null, +static const tsk_object_def_t tnet_dtls_socket_def_s = { + sizeof(tnet_dtls_socket_t), + tnet_dtls_socket_ctor, + tnet_dtls_socket_dtor, + tsk_null, }; const tsk_object_def_t *tnet_dtls_socket_def_t = &tnet_dtls_socket_def_s; diff --git a/tinyNET/src/tls/tnet_dtls.h b/tinyNET/src/tls/tnet_dtls.h index e5b518c..19bb074 100755 --- a/tinyNET/src/tls/tnet_dtls.h +++ b/tinyNET/src/tls/tnet_dtls.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -34,15 +34,14 @@ struct tnet_socket_s; typedef void tnet_dtls_socket_handle_t; -typedef enum tnet_dtls_socket_event_type_e -{ - tnet_dtls_socket_event_type_handshake_started, - tnet_dtls_socket_event_type_handshake_succeed, - tnet_dtls_socket_event_type_handshake_failed, - tnet_dtls_socket_event_type_fingerprint_mismatch, - tnet_dtls_socket_event_type_error, - tnet_dtls_socket_event_type_dtls_srtp_profile_selected, /* SRTP_AES128_CM_SHA1_80 | SRTP_AES128_CM_SHA1_32 */ - tnet_dtls_socket_event_type_dtls_srtp_data, /* key||salt */ +typedef enum tnet_dtls_socket_event_type_e { + tnet_dtls_socket_event_type_handshake_started, + tnet_dtls_socket_event_type_handshake_succeed, + tnet_dtls_socket_event_type_handshake_failed, + tnet_dtls_socket_event_type_fingerprint_mismatch, + tnet_dtls_socket_event_type_error, + tnet_dtls_socket_event_type_dtls_srtp_profile_selected, /* SRTP_AES128_CM_SHA1_80 | SRTP_AES128_CM_SHA1_32 */ + tnet_dtls_socket_event_type_dtls_srtp_data, /* key||salt */ } tnet_dtls_socket_event_type_t; diff --git a/tinyNET/src/tls/tnet_tls.c b/tinyNET/src/tls/tnet_tls.c index 0ae520c..1904fa3 100755 --- a/tinyNET/src/tls/tnet_tls.c +++ b/tinyNET/src/tls/tnet_tls.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2010-2012 Mamadou Diop. * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -34,270 +34,266 @@ #define TNET_TLS_TIMEOUT 2000 #define TNET_TLS_RETRY_COUNT 10 -typedef struct tnet_tls_socket_s -{ - TSK_DECLARE_OBJECT; - - tnet_fd_t fd; /* not owner: do not try to close */ +typedef struct tnet_tls_socket_s { + TSK_DECLARE_OBJECT; + + tnet_fd_t fd; /* not owner: do not try to close */ #if HAVE_OPENSSL - SSL *ssl; + SSL *ssl; #endif - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } tnet_tls_socket_t; tsk_bool_t tnet_tls_is_supported() { #if HAVE_OPENSSL - return tsk_true; + return tsk_true; #else - return tsk_false; + return tsk_false; #endif } tnet_tls_socket_handle_t* tnet_tls_socket_create(tnet_fd_t fd, struct ssl_ctx_st* ssl_ctx) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("OpenSSL not enabled"); - return tsk_null; + TSK_DEBUG_ERROR("OpenSSL not enabled"); + return tsk_null; #else - tnet_tls_socket_t* socket; - if(fd <= 0 || !ssl_ctx){ - TSK_DEBUG_ERROR("Invalid parameter"); - return tsk_null; - } - if((socket = tsk_object_new(tnet_tls_socket_def_t))){ - socket->fd = fd; - if(!(socket->ssl = SSL_new(ssl_ctx))){ - TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - if(SSL_set_fd(socket->ssl, socket->fd) != 1){ - TSK_DEBUG_ERROR("SSL_set_fd(%d) failed [%s]", socket->fd, ERR_error_string(ERR_get_error(), tsk_null)); - TSK_OBJECT_SAFE_FREE(socket); - return tsk_null; - } - } - return socket; + tnet_tls_socket_t* socket; + if(fd <= 0 || !ssl_ctx) { + TSK_DEBUG_ERROR("Invalid parameter"); + return tsk_null; + } + if((socket = tsk_object_new(tnet_tls_socket_def_t))) { + socket->fd = fd; + if(!(socket->ssl = SSL_new(ssl_ctx))) { + TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + if(SSL_set_fd(socket->ssl, socket->fd) != 1) { + TSK_DEBUG_ERROR("SSL_set_fd(%d) failed [%s]", socket->fd, ERR_error_string(ERR_get_error(), tsk_null)); + TSK_OBJECT_SAFE_FREE(socket); + return tsk_null; + } + } + return socket; #endif } int tnet_tls_socket_connect(tnet_tls_socket_handle_t* self) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if((ret = SSL_connect(socket->ssl)) != 1){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_SYSCALL){ - ret = 0; /* up to the caller to check that the socket is writable and valid */ - } - else{ - TSK_DEBUG_ERROR("SSL_connect failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - } - else{ - ret = 0; - } - - return ret; + int ret; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if((ret = SSL_connect(socket->ssl)) != 1) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_SYSCALL) { + ret = 0; /* up to the caller to check that the socket is writable and valid */ + } + else { + TSK_DEBUG_ERROR("SSL_connect failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + } + else { + ret = 0; + } + + return ret; #endif } int tnet_tls_socket_accept(tnet_tls_socket_handle_t* self) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if((ret = SSL_accept(socket->ssl)) != 1){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_READ){ - int retval; - fd_set rfds; - while (1) - { - FD_ZERO(&rfds); - FD_SET(socket->fd, &rfds); - retval = select(socket->fd + 1, &rfds, NULL, NULL, NULL); - if (retval == -1){ - TNET_PRINT_LAST_ERROR("select() failed"); - } - else if (retval) - { - if (FD_ISSET(socket->fd, &rfds)){ - ret = SSL_accept(socket->ssl); - ret = SSL_get_error(socket->ssl, ret); - if (ret == SSL_ERROR_WANT_READ){ - continue; - } - else{ - if(ret == SSL_ERROR_NONE){ - return 0; - } - break; - } - } - } - else - { - break; - } - } - } - TSK_DEBUG_ERROR("SSL_accept() failed with error code [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - return -3; - } - - return 0; + int ret = -1; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if((ret = SSL_accept(socket->ssl)) != 1) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_READ) { + int retval; + fd_set rfds; + while (1) { + FD_ZERO(&rfds); + FD_SET(socket->fd, &rfds); + retval = select(socket->fd + 1, &rfds, NULL, NULL, NULL); + if (retval == -1) { + TNET_PRINT_LAST_ERROR("select() failed"); + } + else if (retval) { + if (FD_ISSET(socket->fd, &rfds)) { + ret = SSL_accept(socket->ssl); + ret = SSL_get_error(socket->ssl, ret); + if (ret == SSL_ERROR_WANT_READ) { + continue; + } + else { + if(ret == SSL_ERROR_NONE) { + return 0; + } + break; + } + } + } + else { + break; + } + } + } + TSK_DEBUG_ERROR("SSL_accept() failed with error code [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + return -3; + } + + return 0; #endif } int tnet_tls_socket_write(tnet_tls_socket_handle_t* self, const void* data, tsk_size_t size) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tnet_tls_socket_t* socket = self; - tsk_bool_t try_again = tsk_true, want_read, want_write; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - /* Write */ - tsk_safeobj_lock(socket); - while(((ret = SSL_write(socket->ssl, data, (int)size)) <= 0) && try_again){ - ret = SSL_get_error(socket->ssl, ret); - want_read = (ret == SSL_ERROR_WANT_READ); - want_write = (ret == SSL_ERROR_WANT_WRITE); - - if(want_write || want_read){ - if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, want_write))){ - continue; - } - } - else{ - TSK_DEBUG_ERROR("SSL_write failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - ret = -3; - try_again = tsk_false; - } - } - tsk_safeobj_unlock(socket); - - ret = (ret > 0) ? 0 : -3; - return ret; + int ret = -1; + tnet_tls_socket_t* socket = self; + tsk_bool_t try_again = tsk_true, want_read, want_write; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + /* Write */ + tsk_safeobj_lock(socket); + while(((ret = SSL_write(socket->ssl, data, (int)size)) <= 0) && try_again) { + ret = SSL_get_error(socket->ssl, ret); + want_read = (ret == SSL_ERROR_WANT_READ); + want_write = (ret == SSL_ERROR_WANT_WRITE); + + if(want_write || want_read) { + if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, want_write))) { + continue; + } + } + else { + TSK_DEBUG_ERROR("SSL_write failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + ret = -3; + try_again = tsk_false; + } + } + tsk_safeobj_unlock(socket); + + ret = (ret > 0) ? 0 : -3; + return ret; #endif } int tnet_tls_socket_recv(tnet_tls_socket_handle_t* self, void** data, tsk_size_t *size, tsk_bool_t *isEncrypted) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("You MUST enable OpenSSL"); - return -200; + TSK_DEBUG_ERROR("You MUST enable OpenSSL"); + return -200; #else - int ret = -1; - tsk_size_t read = 0; - tsk_size_t to_read = *size; - int rcount = TNET_TLS_RETRY_COUNT; - tnet_tls_socket_t* socket = self; - - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(socket); - - *isEncrypted = SSL_is_init_finished(socket->ssl) ? tsk_false : tsk_true; - - /* SSL handshake has completed? */ - if(*isEncrypted){ - char* buffer[1024]; - if((ret = SSL_read(socket->ssl, buffer, sizeof(buffer))) <= 0){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ){ - ret = 0; - } - else{ - TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - *size = 0; - } - else{ - *size = ret; - ret = 0; - } - - goto bail; - } - - /* Read Application data */ -ssl_read: - if(rcount && ((ret = SSL_read(socket->ssl, (((uint8_t*)*data)+read), (int)to_read)) <= 0)){ - ret = SSL_get_error(socket->ssl, ret); - if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ){ - if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, (ret == SSL_ERROR_WANT_WRITE)))){ - rcount--; - goto ssl_read; - } - } - else if(SSL_ERROR_ZERO_RETURN){ /* connection closed: do nothing, the transport layer will be alerted. */ - *size = 0; - ret = 0; - TSK_DEBUG_INFO("TLS connection closed."); - } - else{ - TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); - } - } - else if(ret >=0){ - read += (tsk_size_t)ret; - - if((ret = SSL_pending(socket->ssl)) > 0){ - void *ptr; - to_read = ret; - - if((ptr = tsk_realloc(*data, (read + to_read)))){ - *data = ptr; - goto ssl_read; - } - } - } + int ret = -1; + tsk_size_t read = 0; + tsk_size_t to_read = *size; + int rcount = TNET_TLS_RETRY_COUNT; + tnet_tls_socket_t* socket = self; + + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + tsk_safeobj_lock(socket); + + *isEncrypted = SSL_is_init_finished(socket->ssl) ? tsk_false : tsk_true; + + /* SSL handshake has completed? */ + if(*isEncrypted) { + char* buffer[1024]; + if((ret = SSL_read(socket->ssl, buffer, sizeof(buffer))) <= 0) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) { + ret = 0; + } + else { + TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + *size = 0; + } + else { + *size = ret; + ret = 0; + } + + goto bail; + } + + /* Read Application data */ +ssl_read: + if(rcount && ((ret = SSL_read(socket->ssl, (((uint8_t*)*data)+read), (int)to_read)) <= 0)) { + ret = SSL_get_error(socket->ssl, ret); + if(ret == SSL_ERROR_WANT_WRITE || ret == SSL_ERROR_WANT_READ) { + if(!(ret = tnet_sockfd_waitUntil(socket->fd, TNET_TLS_TIMEOUT, (ret == SSL_ERROR_WANT_WRITE)))) { + rcount--; + goto ssl_read; + } + } + else if(SSL_ERROR_ZERO_RETURN) { /* connection closed: do nothing, the transport layer will be alerted. */ + *size = 0; + ret = 0; + TSK_DEBUG_INFO("TLS connection closed."); + } + else { + TSK_DEBUG_ERROR("SSL_read failed [%d, %s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); + } + } + else if(ret >=0) { + read += (tsk_size_t)ret; + + if((ret = SSL_pending(socket->ssl)) > 0) { + void *ptr; + to_read = ret; + + if((ptr = tsk_realloc(*data, (read + to_read)))) { + *data = ptr; + goto ssl_read; + } + } + } bail: - tsk_safeobj_unlock(socket); - - if(read){ - *size = read; - return 0; - } - else{ - return ret; - } + tsk_safeobj_unlock(socket); + + if(read) { + *size = read; + return 0; + } + else { + return ret; + } #endif } @@ -309,34 +305,33 @@ bail: // static tsk_object_t* tnet_tls_socket_ctor(tsk_object_t * self, va_list * app) { - tnet_tls_socket_t *socket = self; - if(socket){ - tsk_safeobj_init(socket); - } - return self; + tnet_tls_socket_t *socket = self; + if(socket) { + tsk_safeobj_init(socket); + } + return self; } static tsk_object_t* tnet_tls_socket_dtor(tsk_object_t * self) -{ - tnet_tls_socket_t *socket = self; - if(socket){ +{ + tnet_tls_socket_t *socket = self; + if(socket) { #if HAVE_OPENSSL - if(socket->ssl){ - SSL_shutdown(socket->ssl); - SSL_free(socket->ssl); - } + if(socket->ssl) { + SSL_shutdown(socket->ssl); + SSL_free(socket->ssl); + } #endif - tsk_safeobj_deinit(socket); - } - return self; + tsk_safeobj_deinit(socket); + } + return self; } -static const tsk_object_def_t tnet_tls_socket_def_s = -{ - sizeof(tnet_tls_socket_t), - tnet_tls_socket_ctor, - tnet_tls_socket_dtor, - tsk_null, +static const tsk_object_def_t tnet_tls_socket_def_s = { + sizeof(tnet_tls_socket_t), + tnet_tls_socket_ctor, + tnet_tls_socket_dtor, + tsk_null, }; const tsk_object_def_t *tnet_tls_socket_def_t = &tnet_tls_socket_def_s; diff --git a/tinyNET/src/tls/tnet_tls.h b/tinyNET/src/tls/tnet_tls.h index 5e00ec8..d7bacbc 100755 --- a/tinyNET/src/tls/tnet_tls.h +++ b/tinyNET/src/tls/tnet_tls.h @@ -1,19 +1,19 @@ /* * Copyright (C) 2010-2012 Mamadou Diop. * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * diff --git a/tinyNET/src/tnet.c b/tinyNET/src/tnet.c index 25d763b..0bd15e0 100755 --- a/tinyNET/src/tnet.c +++ b/tinyNET/src/tnet.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2010-2015 Mamadou DIOP. -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -45,7 +45,7 @@ * * ====== * -* - @ref tnet_socket_group +* - @ref tnet_socket_group * - @ref tnet_utils_group * - @ref tnet_dhcp_group * - @ref tnet_dhcp6_group @@ -70,32 +70,32 @@ tsk_bool_t tnet_isBigEndian = tsk_false; * You MUST call @ref tnet_cleanup to cleanup the network stack if you no longer need to use networking function. * * @sa @ref tnet_cleanup. - * @return 0 if succeed and error code otherwise. + * @return 0 if succeed and error code otherwise. **/ int tnet_startup() { - int err = 0; - short word = 0x4321; + int err = 0; + short word = 0x4321; + + if (__tnet_started) { + goto bail; + } - if (__tnet_started) { - goto bail; - } - if ((err = tnet_proxy_node_plugin_register(tnet_proxy_node_socks_plugin_def_t)) != 0) { goto bail; } - // rand() - srand((unsigned int) tsk_time_epoch()); + // rand() + srand((unsigned int) tsk_time_epoch()); - // endianness - tnet_isBigEndian = ((*(int8_t *)&word) != 0x21); + // endianness + tnet_isBigEndian = ((*(int8_t *)&word) != 0x21); #if TNET_UNDER_WINDOWS - if (tnet_isBigEndian){ - TSK_DEBUG_ERROR("Big endian on Windows machine. Is it right?"); - } + if (tnet_isBigEndian) { + TSK_DEBUG_ERROR("Big endian on Windows machine. Is it right?"); + } #endif - // Print messages regardless the debug level + // Print messages regardless the debug level #if TNET_UNDER_WINDOWS_CE && (BUILD_TYPE_GE && SIN_CITY) # define PRINT_INFO TSK_DEBUG_INFO # define PRINT_ERROR TSK_DEBUG_ERROR @@ -105,45 +105,45 @@ int tnet_startup() #endif #if TNET_UNDER_WINDOWS - { - WORD wVersionRequested; - WSADATA wsaData; - - wVersionRequested = MAKEWORD(2, 2); - - err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) { - PRINT_ERROR("WSAStartup failed with error: %d", err); - return -1; - } - - if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { - PRINT_ERROR("Could not find a usable version of Winsock.dll"); - tnet_cleanup(); - return -2; - } - else { - PRINT_INFO("The Winsock 2.2 dll was found okay"); - } - } + { + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + PRINT_ERROR("WSAStartup failed with error: %d", err); + return -1; + } + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + PRINT_ERROR("Could not find a usable version of Winsock.dll"); + tnet_cleanup(); + return -2; + } + else { + PRINT_INFO("The Winsock 2.2 dll was found okay"); + } + } #endif /* TNET_UNDER_WINDOWS */ #if HAVE_OPENSSL - PRINT_INFO("SSL is enabled :)"); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - SSL_load_error_strings(); + PRINT_INFO("SSL is enabled :)"); + SSL_library_init(); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); - PRINT_INFO("DTLS supported: %s", tnet_dtls_is_supported() ? "yes" : "no"); - PRINT_INFO("DTLS-SRTP supported: %s", tnet_dtls_is_srtp_supported() ? "yes" : "no"); + PRINT_INFO("DTLS supported: %s", tnet_dtls_is_supported() ? "yes" : "no"); + PRINT_INFO("DTLS-SRTP supported: %s", tnet_dtls_is_srtp_supported() ? "yes" : "no"); #else - PRINT_ERROR("SSL is disabled :("); + PRINT_ERROR("SSL is disabled :("); #endif - - __tnet_started = tsk_true; + + __tnet_started = tsk_true; bail: - return err; + return err; } @@ -155,20 +155,20 @@ bail: **/ int tnet_cleanup() { - if (!__tnet_started){ - goto bail; - } - + if (!__tnet_started) { + goto bail; + } + tnet_proxy_node_plugin_unregister(tnet_proxy_node_socks_plugin_def_t); #if TNET_UNDER_WINDOWS - __tnet_started = tsk_false; - return WSACleanup(); + __tnet_started = tsk_false; + return WSACleanup(); #else - __tnet_started = tsk_false; + __tnet_started = tsk_false; #endif bail: - return 0; + return 0; } diff --git a/tinyNET/src/tnet.h b/tinyNET/src/tnet.h index 92b8e53..94385cc 100755 --- a/tinyNET/src/tnet.h +++ b/tinyNET/src/tnet.h @@ -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. * diff --git a/tinyNET/src/tnet_auth.c b/tinyNET/src/tnet_auth.c index 941db1e..e8cbcfb 100755 --- a/tinyNET/src/tnet_auth.c +++ b/tinyNET/src/tnet_auth.c @@ -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. * diff --git a/tinyNET/src/tnet_auth.h b/tinyNET/src/tnet_auth.h index 1f9642e..36880fd 100755 --- a/tinyNET/src/tnet_auth.h +++ b/tinyNET/src/tnet_auth.h @@ -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. * diff --git a/tinyNET/src/tnet_endianness.c b/tinyNET/src/tnet_endianness.c index 62f1708..f204f0e 100755 --- a/tinyNET/src/tnet_endianness.c +++ b/tinyNET/src/tnet_endianness.c @@ -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. * @@ -39,20 +39,20 @@ extern tsk_bool_t tnet_isBigEndian; */ unsigned short tnet_htons(unsigned short x) { - if(tnet_is_BE()){ - return x; - } - else{ - return ((((uint16_t)(x) & 0xff00) >> 8) | - (((uint16_t)(x) & 0x00ff) << 8)); - } + if(tnet_is_BE()) { + return x; + } + else { + return ((((uint16_t)(x) & 0xff00) >> 8) | + (((uint16_t)(x) & 0x00ff) << 8)); + } } /* Memory alignment hack */ unsigned short tnet_htons_2(const void* px) { - unsigned short y = TSK_TO_UINT16((const uint8_t*)px); - return tnet_htons(y); + unsigned short y = TSK_TO_UINT16((const uint8_t*)px); + return tnet_htons(y); } /** Converts a 32-bit value from host to TCP/IP network byte order (big-endian). @@ -61,22 +61,22 @@ unsigned short tnet_htons_2(const void* px) */ unsigned long tnet_htonl(unsigned long x) { - if(tnet_is_BE()){ - return x; - } - else{ - return ((((uint32_t)(x) & 0xff000000) >> 24) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x000000ff) << 24)); - } + if(tnet_is_BE()) { + return x; + } + else { + return ((((uint32_t)(x) & 0xff000000) >> 24) | \ + (((uint32_t)(x) & 0x00ff0000) >> 8) | \ + (((uint32_t)(x) & 0x0000ff00) << 8) | \ + (((uint32_t)(x) & 0x000000ff) << 24)); + } } /* Memory alignment hack */ unsigned long tnet_htonl_2(const void* px) { - unsigned long y = TSK_TO_UINT32((const uint8_t*)px); - return tnet_htonl(y); + unsigned long y = TSK_TO_UINT32((const uint8_t*)px); + return tnet_htonl(y); } /** Indicates whether we are on a Big Endian host or not.<br> @@ -84,15 +84,16 @@ unsigned long tnet_htonl_2(const void* px) * @ref tnet_startup(). * @retval @a tsk_true if the program is runnin on a Big Endian host and @a tsk_false otherwise. */ -tsk_bool_t tnet_is_BE(){ - /* If LITTLE_ENDIAN or BIG_ENDIAN macros have been defined in config.h ==> use them - * otherwise ==> dyn retrieve the endianness - */ +tsk_bool_t tnet_is_BE() +{ + /* If LITTLE_ENDIAN or BIG_ENDIAN macros have been defined in config.h ==> use them + * otherwise ==> dyn retrieve the endianness + */ #if LITTLE_ENDIAN - return tsk_false; + return tsk_false; #elif BIG_ENDIAN - return tsk_true; + return tsk_true; #else - return tnet_isBigEndian; + return tnet_isBigEndian; #endif } diff --git a/tinyNET/src/tnet_endianness.h b/tinyNET/src/tnet_endianness.h index 80a1232..4e28e04 100755 --- a/tinyNET/src/tnet_endianness.h +++ b/tinyNET/src/tnet_endianness.h @@ -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. * diff --git a/tinyNET/src/tnet_hardwares.h b/tinyNET/src/tnet_hardwares.h index 7d015b5..641e85d 100755 --- a/tinyNET/src/tnet_hardwares.h +++ b/tinyNET/src/tnet_hardwares.h @@ -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. * @@ -38,24 +38,23 @@ TNET_BEGIN_DECLS * List of Hardware types as assigned by the IANA. * See RFC 1340, 826 and... for more information. */ -typedef enum tnet_hardware_type_e -{ - tnet_htype_Ethernet_10Mb = 1, /**< Ethernet (10Mb) */ - tnet_htype_Ethernet_3Mb = 2, /**< Experimental Ethernet (3Mb) */ - tnet_htype_AX_25 = 3, /**< Amateur Radio AX.25 */ - tnet_htype_Token_Ring = 4, /**< Proteon ProNET Token Ring */ - tnet_htype_Chaos = 5, /**< Chaos */ - tnet_htype_IEEE_802_Networks = 6, /**< IEEE 802 Networks */ - tnet_htype_ARCNET = 7, /**< ARCNET */ - tnet_htype_Hyperchannel = 8, /**< Hyperchannel */ - tnet_htype_Lanstar = 9, /**< Lanstar */ - tnet_htype_Autonet_Short_Address = 10, /**< Autonet Short Address */ - tnet_htype_ALocalTalk = 11, /**< LocalTalk */ - tnet_htype_LocalNet= 12, /**< LocalNet (IBM PCNet or SYTEK LocalNET) */ - tnet_htype_Ultra_link = 13, /**< Ultra link */ - tnet_htype_SMDS = 14, /**< SMDS */ - tnet_htype_Frame_Relay = 15, /**< Frame Relay */ - tnet_htype_ATM = 16, /**< Asynchronous Transmission Mode (ATM) */ +typedef enum tnet_hardware_type_e { + tnet_htype_Ethernet_10Mb = 1, /**< Ethernet (10Mb) */ + tnet_htype_Ethernet_3Mb = 2, /**< Experimental Ethernet (3Mb) */ + tnet_htype_AX_25 = 3, /**< Amateur Radio AX.25 */ + tnet_htype_Token_Ring = 4, /**< Proteon ProNET Token Ring */ + tnet_htype_Chaos = 5, /**< Chaos */ + tnet_htype_IEEE_802_Networks = 6, /**< IEEE 802 Networks */ + tnet_htype_ARCNET = 7, /**< ARCNET */ + tnet_htype_Hyperchannel = 8, /**< Hyperchannel */ + tnet_htype_Lanstar = 9, /**< Lanstar */ + tnet_htype_Autonet_Short_Address = 10, /**< Autonet Short Address */ + tnet_htype_ALocalTalk = 11, /**< LocalTalk */ + tnet_htype_LocalNet= 12, /**< LocalNet (IBM PCNet or SYTEK LocalNET) */ + tnet_htype_Ultra_link = 13, /**< Ultra link */ + tnet_htype_SMDS = 14, /**< SMDS */ + tnet_htype_Frame_Relay = 15, /**< Frame Relay */ + tnet_htype_ATM = 16, /**< Asynchronous Transmission Mode (ATM) */ } tnet_hardware_type_t; diff --git a/tinyNET/src/tnet_nat.c b/tinyNET/src/tnet_nat.c index 53a009a..7e536c1 100755 --- a/tinyNET/src/tnet_nat.c +++ b/tinyNET/src/tnet_nat.c @@ -7,12 +7,12 @@ * 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. * @@ -40,24 +40,23 @@ /**@defgroup tnet_nat_group NAT Traversal API (STUN, TURN and ICE). */ -typedef struct tnet_nat_ctx_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_nat_ctx_s { + TSK_DECLARE_OBJECT; - tnet_socket_type_t socket_type; + tnet_socket_type_t socket_type; - char* username; /**< The username to use to authenticate against the TURN/STUN server. */ - char* password; /**< The password to use to authenticate against the TURN/STUN server. */ + char* username; /**< The username to use to authenticate against the TURN/STUN server. */ + char* password; /**< The password to use to authenticate against the TURN/STUN server. */ - char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */ - tnet_port_t server_port; /**< TURN/STUN server port. */ + char* server_address; /**< TURN/STUN server address (could be FQDN or IP) */ + tnet_port_t server_port; /**< TURN/STUN server port. */ - uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */ - uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */ + uint16_t RTO; /**< Estimate of the round-trip time (RTT) in millisecond. */ + uint16_t Rc; /**< Number of retransmissions for UDP in millisecond. */ - unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */ - - tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */ + unsigned use_dnsquery:1; /**< Indicates whether to use DNS SRV query to find the stun/turn ip address. */ + + tnet_stun_bindings_L_t *stun_bindings; /**< List of all STUN2 bindings associated to this context. */ } tnet_nat_ctx_t; @@ -67,88 +66,88 @@ tnet_nat_ctx_t; */ struct tnet_nat_ctx_s* tnet_nat_context_create(tnet_socket_type_t socket_type, const char* pc_username, const char* pc_password) { - extern const tsk_object_def_t *tnet_nat_context_def_t; - struct tnet_nat_ctx_s* p_ctx; - - if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) { - TSK_OBJECT_SAFE_FREE(p_ctx); - TSK_DEBUG_ERROR("Failed to create NAT context"); - return tsk_null; - } - - p_ctx->socket_type = socket_type; - p_ctx->username = tsk_strdup(pc_username); - p_ctx->password = tsk_strdup(pc_password); - p_ctx->server_port = kStunPortDefaultTcpUdp; - /* 7.2.1. Sending over UDP - In fixed-line access links, a value of 500 ms is RECOMMENDED. - */ - p_ctx->RTO = kStunRTO; - /* 7.2.1. Sending over UDP - Rc SHOULD be configurable and SHOULD have a default of 7. - */ - p_ctx->Rc = kStunRC; - - return p_ctx; + extern const tsk_object_def_t *tnet_nat_context_def_t; + struct tnet_nat_ctx_s* p_ctx; + + if (!(p_ctx = tsk_object_new(tnet_nat_context_def_t)) || !(p_ctx->stun_bindings = tsk_list_create())) { + TSK_OBJECT_SAFE_FREE(p_ctx); + TSK_DEBUG_ERROR("Failed to create NAT context"); + return tsk_null; + } + + p_ctx->socket_type = socket_type; + p_ctx->username = tsk_strdup(pc_username); + p_ctx->password = tsk_strdup(pc_password); + p_ctx->server_port = kStunPortDefaultTcpUdp; + /* 7.2.1. Sending over UDP + In fixed-line access links, a value of 500 ms is RECOMMENDED. + */ + p_ctx->RTO = kStunRTO; + /* 7.2.1. Sending over UDP + Rc SHOULD be configurable and SHOULD have a default of 7. + */ + p_ctx->Rc = kStunRC; + + return p_ctx; } -/** Predicate function to find stun binding by id. +/** Predicate function to find stun binding by id. * - * @param [in,out] item The current list item. - * @param [in,out] id A pointer to the binding identifier. + * @param [in,out] item The current list item. + * @param [in,out] id A pointer to the binding identifier. * - * @return Zero if current list item hold a binding with the same id and -1 otherwise. + * @return Zero if current list item hold a binding with the same id and -1 otherwise. **/ int __pred_find_stun_binding(const tsk_list_item_t* item, const void* id) { - if(item) { - tnet_stun_binding_t *p_bind = item->data; - if (p_bind) { - tnet_stun_binding_id_t binding_id = *((tnet_stun_binding_id_t*)id); - return (p_bind->id == binding_id) ? 0 : -1; - } - } - return -1; + if(item) { + tnet_stun_binding_t *p_bind = item->data; + if (p_bind) { + tnet_stun_binding_id_t binding_id = *((tnet_stun_binding_id_t*)id); + return (p_bind->id == binding_id) ? 0 : -1; + } + } + return -1; } /**@ingroup tnet_nat_group * * Sets the address of the STUN/TURN server. * - * @param [in,out] p_self The NAT context. - * @param [in,out] pc_server_address The address of server. + * @param [in,out] p_self The NAT context. + * @param [in,out] pc_server_address The address of server. * - * @return Zero if succeed and non zero error code otherwise. + * @return Zero if succeed and non zero error code otherwise. **/ int tnet_nat_set_server_address(struct tnet_nat_ctx_s* p_self, const char* pc_server_address) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_strupdate(&(p_self->server_address), pc_server_address); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_strupdate(&(p_self->server_address), pc_server_address); + return 0; } /**@ingroup tnet_nat_group * * Sets the address and port of the STUN/TURN server. * - * @param [in,out] p_self The NAT context. - * @param [in,out] pc_server_address The address of server. - * @param u_server_port The server port. + * @param [in,out] p_self The NAT context. + * @param [in,out] pc_server_address The address of server. + * @param u_server_port The server port. * - * @return Zero if succeed and non zero error code otherwise. + * @return Zero if succeed and non zero error code otherwise. **/ int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_address, tnet_port_t u_server_port) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_strupdate(&(p_self->server_address), pc_server_address); - p_self->server_port = u_server_port; - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_strupdate(&(p_self->server_address), pc_server_address); + p_self->server_port = u_server_port; + return 0; } /**@ingroup tnet_nat_group @@ -156,7 +155,7 @@ int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_add * Creates and sends a STUN2 binding request to the STUN/TURN server in order to get the server reflexive * address associated to this file descriptor (or socket). The caller should call @ref tnet_nat_stun_unbind to destroy the binding. * - * @param [in,out] p_self The NAT context. + * @param [in,out] p_self The NAT context. * @param localFD The local file descriptor (or socket) for which to get the reflexive server address. * * @return A valid binding id if succeed and @ref kStunBindingInvalidId otherwise. If the returned id is valid then @@ -166,13 +165,13 @@ int tnet_nat_set_server(struct tnet_nat_ctx_s* p_self, const char* pc_server_add **/ tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, const tnet_fd_t localFD) { - tnet_stun_binding_id_t id = kStunBindingInvalidId; - tnet_stun_binding_t *p_binding = tsk_null; - int ret; - if (!p_self || localFD == TNET_INVALID_FD) { - TSK_DEBUG_ERROR("Invalid parameter"); - goto bail; - } + tnet_stun_binding_id_t id = kStunBindingInvalidId; + tnet_stun_binding_t *p_binding = tsk_null; + int ret; + if (!p_self || localFD == TNET_INVALID_FD) { + TSK_DEBUG_ERROR("Invalid parameter"); + goto bail; + } if ((ret = tnet_stun_binding_create(localFD, p_self->socket_type, p_self->server_address, p_self->server_port, p_self->username, p_self->password, &p_binding))) { goto bail; } @@ -183,7 +182,7 @@ tnet_stun_binding_id_t tnet_nat_stun_bind(const struct tnet_nat_ctx_s* p_self, c tsk_list_push_back_data(p_self->stun_bindings, (void**)&p_binding); bail: - TSK_OBJECT_SAFE_FREE(p_binding); + TSK_OBJECT_SAFE_FREE(p_binding); return id; } @@ -198,19 +197,19 @@ bail: **/ int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_stun_binding_s *p_binding) { - int ret = -1; + int ret = -1; tnet_stun_pkt_resp_t *p_pkt_resp = tsk_null; tnet_stun_pkt_req_t *p_pkt_req = tsk_null; - if (!pc_self || !p_binding) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!pc_self || !p_binding) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) { - TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport"); - return -2; - } + if (!TNET_SOCKET_TYPE_IS_DGRAM(p_binding->socket_type)) { + TSK_DEBUG_ERROR("Only DGRAM could be used for STUN transport"); + return -2; + } if ((ret = tnet_stun_binding_create_req(p_binding, &p_pkt_req))) { goto bail; @@ -225,51 +224,51 @@ int tnet_nat_stun_send_bind(const struct tnet_nat_ctx_s* pc_self, struct tnet_st authentication or message integrity applied. */ stun_phase0: { - if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) { - goto bail; - } + if ((ret = tnet_stun_utils_send_unreliably(p_binding->localFD, pc_self->RTO, pc_self->Rc, p_pkt_req, (struct sockaddr*)&p_binding->addr_server, &p_pkt_resp))) { + goto bail; + } if (p_pkt_resp) { if (TNET_STUN_PKT_RESP_IS_ERROR(p_pkt_resp)) { - uint16_t u_code; - if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) { - goto bail; - } - if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { - if (u_code == kStunErrCodeUnauthorized) { - // Make sure this is not an authentication failure (#2 401) - // Do not send another req to avoid endless messages - if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? - TSK_DEBUG_ERROR("STUN authentication failed"); - goto bail; - } - } - if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) { - goto bail; - } - // Try to send again now that authinfo is up2date - goto stun_phase0; - } - else if (u_code == kStunErrCodeUnknownAttributes) { - if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) { - goto bail; - } - // Try to send again now that authinfo is up2date - goto stun_phase0; - } - ret = -3; + uint16_t u_code; + if ((ret = tnet_stun_pkt_get_errorcode(p_pkt_resp, &u_code))) { + goto bail; + } + if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { + if (u_code == kStunErrCodeUnauthorized) { + // Make sure this is not an authentication failure (#2 401) + // Do not send another req to avoid endless messages + if ((tnet_stun_pkt_attr_exists(p_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? + TSK_DEBUG_ERROR("STUN authentication failed"); + goto bail; + } + } + if ((ret = tnet_stun_pkt_auth_prepare_2(p_pkt_req, p_binding->p_username, p_binding->p_password, p_pkt_resp))) { + goto bail; + } + // Try to send again now that authinfo is up2date + goto stun_phase0; + } + else if (u_code == kStunErrCodeUnknownAttributes) { + if((ret = tnet_stun_pkt_process_err420(p_pkt_req, p_pkt_resp))) { + goto bail; + } + // Try to send again now that authinfo is up2date + goto stun_phase0; + } + ret = -3; } else { - const tnet_stun_attr_address_t* pc_addr; - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { - TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr); - p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr)); - } - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { - TSK_OBJECT_SAFE_FREE(p_binding->p_maddr); - p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr)); - } - } + const tnet_stun_attr_address_t* pc_addr; + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { + TSK_OBJECT_SAFE_FREE(p_binding->p_xmaddr); + p_binding->p_xmaddr = tsk_object_ref(TSK_OBJECT(pc_addr)); + } + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt_resp, tnet_stun_attr_type_mapped_address, (const tnet_stun_attr_t**)&pc_addr)) == 0 && pc_addr) { + TSK_OBJECT_SAFE_FREE(p_binding->p_maddr); + p_binding->p_maddr = tsk_object_ref(TSK_OBJECT(pc_addr)); + } + } } } /* END OF stun_phase0 */ @@ -285,51 +284,51 @@ bail: * Gets the server reflexive address associated to this STUN2 binding. * * - * @param [in,out] p_self The NAT context. - * @param id The id of the STUN2 binding conetxt (obtained using @ref tnet_nat_stun_bind) holding the server-reflexive address. - * @param [in,out] pp_ip The reflexive IP address. It is up the the caller to free the returned string - * @param [in,out] pu_port The reflexive port. + * @param [in,out] p_self The NAT context. + * @param id The id of the STUN2 binding conetxt (obtained using @ref tnet_nat_stun_bind) holding the server-reflexive address. + * @param [in,out] pp_ip The reflexive IP address. It is up the the caller to free the returned string + * @param [in,out] pu_port The reflexive port. * - * @return Zero if succeed and non zero error code otherwise. + * @return Zero if succeed and non zero error code otherwise. **/ int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id, char** pp_ip, tnet_port_t *pu_port) { - const tsk_list_item_t* item; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!pp_ip && !pu_port) { - return 0; - } - - if ((item = tsk_list_find_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id)) && item->data) { - const tnet_stun_binding_t *pc_bind = (const tnet_stun_binding_t *)item->data; - const struct tnet_stun_attr_address_s *pc_addr = pc_bind->p_xmaddr ? pc_bind->p_xmaddr : pc_bind->p_maddr; - if (pc_addr) { - tnet_ip_t ip; - int ret; - if ((ret = tnet_stun_utils_inet_ntop((pc_addr->e_family == tnet_stun_address_family_ipv6), &pc_addr->address, &ip))) { - return ret; - } - if (pp_ip) { - tsk_strupdate(pp_ip, ip); - } - if (pu_port) { - *pu_port = pc_addr->u_port; - } - return 0; - } - } - return -2; + const tsk_list_item_t* item; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!pp_ip && !pu_port) { + return 0; + } + + if ((item = tsk_list_find_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id)) && item->data) { + const tnet_stun_binding_t *pc_bind = (const tnet_stun_binding_t *)item->data; + const struct tnet_stun_attr_address_s *pc_addr = pc_bind->p_xmaddr ? pc_bind->p_xmaddr : pc_bind->p_maddr; + if (pc_addr) { + tnet_ip_t ip; + int ret; + if ((ret = tnet_stun_utils_inet_ntop((pc_addr->e_family == tnet_stun_address_family_ipv6), &pc_addr->address, &ip))) { + return ret; + } + if (pp_ip) { + tsk_strupdate(pp_ip, ip); + } + if (pu_port) { + *pu_port = pc_addr->u_port; + } + return 0; + } + } + return -2; } /**@ingroup tnet_nat_group * * Removes a STUN2 binding from the NAT context. * - * @param [in,out] p_self The NAT context from which to remove the STUN2 binding. - * @param id The id of the STUN2 binding to remove. + * @param [in,out] p_self The NAT context from which to remove the STUN2 binding. + * @param id The id of the STUN2 binding to remove. * * @return Zero if succeed and non zero error code otherwise. * @@ -338,12 +337,12 @@ int tnet_nat_stun_get_reflexive_address(const struct tnet_nat_ctx_s* p_self, tne **/ int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_id_t id) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_list_remove_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_list_remove_item_by_pred(p_self->stun_bindings, __pred_find_stun_binding, &id); + return 0; } @@ -352,30 +351,29 @@ int tnet_nat_stun_unbind(const struct tnet_nat_ctx_s* p_self, tnet_stun_binding_ // static tsk_object_t* tnet_nat_context_ctor(tsk_object_t * self, va_list * app) { - tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self; - if (p_ctx) { - } - return self; + tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self; + if (p_ctx) { + } + return self; } static tsk_object_t* tnet_nat_context_dtor(tsk_object_t * self) -{ - tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self; - if (p_ctx) { - TSK_FREE(p_ctx->username); - TSK_FREE(p_ctx->password); - TSK_FREE(p_ctx->server_address); - - TSK_OBJECT_SAFE_FREE(p_ctx->stun_bindings); - TSK_DEBUG_INFO("*** NAT context destroyed ***"); - } - - return self; -} -static const tsk_object_def_t tnet_nat_context_def_s = { - sizeof(tnet_nat_ctx_t), - tnet_nat_context_ctor, - tnet_nat_context_dtor, - tsk_null, + tnet_nat_ctx_t *p_ctx = (tnet_nat_ctx_t*)self; + if (p_ctx) { + TSK_FREE(p_ctx->username); + TSK_FREE(p_ctx->password); + TSK_FREE(p_ctx->server_address); + + TSK_OBJECT_SAFE_FREE(p_ctx->stun_bindings); + TSK_DEBUG_INFO("*** NAT context destroyed ***"); + } + + return self; +} +static const tsk_object_def_t tnet_nat_context_def_s = { + sizeof(tnet_nat_ctx_t), + tnet_nat_context_ctor, + tnet_nat_context_dtor, + tsk_null, }; const tsk_object_def_t *tnet_nat_context_def_t = &tnet_nat_context_def_s; diff --git a/tinyNET/src/tnet_nat.h b/tinyNET/src/tnet_nat.h index 46d774f..626851d 100755 --- a/tinyNET/src/tnet_nat.h +++ b/tinyNET/src/tnet_nat.h @@ -6,12 +6,12 @@ * 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. * diff --git a/tinyNET/src/tnet_poll.c b/tinyNET/src/tnet_poll.c index 816f9c6..ebde819 100755 --- a/tinyNET/src/tnet_poll.c +++ b/tinyNET/src/tnet_poll.c @@ -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. * @@ -25,11 +25,11 @@ /** * - * @brief poll() method implementation for multiplexing network sockets. + * @brief poll() method implementation for multiplexing network sockets. * - * @param fds An array of pollfd structures. - * @param nfds The number of file descriptors set in fds[ ]. - * @param timeout How long poll() should wait for an event to occur (in milliseconds). + * @param fds An array of pollfd structures. + * @param nfds The number of file descriptors set in fds[ ]. + * @param timeout How long poll() should wait for an event to occur (in milliseconds). * * @return The number of elements in fdarray for which an revents member of the POLLFD structure is nonzero. * If the the returned value if <0 this mean that error occurred. @@ -37,71 +37,71 @@ int tnet_poll(tnet_pollfd_t fds[ ], tnet_nfds_t nfds, int timeout) { - tsk_size_t i; - int ret; - int highest_fd = -1; + tsk_size_t i; + int ret; + int highest_fd = -1; + + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + struct timeval timetowait; + + /* + * cleanup fd_sets + */ + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); - fd_set readfds; - fd_set writefds; - fd_set exceptfds; - struct timeval timetowait; + /* + * set timeout + */ + if(timeout >=0) { + timetowait.tv_sec = (timeout/1000); + timetowait.tv_usec = (timeout%1000) * 1000; + } - /* - * cleanup fd_sets - */ - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); + /* + * add descriptors to the fd_sets + */ + for(i = 0; i<nfds; i++) { + if(fds[i].fd != TNET_INVALID_FD) { + if(fds[i].events & TNET_POLLIN) { + FD_SET(fds[i].fd, &readfds); + } + if(fds[i].events & TNET_POLLOUT) { + FD_SET(fds[i].fd, &writefds); + } + if(fds[i].events & TNET_POLLPRI) { + FD_SET(fds[i].fd, &exceptfds); + } + } - /* - * set timeout - */ - if(timeout >=0){ - timetowait.tv_sec = (timeout/1000); - timetowait.tv_usec = (timeout%1000) * 1000; - } + highest_fd = (highest_fd < fds[i].fd) ? fds[i].fd : highest_fd; + } - /* - * add descriptors to the fd_sets - */ - for(i = 0; i<nfds; i++){ - if(fds[i].fd != TNET_INVALID_FD){ - if(fds[i].events & TNET_POLLIN){ - FD_SET(fds[i].fd, &readfds); - } - if(fds[i].events & TNET_POLLOUT){ - FD_SET(fds[i].fd, &writefds); - } - if(fds[i].events & TNET_POLLPRI){ - FD_SET(fds[i].fd, &exceptfds); - } - } - - highest_fd = (highest_fd < fds[i].fd) ? fds[i].fd : highest_fd; - } - - /*====================================== - * select - */ - if((ret = select(highest_fd + 1, &readfds, &writefds, &exceptfds, (timeout >=0) ? &timetowait : 0)) >= 0){ - for(i = 0; i<nfds; i++){ - if(fds[i].fd != TNET_INVALID_FD){ - fds[i].revents = 0; + /*====================================== + * select + */ + if((ret = select(highest_fd + 1, &readfds, &writefds, &exceptfds, (timeout >=0) ? &timetowait : 0)) >= 0) { + for(i = 0; i<nfds; i++) { + if(fds[i].fd != TNET_INVALID_FD) { + fds[i].revents = 0; - if(FD_ISSET(fds[i].fd, &readfds)){ - fds[i].revents |= TNET_POLLIN; - } - if(FD_ISSET(fds[i].fd, &writefds)){ - fds[i].revents |= TNET_POLLOUT; - } - if(FD_ISSET(fds[i].fd, &exceptfds)){ - fds[i].revents |= TNET_POLLPRI; - } - } - } - } + if(FD_ISSET(fds[i].fd, &readfds)) { + fds[i].revents |= TNET_POLLIN; + } + if(FD_ISSET(fds[i].fd, &writefds)) { + fds[i].revents |= TNET_POLLOUT; + } + if(FD_ISSET(fds[i].fd, &exceptfds)) { + fds[i].revents |= TNET_POLLPRI; + } + } + } + } - return ret; + return ret; } #endif /* TNET_USE_POLL */ diff --git a/tinyNET/src/tnet_poll.h b/tinyNET/src/tnet_poll.h index becd1c3..a9c4a0f 100755 --- a/tinyNET/src/tnet_poll.h +++ b/tinyNET/src/tnet_poll.h @@ -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,7 +44,7 @@ typedef unsigned long tnet_nfds_t; typedef struct pollfd tnet_pollfd_t; -#define TNET_POLLRDNORM POLLRDNORM +#define TNET_POLLRDNORM POLLRDNORM #define TNET_POLLRDBAND POLLRDBAND #define TNET_POLLIN POLLIN #define TNET_POLLPRI POLLPRI @@ -65,8 +65,7 @@ typedef struct pollfd tnet_pollfd_t; #else -typedef struct tnet_pollfd_s -{ +typedef struct tnet_pollfd_s { tnet_fd_t fd; short events; short revents; diff --git a/tinyNET/src/tnet_proto.h b/tinyNET/src/tnet_proto.h index ef7d89e..3365989 100755 --- a/tinyNET/src/tnet_proto.h +++ b/tinyNET/src/tnet_proto.h @@ -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. * @@ -37,156 +37,155 @@ TNET_BEGIN_DECLS /** * @enum tnet_proto_e * - * @brief List of all assigned protocols as defined by the IANA + * @brief List of all assigned protocols as defined by the IANA (http://www.iana.org/assignments/protocol-numbers/). **/ -typedef enum tnet_proto_e -{ - TNET_PROTO_HOPOPT = 0, /**< HOPOPT IPv6 Hop-by-Hop Option [RFC1883] */ - TNET_PROTO_ICMP = 1, /**< ICMP Internet Control Message [RFC792] */ - TNET_PROTO_IGMP = 2, /**< IGMP Internet Group Management [RFC1112] */ - TNET_PROTO_GGP = 3, /**< GGP Gateway-to-Gateway [RFC823] */ - TNET_PROTO_IP = 4, /**< IP IP in IP (encapsulation) [RFC2003] */ - TNET_PROTO_ST = 5, /**< ST Stream [RFC1190][RFC1819] */ - TNET_PROTO_TCP = 6, /**< TCP Transmission Control [RFC793] */ - TNET_PROTO_CBT = 7, /**< CBT CBT [Ballardie] */ - TNET_PROTO_EGP = 8, /**< EGP Exterior Gateway Protocol [RFC888][DLM1] */ - TNET_PROTO_IGP = 9, /**< IGP any private interior gateway [IANA](used by Cisco for their IGRP) */ - TNET_PROTO_BBN_RCC_MON = 10, /**< BBN-RCC-MON BBN RCC Monitoring [SGC] */ - TNET_PROTO_NVP_II = 11, /**< NVP-II Network Voice Protocol [RFC741][SC3] */ - TNET_PROTO_PUP = 12, /**< PUP PUP [PUP][XEROX] */ - TNET_PROTO_ARGUS = 13, /**< ARGUS ARGUS [RWS4] */ - TNET_PROTO_EMCON = 14, /**< EMCON EMCON [BN7] */ - TNET_PROTO_XNET = 15, /**< XNET Cross Net Debugger [IEN158][JFH2] */ - TNET_PROTO_CHAOS = 16, /**< CHAOS Chaos [NC3] */ - TNET_PROTO_UDP = 17, /**< UDP User Datagram [RFC768][JBP] */ - TNET_PROTO_MUX = 18, /**< MUX Multiplexing [IEN90][JBP] */ - TNET_PROTO_DCN_MEAS = 19, /**< DCN-MEAS DCN Measurement Subsystems [DLM1] */ - TNET_PROTO_HMP = 20, /**< HMP Host Monitoring [RFC869][RH6] */ - TNET_PROTO_PRM = 21, /**< PRM Packet Radio Measurement [ZSU] */ - TNET_PROTO_XNS_IDP = 22, /**< XNS-IDP XEROX NS IDP [ETHERNET][XEROX] */ - TNET_PROTO_TRUNK_1 = 23, /**< TRUNK-1 Trunk-1 [BWB6] */ - TNET_PROTO_TRUNK_2 = 24, /**< TRUNK-2 Trunk-2 [BWB6] */ - TNET_PROTO_LEAF_1 = 25, /**< LEAF-1 Leaf-1 [BWB6] */ - TNET_PROTO_LEAF_2 = 26, /**< LEAF-2 Leaf-2 [BWB6] */ - TNET_PROTO_RDP = 27, /**< RDP Reliable Data Protocol [RFC908][RH6] */ - TNET_PROTO_IRTP = 28, /**< IRTP Internet Reliable Transaction [RFC938][TXM] */ - TNET_PROTO_ISO_TP4 = 29, /**< ISO-TP4 ISO Transport Protocol Class 4 [RFC905][RC77] */ - TNET_PROTO_NETBLT = 30, /**< NETBLT Bulk Data Transfer Protocol [RFC969][DDC1] */ - TNET_PROTO_MFE_NSP = 31, /**< MFE-NSP MFE Network Services Protocol [MFENET][BCH2] */ - TNET_PROTO_MERIT_INP = 32, /**< MERIT-INP MERIT Internodal Protocol [HWB] */ - TNET_PROTO_DCCP = 33, /**< DCCP Datagram Congestion Control Protocol [RFC4340] */ - TNET_PROTO_3PC = 34, /**< 3PC Third Party Connect Protocol [SAF3] */ - TNET_PROTO_IDPR = 35, /**< IDPR Inter-Domain Policy Routing Protocol [MXS1] */ - TNET_PROTO_XTP = 36, /**< XTP XTP [GXC] */ - TNET_PROTO_DDP = 37, /**< DDP Datagram Delivery Protocol [WXC] */ - TNET_PROTO_IDPR_CMTP = 38, /**< IDPR-CMTP IDPR Control Message Transport Proto [MXS1] */ - TNET_PROTO_TP_PP = 39, /**< TP++ TP++ Transport Protocol [DXF] */ - TNET_PROTO_IL = 40, /**< IL IL Transport Protocol [Presotto] */ - TNET_PROTO_IPv6 = 41, /**< IPv6 Ipv6 [Deering] */ - TNET_PROTO_SDRP = 42, /**< SDRP Source Demand Routing Protocol [DXE1] */ - TNET_PROTO_IPv6_Route = 43, /**< IPv6-Route Routing Header for IPv6 [Deering] */ - TNET_PROTO_IPv6_Frag = 44, /**< IPv6-Frag Fragment Header for IPv6 [Deering] */ - TNET_PROTO_IDRP = 45, /**< IDRP Inter-Domain Routing Protocol [Hares] */ - TNET_PROTO_RSVP = 46, /**< RSVP Reservation Protocol [Braden] */ - TNET_PROTO_GRE = 47, /**< GRE General Routing Encapsulation [Li] */ - TNET_PROTO_DSR = 48, /**< DSR Dynamic Source Routing Protocol [RFC4728] */ - TNET_PROTO_BNA = 49, /**< BNA BNA [Salamon] */ - TNET_PROTO_ESP = 50, /**< ESP Encap Security Payload [RFC4303] */ - TNET_PROTO_AH = 51, /**< AH Authentication Header [RFC4302] */ - TNET_PROTO_I_NLSP = 52, /**< I-NLSP Integrated Net Layer Security TUBA [GLENN] */ - TNET_PROTO_SWIPE = 53, /**< SWIPE IP with Encryption [JI6] */ - TNET_PROTO_NARP = 54, /**< NARP NBMA Address Resolution Protocol [RFC1735] */ - TNET_PROTO_MOBILE = 55, /**< MOBILE IP Mobility [Perkins] */ - TNET_PROTO_TLSP = 56, /**< TLSP Transport Layer Security Protocol [Oberg] using Kryptonet key management */ - TNET_PROTO_SKIP = 57, /**< SKIP SKIP [Markson] */ - TNET_PROTO_IPv6_ICMP = 58, /**< IPv6-ICMP ICMP for IPv6 [RFC1883] */ - TNET_PROTO_IPv6_NoNxt = 59, /**< IPv6-NoNxt No Next Header for IPv6 [RFC1883] */ - TNET_PROTO_IPv6_Opts = 60, /**< IPv6-Opts Destination Options for IPv6 [RFC1883] */ - TNET_PROTO_ANY_INTERNAL = 61, /**< any host internal protocol [IANA] */ - TNET_PROTO_CFTP = 62, /**< CFTP CFTP [CFTP][HCF2] */ - TNET_PROTO_ANY_LOCAL = 63, /**< any local network [IANA] */ - TNET_PROTO_SAT_EXPAK = 64, /**< SAT-EXPAK SATNET and Backroom EXPAK [SHB] */ - TNET_PROTO_KRYPTOLAN = 65, /**< KRYPTOLAN Kryptolan [PXL1] */ - TNET_PROTO_RVD = 66, /**< RVD MIT Remote Virtual Disk Protocol [MBG] */ - TNET_PROTO_IPPC = 67, /**< IPPC Internet Pluribus Packet Core [SHB] */ - TNET_PROTO_ANY_DISTRIBUTED = 68, /**< any distributed file system [IANA] */ - TNET_PROTO_SAT_MON = 69, /**< SAT-MON SATNET Monitoring [SHB] */ - TNET_PROTO_VISA = 70, /**< VISA VISA Protocol [GXT1] */ - TNET_PROTO_IPCV = 71, /**< IPCV Internet Packet Core Utility [SHB] */ - TNET_PROTO_CPNX = 72, /**< CPNX Computer Protocol Network Executive [DXM2] */ - TNET_PROTO_CPHB = 73, /**< CPHB Computer Protocol Heart Beat [DXM2] */ - TNET_PROTO_WSN = 74, /**< WSN Wang Span Network [VXD] */ - TNET_PROTO_PVP = 75, /**< PVP Packet Video Protocol [SC3] */ - TNET_PROTO_BR_SAT_MON = 76, /**< BR-SAT-MON Backroom SATNET Monitoring [SHB] */ - TNET_PROTO_SUN_ND = 77, /**< SUN-ND SUN ND PROTOCOL-Temporary [WM3] */ - TNET_PROTO_WB_MON = 78, /**< WB-MON WIDEBAND Monitoring [SHB] */ - TNET_PROTO_WB_EXPAK = 79, /**< WB-EXPAK WIDEBAND EXPAK [SHB] */ - TNET_PROTO_ISO_IP = 80, /**< ISO-IP ISO Internet Protocol [MTR] */ - TNET_PROTO_VMTP = 81, /**< VMTP VMTP [DRC3] */ - TNET_PROTO_SECURE_VMTP = 82, /**< SECURE-VMTP SECURE-VMTP [DRC3] */ - TNET_PROTO_VINES = 83, /**< VINES VINES [BXH] */ - TNET_PROTO_TTP = 84, /**< TTP TTP [JXS] */ - TNET_PROTO_NSFNET_IGP = 85, /**< NSFNET-IGP NSFNET-IGP [HWB] */ - TNET_PROTO_DGP = 86, /**< DGP Dissimilar Gateway Protocol [DGP][ML109] */ - TNET_PROTO_TCF = 87, /**< TCF TCF [GAL5] */ - TNET_PROTO_EIGRP = 88, /**< EIGRP EIGRP [CISCO][GXS] */ - TNET_PROTO_OSPFIGP = 89, /**< OSPFIGP OSPFIGP [RFC1583][JTM4] */ - TNET_PROTO_Sprite_RPC = 90, /**< Sprite-RPC Sprite RPC Protocol [SPRITE][BXW] */ - TNET_PROTO_LARP = 91, /**< LARP Locus Address Resolution Protocol [BXH] */ - TNET_PROTO_MTP = 92, /**< MTP Multicast Transport Protocol [SXA] */ - TNET_PROTO_AX25 = 93, /**< AX.25 AX.25 Frames [BK29] */ - TNET_PROTO_IPIP = 94, /**< IPIP IP-within-IP Encapsulation Protocol [JI6] */ - TNET_PROTO_MICP = 95, /**< MICP Mobile Internetworking Control Pro. [JI6] */ - TNET_PROTO_SCC_SP = 96, /**< SCC-SP Semaphore Communications Sec. Pro. [HXH] */ - TNET_PROTO_ETHERIP = 97, /**< ETHERIP Ethernet-within-IP Encapsulation [RFC3378] */ - TNET_PROTO_ENCAP = 98, /**< ENCAP Encapsulation Header [RFC1241,RXB3] */ - TNET_PROTO_ANY_PRIV_ENC = 99, /**< any private encryption scheme [IANA] */ - TNET_PROTO_GMTP = 100, /**< GMTP GMTP [RXB5] */ - TNET_PROTO_IFMP = 101, /**< IFMP Ipsilon Flow Management Protocol [Hinden] */ - TNET_PROTO_PNNI = 102, /**< PNNI PNNI over IP [Callon] */ - TNET_PROTO_PIM = 103, /**< PIM Protocol Independent Multicast [Farinacci] */ - TNET_PROTO_ARIS = 104, /**< ARIS ARIS [Feldman] */ - TNET_PROTO_SCPS = 105, /**< SCPS SCPS [Durst] */ - TNET_PROTO_QNX = 106, /**< QNX QNX [Hunter] */ - TNET_PROTO_AN = 107, /**< A/N Active Networks [Braden] */ - TNET_PROTO_IPComp = 108, /**< IPComp IP Payload Compression Protocol [RFC2393] */ - TNET_PROTO_SNP = 109, /**< SNP Sitara Networks Protocol [Sridhar] */ - TNET_PROTO_Compaq_Peer = 110, /**< Compaq-Peer Compaq Peer Protocol [Volpe] */ - TNET_PROTO_IPX_in_IP = 11, /**< IPX-in-IP IPX in IP [Lee] */ - TNET_PROTO_VRRP = 112, /**< VRRP Virtual Router Redundancy Protocol [RFC3768][RFC-ietf-vrrp-unified-spec-05.txt] */ - TNET_PROTO_PGM = 113, /**< PGM PGM Reliable Transport Protocol [Speakman] */ - TNET_PROTO_ANY_ZERO_HOP = 114, /**< any 0-hop protocol [IANA] */ - TNET_PROTO_L2TP = 115, /**< L2TP Layer Two Tunneling Protocol [Aboba] */ - TNET_PROTO_DDX = 116, /**< DDX D-II Data Exchange (DDX) [Worley] */ - TNET_PROTO_IATP = 117, /**< IATP Interactive Agent Transfer Protocol [Murphy] */ - TNET_PROTO_STP = 118, /**< STP Schedule Transfer Protocol [JMP] */ - TNET_PROTO_SRP = 119, /**< SRP SpectraLink Radio Protocol [Hamilton] */ - TNET_PROTO_UTI = 120, /**< UTI UTI [Lothberg] */ - TNET_PROTO_SMP = 121, /**< SMP Simple Message Protocol [Ekblad] */ - TNET_PROTO_SM = 122, /**< SM SM [Crowcroft] */ - TNET_PROTO_PTP = 123, /**< PTP Performance Transparency Protocol [Welzl] */ - TNET_PROTO_ISIS = 124, /**< ISIS over IPv4 [Przygienda] */ - TNET_PROTO_FIRE = 125, /**< FIRE [Partridge] */ - TNET_PROTO_CRTP = 126, /**< CRTP Combat Radio Transport Protocol [Sautter] */ - TNET_PROTO_CRUDP = 127, /**< CRUDP Combat Radio User Datagram [Sautter] */ - TNET_PROTO_SSCOPMCE = 128, /**< SSCOPMCE [Waber] */ - TNET_PROTO_IPLT = 129, /**< IPLT [Hollbach] */ - TNET_PROTO_SPS = 130, /**< SPS Secure Packet Shield [McIntosh] */ - TNET_PROTO_PIPE = 131, /**< PIPE Private IP Encapsulation within IP [Petri] */ - TNET_PROTO_SCTP = 132, /**< SCTP Stream Control Transmission Protocol [Stewart] */ - TNET_PROTO_FC = 133, /**< FC Fibre Channel [Rajagopal] */ - TNET_PROTO_RSVP_E2E_IGNORE = 134, /**< RSVP-E2E-IGNORE [RFC3175] */ - TNET_PROTO_Mobility_Header = 135, /**< Mobility Header [RFC3775] */ - TNET_PROTO_UDPLite = 136, /**< UDPLite [RFC3828] */ - TNET_PROTO_MPLS_in_IP = 137, /**< MPLS-in-IP [RFC4023] */ - TNET_PROTO_manet = 138, /**< manet MANET Protocols [RFC5498] */ - TNET_PROTO_HIP = 139, /**< HIP Host Identity Protocol [RFC5201] */ - TNET_PROTO_Shim6 = 140, /**< Shim6 Shim6 Protocol [RFC5533] */ - //TNET_PROTO_ = 141-252 Unassigned [IANA] - TNET_PROTO_EXP1 = 253, /**< Use for experimentation and testing [RFC3692] */ - TNET_PROTO_EXP2 = 254, /**< Use for experimentation and testing [RFC3692] */ - TNET_PROTO_Reserved = 255, /**< Reserved [IANA] */ +typedef enum tnet_proto_e { + TNET_PROTO_HOPOPT = 0, /**< HOPOPT IPv6 Hop-by-Hop Option [RFC1883] */ + TNET_PROTO_ICMP = 1, /**< ICMP Internet Control Message [RFC792] */ + TNET_PROTO_IGMP = 2, /**< IGMP Internet Group Management [RFC1112] */ + TNET_PROTO_GGP = 3, /**< GGP Gateway-to-Gateway [RFC823] */ + TNET_PROTO_IP = 4, /**< IP IP in IP (encapsulation) [RFC2003] */ + TNET_PROTO_ST = 5, /**< ST Stream [RFC1190][RFC1819] */ + TNET_PROTO_TCP = 6, /**< TCP Transmission Control [RFC793] */ + TNET_PROTO_CBT = 7, /**< CBT CBT [Ballardie] */ + TNET_PROTO_EGP = 8, /**< EGP Exterior Gateway Protocol [RFC888][DLM1] */ + TNET_PROTO_IGP = 9, /**< IGP any private interior gateway [IANA](used by Cisco for their IGRP) */ + TNET_PROTO_BBN_RCC_MON = 10, /**< BBN-RCC-MON BBN RCC Monitoring [SGC] */ + TNET_PROTO_NVP_II = 11, /**< NVP-II Network Voice Protocol [RFC741][SC3] */ + TNET_PROTO_PUP = 12, /**< PUP PUP [PUP][XEROX] */ + TNET_PROTO_ARGUS = 13, /**< ARGUS ARGUS [RWS4] */ + TNET_PROTO_EMCON = 14, /**< EMCON EMCON [BN7] */ + TNET_PROTO_XNET = 15, /**< XNET Cross Net Debugger [IEN158][JFH2] */ + TNET_PROTO_CHAOS = 16, /**< CHAOS Chaos [NC3] */ + TNET_PROTO_UDP = 17, /**< UDP User Datagram [RFC768][JBP] */ + TNET_PROTO_MUX = 18, /**< MUX Multiplexing [IEN90][JBP] */ + TNET_PROTO_DCN_MEAS = 19, /**< DCN-MEAS DCN Measurement Subsystems [DLM1] */ + TNET_PROTO_HMP = 20, /**< HMP Host Monitoring [RFC869][RH6] */ + TNET_PROTO_PRM = 21, /**< PRM Packet Radio Measurement [ZSU] */ + TNET_PROTO_XNS_IDP = 22, /**< XNS-IDP XEROX NS IDP [ETHERNET][XEROX] */ + TNET_PROTO_TRUNK_1 = 23, /**< TRUNK-1 Trunk-1 [BWB6] */ + TNET_PROTO_TRUNK_2 = 24, /**< TRUNK-2 Trunk-2 [BWB6] */ + TNET_PROTO_LEAF_1 = 25, /**< LEAF-1 Leaf-1 [BWB6] */ + TNET_PROTO_LEAF_2 = 26, /**< LEAF-2 Leaf-2 [BWB6] */ + TNET_PROTO_RDP = 27, /**< RDP Reliable Data Protocol [RFC908][RH6] */ + TNET_PROTO_IRTP = 28, /**< IRTP Internet Reliable Transaction [RFC938][TXM] */ + TNET_PROTO_ISO_TP4 = 29, /**< ISO-TP4 ISO Transport Protocol Class 4 [RFC905][RC77] */ + TNET_PROTO_NETBLT = 30, /**< NETBLT Bulk Data Transfer Protocol [RFC969][DDC1] */ + TNET_PROTO_MFE_NSP = 31, /**< MFE-NSP MFE Network Services Protocol [MFENET][BCH2] */ + TNET_PROTO_MERIT_INP = 32, /**< MERIT-INP MERIT Internodal Protocol [HWB] */ + TNET_PROTO_DCCP = 33, /**< DCCP Datagram Congestion Control Protocol [RFC4340] */ + TNET_PROTO_3PC = 34, /**< 3PC Third Party Connect Protocol [SAF3] */ + TNET_PROTO_IDPR = 35, /**< IDPR Inter-Domain Policy Routing Protocol [MXS1] */ + TNET_PROTO_XTP = 36, /**< XTP XTP [GXC] */ + TNET_PROTO_DDP = 37, /**< DDP Datagram Delivery Protocol [WXC] */ + TNET_PROTO_IDPR_CMTP = 38, /**< IDPR-CMTP IDPR Control Message Transport Proto [MXS1] */ + TNET_PROTO_TP_PP = 39, /**< TP++ TP++ Transport Protocol [DXF] */ + TNET_PROTO_IL = 40, /**< IL IL Transport Protocol [Presotto] */ + TNET_PROTO_IPv6 = 41, /**< IPv6 Ipv6 [Deering] */ + TNET_PROTO_SDRP = 42, /**< SDRP Source Demand Routing Protocol [DXE1] */ + TNET_PROTO_IPv6_Route = 43, /**< IPv6-Route Routing Header for IPv6 [Deering] */ + TNET_PROTO_IPv6_Frag = 44, /**< IPv6-Frag Fragment Header for IPv6 [Deering] */ + TNET_PROTO_IDRP = 45, /**< IDRP Inter-Domain Routing Protocol [Hares] */ + TNET_PROTO_RSVP = 46, /**< RSVP Reservation Protocol [Braden] */ + TNET_PROTO_GRE = 47, /**< GRE General Routing Encapsulation [Li] */ + TNET_PROTO_DSR = 48, /**< DSR Dynamic Source Routing Protocol [RFC4728] */ + TNET_PROTO_BNA = 49, /**< BNA BNA [Salamon] */ + TNET_PROTO_ESP = 50, /**< ESP Encap Security Payload [RFC4303] */ + TNET_PROTO_AH = 51, /**< AH Authentication Header [RFC4302] */ + TNET_PROTO_I_NLSP = 52, /**< I-NLSP Integrated Net Layer Security TUBA [GLENN] */ + TNET_PROTO_SWIPE = 53, /**< SWIPE IP with Encryption [JI6] */ + TNET_PROTO_NARP = 54, /**< NARP NBMA Address Resolution Protocol [RFC1735] */ + TNET_PROTO_MOBILE = 55, /**< MOBILE IP Mobility [Perkins] */ + TNET_PROTO_TLSP = 56, /**< TLSP Transport Layer Security Protocol [Oberg] using Kryptonet key management */ + TNET_PROTO_SKIP = 57, /**< SKIP SKIP [Markson] */ + TNET_PROTO_IPv6_ICMP = 58, /**< IPv6-ICMP ICMP for IPv6 [RFC1883] */ + TNET_PROTO_IPv6_NoNxt = 59, /**< IPv6-NoNxt No Next Header for IPv6 [RFC1883] */ + TNET_PROTO_IPv6_Opts = 60, /**< IPv6-Opts Destination Options for IPv6 [RFC1883] */ + TNET_PROTO_ANY_INTERNAL = 61, /**< any host internal protocol [IANA] */ + TNET_PROTO_CFTP = 62, /**< CFTP CFTP [CFTP][HCF2] */ + TNET_PROTO_ANY_LOCAL = 63, /**< any local network [IANA] */ + TNET_PROTO_SAT_EXPAK = 64, /**< SAT-EXPAK SATNET and Backroom EXPAK [SHB] */ + TNET_PROTO_KRYPTOLAN = 65, /**< KRYPTOLAN Kryptolan [PXL1] */ + TNET_PROTO_RVD = 66, /**< RVD MIT Remote Virtual Disk Protocol [MBG] */ + TNET_PROTO_IPPC = 67, /**< IPPC Internet Pluribus Packet Core [SHB] */ + TNET_PROTO_ANY_DISTRIBUTED = 68, /**< any distributed file system [IANA] */ + TNET_PROTO_SAT_MON = 69, /**< SAT-MON SATNET Monitoring [SHB] */ + TNET_PROTO_VISA = 70, /**< VISA VISA Protocol [GXT1] */ + TNET_PROTO_IPCV = 71, /**< IPCV Internet Packet Core Utility [SHB] */ + TNET_PROTO_CPNX = 72, /**< CPNX Computer Protocol Network Executive [DXM2] */ + TNET_PROTO_CPHB = 73, /**< CPHB Computer Protocol Heart Beat [DXM2] */ + TNET_PROTO_WSN = 74, /**< WSN Wang Span Network [VXD] */ + TNET_PROTO_PVP = 75, /**< PVP Packet Video Protocol [SC3] */ + TNET_PROTO_BR_SAT_MON = 76, /**< BR-SAT-MON Backroom SATNET Monitoring [SHB] */ + TNET_PROTO_SUN_ND = 77, /**< SUN-ND SUN ND PROTOCOL-Temporary [WM3] */ + TNET_PROTO_WB_MON = 78, /**< WB-MON WIDEBAND Monitoring [SHB] */ + TNET_PROTO_WB_EXPAK = 79, /**< WB-EXPAK WIDEBAND EXPAK [SHB] */ + TNET_PROTO_ISO_IP = 80, /**< ISO-IP ISO Internet Protocol [MTR] */ + TNET_PROTO_VMTP = 81, /**< VMTP VMTP [DRC3] */ + TNET_PROTO_SECURE_VMTP = 82, /**< SECURE-VMTP SECURE-VMTP [DRC3] */ + TNET_PROTO_VINES = 83, /**< VINES VINES [BXH] */ + TNET_PROTO_TTP = 84, /**< TTP TTP [JXS] */ + TNET_PROTO_NSFNET_IGP = 85, /**< NSFNET-IGP NSFNET-IGP [HWB] */ + TNET_PROTO_DGP = 86, /**< DGP Dissimilar Gateway Protocol [DGP][ML109] */ + TNET_PROTO_TCF = 87, /**< TCF TCF [GAL5] */ + TNET_PROTO_EIGRP = 88, /**< EIGRP EIGRP [CISCO][GXS] */ + TNET_PROTO_OSPFIGP = 89, /**< OSPFIGP OSPFIGP [RFC1583][JTM4] */ + TNET_PROTO_Sprite_RPC = 90, /**< Sprite-RPC Sprite RPC Protocol [SPRITE][BXW] */ + TNET_PROTO_LARP = 91, /**< LARP Locus Address Resolution Protocol [BXH] */ + TNET_PROTO_MTP = 92, /**< MTP Multicast Transport Protocol [SXA] */ + TNET_PROTO_AX25 = 93, /**< AX.25 AX.25 Frames [BK29] */ + TNET_PROTO_IPIP = 94, /**< IPIP IP-within-IP Encapsulation Protocol [JI6] */ + TNET_PROTO_MICP = 95, /**< MICP Mobile Internetworking Control Pro. [JI6] */ + TNET_PROTO_SCC_SP = 96, /**< SCC-SP Semaphore Communications Sec. Pro. [HXH] */ + TNET_PROTO_ETHERIP = 97, /**< ETHERIP Ethernet-within-IP Encapsulation [RFC3378] */ + TNET_PROTO_ENCAP = 98, /**< ENCAP Encapsulation Header [RFC1241,RXB3] */ + TNET_PROTO_ANY_PRIV_ENC = 99, /**< any private encryption scheme [IANA] */ + TNET_PROTO_GMTP = 100, /**< GMTP GMTP [RXB5] */ + TNET_PROTO_IFMP = 101, /**< IFMP Ipsilon Flow Management Protocol [Hinden] */ + TNET_PROTO_PNNI = 102, /**< PNNI PNNI over IP [Callon] */ + TNET_PROTO_PIM = 103, /**< PIM Protocol Independent Multicast [Farinacci] */ + TNET_PROTO_ARIS = 104, /**< ARIS ARIS [Feldman] */ + TNET_PROTO_SCPS = 105, /**< SCPS SCPS [Durst] */ + TNET_PROTO_QNX = 106, /**< QNX QNX [Hunter] */ + TNET_PROTO_AN = 107, /**< A/N Active Networks [Braden] */ + TNET_PROTO_IPComp = 108, /**< IPComp IP Payload Compression Protocol [RFC2393] */ + TNET_PROTO_SNP = 109, /**< SNP Sitara Networks Protocol [Sridhar] */ + TNET_PROTO_Compaq_Peer = 110, /**< Compaq-Peer Compaq Peer Protocol [Volpe] */ + TNET_PROTO_IPX_in_IP = 11, /**< IPX-in-IP IPX in IP [Lee] */ + TNET_PROTO_VRRP = 112, /**< VRRP Virtual Router Redundancy Protocol [RFC3768][RFC-ietf-vrrp-unified-spec-05.txt] */ + TNET_PROTO_PGM = 113, /**< PGM PGM Reliable Transport Protocol [Speakman] */ + TNET_PROTO_ANY_ZERO_HOP = 114, /**< any 0-hop protocol [IANA] */ + TNET_PROTO_L2TP = 115, /**< L2TP Layer Two Tunneling Protocol [Aboba] */ + TNET_PROTO_DDX = 116, /**< DDX D-II Data Exchange (DDX) [Worley] */ + TNET_PROTO_IATP = 117, /**< IATP Interactive Agent Transfer Protocol [Murphy] */ + TNET_PROTO_STP = 118, /**< STP Schedule Transfer Protocol [JMP] */ + TNET_PROTO_SRP = 119, /**< SRP SpectraLink Radio Protocol [Hamilton] */ + TNET_PROTO_UTI = 120, /**< UTI UTI [Lothberg] */ + TNET_PROTO_SMP = 121, /**< SMP Simple Message Protocol [Ekblad] */ + TNET_PROTO_SM = 122, /**< SM SM [Crowcroft] */ + TNET_PROTO_PTP = 123, /**< PTP Performance Transparency Protocol [Welzl] */ + TNET_PROTO_ISIS = 124, /**< ISIS over IPv4 [Przygienda] */ + TNET_PROTO_FIRE = 125, /**< FIRE [Partridge] */ + TNET_PROTO_CRTP = 126, /**< CRTP Combat Radio Transport Protocol [Sautter] */ + TNET_PROTO_CRUDP = 127, /**< CRUDP Combat Radio User Datagram [Sautter] */ + TNET_PROTO_SSCOPMCE = 128, /**< SSCOPMCE [Waber] */ + TNET_PROTO_IPLT = 129, /**< IPLT [Hollbach] */ + TNET_PROTO_SPS = 130, /**< SPS Secure Packet Shield [McIntosh] */ + TNET_PROTO_PIPE = 131, /**< PIPE Private IP Encapsulation within IP [Petri] */ + TNET_PROTO_SCTP = 132, /**< SCTP Stream Control Transmission Protocol [Stewart] */ + TNET_PROTO_FC = 133, /**< FC Fibre Channel [Rajagopal] */ + TNET_PROTO_RSVP_E2E_IGNORE = 134, /**< RSVP-E2E-IGNORE [RFC3175] */ + TNET_PROTO_Mobility_Header = 135, /**< Mobility Header [RFC3775] */ + TNET_PROTO_UDPLite = 136, /**< UDPLite [RFC3828] */ + TNET_PROTO_MPLS_in_IP = 137, /**< MPLS-in-IP [RFC4023] */ + TNET_PROTO_manet = 138, /**< manet MANET Protocols [RFC5498] */ + TNET_PROTO_HIP = 139, /**< HIP Host Identity Protocol [RFC5201] */ + TNET_PROTO_Shim6 = 140, /**< Shim6 Shim6 Protocol [RFC5533] */ + //TNET_PROTO_ = 141-252 Unassigned [IANA] + TNET_PROTO_EXP1 = 253, /**< Use for experimentation and testing [RFC3692] */ + TNET_PROTO_EXP2 = 254, /**< Use for experimentation and testing [RFC3692] */ + TNET_PROTO_Reserved = 255, /**< Reserved [IANA] */ } tnet_proto_t; diff --git a/tinyNET/src/tnet_proxy_node_socks_plugin.c b/tinyNET/src/tnet_proxy_node_socks_plugin.c index e5f8d08..f15f706 100755 --- a/tinyNET/src/tnet_proxy_node_socks_plugin.c +++ b/tinyNET/src/tnet_proxy_node_socks_plugin.c @@ -89,22 +89,21 @@ typedef enum socks5_state_e { socks5_state_auth_req, socks5_state_conn_req, socks5_state_conn_accept, - + socks5_state_error } socks5_state_t; -typedef struct tnet_proxy_node_socks_plugin_s -{ +typedef struct tnet_proxy_node_socks_plugin_s { TNET_DECLARE_PROXY_NONE; - + struct { tsk_bool_t completed; tsk_bool_t started; tsk_buffer_t* buff; uint8_t* pending_data_ptr; tsk_size_t pending_data_len; - + socks5_state_t socks5_state; socks5_auth_method_t socks5_auth_method; #if TNET_SOCKS5_HAVE_AUTH_GSSAPI @@ -114,10 +113,10 @@ typedef struct tnet_proxy_node_socks_plugin_s OM_uint32 status_major; gss_name_t server_name; tsk_bool_t init_sec_complete; - }gss; + } gss; #endif /* TNET_SOCKS5_HAVE_AUTH_GSSAPI */ } handshacking; - + TSK_DECLARE_SAFEOBJ; } tnet_proxy_node_socks_plugin_t; @@ -135,18 +134,18 @@ static int _tnet_proxy_node_socks_plugin_configure(tnet_proxy_node_t* self, ...) tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; va_list ap; int ret = 0; - + // input parameters already checked by the caller - + tsk_safeobj_lock(node); - + // extract dst_host, dst_port, proxy_host, proxy_port, ipv6_enabled, ... va_start(ap, self); ret = tnet_proxy_node_configure_2(self, &ap); va_end(ap); - + tsk_safeobj_unlock(node); - + return 0; } @@ -154,9 +153,9 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se { tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; int ret = 0; - + // input parameters already checked by the caller - + tsk_safeobj_lock(node); if (node->handshacking.started) { TSK_DEBUG_ERROR("handshaking already started"); @@ -167,11 +166,11 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se ret = -2; goto bail; } - + // reset pending data TSK_FREE(node->handshacking.pending_data_ptr); node->handshacking.pending_data_len = 0; - + #if USING_CFSTREAM if (tsk_strnullORempty(self->proxy_host) || !self->proxy_port) { TSK_DEBUG_ERROR("Invalid proxy host and/or port for socks server %s:%hu", self->proxy_host, self->proxy_port); @@ -183,7 +182,7 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se ret = -3; goto bail; } - + CFStringRef cfstrHost = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, self->proxy_host, kCFStringEncodingUTF8, NULL); int intPort = (int)self->proxy_port; CFNumberRef cfintPort = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &intPort); @@ -202,10 +201,10 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se CFDictionarySetValue(socksConfig, kCFStreamPropertySOCKSPassword, cfstrPassword); CFRelease(cfstrPassword); } - + if (!CFReadStreamSetProperty(self->cf_read_stream, kCFStreamPropertySOCKSProxy, socksConfig)) { CFStreamError error = CFReadStreamGetError(self->cf_read_stream); - + TSK_DEBUG_INFO("CFReadStreamSetProperty(kCFStreamPropertySOCKSProxy) failed code=%d, domain=%ld", (int)error.error, error.domain); ret = -4; } @@ -214,12 +213,12 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se TSK_DEBUG_INFO("CFWriteStreamSetProperty(kCFStreamPropertySOCKSProxy) code=%d, domain=%ld", (int)error.error, error.domain); ret = -5; } - + CFRelease(cfstrHost); CFRelease(cfintPort); CFRelease(socksConfig); CFRelease(proxyDict); - + node->handshacking.started = (ret == 0); node->handshacking.completed = node->handshacking.started; // no handshaking data to send, up to the system #else @@ -227,15 +226,15 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se tsk_size_t size_to_reserve, userid_len = tsk_strlen(self->login), domain_len = 0; if (self->type == tnet_proxy_type_socks4 || self->type == tnet_proxy_type_socks4a) { size_to_reserve = 1 /* version number */ - + 1 /* command code */ - + 2 /* network byte order port number */ - + 4 /* network byte order IP address */ - + userid_len + 1 /* the user ID string, variable length, terminated with a null (0x00) */ - ; + + 1 /* command code */ + + 2 /* network byte order port number */ + + 4 /* network byte order IP address */ + + userid_len + 1 /* the user ID string, variable length, terminated with a null (0x00) */ + ; if (self->type == tnet_proxy_type_socks4a) { domain_len = tsk_strlen(self->dst_host); size_to_reserve += domain_len + 1/* the domain name of the host we want to contact, variable length, terminated with a null (0x00) */ - ; + ; } } else { // SOCKS5 @@ -246,17 +245,17 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se } // Greeting size_to_reserve = 1 /* version number */ - + 1 /* number of authentication methods supported */ + + 1 /* number of authentication methods supported */ #if TNET_SOCKS5_HAVE_AUTH_NONE - + 1 + + 1 #endif #if TNET_SOCKS5_HAVE_AUTH_USRPWD - + 1 + + 1 #endif #if TNET_SOCKS5_HAVE_AUTH_GSSAPI - + 1 + + 1 #endif - ; + ; } node->handshacking.pending_data_ptr = (uint8_t*)tsk_realloc(node->handshacking.pending_data_ptr, size_to_reserve); if (!node->handshacking.pending_data_ptr) { @@ -266,7 +265,7 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se goto bail; } node->handshacking.pending_data_len = size_to_reserve; - + if (self->type == tnet_proxy_type_socks4 || self->type == tnet_proxy_type_socks4a) { node->handshacking.pending_data_ptr[0] = 0x04; // version number node->handshacking.pending_data_ptr[1] = 0x01; // establish a TCP/IP stream connection (caller aldready check we're dealing with Streams) @@ -294,7 +293,7 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se memcpy(&node->handshacking.pending_data_ptr[8], self->login, userid_len); } node->handshacking.pending_data_ptr[8 + userid_len] = 0x00; - + // the domain name of the host we want to contact, variable length, terminated with a null (0x00) if (self->type == tnet_proxy_type_socks4a) { if (domain_len > 0) { @@ -331,8 +330,8 @@ static int _tnet_proxy_node_socks_plugin_start_handshaking(tnet_proxy_node_t* se node->handshacking.started = tsk_true; } #endif - - + + bail: tsk_safeobj_unlock(node); return ret; @@ -342,17 +341,17 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* { tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; int ret = 0; - + // input parameters already checked by the caller - + tsk_safeobj_lock(node); - + if (!node->handshacking.started) { TSK_DEBUG_ERROR("handshaking not started"); ret = -3; goto bail; } - + #if USING_CFSTREAM TSK_DEBUG_ERROR("Up to CFStreams to handle handshaking"); ret = -2; @@ -400,7 +399,8 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* } if (buff[0] != 0x05) { TSK_DEBUG_ERROR("Invalid version (%d)", buff[0]); - ret = -3; goto bail; + ret = -3; + goto bail; } if (buff[1] == kSocks5AuthMethodNone || buff[1] == kSocks5AuthMethodUsrPwd || buff[1] == kSocks5AuthMethodGSSAPI) { node->handshacking.socks5_auth_method = (socks5_auth_method_t)buff[1]; @@ -410,16 +410,17 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* node->handshacking.socks5_state = socks5_state_conn_req; // FIXME: TSK_DEBUG_ERROR("Not implemented yet"); - ret = -3; goto bail; + ret = -3; + goto bail; } else { if (node->handshacking.socks5_auth_method == kSocks5AuthMethodUsrPwd) { tsk_size_t userlen = tsk_strlen(self->login), pwdlen = tsk_strlen(self->password); tsk_size_t size_to_reserve = 1 /* version number */ - + 1 /* username length */ - + userlen /* username */ - + 1 /* password length */ - + pwdlen; + + 1 /* username length */ + + userlen /* username */ + + 1 /* password length */ + + pwdlen; node->handshacking.pending_data_ptr = (uint8_t*)tsk_realloc(node->handshacking.pending_data_ptr, size_to_reserve); if (!node->handshacking.pending_data_ptr) { TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)size_to_reserve); @@ -428,7 +429,7 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* goto bail; } node->handshacking.pending_data_len = size_to_reserve; - + node->handshacking.pending_data_ptr[0] = 0x01; node->handshacking.pending_data_ptr[1] = (userlen & 0xFF); if (userlen > 0) { @@ -450,21 +451,24 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* TSK_DEBUG_ERROR("gss_import_name() failed"); goto bail; } - + #else TSK_DEBUG_ERROR("GSSAPI not supported"); - ret = -3; goto bail; + ret = -3; + goto bail; #endif } else { TSK_DEBUG_ERROR("Not implemented yet"); - ret = -3; goto bail; + ret = -3; + goto bail; } } } else { TSK_DEBUG_ERROR("Invalid authentication method (%d)", buff[1]); - ret = -3; goto bail; + ret = -3; + goto bail; } } else if (node->handshacking.socks5_state == socks5_state_auth_req) { @@ -476,12 +480,14 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* } if (buff[0] != 0x1) { TSK_DEBUG_ERROR("Invalid version :%d", buff[0]); - ret = -3; goto bail; + ret = -3; + goto bail; } TSK_DEBUG_INFO("Socks5 authentication status code: %d", buff[1]); if (buff[1] != 0x00) { TSK_DEBUG_ERROR("Authentication failed with status code :%d", buff[1]); - ret = -3; goto bail; + ret = -3; + goto bail; } tsk_buffer_remove(node->handshacking.buff, 0, 2); // remove parsed bytes node->handshacking.socks5_state = socks5_state_conn_req; @@ -489,13 +495,15 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* else if (node->handshacking.socks5_auth_method == kSocks5AuthMethodGSSAPI) { // FIXME: TSK_DEBUG_ERROR("Not implemented yet"); - ret = -3; goto bail; + ret = -3; + goto bail; } else { TSK_DEBUG_ERROR("Invalid authentication method (%d)", buff[1]); - ret = -3; goto bail; + ret = -3; + goto bail; } - + // State changed from "auth_req" to "conn_req" : build connection request if (node->handshacking.socks5_state == socks5_state_conn_req) { #define kAddrTypeIPv4 0x01 @@ -505,12 +513,12 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* tsk_bool_t is_ip = tsk_false; // ip or domain name uint8_t addr_type = 0x00; tsk_size_t dst_addr_len = 0, size_to_reserve = 1 /* version number */ - + 1 /* command code */ - + 1 /* reserved, must be 0x00 */ - + 1 /* address type */ - + 0 /* destination address (==to be computed later==) */ - + 2 /* port number in a network byte order */ - ; + + 1 /* command code */ + + 1 /* reserved, must be 0x00 */ + + 1 /* address type */ + + 0 /* destination address (==to be computed later==) */ + + 2 /* port number in a network byte order */ + ; if ((ret = tnet_sockaddr_init(self->dst_host, self->dst_port, self->socket.type, &addr)) != 0) { TSK_DEBUG_WARN("tnet_sockaddr_init(%s, %d, %d) failed", self->dst_host, self->dst_port, self->socket.type); // maybe DNS issue (e.g UDP blocked), do not exit, up to the server to resolve it @@ -534,10 +542,11 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* if (!node->handshacking.pending_data_ptr) { TSK_DEBUG_ERROR("Failed to allocate buffer with size = %u", (unsigned)size_to_reserve); node->handshacking.pending_data_len = 0; - ret = -5; goto bail; + ret = -5; + goto bail; } node->handshacking.pending_data_len = size_to_reserve; - + node->handshacking.pending_data_ptr[0] = 0x05; // version number node->handshacking.pending_data_ptr[1] = 0x01; // establish a TCP/IP stream connection node->handshacking.pending_data_ptr[2] = 0x00; // reserved, must be 0x00 @@ -564,12 +573,14 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* } if (buff[0] != 0x05) { TSK_DEBUG_ERROR("Invalid version (%d)", buff[0]); - ret = -3; goto bail; + ret = -3; + goto bail; } TSK_DEBUG_INFO("Socks5 connection request status code: %d", buff[1]); if (buff[1] != 0x00) { TSK_DEBUG_ERROR("Socks5 connection request failed with status code :%d", buff[1]); - ret = -3; goto bail; + ret = -3; + goto bail; } tsk_buffer_remove(node->handshacking.buff, 0, 2); // remove parsed bytes node->handshacking.socks5_state = socks5_state_conn_accept; @@ -592,7 +603,7 @@ static int _tnet_proxy_node_socks_plugin_set_handshaking_data(tnet_proxy_node_t* goto bail; } #endif - + bail: if (ret != 0) { if (self->type == tnet_proxy_type_socks5) { @@ -607,11 +618,11 @@ static int _tnet_proxy_node_socks_plugin_get_handshaking_pending_data(tnet_proxy { tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; int ret = -1; - + // input parameters already checked by the caller - + tsk_safeobj_lock(node); - + #if USING_CFSTREAM *data_psize = 0; // no pending data ret = 0; @@ -627,7 +638,7 @@ static int _tnet_proxy_node_socks_plugin_get_handshaking_pending_data(tnet_proxy node->handshacking.pending_data_len = 0; } #endif - + tsk_safeobj_unlock(node); return ret; } @@ -636,9 +647,9 @@ static int _tnet_proxy_node_socks_plugin_get_handshaking_completed(tnet_proxy_no { tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; int ret = 0; - + // input parameters already checked by the caller - + tsk_safeobj_lock(node); *completed = node->handshacking.completed; tsk_safeobj_unlock(node); @@ -648,23 +659,34 @@ static int _tnet_proxy_node_socks_plugin_get_handshaking_completed(tnet_proxy_no static const char* __socks5_state_to_string(socks5_state_t state) { switch (state) { - case socks5_state_none: return "none"; - case socks5_state_greeting: return "greeting"; - case socks5_state_auth_req: return "auth_req"; - case socks5_state_conn_req: return "conn_req"; - case socks5_state_conn_accept: return "conn_accept"; - case socks5_state_error: return "error"; - default: return "unknown"; + case socks5_state_none: + return "none"; + case socks5_state_greeting: + return "greeting"; + case socks5_state_auth_req: + return "auth_req"; + case socks5_state_conn_req: + return "conn_req"; + case socks5_state_conn_accept: + return "conn_accept"; + case socks5_state_error: + return "error"; + default: + return "unknown"; } } static const char* __socks5_method_to_string(socks5_auth_method_t method) { switch (method) { - case kSocks5AuthMethodNone: return "none"; - case kSocks5AuthMethodGSSAPI: return "gssapi"; - case kSocks5AuthMethodUsrPwd: return "usr/pwd"; - default: return "unknown"; + case kSocks5AuthMethodNone: + return "none"; + case kSocks5AuthMethodGSSAPI: + return "gssapi"; + case kSocks5AuthMethodUsrPwd: + return "usr/pwd"; + default: + return "unknown"; } } @@ -676,7 +698,7 @@ static int __socks5_gss_import_name(tnet_proxy_node_t* self) int i, ret = 0; tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; gss_buffer_desc input_name_buffer = GSS_C_EMPTY_BUFFER; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -686,7 +708,7 @@ static int __socks5_gss_import_name(tnet_proxy_node_t* self) // reset pending handshaking data TSK_FREE(node->handshacking.pending_data_ptr); node->handshacking.pending_data_len = 0; - + /* For example, when using Kerberos V5 naming, the imported name may be of the form "SERVICE:socks@socks_server_hostname" where @@ -697,7 +719,7 @@ static int __socks5_gss_import_name(tnet_proxy_node_t* self) for (i = 0; i < input_name_buffer.length; ++i) { ((char*)input_name_buffer.value)[i] = tolower(((char*)input_name_buffer.value)[i]); } - + /* The client should call gss_import_name to obtain an internal representation of the server name. For maximal portability the @@ -709,19 +731,20 @@ static int __socks5_gss_import_name(tnet_proxy_node_t* self) TSK_DEBUG_INFO("gss_import_name(%.*s, GSS_C_NULL_OID): minor_status = %u, major_status = %u", (int)input_name_buffer.length, (const char*)input_name_buffer.value, node->handshacking.gss.status_minor, node->handshacking.gss.status_major); if (node->handshacking.gss.status_major != GSS_S_COMPLETE) { __socks_gss_print_error("gss_import_name failed", node->handshacking.gss.status_major, node->handshacking.gss.status_minor); - ret = -2; goto bail; + ret = -2; + goto bail; } /* debug */{ gss_OID output_name_type; gss_buffer_desc output_name = GSS_C_EMPTY_BUFFER; node->handshacking.gss.status_major = gss_display_name(&node->handshacking.gss.status_minor, - node->handshacking.gss.server_name, - &output_name, - &output_name_type); + node->handshacking.gss.server_name, + &output_name, + &output_name_type); TSK_DEBUG_INFO("gss_display_name(%.*s): minor_status = %u, major_status = %u, output = %.*s", (int)input_name_buffer.length, (const char*)input_name_buffer.value, node->handshacking.gss.status_minor, node->handshacking.gss.status_major, (int)output_name.length, (const char*)output_name.value); node->handshacking.gss.status_major = gss_release_buffer(&node->handshacking.gss.status_minor, &output_name); } - + bail: gss_release_buffer(&node->handshacking.gss.status_minor, &input_name_buffer); return 0; @@ -736,17 +759,17 @@ static int __socks5_gss_init_sec_context(tnet_proxy_node_t* self) tnet_proxy_node_socks_plugin_t* node = (tnet_proxy_node_socks_plugin_t*)self; gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER, *input_token_ptr = GSS_C_NO_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - -/* - +------+------+------+.......................+ - + ver | mtyp | len | token | - +------+------+------+.......................+ - + 0x01 | 0x01 | 0x02 | up to 2^16 - 1 octets | - +------+------+------+.......................+ -*/ + + /* + +------+------+------+.......................+ + + ver | mtyp | len | token | + +------+------+------+.......................+ + + 0x01 | 0x01 | 0x02 | up to 2^16 - 1 octets | + +------+------+------+.......................+ + */ #define kTokenMsgHdrLongLen 4 // with "len" field #define kTokenMsgHdrShortLen 2 // without "len" field - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -766,44 +789,46 @@ static int __socks5_gss_init_sec_context(tnet_proxy_node_t* self) } else { TSK_DEBUG_ERROR("GSS invalid mtyp(%u)", buff[1]); - ret = -5; goto bail; + ret = -5; + goto bail; } } - + req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_DELEG_FLAG; // However, GSS_C_SEQUENCE_FLAG should only be passed in for TCP-based clients, not for UDP-based clients. if (TNET_SOCKET_TYPE_IS_STREAM(self->socket.type)) { req_flags |= GSS_C_SEQUENCE_FLAG; } - + node->handshacking.gss.status_major = gss_delete_sec_context(&node->handshacking.gss.status_minor, &node->handshacking.gss.ctx, NULL); - + node->handshacking.gss.ctx = GSS_C_NO_CONTEXT; node->handshacking.gss.status_major = gss_init_sec_context(&node->handshacking.gss.status_minor, - GSS_C_NO_CREDENTIAL, // GSS_C_NO_CREDENTIAL into cred_handle to specify the default credential (for initiator usage) - &node->handshacking.gss.ctx, - node->handshacking.gss.server_name, - GSS_C_NULL_OID, // GSS_C_NULL_OID into mech_type to specify the default mechanism - req_flags, - GSS_C_INDEFINITE, - GSS_C_NO_CHANNEL_BINDINGS, - input_token_ptr, - tsk_null, - &output_token, - tsk_null, - tsk_null); - - + GSS_C_NO_CREDENTIAL, // GSS_C_NO_CREDENTIAL into cred_handle to specify the default credential (for initiator usage) + &node->handshacking.gss.ctx, + node->handshacking.gss.server_name, + GSS_C_NULL_OID, // GSS_C_NULL_OID into mech_type to specify the default mechanism + req_flags, + GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + input_token_ptr, + tsk_null, + &output_token, + tsk_null, + tsk_null); + + // Only "GSS_S_COMPLETE" and "GSS_S_CONTINUE_NEEDED" are acceptable if (node->handshacking.gss.status_major != GSS_S_COMPLETE && node->handshacking.gss.status_major != GSS_S_CONTINUE_NEEDED) { __socks_gss_print_error("gss_init_sec_context failed", node->handshacking.gss.status_major, node->handshacking.gss.status_minor); - ret = -2; goto bail; + ret = -2; + goto bail; } - + // reset pending handshaking data TSK_FREE(node->handshacking.pending_data_ptr); node->handshacking.pending_data_len = 0; - + if (output_token.length > 0 && output_token.value) { node->handshacking.pending_data_len = kTokenMsgHdrLongLen + output_token.length; node->handshacking.pending_data_ptr = tsk_realloc(node->handshacking.pending_data_ptr, node->handshacking.pending_data_len); @@ -819,14 +844,14 @@ static int __socks5_gss_init_sec_context(tnet_proxy_node_t* self) node->handshacking.pending_data_ptr[3] = output_token.length & 0xFF; memcpy(&node->handshacking.pending_data_ptr[4], output_token.value, output_token.length); } - + if (input_token.length > 0) { tsk_buffer_remove(node->handshacking.buff, 0, kTokenMsgHdrLongLen + input_token.length); } - + // update "init_sec_complete" node->handshacking.gss.init_sec_complete = (ret == 0) && (node->handshacking.gss.status_major == GSS_S_COMPLETE); - + bail: return ret; } @@ -835,7 +860,7 @@ static void __socks_gss_print_error(const char* info, OM_uint32 status_major, OM { OM_uint32 m1, m2, s1, s2; gss_buffer_desc out1 = {.value = tsk_null, .length = 0}, out2 = {.value = tsk_null, .length = 0}; - + // print the error m1 = 0, s1 = 0; gss_display_status(&s1, status_major, GSS_C_GSS_CODE, GSS_C_NULL_OID, &m1, &out1); @@ -885,29 +910,27 @@ static tsk_object_t* tnet_proxy_node_socks_plugin_dtor(tsk_object_t * self) } #endif /* TNET_SOCKS5_HAVE_AUTH_GSSAPI */ tsk_safeobj_deinit(node); - + TSK_DEBUG_INFO("*** Socks(4/4a/5) proxy node destroyed ***"); } return self; } /* object definition */ -static const tsk_object_def_t thttp_proxy_node_def_s = -{ +static const tsk_object_def_t thttp_proxy_node_def_s = { sizeof(tnet_proxy_node_socks_plugin_t), tnet_proxy_node_socks_plugin_ctor, tnet_proxy_node_socks_plugin_dtor, tsk_null, }; /* plugin definition*/ -static const struct tnet_proxy_node_plugin_def_s tnet_proxy_node_socks_plugin_def_s = -{ +static const struct tnet_proxy_node_plugin_def_s tnet_proxy_node_socks_plugin_def_s = { &thttp_proxy_node_def_s, - + (tnet_proxy_type_socks4 | tnet_proxy_type_socks4a | tnet_proxy_type_socks5), - + "SOCKS(4/4a/5) proxy node plugin", - + _tnet_proxy_node_socks_plugin_configure, _tnet_proxy_node_socks_plugin_start_handshaking, _tnet_proxy_node_socks_plugin_set_handshaking_data, diff --git a/tinyNET/src/tnet_proxy_plugin.c b/tinyNET/src/tnet_proxy_plugin.c index dbcd143..1555dce 100755 --- a/tinyNET/src/tnet_proxy_plugin.c +++ b/tinyNET/src/tnet_proxy_plugin.c @@ -34,17 +34,17 @@ const tnet_proxy_node_plugin_def_t* __tnet_proxy_node_plugins[TNET_PROXY_NODE_MA tsk_bool_t tnet_proxy_node_is_nettransport_supported(enum tnet_proxy_type_e proxy_type, enum tnet_socket_type_e socket_type) { switch (proxy_type) { - case tnet_proxy_type_http: + case tnet_proxy_type_http: case tnet_proxy_type_https: - return TNET_SOCKET_TYPE_IS_STREAM(socket_type); - - case tnet_proxy_type_socks4: - case tnet_proxy_type_socks4a: - return TNET_SOCKET_TYPE_IS_STREAM(socket_type) && TNET_SOCKET_TYPE_IS_IPV4(socket_type); - case tnet_proxy_type_socks5: // SOCKS5 adds support for UDP and IPv6 - return TNET_SOCKET_TYPE_IS_STREAM(socket_type) || TNET_SOCKET_TYPE_IS_DGRAM(socket_type);// for now we don't support socks for UDP (just like a browser) - default: - return tsk_false; + return TNET_SOCKET_TYPE_IS_STREAM(socket_type); + + case tnet_proxy_type_socks4: + case tnet_proxy_type_socks4a: + return TNET_SOCKET_TYPE_IS_STREAM(socket_type) && TNET_SOCKET_TYPE_IS_IPV4(socket_type); + case tnet_proxy_type_socks5: // SOCKS5 adds support for UDP and IPv6 + return TNET_SOCKET_TYPE_IS_STREAM(socket_type) || TNET_SOCKET_TYPE_IS_DGRAM(socket_type);// for now we don't support socks for UDP (just like a browser) + default: + return tsk_false; } } @@ -61,12 +61,12 @@ int tnet_proxy_node_configure(tnet_proxy_node_t* self, ...) { va_list ap; int ret = 0; - + if (!self) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + va_start(ap, self); ret = tnet_proxy_node_configure_2(self, &ap); va_end(ap); @@ -77,73 +77,81 @@ int tnet_proxy_node_configure_2(tnet_proxy_node_t* self, va_list* app) { int ret = 0; tnet_proxy_node_param_type_t ptype; - + if (!self || !app) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + while ((ptype = va_arg(*app, tnet_proxy_node_param_type_t)) != tnet_proxy_node_param_type_null) { switch (ptype) { - case tnet_proxy_node_param_type_destination_address: - case tnet_proxy_node_param_type_proxy_address: { - // (const char*)(HOST_STR), (int)(PORT_INT) - const char* HOST_STR = va_arg(*app, const char*); - int PORT_INT = va_arg(*app, int); - if (PORT_INT < 1 || PORT_INT > 0xFFF) { - TSK_DEBUG_ERROR("Invalid value for port number: %d", PORT_INT); - ret = -3; - goto bail; - } - if (ptype == tnet_proxy_node_param_type_destination_address) { - tsk_strupdate(&self->dst_host, HOST_STR); - self->dst_port = (tnet_port_t)PORT_INT; - } - else { - tsk_strupdate(&self->proxy_host, HOST_STR); - self->proxy_port = (tnet_port_t)PORT_INT; - } - break; + case tnet_proxy_node_param_type_destination_address: + case tnet_proxy_node_param_type_proxy_address: { + // (const char*)(HOST_STR), (int)(PORT_INT) + const char* HOST_STR = va_arg(*app, const char*); + int PORT_INT = va_arg(*app, int); + if (PORT_INT < 1 || PORT_INT > 0xFFF) { + TSK_DEBUG_ERROR("Invalid value for port number: %d", PORT_INT); + ret = -3; + goto bail; } - case tnet_proxy_node_param_type_ipv6: { - /* (tsk_bool_t)(IPV6_BOOL) */ - self->ipv6 = va_arg(*app, tsk_bool_t); - break; + if (ptype == tnet_proxy_node_param_type_destination_address) { + tsk_strupdate(&self->dst_host, HOST_STR); + self->dst_port = (tnet_port_t)PORT_INT; } - case tnet_proxy_node_param_type_credentials: { - /* (const char*)(LOGIN_STR), (const char*)(PASSWORD_STR) */ - const char* LOGIN_STR = va_arg(*app, const char*); - const char* PASSWORD_STR = va_arg(*app, const char*); - tsk_strupdate(&self->login, LOGIN_STR); - tsk_strupdate(&self->password, PASSWORD_STR); - break; - } - case tnet_proxy_node_param_type_socket: { - /* (tnet_fd_t)(FD_FD), (enum tnet_socket_type_e)(type) */ - self->socket.fd = va_arg(*app, tnet_fd_t); - self->socket.type = va_arg(*app, enum tnet_socket_type_e); - break; + else { + tsk_strupdate(&self->proxy_host, HOST_STR); + self->proxy_port = (tnet_port_t)PORT_INT; } + break; + } + case tnet_proxy_node_param_type_ipv6: { + /* (tsk_bool_t)(IPV6_BOOL) */ + self->ipv6 = va_arg(*app, tsk_bool_t); + break; + } + case tnet_proxy_node_param_type_credentials: { + /* (const char*)(LOGIN_STR), (const char*)(PASSWORD_STR) */ + const char* LOGIN_STR = va_arg(*app, const char*); + const char* PASSWORD_STR = va_arg(*app, const char*); + tsk_strupdate(&self->login, LOGIN_STR); + tsk_strupdate(&self->password, PASSWORD_STR); + break; + } + case tnet_proxy_node_param_type_socket: { + /* (tnet_fd_t)(FD_FD), (enum tnet_socket_type_e)(type) */ + self->socket.fd = va_arg(*app, tnet_fd_t); + self->socket.type = va_arg(*app, enum tnet_socket_type_e); + break; + } #if TNET_UNDER_APPLE - case tnet_proxy_node_param_type_cfstreams: { - /* (CFReadStreamRef)(READ_CFSTREAM), (CFWriteStreamRef)(WRITE_CFSTREAM) */ - CFReadStreamRef READ_CFSTREAM = va_arg(*app, CFReadStreamRef); - CFWriteStreamRef WRITE_CFSTREAM = va_arg(*app, CFWriteStreamRef); - if (self->cf_read_stream) CFRelease(self->cf_read_stream), self->cf_read_stream = tsk_null; - if (self->cf_write_stream) CFRelease(self->cf_write_stream), self->cf_write_stream = tsk_null; - if (READ_CFSTREAM) self->cf_read_stream = (CFReadStreamRef)CFRetain(READ_CFSTREAM); - if (WRITE_CFSTREAM) self->cf_write_stream = (CFWriteStreamRef)CFRetain(WRITE_CFSTREAM); - break; + case tnet_proxy_node_param_type_cfstreams: { + /* (CFReadStreamRef)(READ_CFSTREAM), (CFWriteStreamRef)(WRITE_CFSTREAM) */ + CFReadStreamRef READ_CFSTREAM = va_arg(*app, CFReadStreamRef); + CFWriteStreamRef WRITE_CFSTREAM = va_arg(*app, CFWriteStreamRef); + if (self->cf_read_stream) { + CFRelease(self->cf_read_stream), self->cf_read_stream = tsk_null; } -#endif /* TNET_UNDER_APPLE */ - default: { - TSK_DEBUG_ERROR("%d not valid param type", ptype); - ret = -2; - goto bail; + if (self->cf_write_stream) { + CFRelease(self->cf_write_stream), self->cf_write_stream = tsk_null; + } + if (READ_CFSTREAM) { + self->cf_read_stream = (CFReadStreamRef)CFRetain(READ_CFSTREAM); } + if (WRITE_CFSTREAM) { + self->cf_write_stream = (CFWriteStreamRef)CFRetain(WRITE_CFSTREAM); + } + break; + } +#endif /* TNET_UNDER_APPLE */ + default: { + TSK_DEBUG_ERROR("%d not valid param type", ptype); + ret = -2; + goto bail; + } } } - + bail: return ret; } @@ -210,16 +218,16 @@ int tnet_proxy_node_plugin_register(const tnet_proxy_node_plugin_def_t* plugin) TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + /* add or replace the plugin */ for (i = 0; i<TNET_PROXY_NODE_MAX_PLUGINS; i++) { - if (!__tnet_proxy_node_plugins[i] || (__tnet_proxy_node_plugins[i] == plugin)){ + if (!__tnet_proxy_node_plugins[i] || (__tnet_proxy_node_plugins[i] == plugin)) { __tnet_proxy_node_plugins[i] = plugin; TSK_DEBUG_INFO("Register network proxy node plugin: %s", plugin->desc); return 0; } } - + TSK_DEBUG_ERROR("There are already %d network proxy node plugins.", TNET_PROXY_NODE_MAX_PLUGINS); return -2; } @@ -232,7 +240,7 @@ int tnet_proxy_node_plugin_unregister(const tnet_proxy_node_plugin_def_t* plugin TSK_DEBUG_ERROR("Invalid Parameter"); return -1; } - + /* find the plugin to unregister */ for (i = 0; i<TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[i]; i++) { if (__tnet_proxy_node_plugins[i] == plugin) { @@ -242,7 +250,7 @@ int tnet_proxy_node_plugin_unregister(const tnet_proxy_node_plugin_def_t* plugin break; } } - + /* compact */ if (found) { for (; i<(TNET_PROXY_NODE_MAX_PLUGINS - 1); i++) { @@ -262,8 +270,8 @@ tsk_size_t tnet_proxy_node_plugin_registry_count() { tsk_size_t count; for(count = 0; - count < TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[count]; - ++count) ; + count < TNET_PROXY_NODE_MAX_PLUGINS && __tnet_proxy_node_plugins[count]; + ++count) ; return count; } diff --git a/tinyNET/src/tnet_proxy_plugin.h b/tinyNET/src/tnet_proxy_plugin.h index 0a247bc..75d9612 100755 --- a/tinyNET/src/tnet_proxy_plugin.h +++ b/tinyNET/src/tnet_proxy_plugin.h @@ -35,7 +35,7 @@ TNET_BEGIN_DECLS typedef struct tnet_proxy_node_s { TSK_DECLARE_OBJECT; - + enum tnet_proxy_type_e type; tsk_bool_t ipv6; char* dst_host; @@ -52,7 +52,7 @@ typedef struct tnet_proxy_node_s { CFReadStreamRef cf_read_stream; CFWriteStreamRef cf_write_stream; #endif /* TNET_UNDER_APPLE */ - + const struct tnet_proxy_node_plugin_def_s* plugin; } tnet_proxy_node_t; @@ -60,8 +60,7 @@ tnet_proxy_node_t; #define TNET_PROXY_NODE(self) ((tnet_proxy_node_t*)(self)) #define TNET_DECLARE_PROXY_NONE tnet_proxy_node_t __node__ -typedef enum tnet_proxy_node_param_type_e -{ +typedef enum tnet_proxy_node_param_type_e { tnet_proxy_node_param_type_null = 0, tnet_proxy_node_param_type_destination_address, tnet_proxy_node_param_type_proxy_address, @@ -85,17 +84,16 @@ tnet_proxy_node_param_type_t; #endif /* TNET_UNDER_APPLE */ /** Virtual table used to define a proxy node plugin */ -typedef struct tnet_proxy_node_plugin_def_s -{ +typedef struct tnet_proxy_node_plugin_def_s { //! object definition used to create an instance of the plugin const tsk_object_def_t* objdef; - + //! plugin type enum tnet_proxy_type_e type; - + //! full description (usefull for debugging) const char* desc; - + int (* configure) (tnet_proxy_node_t* self, ...); int (* start_handshaking) (tnet_proxy_node_t* self); int (* set_handshaking_data) (tnet_proxy_node_t* self, const void* data_ptr, tsk_size_t data_size); diff --git a/tinyNET/src/tnet_proxydetect.c b/tinyNET/src/tnet_proxydetect.c index 162985c..af0bec7 100755 --- a/tinyNET/src/tnet_proxydetect.c +++ b/tinyNET/src/tnet_proxydetect.c @@ -29,29 +29,28 @@ static tsk_object_t* _tnet_proxyinfo_ctor(tsk_object_t * self, va_list * app) { tnet_proxyinfo_t *info = (tnet_proxyinfo_t *)self; if (info) { - + } return self; } static tsk_object_t* _tnet_proxyinfo_dtor(tsk_object_t * self) { tnet_proxyinfo_t *info = (tnet_proxyinfo_t *)self; - if (info){ + if (info) { TSK_FREE(info->autoconfig_url); TSK_FREE(info->bypass_list); TSK_FREE(info->hostname); TSK_FREE(info->username); TSK_FREE(info->password); } - + return self; } -static const tsk_object_def_t tnet_proxyinfo_def_s = -{ +static const tsk_object_def_t tnet_proxyinfo_def_s = { sizeof(tnet_proxyinfo_t), _tnet_proxyinfo_ctor, _tnet_proxyinfo_dtor, - tsk_null, + tsk_null, }; const tsk_object_def_t *tnet_proxyinfo_def_t = &tnet_proxyinfo_def_s; @@ -62,7 +61,7 @@ tnet_proxyinfo_t* tnet_proxyinfo_create() TSK_DEBUG_ERROR("Failed to creatr 'tnet_proxyinfo_t' instance"); return info; } - + return info; } @@ -121,7 +120,7 @@ tnet_proxyinfo_t* tnet_proxydetect_get_info(const char* url, tnet_socket_type_t TSK_DEBUG_ERROR("CFNetworkCopySystemProxySettings returned nil"); goto resolve_done; } - + cfProxies = CFNetworkCopyProxiesForURL(cfTargetUrl, cfProxySettings); if (!cfProxies) { TSK_DEBUG_ERROR("CFNetworkCopyProxiesForURL returned 0-array"); @@ -129,8 +128,8 @@ tnet_proxyinfo_t* tnet_proxydetect_get_info(const char* url, tnet_socket_type_t } // find best proxy _appl_find_best_proxy(cfTargetUrl, cfProxies, &_info); - - + + resolve_done: if (cfUrl) { CFRelease(cfUrl); @@ -144,7 +143,7 @@ resolve_done: if (cfProxies) { CFRelease(cfProxies); } - + if (_appl_proxyinfo_is_valid(&_info)) { info = tnet_proxyinfo_create(); if (info) { @@ -157,7 +156,7 @@ resolve_done: } } _appl_proxyinfo_release(&_info); - + return info; } @@ -165,8 +164,8 @@ static tsk_bool_t _appl_proxyinfo_is_valid(const appl_proxyinfo_xt * info) { if (info) { return info->port - && info->type && !CFEqual(info->type, kCFProxyTypeNone) - && info->host && CFStringGetLength(info->host) > 0 && CFStringCompare(info->host, CFSTR("127.0.0.1"), 0) != kCFCompareEqualTo; + && info->type && !CFEqual(info->type, kCFProxyTypeNone) + && info->host && CFStringGetLength(info->host) > 0 && CFStringCompare(info->host, CFSTR("127.0.0.1"), 0) != kCFCompareEqualTo; } return tsk_false; } @@ -201,7 +200,8 @@ static void _ProxyAutoConfigurationResultCallback(void *client, CFArrayRef proxy CFTypeRef* cfResult = (CFTypeRef*)client; if (error != NULL) { *cfResult = CFRetain(error); - } else { + } + else { *cfResult = CFRetain(proxyList); } CFRunLoopStop(CFRunLoopGetCurrent()); @@ -212,14 +212,14 @@ static void _appl_find_best_proxy(CFURLRef cfTargetURL, CFArrayRef _cfProxies, a CFDictionaryRef cfProxy; CFIndex index = 0; CFIndex count = CFArrayGetCount(_cfProxies); - + while (index < count && (cfProxy = CFArrayGetValueAtIndex(_cfProxies, index++)) && !_appl_proxyinfo_is_valid(_proxyInfo)) { _appl_proxyinfo_release(_proxyInfo); CFStringRef cfProxyType = CFDictionaryGetValue(cfProxy, (const void*)kCFProxyTypeKey); if (!cfProxyType) { continue; } - + TSK_DEBUG_INFO("Found at %li proxy type = %s", (index - 1), CFStringGetCStringPtr(cfProxyType, kCFStringEncodingUTF8)); if (CFEqual(cfProxyType, kCFProxyTypeNone)) { continue; @@ -255,9 +255,9 @@ static void _appl_find_best_proxy(CFURLRef cfTargetURL, CFArrayRef _cfProxies, a CFTypeRef cfResult = NULL; CFStreamClientContext context = { 0, &cfResult, NULL, NULL, NULL }; CFRunLoopSourceRef cfrunLoop = CFNetworkExecuteProxyAutoConfigurationURL(cfPACUrl, - cfTargetURL, - _ProxyAutoConfigurationResultCallback, - &context); + cfTargetURL, + _ProxyAutoConfigurationResultCallback, + &context); if (!cfrunLoop) { TSK_DEBUG_ERROR("CFNetworkExecuteProxyAutoConfigurationURL(%li, %s) failed", (index - 1), CFStringGetCStringPtr(CFURLGetString(cfPACUrl), kCFStringEncodingUTF8)); continue; diff --git a/tinyNET/src/tnet_proxydetect.h b/tinyNET/src/tnet_proxydetect.h index 23c5439..1f5597c 100755 --- a/tinyNET/src/tnet_proxydetect.h +++ b/tinyNET/src/tnet_proxydetect.h @@ -27,17 +27,17 @@ TNET_BEGIN_DECLS typedef struct tnet_proxyinfo_s { - TSK_DECLARE_OBJECT; + TSK_DECLARE_OBJECT; - tnet_proxy_type_t type; - char* autoconfig_url; - tsk_bool_t autodetect; - char* bypass_list; + tnet_proxy_type_t type; + char* autoconfig_url; + tsk_bool_t autodetect; + char* bypass_list; char* hostname; tnet_socket_type_t socket_type; tnet_port_t port; - char* username; - char* password; + char* username; + char* password; } tnet_proxyinfo_t; diff --git a/tinyNET/src/tnet_socket.c b/tinyNET/src/tnet_socket.c index 2d104d1..5f071de 100755 --- a/tinyNET/src/tnet_socket.c +++ b/tinyNET/src/tnet_socket.c @@ -93,133 +93,133 @@ static int tnet_socket_close(tnet_socket_t *sock); */ tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_, tnet_socket_type_t type, tsk_bool_t nonblocking, tsk_bool_t bindsocket) { - tnet_socket_t *sock; - if ((sock = tsk_object_new(tnet_socket_def_t))) { - int status; - tsk_istr_t port; - struct addrinfo *result = tsk_null; - struct addrinfo *ptr = tsk_null; - struct addrinfo hints; - tnet_host_t local_hostname; - - sock->port = port_; - tsk_itoa(sock->port, &port); - sock->type = type; - - memset(local_hostname, 0, sizeof(local_hostname)); - - /* Get the local host name */ - if (host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host)){ - memcpy(local_hostname, host, tsk_strlen(host) > sizeof(local_hostname) - 1 ? sizeof(local_hostname) - 1 : tsk_strlen(host)); - } - else{ - if (TNET_SOCKET_TYPE_IS_IPV6(sock->type)){ - memcpy(local_hostname, "::", 2); - } - else { - memcpy(local_hostname, "0.0.0.0", 7); - } - } - - /* hints address info structure */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock->type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock->type) ? AF_INET6 : AF_INET); - hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? SOCK_STREAM : SOCK_DGRAM; - hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? IPPROTO_TCP : IPPROTO_UDP; - hints.ai_flags = AI_PASSIVE + tnet_socket_t *sock; + if ((sock = tsk_object_new(tnet_socket_def_t))) { + int status; + tsk_istr_t port; + struct addrinfo *result = tsk_null; + struct addrinfo *ptr = tsk_null; + struct addrinfo hints; + tnet_host_t local_hostname; + + sock->port = port_; + tsk_itoa(sock->port, &port); + sock->type = type; + + memset(local_hostname, 0, sizeof(local_hostname)); + + /* Get the local host name */ + if (host != TNET_SOCKET_HOST_ANY && !tsk_strempty(host)) { + memcpy(local_hostname, host, tsk_strlen(host) > sizeof(local_hostname) - 1 ? sizeof(local_hostname) - 1 : tsk_strlen(host)); + } + else { + if (TNET_SOCKET_TYPE_IS_IPV6(sock->type)) { + memcpy(local_hostname, "::", 2); + } + else { + memcpy(local_hostname, "0.0.0.0", 7); + } + } + + /* hints address info structure */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(sock->type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(sock->type) ? AF_INET6 : AF_INET); + hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? SOCK_STREAM : SOCK_DGRAM; + hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(sock->type) ? IPPROTO_TCP : IPPROTO_UDP; + hints.ai_flags = AI_PASSIVE #if !TNET_UNDER_WINDOWS || _WIN32_WINNT>=0x600 - | AI_ADDRCONFIG + | AI_ADDRCONFIG #endif - ; - - /* Performs getaddrinfo */ - if ((status = tnet_getaddrinfo(local_hostname, port, &hints, &result))) { - TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]", - hints.ai_family, local_hostname, port, tnet_gai_strerror(status)); - goto bail; - } - - /* Find our address. */ - for (ptr = result; ptr; ptr = ptr->ai_next){ - sock->fd = (tnet_fd_t)tnet_soccket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); - if (ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET){ - continue; - } - /* To avoid "Address already in use" error - * Check issue 368 (https://code.google.com/p/doubango/issues/detail?id=368) to understand why it's not used for UDP/DTLS. - */ - // - if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) { - if ((status = tnet_sockfd_reuseaddr(sock->fd, 1))) { - // do not break...continue - } - } - - if (bindsocket){ - /* Bind the socket */ - if ((status = bind(sock->fd, ptr->ai_addr, (int)ptr->ai_addrlen))){ - TNET_PRINT_LAST_ERROR("bind to [%s:%s]have failed", local_hostname, port); - tnet_socket_close(sock); - continue; - } - - /* Get local IP string. */ - if ((status = tnet_get_ip_n_port(sock->fd, tsk_true/*local*/, &sock->ip, &sock->port))) /* % */ - //if((status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST))) - { - TNET_PRINT_LAST_ERROR("Failed to get local IP and port."); - tnet_socket_close(sock); - continue; - } - } - - /* sets the real socket type (if ipv46) */ - if (ptr->ai_family == AF_INET6) { - TNET_SOCKET_TYPE_SET_IPV6Only(sock->type); - } - else { - TNET_SOCKET_TYPE_SET_IPV4Only(sock->type); - } - break; - } - - /* Check socket validity. */ - if (!TNET_SOCKET_IS_VALID(sock)) { - TNET_PRINT_LAST_ERROR("Invalid socket."); - goto bail; - } + ; + + /* Performs getaddrinfo */ + if ((status = tnet_getaddrinfo(local_hostname, port, &hints, &result))) { + TNET_PRINT_LAST_ERROR("tnet_getaddrinfo(family=%d, hostname=%s and port=%s) failed: [%s]", + hints.ai_family, local_hostname, port, tnet_gai_strerror(status)); + goto bail; + } + + /* Find our address. */ + for (ptr = result; ptr; ptr = ptr->ai_next) { + sock->fd = (tnet_fd_t)tnet_soccket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + if (ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET) { + continue; + } + /* To avoid "Address already in use" error + * Check issue 368 (https://code.google.com/p/doubango/issues/detail?id=368) to understand why it's not used for UDP/DTLS. + */ + // + if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) { + if ((status = tnet_sockfd_reuseaddr(sock->fd, 1))) { + // do not break...continue + } + } + + if (bindsocket) { + /* Bind the socket */ + if ((status = bind(sock->fd, ptr->ai_addr, (int)ptr->ai_addrlen))) { + TNET_PRINT_LAST_ERROR("bind to [%s:%s]have failed", local_hostname, port); + tnet_socket_close(sock); + continue; + } + + /* Get local IP string. */ + if ((status = tnet_get_ip_n_port(sock->fd, tsk_true/*local*/, &sock->ip, &sock->port))) /* % */ + //if((status = tnet_getnameinfo(ptr->ai_addr, ptr->ai_addrlen, sock->ip, sizeof(sock->ip), 0, 0, NI_NUMERICHOST))) + { + TNET_PRINT_LAST_ERROR("Failed to get local IP and port."); + tnet_socket_close(sock); + continue; + } + } + + /* sets the real socket type (if ipv46) */ + if (ptr->ai_family == AF_INET6) { + TNET_SOCKET_TYPE_SET_IPV6Only(sock->type); + } + else { + TNET_SOCKET_TYPE_SET_IPV4Only(sock->type); + } + break; + } + + /* Check socket validity. */ + if (!TNET_SOCKET_IS_VALID(sock)) { + TNET_PRINT_LAST_ERROR("Invalid socket."); + goto bail; + } #if TNET_UNDER_IPHONE || TNET_UNDER_IPHONE_SIMULATOR - /* disable SIGPIPE signal */ - { - int yes = 1; - if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))){ - TNET_PRINT_LAST_ERROR("setsockopt(SO_NOSIGPIPE) have failed."); - } - } + /* disable SIGPIPE signal */ + { + int yes = 1; + if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))) { + TNET_PRINT_LAST_ERROR("setsockopt(SO_NOSIGPIPE) have failed."); + } + } #endif /* TNET_UNDER_IPHONE */ - /* Sets the socket to nonblocking mode */ - if(nonblocking){ - if((status = tnet_sockfd_set_nonblocking(sock->fd))){ - goto bail; - } - } - - bail: - /* Free addrinfo */ - tnet_freeaddrinfo(result); - - /* Close socket if failed. */ - if (status){ - if (TNET_SOCKET_IS_VALID(sock)){ - tnet_socket_close(sock); - } - return tsk_null; - } -} + /* Sets the socket to nonblocking mode */ + if(nonblocking) { + if((status = tnet_sockfd_set_nonblocking(sock->fd))) { + goto bail; + } + } + +bail: + /* Free addrinfo */ + tnet_freeaddrinfo(result); - return sock; + /* Close socket if failed. */ + if (status) { + if (TNET_SOCKET_IS_VALID(sock)) { + tnet_socket_close(sock); + } + return tsk_null; + } + } + + return sock; } /**@ingroup tnet_socket_group @@ -232,7 +232,7 @@ tnet_socket_t* tnet_socket_create_2(const char* host, tnet_port_t port_, tnet_so */ tnet_socket_t* tnet_socket_create(const char* host, tnet_port_t port, tnet_socket_type_t type) { - return tnet_socket_create_2(host, port, type, tsk_true, tsk_true); + return tnet_socket_create_2(host, port, type, tsk_true, tsk_true); } /**@ingroup tnet_socket_group @@ -240,15 +240,15 @@ tnet_socket_t* tnet_socket_create(const char* host, tnet_port_t port, tnet_socke */ int tnet_socket_send_stream(tnet_socket_t* self, const void* data, tsk_size_t size) { - if (!self || self->fd == TNET_INVALID_FD || !data || !size || !TNET_SOCKET_TYPE_IS_STREAM(self->type)) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (self->tlshandle && (TNET_SOCKET_TYPE_IS_TLS(self->type) || TNET_SOCKET_TYPE_IS_WSS(self->type))) { - return tnet_tls_socket_send(self->tlshandle, data, size) == 0 ? (int)size : -1; // returns zero on success - } - - return (int)tnet_sockfd_send(self->fd, data, size, 0); + if (!self || self->fd == TNET_INVALID_FD || !data || !size || !TNET_SOCKET_TYPE_IS_STREAM(self->type)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (self->tlshandle && (TNET_SOCKET_TYPE_IS_TLS(self->type) || TNET_SOCKET_TYPE_IS_WSS(self->type))) { + return tnet_tls_socket_send(self->tlshandle, data, size) == 0 ? (int)size : -1; // returns zero on success + } + + return (int)tnet_sockfd_send(self->fd, data, size, 0); } /**@ingroup tnet_socket_group @@ -264,7 +264,7 @@ int tnet_socket_handle_brokenpipe(tnet_socket_t* self) } fd_old = self->fd; fd_new = TNET_INVALID_FD; - + // close old fd ret = tnet_sockfd_close(&self->fd); // try to create an fd binding to the same address @@ -277,7 +277,7 @@ int tnet_socket_handle_brokenpipe(tnet_socket_t* self) /* disable SIGPIPE signal */ { int yes = 1; - if (setsockopt(fd_new, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))){ + if (setsockopt(fd_new, SOL_SOCKET, SO_NOSIGPIPE, (char*)&yes, sizeof(int))) { TNET_PRINT_LAST_ERROR("setsockopt(%d, SO_NOSIGPIPE) have failed", fd_new); } } @@ -294,7 +294,7 @@ int tnet_socket_handle_brokenpipe(tnet_socket_t* self) **/ static int tnet_socket_close(tnet_socket_t *sock) { - return tnet_sockfd_close(&(sock->fd)); + return tnet_sockfd_close(&(sock->fd)); } //================================================================================================= @@ -302,37 +302,36 @@ static int tnet_socket_close(tnet_socket_t *sock) // static tsk_object_t* tnet_socket_ctor(tsk_object_t * self, va_list * app) { - tnet_socket_t *sock = self; - if (sock){ - } - return self; + tnet_socket_t *sock = self; + if (sock) { + } + return self; } static tsk_object_t* tnet_socket_dtor(tsk_object_t * self) { - tnet_socket_t *sock = self; + tnet_socket_t *sock = self; - if (sock){ - /* Close the socket */ - if (TNET_SOCKET_IS_VALID(sock)){ - tnet_socket_close(sock); - } - /* Clean up TLS handle */ - TSK_OBJECT_SAFE_FREE(sock->tlshandle); + if (sock) { + /* Close the socket */ + if (TNET_SOCKET_IS_VALID(sock)) { + tnet_socket_close(sock); + } + /* Clean up TLS handle */ + TSK_OBJECT_SAFE_FREE(sock->tlshandle); - /* Clean up DTLS handle */ - TSK_OBJECT_SAFE_FREE(sock->dtlshandle); - } + /* Clean up DTLS handle */ + TSK_OBJECT_SAFE_FREE(sock->dtlshandle); + } - return self; + return self; } -static const tsk_object_def_t tnet_socket_def_s = -{ - sizeof(tnet_socket_t), - tnet_socket_ctor, - tnet_socket_dtor, - tsk_null, +static const tsk_object_def_t tnet_socket_def_s = { + sizeof(tnet_socket_t), + tnet_socket_ctor, + tnet_socket_dtor, + tsk_null, }; const tsk_object_def_t *tnet_socket_def_t = &tnet_socket_def_s; diff --git a/tinyNET/src/tnet_socket.h b/tinyNET/src/tnet_socket.h index 3c7dc34..daceb53 100755 --- a/tinyNET/src/tnet_socket.h +++ b/tinyNET/src/tnet_socket.h @@ -7,12 +7,12 @@ * 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. * @@ -38,9 +38,8 @@ TNET_BEGIN_DECLS -typedef enum tnet_socket_type_e -{ - tnet_socket_type_invalid = 0x0000, /**< Invalid socket.*/ +typedef enum tnet_socket_type_e { + tnet_socket_type_invalid = 0x0000, /**< Invalid socket.*/ #define TNET_SOCKET_TYPE_IPV4 (0x0001 << 0) #define TNET_SOCKET_TYPE_UDP (0x0001 << 1) @@ -50,53 +49,53 @@ typedef enum tnet_socket_type_e #define TNET_SOCKET_TYPE_SCTP (0x0001 << 5) #define TNET_SOCKET_TYPE_WS (0x0001 << 6) #define TNET_SOCKET_TYPE_WSS (0x0001 << 7) - tnet_socket_type_udp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_UDP), /**< UDP/IPv4 socket.*/ - tnet_socket_type_dtls_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_DTLS), /**< DTLS/IPv4 socket.*/ - tnet_socket_type_tcp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_TCP), /**< TCP/IPv4 socket.*/ - tnet_socket_type_tls_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_TLS), /**< TLS/IPv4 socket.*/ - tnet_socket_type_sctp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_SCTP), /**< SCTP/IPv4 socket.*/ - tnet_socket_type_ws_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_WS), /**< WebSocket/IPv4 socket.*/ - tnet_socket_type_wss_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_WSS), /**< WebSocket Secure/IPv4 socket.*/ + tnet_socket_type_udp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_UDP), /**< UDP/IPv4 socket.*/ + tnet_socket_type_dtls_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_DTLS), /**< DTLS/IPv4 socket.*/ + tnet_socket_type_tcp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_TCP), /**< TCP/IPv4 socket.*/ + tnet_socket_type_tls_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_TLS), /**< TLS/IPv4 socket.*/ + tnet_socket_type_sctp_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_SCTP), /**< SCTP/IPv4 socket.*/ + tnet_socket_type_ws_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_WS), /**< WebSocket/IPv4 socket.*/ + tnet_socket_type_wss_ipv4 = (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_WSS), /**< WebSocket Secure/IPv4 socket.*/ #define TNET_SOCKET_TYPE_IPSEC (0x0001 << 8) - tnet_socket_type_udp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv4), /**< UDP/IPSec/IPv4 socket.*/ - tnet_socket_type_dtls_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_dtls_ipv4), /**< DTLS/IPSec/IPv4 socket.*/ - tnet_socket_type_tcp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv4), /**< TCP/IPSec/IPv4 socket.*/ - tnet_socket_type_tls_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv4), /**< TLS/IPSec /IPv4socket.*/ - tnet_socket_type_sctp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv4), /**< SCTP/IPSec/IPv4 socket.*/ - tnet_socket_type_ws_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv4), /**< WS/IPSec/IPv4 socket.*/ - tnet_socket_type_wss_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv4), /**< WSS/IPSec/IPv4 socket.*/ + tnet_socket_type_udp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv4), /**< UDP/IPSec/IPv4 socket.*/ + tnet_socket_type_dtls_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_dtls_ipv4), /**< DTLS/IPSec/IPv4 socket.*/ + tnet_socket_type_tcp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv4), /**< TCP/IPSec/IPv4 socket.*/ + tnet_socket_type_tls_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv4), /**< TLS/IPSec /IPv4socket.*/ + tnet_socket_type_sctp_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv4), /**< SCTP/IPSec/IPv4 socket.*/ + tnet_socket_type_ws_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv4), /**< WS/IPSec/IPv4 socket.*/ + tnet_socket_type_wss_ipsec_ipv4 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv4), /**< WSS/IPSec/IPv4 socket.*/ #define TNET_SOCKET_TYPE_IPV6 (0x0001 << 12) - tnet_socket_type_udp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_udp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< UDP/IPv6 socket.*/ - tnet_socket_type_dtls_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_dtls_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< DTLS/IPv6 socket.*/ - tnet_socket_type_tcp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_tcp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< TCP/IPv6 socket.*/ - tnet_socket_type_tls_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_tls_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< TLS/IPv6 socket.*/ - tnet_socket_type_sctp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_sctp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< SCTP/IPv6 socket.*/ - tnet_socket_type_ws_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_ws_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< WS/IPv6 socket.*/ - tnet_socket_type_wss_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_wss_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< WSS/IPv6 socket.*/ - tnet_socket_type_udp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv6), /**< UDP/IPSec/IPv6 socket.*/ - tnet_socket_type_tcp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv6), /**< TCP/IPSec/IPv6 socket.*/ - tnet_socket_type_tls_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv6), /**< TLS/IPSec/IPv6 socket.*/ - tnet_socket_type_sctp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv6),/**< SCTP/IPSec/IPv6 socket.*/ - tnet_socket_type_ws_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv6), /**< WS/IPSec/IPv6 socket.*/ - tnet_socket_type_wss_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv6),/**< WSS/IPSec/IPv6 socket.*/ + tnet_socket_type_udp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_udp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< UDP/IPv6 socket.*/ + tnet_socket_type_dtls_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_dtls_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< DTLS/IPv6 socket.*/ + tnet_socket_type_tcp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_tcp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< TCP/IPv6 socket.*/ + tnet_socket_type_tls_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_tls_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< TLS/IPv6 socket.*/ + tnet_socket_type_sctp_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_sctp_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< SCTP/IPv6 socket.*/ + tnet_socket_type_ws_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_ws_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< WS/IPv6 socket.*/ + tnet_socket_type_wss_ipv6 = (TNET_SOCKET_TYPE_IPV6 | (tnet_socket_type_wss_ipv4 ^ TNET_SOCKET_TYPE_IPV4)), /**< WSS/IPv6 socket.*/ + tnet_socket_type_udp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv6), /**< UDP/IPSec/IPv6 socket.*/ + tnet_socket_type_tcp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv6), /**< TCP/IPSec/IPv6 socket.*/ + tnet_socket_type_tls_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv6), /**< TLS/IPSec/IPv6 socket.*/ + tnet_socket_type_sctp_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv6),/**< SCTP/IPSec/IPv6 socket.*/ + tnet_socket_type_ws_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv6), /**< WS/IPSec/IPv6 socket.*/ + tnet_socket_type_wss_ipsec_ipv6 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv6),/**< WSS/IPSec/IPv6 socket.*/ #define TNET_SOCKET_TYPE_IPV46 (TNET_SOCKET_TYPE_IPV4 | TNET_SOCKET_TYPE_IPV6) - tnet_socket_type_udp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_udp_ipv4 | tnet_socket_type_udp_ipv6)), /**< UDP/IPv4/6 socket.*/ - tnet_socket_type_dtls_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_dtls_ipv4 | tnet_socket_type_dtls_ipv6)), /**< DTLS/IPv4/6 socket.*/ - tnet_socket_type_tcp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_tcp_ipv4 | tnet_socket_type_tcp_ipv6)), /**< TCP/IPv4/6 socket.*/ - tnet_socket_type_tls_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_tls_ipv4 | tnet_socket_type_tls_ipv6)), /**< TLS/IPv4/6 socket.*/ - tnet_socket_type_sctp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_sctp_ipv4 | tnet_socket_type_sctp_ipv6)), /**< SCTP/IPv4/6 socket.*/ - tnet_socket_type_ws_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_ws_ipv4 | tnet_socket_type_ws_ipv6)), /**< WS/IPv4/6 socket.*/ - tnet_socket_type_wss_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_wss_ipv4 | tnet_socket_type_wss_ipv6)), /**< WSS/IPv4/6 socket.*/ - tnet_socket_type_udp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv46), /**< UDP/IPSec/IPv4/6 socket.*/ - tnet_socket_type_dtls_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_dtls_ipv46), /**< DTLS/IPSec/IPv4/6 socket.*/ - tnet_socket_type_tcp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv46), /**< TCP/IPSec/IPv4/6 socket.*/ - tnet_socket_type_tls_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv46), /**< TLS/IPSec/IPv4/6 socket.*/ - tnet_socket_type_sctp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv46),/**< SCTP/IPSec/IPv4/6 socket.*/ - tnet_socket_type_ws_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv46),/**< WS/IPSec/IPv4/6 socket.*/ - tnet_socket_type_wss_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv46),/**< WSS/IPSec/IPv4/6 socket.*/ + tnet_socket_type_udp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_udp_ipv4 | tnet_socket_type_udp_ipv6)), /**< UDP/IPv4/6 socket.*/ + tnet_socket_type_dtls_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_dtls_ipv4 | tnet_socket_type_dtls_ipv6)), /**< DTLS/IPv4/6 socket.*/ + tnet_socket_type_tcp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_tcp_ipv4 | tnet_socket_type_tcp_ipv6)), /**< TCP/IPv4/6 socket.*/ + tnet_socket_type_tls_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_tls_ipv4 | tnet_socket_type_tls_ipv6)), /**< TLS/IPv4/6 socket.*/ + tnet_socket_type_sctp_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_sctp_ipv4 | tnet_socket_type_sctp_ipv6)), /**< SCTP/IPv4/6 socket.*/ + tnet_socket_type_ws_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_ws_ipv4 | tnet_socket_type_ws_ipv6)), /**< WS/IPv4/6 socket.*/ + tnet_socket_type_wss_ipv46 = (TNET_SOCKET_TYPE_IPV46 | (tnet_socket_type_wss_ipv4 | tnet_socket_type_wss_ipv6)), /**< WSS/IPv4/6 socket.*/ + tnet_socket_type_udp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_udp_ipv46), /**< UDP/IPSec/IPv4/6 socket.*/ + tnet_socket_type_dtls_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_dtls_ipv46), /**< DTLS/IPSec/IPv4/6 socket.*/ + tnet_socket_type_tcp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tcp_ipv46), /**< TCP/IPSec/IPv4/6 socket.*/ + tnet_socket_type_tls_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_tls_ipv46), /**< TLS/IPSec/IPv4/6 socket.*/ + tnet_socket_type_sctp_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_sctp_ipv46),/**< SCTP/IPSec/IPv4/6 socket.*/ + tnet_socket_type_ws_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_ws_ipv46),/**< WS/IPSec/IPv4/6 socket.*/ + tnet_socket_type_wss_ipsec_ipv46 = (TNET_SOCKET_TYPE_IPSEC | tnet_socket_type_wss_ipv46),/**< WSS/IPSec/IPv4/6 socket.*/ } tnet_socket_type_t; @@ -165,17 +164,16 @@ tnet_socket_type_t; /** * Socket. */ -typedef struct tnet_socket_s -{ - TSK_DECLARE_OBJECT; - - tnet_socket_type_t type; - tnet_fd_t fd; - tnet_ip_t ip; - uint16_t port; - - tnet_tls_socket_handle_t* tlshandle; - tnet_dtls_socket_handle_t* dtlshandle; +typedef struct tnet_socket_s { + TSK_DECLARE_OBJECT; + + tnet_socket_type_t type; + tnet_fd_t fd; + tnet_ip_t ip; + uint16_t port; + + tnet_tls_socket_handle_t* tlshandle; + tnet_dtls_socket_handle_t* dtlshandle; } tnet_socket_t; diff --git a/tinyNET/src/tnet_transport.c b/tinyNET/src/tnet_transport.c index 7d26d08..fe9810e 100755 --- a/tinyNET/src/tnet_transport.c +++ b/tinyNET/src/tnet_transport.c @@ -56,7 +56,7 @@ static int _tnet_transport_dtls_cb(const void* usrdata, tnet_dtls_socket_event_t static int _tnet_transport_ssl_init(tnet_transport_t* transport) { - if (!transport){ + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -65,20 +65,20 @@ static int _tnet_transport_ssl_init(tnet_transport_t* transport) tnet_socket_type_t type = tnet_transport_get_type(transport); tsk_bool_t is_tls = (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)); tsk_bool_t is_dtls = transport->dtls.enabled/* TNET_SOCKET_TYPE_IS_DTLS(type)*/; // DTLS-RTP, not raw DTLS - if (is_dtls && !tnet_dtls_is_supported()){ + if (is_dtls && !tnet_dtls_is_supported()) { TSK_DEBUG_ERROR("Requesting to create DTLS transport but source code not built with support for this feature"); return -1; } - if (is_tls && !tnet_tls_is_supported()){ + if (is_tls && !tnet_tls_is_supported()) { TSK_DEBUG_ERROR("Requesting to create TLS transport but source code not built with support for this feature"); return -1; } - if ((transport->tls.enabled = is_tls)){ - if (!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))){ + if ((transport->tls.enabled = is_tls)) { + if (!transport->tls.ctx_client && !(transport->tls.ctx_client = SSL_CTX_new(SSLv23_client_method()))) { TSK_DEBUG_ERROR("Failed to create SSL client context"); return -2; } - if (!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))){ + if (!transport->tls.ctx_server && !(transport->tls.ctx_server = SSL_CTX_new(SSLv23_server_method()))) { TSK_DEBUG_ERROR("Failed to create SSL server context"); return -3; } @@ -86,56 +86,56 @@ static int _tnet_transport_ssl_init(tnet_transport_t* transport) SSL_CTX_set_mode(transport->tls.ctx_server, SSL_MODE_AUTO_RETRY); SSL_CTX_set_verify(transport->tls.ctx_server, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() SSL_CTX_set_verify(transport->tls.ctx_client, SSL_VERIFY_NONE, tsk_null); // to be updated by tnet_transport_tls_set_certs() - if (SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0){ + if (SSL_CTX_set_cipher_list(transport->tls.ctx_client, TNET_CIPHER_LIST) <= 0 || SSL_CTX_set_cipher_list(transport->tls.ctx_server, TNET_CIPHER_LIST) <= 0) { TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); return -4; } } #if HAVE_OPENSSL_DTLS - if ((transport->dtls.enabled = is_dtls)){ - if (!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))){ - TSK_DEBUG_ERROR("Failed to create DTLSv1 context"); - TSK_OBJECT_SAFE_FREE(transport); - return -5; - } - SSL_CTX_set_read_ahead(transport->dtls.ctx, 1); - // SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL); - // SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY); - SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs() - if (SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0){ - TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); - return -6; - } - //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP - // Up to the DTLS socket to set the default MTU value - SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_NO_QUERY_MTU); - SSL_CTX_ctrl(transport->dtls.ctx, SSL_CTRL_SET_MTU, TNET_DTLS_MTU - 28, NULL); - - transport->dtls.activated = tsk_true; - } + if ((transport->dtls.enabled = is_dtls)) { + if (!transport->dtls.ctx && !(transport->dtls.ctx = SSL_CTX_new(DTLSv1_method()))) { + TSK_DEBUG_ERROR("Failed to create DTLSv1 context"); + TSK_OBJECT_SAFE_FREE(transport); + return -5; + } + SSL_CTX_set_read_ahead(transport->dtls.ctx, 1); + // SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_ALL); + // SSL_CTX_set_mode(transport->dtls.ctx, SSL_MODE_AUTO_RETRY); + SSL_CTX_set_verify(transport->dtls.ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, tsk_null); // to be updated by tnet_transport_tls_set_certs() + if (SSL_CTX_set_cipher_list(transport->dtls.ctx, TNET_CIPHER_LIST) <= 0) { + TSK_DEBUG_ERROR("SSL_CTX_set_cipher_list failed [%s]", ERR_error_string(ERR_get_error(), tsk_null)); + return -6; + } + //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP + // Up to the DTLS socket to set the default MTU value + SSL_CTX_set_options(transport->dtls.ctx, SSL_OP_NO_QUERY_MTU); + SSL_CTX_ctrl(transport->dtls.ctx, SSL_CTRL_SET_MTU, TNET_DTLS_MTU - 28, NULL); + + transport->dtls.activated = tsk_true; + } #endif /* HAVE_OPENSSL_DTLS */ } #endif /* HAVE_OPENSSL */ - + return 0; } static int _tnet_transport_ssl_deinit(tnet_transport_t* transport) { - if (!transport){ + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } #if HAVE_OPENSSL - if (transport->tls.ctx_client){ + if (transport->tls.ctx_client) { SSL_CTX_free(transport->tls.ctx_client); transport->tls.ctx_client = tsk_null; } - if (transport->tls.ctx_server){ + if (transport->tls.ctx_server) { SSL_CTX_free(transport->tls.ctx_server); transport->tls.ctx_server = tsk_null; } - if (transport->dtls.ctx){ + if (transport->dtls.ctx) { SSL_CTX_free(transport->dtls.ctx); transport->dtls.ctx = tsk_null; } @@ -146,63 +146,63 @@ static int _tnet_transport_ssl_deinit(tnet_transport_t* transport) tnet_transport_t* tnet_transport_create(const char* host, tnet_port_t port, tnet_socket_type_t type, const char* description) { tnet_transport_t* transport; - - if ((transport = tsk_object_new(tnet_transport_def_t))){ + + if ((transport = tsk_object_new(tnet_transport_def_t))) { transport->description = tsk_strdup(description); transport->local_host = tsk_strdup(host); transport->req_local_port = port; transport->type = type; transport->context = tnet_transport_context_create(); - - if ((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))){ + + if ((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))) { transport->local_ip = tsk_strdup(transport->master->ip); transport->bind_local_port = transport->master->port; } - else{ + else { TSK_DEBUG_ERROR("Failed to create master socket"); TSK_OBJECT_SAFE_FREE(transport); } - - if (_tnet_transport_ssl_init(transport) != 0){ + + if (_tnet_transport_ssl_init(transport) != 0) { TSK_DEBUG_ERROR("Failed to initialize TLS and/or DTLS caps"); TSK_OBJECT_SAFE_FREE(transport); } // set priority tsk_runnable_set_priority(TSK_RUNNABLE(transport), TSK_THREAD_PRIORITY_TIME_CRITICAL); } - + return transport; } tnet_transport_t* tnet_transport_create_2(tnet_socket_t *master, const char* description) { tnet_transport_t* transport; - if (!master){ + if (!master) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - - if ((transport = tsk_object_new(tnet_transport_def_t))){ + + if ((transport = tsk_object_new(tnet_transport_def_t))) { transport->description = tsk_strdup(description); transport->local_host = tsk_strdup(master->ip); transport->req_local_port = master->port; transport->type = master->type; - + transport->master = tsk_object_ref(master); transport->local_ip = tsk_strdup(transport->master->ip); transport->bind_local_port = transport->master->port; - + transport->context = tnet_transport_context_create(); - - if (_tnet_transport_ssl_init(transport) != 0){ + + if (_tnet_transport_ssl_init(transport) != 0) { TSK_DEBUG_ERROR("Failed to initialize TLS and/or DTLS caps"); TSK_OBJECT_SAFE_FREE(transport); } - + // set priority tsk_runnable_set_priority(TSK_RUNNABLE(transport), TSK_THREAD_PRIORITY_TIME_CRITICAL); } - + return transport; } @@ -215,53 +215,53 @@ int tnet_transport_tls_set_certs(tnet_transport_handle_t *handle, const char* ca { tnet_transport_t *transport = handle; static const char* ssl_password = tsk_null; - + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + tsk_strupdate(&transport->tls.ca, ca); tsk_strupdate(&transport->tls.pvk, pvk); tsk_strupdate(&transport->tls.pbk, pbk); transport->tls.verify = verify; - + #if HAVE_OPENSSL { int32_t i, ret; SSL_CTX* contexts[3] = { tsk_null }; - + /* init DTLS/TLS contexts */ - if ((ret = _tnet_transport_ssl_init(transport))){ + if ((ret = _tnet_transport_ssl_init(transport))) { return ret; } - - if (transport->tls.enabled){ + + if (transport->tls.enabled) { contexts[0] = transport->tls.ctx_client; contexts[1] = transport->tls.ctx_server; } - if (transport->dtls.enabled){ + if (transport->dtls.enabled) { contexts[2] = transport->dtls.ctx; /* Reset fingerprints */ memset(transport->dtls.fingerprints, 0, sizeof(transport->dtls.fingerprints)); } - - for (i = 0; i < sizeof(contexts) / sizeof(contexts[0]); ++i){ - if (!contexts[i]){ + + for (i = 0; i < sizeof(contexts) / sizeof(contexts[0]); ++i) { + if (!contexts[i]) { continue; } SSL_CTX_set_verify(contexts[i], transport->tls.verify ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : SSL_VERIFY_NONE, tsk_null); - if (!tsk_strnullORempty(transport->tls.pbk) || !tsk_strnullORempty(transport->tls.pvk) || !tsk_strnullORempty(transport->tls.ca)){ + if (!tsk_strnullORempty(transport->tls.pbk) || !tsk_strnullORempty(transport->tls.pvk) || !tsk_strnullORempty(transport->tls.ca)) { /* Sets Public key (cert) */ if (!tsk_strnullORempty(transport->tls.pbk) && (ret = SSL_CTX_use_certificate_file(contexts[i], transport->tls.pbk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_certificate_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); return -3; } /*Sets the password of the private key*/ - if (!tsk_strnullORempty(ssl_password)){ + if (!tsk_strnullORempty(ssl_password)) { SSL_CTX_set_default_passwd_cb_userdata(contexts[i], (void*)ssl_password); } - + /* Sets Private key (cert) */ if (!tsk_strnullORempty(transport->tls.pvk) && (ret = SSL_CTX_use_PrivateKey_file(contexts[i], transport->tls.pvk, SSL_FILETYPE_PEM)) != 1) { TSK_DEBUG_ERROR("SSL_CTX_use_PrivateKey_file failed [%d,%s]", ret, ERR_error_string(ERR_get_error(), tsk_null)); @@ -281,47 +281,46 @@ int tnet_transport_tls_set_certs(tnet_transport_handle_t *handle, const char* ca } } #endif /* HAVE_OPENSSL */ - + return 0; } int tnet_transport_start(tnet_transport_handle_t* handle) { int ret = -1; - if (handle){ + if (handle) { tnet_transport_t *transport = handle; - + /* prepare transport */ - if ((ret = tnet_transport_prepare(transport))){ + if ((ret = tnet_transport_prepare(transport))) { TSK_DEBUG_ERROR("Failed to prepare transport."); goto bail; } - + /* start transport */ TSK_RUNNABLE(transport)->run = run; - if ((ret = tsk_runnable_start(TSK_RUNNABLE(transport), tnet_transport_event_def_t))){ + if ((ret = tsk_runnable_start(TSK_RUNNABLE(transport), tnet_transport_event_def_t))) { TSK_DEBUG_ERROR("Failed to start transport."); goto bail; } } - else{ + else { TSK_DEBUG_ERROR("NULL transport object."); } - + bail: return ret; } int tnet_transport_issecure(const tnet_transport_handle_t *handle) { - if (handle) - { + if (handle) { const tnet_transport_t *transport = handle; - if (transport->master){ + if (transport->master) { return TNET_SOCKET_TYPE_IS_SECURE(transport->master->type); } } - else{ + else { TSK_DEBUG_ERROR("NULL transport object."); } return 0; @@ -329,11 +328,11 @@ int tnet_transport_issecure(const tnet_transport_handle_t *handle) const char* tnet_transport_get_description(const tnet_transport_handle_t *handle) { - if (handle){ + if (handle) { const tnet_transport_t *transport = handle; return transport->description; } - else{ + else { TSK_DEBUG_ERROR("NULL transport object."); return tsk_null; } @@ -341,10 +340,10 @@ const char* tnet_transport_get_description(const tnet_transport_handle_t *handle int tnet_transport_get_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_ip_t *ip, tnet_port_t *port) { - if (handle){ + if (handle) { return tnet_get_ip_n_port(fd, tsk_true/*local*/, ip, port); } - else{ + else { TSK_DEBUG_ERROR("NULL transport object."); } return -1; @@ -353,17 +352,17 @@ int tnet_transport_get_ip_n_port(const tnet_transport_handle_t *handle, tnet_fd_ int tnet_transport_get_ip_n_port_2(const tnet_transport_handle_t *handle, tnet_ip_t *ip, tnet_port_t *port) { const tnet_transport_t *transport = handle; - if (transport){ + if (transport) { // do not check the master, let the application die if "null" - if (ip){ + if (ip) { memcpy(*ip, transport->master->ip, sizeof(transport->master->ip)); } - if (port){ + if (port) { *port = transport->master->port; } return 0; } - else{ + else { TSK_DEBUG_ERROR("NULL transport object."); return -1; } @@ -385,27 +384,27 @@ int tnet_transport_get_public_ip_n_port(const tnet_transport_handle_t *handle, t tsk_bool_t stun_ok = tsk_false; struct tnet_nat_ctx_s* natt_ctx; const tnet_transport_t *transport = handle; - if (!transport){ + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (TNET_SOCKET_TYPE_IS_DGRAM(transport->type) && (natt_ctx = tsk_object_ref(transport->natt_ctx))) { tnet_stun_binding_id_t bind_id = kStunBindingInvalidId; // if the socket is already monitored by the transport we should pause because both the transport and // NAT binder will try to read from it - + // Pause the soket tnet_transport_pause_socket(transport, fd, tsk_true); // Performs STUN binding bind_id = tnet_nat_stun_bind(transport->natt_ctx, fd); // Resume the socket tnet_transport_pause_socket(transport, fd, tsk_false); - + if (bind_id != kStunBindingInvalidId) { char* public_ip = tsk_null; - if (tnet_nat_stun_get_reflexive_address(transport->natt_ctx, bind_id, &public_ip, port) == 0){ - if (ip && public_ip){ + if (tnet_nat_stun_get_reflexive_address(transport->natt_ctx, bind_id, &public_ip, port) == 0) { + if (ip && public_ip) { tsk_size_t ip_len = tsk_strlen(public_ip); memcpy(ip, public_ip, ip_len > sizeof(*ip) ? sizeof(*ip) : ip_len); } @@ -416,44 +415,44 @@ int tnet_transport_get_public_ip_n_port(const tnet_transport_handle_t *handle, t } tsk_object_unref(natt_ctx); } - - if (!stun_ok){ - if (fd == TNET_INVALID_FD && transport->local_ip){ + + if (!stun_ok) { + if (fd == TNET_INVALID_FD && transport->local_ip) { memcpy(*ip, transport->local_ip, TSK_MIN(sizeof(tnet_ip_t), tsk_strlen(transport->local_ip))); *port = transport->bind_local_port; return 0; } - else{ + else { return tnet_transport_get_ip_n_port(handle, fd, ip, port); } } - + return 0; } const char* tnet_transport_dtls_get_local_fingerprint(const tnet_transport_handle_t *handle, tnet_dtls_hash_type_t hash) { const tnet_transport_t *transport = handle; - - if (!transport){ + + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return tsk_null; } - - if (!transport->dtls.enabled){ + + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return tsk_null; } - if (hash > sizeof(transport->dtls.fingerprints) / sizeof(transport->dtls.fingerprints[0])){ + if (hash > sizeof(transport->dtls.fingerprints) / sizeof(transport->dtls.fingerprints[0])) { TSK_DEBUG_ERROR("%d not valid for fingerprint hash", hash); return tsk_null; } - if (tsk_strnullORempty(transport->tls.pbk)){ + if (tsk_strnullORempty(transport->tls.pbk)) { TSK_DEBUG_ERROR("No certificate for which to get fingerprint"); return tsk_null; } - - if (tnet_dtls_get_fingerprint(transport->tls.pbk, &((tnet_transport_t *)transport)->dtls.fingerprints[hash], hash) == 0){ + + if (tnet_dtls_get_fingerprint(transport->tls.pbk, &((tnet_transport_t *)transport)->dtls.fingerprints[hash], hash) == 0) { return (const char*)transport->dtls.fingerprints[hash]; } return tsk_null; @@ -465,12 +464,12 @@ const char* tnet_transport_dtls_get_local_fingerprint(const tnet_transport_handl int tnet_transport_dtls_use_srtp(tnet_transport_handle_t *handle, const char* srtp_profiles, struct tnet_socket_s** sockets, tsk_size_t sockets_count) { tnet_transport_t *transport = handle; - - if (!transport || !srtp_profiles){ + + if (!transport || !srtp_profiles) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (!transport->dtls.enabled){ + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; } @@ -479,9 +478,9 @@ int tnet_transport_dtls_use_srtp(tnet_transport_handle_t *handle, const char* sr tsk_size_t i; transport->dtls.use_srtp = tsk_true; SSL_CTX_set_tlsext_use_srtp(transport->dtls.ctx, srtp_profiles); - if (sockets){ - for (i = 0; i < sockets_count; ++i){ - if (sockets[i] && sockets[i]->dtlshandle){ + if (sockets) { + for (i = 0; i < sockets_count; ++i) { + if (sockets[i] && sockets[i]->dtlshandle) { tnet_dtls_socket_use_srtp(sockets[i]->dtlshandle); } } @@ -497,20 +496,20 @@ int tnet_transport_dtls_use_srtp(tnet_transport_handle_t *handle, const char* sr int tnet_transport_dtls_set_remote_fingerprint(tnet_transport_handle_t *handle, const tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash, struct tnet_socket_s** sockets, tsk_size_t sockets_count) { const tnet_transport_t *transport = handle; - - if (!transport || !fingerprint){ + + if (!transport || !fingerprint) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (!transport->dtls.enabled){ + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; } #if HAVE_OPENSSL_DTLS - if (sockets){ + if (sockets) { tsk_size_t i; - for (i = 0; i < sockets_count; ++i){ - if (sockets[i] && sockets[i]->dtlshandle){ + for (i = 0; i < sockets_count; ++i) { + if (sockets[i] && sockets[i]->dtlshandle) { tnet_dtls_socket_set_remote_fingerprint(sockets[i]->dtlshandle, fingerprint, hash); } } @@ -525,7 +524,7 @@ int tnet_transport_dtls_set_remote_fingerprint(tnet_transport_handle_t *handle, tsk_bool_t tnet_transport_dtls_is_enabled(const tnet_transport_handle_t *handle) { const tnet_transport_t *transport = handle; - if (!transport){ + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } @@ -545,18 +544,18 @@ int tnet_transport_dtls_set_enabled(tnet_transport_handle_t *handle, tsk_bool_t tnet_transport_t *transport = handle; tnet_socket_type_t type; int ret; - - if (!transport){ + + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } type = tnet_transport_get_type(transport); - + if (enabled & !tnet_dtls_is_supported()) { TSK_DEBUG_ERROR("Trying to enable DTLS but code source not built with this feature"); return -1; } - + if ((transport->dtls.enabled = enabled)) { if ((ret = _tnet_transport_ssl_init(transport))) { return ret; @@ -565,7 +564,7 @@ int tnet_transport_dtls_set_enabled(tnet_transport_handle_t *handle, tsk_bool_t else { ret = _tnet_transport_ssl_deinit(transport); } - + if (sockets && sockets_count) { tsk_size_t i; for (i = 0; i < sockets_count; ++i) { @@ -588,19 +587,19 @@ int tnet_transport_dtls_set_enabled(tnet_transport_handle_t *handle, tsk_bool_t } } } - + return ret; } int tnet_transport_dtls_set_setup(tnet_transport_handle_t* handle, tnet_dtls_setup_t setup, struct tnet_socket_s** sockets, tsk_size_t sockets_count) { tnet_transport_t *transport = handle; - + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; @@ -620,12 +619,12 @@ int tnet_transport_dtls_set_setup(tnet_transport_handle_t* handle, tnet_dtls_set int tnet_transport_dtls_set_store_handshakingdata(tnet_transport_handle_t* handle, tsk_bool_t handshake_storedata, struct tnet_socket_s** sockets, tsk_size_t sockets_count) { tnet_transport_t *transport = handle; - + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; @@ -646,29 +645,29 @@ int tnet_transport_dtls_do_handshake(tnet_transport_handle_t *handle, struct tne { tnet_transport_t *transport = handle; tsk_size_t i; - + if (!transport || !sockets) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; } - + if (sockets) { int ret; for (i = 0; i < sockets_count; ++i) { if (sockets[i] && sockets[i]->dtlshandle) { if ((ret = tnet_dtls_socket_do_handshake(sockets[i]->dtlshandle, - (remote_addrs && i < remote_addrs_count) ? remote_addrs[i] : tsk_null)) != 0){ + (remote_addrs && i < remote_addrs_count) ? remote_addrs[i] : tsk_null)) != 0) { return ret; } } } } - + return 0; } @@ -676,22 +675,22 @@ int tnet_transport_dtls_get_handshakingdata(tnet_transport_handle_t* handle, con { tnet_transport_t *transport = handle; tsk_size_t i; - + if (!transport || !sockets) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + if (!transport->dtls.enabled) { TSK_DEBUG_ERROR("DTLS not enabled on this transport"); return -2; } - + if (sockets) { int ret; for (i = 0; i < sockets_count; ++i) { if (sockets[i] && sockets[i]->dtlshandle) { - if ((ret = tnet_dtls_socket_get_handshakingdata(sockets[i]->dtlshandle, &data[i], &size[i])) != 0){ + if ((ret = tnet_dtls_socket_get_handshakingdata(sockets[i]->dtlshandle, &data[i], &size[i])) != 0) { return ret; } } @@ -701,13 +700,13 @@ int tnet_transport_dtls_get_handshakingdata(tnet_transport_handle_t* handle, con } } } - + return 0; } tnet_socket_type_t tnet_transport_get_type(const tnet_transport_handle_t *handle) { - if (!handle){ + if (!handle) { TSK_DEBUG_ERROR("Invalid parameter"); return tnet_socket_type_invalid; } @@ -716,7 +715,7 @@ tnet_socket_type_t tnet_transport_get_type(const tnet_transport_handle_t *handle tnet_fd_t tnet_transport_get_master_fd(const tnet_transport_handle_t *handle) { - if (!handle){ + if (!handle) { TSK_DEBUG_ERROR("Invalid parameter"); return TNET_INVALID_FD; } @@ -725,12 +724,16 @@ tnet_fd_t tnet_transport_get_master_fd(const tnet_transport_handle_t *handle) int tnet_transport_get_bytes_count(const tnet_transport_handle_t *handle, uint64_t* bytes_in, uint64_t* bytes_out) { - if (!handle){ + if (!handle) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (bytes_in) *bytes_in = ((const tnet_transport_t *)handle)->bytes_in; - if (bytes_out) *bytes_out = ((const tnet_transport_t *)handle)->bytes_out; + if (bytes_in) { + *bytes_in = ((const tnet_transport_t *)handle)->bytes_in; + } + if (bytes_out) { + *bytes_out = ((const tnet_transport_t *)handle)->bytes_out; + } return 0; } @@ -762,18 +765,18 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru tnet_port_t to_port = port; tnet_socket_type_t to_type = type; tnet_proxyinfo_t* proxy_info = tsk_null; - + if (!transport || !transport->master) { TSK_DEBUG_ERROR("Invalid transport handle"); goto bail; } - + if ((TNET_SOCKET_TYPE_IS_STREAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_STREAM(type)) || - (TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))) { + (TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type) && !TNET_SOCKET_TYPE_IS_DGRAM(type))) { TSK_DEBUG_ERROR("Master/destination types mismatch [%u/%u]", transport->master->type, type); goto bail; } - + if (use_proxy) { // auto-detect the proxy if (transport->proxy.auto_detect) { @@ -788,7 +791,7 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru proxy_info = tsk_object_ref(transport->proxy.info); } } - + use_proxy &= tnet_proxyinfo_is_valid(proxy_info); if (use_proxy) { if (tnet_proxy_node_is_nettransport_supported(proxy_info->type, type)) { @@ -807,9 +810,9 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru use_proxy = tsk_false; } } - + TSK_DEBUG_INFO("tnet_transport_connectto_3(host=%s, port=%d, type=%d, fd=%d, use_proxy=%d, to_host=%s, to_port=%d, to_type=%d, proxy_type=%d)" , host, port, type, fd, use_proxy, to_host, to_port, to_type, proxy_info ? proxy_info->type : 0); - + /* Init destination sockaddr fields */ if ((status = tnet_sockaddr_init(to_host, to_port, to_type, &to))) { TSK_DEBUG_ERROR("Invalid HOST/PORT [%s/%u]", host, port); @@ -824,7 +827,7 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru TNET_SOCKET_TYPE_SET_IPV4Only(type); } } - + /* * STREAM ==> create new socket and connect it to the remote host. * DGRAM ==> connect the master to the remote host. @@ -836,7 +839,7 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru goto bail; } } - + if ((status = tnet_sockfd_connectto(fd, (const struct sockaddr_storage *)&to))) { if (fd != transport->master->fd) { tnet_sockfd_close(&fd); @@ -866,7 +869,7 @@ tnet_fd_t tnet_transport_connectto_3(const tnet_transport_handle_t *handle, stru goto bail; } } - + bail: TSK_OBJECT_SAFE_FREE(tls_handle); TSK_OBJECT_SAFE_FREE(proxy_info); @@ -876,12 +879,12 @@ bail: int tnet_transport_set_callback(const tnet_transport_handle_t *handle, tnet_transport_cb_f callback, const void* callback_data) { tnet_transport_t *transport = (tnet_transport_t*)handle; - + if (!transport) { TSK_DEBUG_ERROR("Invalid server handle."); return -1; } - + transport->callback = callback; transport->callback_data = callback_data; return 0; @@ -912,7 +915,7 @@ int tnet_transport_set_proxy_info(tnet_transport_handle_t *handle, enum tnet_pro proxy_info->port = port; proxy_info->username = tsk_strdup(login); proxy_info->password = tsk_strdup(password); - + TSK_OBJECT_SAFE_FREE(transport->proxy.info); transport->proxy.info = proxy_info; return 0; @@ -927,7 +930,7 @@ int tnet_transport_shutdown(tnet_transport_handle_t* handle) { if (handle) { int ret; - if ((ret = tnet_transport_stop(handle)) == 0){ + if ((ret = tnet_transport_stop(handle)) == 0) { ret = tnet_transport_unprepare(handle); } return ret; @@ -947,16 +950,32 @@ static int _tnet_transport_dtls_cb(const void* usrdata, tnet_dtls_socket_event_t const struct sockaddr_storage* remote_addr; tnet_fd_t fd; tnet_transport_event_t* e; - + switch (dtls_e) { - case tnet_dtls_socket_event_type_handshake_started: t_e = event_dtls_handshake_started; break; - case tnet_dtls_socket_event_type_handshake_succeed: t_e = event_dtls_handshake_succeed; break; - case tnet_dtls_socket_event_type_handshake_failed: t_e = event_dtls_handshake_failed; break; - case tnet_dtls_socket_event_type_fingerprint_mismatch: t_e = event_dtls_fingerprint_mismatch; break; - case tnet_dtls_socket_event_type_dtls_srtp_profile_selected: t_e = event_dtls_srtp_profile_selected; break; - case tnet_dtls_socket_event_type_dtls_srtp_data: t_e = event_dtls_srtp_data; break; - case tnet_dtls_socket_event_type_error: t_e = event_dtls_error; break; - default: TSK_DEBUG_ERROR("DTLS event = %d ignored", dtls_e); return -1; + case tnet_dtls_socket_event_type_handshake_started: + t_e = event_dtls_handshake_started; + break; + case tnet_dtls_socket_event_type_handshake_succeed: + t_e = event_dtls_handshake_succeed; + break; + case tnet_dtls_socket_event_type_handshake_failed: + t_e = event_dtls_handshake_failed; + break; + case tnet_dtls_socket_event_type_fingerprint_mismatch: + t_e = event_dtls_fingerprint_mismatch; + break; + case tnet_dtls_socket_event_type_dtls_srtp_profile_selected: + t_e = event_dtls_srtp_profile_selected; + break; + case tnet_dtls_socket_event_type_dtls_srtp_data: + t_e = event_dtls_srtp_data; + break; + case tnet_dtls_socket_event_type_error: + t_e = event_dtls_error; + break; + default: + TSK_DEBUG_ERROR("DTLS event = %d ignored", dtls_e); + return -1; } remote_addr = tnet_dtls_socket_get_remote_addr(handle); fd = tnet_dtls_socket_get_fd(handle); @@ -994,11 +1013,11 @@ static void* TSK_STDCALL run(void* self) int ret = 0; tsk_list_item_t *curr; tnet_transport_t *transport = self; - + TSK_DEBUG_INFO("Transport::run(%s) - enter", transport->description); - + /* create main thread */ - if ((ret = tsk_thread_create(transport->mainThreadId, tnet_transport_mainthread, transport))){ /* More important than "tsk_runnable_start" ==> start it first. */ + if ((ret = tsk_thread_create(transport->mainThreadId, tnet_transport_mainthread, transport))) { /* More important than "tsk_runnable_start" ==> start it first. */ TSK_FREE(transport->context); /* Otherwise (tsk_thread_create is ok) will be freed when mainthread exit. */ TSK_DEBUG_FATAL("Failed to create main thread [%d]", ret); return tsk_null; @@ -1009,22 +1028,22 @@ static void* TSK_STDCALL run(void* self) #if !TNET_UNDER_APPLE ret = tsk_thread_set_priority(transport->mainThreadId[0], TSK_THREAD_PRIORITY_TIME_CRITICAL); #endif - + TSK_RUNNABLE_RUN_BEGIN(transport); - - if ((curr = TSK_RUNNABLE_POP_FIRST_SAFE(TSK_RUNNABLE(transport)))){ + + if ((curr = TSK_RUNNABLE_POP_FIRST_SAFE(TSK_RUNNABLE(transport)))) { const tnet_transport_event_t *e = (const tnet_transport_event_t*)curr->data; - + if (transport->callback) { transport->callback(e); } tsk_object_unref(curr); } - + TSK_RUNNABLE_RUN_END(transport); - + TSK_DEBUG_INFO("Transport::run(%s) - exit", transport->description); - + return tsk_null; } @@ -1037,7 +1056,7 @@ static void* TSK_STDCALL run(void* self) static tsk_object_t* tnet_transport_ctor(tsk_object_t * self, va_list * app) { tnet_transport_t *transport = self; - if (transport){ + if (transport) { } return self; } @@ -1045,7 +1064,7 @@ static tsk_object_t* tnet_transport_ctor(tsk_object_t * self, va_list * app) static tsk_object_t* tnet_transport_dtor(tsk_object_t * self) { tnet_transport_t *transport = self; - if (transport){ + if (transport) { tnet_transport_set_callback(transport, tsk_null, tsk_null); tnet_transport_shutdown(transport); TSK_OBJECT_SAFE_FREE(transport->master); @@ -1053,25 +1072,24 @@ static tsk_object_t* tnet_transport_dtor(tsk_object_t * self) TSK_OBJECT_SAFE_FREE(transport->natt_ctx); TSK_FREE(transport->local_ip); TSK_FREE(transport->local_host); - + // proxy TSK_OBJECT_SAFE_FREE(transport->proxy.info); - + // (tls and dtls) = ssl TSK_FREE(transport->tls.ca); TSK_FREE(transport->tls.pbk); TSK_FREE(transport->tls.pvk); _tnet_transport_ssl_deinit(transport); // openssl contexts - + TSK_DEBUG_INFO("*** Transport (%s) destroyed ***", transport->description); TSK_FREE(transport->description); } - + return self; } -static const tsk_object_def_t tnet_transport_def_s = -{ +static const tsk_object_def_t tnet_transport_def_s = { sizeof(tnet_transport_t), tnet_transport_ctor, tnet_transport_dtor, @@ -1087,7 +1105,7 @@ const tsk_object_def_t *tnet_transport_def_t = &tnet_transport_def_s; static tsk_object_t* tnet_transport_event_ctor(tsk_object_t * self, va_list * app) { tnet_transport_event_t *e = self; - if (e){ + if (e) { e->type = va_arg(*app, tnet_transport_event_type_t); e->callback_data = va_arg(*app, const void*); e->local_fd = va_arg(*app, tnet_fd_t); @@ -1098,15 +1116,14 @@ static tsk_object_t* tnet_transport_event_ctor(tsk_object_t * self, va_list * ap static tsk_object_t* tnet_transport_event_dtor(tsk_object_t * self) { tnet_transport_event_t *e = self; - if (e){ + if (e) { TSK_FREE(e->data); } - + return self; } -static const tsk_object_def_t tnet_transport_event_def_s = -{ +static const tsk_object_def_t tnet_transport_event_def_s = { sizeof(tnet_transport_event_t), tnet_transport_event_ctor, tnet_transport_event_dtor, diff --git a/tinyNET/src/tnet_transport.h b/tinyNET/src/tnet_transport.h index c4da35b..f86829c 100755 --- a/tinyNET/src/tnet_transport.h +++ b/tinyNET/src/tnet_transport.h @@ -41,38 +41,36 @@ TNET_BEGIN_DECLS #define TNET_TRANSPORT_CB_F(callback) ((tnet_transport_cb_f)callback) -typedef enum tnet_transport_event_type_e -{ - event_data, - event_closed, - event_error, - event_removed, - event_connected, - event_accepted, +typedef enum tnet_transport_event_type_e { + event_data, + event_closed, + event_error, + event_removed, + event_connected, + event_accepted, event_brokenpipe, // iOS: UDP sockets closed, to be restored now that the app is on foreground - event_dtls_handshake_started, - event_dtls_handshake_succeed, - event_dtls_handshake_failed, - event_dtls_fingerprint_mismatch, - event_dtls_srtp_data, - event_dtls_srtp_profile_selected, - event_dtls_error + event_dtls_handshake_started, + event_dtls_handshake_succeed, + event_dtls_handshake_failed, + event_dtls_fingerprint_mismatch, + event_dtls_srtp_data, + event_dtls_srtp_profile_selected, + event_dtls_error } tnet_transport_event_type_t; -typedef struct tnet_transport_event_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_transport_event_s { + TSK_DECLARE_OBJECT; - tnet_transport_event_type_t type; + tnet_transport_event_type_t type; - void* data; - tsk_size_t size; + void* data; + tsk_size_t size; - const void* callback_data; - tnet_fd_t local_fd; - struct sockaddr_storage remote_addr; + const void* callback_data; + tnet_fd_t local_fd; + struct sockaddr_storage remote_addr; } tnet_transport_event_t; @@ -123,52 +121,51 @@ TINYNET_API tnet_fd_t tnet_transport_get_master_fd(const tnet_transport_handle_t TINYNET_API int tnet_transport_get_bytes_count(const tnet_transport_handle_t *handle, uint64_t* bytes_in, uint64_t* bytes_out); TINYNET_API int tnet_transport_shutdown(tnet_transport_handle_t* handle); -typedef struct tnet_transport_s -{ - TSK_DECLARE_RUNNABLE; - - tnet_socket_type_t type; - char* local_ip; - char* local_host; - tnet_port_t req_local_port; // user requested local port - tnet_port_t bind_local_port; // local port on which we are listening (same as master socket) - struct tnet_nat_ctx_s* natt_ctx; - tnet_socket_t *master; - - tsk_object_t *context; - tsk_bool_t prepared; - +typedef struct tnet_transport_s { + TSK_DECLARE_RUNNABLE; + + tnet_socket_type_t type; + char* local_ip; + char* local_host; + tnet_port_t req_local_port; // user requested local port + tnet_port_t bind_local_port; // local port on which we are listening (same as master socket) + struct tnet_nat_ctx_s* natt_ctx; + tnet_socket_t *master; + + tsk_object_t *context; + tsk_bool_t prepared; + uint64_t bytes_out; uint64_t bytes_in; - //unsigned connected:1; - void* mainThreadId[1]; - - char *description; - - tnet_transport_cb_f callback; - const void* callback_data; - - /* TLS certs */ - struct { - char* ca; - char* pvk; - char* pbk; - tsk_bool_t enabled; - tsk_bool_t verify; // whether to verify client/server certificate - struct ssl_ctx_st *ctx_client; - struct ssl_ctx_st *ctx_server; - }tls; - - /* DTLS */ - struct{ - tsk_bool_t enabled; - tsk_bool_t activated; - tsk_bool_t use_srtp; - struct ssl_ctx_st *ctx; - tnet_fingerprint_t fingerprints[TNET_DTLS_HASH_TYPE_MAX]; - }dtls; - + //unsigned connected:1; + void* mainThreadId[1]; + + char *description; + + tnet_transport_cb_f callback; + const void* callback_data; + + /* TLS certs */ + struct { + char* ca; + char* pvk; + char* pbk; + tsk_bool_t enabled; + tsk_bool_t verify; // whether to verify client/server certificate + struct ssl_ctx_st *ctx_client; + struct ssl_ctx_st *ctx_server; + } tls; + + /* DTLS */ + struct { + tsk_bool_t enabled; + tsk_bool_t activated; + tsk_bool_t use_srtp; + struct ssl_ctx_st *ctx; + tnet_fingerprint_t fingerprints[TNET_DTLS_HASH_TYPE_MAX]; + } dtls; + /* PROXY */ struct { tsk_bool_t auto_detect; diff --git a/tinyNET/src/tnet_transport_cfsocket.c b/tinyNET/src/tnet_transport_cfsocket.c index 4115b22..ed844b6 100755 --- a/tinyNET/src/tnet_transport_cfsocket.c +++ b/tinyNET/src/tnet_transport_cfsocket.c @@ -55,25 +55,24 @@ #define TNET_BUFFER_STREAM_MIN_SIZE 1024 /*== Socket description ==*/ -typedef struct transport_socket_xs -{ +typedef struct transport_socket_xs { tnet_fd_t fd; tsk_bool_t owner; tsk_bool_t readable; tsk_bool_t writable; tsk_bool_t paused; tsk_bool_t is_client; - + tnet_proxy_node_t *proxy_node; tnet_proxyinfo_t* proxy_info; tsk_bool_t proxy_handshacking_completed; tsk_bool_t proxy_handshacking_started; - + char* dst_host; tnet_port_t dst_port; - + tnet_socket_type_t type; - + CFSocketRef cf_socket; CFReadStreamRef cf_read_stream; CFWriteStreamRef cf_write_stream; @@ -82,15 +81,14 @@ typedef struct transport_socket_xs transport_socket_xt; /*== Transport context structure definition ==*/ -typedef struct transport_context_s -{ +typedef struct transport_context_s { TSK_DECLARE_OBJECT; - + tsk_size_t count; transport_socket_xt* sockets[TNET_MAX_FDS]; - + CFRunLoopRef cf_run_loop; - + TSK_DECLARE_SAFEOBJ; } transport_context_t; @@ -114,32 +112,32 @@ static BOOL isTrusted(tnet_transport_t *transport, id cfStream, BOOL bReadStream SecCertificateRef certArray[2] = { NULL, NULL }; CFArrayRef refCertArray = NULL; CFIndex certArrayCount = 0; - + trust = bReadStream - ? (SecTrustRef)CFReadStreamCopyProperty((CFReadStreamRef)cfStream, kCFStreamPropertySSLPeerTrust) - : (SecTrustRef)CFWriteStreamCopyProperty((CFWriteStreamRef)cfStream, kCFStreamPropertySSLPeerTrust); + ? (SecTrustRef)CFReadStreamCopyProperty((CFReadStreamRef)cfStream, kCFStreamPropertySSLPeerTrust) + : (SecTrustRef)CFWriteStreamCopyProperty((CFWriteStreamRef)cfStream, kCFStreamPropertySSLPeerTrust); if (!trust) { TSK_DEBUG_ERROR("Failed to get SecTrustRef object from '%s' stream", bReadStream ? "read" : "write"); goto bail; } - + NSString *caName = NULL, *pbName = NULL; - + if (!tsk_strnullORempty(transport->tls.ca)) { - caName = [[[NSString stringWithCString:transport->tls.ca encoding: NSUTF8StringEncoding] lastPathComponent] stringByDeletingPathExtension]; +caName = [[[NSString stringWithCString:transport->tls.ca encoding: NSUTF8StringEncoding] lastPathComponent] stringByDeletingPathExtension]; } if (!tsk_strnullORempty(transport->tls.pbk)) { - pbName = [[[NSString stringWithCString:transport->tls.pbk encoding: NSUTF8StringEncoding] lastPathComponent] stringByDeletingPathExtension]; +pbName = [[[NSString stringWithCString:transport->tls.pbk encoding: NSUTF8StringEncoding] lastPathComponent] stringByDeletingPathExtension]; } TSK_DEBUG_INFO("SSL::isTrusted(ca=%s, pb=%s)", [caName UTF8String], [pbName UTF8String]); - + if (caName) { - NSString *caPath = [[NSBundle mainBundle] pathForResource:caName ofType:@"der"]; - if (![[NSFileManager defaultManager] fileExistsAtPath:caPath]) { +NSString *caPath = [[NSBundle mainBundle] pathForResource:caName ofType:@"der"]; +if (![[NSFileManager defaultManager] fileExistsAtPath:caPath]) { TSK_DEBUG_WARN("Cannot find SSL CA file '%s.der'", [caPath UTF8String]); } else { - NSData *certData = [[NSData alloc] initWithContentsOfFile:caPath]; +NSData *certData = [[NSData alloc] initWithContentsOfFile:caPath]; CFDataRef certDataRef = (CFDataRef)certData; SecCertificateRef cert = certDataRef ? SecCertificateCreateWithData(NULL, certDataRef) : NULL; [certData release]; @@ -153,12 +151,12 @@ static BOOL isTrusted(tnet_transport_t *transport, id cfStream, BOOL bReadStream } } if (pbName) { - NSString *pbPath = [[NSBundle mainBundle] pathForResource:pbName ofType:@"der"]; - if (![[NSFileManager defaultManager] fileExistsAtPath:pbPath]) { +NSString *pbPath = [[NSBundle mainBundle] pathForResource:pbName ofType:@"der"]; +if (![[NSFileManager defaultManager] fileExistsAtPath:pbPath]) { TSK_DEBUG_WARN("Cannot find SSL PUB file '%s.der'", [pbPath UTF8String]); } else { - NSData *certData = [[NSData alloc] initWithContentsOfFile:pbPath]; +NSData *certData = [[NSData alloc] initWithContentsOfFile:pbPath]; CFDataRef certDataRef = (CFDataRef)certData; SecCertificateRef cert = certDataRef ? SecCertificateCreateWithData(NULL, certDataRef) : NULL; [certData release]; @@ -191,7 +189,7 @@ static BOOL isTrusted(tnet_transport_t *transport, id cfStream, BOOL bReadStream } bTrusted = (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified); TSK_DEBUG_INFO("SecTrustEvaluate result = %d", result); - + bail: CFRelease(trust); CFRelease(refCertArray); @@ -202,28 +200,28 @@ bail: static int recvData(tnet_transport_t *transport, transport_socket_xt* active_socket) { int ret; - if(!transport || !transport->context || !active_socket){ + if(!transport || !transport->context || !active_socket) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + void* buffer = tsk_null; tsk_size_t len = 0; struct sockaddr_storage remote_addr = {0}; - + /* check whether the socket is paused or not */ if (active_socket->paused) { TSK_DEBUG_INFO("Socket is paused"); goto bail; } - + tsk_bool_t is_stream = TNET_SOCKET_TYPE_IS_STREAM(active_socket->type); - + if (tnet_ioctlt(active_socket->fd, FIONREAD, &len) < 0) { TNET_PRINT_LAST_ERROR("ioctl() failed"); goto bail; } - + if (!len) { // probably incoming connection if (is_stream && !active_socket->is_client) { @@ -235,26 +233,26 @@ static int recvData(tnet_transport_t *transport, transport_socket_xt* active_soc goto bail; } } - + if (is_stream && CFReadStreamHasBytesAvailable(active_socket->cf_read_stream)) { if ((buffer = tsk_calloc(TNET_BUFFER_STREAM_MIN_SIZE, sizeof(uint8_t)))) { len = CFReadStreamRead(active_socket->cf_read_stream, buffer, (CFIndex)TNET_BUFFER_STREAM_MIN_SIZE); ret = (int)len; } } - + if (ret <= 0) { TSK_DEBUG_WARN("ioctl() returned zero for fd=%d", active_socket->fd); goto bail; } } - + if (len && !buffer) { - if(!(buffer = tsk_calloc(len, sizeof(uint8_t)))){ + if(!(buffer = tsk_calloc(len, sizeof(uint8_t)))) { TSK_DEBUG_ERROR("calloc(%zu) failed", len); goto bail; } - + // Receive the waiting data if (is_stream) { ret = tnet_getpeername(active_socket->fd, &remote_addr); @@ -269,23 +267,23 @@ static int recvData(tnet_transport_t *transport, transport_socket_xt* active_soc ret = tnet_sockfd_recvfrom(active_socket->fd, buffer, len, 0, (struct sockaddr*)&remote_addr); } } - - - if(ret < 0){ + + + if(ret < 0) { removeSocket(active_socket, transport->context); TNET_PRINT_LAST_ERROR("recv/recvfrom have failed."); goto bail; } - + if ((len != (tsk_size_t)ret) && len) { len = (tsk_size_t)ret; } - + if (!active_socket->proxy_handshacking_completed && active_socket->proxy_handshacking_started && active_socket->proxy_node && active_socket->proxy_info) { void* handshaking_data_ptr = tsk_null; tsk_size_t handshaking_data_size = 0; TSK_DEBUG_INFO("Proxy handshaking data:%.*s", (int)len, buffer); - + // handle incoming hadshaking data if ((ret = tnet_proxy_node_set_handshaking_data(active_socket->proxy_node, buffer, len)) != 0) { TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); @@ -318,18 +316,19 @@ static int recvData(tnet_transport_t *transport, transport_socket_xt* active_soc } goto bail; // do not forward the data to the end-user } - + if (len && buffer) { tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); if (e && buffer && len) { - e->data = buffer; buffer = NULL; + e->data = buffer; + buffer = NULL; e->size = len; e->remote_addr = remote_addr; - + TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); } } - + bail: TSK_FREE(buffer); return 0; @@ -341,31 +340,31 @@ int tnet_transport_add_socket_2(const tnet_transport_handle_t *handle, tnet_fd_t transport_context_t* context; int ret = -1; (void)(tlsHandle); - + if (!transport) { TSK_DEBUG_ERROR("Invalid server handle."); return ret; } - + if (!(context = (transport_context_t*)transport->context)) { TSK_DEBUG_ERROR("Invalid context."); return -2; } - - if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)){ + + if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) { transport->tls.enabled = 1; } - + if ((ret = addSocket2(fd, type, transport, take_ownership, isClient, dst_host, dst_port, proxy_info))) { TSK_DEBUG_ERROR("Failed to add new Socket."); return ret; } - + if (context->cf_run_loop) { // Signal the run-loop CFRunLoopWakeUp(context->cf_run_loop); } - + return 0; } @@ -377,23 +376,24 @@ int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t f return tnet_transport_add_socket_2(handle, fd, type, take_ownership, isClient, tlsHandle, __dst_host_null, __dst_port_zero, __proxy_info_null); } -int tnet_transport_pause_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tsk_bool_t pause){ +int tnet_transport_pause_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tsk_bool_t pause) +{ tnet_transport_t *transport = (tnet_transport_t*)handle; transport_context_t *context; transport_socket_xt* socket; - - if(!transport || !(context = (transport_context_t *)transport->context)){ + + if(!transport || !(context = (transport_context_t *)transport->context)) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - - if((socket = (transport_socket_xt*)getSocket(context, fd))){ + + if((socket = (transport_socket_xt*)getSocket(context, fd))) { socket->paused = pause; } else { TSK_DEBUG_WARN("Failed to find socket with fd=%d", (int)fd); } - + return 0; } @@ -404,19 +404,19 @@ int tnet_transport_remove_socket(const tnet_transport_handle_t *handle, tnet_fd_ transport_context_t *context; tsk_size_t i; tsk_bool_t found = tsk_false; - + if (!transport || !fd) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + TSK_DEBUG_INFO("Removing socket %d", *fd); - + if (!(context = (transport_context_t*)transport->context)) { TSK_DEBUG_ERROR("Invalid context."); return -2; } - + for(i=0; i<context->count; ++i) { if (context->sockets[i]->fd == *fd) { removeSocketAtIndex((int)i, context); @@ -425,15 +425,15 @@ int tnet_transport_remove_socket(const tnet_transport_handle_t *handle, tnet_fd_ break; } } - + if (found && context->cf_run_loop) { // Signal the run-loop CFRunLoopWakeUp(context->cf_run_loop); return 0; } - + // ... - + return -1; } @@ -441,29 +441,29 @@ tsk_size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t { tnet_transport_t *transport = (tnet_transport_t*)handle; int numberOfBytesSent = 0; - + if (!transport) { TSK_DEBUG_ERROR("Invalid transport handle."); goto bail; } - + const transport_socket_xt* sock = getSocket(transport->context, from); if (sock && sock->cf_write_stream && TNET_SOCKET_TYPE_IS_STREAM(sock->type) && sock->cf_write_stream) { int sent = 0, to_send; const uint8_t* buff_ptr = (const uint8_t*)buf; // on iOS when TLS is enabled sending more than 1024 bytes could fails static const int max_size_to_send = 1024; - + to_send = (int)TSK_MIN(max_size_to_send, size); - + if (CFWriteStreamGetStatus(sock->cf_write_stream) == kCFStreamStatusNotOpen) { - if(!CFWriteStreamOpen(sock->cf_write_stream)){ + if(!CFWriteStreamOpen(sock->cf_write_stream)) { TSK_DEBUG_ERROR("CFWriteStreamOpen() failed"); return numberOfBytesSent; } } if (CFReadStreamGetStatus(sock->cf_read_stream) == kCFStreamStatusNotOpen) { - if(!CFReadStreamOpen(sock->cf_read_stream)){ + if(!CFReadStreamOpen(sock->cf_read_stream)) { TSK_DEBUG_ERROR("CFReadStreamOpen() failed"); return numberOfBytesSent; } @@ -472,17 +472,18 @@ tsk_size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t numberOfBytesSent += sent; to_send = (int)TSK_MIN(max_size_to_send, (size - numberOfBytesSent)); } - if(sent < 0){ + if(sent < 0) { TNET_PRINT_LAST_ERROR("Send have failed"); goto bail; } - } else { + } + else { if ((numberOfBytesSent = (int)send(from, buf, size, 0)) < size) { TNET_PRINT_LAST_ERROR("Send have failed"); goto bail; } } - + bail: return numberOfBytesSent; } @@ -491,17 +492,17 @@ tsk_size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_ { tnet_transport_t *transport = (tnet_transport_t*)handle; int numberOfBytesSent = 0, ret; - + if (!transport) { TSK_DEBUG_ERROR("Invalid server handle"); goto bail; } - + if (!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { TSK_DEBUG_ERROR("In order to use sendto you must use an udp transport"); goto bail; } - + while (numberOfBytesSent < size && (ret = (int)sendto(from, buf, size, 0, to, tnet_get_sockaddr_size(to))) >= 0) { numberOfBytesSent += ret; } @@ -514,7 +515,7 @@ tsk_size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_ TNET_PRINT_LAST_ERROR("sendto(fd=%d) have failed", from); } } - + bail: return numberOfBytesSent; } @@ -522,20 +523,20 @@ bail: int tnet_transport_have_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd) { tnet_transport_t *transport = (tnet_transport_t*)handle; - + if (!transport) { TSK_DEBUG_ERROR("Invalid server handle."); return 0; } - + return (getSocket((transport_context_t*)transport->context, fd) != 0); } const tnet_tls_socket_handle_t* tnet_transport_get_tlshandle(const tnet_transport_handle_t *handle, tnet_fd_t fd) { tnet_transport_t *transport = (tnet_transport_t*)handle; - - if(!transport){ + + if(!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return 0; } @@ -548,7 +549,7 @@ static const transport_socket_xt* getSocket(transport_context_t *context, tnet_f { tsk_size_t i; transport_socket_xt* ret = tsk_null; - + if (context) { tsk_safeobj_lock(context); for(i=0; i<context->count; i++) { @@ -559,14 +560,14 @@ static const transport_socket_xt* getSocket(transport_context_t *context, tnet_f } tsk_safeobj_unlock(context); } - + return ret; } static const transport_socket_xt* getSocketByStream(transport_context_t *context, void* cf_stream) { tsk_size_t i; transport_socket_xt* ret = tsk_null; - + if (context) { tsk_safeobj_lock(context); for(i=0; i<context->count; i++) { @@ -577,13 +578,14 @@ static const transport_socket_xt* getSocketByStream(transport_context_t *context } tsk_safeobj_unlock(context); } - + return ret; } /*== Add new socket ==*/ -int addSocket2(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client , const char* dst_host, tnet_port_t dst_port, struct tnet_proxyinfo_s* proxy_info) { +int addSocket2(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client , const char* dst_host, tnet_port_t dst_port, struct tnet_proxyinfo_s* proxy_info) +{ transport_context_t *context = transport?transport->context:0; if (context) { transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt)); @@ -596,24 +598,24 @@ int addSocket2(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transpor if (dst_host && dst_port && tnet_proxyinfo_is_valid(proxy_info)) { sock->proxy_info = tsk_object_ref(proxy_info); } - + if (!sock) { TSK_DEBUG_ERROR("Failed to allocate socket"); return -1; } - + tsk_safeobj_lock(context); wrapSocket(transport, sock); context->sockets[context->count] = sock; context->count++; - + tsk_safeobj_unlock(context); - + TSK_DEBUG_INFO("Socket added"); - + return 0; } - else{ + else { TSK_DEBUG_ERROR("Context is Null."); return -1; } @@ -631,19 +633,19 @@ int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport int removeSocketAtIndex(int index, transport_context_t *context) { int i; - + tsk_safeobj_lock(context); - + if (index < (int)context->count) { transport_socket_xt *sock = context->sockets[index]; tnet_fd_t fd = sock->fd; - + // Remove from runloop if (context->cf_run_loop && sock->cf_run_loop_source) { CFRunLoopRemoveSource(context->cf_run_loop, sock->cf_run_loop_source, kCFRunLoopCommonModes); CFRelease(sock->cf_run_loop_source), sock->cf_run_loop_source = NULL; } - + // Invalidate CFSocket if (sock->cf_socket) { if (CFSocketIsValid(sock->cf_socket)) { @@ -652,7 +654,7 @@ int removeSocketAtIndex(int index, transport_context_t *context) CFRelease(sock->cf_socket); sock->cf_socket = NULL; } - + // Close and free write stream if (sock->cf_write_stream) { if (CFWriteStreamGetStatus(sock->cf_write_stream) != kCFStreamStatusClosed) { @@ -661,7 +663,7 @@ int removeSocketAtIndex(int index, transport_context_t *context) CFRelease(sock->cf_write_stream); sock->cf_write_stream = NULL; } - + // Close and free read stream if (sock->cf_read_stream) { if (CFReadStreamGetStatus(sock->cf_read_stream) != kCFStreamStatusClosed) { @@ -670,38 +672,38 @@ int removeSocketAtIndex(int index, transport_context_t *context) CFRelease(sock->cf_read_stream); sock->cf_read_stream = NULL; } - + // Close the socket if we are the owner. if (sock->owner) { tnet_sockfd_close(&(sock->fd)); } - + TSK_FREE(sock->dst_host); TSK_OBJECT_SAFE_FREE(sock->proxy_node); TSK_OBJECT_SAFE_FREE(sock->proxy_info); TSK_FREE(sock); - + for (i = index ; i<context->count-1; ++i) { context->sockets[i] = context->sockets[i+1]; } - + context->sockets[context->count-1] = tsk_null; context->count--; - + TSK_DEBUG_INFO("Socket removed: %d", fd); } - + tsk_safeobj_unlock(context); - + return 0; } int removeSocket(transport_socket_xt *value, transport_context_t *context) { int i; - + tsk_safeobj_lock(context); - + for(i = 0; i < context->count; i++) { transport_socket_xt *sock = context->sockets[i]; if (sock == value) { @@ -709,9 +711,9 @@ int removeSocket(transport_socket_xt *value, transport_context_t *context) break; } } - + tsk_safeobj_unlock(context); - + return 0; } @@ -719,19 +721,19 @@ int tnet_transport_stop(tnet_transport_t *transport) { int ret; transport_context_t *context; - + if (!transport) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + context = transport->context; - + if ((ret = tsk_runnable_stop(TSK_RUNNABLE(transport)))) { return ret; } - - if(transport->mainThreadId[0]){ + + if(transport->mainThreadId[0]) { if (context && context->cf_run_loop) { // Signal the run-loop CFRunLoopWakeUp(context->cf_run_loop); @@ -747,29 +749,29 @@ int tnet_transport_prepare(tnet_transport_t *transport) { int ret = -1; transport_context_t *context; - + if (!transport || !(context = transport->context)) { TSK_DEBUG_ERROR("Invalid parameter."); return -1; } - + if (transport->prepared) { TSK_DEBUG_ERROR("Transport already prepared."); return -2; } - + /* Prepare master */ - if(!transport->master){ - if((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))){ + if(!transport->master) { + if((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))) { tsk_strupdate(&transport->local_ip, transport->master->ip); transport->bind_local_port = transport->master->port; } - else{ + else { TSK_DEBUG_ERROR("Failed to create master socket"); return -3; } } - + /* Start listening */ if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { if ((ret = tnet_sockfd_listen(transport->master->fd, TNET_MAX_FDS))) { @@ -777,7 +779,7 @@ int tnet_transport_prepare(tnet_transport_t *transport) goto bail; } } - + /* Add the master socket to the context. */ // don't take ownership: will be closed by the dtor() when refCount==0 // otherwise will be cosed twice: dtor() and removeSocket @@ -785,281 +787,275 @@ int tnet_transport_prepare(tnet_transport_t *transport) TSK_DEBUG_ERROR("Failed to add master socket"); goto bail; } - + transport->prepared = tsk_true; - + bail: return ret; } -int tnet_transport_unprepare(tnet_transport_t *transport){ +int tnet_transport_unprepare(tnet_transport_t *transport) +{ transport_context_t *context; - - if(!transport || !(context = transport->context)){ + + if(!transport || !(context = transport->context)) { TSK_DEBUG_ERROR("Invalid parameter."); return -1; } - - if(!transport->prepared){ + + if(!transport->prepared) { return 0; } - + transport->prepared = tsk_false; - - while(context->count){ + + while(context->count) { removeSocketAtIndex(0, context); // safe } - + // destroy master as it has been closed by removeSocket() TSK_OBJECT_SAFE_FREE(transport->master); - + return 0; } -void __CFReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) { +void __CFReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) +{ // Extract the context tnet_transport_t *transport = (tnet_transport_t *) clientCallBackInfo; transport_context_t *context = transport->context; - + /* lock context */ tsk_safeobj_lock(context); - + // Extract the native socket CFDataRef data = CFReadStreamCopyProperty(stream, kCFStreamPropertySocketNativeHandle); transport_socket_xt *sock = tsk_null; - if(data){ + if(data) { CFSocketNativeHandle fd; CFDataGetBytes(data, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8*) &fd); CFRelease(data); sock = (transport_socket_xt *) getSocket(context, fd); - } else if (eventType == kCFStreamEventErrorOccurred) { // this event returns null data + } + else if (eventType == kCFStreamEventErrorOccurred) { // this event returns null data sock = (transport_socket_xt *) getSocketByStream(context, stream); } - + if(!sock) { goto bail; } - + switch(eventType) { - case kCFStreamEventOpenCompleted: - { - TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> kCFStreamEventOpenCompleted(fd=%d)", sock->fd); + case kCFStreamEventOpenCompleted: { + TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> kCFStreamEventOpenCompleted(fd=%d)", sock->fd); #if 0 - // Check SSL certificates - if (TNET_SOCKET_TYPE_IS_TLS(sock->type) && transport->tls.verify) { - if (!isTrusted(transport, (__bridge id)stream, YES/*YES read stream*/)) { - TSK_DEBUG_ERROR("Remote SSL certs not trusted...closing the write stream"); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); - removeSocket(sock, context); - break; - } + // Check SSL certificates + if (TNET_SOCKET_TYPE_IS_TLS(sock->type) && transport->tls.verify) { + if (!isTrusted(transport, (__bridge id)stream, YES/*YES read stream*/)) { + TSK_DEBUG_ERROR("Remote SSL certs not trusted...closing the write stream"); + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); + removeSocket(sock, context); + break; } + } #endif - // Set "readable" flag - if (!sock->readable) { - sock->readable = tsk_true; - if (sock->writable) { - if (!sock->proxy_info || sock->proxy_handshacking_completed) { - // no proxy or handshaking not done yet - TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, sock->fd); - } - else if (sock->proxy_info && !sock->proxy_handshacking_started) { - // proxy handshaking not done yet - sock->proxy_handshacking_started = tsk_true; - startProxyHandshaking(transport, sock); - } + // Set "readable" flag + if (!sock->readable) { + sock->readable = tsk_true; + if (sock->writable) { + if (!sock->proxy_info || sock->proxy_handshacking_completed) { + // no proxy or handshaking not done yet + TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, sock->fd); + } + else if (sock->proxy_info && !sock->proxy_handshacking_started) { + // proxy handshaking not done yet + sock->proxy_handshacking_started = tsk_true; + startProxyHandshaking(transport, sock); } } - break; - } - case kCFStreamEventEndEncountered: - { - TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> kCFStreamEventEndEncountered(fd=%d)", sock->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); - removeSocket(sock, context); - break; - } - case kCFStreamEventHasBytesAvailable: - { - recvData(transport, sock); - break; - } - case kCFStreamEventErrorOccurred: - { - // Get the error code - CFErrorRef error = CFReadStreamCopyError(stream); - if (error) { - TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> Error=%lu -> %s, fd=%d, status=%ld", CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorGetDomain(error), kCFStringEncodingUTF8), sock->fd, CFReadStreamGetStatus(stream)); - CFRelease(error); - } - - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd); - removeSocket(sock, context); - break; } - default: - { - // Not Implemented - TSK_DEBUG_WARN("Not implemented"); - break; + break; + } + case kCFStreamEventEndEncountered: { + TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> kCFStreamEventEndEncountered(fd=%d)", sock->fd); + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); + removeSocket(sock, context); + break; + } + case kCFStreamEventHasBytesAvailable: { + recvData(transport, sock); + break; + } + case kCFStreamEventErrorOccurred: { + // Get the error code + CFErrorRef error = CFReadStreamCopyError(stream); + if (error) { + TSK_DEBUG_INFO("__CFReadStreamClientCallBack --> Error=%lu -> %s, fd=%d, status=%ld", CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorGetDomain(error), kCFStringEncodingUTF8), sock->fd, CFReadStreamGetStatus(stream)); + CFRelease(error); } + + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd); + removeSocket(sock, context); + break; + } + default: { + // Not Implemented + TSK_DEBUG_WARN("Not implemented"); + break; + } } - + /* unlock context */ bail: tsk_safeobj_unlock(context); } -void __CFWriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) { +void __CFWriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo) +{ // Extract the context tnet_transport_t *transport = (tnet_transport_t *) clientCallBackInfo; transport_context_t *context = transport->context; - + /* lock context */ tsk_safeobj_lock(context); - + // Extract the native socket CFDataRef data = CFWriteStreamCopyProperty(stream, kCFStreamPropertySocketNativeHandle); transport_socket_xt *sock = tsk_null; - if(data){ + if(data) { CFSocketNativeHandle fd; CFDataGetBytes(data, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8*) &fd); CFRelease(data); sock = (transport_socket_xt *) getSocket(context, fd); - } else if (eventType == kCFStreamEventErrorOccurred) { // this event returns null data + } + else if (eventType == kCFStreamEventErrorOccurred) { // this event returns null data sock = (transport_socket_xt *) getSocketByStream(context, stream); } - + if(!sock) { goto bail; } - + switch(eventType) { - case kCFStreamEventOpenCompleted: - { - TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventOpenCompleted(fd=%d)", sock->fd); - // still not connected, see kCFStreamEventCanAcceptBytes - break; + case kCFStreamEventOpenCompleted: { + TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventOpenCompleted(fd=%d)", sock->fd); + // still not connected, see kCFStreamEventCanAcceptBytes + break; + } + case kCFStreamEventCanAcceptBytes: { + // To avoid blocking, call this function only if CFWriteStreamCanAcceptBytes returns true or after the stream’s client (set with CFWriteStreamSetClient) is notified of a kCFStreamEventCanAcceptBytes event. + TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventCanAcceptBytes(fd=%d)", sock->fd); + // Check SSL certificates + if (TNET_SOCKET_TYPE_IS_TLS(sock->type) && transport->tls.verify) { + if (!isTrusted(transport, (__bridge id)stream, FALSE/*NOT read stream*/)) { + TSK_DEBUG_ERROR("Remote SSL certs not trusted...closing the write stream"); + removeSocket(sock, context); + break; + } } - case kCFStreamEventCanAcceptBytes: - { - // To avoid blocking, call this function only if CFWriteStreamCanAcceptBytes returns true or after the stream’s client (set with CFWriteStreamSetClient) is notified of a kCFStreamEventCanAcceptBytes event. - TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventCanAcceptBytes(fd=%d)", sock->fd); - // Check SSL certificates - if (TNET_SOCKET_TYPE_IS_TLS(sock->type) && transport->tls.verify) { - if (!isTrusted(transport, (__bridge id)stream, FALSE/*NOT read stream*/)) { - TSK_DEBUG_ERROR("Remote SSL certs not trusted...closing the write stream"); - removeSocket(sock, context); - break; + // Set "writable" flag + if (!sock->writable) { + sock->writable = tsk_true; + if (sock->readable) { + if (!sock->proxy_info || sock->proxy_handshacking_completed) { + // no proxy or handshaking not done yet + TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, sock->fd); } - } - // Set "writable" flag - if (!sock->writable) { - sock->writable = tsk_true; - if (sock->readable) { - if (!sock->proxy_info || sock->proxy_handshacking_completed) { - // no proxy or handshaking not done yet - TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, sock->fd); - } - else if (sock->proxy_info && !sock->proxy_handshacking_started) { - // proxy handshaking not done yet - sock->proxy_handshacking_started = tsk_true; - startProxyHandshaking(transport, sock); - } + else if (sock->proxy_info && !sock->proxy_handshacking_started) { + // proxy handshaking not done yet + sock->proxy_handshacking_started = tsk_true; + startProxyHandshaking(transport, sock); } } - break; - } - case kCFStreamEventEndEncountered: - { - TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventEndEncountered(fd=%d)", sock->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); - removeSocket(sock, context); - break; } - case kCFStreamEventErrorOccurred: - { - // Get the error code - CFErrorRef error = CFWriteStreamCopyError(stream); - if (error) { - TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> Error=%lu -> %s, fd=%d", CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorGetDomain(error), kCFStringEncodingUTF8), sock->fd); - CFRelease(error); - } - - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd); - removeSocket(sock, context); - break; - } - default: - { - // Not Implemented - TSK_DEBUG_ERROR("Not implemented"); - break; + break; + } + case kCFStreamEventEndEncountered: { + TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> kCFStreamEventEndEncountered(fd=%d)", sock->fd); + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, sock->fd); + removeSocket(sock, context); + break; + } + case kCFStreamEventErrorOccurred: { + // Get the error code + CFErrorRef error = CFWriteStreamCopyError(stream); + if (error) { + TSK_DEBUG_INFO("__CFWriteStreamClientCallBack --> Error=%lu -> %s, fd=%d", CFErrorGetCode(error), CFStringGetCStringPtr(CFErrorGetDomain(error), kCFStringEncodingUTF8), sock->fd); + CFRelease(error); } + + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, sock->fd); + removeSocket(sock, context); + break; + } + default: { + // Not Implemented + TSK_DEBUG_ERROR("Not implemented"); + break; + } } - + /* unlock context */ bail: tsk_safeobj_unlock(context); } -void __CFSocketCallBack(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) { +void __CFSocketCallBack(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) +{ // Extract the context tnet_transport_t *transport = (tnet_transport_t *) info; transport_context_t *context = transport->context; - + // Extract the native socket int fd = CFSocketGetNative(s); transport_socket_xt *sock = (transport_socket_xt *) getSocket(context, fd); - if(!sock) goto bail; - + if(!sock) { + goto bail; + } + /* lock context */ tsk_safeobj_lock(context); - + switch (callbackType) { - case kCFSocketReadCallBack: - { - recvData(transport, sock); - break; - } - case kCFSocketAcceptCallBack: - case kCFSocketConnectCallBack: - case kCFSocketWriteCallBack: - { - TSK_DEBUG_INFO("__CFSocketCallBack(fd=%d), callbackType=%lu", sock->fd, callbackType); - wrapSocket(transport, sock); - break; - } - case kCFSocketDataCallBack: - { - if (data) { - const UInt8 *ptr = CFDataGetBytePtr((CFDataRef)data); - int len = (int)CFDataGetLength((CFDataRef)data); - if (ptr && len > 0) { - tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, sock->fd); - if (e) { - e->data = tsk_malloc(len); - if (e->data) { - memcpy(e->data, ptr, len); - e->size = len; - } - struct sockaddr* address_ = (struct sockaddr*)CFDataGetBytePtr(address); - memcpy(&e->remote_addr, address_, tnet_get_sockaddr_size(address_)); - TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); + case kCFSocketReadCallBack: { + recvData(transport, sock); + break; + } + case kCFSocketAcceptCallBack: + case kCFSocketConnectCallBack: + case kCFSocketWriteCallBack: { + TSK_DEBUG_INFO("__CFSocketCallBack(fd=%d), callbackType=%lu", sock->fd, callbackType); + wrapSocket(transport, sock); + break; + } + case kCFSocketDataCallBack: { + if (data) { + const UInt8 *ptr = CFDataGetBytePtr((CFDataRef)data); + int len = (int)CFDataGetLength((CFDataRef)data); + if (ptr && len > 0) { + tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, sock->fd); + if (e) { + e->data = tsk_malloc(len); + if (e->data) { + memcpy(e->data, ptr, len); + e->size = len; } + struct sockaddr* address_ = (struct sockaddr*)CFDataGetBytePtr(address); + memcpy(&e->remote_addr, address_, tnet_get_sockaddr_size(address_)); + TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); } } - break; - } - - default: - { - // Not Implemented - TSK_DEBUG_ERROR("Not implemented"); - break; } + break; } - + + default: { + // Not Implemented + TSK_DEBUG_ERROR("Not implemented"); + break; + } + } + /* unlock context */ bail: tsk_safeobj_unlock(context); @@ -1076,52 +1072,53 @@ int wrapSocket(tnet_transport_t *transport, transport_socket_xt *sock) TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + // If the socket is already wrapped in a CFSocket or mainthead not started yet then return if (!context->cf_run_loop) { return 0; } - + // Put a reference to the transport context const CFSocketContext socket_context = { 0, transport, NULL, NULL, NULL }; - + // Wrap socket and listen to events if (!sock->cf_socket && !sock->cf_read_stream && !sock->cf_write_stream) { sock->cf_socket = CFSocketCreateWithNative(kCFAllocatorDefault, - sock->fd, - kCFSocketReadCallBack | kCFSocketConnectCallBack | kCFSocketWriteCallBack | kCFSocketAcceptCallBack | kCFSocketDataCallBack, - &__CFSocketCallBack, - &socket_context); - + sock->fd, + kCFSocketReadCallBack | kCFSocketConnectCallBack | kCFSocketWriteCallBack | kCFSocketAcceptCallBack | kCFSocketDataCallBack, + &__CFSocketCallBack, + &socket_context); + // Don't close the socket if the CFSocket is invalidated CFOptionFlags flags = CFSocketGetSocketFlags(sock->cf_socket); flags = flags & ~kCFSocketCloseOnInvalidate; CFSocketSetSocketFlags(sock->cf_socket, flags); - + // Create a new RunLoopSource and register it with the main thread RunLoop sock->cf_run_loop_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sock->cf_socket, 0); CFRunLoopAddSource(context->cf_run_loop, sock->cf_run_loop_source, kCFRunLoopCommonModes); } - + if (TNET_SOCKET_TYPE_IS_DGRAM(sock->type)) { // Nothing to do - - } else if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) { + + } + else if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) { if (!sock->cf_read_stream && !sock->cf_write_stream) { // Create a pair of streams (read/write) from the socket CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock->fd, &sock->cf_read_stream, &sock->cf_write_stream); - + // Don't close underlying socket CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); - + // Mark the stream for VoIP usage CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); - + // Setup a context for the streams CFStreamClientContext streamContext = { 0, transport, NULL, NULL, NULL }; - + // Set the client callback for the stream CFReadStreamSetClient(sock->cf_read_stream, kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, @@ -1131,18 +1128,18 @@ int wrapSocket(tnet_transport_t *transport, transport_socket_xt *sock) kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventCanAcceptBytes |kCFStreamEventEndEncountered, &__CFWriteStreamClientCallBack, &streamContext); - + if (TNET_SOCKET_TYPE_IS_TLS(sock->type)) { if ((ret = enableSSL(transport, sock)) != 0) { return ret; } } - + // Enroll streams in the run-loop CFReadStreamScheduleWithRunLoop(sock->cf_read_stream, context->cf_run_loop, kCFRunLoopCommonModes); CFWriteStreamScheduleWithRunLoop(sock->cf_write_stream, context->cf_run_loop, kCFRunLoopCommonModes); } - + // Open streams only if ready (otherwise, fails on iOS8) if (tnet_sockfd_waitUntilReadable(sock->fd, 1) == 0 || tnet_sockfd_waitUntilWritable(sock->fd, 1) == 0) { // switch from cf_socket to streams @@ -1155,11 +1152,11 @@ int wrapSocket(tnet_transport_t *transport, transport_socket_xt *sock) CFRelease(sock->cf_socket); sock->cf_socket = NULL; } - + should_open_streams = tsk_true; } } - + // Proxy if (sock->proxy_info) { if (sock->proxy_node && sock->proxy_node->type != sock->proxy_info->type) { @@ -1178,7 +1175,7 @@ int wrapSocket(tnet_transport_t *transport, transport_socket_xt *sock) TNET_PROXY_SET_SOCKET(sock->fd, sock->type), TNET_PROXY_NODE_SET_NULL()); } - + // Open streams if (should_open_streams) { if (!CFReadStreamOpen(sock->cf_read_stream)) { @@ -1198,7 +1195,7 @@ int wrapSocket(tnet_transport_t *transport, transport_socket_xt *sock) TSK_DEBUG_INFO("CFWriteStreamOpen(fd=%d) returned with status=%ld", sock->fd, status); } } - + return 0; } @@ -1213,7 +1210,7 @@ static int enableSSL(tnet_transport_t *transport, transport_socket_xt *sock) CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); - + CFMutableDictionaryRef settings = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); #if (__IPHONE_OS_VERSION_MIN_REQUIRED < 40000) // @Deprecated CFDictionaryAddValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); @@ -1223,11 +1220,11 @@ static int enableSSL(tnet_transport_t *transport, transport_socket_xt *sock) CFDictionaryAddValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); CFDictionaryAddValue(settings, kCFStreamSSLIsServer, sock->is_client ? kCFBooleanFalse : kCFBooleanTrue); CFDictionaryAddValue(settings, kCFStreamSSLPeerName, kCFNull); - + // Set the SSL settings CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertySSLSettings, settings); - + CFRelease(settings); } return 0; @@ -1239,12 +1236,12 @@ static int startProxyHandshaking(tnet_transport_t *transport, transport_socket_x int ret; void* handshaking_data_ptr = tsk_null; tsk_size_t handshaking_data_size = 0; - + if (!transport || !(context = transport->context) || !sock || !sock->proxy_info || !sock->proxy_node) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - + // start handshaking if ((ret = tnet_proxy_node_start_handshaking(sock->proxy_node)) != 0) { return ret; @@ -1260,7 +1257,7 @@ static int startProxyHandshaking(tnet_transport_t *transport, transport_socket_x TSK_FREE(handshaking_data_ptr); // check if handshaking completed tnet_proxy_node_get_handshaking_completed(sock->proxy_node, &sock->proxy_handshacking_completed); - + return ret; } @@ -1270,15 +1267,15 @@ void *tnet_transport_mainthread(void *param) tnet_transport_t *transport = param; transport_context_t *context = transport->context; int i; - + /* check whether the transport is already prepared */ if (!transport->prepared) { TSK_DEBUG_ERROR("Transport must be prepared before strating."); goto bail; } - + TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} with fd {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->fd); - + // Set the RunLoop of the context context->cf_run_loop = CFRunLoopGetCurrent(); CFRetain(context->cf_run_loop); @@ -1288,22 +1285,22 @@ void *tnet_transport_mainthread(void *param) wrapSocket(transport, context->sockets[i]); } tsk_safeobj_unlock(context); - + while(TSK_RUNNABLE(transport)->running) { // Give some time to process sources CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, false); - + if (!TSK_RUNNABLE(transport)->running) { goto bail; } } - + // Remove all the sockets, streams and sources from the run loop tsk_safeobj_lock(context); for(i = 0; i < context->count; i++) { transport_context_t *context = transport->context; transport_socket_xt *sock = context->sockets[i]; - + if (!sock) { continue; } @@ -1320,11 +1317,11 @@ void *tnet_transport_mainthread(void *param) } } tsk_safeobj_unlock(context); - - + + bail: TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}...", transport->description, transport->master->ip, transport->master->port); - if(context->cf_run_loop){ + if(context->cf_run_loop) { CFRelease(context->cf_run_loop); context->cf_run_loop = NULL; } @@ -1357,7 +1354,7 @@ static tsk_object_t* transport_context_ctor(tsk_object_t * self, va_list * app) } static tsk_object_t* transport_context_dtor(tsk_object_t * self) -{ +{ transport_context_t *context = self; if (context) { while(context->count) { @@ -1368,12 +1365,11 @@ static tsk_object_t* transport_context_dtor(tsk_object_t * self) return self; } -static const tsk_object_def_t tnet_transport_context_def_s = -{ +static const tsk_object_def_t tnet_transport_context_def_s = { sizeof(transport_context_t), - transport_context_ctor, + transport_context_ctor, transport_context_dtor, - tsk_null, + tsk_null, }; const tsk_object_def_t *tnet_transport_context_def_t = &tnet_transport_context_def_s; diff --git a/tinyNET/src/tnet_transport_poll.c b/tinyNET/src/tnet_transport_poll.c index 0774823..3aa8913 100755 --- a/tinyNET/src/tnet_transport_poll.c +++ b/tinyNET/src/tnet_transport_poll.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2010-2011 Mamadou Diop * Copyright (C) 2012-2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -51,31 +51,29 @@ #endif /*== Socket description ==*/ -typedef struct transport_socket_xs -{ - tnet_fd_t fd; - tsk_bool_t owner; - tsk_bool_t connected; - tsk_bool_t paused; +typedef struct transport_socket_xs { + tnet_fd_t fd; + tsk_bool_t owner; + tsk_bool_t connected; + tsk_bool_t paused; - tnet_socket_type_t type; - tnet_tls_socket_handle_t* tlshandle; + tnet_socket_type_t type; + tnet_tls_socket_handle_t* tlshandle; } transport_socket_xt; /*== Transport context structure definition ==*/ -typedef struct transport_context_s -{ - TSK_DECLARE_OBJECT; - - tsk_size_t count; - tnet_fd_t pipeW; - tnet_fd_t pipeR; - tnet_pollfd_t ufds[TNET_MAX_FDS]; - transport_socket_xt* sockets[TNET_MAX_FDS]; - tsk_bool_t polling; // whether we are poll()ing - - TSK_DECLARE_SAFEOBJ; +typedef struct transport_context_s { + TSK_DECLARE_OBJECT; + + tsk_size_t count; + tnet_fd_t pipeW; + tnet_fd_t pipeR; + tnet_pollfd_t ufds[TNET_MAX_FDS]; + transport_socket_xt* sockets[TNET_MAX_FDS]; + tsk_bool_t polling; // whether we are poll()ing + + TSK_DECLARE_SAFEOBJ; } transport_context_t; @@ -95,269 +93,270 @@ int tnet_transport_add_socket_2(const tnet_transport_handle_t *handle, tnet_fd_t int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t* context; - static char c = '\0'; - int ret = -1; - - if(!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return ret; - } - - if(!(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid context."); - return -2; - } + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t* context; + static char c = '\0'; + int ret = -1; + + if(!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return ret; + } - if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)){ - transport->tls.enabled = 1; - } - - if((ret = addSocket(fd, type, transport, take_ownership, isClient, tlsHandle))){ - TSK_DEBUG_ERROR("Failed to add new Socket."); - return ret; - } + if(!(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid context."); + return -2; + } - // signal - if(context->pipeW && (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started)){ - if((ret = write(context->pipeW, &c, 1)) > 0){ - TSK_DEBUG_INFO("Socket added (external call) %d", fd); - return 0; - } - else{ - TSK_DEBUG_ERROR("Failed to add new Socket."); - return ret; - } - } else { - TSK_DEBUG_INFO("pipeW (write site) not initialized yet."); - return 0; //Will be taken when mainthead start - } + if(TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) { + transport->tls.enabled = 1; + } + + if((ret = addSocket(fd, type, transport, take_ownership, isClient, tlsHandle))) { + TSK_DEBUG_ERROR("Failed to add new Socket."); + return ret; + } + + // signal + if(context->pipeW && (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started)) { + if((ret = write(context->pipeW, &c, 1)) > 0) { + TSK_DEBUG_INFO("Socket added (external call) %d", fd); + return 0; + } + else { + TSK_DEBUG_ERROR("Failed to add new Socket."); + return ret; + } + } + else { + TSK_DEBUG_INFO("pipeW (write site) not initialized yet."); + return 0; //Will be taken when mainthead start + } } int tnet_transport_pause_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tsk_bool_t pause) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t *context; - transport_socket_xt* socket; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t *context; + transport_socket_xt* socket; - if(!transport || !(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!transport || !(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if((socket = getSocket(context, fd))){ - socket->paused = pause; - } - else{ - TSK_DEBUG_WARN("Socket does not exist in this context"); - } - return 0; + if((socket = getSocket(context, fd))) { + socket->paused = pause; + } + else { + TSK_DEBUG_WARN("Socket does not exist in this context"); + } + return 0; } /* Remove socket */ int tnet_transport_remove_socket(const tnet_transport_handle_t *handle, tnet_fd_t *pfd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t *context; - int ret = -1; - tsk_size_t i; - tsk_bool_t found = tsk_false; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t *context; + int ret = -1; + tsk_size_t i; + tsk_bool_t found = tsk_false; tnet_fd_t fd = *pfd; - - TSK_DEBUG_INFO("Removing socket %d", fd); - if(!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return ret; - } - - if(!(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid context."); - return -2; - } - - tsk_safeobj_lock(context); + TSK_DEBUG_INFO("Removing socket %d", fd); - for(i=0; i<context->count; i++){ - if(context->sockets[i]->fd == fd){ - tsk_bool_t self_ref = (&context->sockets[i]->fd == pfd); - removeSocket(i, context); // sockets[i] will be destroyed - found = tsk_true; - TSK_RUNNABLE_ENQUEUE(transport, event_removed, transport->callback_data, fd); - if(!self_ref){ // if self_ref then, pfd no longer valid after removeSocket() - *pfd = TNET_INVALID_FD; - } - break; - } - } + if(!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return ret; + } - tsk_safeobj_unlock(context); - - if(found){ - /* Signal */ - static char c = '\0'; - ret = write(context->pipeW, &c, 1); - return (ret > 0 ? 0 : ret); - } - - // ... - - return -1; + if(!(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid context."); + return -2; + } + + tsk_safeobj_lock(context); + + for(i=0; i<context->count; i++) { + if(context->sockets[i]->fd == fd) { + tsk_bool_t self_ref = (&context->sockets[i]->fd == pfd); + removeSocket(i, context); // sockets[i] will be destroyed + found = tsk_true; + TSK_RUNNABLE_ENQUEUE(transport, event_removed, transport->callback_data, fd); + if(!self_ref) { // if self_ref then, pfd no longer valid after removeSocket() + *pfd = TNET_INVALID_FD; + } + break; + } + } + + tsk_safeobj_unlock(context); + + if(found) { + /* Signal */ + static char c = '\0'; + ret = write(context->pipeW, &c, 1); + return (ret > 0 ? 0 : ret); + } + + // ... + + return -1; } tsk_size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t from, const void* buf, tsk_size_t size) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - int numberOfBytesSent = 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + int numberOfBytesSent = 0; - if(!transport){ - TSK_DEBUG_ERROR("Invalid transport handle."); - goto bail; - } + if(!transport) { + TSK_DEBUG_ERROR("Invalid transport handle."); + goto bail; + } - if(transport->tls.enabled){ - const transport_socket_xt* socket = getSocket(transport->context, from); - if(socket && socket->tlshandle){ - if(!tnet_tls_socket_send(socket->tlshandle, buf, size)){ - numberOfBytesSent = size; - } - else{ - numberOfBytesSent = 0; - } - goto bail; - } - } - else if((numberOfBytesSent = tnet_sockfd_send(from, buf, size, 0)) <= 0){ - TNET_PRINT_LAST_ERROR("send have failed."); + if(transport->tls.enabled) { + const transport_socket_xt* socket = getSocket(transport->context, from); + if(socket && socket->tlshandle) { + if(!tnet_tls_socket_send(socket->tlshandle, buf, size)) { + numberOfBytesSent = size; + } + else { + numberOfBytesSent = 0; + } + goto bail; + } + } + else if((numberOfBytesSent = tnet_sockfd_send(from, buf, size, 0)) <= 0) { + TNET_PRINT_LAST_ERROR("send have failed."); - //tnet_sockfd_close(&from); - goto bail; - } + //tnet_sockfd_close(&from); + goto bail; + } bail: transport->bytes_out += numberOfBytesSent; - return numberOfBytesSent; + return numberOfBytesSent; } tsk_size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_t from, const struct sockaddr *to, const void* buf, tsk_size_t size) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - int numberOfBytesSent = 0; - - if(!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - goto bail; - } - - if(!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)){ - TSK_DEBUG_ERROR("In order to use sendto() you must use an udp transport."); - goto bail; - } - - if((numberOfBytesSent = tnet_sockfd_sendto(from, to, buf, size)) <= 0){ - TNET_PRINT_LAST_ERROR("sendto have failed."); - goto bail; - } - + tnet_transport_t *transport = (tnet_transport_t*)handle; + int numberOfBytesSent = 0; + + if(!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + goto bail; + } + + if(!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { + TSK_DEBUG_ERROR("In order to use sendto() you must use an udp transport."); + goto bail; + } + + if((numberOfBytesSent = tnet_sockfd_sendto(from, to, buf, size)) <= 0) { + TNET_PRINT_LAST_ERROR("sendto have failed."); + goto bail; + } + bail: transport->bytes_out += numberOfBytesSent; - return numberOfBytesSent; + return numberOfBytesSent; } int tnet_transport_have_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - - if(!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return 0; - } - - return (getSocket((transport_context_t*)transport->context, fd) != 0); + tnet_transport_t *transport = (tnet_transport_t*)handle; + + if(!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return 0; + } + + return (getSocket((transport_context_t*)transport->context, fd) != 0); } const tnet_tls_socket_handle_t* tnet_transport_get_tlshandle(const tnet_transport_handle_t *handle, tnet_fd_t fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - const transport_socket_xt *socket; - - if(!transport){ - TSK_DEBUG_ERROR("Invalid parameter"); - return 0; - } - - if((socket = getSocket((transport_context_t*)transport->context, fd))){ - return socket->tlshandle; - } - return 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + const transport_socket_xt *socket; + + if(!transport) { + TSK_DEBUG_ERROR("Invalid parameter"); + return 0; + } + + if((socket = getSocket((transport_context_t*)transport->context, fd))) { + return socket->tlshandle; + } + return 0; } /*== Get socket ==*/ static transport_socket_xt* getSocket(transport_context_t *context, tnet_fd_t fd) { - tsk_size_t i; - transport_socket_xt* ret = 0; - - if(context){ - tsk_safeobj_lock(context); - for(i=0; i<context->count; i++){ - if(context->sockets[i]->fd == fd){ - ret = context->sockets[i]; - break; - } - } - tsk_safeobj_unlock(context); - } - - return ret; + tsk_size_t i; + transport_socket_xt* ret = 0; + + if(context) { + tsk_safeobj_lock(context); + for(i=0; i<context->count; i++) { + if(context->sockets[i]->fd == fd) { + ret = context->sockets[i]; + break; + } + } + tsk_safeobj_unlock(context); + } + + return ret; } /*== Add new socket ==*/ int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client, tnet_tls_socket_handle_t* tlsHandle) { - transport_context_t *context = transport?transport->context:0; - if(context){ - transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt)); - sock->fd = fd; - sock->type = type; - sock->owner = take_ownership; - - if((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled){ - if(tlsHandle){ - sock->tlshandle = tsk_object_ref(tlsHandle); - } - else{ + transport_context_t *context = transport?transport->context:0; + if(context) { + transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt)); + sock->fd = fd; + sock->type = type; + sock->owner = take_ownership; + + if((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled) { + if(tlsHandle) { + sock->tlshandle = tsk_object_ref(tlsHandle); + } + else { #if HAVE_OPENSSL - sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server); + sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server); #endif - } - } - - tsk_safeobj_lock(context); - - context->ufds[context->count].fd = fd; - context->ufds[context->count].events = (fd == context->pipeR) ? TNET_POLLIN : (TNET_POLLIN | TNET_POLLNVAL | TNET_POLLERR); - if(TNET_SOCKET_TYPE_IS_STREAM(sock->type) && fd != context->pipeR){ - context->ufds[context->count].events |= TNET_POLLOUT; // emulate WinSock2 FD_CONNECT event - } - context->ufds[context->count].revents = 0; - context->sockets[context->count] = sock; - - context->count++; - - tsk_safeobj_unlock(context); - - TSK_DEBUG_INFO("Socket added[%s]: fd=%d, tail.count=%d", transport->description, fd, (int)context->count); - - return 0; - } - else{ - TSK_DEBUG_ERROR("Context is Null."); - return -1; - } + } + } + + tsk_safeobj_lock(context); + + context->ufds[context->count].fd = fd; + context->ufds[context->count].events = (fd == context->pipeR) ? TNET_POLLIN : (TNET_POLLIN | TNET_POLLNVAL | TNET_POLLERR); + if(TNET_SOCKET_TYPE_IS_STREAM(sock->type) && fd != context->pipeR) { + context->ufds[context->count].events |= TNET_POLLOUT; // emulate WinSock2 FD_CONNECT event + } + context->ufds[context->count].revents = 0; + context->sockets[context->count] = sock; + + context->count++; + + tsk_safeobj_unlock(context); + + TSK_DEBUG_INFO("Socket added[%s]: fd=%d, tail.count=%d", transport->description, fd, (int)context->count); + + return 0; + } + else { + TSK_DEBUG_ERROR("Context is Null."); + return -1; + } } /*== change connection state ==*/ @@ -378,180 +377,180 @@ static void setConnected(tnet_fd_t fd, transport_context_t *context, int connect /*== Remove socket ==*/ int removeSocket(int index, transport_context_t *context) { - int i; - - tsk_safeobj_lock(context); - - if(index < (int)context->count){ - /* Close the socket if we are the owner. */ - TSK_DEBUG_INFO("Socket to remove: fd=%d, index=%d, tail.count=%d", context->sockets[index]->fd, index, (int)context->count); - if(context->sockets[index]->owner){ - // do not close the socket while it's being poll()ed - // http://stackoverflow.com/questions/5039608/poll-cant-detect-event-when-socket-is-closed-locally - if(context->polling){ - TSK_DEBUG_INFO("RemoveSocket(fd=%d) has been requested but we are poll()ing the socket. ShutdownSocket(fd) called on the socket and we deferred the request.", context->sockets[index]->fd); - TSK_DEBUG_INFO("ShutdownSocket(fd=%d)", context->sockets[index]->fd); - tnet_sockfd_shutdown(context->sockets[index]->fd); - goto done; - } - tnet_sockfd_close(&(context->sockets[index]->fd)); - } - - /* Free tls context */ - TSK_OBJECT_SAFE_FREE(context->sockets[index]->tlshandle); - - // Free socket - TSK_FREE(context->sockets[index]); - - for(i=index ; i<context->count-1; i++){ - context->sockets[i] = context->sockets[i+1]; - context->ufds[i] = context->ufds[i+1]; - } - - context->sockets[context->count-1] = tsk_null; - context->ufds[context->count-1].fd = TNET_INVALID_FD; - context->ufds[context->count-1].events = 0; - context->ufds[context->count-1].revents = 0; - - context->count--; - } + int i; + + tsk_safeobj_lock(context); + + if(index < (int)context->count) { + /* Close the socket if we are the owner. */ + TSK_DEBUG_INFO("Socket to remove: fd=%d, index=%d, tail.count=%d", context->sockets[index]->fd, index, (int)context->count); + if(context->sockets[index]->owner) { + // do not close the socket while it's being poll()ed + // http://stackoverflow.com/questions/5039608/poll-cant-detect-event-when-socket-is-closed-locally + if(context->polling) { + TSK_DEBUG_INFO("RemoveSocket(fd=%d) has been requested but we are poll()ing the socket. ShutdownSocket(fd) called on the socket and we deferred the request.", context->sockets[index]->fd); + TSK_DEBUG_INFO("ShutdownSocket(fd=%d)", context->sockets[index]->fd); + tnet_sockfd_shutdown(context->sockets[index]->fd); + goto done; + } + tnet_sockfd_close(&(context->sockets[index]->fd)); + } + + /* Free tls context */ + TSK_OBJECT_SAFE_FREE(context->sockets[index]->tlshandle); + + // Free socket + TSK_FREE(context->sockets[index]); + + for(i=index ; i<context->count-1; i++) { + context->sockets[i] = context->sockets[i+1]; + context->ufds[i] = context->ufds[i+1]; + } + + context->sockets[context->count-1] = tsk_null; + context->ufds[context->count-1].fd = TNET_INVALID_FD; + context->ufds[context->count-1].events = 0; + context->ufds[context->count-1].revents = 0; + + context->count--; + } done: - tsk_safeobj_unlock(context); - - return 0; + tsk_safeobj_unlock(context); + + return 0; } int tnet_transport_stop(tnet_transport_t *transport) -{ - int ret; - transport_context_t *context; +{ + int ret; + transport_context_t *context; - if(!transport){ - return -1; - } - - context = transport->context; + if(!transport) { + return -1; + } - if((ret = tsk_runnable_stop(TSK_RUNNABLE(transport)))){ - return ret; - } - - if(context){ - static char c = '\0'; - - // signal - tsk_safeobj_lock(context); // =>MUST - if(tnet_transport_have_socket(transport, context->pipeR)){ // to avoid SIGPIPE=> check that there is at least one reader - write(context->pipeW, &c, 1); - } - tsk_safeobj_unlock(context); - } - - if(transport->mainThreadId[0]){ - return tsk_thread_join(transport->mainThreadId); - } - else{ - /* already soppped */ - return 0; - } + context = transport->context; + + if((ret = tsk_runnable_stop(TSK_RUNNABLE(transport)))) { + return ret; + } + + if(context) { + static char c = '\0'; + + // signal + tsk_safeobj_lock(context); // =>MUST + if(tnet_transport_have_socket(transport, context->pipeR)) { // to avoid SIGPIPE=> check that there is at least one reader + write(context->pipeW, &c, 1); + } + tsk_safeobj_unlock(context); + } + + if(transport->mainThreadId[0]) { + return tsk_thread_join(transport->mainThreadId); + } + else { + /* already soppped */ + return 0; + } } int tnet_transport_prepare(tnet_transport_t *transport) { - int ret = -1; - transport_context_t *context; - tnet_fd_t pipes[2]; - - TSK_DEBUG_INFO("tnet_transport_prepare()"); - - if(!transport || !transport->context){ - TSK_DEBUG_ERROR("Invalid parameter."); - return -1; - } - else{ - context = transport->context; - } - - if(transport->prepared){ - TSK_DEBUG_ERROR("Transport already prepared."); - return -2; - } + int ret = -1; + transport_context_t *context; + tnet_fd_t pipes[2]; + + TSK_DEBUG_INFO("tnet_transport_prepare()"); + + if(!transport || !transport->context) { + TSK_DEBUG_ERROR("Invalid parameter."); + return -1; + } + else { + context = transport->context; + } + + if(transport->prepared) { + TSK_DEBUG_ERROR("Transport already prepared."); + return -2; + } + + /* Prepare master */ + if(!transport->master) { + if((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))) { + tsk_strupdate(&transport->local_ip, transport->master->ip); + transport->bind_local_port = transport->master->port; + } + else { + TSK_DEBUG_ERROR("Failed to create master socket"); + return -3; + } + } + + /* Start listening */ + if(TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { + if((ret = tnet_sockfd_listen(transport->master->fd, TNET_MAX_FDS))) { + TNET_PRINT_LAST_ERROR("listen have failed."); + goto bail; + } + } + + /* Create and add pipes to the fd_set */ + if((ret = pipe(pipes))) { + TNET_PRINT_LAST_ERROR("Failed to create new pipes."); + goto bail; + } + + /* set both R and W sides */ + context->pipeR = pipes[0]; + context->pipeW = pipes[1]; + + /* add R side */ + TSK_DEBUG_INFO("pipeR fd=%d, pipeW=%d", context->pipeR, context->pipeW); + if((ret = addSocket(context->pipeR, transport->master->type, transport, tsk_true, tsk_false, tsk_null))) { + goto bail; + } + + /* Add the master socket to the context. */ + TSK_DEBUG_INFO("master fd=%d", transport->master->fd); + // don't take ownership: will be closed by the dctor() when refCount==0 + // otherwise will be closed twice: dctor() and removeSocket() + if((ret = addSocket(transport->master->fd, transport->master->type, transport, tsk_false, tsk_false, tsk_null))) { + TSK_DEBUG_ERROR("Failed to add master socket"); + goto bail; + } + + transport->prepared = tsk_true; - /* Prepare master */ - if(!transport->master){ - if((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))){ - tsk_strupdate(&transport->local_ip, transport->master->ip); - transport->bind_local_port = transport->master->port; - } - else{ - TSK_DEBUG_ERROR("Failed to create master socket"); - return -3; - } - } - - /* Start listening */ - if(TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)){ - if((ret = tnet_sockfd_listen(transport->master->fd, TNET_MAX_FDS))){ - TNET_PRINT_LAST_ERROR("listen have failed."); - goto bail; - } - } - - /* Create and add pipes to the fd_set */ - if((ret = pipe(pipes))){ - TNET_PRINT_LAST_ERROR("Failed to create new pipes."); - goto bail; - } - - /* set both R and W sides */ - context->pipeR = pipes[0]; - context->pipeW = pipes[1]; - - /* add R side */ - TSK_DEBUG_INFO("pipeR fd=%d, pipeW=%d", context->pipeR, context->pipeW); - if((ret = addSocket(context->pipeR, transport->master->type, transport, tsk_true, tsk_false, tsk_null))){ - goto bail; - } - - /* Add the master socket to the context. */ - TSK_DEBUG_INFO("master fd=%d", transport->master->fd); - // don't take ownership: will be closed by the dctor() when refCount==0 - // otherwise will be closed twice: dctor() and removeSocket() - if((ret = addSocket(transport->master->fd, transport->master->type, transport, tsk_false, tsk_false, tsk_null))){ - TSK_DEBUG_ERROR("Failed to add master socket"); - goto bail; - } - - transport->prepared = tsk_true; - bail: - return ret; + return ret; } int tnet_transport_unprepare(tnet_transport_t *transport) { - //int ret = -1; - transport_context_t *context; - - if(!transport || !transport->context){ - TSK_DEBUG_ERROR("Invalid parameter."); - return -1; - } - else{ - context = transport->context; - } + //int ret = -1; + transport_context_t *context; - if(!transport->prepared){ - return 0; - } + if(!transport || !transport->context) { + TSK_DEBUG_ERROR("Invalid parameter."); + return -1; + } + else { + context = transport->context; + } - transport->prepared = tsk_false; - - while(context->count){ - removeSocket(0, context); // safe - } + if(!transport->prepared) { + return 0; + } - /* reset both R and W sides */ + transport->prepared = tsk_false; + + while(context->count) { + removeSocket(0, context); // safe + } + + /* reset both R and W sides */ if (context->pipeW != -1) { if (close(context->pipeW)) { TSK_DEBUG_ERROR("Failed to close pipeW:%d", context->pipeW); @@ -560,244 +559,242 @@ int tnet_transport_unprepare(tnet_transport_t *transport) } context->pipeR = -1; - // destroy master as it has been closed by removeSocket() - TSK_OBJECT_SAFE_FREE(transport->master); + // destroy master as it has been closed by removeSocket() + TSK_OBJECT_SAFE_FREE(transport->master); - return 0; + return 0; } /*=== Main thread */ void *tnet_transport_mainthread(void *param) { - tnet_transport_t *transport = param; - transport_context_t *context = transport->context; - int ret, status; - tsk_size_t i; - tsk_bool_t is_stream; + tnet_transport_t *transport = param; + transport_context_t *context = transport->context; + int ret, status; + tsk_size_t i; + tsk_bool_t is_stream; tnet_fd_t fd; - struct sockaddr_storage remote_addr = {0}; - transport_socket_xt* active_socket; + struct sockaddr_storage remote_addr = {0}; + transport_socket_xt* active_socket; - /* check whether the transport is already prepared */ - if(!transport->prepared){ - TSK_DEBUG_ERROR("Transport must be prepared before strating."); - goto bail; - } - - is_stream = TNET_SOCKET_TYPE_IS_STREAM(transport->master->type); - - TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} using master fd {%d} with type {%d} with max_fds {%lu}...", - transport->description, - transport->master->ip, - transport->master->port, - transport->master->fd, - transport->master->type, - sizeof(context->ufds)/sizeof(context->ufds[0])); - - while(TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started){ - context->polling = tsk_true; - ret = tnet_poll(context->ufds, context->count, -1); - context->polling = tsk_false; - if(ret < 0){ - TNET_PRINT_LAST_ERROR("poll() have failed."); - goto bail; - } + /* check whether the transport is already prepared */ + if(!transport->prepared) { + TSK_DEBUG_ERROR("Transport must be prepared before strating."); + goto bail; + } + + is_stream = TNET_SOCKET_TYPE_IS_STREAM(transport->master->type); + + TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} using master fd {%d} with type {%d} with max_fds {%lu}...", + transport->description, + transport->master->ip, + transport->master->port, + transport->master->fd, + transport->master->type, + sizeof(context->ufds)/sizeof(context->ufds[0])); + + while(TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) { + context->polling = tsk_true; + ret = tnet_poll(context->ufds, context->count, -1); + context->polling = tsk_false; + if(ret < 0) { + TNET_PRINT_LAST_ERROR("poll() have failed."); + goto bail; + } + + if(!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) { + TSK_DEBUG_INFO("Stopping [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); + goto bail; + } + + /* lock context */ + tsk_safeobj_lock(context); + + /* == == */ + for(i=0; i<context->count; i++) { + if(!context->ufds[i].revents) { + continue; + } + + // TSK_DEBUG_INFO("REVENTS(i=%d) = %d", i, context->ufds[i].revents); + + if(context->ufds[i].fd == context->pipeR) { + TSK_DEBUG_INFO("PipeR event = %d", context->ufds[i].revents); + if(context->ufds[i].revents & TNET_POLLIN) { + static char __buffer[1024]; + if(read(context->pipeR, __buffer, sizeof(__buffer)) < 0) { + TNET_PRINT_LAST_ERROR("Failed to read from the Pipe"); + } + } + else if(context->ufds[i].revents & TNET_POLLHUP) { + TNET_PRINT_LAST_ERROR("Pipe Error"); + goto bail; + } + context->ufds[i].revents = 0; + continue; + } + + /* Get active event and socket */ + active_socket = context->sockets[i]; - if(!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started){ - TSK_DEBUG_INFO("Stopping [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); - goto bail; - } - - /* lock context */ - tsk_safeobj_lock(context); - - /* == == */ - for(i=0; i<context->count; i++) - { - if(!context->ufds[i].revents){ - continue; - } - - // TSK_DEBUG_INFO("REVENTS(i=%d) = %d", i, context->ufds[i].revents); - - if(context->ufds[i].fd == context->pipeR){ - TSK_DEBUG_INFO("PipeR event = %d", context->ufds[i].revents); - if(context->ufds[i].revents & TNET_POLLIN){ - static char __buffer[1024]; - if(read(context->pipeR, __buffer, sizeof(__buffer)) < 0){ - TNET_PRINT_LAST_ERROR("Failed to read from the Pipe"); - } - } - else if(context->ufds[i].revents & TNET_POLLHUP){ - TNET_PRINT_LAST_ERROR("Pipe Error"); - goto bail; - } - context->ufds[i].revents = 0; - continue; - } - - /* Get active event and socket */ - active_socket = context->sockets[i]; - /*================== TNET_POLLHUP ==================*/ - if(context->ufds[i].revents & (TNET_POLLHUP)){ - if(context->ufds[i].revents & TNET_POLLOUT){ - TSK_DEBUG_INFO("POLLOUT and POLLHUP are exclusive"); - } - else{ - fd = active_socket->fd; - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLHUP(%d)", transport->description, fd); - - tnet_transport_remove_socket(transport, &active_socket->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); - continue; - } - } - - /*================== TNET_POLLERR ==================*/ - if(context->ufds[i].revents & (TNET_POLLERR)){ + if(context->ufds[i].revents & (TNET_POLLHUP)) { + if(context->ufds[i].revents & TNET_POLLOUT) { + TSK_DEBUG_INFO("POLLOUT and POLLHUP are exclusive"); + } + else { + fd = active_socket->fd; + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLHUP(%d)", transport->description, fd); + + tnet_transport_remove_socket(transport, &active_socket->fd); + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); + continue; + } + } + + /*================== TNET_POLLERR ==================*/ + if(context->ufds[i].revents & (TNET_POLLERR)) { fd = active_socket->fd; - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLERR(%d)", transport->description, fd); - + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLERR(%d)", transport->description, fd); + tnet_transport_remove_socket(transport, &active_socket->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); - continue; - } - - /*================== TNET_POLLNVAL ==================*/ - if(context->ufds[i].revents & (TNET_POLLNVAL)){ + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); + continue; + } + + /*================== TNET_POLLNVAL ==================*/ + if(context->ufds[i].revents & (TNET_POLLNVAL)) { fd = active_socket->fd; - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLNVAL(%d)", transport->description, fd); - + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLNVAL(%d)", transport->description, fd); + tnet_transport_remove_socket(transport, &active_socket->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); - continue; - } - - /*================== POLLIN ==================*/ - if(context->ufds[i].revents & TNET_POLLIN) - { - tsk_size_t len = 0; - void* buffer = tsk_null; - tnet_transport_event_t* e; - - // TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLIN(%d)", transport->description, active_socket->fd); - - /* check whether the socket is paused or not */ - if(active_socket->paused){ - TSK_DEBUG_INFO("Socket is paused"); - goto TNET_POLLIN_DONE; - } - - /* Retrieve the amount of pending data. - * IMPORTANT: If you are using Symbian please update your SDK to the latest build (August 2009) to have 'FIONREAD'. - * This apply whatever you are using the 3rd or 5th edition. - * Download link: http://wiki.forum.nokia.com/index.php/Open_C/C%2B%2B_Release_History - */ - ret = tnet_ioctlt(active_socket->fd, FIONREAD, &len); - if((ret < 0 || !len) && is_stream){ - /* It's probably an incoming connection --> try to accept() it */ - int listening = 0, remove_socket = 0; - socklen_t socklen = sizeof(listening); - - TSK_DEBUG_INFO("ioctlt(%d), len=%u returned zero or failed", active_socket->fd, (unsigned)len); - - // check if socket is listening - if(getsockopt(active_socket->fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &socklen) != 0){ + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); + continue; + } + + /*================== POLLIN ==================*/ + if(context->ufds[i].revents & TNET_POLLIN) { + tsk_size_t len = 0; + void* buffer = tsk_null; + tnet_transport_event_t* e; + + // TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLIN(%d)", transport->description, active_socket->fd); + + /* check whether the socket is paused or not */ + if(active_socket->paused) { + TSK_DEBUG_INFO("Socket is paused"); + goto TNET_POLLIN_DONE; + } + + /* Retrieve the amount of pending data. + * IMPORTANT: If you are using Symbian please update your SDK to the latest build (August 2009) to have 'FIONREAD'. + * This apply whatever you are using the 3rd or 5th edition. + * Download link: http://wiki.forum.nokia.com/index.php/Open_C/C%2B%2B_Release_History + */ + ret = tnet_ioctlt(active_socket->fd, FIONREAD, &len); + if((ret < 0 || !len) && is_stream) { + /* It's probably an incoming connection --> try to accept() it */ + int listening = 0, remove_socket = 0; + socklen_t socklen = sizeof(listening); + + TSK_DEBUG_INFO("ioctlt(%d), len=%u returned zero or failed", active_socket->fd, (unsigned)len); + + // check if socket is listening + if(getsockopt(active_socket->fd, SOL_SOCKET, SO_ACCEPTCONN, &listening, &socklen) != 0) { #if defined(BSD) /* old FreeBSD versions (and OSX up to Lion) do not support SO_ACCEPTCONN */ listening = 1; #else - TNET_PRINT_LAST_ERROR("getsockopt(SO_ACCEPTCONN, %d) failed\n", active_socket->fd); + TNET_PRINT_LAST_ERROR("getsockopt(SO_ACCEPTCONN, %d) failed\n", active_socket->fd); /* not socket accepted -> no socket to remove */ goto TNET_POLLIN_DONE; #endif - } - if (listening){ - if((fd = accept(active_socket->fd, tsk_null, tsk_null)) != TNET_INVALID_SOCKET){ - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT(fd=%d)", transport->description, fd); - addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null); - TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); - if(active_socket->tlshandle){ - transport_socket_xt* tls_socket; - if((tls_socket = getSocket(context, fd))){ - if(tnet_tls_socket_accept(tls_socket->tlshandle) != 0){ - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); - tnet_transport_remove_socket(transport, &fd); - TNET_PRINT_LAST_ERROR("SSL_accept() failed"); - continue; - } - } - } - } - else{ - TNET_PRINT_LAST_ERROR("accept(%d) failed", active_socket->fd); - remove_socket = 1; - } - } - else{ - TSK_DEBUG_INFO("Closing socket with fd = %d because ioctlt() returned zero or failed", active_socket->fd); - remove_socket = 1; - } - - if(remove_socket){ - fd = active_socket->fd; - tnet_transport_remove_socket(transport, &active_socket->fd); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); - continue; - } - goto TNET_POLLIN_DONE; - } - - if(len <= 0){ + } + if (listening) { + if((fd = accept(active_socket->fd, tsk_null, tsk_null)) != TNET_INVALID_SOCKET) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT(fd=%d)", transport->description, fd); + addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null); + TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); + if(active_socket->tlshandle) { + transport_socket_xt* tls_socket; + if((tls_socket = getSocket(context, fd))) { + if(tnet_tls_socket_accept(tls_socket->tlshandle) != 0) { + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); + tnet_transport_remove_socket(transport, &fd); + TNET_PRINT_LAST_ERROR("SSL_accept() failed"); + continue; + } + } + } + } + else { + TNET_PRINT_LAST_ERROR("accept(%d) failed", active_socket->fd); + remove_socket = 1; + } + } + else { + TSK_DEBUG_INFO("Closing socket with fd = %d because ioctlt() returned zero or failed", active_socket->fd); + remove_socket = 1; + } + + if(remove_socket) { + fd = active_socket->fd; + tnet_transport_remove_socket(transport, &active_socket->fd); + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, fd); + continue; + } + goto TNET_POLLIN_DONE; + } + + if(len <= 0) { #if ANDROID - // workaround for indoona OSX which sends bodiless UDP packets - // vand Android requires to call recv() even if len is equal to zero - if(len == 0 && ret == 0){ - static char __fake_buff[1]; - ret = recv(active_socket->fd, __fake_buff, len, 0); - } + // workaround for indoona OSX which sends bodiless UDP packets + // vand Android requires to call recv() even if len is equal to zero + if(len == 0 && ret == 0) { + static char __fake_buff[1]; + ret = recv(active_socket->fd, __fake_buff, len, 0); + } #endif - goto TNET_POLLIN_DONE; - } - - if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) { - TSK_DEBUG_ERROR("TSK_CALLOC FAILED"); - goto TNET_POLLIN_DONE; - } - - // Retrieve the remote address - if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { - ret = tnet_getpeername(active_socket->fd, &remote_addr); - } - - // Receive the waiting data - if (active_socket->tlshandle) { - int isEncrypted; - tsk_size_t tlslen = len; - if ((ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted)) == 0) { - if (isEncrypted) { - TSK_FREE(buffer); - goto TNET_POLLIN_DONE; - } - if (ret == 0) { - len = ret = tlslen; - } - } - } - else { - if (is_stream) { - ret = tnet_sockfd_recv(active_socket->fd, buffer, len, 0); - } - else { - ret = tnet_sockfd_recvfrom(active_socket->fd, buffer, len, 0, (struct sockaddr*)&remote_addr); - } - } - - if(ret < 0){ - TSK_FREE(buffer); + goto TNET_POLLIN_DONE; + } + + if (!(buffer = tsk_calloc(len, sizeof(uint8_t)))) { + TSK_DEBUG_ERROR("TSK_CALLOC FAILED"); + goto TNET_POLLIN_DONE; + } + + // Retrieve the remote address + if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { + ret = tnet_getpeername(active_socket->fd, &remote_addr); + } + + // Receive the waiting data + if (active_socket->tlshandle) { + int isEncrypted; + tsk_size_t tlslen = len; + if ((ret = tnet_tls_socket_recv(active_socket->tlshandle, &buffer, &tlslen, &isEncrypted)) == 0) { + if (isEncrypted) { + TSK_FREE(buffer); + goto TNET_POLLIN_DONE; + } + if (ret == 0) { + len = ret = tlslen; + } + } + } + else { + if (is_stream) { + ret = tnet_sockfd_recv(active_socket->fd, buffer, len, 0); + } + else { + ret = tnet_sockfd_recvfrom(active_socket->fd, buffer, len, 0, (struct sockaddr*)&remote_addr); + } + } + + if(ret < 0) { + TSK_FREE(buffer); status = tnet_geterrno(); - // do not remove the socket for i/o pending errors + // do not remove the socket for i/o pending errors if (status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_INPROGRESS || status == TNET_ERROR_EAGAIN) { TSK_DEBUG_WARN("recv returned error code:%d", status); } @@ -805,61 +802,62 @@ void *tnet_transport_mainthread(void *param) TNET_PRINT_LAST_ERROR("recv/recvfrom have failed"); removeSocket(i, context); } - goto TNET_POLLIN_DONE; - } - - if((len != (tsk_size_t)ret) && len){ - len = (tsk_size_t)ret; - // buffer = tsk_realloc(buffer, len); - } - - if(len > 0){ + goto TNET_POLLIN_DONE; + } + + if((len != (tsk_size_t)ret) && len) { + len = (tsk_size_t)ret; + // buffer = tsk_realloc(buffer, len); + } + + if(len > 0) { transport->bytes_in += len; - e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); - e->data = buffer, buffer = tsk_null; - e->size = len; - e->remote_addr = remote_addr; - - TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); - } - TSK_FREE(buffer); + e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); + e->data = buffer, buffer = tsk_null; + e->size = len; + e->remote_addr = remote_addr; + + TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); + } + TSK_FREE(buffer); TNET_POLLIN_DONE: - /*context->ufds[i].revents &= ~TNET_POLLIN*/; - } + /*context->ufds[i].revents &= ~TNET_POLLIN*/ + ; + } - /*================== TNET_POLLOUT ==================*/ - if(context->ufds[i].revents & TNET_POLLOUT){ - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLOUT", transport->description); - if(!active_socket->connected){ - active_socket->connected = tsk_true; - TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); - } - //else{ - context->ufds[i].events &= ~TNET_POLLOUT; - //} - } + /*================== TNET_POLLOUT ==================*/ + if(context->ufds[i].revents & TNET_POLLOUT) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLOUT", transport->description); + if(!active_socket->connected) { + active_socket->connected = tsk_true; + TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); + } + //else{ + context->ufds[i].events &= ~TNET_POLLOUT; + //} + } - /*================== TNET_POLLPRI ==================*/ - if(context->ufds[i].revents & TNET_POLLPRI){ - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLPRI", transport->description); - } + /*================== TNET_POLLPRI ==================*/ + if(context->ufds[i].revents & TNET_POLLPRI) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- TNET_POLLPRI", transport->description); + } context->ufds[i].revents = 0; - }/* for */ + }/* for */ done: - /* unlock context */ - tsk_safeobj_unlock(context); + /* unlock context */ + tsk_safeobj_unlock(context); - } /* while */ + } /* while */ bail: - - TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}", transport->description, transport->master->ip, transport->master->port); - return 0; + + TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d}", transport->description, transport->master->ip, transport->master->port); + return 0; } @@ -871,7 +869,7 @@ bail: void* tnet_transport_context_create() { - return tsk_object_new(tnet_transport_context_def_t); + return tsk_object_new(tnet_transport_context_def_t); } @@ -880,32 +878,31 @@ void* tnet_transport_context_create() // static tsk_object_t* transport_context_ctor(tsk_object_t * self, va_list * app) { - transport_context_t *context = self; - if(context){ + transport_context_t *context = self; + if(context) { context->pipeR = context->pipeW = -1; - tsk_safeobj_init(context); - } - return self; + tsk_safeobj_init(context); + } + return self; } static tsk_object_t* transport_context_dtor(tsk_object_t * self) -{ - transport_context_t *context = self; - if(context){ - while(context->count){ - removeSocket(0, context); - } - tsk_safeobj_deinit(context); - } - return self; +{ + transport_context_t *context = self; + if(context) { + while(context->count) { + removeSocket(0, context); + } + tsk_safeobj_deinit(context); + } + return self; } -static const tsk_object_def_t tnet_transport_context_def_s = -{ -sizeof(transport_context_t), -transport_context_ctor, -transport_context_dtor, -tsk_null, +static const tsk_object_def_t tnet_transport_context_def_s = { + sizeof(transport_context_t), + transport_context_ctor, + transport_context_dtor, + tsk_null, }; const tsk_object_def_t *tnet_transport_context_def_t = &tnet_transport_context_def_s; diff --git a/tinyNET/src/tnet_transport_win32.c b/tinyNET/src/tnet_transport_win32.c index 6f7886f..626cccc 100755 --- a/tinyNET/src/tnet_transport_win32.c +++ b/tinyNET/src/tnet_transport_win32.c @@ -36,28 +36,26 @@ #if TNET_UNDER_WINDOWS && !TNET_USE_POLL /*== Socket description ==*/ -typedef struct transport_socket_xs -{ - tnet_fd_t fd; - unsigned owner : 1; - unsigned connected : 1; - unsigned paused : 1; - - tnet_socket_type_t type; - tnet_tls_socket_handle_t* tlshandle; +typedef struct transport_socket_xs { + tnet_fd_t fd; + unsigned owner : 1; + unsigned connected : 1; + unsigned paused : 1; + + tnet_socket_type_t type; + tnet_tls_socket_handle_t* tlshandle; } transport_socket_xt; /*== Transport context structure definition ==*/ -typedef struct transport_context_s -{ - TSK_DECLARE_OBJECT; +typedef struct transport_context_s { + TSK_DECLARE_OBJECT; - tsk_size_t count; - WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS]; - transport_socket_xt* sockets[WSA_MAXIMUM_WAIT_EVENTS]; + tsk_size_t count; + WSAEVENT events[WSA_MAXIMUM_WAIT_EVENTS]; + transport_socket_xt* sockets[WSA_MAXIMUM_WAIT_EVENTS]; - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } transport_context_t; @@ -68,54 +66,52 @@ static int removeSocket(int index, transport_context_t *context); /* Checks if socket is connected */ int tnet_transport_isconnected(const tnet_transport_handle_t *handle, tnet_fd_t fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t *context; - tsk_size_t i; - - if (!transport) - { - TSK_DEBUG_ERROR("Invalid server handle."); - return 0; - } - - context = (transport_context_t*)transport->context; - for (i = 0; i < context->count; i++) - { - const transport_socket_xt* socket = context->sockets[i]; - if (socket->fd == fd){ - return socket->connected; - } - } - - return 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t *context; + tsk_size_t i; + + if (!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return 0; + } + + context = (transport_context_t*)transport->context; + for (i = 0; i < context->count; i++) { + const transport_socket_xt* socket = context->sockets[i]; + if (socket->fd == fd) { + return socket->connected; + } + } + + return 0; } int tnet_transport_have_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; + tnet_transport_t *transport = (tnet_transport_t*)handle; - if (!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return 0; - } + if (!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return 0; + } - return (getSocket((transport_context_t*)transport->context, fd) != 0); + return (getSocket((transport_context_t*)transport->context, fd) != 0); } const tnet_tls_socket_handle_t* tnet_transport_get_tlshandle(const tnet_transport_handle_t *handle, tnet_fd_t fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_socket_xt *socket; - - if (!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return 0; - } - - if ((socket = getSocket((transport_context_t*)transport->context, fd))){ - return socket->tlshandle; - } - return 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_socket_xt *socket; + + if (!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return 0; + } + + if ((socket = getSocket((transport_context_t*)transport->context, fd))) { + return socket->tlshandle; + } + return 0; } int tnet_transport_add_socket_2(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle, const char* dst_host, tnet_port_t dst_port, struct tnet_proxyinfo_s* proxy_info) @@ -132,102 +128,102 @@ int tnet_transport_add_socket_2(const tnet_transport_handle_t *handle, tnet_fd_t */ int tnet_transport_add_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tnet_socket_type_t type, tsk_bool_t take_ownership, tsk_bool_t isClient, tnet_tls_socket_handle_t* tlsHandle) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t* context; - int ret = -1; - - if (!transport){ - TSK_DEBUG_ERROR("Invalid server handle."); - return ret; - } - - if (!(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid context."); - return -2; - } - - if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)){ - transport->tls.enabled = tsk_true; - } - - addSocket(fd, type, transport, take_ownership, isClient, tlsHandle); - - if (WSAEventSelect(fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR){ - removeSocket((int)(context->count - 1), context); - TNET_PRINT_LAST_ERROR("WSAEventSelect have failed."); - return -1; - } - - /* Signal if transport is running */ - if (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started){ - if (WSASetEvent(context->events[0])){ - TSK_DEBUG_INFO("New socket added to the network transport."); - return 0; - } - TSK_DEBUG_ERROR("Transport not started yet"); - return -1; - } - - TSK_DEBUG_INFO("Adding socket delayed"); - return 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t* context; + int ret = -1; + + if (!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + return ret; + } + + if (!(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid context."); + return -2; + } + + if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) { + transport->tls.enabled = tsk_true; + } + + addSocket(fd, type, transport, take_ownership, isClient, tlsHandle); + + if (WSAEventSelect(fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR) { + removeSocket((int)(context->count - 1), context); + TNET_PRINT_LAST_ERROR("WSAEventSelect have failed."); + return -1; + } + + /* Signal if transport is running */ + if (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) { + if (WSASetEvent(context->events[0])) { + TSK_DEBUG_INFO("New socket added to the network transport."); + return 0; + } + TSK_DEBUG_ERROR("Transport not started yet"); + return -1; + } + + TSK_DEBUG_INFO("Adding socket delayed"); + return 0; } int tnet_transport_pause_socket(const tnet_transport_handle_t *handle, tnet_fd_t fd, tsk_bool_t pause) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t *context; - transport_socket_xt* socket; - - if (!transport || !(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if ((socket = getSocket(context, fd))){ - socket->paused = pause; - } - else{ - TSK_DEBUG_WARN("Socket does not exist in this context"); - } - return 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t *context; + transport_socket_xt* socket; + + if (!transport || !(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if ((socket = getSocket(context, fd))) { + socket->paused = pause; + } + else { + TSK_DEBUG_WARN("Socket does not exist in this context"); + } + return 0; } /* Remove socket */ int tnet_transport_remove_socket(const tnet_transport_handle_t *handle, tnet_fd_t* fd) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - transport_context_t *context; - int ret = -1; - tsk_size_t i; - tsk_bool_t found = tsk_false; - - if (!transport || !(context = (transport_context_t*)transport->context)){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - for (i = 0; i < context->count; i++){ - if (context->sockets[i]->fd == *fd){ - removeSocket((int)i, context); - found = tsk_true; - TSK_RUNNABLE_ENQUEUE(transport, event_removed, transport->callback_data, *fd); - *fd = TNET_INVALID_FD; - break; - } - } - - if (found){ - /* Signal */ - if (WSASetEvent(context->events[0])){ - TSK_DEBUG_INFO("Old socket removed from the network transport."); - return 0; - } - } - - // ... - - return -1; + tnet_transport_t *transport = (tnet_transport_t*)handle; + transport_context_t *context; + int ret = -1; + tsk_size_t i; + tsk_bool_t found = tsk_false; + + if (!transport || !(context = (transport_context_t*)transport->context)) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + for (i = 0; i < context->count; i++) { + if (context->sockets[i]->fd == *fd) { + removeSocket((int)i, context); + found = tsk_true; + TSK_RUNNABLE_ENQUEUE(transport, event_removed, transport->callback_data, *fd); + *fd = TNET_INVALID_FD; + break; + } + } + + if (found) { + /* Signal */ + if (WSASetEvent(context->events[0])) { + TSK_DEBUG_INFO("Old socket removed from the network transport."); + return 0; + } + } + + // ... + + return -1; } /* @@ -235,58 +231,58 @@ int tnet_transport_remove_socket(const tnet_transport_handle_t *handle, tnet_fd_ */ tsk_size_t tnet_transport_send(const tnet_transport_handle_t *handle, tnet_fd_t from, const void* buf, tsk_size_t size) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - int ret = -1; - tsk_size_t sent = 0; - - if (!transport){ - TSK_DEBUG_ERROR("Invalid transport handle."); - goto bail; - } - - while (sent < size) { - int try_guard = 10; - if (transport->tls.enabled){ - transport_socket_xt* socket = getSocket(transport->context, from); - if (socket && socket->tlshandle) { - if (tnet_tls_socket_send(socket->tlshandle, buf, size) == 0) { - sent = size; - } - else { - TSK_DEBUG_ERROR("Tring to use a socket without TLS handle to send data"); - } - goto bail; // TLS do not retry - } - } - else { - WSABUF wsaBuffer; - DWORD numberOfBytesSent = 0; - wsaBuffer.buf = ((CHAR*)buf) + sent; - wsaBuffer.len = (ULONG)(size - sent); + tnet_transport_t *transport = (tnet_transport_t*)handle; + int ret = -1; + tsk_size_t sent = 0; + + if (!transport) { + TSK_DEBUG_ERROR("Invalid transport handle."); + goto bail; + } + + while (sent < size) { + int try_guard = 10; + if (transport->tls.enabled) { + transport_socket_xt* socket = getSocket(transport->context, from); + if (socket && socket->tlshandle) { + if (tnet_tls_socket_send(socket->tlshandle, buf, size) == 0) { + sent = size; + } + else { + TSK_DEBUG_ERROR("Tring to use a socket without TLS handle to send data"); + } + goto bail; // TLS do not retry + } + } + else { + WSABUF wsaBuffer; + DWORD numberOfBytesSent = 0; + wsaBuffer.buf = ((CHAR*)buf) + sent; + wsaBuffer.len = (ULONG)(size - sent); try_again: - if ((ret = WSASend(from, &wsaBuffer, 1, &numberOfBytesSent, 0, NULL, NULL)) == SOCKET_ERROR) { - ret = WSAGetLastError(); - if (ret == WSA_IO_PENDING || ret == WSAEWOULDBLOCK) { - TSK_DEBUG_INFO("SendTCP() - WouldBlock. Retrying..."); - if (try_guard--) { - tsk_thread_sleep(10); - goto try_again; - } - } - else { - TNET_PRINT_LAST_ERROR("WSASend have failed."); - goto bail; - } - } - else { - sent += numberOfBytesSent; - } - } - } + if ((ret = WSASend(from, &wsaBuffer, 1, &numberOfBytesSent, 0, NULL, NULL)) == SOCKET_ERROR) { + ret = WSAGetLastError(); + if (ret == WSA_IO_PENDING || ret == WSAEWOULDBLOCK) { + TSK_DEBUG_INFO("SendTCP() - WouldBlock. Retrying..."); + if (try_guard--) { + tsk_thread_sleep(10); + goto try_again; + } + } + else { + TNET_PRINT_LAST_ERROR("WSASend have failed."); + goto bail; + } + } + else { + sent += numberOfBytesSent; + } + } + } bail: transport->bytes_out += sent; - return sent; + return sent; } /* @@ -294,27 +290,27 @@ bail: */ tsk_size_t tnet_transport_sendto(const tnet_transport_handle_t *handle, tnet_fd_t from, const struct sockaddr *to, const void* buf, tsk_size_t size) { - tnet_transport_t *transport = (tnet_transport_t*)handle; - int numberOfBytesSent = 0; + tnet_transport_t *transport = (tnet_transport_t*)handle; + int numberOfBytesSent = 0; - if (!transport) { - TSK_DEBUG_ERROR("Invalid server handle."); - goto bail; - } + if (!transport) { + TSK_DEBUG_ERROR("Invalid server handle."); + goto bail; + } - if (!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { - TSK_DEBUG_ERROR("In order to use sendto() you must use an udp transport."); - goto bail; - } + if (!TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { + TSK_DEBUG_ERROR("In order to use sendto() you must use an udp transport."); + goto bail; + } - if ((numberOfBytesSent = tnet_sockfd_sendto(from, to, buf, size)) <= 0) { - TNET_PRINT_LAST_ERROR("sendto have failed."); - goto bail; - } + if ((numberOfBytesSent = tnet_sockfd_sendto(from, to, buf, size)) <= 0) { + TNET_PRINT_LAST_ERROR("sendto have failed."); + goto bail; + } bail: transport->bytes_out += numberOfBytesSent; - return numberOfBytesSent; + return numberOfBytesSent; } @@ -327,472 +323,472 @@ bail: /*== CAllback function to check if we should accept the new socket or not == */ int CALLBACK AcceptCondFunc(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS lpSQos, LPQOS lpGQos, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData, GROUP FAR *Group, DWORD_PTR CallbackData) { - transport_context_t *context = (transport_context_t*)CallbackData; - return context->count < WSA_MAXIMUM_WAIT_EVENTS ? CF_ACCEPT : CF_REJECT; + transport_context_t *context = (transport_context_t*)CallbackData; + return context->count < WSA_MAXIMUM_WAIT_EVENTS ? CF_ACCEPT : CF_REJECT; } /*== Get socket ==*/ static transport_socket_xt* getSocket(transport_context_t *context, tnet_fd_t fd) { - tsk_size_t i; - transport_socket_xt* ret = 0; - - if (context) { - tsk_safeobj_lock(context); - for (i = 0; i < context->count; i++) { - if (context->sockets[i]->fd == fd) { - ret = context->sockets[i]; - break; - } - } - tsk_safeobj_unlock(context); - } - - return ret; + tsk_size_t i; + transport_socket_xt* ret = 0; + + if (context) { + tsk_safeobj_lock(context); + for (i = 0; i < context->count; i++) { + if (context->sockets[i]->fd == fd) { + ret = context->sockets[i]; + break; + } + } + tsk_safeobj_unlock(context); + } + + return ret; } /*== Add new socket ==*/ static int addSocket(tnet_fd_t fd, tnet_socket_type_t type, tnet_transport_t *transport, tsk_bool_t take_ownership, tsk_bool_t is_client, tnet_tls_socket_handle_t* tlsHandle) { - transport_context_t *context; + transport_context_t *context; - if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) { + if (TNET_SOCKET_TYPE_IS_TLS(type) || TNET_SOCKET_TYPE_IS_WSS(type)) { #if !HAVE_OPENSSL - TSK_DEBUG_ERROR("Cannot create TLS socket: OpenSSL missing"); - return -2; + TSK_DEBUG_ERROR("Cannot create TLS socket: OpenSSL missing"); + return -2; #endif - } - - if ((context = transport ? transport->context : tsk_null)) { - transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt)); - sock->fd = fd; - sock->type = type; - sock->owner = take_ownership ? 1 : 0; - - if ((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled) { - if (tlsHandle) { - sock->tlshandle = tsk_object_ref(tlsHandle); - } - else{ + } + + if ((context = transport ? transport->context : tsk_null)) { + transport_socket_xt *sock = tsk_calloc(1, sizeof(transport_socket_xt)); + sock->fd = fd; + sock->type = type; + sock->owner = take_ownership ? 1 : 0; + + if ((TNET_SOCKET_TYPE_IS_TLS(sock->type) || TNET_SOCKET_TYPE_IS_WSS(sock->type)) && transport->tls.enabled) { + if (tlsHandle) { + sock->tlshandle = tsk_object_ref(tlsHandle); + } + else { #if HAVE_OPENSSL - sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server); + sock->tlshandle = tnet_tls_socket_create(sock->fd, is_client ? transport->tls.ctx_client : transport->tls.ctx_server); #endif - } - } + } + } - tsk_safeobj_lock(context); - context->events[context->count] = WSACreateEvent(); - context->sockets[context->count] = sock; + tsk_safeobj_lock(context); + context->events[context->count] = WSACreateEvent(); + context->sockets[context->count] = sock; - context->count++; + context->count++; - TSK_DEBUG_INFO("Transport[%s] sockets count = %u", transport->description, context->count); + TSK_DEBUG_INFO("Transport[%s] sockets count = %u", transport->description, context->count); - tsk_safeobj_unlock(context); + tsk_safeobj_unlock(context); - return 0; - } - else { - TSK_DEBUG_ERROR("Context is Null."); - return -1; - } - } + return 0; + } + else { + TSK_DEBUG_ERROR("Context is Null."); + return -1; + } +} /*== Remove socket ==*/ static int removeSocket(int index, transport_context_t *context) { - tsk_size_t i; + tsk_size_t i; - tsk_safeobj_lock(context); + tsk_safeobj_lock(context); - if (index < (int)context->count) { + if (index < (int)context->count) { - /* Close the socket if we are the owner. */ - if (context->sockets[index]->owner) { - tnet_sockfd_close(&(context->sockets[index]->fd)); - } + /* Close the socket if we are the owner. */ + if (context->sockets[index]->owner) { + tnet_sockfd_close(&(context->sockets[index]->fd)); + } - /* Free tls context */ - if (context->sockets[index]->tlshandle) { - TSK_OBJECT_SAFE_FREE(context->sockets[index]->tlshandle); - } - // Free socket - TSK_FREE(context->sockets[index]); + /* Free tls context */ + if (context->sockets[index]->tlshandle) { + TSK_OBJECT_SAFE_FREE(context->sockets[index]->tlshandle); + } + // Free socket + TSK_FREE(context->sockets[index]); - // Close event - WSACloseEvent(context->events[index]); + // Close event + WSACloseEvent(context->events[index]); - for (i = index; i < context->count - 1; i++) { - context->sockets[i] = context->sockets[i + 1]; - context->events[i] = context->events[i + 1]; - } + for (i = index; i < context->count - 1; i++) { + context->sockets[i] = context->sockets[i + 1]; + context->events[i] = context->events[i + 1]; + } - context->sockets[context->count - 1] = 0; - context->events[context->count - 1] = 0; + context->sockets[context->count - 1] = 0; + context->events[context->count - 1] = 0; - context->count--; - TSK_DEBUG_INFO("Transport sockets count = %u", context->count); - } + context->count--; + TSK_DEBUG_INFO("Transport sockets count = %u", context->count); + } - tsk_safeobj_unlock(context); + tsk_safeobj_unlock(context); - return 0; + return 0; } /*=== stop all threads */ int tnet_transport_stop(tnet_transport_t *transport) { - int ret; - - if ((ret = tsk_runnable_stop(TSK_RUNNABLE(transport)))){ - return ret; - } - - if (transport->mainThreadId[0]){ - WSASetEvent(((transport_context_t*)(transport->context))->events[0]); - return tsk_thread_join(transport->mainThreadId); - } - else{ - /* already stoppped */ - return 0; - } + int ret; + + if ((ret = tsk_runnable_stop(TSK_RUNNABLE(transport)))) { + return ret; + } + + if (transport->mainThreadId[0]) { + WSASetEvent(((transport_context_t*)(transport->context))->events[0]); + return tsk_thread_join(transport->mainThreadId); + } + else { + /* already stoppped */ + return 0; + } } int tnet_transport_prepare(tnet_transport_t *transport) { - int ret = -1; - transport_context_t *context; - - if (!transport || !transport->context){ - TSK_DEBUG_ERROR("Invalid parameter."); - return -1; - } - else{ - context = transport->context; - } - - if (transport->prepared){ - TSK_DEBUG_ERROR("Transport already prepared."); - return -2; - } - - /* Prepare master */ - if (!transport->master){ - if ((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))){ - tsk_strupdate(&transport->local_ip, transport->master->ip); - transport->bind_local_port = transport->master->port; - } - else{ - TSK_DEBUG_ERROR("Failed to create master socket"); - return -3; - } - } - - /* Start listening */ - if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { - if ((ret = tnet_sockfd_listen(transport->master->fd, WSA_MAXIMUM_WAIT_EVENTS))) { - TNET_PRINT_LAST_ERROR("listen have failed."); - goto bail; - } - } - - /* Add the master socket to the context. */ - // don't take ownership: will be closed by the dctor() when refCount==0 - // otherwise will be closed twice: dctor() and removeSocket() - if ((ret = addSocket(transport->master->fd, transport->master->type, transport, tsk_false, tsk_false, tsk_null))) { - TSK_DEBUG_ERROR("Failed to add master socket"); - goto bail; - } - - /* set events on master socket */ - if ((ret = WSAEventSelect(transport->master->fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR)) { - TNET_PRINT_LAST_ERROR("WSAEventSelect have failed."); - goto bail; - } - - transport->prepared = tsk_true; + int ret = -1; + transport_context_t *context; + + if (!transport || !transport->context) { + TSK_DEBUG_ERROR("Invalid parameter."); + return -1; + } + else { + context = transport->context; + } + + if (transport->prepared) { + TSK_DEBUG_ERROR("Transport already prepared."); + return -2; + } + + /* Prepare master */ + if (!transport->master) { + if ((transport->master = tnet_socket_create(transport->local_host, transport->req_local_port, transport->type))) { + tsk_strupdate(&transport->local_ip, transport->master->ip); + transport->bind_local_port = transport->master->port; + } + else { + TSK_DEBUG_ERROR("Failed to create master socket"); + return -3; + } + } + + /* Start listening */ + if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { + if ((ret = tnet_sockfd_listen(transport->master->fd, WSA_MAXIMUM_WAIT_EVENTS))) { + TNET_PRINT_LAST_ERROR("listen have failed."); + goto bail; + } + } + + /* Add the master socket to the context. */ + // don't take ownership: will be closed by the dctor() when refCount==0 + // otherwise will be closed twice: dctor() and removeSocket() + if ((ret = addSocket(transport->master->fd, transport->master->type, transport, tsk_false, tsk_false, tsk_null))) { + TSK_DEBUG_ERROR("Failed to add master socket"); + goto bail; + } + + /* set events on master socket */ + if ((ret = WSAEventSelect(transport->master->fd, context->events[context->count - 1], FD_ALL_EVENTS) == SOCKET_ERROR)) { + TNET_PRINT_LAST_ERROR("WSAEventSelect have failed."); + goto bail; + } + + transport->prepared = tsk_true; bail: - return ret; + return ret; } int tnet_transport_unprepare(tnet_transport_t *transport) { - int ret = -1; - transport_context_t *context; - - if (!transport || !transport->context){ - TSK_DEBUG_ERROR("Invalid parameter."); - return -1; - } - else{ - context = transport->context; - } - - if (!transport->prepared){ - return 0; - } - - transport->prepared = tsk_false; - - while (context->count){ - removeSocket(0, context); // safe - } - // destroy master as it has been close by removeSocket() - TSK_OBJECT_SAFE_FREE(transport->master); - - return 0; + int ret = -1; + transport_context_t *context; + + if (!transport || !transport->context) { + TSK_DEBUG_ERROR("Invalid parameter."); + return -1; + } + else { + context = transport->context; + } + + if (!transport->prepared) { + return 0; + } + + transport->prepared = tsk_false; + + while (context->count) { + removeSocket(0, context); // safe + } + // destroy master as it has been close by removeSocket() + TSK_OBJECT_SAFE_FREE(transport->master); + + return 0; } /*=== Main thread */ void* TSK_STDCALL tnet_transport_mainthread(void *param) { - tnet_transport_t *transport = (tnet_transport_t*)param; - transport_context_t *context = (transport_context_t*)transport->context; - DWORD evt; - WSANETWORKEVENTS networkEvents; - DWORD flags = 0; - int ret; - - struct sockaddr_storage remote_addr = { 0 }; - WSAEVENT active_event; - transport_socket_xt* active_socket; - int index; - - TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); - - while (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) { - /* Wait for multiple events */ - if ((evt = WSAWaitForMultipleEvents((DWORD)context->count, context->events, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { - TNET_PRINT_LAST_ERROR("WSAWaitForMultipleEvents have failed."); - goto bail; - } - - if (!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) { - goto bail; - } - - /* lock context */ - tsk_safeobj_lock(context); - - /* Get active event and socket */ - index = (evt - WSA_WAIT_EVENT_0); - active_event = context->events[index]; - if (!(active_socket = context->sockets[index])) { - goto done; - } - - /* Get the network events flags */ - if (WSAEnumNetworkEvents(active_socket->fd, active_event, &networkEvents) == SOCKET_ERROR) { - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); - TNET_PRINT_LAST_ERROR("WSAEnumNetworkEvents have failed."); - - tsk_safeobj_unlock(context); - goto bail; - } - - /*================== FD_ACCEPT ==================*/ - if (networkEvents.lNetworkEvents & FD_ACCEPT) { - tnet_fd_t fd; - - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT", transport->description); - - if (networkEvents.iErrorCode[FD_ACCEPT_BIT]) { - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); - TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); - goto done; - } - - /* Accept the connection */ - if ((fd = (tnet_fd_t)WSAAccept(active_socket->fd, NULL, NULL, AcceptCondFunc, (DWORD_PTR)context)) != INVALID_SOCKET) { - /* Add the new fd to the server context */ - addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null); - if (active_socket->tlshandle) { - transport_socket_xt* tls_socket; - if ((tls_socket = getSocket(context, fd))) { - if (tnet_tls_socket_accept(tls_socket->tlshandle)) { - tnet_transport_remove_socket(transport, &fd); - TNET_PRINT_LAST_ERROR("SSL_accept() failed"); - goto done; - } - } - } - if (WSAEventSelect(fd, context->events[context->count - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) { - tnet_transport_remove_socket(transport, &fd); - TNET_PRINT_LAST_ERROR("WSAEventSelect() have failed."); - goto done; - } - TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); - } - else { - TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); - goto done; - } - - - - - } - - /*================== FD_CONNECT ==================*/ - if (networkEvents.lNetworkEvents & FD_CONNECT) { - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CONNECT", transport->description); - - if (networkEvents.iErrorCode[FD_CONNECT_BIT]) { - tnet_fd_t fd = active_socket->fd; - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); - tnet_transport_remove_socket(transport, &fd); - TNET_PRINT_LAST_ERROR("CONNECT FAILED."); - goto done; - } - else { - TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); - active_socket->connected = 1; - } - } - - - /*================== FD_READ ==================*/ - if (networkEvents.lNetworkEvents & FD_READ) { - DWORD readCount = 0; - WSABUF wsaBuffer; - - /* TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_READ", transport->description); */ - - /* check whether the socket is paused or not */ - if (active_socket->paused){ - TSK_DEBUG_INFO("Socket is paused"); - goto FD_READ_DONE; - } - - if (networkEvents.iErrorCode[FD_READ_BIT]) { - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); - TNET_PRINT_LAST_ERROR("READ FAILED."); - goto done; - } - - /* Retrieve the amount of pending data */ - if (tnet_ioctlt(active_socket->fd, FIONREAD, &(wsaBuffer.len)) < 0) { - TNET_PRINT_LAST_ERROR("IOCTLT FAILED."); - goto done; - } - - if (!wsaBuffer.len) { - goto done; - } - - /* Alloc data */ - if (!(wsaBuffer.buf = tsk_calloc(wsaBuffer.len, sizeof(uint8_t)))) { - goto done; - } - - /* Retrieve the remote address */ - if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { - ret = tnet_getpeername(active_socket->fd, &remote_addr); - } - - /* Receive the waiting data. */ - if (active_socket->tlshandle) { - int isEncrypted; - tsk_size_t len = wsaBuffer.len; - if (!(ret = tnet_tls_socket_recv(active_socket->tlshandle, &wsaBuffer.buf, &len, &isEncrypted))) { - if (isEncrypted) { - TSK_FREE(wsaBuffer.buf); - goto done; - } - wsaBuffer.len = (ULONG)len; - } - } - else { - if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { - ret = WSARecv(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, 0, 0); - } - else { - int len = sizeof(remote_addr); - ret = WSARecvFrom(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, - (struct sockaddr*)&remote_addr, &len, 0, 0); - } - if (readCount < wsaBuffer.len) { - wsaBuffer.len = readCount; - /* wsaBuffer.buf = tsk_realloc(wsaBuffer.buf, readCount); */ - } - } - - if (ret) { - ret = WSAGetLastError(); - if (ret == WSAEWOULDBLOCK) { - // Doesn't (always) mean congestion but... another thread is also poll()ing the FD. For example, when TURN session has a reference to the fd. - TSK_DEBUG_WARN("WSAEWOULDBLOCK error for READ SSESSION"); - } - else if (ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { - /* For DGRAM ==> The sent packet gernerated "ICMP Destination/Port unreachable" result. */ - TSK_FREE(wsaBuffer.buf); - goto done; // ignore and retry. - } - else { - TSK_FREE(wsaBuffer.buf); - - removeSocket(index, context); - TNET_PRINT_LAST_ERROR("WSARecv have failed."); - goto done; - } - } - else - { - tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); + tnet_transport_t *transport = (tnet_transport_t*)param; + transport_context_t *context = (transport_context_t*)transport->context; + DWORD evt; + WSANETWORKEVENTS networkEvents; + DWORD flags = 0; + int ret; + + struct sockaddr_storage remote_addr = { 0 }; + WSAEVENT active_event; + transport_socket_xt* active_socket; + int index; + + TSK_DEBUG_INFO("Starting [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); + + while (TSK_RUNNABLE(transport)->running || TSK_RUNNABLE(transport)->started) { + /* Wait for multiple events */ + if ((evt = WSAWaitForMultipleEvents((DWORD)context->count, context->events, FALSE, WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED) { + TNET_PRINT_LAST_ERROR("WSAWaitForMultipleEvents have failed."); + goto bail; + } + + if (!TSK_RUNNABLE(transport)->running && !TSK_RUNNABLE(transport)->started) { + goto bail; + } + + /* lock context */ + tsk_safeobj_lock(context); + + /* Get active event and socket */ + index = (evt - WSA_WAIT_EVENT_0); + active_event = context->events[index]; + if (!(active_socket = context->sockets[index])) { + goto done; + } + + /* Get the network events flags */ + if (WSAEnumNetworkEvents(active_socket->fd, active_event, &networkEvents) == SOCKET_ERROR) { + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); + TNET_PRINT_LAST_ERROR("WSAEnumNetworkEvents have failed."); + + tsk_safeobj_unlock(context); + goto bail; + } + + /*================== FD_ACCEPT ==================*/ + if (networkEvents.lNetworkEvents & FD_ACCEPT) { + tnet_fd_t fd; + + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_ACCEPT", transport->description); + + if (networkEvents.iErrorCode[FD_ACCEPT_BIT]) { + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); + TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); + goto done; + } + + /* Accept the connection */ + if ((fd = (tnet_fd_t)WSAAccept(active_socket->fd, NULL, NULL, AcceptCondFunc, (DWORD_PTR)context)) != INVALID_SOCKET) { + /* Add the new fd to the server context */ + addSocket(fd, transport->master->type, transport, tsk_true, tsk_false, tsk_null); + if (active_socket->tlshandle) { + transport_socket_xt* tls_socket; + if ((tls_socket = getSocket(context, fd))) { + if (tnet_tls_socket_accept(tls_socket->tlshandle)) { + tnet_transport_remove_socket(transport, &fd); + TNET_PRINT_LAST_ERROR("SSL_accept() failed"); + goto done; + } + } + } + if (WSAEventSelect(fd, context->events[context->count - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR) { + tnet_transport_remove_socket(transport, &fd); + TNET_PRINT_LAST_ERROR("WSAEventSelect() have failed."); + goto done; + } + TSK_RUNNABLE_ENQUEUE(transport, event_accepted, transport->callback_data, fd); + } + else { + TNET_PRINT_LAST_ERROR("ACCEPT FAILED."); + goto done; + } + + + + + } + + /*================== FD_CONNECT ==================*/ + if (networkEvents.lNetworkEvents & FD_CONNECT) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CONNECT", transport->description); + + if (networkEvents.iErrorCode[FD_CONNECT_BIT]) { + tnet_fd_t fd = active_socket->fd; + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, fd); + tnet_transport_remove_socket(transport, &fd); + TNET_PRINT_LAST_ERROR("CONNECT FAILED."); + goto done; + } + else { + TSK_RUNNABLE_ENQUEUE(transport, event_connected, transport->callback_data, active_socket->fd); + active_socket->connected = 1; + } + } + + + /*================== FD_READ ==================*/ + if (networkEvents.lNetworkEvents & FD_READ) { + DWORD readCount = 0; + WSABUF wsaBuffer; + + /* TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_READ", transport->description); */ + + /* check whether the socket is paused or not */ + if (active_socket->paused) { + TSK_DEBUG_INFO("Socket is paused"); + goto FD_READ_DONE; + } + + if (networkEvents.iErrorCode[FD_READ_BIT]) { + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); + TNET_PRINT_LAST_ERROR("READ FAILED."); + goto done; + } + + /* Retrieve the amount of pending data */ + if (tnet_ioctlt(active_socket->fd, FIONREAD, &(wsaBuffer.len)) < 0) { + TNET_PRINT_LAST_ERROR("IOCTLT FAILED."); + goto done; + } + + if (!wsaBuffer.len) { + goto done; + } + + /* Alloc data */ + if (!(wsaBuffer.buf = tsk_calloc(wsaBuffer.len, sizeof(uint8_t)))) { + goto done; + } + + /* Retrieve the remote address */ + if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { + ret = tnet_getpeername(active_socket->fd, &remote_addr); + } + + /* Receive the waiting data. */ + if (active_socket->tlshandle) { + int isEncrypted; + tsk_size_t len = wsaBuffer.len; + if (!(ret = tnet_tls_socket_recv(active_socket->tlshandle, &wsaBuffer.buf, &len, &isEncrypted))) { + if (isEncrypted) { + TSK_FREE(wsaBuffer.buf); + goto done; + } + wsaBuffer.len = (ULONG)len; + } + } + else { + if (TNET_SOCKET_TYPE_IS_STREAM(transport->master->type)) { + ret = WSARecv(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, 0, 0); + } + else { + int len = sizeof(remote_addr); + ret = WSARecvFrom(active_socket->fd, &wsaBuffer, 1, &readCount, &flags, + (struct sockaddr*)&remote_addr, &len, 0, 0); + } + if (readCount < wsaBuffer.len) { + wsaBuffer.len = readCount; + /* wsaBuffer.buf = tsk_realloc(wsaBuffer.buf, readCount); */ + } + } + + if (ret) { + ret = WSAGetLastError(); + if (ret == WSAEWOULDBLOCK) { + // Doesn't (always) mean congestion but... another thread is also poll()ing the FD. For example, when TURN session has a reference to the fd. + TSK_DEBUG_WARN("WSAEWOULDBLOCK error for READ SSESSION"); + } + else if (ret == WSAECONNRESET && TNET_SOCKET_TYPE_IS_DGRAM(transport->master->type)) { + /* For DGRAM ==> The sent packet gernerated "ICMP Destination/Port unreachable" result. */ + TSK_FREE(wsaBuffer.buf); + goto done; // ignore and retry. + } + else { + TSK_FREE(wsaBuffer.buf); + + removeSocket(index, context); + TNET_PRINT_LAST_ERROR("WSARecv have failed."); + goto done; + } + } + else { + tnet_transport_event_t* e = tnet_transport_event_create(event_data, transport->callback_data, active_socket->fd); transport->bytes_in += wsaBuffer.len; - e->data = wsaBuffer.buf; - e->size = wsaBuffer.len; - e->remote_addr = remote_addr; + e->data = wsaBuffer.buf; + e->size = wsaBuffer.len; + e->remote_addr = remote_addr; - TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); - } - FD_READ_DONE:; - } + TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(TSK_RUNNABLE(transport), e); + } +FD_READ_DONE: + ; + } - /*================== FD_WRITE ==================*/ - if (networkEvents.lNetworkEvents & FD_WRITE) { - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_WRITE", transport->description); + /*================== FD_WRITE ==================*/ + if (networkEvents.lNetworkEvents & FD_WRITE) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_WRITE", transport->description); - if (networkEvents.iErrorCode[FD_WRITE_BIT]) { - TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); - TNET_PRINT_LAST_ERROR("WRITE FAILED."); - goto done; - } - } + if (networkEvents.iErrorCode[FD_WRITE_BIT]) { + TSK_RUNNABLE_ENQUEUE(transport, event_error, transport->callback_data, active_socket->fd); + TNET_PRINT_LAST_ERROR("WRITE FAILED."); + goto done; + } + } - /*================== FD_CLOSE ==================*/ - if (networkEvents.lNetworkEvents & FD_CLOSE) { - TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CLOSE", transport->description); + /*================== FD_CLOSE ==================*/ + if (networkEvents.lNetworkEvents & FD_CLOSE) { + TSK_DEBUG_INFO("NETWORK EVENT FOR SERVER [%s] -- FD_CLOSE", transport->description); - TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, active_socket->fd); - removeSocket(index, context); - } + TSK_RUNNABLE_ENQUEUE(transport, event_closed, transport->callback_data, active_socket->fd); + removeSocket(index, context); + } - /* http://msdn.microsoft.com/en-us/library/ms741690(VS.85).aspx + /* http://msdn.microsoft.com/en-us/library/ms741690(VS.85).aspx - The proper way to reset the state of an event object used with the WSAEventSelect function - is to pass the handle of the event object to the WSAEnumNetworkEvents function in the hEventObject parameter. - This will reset the event object and adjust the status of active FD events on the socket in an atomic fashion. - */ - /* WSAResetEvent(active_event); <== DO NOT USE (see above) */ + The proper way to reset the state of an event object used with the WSAEventSelect function + is to pass the handle of the event object to the WSAEnumNetworkEvents function in the hEventObject parameter. + This will reset the event object and adjust the status of active FD events on the socket in an atomic fashion. + */ + /* WSAResetEvent(active_event); <== DO NOT USE (see above) */ - done: - /* unlock context */ - tsk_safeobj_unlock(context); - } /* while(transport->running) */ +done: + /* unlock context */ + tsk_safeobj_unlock(context); + } /* while(transport->running) */ bail: - TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); - return tsk_null; + TSK_DEBUG_INFO("Stopped [%s] server with IP {%s} on port {%d} with type {%d}...", transport->description, transport->master->ip, transport->master->port, transport->master->type); + return tsk_null; } @@ -800,7 +796,7 @@ bail: tsk_object_t* tnet_transport_context_create() { - return tsk_object_new(tnet_transport_context_def_t); + return tsk_object_new(tnet_transport_context_def_t); } @@ -809,31 +805,30 @@ tsk_object_t* tnet_transport_context_create() // static tsk_object_t* transport_context_ctor(tsk_object_t * self, va_list * app) { - transport_context_t *context = self; - if (context){ - tsk_safeobj_init(context); - } - return self; + transport_context_t *context = self; + if (context) { + tsk_safeobj_init(context); + } + return self; } static tsk_object_t* transport_context_dtor(tsk_object_t * self) { - transport_context_t *context = self; - if (context) { - while (context->count) { - removeSocket(0, context); - } - tsk_safeobj_deinit(context); - } - return self; + transport_context_t *context = self; + if (context) { + while (context->count) { + removeSocket(0, context); + } + tsk_safeobj_deinit(context); + } + return self; } -static const tsk_object_def_t tnet_transport_context_def_s = -{ - sizeof(transport_context_t), - transport_context_ctor, - transport_context_dtor, - tsk_null, +static const tsk_object_def_t tnet_transport_context_def_s = { + sizeof(transport_context_t), + transport_context_ctor, + transport_context_dtor, + tsk_null, }; const tsk_object_def_t *tnet_transport_context_def_t = &tnet_transport_context_def_s; #endif /* TNET_UNDER_WINDOWS */ diff --git a/tinyNET/src/tnet_types.h b/tinyNET/src/tnet_types.h index f4b55e2..6edd9cf 100755 --- a/tinyNET/src/tnet_types.h +++ b/tinyNET/src/tnet_types.h @@ -7,12 +7,12 @@ * 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. * @@ -82,14 +82,13 @@ typedef void tnet_transport_handle_t; typedef tsk_list_t tnet_interfaces_L_t; /**< List of @ref tnet_interface_t elements*/ typedef tsk_list_t tnet_addresses_L_t; /**< List of @ref tnet_address_t elements*/ -typedef enum tnet_dtls_setup_e -{ - tnet_dtls_setup_none, - tnet_dtls_setup_actpass, - tnet_dtls_setup_active, - tnet_dtls_setup_passive, +typedef enum tnet_dtls_setup_e { + tnet_dtls_setup_none, + tnet_dtls_setup_actpass, + tnet_dtls_setup_active, + tnet_dtls_setup_passive, - TNET_DTLS_SETUP_MAX + TNET_DTLS_SETUP_MAX } tnet_dtls_setup_t; @@ -103,27 +102,24 @@ typedef enum tnet_proxy_type_e { } tnet_proxy_type_t; -static const char* TNET_DTLS_SETUP_NAMES[TNET_DTLS_SETUP_MAX] = -{ - "UNKNOWN", "actpass", "active", "passive" +static const char* TNET_DTLS_SETUP_NAMES[TNET_DTLS_SETUP_MAX] = { + "UNKNOWN", "actpass", "active", "passive" }; -typedef enum tnet_dtls_hash_type_e -{ - tnet_dtls_hash_type_none, - tnet_dtls_hash_type_md5, - tnet_dtls_hash_type_sha1, - tnet_dtls_hash_type_sha256, - tnet_dtls_hash_type_sha512, +typedef enum tnet_dtls_hash_type_e { + tnet_dtls_hash_type_none, + tnet_dtls_hash_type_md5, + tnet_dtls_hash_type_sha1, + tnet_dtls_hash_type_sha256, + tnet_dtls_hash_type_sha512, - TNET_DTLS_HASH_TYPE_MAX + TNET_DTLS_HASH_TYPE_MAX } tnet_dtls_hash_type_t; // Hash names are case-insensitive but use lower case values because of https://bugzilla.mozilla.org/show_bug.cgi?id=828027 -static const char* TNET_DTLS_HASH_NAMES[TNET_DTLS_HASH_TYPE_MAX] = -{ - "UNKNOWN", "md5", "sha-1", "sha-256", "sha-512" +static const char* TNET_DTLS_HASH_NAMES[TNET_DTLS_HASH_TYPE_MAX] = { + "UNKNOWN", "md5", "sha-1", "sha-256", "sha-512" }; #if TNET_UNDER_WINDOWS @@ -139,22 +135,20 @@ static const char* TNET_DTLS_HASH_NAMES[TNET_DTLS_HASH_TYPE_MAX] = # if !defined (WC_ERR_INVALID_CHARS) # define WC_ERR_INVALID_CHARS 0 # endif - static TNET_INLINE const char* tnet_gai_strerror(int ecode) - { - static char aBuff[1024] = {0}; - - WCHAR *wBuff = gai_strerrorW(ecode); - int len; - if((len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wBuff, wcslen(wBuff), aBuff, sizeof(aBuff) - 1, NULL, NULL)) > 0) - { - aBuff[len] = '\0'; - } - else - { - aBuff[0] = '\0'; - } - return aBuff; - } +static TNET_INLINE const char* tnet_gai_strerror(int ecode) +{ + static char aBuff[1024] = {0}; + + WCHAR *wBuff = gai_strerrorW(ecode); + int len; + if((len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wBuff, wcslen(wBuff), aBuff, sizeof(aBuff) - 1, NULL, NULL)) > 0) { + aBuff[len] = '\0'; + } + else { + aBuff[0] = '\0'; + } + return aBuff; +} # else # define tnet_gai_strerror gai_strerrorA # endif diff --git a/tinyNET/src/tnet_utils.c b/tinyNET/src/tnet_utils.c index 64b1ea8..d01facd 100755 --- a/tinyNET/src/tnet_utils.c +++ b/tinyNET/src/tnet_utils.c @@ -117,18 +117,18 @@ void tnet_getlasterror(tnet_error_t *error) { int err = tnet_geterrno(); memset(*error, 0, sizeof(*error)); - + #if TNET_UNDER_WINDOWS_RT // FormatMessageA Not allowed on Market static WCHAR wBuff[1024] = { 0 }; FormatMessageW( - FORMAT_MESSAGE_FROM_SYSTEM, - tsk_null, - err, - 0, - wBuff, - sizeof(wBuff)-1, - tsk_null); + FORMAT_MESSAGE_FROM_SYSTEM, + tsk_null, + err, + 0, + wBuff, + sizeof(wBuff)-1, + tsk_null); WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wBuff, wcslen(wBuff), *error, sizeof(*error) - 1, NULL, NULL); #elif TNET_UNDER_WINDOWS { @@ -138,13 +138,13 @@ void tnet_getlasterror(tnet_error_t *error) FormatMessageA #endif ( - FORMAT_MESSAGE_FROM_SYSTEM, - tsk_null, - err, - 0, - *error, - sizeof(*error) - 1, - tsk_null); + FORMAT_MESSAGE_FROM_SYSTEM, + tsk_null, + err, + 0, + *error, + sizeof(*error) - 1, + tsk_null); } #else strerror_r(err, *error, sizeof(*error)); @@ -175,7 +175,7 @@ int tnet_geterrno() tnet_interfaces_L_t* tnet_get_interfaces() { tnet_interfaces_L_t * ifaces = tsk_list_create(); - + #if TNET_UNDER_WINDOWS/*=== WINDOWS XP/VISTA/7/CE===*/ #if TNET_UNDER_WINDOWS_RT TSK_DEBUG_ERROR("Not implemented on your OS"); @@ -183,101 +183,95 @@ tnet_interfaces_L_t* tnet_get_interfaces() #else /* !TNET_UNDER_WINDOWS_RT */ #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) - + PIP_ADAPTER_INFO pAdapterInfo = NULL; PIP_ADAPTER_INFO pAdapter = NULL; DWORD dwRetVal = 0; - + ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(sizeof(IP_ADAPTER_INFO)); - if (pAdapterInfo == NULL) - { + if (pAdapterInfo == NULL) { TSK_DEBUG_ERROR("Error allocating memory needed to call GetAdaptersinfo."); goto bail; } // Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable - if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) - { + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { FREE(pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *)MALLOC(ulOutBufLen); - if (pAdapterInfo == NULL) - { + if (pAdapterInfo == NULL) { TSK_DEBUG_ERROR("Error allocating memory needed to call GetAdaptersinfo."); goto bail; } } - - if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) - { + + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { pAdapter = pAdapterInfo; - while (pAdapter) - { + while (pAdapter) { tnet_interface_t *iface; - - if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK){ + + if (pAdapter->Type == MIB_IF_TYPE_LOOPBACK) { continue; } - + iface = tnet_interface_create(pAdapter->Description, pAdapter->Address, pAdapter->AddressLength); iface->index = pAdapter->Index; tsk_list_push_back_data(ifaces, &(iface)); - + pAdapter = pAdapter->Next; } } - - if (pAdapterInfo) - { + + if (pAdapterInfo) { FREE(pAdapterInfo); } - - + + #undef MALLOC #undef FREE #endif /* !TNET_UNDER_WINDOWS_RT */ - + #elif HAVE_IFADDRS_H && HAVE_GETIFADDRS /*=== Using getifaddrs ===*/ - + // see http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html struct ifaddrs *ifaddr = tsk_null, *ifa = tsk_null; - + /* Get interfaces */ - if(getifaddrs(&ifaddr) == -1){ + if(getifaddrs(&ifaddr) == -1) { TSK_DEBUG_ERROR("getifaddrs failed and errno= [%d]", tnet_geterrno()); goto bail; } - - for(ifa = ifaddr; ifa; ifa = ifa->ifa_next){ + + for(ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if((ifa->ifa_flags & IFF_LOOPBACK) || !(ifa->ifa_flags & IFF_UP)) { continue; } - - if(ifa->ifa_addr->sa_family != AF_LINK){ + + if(ifa->ifa_addr->sa_family != AF_LINK) { continue; } - + #if defined(__linux__) && 0 /* FIXME */ { struct ifreq ifr; tnet_fd_t fd = TNET_INVALID_FD; - - if((fd = socket(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + + if((fd = socket(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP)) < 0) { TSK_DEBUG_ERROR("Failed to create new DGRAM socket and errno= [%d]", tnet_geterrno()); goto next; } - + ifr.ifr_addr.sa_family = ifa->ifa_addr->sa_family; strcpy(ifr.ifr_name, ifa.ifa_name); - if(tnet_ioctl(fd, SIOCGIFHWADDR, &ifr)<0){ + if(tnet_ioctl(fd, SIOCGIFHWADDR, &ifr)<0) { TSK_DEBUG_ERROR("tnet_ioctl(SIOCGIFHWADDR)", tnet_geterrno()); goto next; } - else{ + else { //sockaddr_dl* sdl = (struct sockaddr_dl *)ifa->ifa_addr; tnet_interface_t *iface = tnet_interface_create(ifr->ifr_name, ifr->ifr_hwaddr.sa_data, 6); tsk_list_push_back_data(ifaces, (void**)&(iface)); } - next: +next: tnet_sockfd_close(&fd); } #else @@ -288,66 +282,65 @@ tnet_interfaces_L_t* tnet_get_interfaces() tsk_list_push_back_data(ifaces, (void**)&(iface)); } #endif - + }/* for */ - + freeifaddrs(ifaddr); - + #else /*=== ANDROID,... --> Using SIOCGIFCONF and SIOCGIFHWADDR ===*/ - + tnet_fd_t fd = TNET_INVALID_FD; char buffer[1024]; struct ifconf ifc; - + struct sockaddr_in *sin; struct ifreq *ifr; - - if((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + + if((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { TSK_DEBUG_ERROR("Failed to create new DGRAM socket and errno= [%d]", tnet_geterrno()); goto done; } - + ifc.ifc_len = sizeof(buffer); ifc.ifc_buf = buffer; - - if(ioctl(fd, SIOCGIFCONF, &ifc) < 0){ + + if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) { TSK_DEBUG_ERROR("ioctl(SIOCGIFCONF) failed and errno= [%d]", tnet_geterrno()); goto done; } - if(!ifr || !ifc.ifc_req){ + if(!ifr || !ifc.ifc_req) { TSK_DEBUG_ERROR("ifr or ifc.ifc_req is null"); goto done; } - - if(!ifr->ifr_name){ + + if(!ifr->ifr_name) { TSK_DEBUG_ERROR("ifr->ifr_name is null"); goto done; } - - for(ifr = ifc.ifc_req; ifr && !tsk_strempty(ifr->ifr_name); ifr++){ + + for(ifr = ifc.ifc_req; ifr && !tsk_strempty(ifr->ifr_name); ifr++) { sin = (struct sockaddr_in *)&(ifr->ifr_addr); // TODO: IPAddress if needed - if(/*ioctl(fd, SIOCGIFFLAGS, &ifr) == 0*/1){ - if (!(ifr->ifr_flags & IFF_LOOPBACK) && (ifr->ifr_flags & IFF_UP)){ - if(/*ioctl(fd, SIOCGIFHWADDR, &ifr) == 0*/1){ + if(/*ioctl(fd, SIOCGIFFLAGS, &ifr) == 0*/1) { + if (!(ifr->ifr_flags & IFF_LOOPBACK) && (ifr->ifr_flags & IFF_UP)) { + if(/*ioctl(fd, SIOCGIFHWADDR, &ifr) == 0*/1) { tnet_interface_t *iface = tnet_interface_create(ifr->ifr_name, ifr->ifr_hwaddr.sa_data, 6); tsk_list_push_back_data(ifaces, (void**)&(iface)); //iface->index = if_nametoindex(ifr->ifr_name); } } } - else - { + else { TSK_DEBUG_ERROR("ioctl(SIOCGIFFLAGS) failed and errno= [%d]", tnet_geterrno()); } } - + done: tnet_sockfd_close(&fd); - - + + #endif - + bail: return ifaces; } @@ -366,69 +359,71 @@ bail: tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, tsk_bool_t anycast, tsk_bool_t multicast, tsk_bool_t dnsserver, long if_index) { tnet_addresses_L_t *addresses = tsk_list_create(); - + #if TNET_UNDER_WINDOWS #if TNET_UNDER_WINDOWS_RT TSK_DEBUG_ERROR("Not implemented on your OS"); #else /* !TSK_UNDER_WINDOWS_RT */ - + #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) - + /* Declare and initialize variables */ tnet_ip_t ip; DWORD dwSize = 0; DWORD dwRetVal = 0; - + int i = 0; - + // Set the flags to pass to GetAdaptersAddresses ULONG flags = GAA_FLAG_INCLUDE_PREFIX; - + LPVOID lpMsgBuf = NULL; - + PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 0; - + PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; IP_ADAPTER_PREFIX *pPrefix = NULL; - - + + outBufLen = sizeof(IP_ADAPTER_ADDRESSES); pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); - + // Make an initial call to GetAdaptersAddresses to get the // size needed into the outBufLen variable - if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW){ + if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen); } - else goto bail; - - if (pAddresses == NULL){ + else { + goto bail; + } + + if (pAddresses == NULL) { TSK_DEBUG_ERROR("Memory allocation failed for IP_ADAPTER_ADDRESSES struct."); goto bail; } - + dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); - + if (dwRetVal == NO_ERROR) { pCurrAddresses = pAddresses; - while (pCurrAddresses){ - if ((if_index != -1) && (pCurrAddresses->IfIndex != if_index && pCurrAddresses->Ipv6IfIndex != if_index)){ + while (pCurrAddresses) { + if ((if_index != -1) && (pCurrAddresses->IfIndex != if_index && pCurrAddresses->Ipv6IfIndex != if_index)) { goto next; } - if (pCurrAddresses->OperStatus != IfOperStatusUp){ + if (pCurrAddresses->OperStatus != IfOperStatusUp) { goto next; } - + /* == UNICAST addresses == */ pUnicast = pCurrAddresses->FirstUnicastAddress; - while (unicast && pUnicast){ + while (unicast && pUnicast) { //memset(ip, '\0', sizeof(ip)); tnet_get_sockip(pUnicast->Address.lpSockaddr, &ip); TSK_DEBUG_INFO("Found local IP address = AdapterName=%s Ip=%s", pCurrAddresses->AdapterName, ip); @@ -438,13 +433,13 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, address->unicast = 1; tsk_list_push_ascending_data(addresses, &address); } - + pUnicast = pUnicast->Next; } - + /* == ANYCAST addresses == */ pAnycast = pCurrAddresses->FirstAnycastAddress; - while (anycast && pAnycast){ + while (anycast && pAnycast) { //memset(ip, '\0', sizeof(ip)); tnet_get_sockip(pAnycast->Address.lpSockaddr, &ip); { @@ -453,13 +448,13 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, address->anycast = 1; tsk_list_push_ascending_data(addresses, &address); } - + pAnycast = pAnycast->Next; } - + /* == MULTYCAST addresses == */ pMulticast = pCurrAddresses->FirstMulticastAddress; - while (multicast && pMulticast){ + while (multicast && pMulticast) { //memset(ip, '\0', sizeof(ip)); tnet_get_sockip(pMulticast->Address.lpSockaddr, &ip); { @@ -468,69 +463,69 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, address->multicast = 1; tsk_list_push_ascending_data(addresses, &address); } - + pMulticast = pMulticast->Next; } - + /* == DNS servers == */ pDnServer = pCurrAddresses->FirstDnsServerAddress; - while (dnsserver && pDnServer){ + while (dnsserver && pDnServer) { //memset(ip, '\0', sizeof(ip)); - if (!tnet_get_sockip(pDnServer->Address.lpSockaddr, &ip)){ + if (!tnet_get_sockip(pDnServer->Address.lpSockaddr, &ip)) { tnet_address_t *address = tnet_address_create(ip); address->family = pDnServer->Address.lpSockaddr->sa_family; address->dnsserver = 1; tsk_list_push_ascending_data(addresses, &address); } - + pDnServer = pDnServer->Next; } - next: +next: pCurrAddresses = pCurrAddresses->Next; } } - - if (pAddresses){ + + if (pAddresses) { FREE(pAddresses); } - + #undef MALLOC #undef FREE - - bail : - + +bail : + #endif /* !TSK_UNDER_WINDOWS_RT */ - + #else /* !TSK_UNDER_WINDOWS (MAC OS X, UNIX, ANDROID ...) */ - + tnet_ip_t ip; #if HAVE_IFADDRS_H && HAVE_GETIFADDRS /*=== Using getifaddrs ===*/ - + // see http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html struct ifaddrs *ifaddr = tsk_null, *ifa = tsk_null; struct sockaddr *addr; - + /* Get interfaces */ - if(getifaddrs(&ifaddr) == -1){ + if(getifaddrs(&ifaddr) == -1) { TSK_DEBUG_ERROR("getifaddrs failed and errno= [%d]", tnet_geterrno()); goto bail; } - + /* == Unicast addresses == */ - for(ifa = ifaddr; ifa; ifa = ifa->ifa_next){ - if(!ifa->ifa_addr){ + for(ifa = ifaddr; ifa; ifa = ifa->ifa_next) { + if(!ifa->ifa_addr) { continue; } // Skip loopback if ((ifa->ifa_flags & IFF_LOOPBACK) || !(ifa->ifa_flags & IFF_UP)) { continue; } - + // Skip unwanted interface if (if_index != -1 && if_nametoindex(ifa->ifa_name) != if_index) { continue; } - + // Only deal with Unicast address if (unicast) { if (family == AF_INET && ifa->ifa_addr->sa_family != AF_INET) { @@ -542,11 +537,11 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6) { continue; } - + // Get the IP string addr = (struct sockaddr *) ifa->ifa_addr; tnet_get_sockip(addr, &ip); - + // Push a new address tnet_address_t *address = tnet_address_create(ip); address->family = ifa->ifa_addr->sa_family; @@ -554,81 +549,81 @@ tnet_addresses_L_t* tnet_get_addresses(tnet_family_t family, tsk_bool_t unicast, tsk_list_push_ascending_data(addresses, (void **) &address); } } - + if (ifaddr) { free(ifaddr); } - + #else /* ANDROID or any system without getifaddrs */ - + tnet_address_t *address; tnet_fd_t fd = TNET_INVALID_FD; struct ifconf ifc; struct ifreq *ifr = 0; memset(&ifc, 0, sizeof(ifc)); - - if((fd = socket(family, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + + if((fd = socket(family, SOCK_DGRAM, IPPROTO_UDP)) < 0) { TSK_DEBUG_ERROR("Failed to create new DGRAM socket and errno= [%d]", tnet_geterrno()); goto done; } - - if(ioctl(fd, SIOCGIFCONF, &ifc) < 0){ + + if(ioctl(fd, SIOCGIFCONF, &ifc) < 0) { TSK_DEBUG_ERROR("ioctl(SIOCGIFCONF) failed and errno= [%d]", tnet_geterrno()); goto done; } - + if (!(ifr = (struct ifreq*) malloc(ifc.ifc_len))) { TSK_DEBUG_ERROR("Could not malloc ifreq with size =%d", ifc.ifc_len); goto done; } - + ifc.ifc_ifcu.ifcu_req = ifr; if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { TSK_DEBUG_ERROR("ioctl SIOCGIFCONF failed"); goto done; } - + int i; - for(i = 0; i < ifc.ifc_len / sizeof(struct ifreq); ++i){ + for(i = 0; i < ifc.ifc_len / sizeof(struct ifreq); ++i) { if (unicast) { - + } // Skip unwanted interface if (if_index != -1 && ifr->ifr_ifindex != if_index) { continue; } - + // Get the IP string - if(tnet_get_sockip(&ifr[i].ifr_addr, &ip) == 0){ + if(tnet_get_sockip(&ifr[i].ifr_addr, &ip) == 0) { // Push a new address - if((address = tnet_address_create(ip))){ + if((address = tnet_address_create(ip))) { address->family = family; address->unicast = unicast; tsk_list_push_ascending_data(addresses, (void **) &address); } } } - + done: TSK_FREE(ifr); tnet_sockfd_close(&fd); - + #endif /* HAVE_IFADDRS_H && HAVE_GETIFADDRS */ - + bail: - + /* == DNS servers == */ - if(dnsserver){ + if(dnsserver) { TSK_DEBUG_INFO("Calling 'tnet_dns_resolvconf_parse()' to load DNS servers"); tnet_addresses_L_t * dns_servers; - if((dns_servers = tnet_dns_resolvconf_parse("/etc/resolv.conf"))){ + if((dns_servers = tnet_dns_resolvconf_parse("/etc/resolv.conf"))) { tsk_list_pushback_list(addresses, dns_servers); TSK_OBJECT_SAFE_FREE(dns_servers); } } - + #endif - + return addresses; } @@ -637,39 +632,39 @@ bail: */ int tnet_get_mac_address(tnet_mac_address* address) { - static const tsk_size_t __tnet_mac_address_len = sizeof(tnet_mac_address) / sizeof(uint8_t/*tnet_mac_address[0]*/); - int ret = -1; - if (!address) { - TSK_DEBUG_ERROR("Invalid parameter"); - } + static const tsk_size_t __tnet_mac_address_len = sizeof(tnet_mac_address) / sizeof(uint8_t/*tnet_mac_address[0]*/); + int ret = -1; + if (!address) { + TSK_DEBUG_ERROR("Invalid parameter"); + } #if TNET_UNDER_WINDOWS # if TNET_UNDER_WINDOWS_RT - TSK_DEBUG_ERROR("Not implemented on your OS"); + TSK_DEBUG_ERROR("Not implemented on your OS"); # else /* !TSK_UNDER_WINDOWS_RT */ - { - IP_ADAPTER_INFO *info = NULL, *pos; - DWORD size = 0; - ULONG _ret; - - if ((_ret = GetAdaptersInfo(info, &size)) == ERROR_SUCCESS || _ret == ERROR_BUFFER_OVERFLOW) { - info = (IP_ADAPTER_INFO *)tsk_calloc(size + 1, 1); - if (info) { - if ((_ret = GetAdaptersInfo(info, &size)) == ERROR_SUCCESS) { - UINT i; - for (pos = info; pos != NULL && ret != 0; pos = pos->Next) { - if (pos->Type == MIB_IF_TYPE_LOOPBACK && pos->Next) { // skip loopback if we still have items to check - continue; - } - for (i = 0; i < pos->AddressLength && i < __tnet_mac_address_len; ++i) { - (*address)[i] = pos->Address[i]; - } - ret = 0; - } - } - } - TSK_FREE(info); - } - } + { + IP_ADAPTER_INFO *info = NULL, *pos; + DWORD size = 0; + ULONG _ret; + + if ((_ret = GetAdaptersInfo(info, &size)) == ERROR_SUCCESS || _ret == ERROR_BUFFER_OVERFLOW) { + info = (IP_ADAPTER_INFO *)tsk_calloc(size + 1, 1); + if (info) { + if ((_ret = GetAdaptersInfo(info, &size)) == ERROR_SUCCESS) { + UINT i; + for (pos = info; pos != NULL && ret != 0; pos = pos->Next) { + if (pos->Type == MIB_IF_TYPE_LOOPBACK && pos->Next) { // skip loopback if we still have items to check + continue; + } + for (i = 0; i < pos->AddressLength && i < __tnet_mac_address_len; ++i) { + (*address)[i] = pos->Address[i]; + } + ret = 0; + } + } + } + TSK_FREE(info); + } + } # endif /* TSK_UNDER_WINDOWS_RT */ #elif HAVE_IFADDRS_H && HAVE_GETIFADDRS && HAVE_STRUCT_SOCKADDR_DL struct ifaddrs *ifaddrs, *ifaddr; @@ -696,13 +691,13 @@ int tnet_get_mac_address(tnet_mac_address* address) struct ifreq ifr; struct ifconf ifc; char buf[1024]; - + tnet_fd_t fd = tnet_soccket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (fd == TNET_INVALID_FD) { TSK_DEBUG_ERROR("Failed to create socket"); return -1; } - + ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { @@ -710,10 +705,10 @@ int tnet_get_mac_address(tnet_mac_address* address) tnet_sockfd_close(&fd); return -1; } - + struct ifreq* it = ifc.ifc_req; const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq)); - + for (; it != end; ++it) { strcpy(ifr.ifr_name, it->ifr_name); if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) { @@ -732,7 +727,7 @@ int tnet_get_mac_address(tnet_mac_address* address) } #endif - return ret; + return ret; } /**@ingroup tnet_utils_group @@ -747,82 +742,76 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty { int ret = -1; struct sockaddr_storage destAddr; - + #if TNET_UNDER_WINDOWS long dwBestIfIndex = -1; #endif #if TNET_UNDER_WINDOWS_RT Windows::Networking::Connectivity::ConnectionProfile^ profile; #endif - - if (!destination || !source){ + + if (!destination || !source) { TSK_DEBUG_ERROR("Invalid parameter"); goto bail; } - + memset(*source, '\0', sizeof(*source)); - + // special cases for Windows Phone device and emulator #if TNET_UNDER_WINDOWS_PHONE - if (tsk_strequals(destination, "127.0.0.1")){ + if (tsk_strequals(destination, "127.0.0.1")) { memcpy(*source, "127.0.0.1", 9); - ret = 0; goto bail; + ret = 0; + goto bail; } - if(tsk_strequals(destination, "::1")){ + if(tsk_strequals(destination, "::1")) { memcpy(*source, "::1", 3); - ret = 0; goto bail; + ret = 0; + goto bail; } #endif - - if((ret = tnet_sockaddr_init(destination, port, type, &destAddr))){ + + if((ret = tnet_sockaddr_init(destination, port, type, &destAddr))) { goto bail; } - + #if TNET_UNDER_WINDOWS_RT /* Windows Phone 8, Surface or any RT */ profile = Windows::Networking::Connectivity::NetworkInformation::GetInternetConnectionProfile(); - - if (profile != nullptr && profile->NetworkAdapter != nullptr){ + + if (profile != nullptr && profile->NetworkAdapter != nullptr) { TSK_DEBUG_INFO("Network profile IanaInterfaceType = %d", profile->NetworkAdapter->IanaInterfaceType); Windows::Foundation::Collections::IVectorView<Windows::Networking::HostName^>^ HostNames = Windows::Networking::Connectivity::NetworkInformation::GetHostNames(); - - if(HostNames->Size > 0) - { + + if(HostNames->Size > 0) { Windows::Foundation::Collections::IIterator<Windows::Networking::HostName^>^ HostName = HostNames->First(); - do - { + do { std::vector<char> CanonicalName = rt_tsk_str_to_native(HostName->Current->CanonicalName); TSK_DEBUG_INFO("Checking IP address = %s", CanonicalName.data()); - if((TNET_SOCKET_TYPE_IS_IPV4(type) && HostName->Current->IPInformation->PrefixLength->Value > 32) || (TNET_SOCKET_TYPE_IS_IPV6(type) && HostName->Current->IPInformation->PrefixLength->Value > 128)) - { + if((TNET_SOCKET_TYPE_IS_IPV4(type) && HostName->Current->IPInformation->PrefixLength->Value > 32) || (TNET_SOCKET_TYPE_IS_IPV6(type) && HostName->Current->IPInformation->PrefixLength->Value > 128)) { TSK_DEBUG_INFO("Type mismatch - Skiping IP address=%s, IanaInterfaceType=%d, PrefixLength=%d", CanonicalName.data(), HostName->Current->IPInformation->NetworkAdapter->IanaInterfaceType, HostName->Current->IPInformation->PrefixLength->Value); continue; } - - - if(HostName->Current->IPInformation != nullptr) - { + + + if(HostName->Current->IPInformation != nullptr) { // http://msdn.microsoft.com/en-us/library/windows/apps/windows.networking.connectivity.networkadapter.networkadapterid.aspx // HostName->Current->IPInformation->NetworkAdapter->NetworkAdapterId not implemented on WP8 #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP tnet_socket_t* ss = tnet_socket_create(CanonicalName.data(), TNET_SOCKET_PORT_ANY, type); - if(ss) - { + if(ss) { ret = connect(ss->fd, (const sockaddr*)&destAddr, tnet_get_sockaddr_size((const sockaddr*)&destAddr)); - if(ret && tnet_geterrno() == TNET_ERROR_EAGAIN) - { + if(ret && tnet_geterrno() == TNET_ERROR_EAGAIN) { ret = tnet_sockfd_waitUntilWritable(ss->fd, 500); } TSK_OBJECT_SAFE_FREE(ss); } # else - if(HostName->Current->IPInformation->NetworkAdapter->IanaInterfaceType == profile->NetworkAdapter->IanaInterfaceType) - { + if(HostName->Current->IPInformation->NetworkAdapter->IanaInterfaceType == profile->NetworkAdapter->IanaInterfaceType) { ret = 0; } #endif /* */ - - if(ret == 0) - { + + if(ret == 0) { TSK_DEBUG_INFO("Using best IP address = %s :)", CanonicalName.data()); memcpy(*source, CanonicalName.data(), TSK_MIN(tsk_strlen(CanonicalName.data()), sizeof(*source))); ret = 0; @@ -834,30 +823,29 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty while(HostName->MoveNext()); } } - else - { + else { TSK_DEBUG_ERROR("No network connection available"); } - + #elif TNET_UNDER_WINDOWS /* Windows XP/Vista/7 and Windows Mobile */ - if(GetBestInterfaceEx((struct sockaddr*)&destAddr, &dwBestIfIndex) != NO_ERROR){ + if(GetBestInterfaceEx((struct sockaddr*)&destAddr, &dwBestIfIndex) != NO_ERROR) { ret = tnet_geterrno(); TNET_PRINT_LAST_ERROR("GetBestInterfaceEx() failed."); goto bail; } - else{ + else { tnet_addresses_L_t* addresses = tsk_null; const tsk_list_item_t* item; - - if (!(addresses = tnet_get_addresses(TNET_SOCKET_TYPE_IS_IPV6(type) ? AF_INET6 : AF_INET, tsk_true, tsk_false, tsk_false, tsk_false, dwBestIfIndex))){ + + if (!(addresses = tnet_get_addresses(TNET_SOCKET_TYPE_IS_IPV6(type) ? AF_INET6 : AF_INET, tsk_true, tsk_false, tsk_false, tsk_false, dwBestIfIndex))) { ret = -2; TSK_DEBUG_ERROR("Failed to retrieve addresses."); goto bail; } - - tsk_list_foreach(item, addresses){ + + tsk_list_foreach(item, addresses) { const tnet_address_t* address = item->data; - if (address && address->ip){ + if (address && address->ip) { memcpy(*source, address->ip, tsk_strlen(address->ip) > sizeof(*source) ? sizeof(*source) : tsk_strlen(address->ip)); ret = 0; break; // First is good for us. @@ -867,9 +855,9 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty } #elif HAVE_NET_ROUTE_H && HAVE_IFADDRS_H && HAVE_GETIFADDRS /* Mac OS X, iPhone, iPod Touch, iPad and Linux family except Android */ /* Thanks to Laurent Etiemble */ - + int sdl_index = -1; - + #if HAVE_STRUCT_RT_METRICS && HAVE_STRUCT_SOCKADDR_DL static int seq = 1234; char buf[1024]; @@ -882,20 +870,20 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty struct rt_msghdr *rtm = (struct rt_msghdr *)buf; struct sockaddr_dl so_ifp; #endif /* HAVE_STRUCT_RT_METRICS && HAVE_STRUCT_SOCKADDR_DL */ - + struct sockaddr_storage so_dst = destAddr; struct sockaddr *sa = NULL; struct ifaddrs *ifaddr = 0, *ifa = tsk_null; tnet_ip_t ip; - + #if HAVE_STRUCT_RT_METRICS && HAVE_STRUCT_SOCKADDR_DL bzero(rtm, 1024); cp = (char *)(rtm + 1); - + so_ifp.sdl_index = 0; so_ifp.sdl_family = AF_LINK; so_ifp.sdl_len = sizeof(struct sockaddr_dl); - + rtm->rtm_type = RTM_GET; rtm->rtm_flags = RTF_STATIC | RTF_UP | RTF_GATEWAY; rtm->rtm_version = RTM_VERSION; @@ -904,103 +892,104 @@ int tnet_getbestsource(const char* destination, tnet_port_t port, tnet_socket_ty rtm->rtm_rmx = rt_metrics; rtm->rtm_inits = rtm_inits; rtm->rtm_index = 0; - + /** Roundup value to a 4 bytes boundary. */ #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t)) - + l = ROUNDUP(so_dst.ss_len); memcpy(&so_dst, cp, l); cp += l; - + l = ROUNDUP(so_ifp.sdl_len); memcpy(&so_ifp, cp, l); cp += l; - + l = cp - buf; rtm->rtm_msglen = l; - + s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) { // TODO } - + if ((rlen = write(s, rtm, l)) < 0) { TSK_DEBUG_INFO("writing to routing socket"); // TODO } do { l = read(s, rtm, 1024); - } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); - + } + while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); + /** Advance an address to the closest 4 bytes boundary. */ #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - + if (rtm->rtm_errno == 0 && rtm->rtm_addrs) { cp = (char *)(rtm + 1); for (i = 1; i; i <<= 1) { if (i & rtm->rtm_addrs) { sa = (struct sockaddr *)cp; switch (i) { - case RTA_IFP: - ifp = (struct sockaddr_dl *) sa; - break; + case RTA_IFP: + ifp = (struct sockaddr_dl *) sa; + break; } ADVANCE(cp, sa); } } } - if(ifp){ + if(ifp) { sdl_index = ifp->sdl_index; } #endif /* HAVE_STRUCT_RT_METRICS && HAVE_STRUCT_SOCKADDR_DL */ - + /* Get interfaces */ - if(getifaddrs(&ifaddr) == -1){ + if(getifaddrs(&ifaddr) == -1) { TNET_PRINT_LAST_ERROR("getifaddrs() failed."); goto bail; } - - for(ifa = ifaddr; ifa; ifa = ifa->ifa_next){ + + for(ifa = ifaddr; ifa; ifa = ifa->ifa_next) { if ((ifa->ifa_flags & IFF_LOOPBACK) || !(ifa->ifa_flags & IFF_UP)) { continue; } - + if (sdl_index != -1 && if_nametoindex(ifa->ifa_name) != sdl_index) { continue; } - + if (!ifa->ifa_addr || ifa->ifa_addr->sa_family != destAddr.ss_family) { continue; } - + if (destAddr.ss_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr) ^ - IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) &destAddr)->sin6_addr)) { + IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *) &destAddr)->sin6_addr)) { continue; } if (IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6 *) ifa->ifa_addr)->sin6_addr) ^ - IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6 *) &destAddr)->sin6_addr)) { + IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6 *) &destAddr)->sin6_addr)) { continue; } } - + tnet_get_sockip((struct sockaddr *) ifa->ifa_addr, &ip); - + memcpy(*source, ip, tsk_strlen(ip) > sizeof(*source) ? sizeof(*source) : tsk_strlen(ip)); ret = 0; goto bail; // First is good for us. } - - + + #else /* All other systems (Google Android, Unix-Like systems, uLinux, ....) */ TSK_DEBUG_WARN("getbestroute() not supported on this OS"); memcpy(*source, TNET_SOCKET_TYPE_IS_IPV6(type) ? "::" : "0.0.0.0", TNET_SOCKET_TYPE_IS_IPV6(type) ? 2 : 7 - ); + ); #endif - + bail: return ret; } @@ -1021,7 +1010,7 @@ bail: int tnet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { int ret = -1; - if (hints && (ret = getaddrinfo(node, service, hints, res))){ + if (hints && (ret = getaddrinfo(node, service, hints, res))) { TSK_DEBUG_ERROR("getaddrinfo(family=%d, node=%s and service=%s) failed: [%s]", hints->ai_family, node, service, tnet_gai_strerror(ret)); } return ret; @@ -1035,7 +1024,7 @@ int tnet_getaddrinfo(const char *node, const char *service, const struct addrinf **/ void tnet_freeaddrinfo(struct addrinfo *ai) { - if (ai){ + if (ai) { freeaddrinfo(ai); } } @@ -1048,7 +1037,7 @@ void tnet_freeaddrinfo(struct addrinfo *ai) */ int tnet_getsockname(tnet_fd_t fd, struct sockaddr_storage *result) { - if (fd > 0 && result){ + if (fd > 0 && result) { socklen_t namelen = sizeof(*result); return getsockname(fd, (struct sockaddr*)result, &namelen); } @@ -1057,7 +1046,7 @@ int tnet_getsockname(tnet_fd_t fd, struct sockaddr_storage *result) int tnet_getpeername(tnet_fd_t fd, struct sockaddr_storage *result) { - if (fd > 0 && result){ + if (fd > 0 && result) { socklen_t namelen = sizeof(*result); return getpeername(fd, (struct sockaddr*)result, &namelen); } @@ -1072,7 +1061,7 @@ int tnet_getpeername(tnet_fd_t fd, struct sockaddr_storage *result) tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd) { tnet_socket_type_t type = tnet_socket_type_invalid; - + /*if(fd >0) { struct sockaddr_storage ss; @@ -1088,7 +1077,7 @@ tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd) } } }*/ - + return type; } @@ -1102,39 +1091,39 @@ tnet_socket_type_t tnet_get_socket_type(tnet_fd_t fd) tnet_family_t tnet_get_family(const char* host, tnet_port_t port) { tnet_family_t ret = AF_UNSPEC; - if (host){ + if (host) { int status; tsk_istr_t srv; struct addrinfo *result = tsk_null; struct addrinfo hints; - + /* set the port: used as the default service */ - if (port){ + if (port) { tsk_itoa(port, &srv); } - else{ + else { memset(srv, '\0', sizeof(srv)); } - + memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; - + if ((status = tnet_getaddrinfo(host, srv, &hints, &result))) { TNET_PRINT_LAST_ERROR("getaddrinfo(%s:%d) failed", host, port); goto done; } - + /* Get the First result. */ if (result) { ret = result->ai_family; goto done; } - done: +done: tnet_freeaddrinfo(result); } - + return ret; } @@ -1148,47 +1137,45 @@ tnet_family_t tnet_get_family(const char* host, tnet_port_t port) int tnet_get_sockip_n_port(const struct sockaddr *addr, tnet_ip_t *ip, tnet_port_t *port) { int status = -1; - - if (addr->sa_family == AF_INET){ + + if (addr->sa_family == AF_INET) { const struct sockaddr_in *sin = (const struct sockaddr_in *)addr; - if (port){ + if (port) { *port = tnet_ntohs(sin->sin_port); status = 0; } - if (ip){ - if ((status = tnet_getnameinfo((const struct sockaddr*)sin, sizeof(*sin), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))){ + if (ip) { + if ((status = tnet_getnameinfo((const struct sockaddr*)sin, sizeof(*sin), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))) { return status; } } } - else if (addr->sa_family == AF_INET6) - { + else if (addr->sa_family == AF_INET6) { const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)addr; #if TNET_UNDER_WINDOWS int index; #endif - if (port){ + if (port) { *port = tnet_ntohs(sin6->sin6_port); status = 0; } - if (ip){ - if ((status = tnet_getnameinfo((const struct sockaddr*)sin6, sizeof(*sin6), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))){ + if (ip) { + if ((status = tnet_getnameinfo((const struct sockaddr*)sin6, sizeof(*sin6), *ip, sizeof(*ip), 0, 0, NI_NUMERICHOST))) { return status; } - + #if TNET_UNDER_WINDOWS - if ((index = tsk_strindexOf(*ip, tsk_strlen(*ip), "%")) > 0){ + if ((index = tsk_strindexOf(*ip, tsk_strlen(*ip), "%")) > 0) { *(*ip + index) = '\0'; } #endif } } - else - { + else { TSK_DEBUG_ERROR("Unsupported address family."); return status; } - + return status; } @@ -1202,24 +1189,24 @@ int tnet_get_sockip_n_port(const struct sockaddr *addr, tnet_ip_t *ip, tnet_port */ int tnet_get_peerip_n_port(tnet_fd_t localFD, tnet_ip_t *ip, tnet_port_t *port) { - if (port){ + if (port) { *port = 0; } - - if (localFD > 0){ + + if (localFD > 0) { int status; socklen_t len; struct sockaddr_storage ss; - + len = sizeof(ss); - if ((status = getpeername(localFD, (struct sockaddr *)&ss, &len))){ + if ((status = getpeername(localFD, (struct sockaddr *)&ss, &len))) { TSK_DEBUG_ERROR("TNET_GET_SOCKADDR has failed with status code: %d", status); return -1; } - + return tnet_get_sockip_n_port(((struct sockaddr *)&ss), ip, port); } - + TSK_DEBUG_ERROR("Could not use an invalid socket description."); return -1; } @@ -1230,27 +1217,27 @@ int tnet_get_peerip_n_port(tnet_fd_t localFD, tnet_ip_t *ip, tnet_port_t *port) * @param getlocal Whether to get local or remote ip and port * @param ip [out] The IP address of the local socket. * @param port [out] The port of the local socket. - + * @retval Zero if succeed and non-zero error code otherwise. */ int tnet_get_ip_n_port(tnet_fd_t fd, tsk_bool_t getlocal, tnet_ip_t *ip, tnet_port_t *port) { - if (port){ + if (port) { *port = 0; } - - if (fd > 0){ + + if (fd > 0) { int status; struct sockaddr_storage ss; status = getlocal ? tnet_getsockname(fd, &ss) : tnet_getpeername(fd, &ss); - if (status){ + if (status) { TNET_PRINT_LAST_ERROR("TNET_GET_SOCKADDR has failed with status code: %d", status); return -1; } - + return tnet_get_sockip_n_port(((struct sockaddr *)&ss), ip, port); } - + TSK_DEBUG_ERROR("Could not use an invalid socket description."); return -1; } @@ -1310,7 +1297,7 @@ int tnet_get_fd_opened_count(tsk_size_t* count) char buf[1024]; struct dirent *dp; DIR *dir; - + if (!count) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1457,7 +1444,7 @@ const char *tnet_inet_ntop(int af, const void *src, char *dst, int size) } 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; } @@ -1495,29 +1482,29 @@ int tnet_sockfd_waitUntil(tnet_fd_t fd, long timeout, tsk_bool_t writable) int ret = -1; fd_set fds; struct timeval timetowait; - - if (fd <= 0){ + + if (fd <= 0) { goto bail; } - - if (timeout >= 0){ + + if (timeout >= 0) { timetowait.tv_sec = (timeout / 1000); timetowait.tv_usec = (timeout % 1000) * 1000; } - + FD_ZERO(&fds); FD_SET(fd, &fds); - + ret = select(fd + 1, writable ? 0 : &fds, writable ? &fds : 0, 0, (timeout >= 0) ? &timetowait : 0); - - if (ret == 0){ /* timedout */ + + if (ret == 0) { /* timedout */ ret = -2; } - else if (ret == 1/* the total number of socket handles that are ready */){ + else if (ret == 1/* the total number of socket handles that are ready */) { ret = 0; // Ok } //else: error - + bail: return ret; } @@ -1530,21 +1517,21 @@ int tnet_sockfd_joingroup6(tnet_fd_t fd, const char* multiaddr, unsigned iface_i int ret = -1; //struct ipv6_mreq mreq6; //struct sockaddr_storage ss; - + //if((ret = tnet_sockaddr_init(multiaddr, 0, tnet_socket_type_udp_ipv6, &ss))) //{ // return ret; //} - + //memcpy(&mreq6.ipv6mr_multiaddr, &((struct sockaddr_in6 *) &ss)->sin6_addr, sizeof(struct in6_addr)); //mreq6.ipv6mr_interface = iface_index; - + //if((ret = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char*)&mreq6, sizeof(mreq6)))) //{ // TNET_PRINT_LAST_ERROR("Failed to join IPv6 multicast group."); // return ret; //} - + return ret; } /**@ingroup tnet_utils_group @@ -1565,7 +1552,7 @@ int tnet_resolve(const char *fqdn, tnet_port_t port, tnet_socket_type_t type, tn { struct sockaddr_storage addr; int ret = tnet_sockaddr_init(fqdn, port, type, &addr); - if (ret == 0){ + if (ret == 0) { return tnet_get_sockip_n_port((const struct sockaddr *)&addr, out_ip, out_port); } return ret; @@ -1581,26 +1568,26 @@ int tnet_sockaddrinfo_init(const char *host, tnet_port_t port, enum tnet_socket_ struct addrinfo *ptr = 0; struct addrinfo hints; tsk_istr_t p; - + tsk_itoa(port, &p); - + /* hints address info structure */ memset(&hints, 0, sizeof(hints)); hints.ai_family = TNET_SOCKET_TYPE_IS_IPV46(type) ? AF_UNSPEC : (TNET_SOCKET_TYPE_IS_IPV6(type) ? AF_INET6 : AF_INET); hints.ai_socktype = TNET_SOCKET_TYPE_IS_STREAM(type) ? SOCK_STREAM : SOCK_DGRAM; hints.ai_protocol = TNET_SOCKET_TYPE_IS_STREAM(type) ? IPPROTO_TCP : IPPROTO_UDP; hints.ai_flags = AI_PASSIVE; - + /* Performs getaddrinfo */ - if ((status = tnet_getaddrinfo(host, p, &hints, &result))){ + if ((status = tnet_getaddrinfo(host, p, &hints, &result))) { TNET_PRINT_LAST_ERROR("getaddrinfo have failed."); goto bail; } - + /* Find our address. */ - for (ptr = result; ptr; ptr = ptr->ai_next){ + for (ptr = result; ptr; ptr = ptr->ai_next) { /* Only IPv4 and IPv6 are supported */ - if (ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET){ + if (ptr->ai_family != AF_INET6 && ptr->ai_family != AF_INET) { continue; } /* duplicate addrinfo ==> Bad idea @@ -1611,21 +1598,29 @@ int tnet_sockaddrinfo_init(const char *host, tnet_port_t port, enum tnet_socket_ (*ai)->ai_addrlen = ptr->ai_addrlen; (*ai)->ai_next = 0; (*ai)->ai_canonname = 0;*/ - - if (ai_addr)memcpy(ai_addr, ptr->ai_addr, ptr->ai_addrlen); - if (ai_family) *ai_family = ptr->ai_family; - if (ai_socktype) *ai_socktype = ptr->ai_socktype; - if (ai_protocol) *ai_protocol = ptr->ai_protocol; - + + if (ai_addr) { + memcpy(ai_addr, ptr->ai_addr, ptr->ai_addrlen); + } + if (ai_family) { + *ai_family = ptr->ai_family; + } + if (ai_socktype) { + *ai_socktype = ptr->ai_socktype; + } + if (ai_protocol) { + *ai_protocol = ptr->ai_protocol; + } + /* We prefer IPv4 but IPv6 can also work */ - if (ptr->ai_family == AF_INET){ + if (ptr->ai_family == AF_INET) { break; } } - + bail: tnet_freeaddrinfo(result); - + return status; } @@ -1641,13 +1636,13 @@ int tnet_sockaddr_init(const char *host, tnet_port_t port, tnet_socket_type_t ty { int status; struct sockaddr_storage ai_addr; - - if ((status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, 0, 0, 0))){ + + if ((status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, 0, 0, 0))) { return status; } - + memcpy(addr, &ai_addr, sizeof(ai_addr)); - + return status; } @@ -1665,34 +1660,34 @@ int tnet_sockfd_init(const char *host, tnet_port_t port, enum tnet_socket_type_e struct sockaddr_storage ai_addr; int ai_family, ai_socktype, ai_protocol; *fd = TNET_INVALID_SOCKET; - - if ((status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, &ai_family, &ai_socktype, &ai_protocol))){ + + if ((status = tnet_sockaddrinfo_init(host, port, type, &ai_addr, &ai_family, &ai_socktype, &ai_protocol))) { goto bail; } - - if ((*fd = (tnet_fd_t)socket(ai_family, ai_socktype, ai_protocol)) == TNET_INVALID_SOCKET){ + + if ((*fd = (tnet_fd_t)socket(ai_family, ai_socktype, ai_protocol)) == TNET_INVALID_SOCKET) { TNET_PRINT_LAST_ERROR("Failed to create new socket."); goto bail; } - + #if TNET_USE_POLL || USE_POLL /* For win32 WSA* function the socket is auto. set to nonblocking mode. */ - if ((status = tnet_sockfd_set_nonblocking(*fd))){ + if ((status = tnet_sockfd_set_nonblocking(*fd))) { goto bail; } #endif - + #if TNET_HAVE_SS_LEN if((status = bind(*fd, (const struct sockaddr*)&ai_addr, ai_addr.ss_len))) #else - if ((status = bind(*fd, (const struct sockaddr*)&ai_addr, sizeof(ai_addr)))) + if ((status = bind(*fd, (const struct sockaddr*)&ai_addr, sizeof(ai_addr)))) #endif - { - TNET_PRINT_LAST_ERROR("bind have failed."); - tnet_sockfd_close(fd); - - goto bail; - } - + { + TNET_PRINT_LAST_ERROR("bind have failed."); + tnet_sockfd_close(fd); + + goto bail; + } + bail: return (*fd == TNET_INVALID_SOCKET) ? status : 0; } @@ -1705,8 +1700,7 @@ bail: */ int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking) { - if (fd != TNET_INVALID_FD) - { + if (fd != TNET_INVALID_FD) { #if TNET_UNDER_WINDOWS ULONG mode = nonBlocking; if (ioctlsocket(fd, FIONBIO, &mode)) @@ -1721,15 +1715,15 @@ int tnet_sockfd_set_mode(tnet_fd_t fd, int nonBlocking) TNET_PRINT_LAST_ERROR("fcntl(F_GETFL) have failed."); return -1; } - if(fcntl(fd, F_SETFL, flags | (nonBlocking ? O_NONBLOCK : ~O_NONBLOCK)) < 0){ + if(fcntl(fd, F_SETFL, flags | (nonBlocking ? O_NONBLOCK : ~O_NONBLOCK)) < 0) { TNET_PRINT_LAST_ERROR("fcntl(O_NONBLOCK/O_NONBLOCK) have failed."); return -1; } #endif - + // int on = 1; // ioctl(fd, FIONBIO, (char *)&on); - + } return 0; } @@ -1775,7 +1769,7 @@ int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf, { tsk_size_t sent = 0; int ret = -1; - + if (fd == TNET_INVALID_FD) { TSK_DEBUG_ERROR("Using invalid FD to send data."); goto bail; @@ -1785,7 +1779,7 @@ int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf, ret = -2; goto bail; } - + while (sent < size) { int try_guard = 10; #if TNET_UNDER_WINDOWS @@ -1793,13 +1787,13 @@ int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf, DWORD numberOfBytesSent = 0; wsaBuffer.buf = ((CHAR*)buf) + sent; wsaBuffer.len = (ULONG)(size - sent); - try_again: +try_again: ret = WSASendTo(fd, &wsaBuffer, 1, &numberOfBytesSent, 0, to, tnet_get_sockaddr_size(to), 0, 0); // returns zero if succeed if (ret == 0) { ret = numberOfBytesSent; } #else - try_again: +try_again: ret = sendto(fd, (((const uint8_t*)buf) + sent), (size - sent), 0, to, tnet_get_sockaddr_size(to)); // returns number of sent bytes if succeed #endif if (ret <= 0) { @@ -1819,7 +1813,7 @@ int tnet_sockfd_sendto(tnet_fd_t fd, const struct sockaddr *to, const void* buf, sent += ret; } } - + bail: return (int)((size == sent) ? sent : ret); } @@ -1838,12 +1832,12 @@ bail: int tnet_sockfd_recvfrom(tnet_fd_t fd, void* buf, tsk_size_t size, int flags, struct sockaddr *from) { socklen_t fromlen; - - if (fd == TNET_INVALID_FD){ + + if (fd == TNET_INVALID_FD) { TSK_DEBUG_ERROR("Using invalid FD to recv data."); return -1; } - + fromlen = tnet_get_sockaddr_size(from); return recvfrom(fd, (char*)buf, (int)size, flags, from, &fromlen); } @@ -1861,32 +1855,34 @@ tsk_size_t tnet_sockfd_send(tnet_fd_t fd, const void* buf, tsk_size_t size, int { int ret = -1; tsk_size_t sent = 0; - - if (fd == TNET_INVALID_FD){ + + if (fd == TNET_INVALID_FD) { TSK_DEBUG_ERROR("Using invalid FD to send data."); goto bail; } - - while (sent < size){ - if ((ret = send(fd, (((const char*)buf) + sent), (int)(size - sent), flags)) <= 0){ - if (tnet_geterrno() == TNET_ERROR_WOULDBLOCK){ - if ((ret = tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT))){ + + while (sent < size) { + if ((ret = send(fd, (((const char*)buf) + sent), (int)(size - sent), flags)) <= 0) { + if (tnet_geterrno() == TNET_ERROR_WOULDBLOCK) { + if ((ret = tnet_sockfd_waitUntilWritable(fd, TNET_CONNECT_TIMEOUT))) { break; } - else continue; + else { + continue; + } } - else{ + else { TNET_PRINT_LAST_ERROR("send failed"); // Under Windows XP if WSAGetLastError()==WSAEINTR then try to disable both the ICS and the Firewall // More info about How to disable the ISC: http://support.microsoft.com/?scid=kb%3Ben-us%3B230112&x=6&y=11 goto bail; } } - else{ + else { sent += ret; } } - + bail: //return (size == sent) ? sent : ret; return sent; @@ -1905,17 +1901,17 @@ bail: int tnet_sockfd_recv(tnet_fd_t fd, void* buf, tsk_size_t size, int flags) { int ret = -1; - - if (fd == TNET_INVALID_FD){ + + if (fd == TNET_INVALID_FD) { TSK_DEBUG_ERROR("Using invalid FD to recv data."); goto bail; } - - if ((ret = (int)recv(fd, (char*)buf, (int)size, flags)) <= 0){ + + if ((ret = (int)recv(fd, (char*)buf, (int)size, flags)) <= 0) { TNET_PRINT_LAST_ERROR("recv failed."); goto bail; } - + bail: return ret; } @@ -1929,40 +1925,40 @@ bail: int tnet_sockfd_connectto(tnet_fd_t fd, const struct sockaddr_storage *to) { int status = -1; - + #if TNET_UNDER_WINDOWS - - if ((status = WSAConnect(fd, (LPSOCKADDR)to, sizeof(*to), NULL, NULL, NULL, NULL)) == SOCKET_ERROR){ + + if ((status = WSAConnect(fd, (LPSOCKADDR)to, sizeof(*to), NULL, NULL, NULL, NULL)) == SOCKET_ERROR) { status = WSAGetLastError(); - if (status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_ISCONN || status == TNET_ERROR_INTR || status == TNET_ERROR_INPROGRESS){ + if (status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_ISCONN || status == TNET_ERROR_INTR || status == TNET_ERROR_INPROGRESS) { TSK_DEBUG_WARN("TNET_ERROR_WOULDBLOCK/TNET_ERROR_ISCONN/TNET_ERROR_INTR/TNET_ERROR_INPROGRESS -> you should use tnet_sockfd_waitUntilWritable() before trying to send data"); status = 0; } - else{ + else { TNET_PRINT_LAST_ERROR("WSAConnect have failed"); } } - + #else /* !TNET_UNDER_WINDOWS */ - + #if TNET_HAVE_SS_LEN if ((status = connect(fd, (struct sockaddr*)to, to->ss_len))) # else - if((status = connect(fd, (struct sockaddr*)to, sizeof(*to)))) + if((status = connect(fd, (struct sockaddr*)to, sizeof(*to)))) # endif - { - status = tnet_geterrno(); - if(status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_ISCONN || status == TNET_ERROR_INPROGRESS || status == TNET_ERROR_EAGAIN){ - TSK_DEBUG_INFO("TNET_ERROR_WOULDBLOCK/TNET_ERROR_ISCONN/TNET_ERROR_INPROGRESS/TNET_ERROR_EAGAIN ==> use tnet_sockfd_waitUntilWritable."); - status = 0; - } - else{ - TNET_PRINT_LAST_ERROR("connect have failed."); - } + { + status = tnet_geterrno(); + if(status == TNET_ERROR_WOULDBLOCK || status == TNET_ERROR_ISCONN || status == TNET_ERROR_INPROGRESS || status == TNET_ERROR_EAGAIN) { + TSK_DEBUG_INFO("TNET_ERROR_WOULDBLOCK/TNET_ERROR_ISCONN/TNET_ERROR_INPROGRESS/TNET_ERROR_EAGAIN ==> use tnet_sockfd_waitUntilWritable."); + status = 0; } - + else { + TNET_PRINT_LAST_ERROR("connect have failed."); + } + } + #endif /* TNET_UNDER_WINDOWS */ - + return status; } @@ -1970,10 +1966,12 @@ int tnet_sockfd_connectto(tnet_fd_t fd, const struct sockaddr_storage *to) */ int tnet_sockfd_listen(tnet_fd_t fd, int backlog) { - if (fd > 0){ + if (fd > 0) { return listen(fd, backlog); } - else return -1; + else { + return -1; + } } /**@ingroup tnet_utils_group @@ -1981,11 +1979,11 @@ int tnet_sockfd_listen(tnet_fd_t fd, int backlog) tnet_fd_t tnet_sockfd_accept(tnet_fd_t fd, struct sockaddr *addr, socklen_t *addrlen) { tnet_fd_t ret = TNET_INVALID_FD; - - if (fd > 0){ + + if (fd > 0) { ret = (tnet_fd_t)accept(fd, addr, addrlen); } - + return ret; } @@ -1996,7 +1994,7 @@ tnet_fd_t tnet_sockfd_accept(tnet_fd_t fd, struct sockaddr *addr, socklen_t *add */ int tnet_sockfd_close(tnet_fd_t *fd) { - if (*fd != TNET_INVALID_FD){ + if (*fd != TNET_INVALID_FD) { int ret; #if TNET_UNDER_WINDOWS ret = closesocket(*fd); @@ -2025,12 +2023,24 @@ int tnet_sockfd_shutdown(tnet_fd_t fd) */ tnet_proxy_type_t tnet_proxy_type_from_string(const char* type) { - if (tsk_striequals(type, "http")) return tnet_proxy_type_http; - else if (tsk_striequals(type, "https")) return tnet_proxy_type_https; - else if (tsk_striequals(type, "socks4")) return tnet_proxy_type_socks4; - else if (tsk_striequals(type, "socks4a")) return tnet_proxy_type_socks4a; - else if (tsk_striequals(type, "socks5")) return tnet_proxy_type_socks5; - else return tnet_proxy_type_none; + if (tsk_striequals(type, "http")) { + return tnet_proxy_type_http; + } + else if (tsk_striequals(type, "https")) { + return tnet_proxy_type_https; + } + else if (tsk_striequals(type, "socks4")) { + return tnet_proxy_type_socks4; + } + else if (tsk_striequals(type, "socks4a")) { + return tnet_proxy_type_socks4a; + } + else if (tsk_striequals(type, "socks5")) { + return tnet_proxy_type_socks5; + } + else { + return tnet_proxy_type_none; + } } /**@ingroup tnet_utils_group @@ -2038,12 +2048,18 @@ tnet_proxy_type_t tnet_proxy_type_from_string(const char* type) const char* tnet_proxy_type_to_string(tnet_proxy_type_t type) { switch (type) { - case tnet_proxy_type_http: return "http"; - case tnet_proxy_type_https: return "https"; - case tnet_proxy_type_socks4: return "socks4"; - case tnet_proxy_type_socks4a: return "socks4a"; - case tnet_proxy_type_socks5: return "socks5"; - default: return "none"; + case tnet_proxy_type_http: + return "http"; + case tnet_proxy_type_https: + return "https"; + case tnet_proxy_type_socks4: + return "socks4"; + case tnet_proxy_type_socks4a: + return "socks4a"; + case tnet_proxy_type_socks5: + return "socks5"; + default: + return "none"; } } @@ -2092,13 +2108,13 @@ const char* tnet_proxy_type_to_string(tnet_proxy_type_t type) static tsk_object_t* tnet_interface_ctor(tsk_object_t * self, va_list * app) { tnet_interface_t *iface = (tnet_interface_t *)self; - if (iface){ + if (iface) { const char* description = va_arg(*app, const char*); const void* mac_address = va_arg(*app, const void*); tsk_size_t mac_address_length = va_arg(*app, tsk_size_t); - + iface->description = tsk_strdup(description); - if ((iface->mac_address = (uint8_t*)tsk_calloc(mac_address_length, sizeof(uint8_t)))){ + if ((iface->mac_address = (uint8_t*)tsk_calloc(mac_address_length, sizeof(uint8_t)))) { memcpy(iface->mac_address, mac_address, mac_address_length); } iface->mac_address_length = mac_address_length; @@ -2109,11 +2125,11 @@ static tsk_object_t* tnet_interface_ctor(tsk_object_t * self, va_list * app) static tsk_object_t* tnet_interface_dtor(tsk_object_t * self) { tnet_interface_t *iface = (tnet_interface_t *)self; - if (iface){ + if (iface) { TSK_FREE(iface->description); TSK_FREE(iface->mac_address); } - + return self; } @@ -2121,16 +2137,19 @@ static int tnet_interface_cmp(const tsk_object_t *if1, const tsk_object_t *if2) { const tnet_interface_t *iface1 = (const tnet_interface_t *)if1; const tnet_interface_t *iface2 = (const tnet_interface_t *)if2; - - if (iface1 && iface2){ + + if (iface1 && iface2) { return tsk_stricmp(iface1->description, iface1->description); } - else if (!iface1 && !iface2) return 0; - else return -1; + else if (!iface1 && !iface2) { + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_interface_def_s = -{ +static const tsk_object_def_t tnet_interface_def_s = { sizeof(tnet_interface_t), tnet_interface_ctor, tnet_interface_dtor, @@ -2147,7 +2166,7 @@ const tsk_object_def_t *tnet_interface_def_t = &tnet_interface_def_s; static tsk_object_t* tnet_address_ctor(tsk_object_t * self, va_list * app) { tnet_address_t *address = (tnet_address_t *)self; - if (address){ + if (address) { address->ip = tsk_strdup(va_arg(*app, const char*)); } return self; @@ -2156,10 +2175,10 @@ static tsk_object_t* tnet_address_ctor(tsk_object_t * self, va_list * app) static tsk_object_t* tnet_address_dtor(tsk_object_t * self) { tnet_address_t *address = (tnet_address_t *)self; - if (address){ + if (address) { TSK_FREE(address->ip); } - + return self; } @@ -2167,17 +2186,20 @@ static int tnet_address_cmp(const tsk_object_t *_a1, const tsk_object_t *_a2) { const tnet_address_t *a1 = (const tnet_address_t *)_a1; const tnet_address_t *a2 = (const tnet_address_t *)_a2; - - if (a1 && a2){ + + if (a1 && a2) { // to have AF_UNSPEC, AF_UNIX, AF_INET, ... first return (a1->family - a2->family); } - else if (!a1 && !a2) return 0; - else return -1; + else if (!a1 && !a2) { + return 0; + } + else { + return -1; + } } -static const tsk_object_def_t tnet_address_def_s = -{ +static const tsk_object_def_t tnet_address_def_s = { sizeof(tnet_address_t), tnet_address_ctor, tnet_address_dtor, diff --git a/tinyNET/src/tnet_utils.h b/tinyNET/src/tnet_utils.h index 6673696..a3abbc9 100755 --- a/tinyNET/src/tnet_utils.h +++ b/tinyNET/src/tnet_utils.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2010-2015 Mamadou DIOP. -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -40,33 +40,31 @@ TNET_BEGIN_DECLS /**Interface. */ -typedef struct tnet_interface_s -{ - TSK_DECLARE_OBJECT; - - unsigned index; - - char* description; - uint8_t* mac_address; - tsk_size_t mac_address_length; +typedef struct tnet_interface_s { + TSK_DECLARE_OBJECT; + + unsigned index; + + char* description; + uint8_t* mac_address; + tsk_size_t mac_address_length; } tnet_interface_t; /**Address. */ -typedef struct tnet_address_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_address_s { + TSK_DECLARE_OBJECT; - tnet_family_t family; + tnet_family_t family; - unsigned unicast:1; - unsigned anycast:1; - unsigned multicast:1; - unsigned dnsserver:1; + unsigned unicast:1; + unsigned anycast:1; + unsigned multicast:1; + unsigned dnsserver:1; - char* ip; + char* ip; } tnet_address_t; diff --git a/tinyNET/src/turn/tnet_turn.c b/tinyNET/src/turn/tnet_turn.c index 0f38d02..fc37d68 100755 --- a/tinyNET/src/turn/tnet_turn.c +++ b/tinyNET/src/turn/tnet_turn.c @@ -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. //* @@ -97,7 +97,7 @@ // request->nonce = tsk_strdup(allocation->nonce); // // /* Create random transaction id */ -// { +// { // tsk_istr_t random; // tsk_md5digest_t digest; // @@ -176,8 +176,8 @@ // tnet_turn_attribute_t *attribute; // tnet_turn_channel_binding_id_t number; // uint32_t lifetime; -// -// +// +// // channel_binding = va_arg(*app, const tnet_turn_channel_binding_t *); // number = tnet_htons(channel_binding->id); // lifetime = tnet_htonl(channel_binding->timeout); @@ -216,7 +216,7 @@ // tnet_turn_attribute_xpeer_addr_t* xpeer = tsk_object_ref(va_arg(*app, tnet_turn_attribute_xpeer_addr_t *)); // const void* data = va_arg(*app, const void *); // tsk_size_t size = va_arg(*app, tsk_size_t); -// +// // /* // draft-ietf-behave-turn-16 - 10.1. Forming a Send Indication // @@ -255,7 +255,7 @@ // attribute->xaddress[1] = 0xA1; // attribute->xaddress[2] = 0x83; // attribute->xaddress[3] = 0x47; -// +// // tnet_stun_message_add_attribute(request, (tnet_stun_attr_t**)&attribute); // // /*if((attribute = tnet_turn_attribute_even_port_create(context->enable_evenport))) @@ -293,7 +293,7 @@ // { /* First time we get a nonce */ // tsk_strupdate(&allocation->nonce, nonce); // tsk_strupdate(&allocation->realm, realm); -// +// // /* Delete the message and response before retrying*/ // TSK_OBJECT_SAFE_FREE(response); // TSK_OBJECT_SAFE_FREE(request); @@ -347,7 +347,7 @@ // TSK_OBJECT_SAFE_FREE(response); // } // } -// +// // TSK_OBJECT_SAFE_FREE(request); // return ret; //} @@ -357,12 +357,12 @@ //tnet_turn_allocation_id_t tnet_turn_allocate(const tnet_nat_context_t* nat_context, const tnet_fd_t localFD, tnet_socket_type_t socket_type) //{ // tnet_turn_allocation_id_t id = TNET_TURN_INVALID_ALLOCATION_ID; -// +// // if(nat_context){ // int ret; // tnet_turn_allocation_t* allocation = tnet_turn_allocation_create(localFD, nat_context->socket_type, nat_context->server_address, nat_context->server_port, nat_context->username, nat_context->password); // allocation->software = tsk_strdup(nat_context->software); -// +// // if((ret = tnet_turn_send_request(nat_context, allocation, tnet_turn_create_request_allocate))){ // TSK_DEBUG_ERROR("TURN allocation failed with error code:%d.", ret); // TSK_OBJECT_SAFE_FREE(allocation); @@ -422,9 +422,9 @@ // // if(nat_context && allocation){ // int ret; -// +// // channel_binding = tnet_turn_channel_binding_create(allocation); -// +// // if(channel_binding){ // if(((struct sockaddr*)peer)->sa_family == AF_INET){ // struct sockaddr_in *sin = ((struct sockaddr_in*)peer); @@ -433,7 +433,7 @@ // channel_binding->xpeer = tnet_turn_attribute_xpeer_addr_create_null(); // channel_binding->xpeer->family = stun_ipv4; // channel_binding->xpeer->xport = ((sin->sin_port) ^ tnet_htons(0x2112)); -// +// // _sin_addr = tnet_htonl_2(&sin->sin_addr) ^tnet_htonl(kStunMagicCookieLong); // memcpy(channel_binding->xpeer->xaddress, &_sin_addr, sizeof(_sin_addr)); // } @@ -453,7 +453,7 @@ // if((ret = tnet_turn_send_request(nat_context, allocation, tnet_turn_create_request_channel_bind, channel_binding))){ // TSK_DEBUG_ERROR("TURN (CHANNEL-BIND) failed with error code:%d.", ret); // TSK_OBJECT_SAFE_FREE(channel_binding); -// +// // goto bail; // } // else{ @@ -566,8 +566,8 @@ //{ // tnet_turn_channel_binding_t *channel_binding = self; // if(channel_binding){ -// static tnet_turn_channel_binding_id_t __allocation_unique_id = 0x4000; /* 0x4000 through 0x7FFF */ -// +// static tnet_turn_channel_binding_id_t __allocation_unique_id = 0x4000; /* 0x4000 through 0x7FFF */ +// // channel_binding->id = __allocation_unique_id++; // channel_binding->allocation = va_arg(*app, const tnet_turn_allocation_t *); // channel_binding->timeout = TNET_TURN_CHANBIND_TIMEOUT_DEFAULT; /* 10 minutes as per draft-ietf-behave-turn-16 subclause 11 */ @@ -580,21 +580,21 @@ //} // //static tsk_object_t* tnet_turn_channel_binding_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_channel_binding_t *channel_binding = self; // if(channel_binding){ // TSK_OBJECT_SAFE_FREE(channel_binding->xpeer); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_channel_binding_def_s = +//static const tsk_object_def_t tnet_turn_channel_binding_def_s = //{ // sizeof(tnet_turn_channel_binding_t), -// tnet_turn_channel_binding_ctor, +// tnet_turn_channel_binding_ctor, // tnet_turn_channel_binding_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_channel_binding_def_t = &tnet_turn_channel_binding_def_s; // @@ -611,21 +611,21 @@ //} // //static tsk_object_t* tnet_turn_permission_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_permission_t *permission = self; // if(permission){ // TSK_OBJECT_SAFE_FREE(permission->xpeer); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_permission_def_s = +//static const tsk_object_def_t tnet_turn_permission_def_s = //{ // sizeof(tnet_turn_permission_t), -// tnet_turn_permission_ctor, +// tnet_turn_permission_ctor, // tnet_turn_permission_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_permission_def_t = &tnet_turn_permission_def_s; // @@ -639,7 +639,7 @@ // tnet_turn_allocation_t *allocation = self; // if(allocation){ // static tnet_turn_allocation_id_t __allocation_unique_id = 0; -// +// // const char* server_address; // tnet_port_t server_port; // @@ -647,7 +647,7 @@ // // allocation->localFD = va_arg(*app, tnet_fd_t); // allocation->socket_type = va_arg(*app, tnet_socket_type_t); -// +// // server_address = va_arg(*app, const char*); //#if defined(__GNUC__) // server_port = (tnet_port_t)va_arg(*app, unsigned); @@ -668,7 +668,7 @@ //} // //static tsk_object_t* tnet_turn_allocation_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_allocation_t *allocation = self; // if(allocation){ // TSK_FREE(allocation->relay_address); @@ -679,23 +679,23 @@ // TSK_FREE(allocation->nonce); // // TSK_FREE(allocation->software); -// +// // TSK_OBJECT_SAFE_FREE(allocation->xmaddr); // TSK_OBJECT_SAFE_FREE(allocation->maddr); // // TSK_OBJECT_SAFE_FREE(allocation->channel_bindings); // TSK_OBJECT_SAFE_FREE(allocation->permissions); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_allocation_def_s = +//static const tsk_object_def_t tnet_turn_allocation_def_s = //{ // sizeof(tnet_turn_allocation_t), -// tnet_turn_allocation_ctor, +// tnet_turn_allocation_ctor, // tnet_turn_allocation_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_allocation_def_t = &tnet_turn_allocation_def_s; // diff --git a/tinyNET/src/turn/tnet_turn.h b/tinyNET/src/turn/tnet_turn.h index af3a5e4..f1c050e 100755 --- a/tinyNET/src/turn/tnet_turn.h +++ b/tinyNET/src/turn/tnet_turn.h @@ -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. //* @@ -113,15 +113,15 @@ //typedef struct tnet_turn_allocation_s //{ // TSK_DECLARE_OBJECT; -// +// // tnet_turn_allocation_id_t id; /**< Unique id. */ -// +// // char* relay_address; /**< the relayed transport address */ // //! 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; -// +// // /* 5-tuple */ // tnet_fd_t localFD; // tnet_socket_type_t socket_type; diff --git a/tinyNET/src/turn/tnet_turn_attribute.c b/tinyNET/src/turn/tnet_turn_attribute.c index 719f926..5dc3ee3 100755 --- a/tinyNET/src/turn/tnet_turn_attribute.c +++ b/tinyNET/src/turn/tnet_turn_attribute.c @@ -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. //* @@ -116,7 +116,7 @@ // // /* Attribute Value // */ -// +// // switch(type) // { // /* draft-ietf-behave-turn-16 - 14.1. CHANNEL-NUMBER */ @@ -176,7 +176,7 @@ // TSK_DEBUG_ERROR("==> NOT IMPLEMENTED"); // break; // } -// +// // /* draft-ietf-behave-turn-16 - 14.9. RESERVATION-TOKEN */ // case stun_reservation_token: // { @@ -296,7 +296,7 @@ // TSK_DEBUG_ERROR("SERIALIZE:TOKEN ==> NOT IMPLEMENTED"); // return -3; // } -// +// // default: break; // } // @@ -324,8 +324,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_channelnum_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_channelnum_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_channelnum_t *attribute = self; // if(attribute){ // } @@ -357,8 +357,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_lifetime_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_lifetime_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_lifetime_t *attribute = self; // if(attribute){ // } @@ -386,7 +386,7 @@ // if(attribute){ // const void *payload = va_arg(*app, const void*); // tsk_size_t payload_size = va_arg(*app, tsk_size_t); -// +// // if(payload && payload_size){ // } // TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_peer_address; @@ -395,8 +395,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_xpeer_addr_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_xpeer_addr_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_xpeer_addr_t *attribute = self; // if(attribute){ // } @@ -432,8 +432,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_data_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_data_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_data_t *attribute = self; // if(attribute){ // TSK_OBJECT_SAFE_FREE(attribute->value); @@ -466,7 +466,7 @@ // // TNET_STUN_ATTRIBUTE(attribute)->type = stun_xor_relayed_address; // TNET_STUN_ATTRIBUTE(attribute)->length = payload_size; -// +// // attribute->family = (tnet_stun_addr_family_t)(*(payloadPtr++)); // // attribute->xport = tnet_ntohs_2(payloadPtr); @@ -475,7 +475,7 @@ // // { /*=== Compute IP address */ // tsk_size_t addr_size = (attribute->family == stun_ipv6) ? 16 : (attribute->family == stun_ipv4 ? 4 : 0); -// if(addr_size){ +// if(addr_size){ // tsk_size_t i; // uint32_t addr; // @@ -489,14 +489,14 @@ // else{ // TSK_DEBUG_ERROR("UNKNOWN FAMILY [%u].", attribute->family); // } -// } +// } // } // } // return self; //} // -//static tsk_object_t* tnet_turn_attribute_xrelayed_addr_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_xrelayed_addr_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_xrelayed_addr_t *attribute = self; // if(attribute){ // } @@ -528,8 +528,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_even_port_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_even_port_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_even_port_t *attribute = self; // if(attribute){ // } @@ -561,8 +561,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_reqtrans_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_reqtrans_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_reqtrans_t *attribute = self; // if(attribute){ // } @@ -594,8 +594,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_dontfrag_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_dontfrag_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_dontfrag_t *attribute = self; // if(attribute){ // } @@ -628,8 +628,8 @@ // return self; //} // -//static tsk_object_t* tnet_turn_attribute_restoken_dtor(tsk_object_t * self) -//{ +//static tsk_object_t* tnet_turn_attribute_restoken_dtor(tsk_object_t * self) +//{ // tnet_turn_attribute_restoken_t *attribute = self; // if(attribute){ // } diff --git a/tinyNET/src/turn/tnet_turn_attribute.h b/tinyNET/src/turn/tnet_turn_attribute.h index 127116c..998379e 100755 --- a/tinyNET/src/turn/tnet_turn_attribute.h +++ b/tinyNET/src/turn/tnet_turn_attribute.h @@ -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. //* @@ -117,7 +117,7 @@ //typedef struct tnet_turn_attribute_even_port_s //{ // TNET_STUN_DECLARE_ATTRIBUTE; -// +// ///* // 0 1 2 3 4 5 6 7 // +-+-+-+-+-+-+-+-+ @@ -136,7 +136,7 @@ //typedef struct tnet_turn_attribute_reqtrans_s //{ // TNET_STUN_DECLARE_ATTRIBUTE; -///* +///* // draft-ietf-behave-turn-16 - 14.7. REQUESTED-TRANSPORT // 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 diff --git a/tinyNET/src/turn/tnet_turn_message.c b/tinyNET/src/turn/tnet_turn_message.c index 989fd2b..b0eff46 100755 --- a/tinyNET/src/turn/tnet_turn_message.c +++ b/tinyNET/src/turn/tnet_turn_message.c @@ -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. //* @@ -144,20 +144,20 @@ //} // //static tsk_object_t* tnet_turn_channel_data_dtor(tsk_object_t * self) -//{ +//{ // tnet_turn_channel_data_t *message = self; // if(message){ // TSK_FREE(message->data); // } -// +// // return self; //} // -//static const tsk_object_def_t tnet_turn_channel_data_def_s = +//static const tsk_object_def_t tnet_turn_channel_data_def_s = //{ // sizeof(tnet_turn_channel_data_t), -// tnet_turn_channel_data_ctor, +// tnet_turn_channel_data_ctor, // tnet_turn_channel_data_dtor, -// tsk_null, +// tsk_null, //}; //const tsk_object_def_t *tnet_turn_channel_data_def_t = &tnet_turn_channel_data_def_s; diff --git a/tinyNET/src/turn/tnet_turn_message.h b/tinyNET/src/turn/tnet_turn_message.h index c518366..c98d4f0 100755 --- a/tinyNET/src/turn/tnet_turn_message.h +++ b/tinyNET/src/turn/tnet_turn_message.h @@ -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. //* diff --git a/tinyNET/src/turn/tnet_turn_session.c b/tinyNET/src/turn/tnet_turn_session.c index e131dbc..801f01a 100755 --- a/tinyNET/src/turn/tnet_turn_session.c +++ b/tinyNET/src/turn/tnet_turn_session.c @@ -45,143 +45,141 @@ typedef tnet_stun_pkt_t tnet_turn_pkt_t; -typedef struct tnet_turn_peer_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_turn_peer_s { + TSK_DECLARE_OBJECT; - tnet_turn_peer_id_t id; + tnet_turn_peer_id_t id; - uint16_t u_chan_num; - uint32_t u_conn_id; // rfc6062 - 6.2.1. CONNECTION-ID, For streams only - tnet_fd_t conn_fd; // Connected FD: used for Streams only + uint16_t u_chan_num; + uint32_t u_conn_id; // rfc6062 - 6.2.1. CONNECTION-ID, For streams only + tnet_fd_t conn_fd; // Connected FD: used for Streams only - tnet_stun_addr_t addr_ip; - char* p_addr_ip; - uint16_t u_addr_port; - tsk_bool_t b_ipv6; - tsk_bool_t b_stream_connected; - tsk_buffer_t *p_stream_buff_in; + tnet_stun_addr_t addr_ip; + char* p_addr_ip; + uint16_t u_addr_port; + tsk_bool_t b_ipv6; + tsk_bool_t b_stream_connected; + tsk_buffer_t *p_stream_buff_in; tsk_buffer_t *p_stream_buff_out; - - tnet_stun_state_t e_createperm_state; - tnet_stun_state_t e_chanbind_state; - tnet_stun_state_t e_connect_state; - tnet_stun_state_t e_connbind_state; - - tnet_turn_pkt_t* p_pkt_createperm; - tnet_stun_pkt_t* p_pkt_sendind; - tnet_stun_pkt_t* p_pkt_chanbind; - tnet_stun_pkt_t* p_pkt_connect; // For streams only - tnet_stun_pkt_t* p_pkt_connbind; // For streams only - - struct { - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } createperm; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } chanbind; - } fresh; // schedule refresh - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } createperm; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } chanbind; - } rtt; // retransmit (UDP only, to deal with pkt loss) - } timer; + + tnet_stun_state_t e_createperm_state; + tnet_stun_state_t e_chanbind_state; + tnet_stun_state_t e_connect_state; + tnet_stun_state_t e_connbind_state; + + tnet_turn_pkt_t* p_pkt_createperm; + tnet_stun_pkt_t* p_pkt_sendind; + tnet_stun_pkt_t* p_pkt_chanbind; + tnet_stun_pkt_t* p_pkt_connect; // For streams only + tnet_stun_pkt_t* p_pkt_connbind; // For streams only + + struct { + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } createperm; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } chanbind; + } fresh; // schedule refresh + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } createperm; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } chanbind; + } rtt; // retransmit (UDP only, to deal with pkt loss) + } timer; } tnet_turn_peer_t; typedef tsk_list_t tnet_turn_peers_L_t; -typedef struct tnet_turn_session_s -{ - TSK_DECLARE_OBJECT; +typedef struct tnet_turn_session_s { + TSK_DECLARE_OBJECT; + + tsk_bool_t b_prepared; + tsk_bool_t b_started; + tsk_bool_t b_stopping; + enum tnet_stun_state_e e_alloc_state; + enum tnet_stun_state_e e_refresh_state; - tsk_bool_t b_prepared; - tsk_bool_t b_started; - tsk_bool_t b_stopping; - enum tnet_stun_state_e e_alloc_state; - enum tnet_stun_state_e e_refresh_state; - - enum tnet_turn_transport_e e_req_transport; + enum tnet_turn_transport_e e_req_transport; - uint32_t u_lifetime_alloc_in_sec; + uint32_t u_lifetime_alloc_in_sec; - tnet_turn_pkt_t* p_pkt_alloc; - tnet_stun_pkt_t* p_pkt_refresh; + tnet_turn_pkt_t* p_pkt_alloc; + tnet_stun_pkt_t* p_pkt_refresh; - void* p_buff_send_ptr; - tsk_size_t u_buff_send_size; + void* p_buff_send_ptr; + tsk_size_t u_buff_send_size; - void* p_buff_chandata_ptr; - tsk_size_t u_buff_chandata_size; + void* p_buff_chandata_ptr; + tsk_size_t u_buff_chandata_size; - char* p_rel_ip; - uint16_t u_rel_port; - tsk_bool_t b_rel_ipv6; + char* p_rel_ip; + uint16_t u_rel_port; + tsk_bool_t b_rel_ipv6; + + char* p_srflx_ip; + uint16_t u_srflx_port; + tsk_bool_t b_srflx_ipv6; - char* p_srflx_ip; - uint16_t u_srflx_port; - tsk_bool_t b_srflx_ipv6; - struct { tsk_bool_t auto_detect; struct tnet_proxyinfo_s* info; } proxy; - struct { - char* path_priv; - char* path_pub; - char* path_ca; - tsk_bool_t verify; - } ssl; - - struct { - char* p_usr_name; - char* p_pwd; - } cred; - - struct { - tnet_turn_session_callback_f f_fun; - struct tnet_turn_session_event_xs e; - } cb; - - struct { - tsk_timer_manager_handle_t *p_mgr; - tsk_timer_id_t u_timer_id_refresh; // To refresh Alloc (Send Refresh Indication) - struct { - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } alloc; - struct { - tsk_timer_id_t id; - uint64_t u_timeout; - } refresh; - } rtt; // retransmit (UDP only) - } timer; - - tnet_socket_t* p_lcl_sock; - char* p_srv_host; - uint16_t u_srv_port; - tsk_bool_t b_stream_connected; + struct { + char* path_priv; + char* path_pub; + char* path_ca; + tsk_bool_t verify; + } ssl; + + struct { + char* p_usr_name; + char* p_pwd; + } cred; + + struct { + tnet_turn_session_callback_f f_fun; + struct tnet_turn_session_event_xs e; + } cb; + + struct { + tsk_timer_manager_handle_t *p_mgr; + tsk_timer_id_t u_timer_id_refresh; // To refresh Alloc (Send Refresh Indication) + struct { + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } alloc; + struct { + tsk_timer_id_t id; + uint64_t u_timeout; + } refresh; + } rtt; // retransmit (UDP only) + } timer; + + tnet_socket_t* p_lcl_sock; + char* p_srv_host; + uint16_t u_srv_port; + tsk_bool_t b_stream_connected; tsk_buffer_t* p_stream_buff_out; // data pending until the socket is connected - tsk_bool_t b_stream_error; // Unrecoverable error occured - tsk_buffer_t *p_stream_buff_in; - struct sockaddr_storage srv_addr; - struct tnet_transport_s* p_transport; + tsk_bool_t b_stream_error; // Unrecoverable error occured + tsk_buffer_t *p_stream_buff_in; + struct sockaddr_storage srv_addr; + struct tnet_transport_s* p_transport; - tnet_turn_peers_L_t* p_list_peers; + tnet_turn_peers_L_t* p_list_peers; - TSK_DECLARE_SAFEOBJ; + TSK_DECLARE_SAFEOBJ; } tnet_turn_session_t; @@ -207,87 +205,99 @@ static int _tnet_turn_peer_create(const char* pc_peer_ip, uint16_t u_peer_port, static int _tnet_turn_peer_find_by_xpeer(const tnet_turn_peers_L_t* pc_peers, const tnet_stun_attr_address_t* pc_xpeer, const tnet_turn_peer_t **ppc_peer); /*** PREDICATES ***/ -static int __pred_find_peer_by_id(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->id - *((const tnet_turn_peer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_id(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->id - *((const tnet_turn_peer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_fd(const tsk_list_item_t *item, const void *fd) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->conn_fd - *((const tnet_fd_t*)fd)); - } - return -1; +static int __pred_find_peer_by_fd(const tsk_list_item_t *item, const void *fd) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->conn_fd - *((const tnet_fd_t*)fd)); + } + return -1; } -static int __pred_find_peer_by_channum(const tsk_list_item_t *item, const void *pu_chan_num) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->u_chan_num - *((const uint16_t*)pu_chan_num)); - } - return -1; +static int __pred_find_peer_by_channum(const tsk_list_item_t *item, const void *pu_chan_num) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->u_chan_num - *((const uint16_t*)pu_chan_num)); + } + return -1; } -static int __pred_find_peer_by_timer_rtt_createperm(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.createperm.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_rtt_createperm(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.createperm.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_timer_fresh_createperm(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.createperm.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_fresh_createperm(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.createperm.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_transacid_createperm(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_createperm(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_createperm->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_timer_rtt_chanbind(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.chanbind.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_rtt_chanbind(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.rtt.chanbind.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_timer_fresh_chanbind(const tsk_list_item_t *item, const void *id) { - if (item && item->data) { - return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.chanbind.id - *((const tsk_timer_id_t*)id)); - } - return -1; +static int __pred_find_peer_by_timer_fresh_chanbind(const tsk_list_item_t *item, const void *id) +{ + if (item && item->data) { + return (int)(((const struct tnet_turn_peer_s *)item->data)->timer.fresh.chanbind.id - *((const tsk_timer_id_t*)id)); + } + return -1; } -static int __pred_find_peer_by_transacid_chanbind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_chanbind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_chanbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_connect(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_connect(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connect->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_connectionbind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_connectionbind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_connbind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } -static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, const void *pc_transacid) { - if (item && item->data) { - return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind - ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) - : +1; - } - return -1; +static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, const void *pc_transacid) +{ + if (item && item->data) { + return ((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind + ? tnet_stun_utils_transac_id_cmp(((const struct tnet_turn_peer_s *)item->data)->p_pkt_sendind->transac_id, *((const tnet_stun_transac_id_t*)pc_transacid)) + : +1; + } + return -1; } #define _tnet_turn_session_raise_event0(_p_self, _e_type, _u_peer_id) \ @@ -321,117 +331,117 @@ static int __pred_find_peer_by_transacid_sendind(const tsk_list_item_t *item, co int tnet_turn_session_create(struct tnet_socket_s* p_lcl_sock, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, struct tnet_turn_session_s** pp_self) { - int ret; - extern const tsk_object_def_t *tnet_turn_session_def_t; - tnet_turn_session_t* p_self; - if (!p_lcl_sock || !TNET_SOCKET_IS_VALID(p_lcl_sock) || !pc_srv_host || !u_srv_port || !pp_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if (!(p_self = tsk_object_new(tnet_turn_session_def_t))) { - TSK_DEBUG_ERROR("Failed to create 'tnet_turn_session_def_t' object"); - return -2; - } - if (!(p_self->p_list_peers = tsk_list_create())) { - TSK_DEBUG_ERROR("Failed to create list"); - ret = -3; - goto bail; - } - if (TNET_SOCKET_TYPE_IS_STREAM(p_lcl_sock->type) && !(p_self->p_stream_buff_in = tsk_buffer_create_null())) { - TSK_DEBUG_ERROR("Failed to stream buffer"); - ret = -4; - goto bail; - } - if ((ret = tnet_sockaddr_init(pc_srv_host, u_srv_port, p_lcl_sock->type, &p_self->srv_addr))) { - TSK_DEBUG_ERROR("Invalid TURN SRV address [%s:%u]", pc_srv_host, u_srv_port); - goto bail; - } - tsk_strupdate(&p_self->p_srv_host, pc_srv_host); - p_self->u_srv_port = u_srv_port; - p_self->p_lcl_sock = tsk_object_ref(p_lcl_sock); - p_self->e_req_transport = e_req_transport; - p_self->cb.e.pc_session = p_self; - *pp_self = p_self; + int ret; + extern const tsk_object_def_t *tnet_turn_session_def_t; + tnet_turn_session_t* p_self; + if (!p_lcl_sock || !TNET_SOCKET_IS_VALID(p_lcl_sock) || !pc_srv_host || !u_srv_port || !pp_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if (!(p_self = tsk_object_new(tnet_turn_session_def_t))) { + TSK_DEBUG_ERROR("Failed to create 'tnet_turn_session_def_t' object"); + return -2; + } + if (!(p_self->p_list_peers = tsk_list_create())) { + TSK_DEBUG_ERROR("Failed to create list"); + ret = -3; + goto bail; + } + if (TNET_SOCKET_TYPE_IS_STREAM(p_lcl_sock->type) && !(p_self->p_stream_buff_in = tsk_buffer_create_null())) { + TSK_DEBUG_ERROR("Failed to stream buffer"); + ret = -4; + goto bail; + } + if ((ret = tnet_sockaddr_init(pc_srv_host, u_srv_port, p_lcl_sock->type, &p_self->srv_addr))) { + TSK_DEBUG_ERROR("Invalid TURN SRV address [%s:%u]", pc_srv_host, u_srv_port); + goto bail; + } + tsk_strupdate(&p_self->p_srv_host, pc_srv_host); + p_self->u_srv_port = u_srv_port; + p_self->p_lcl_sock = tsk_object_ref(p_lcl_sock); + p_self->e_req_transport = e_req_transport; + p_self->cb.e.pc_session = p_self; + *pp_self = p_self; bail: - if (ret) { - TSK_OBJECT_SAFE_FREE(p_self); - } - return ret; + if (ret) { + TSK_OBJECT_SAFE_FREE(p_self); + } + return ret; } int tnet_turn_session_create_2(const char* pc_lcl_ip, uint16_t u_lcl_port, enum tnet_socket_type_e e_lcl_type, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, struct tnet_turn_session_s** pp_self) { - tnet_socket_t* p_lcl_sock; - int ret; - if (!pc_srv_host || !u_srv_port || !pp_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!(p_lcl_sock = tnet_socket_create(pc_lcl_ip, u_lcl_port, e_lcl_type))) { - TSK_DEBUG_ERROR("Failed to create socket(%s:%u$%d)", pc_lcl_ip, u_lcl_port, e_lcl_type); - return -2; - } - ret = tnet_turn_session_create(p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); - TSK_OBJECT_SAFE_FREE(p_lcl_sock); - return ret; + tnet_socket_t* p_lcl_sock; + int ret; + if (!pc_srv_host || !u_srv_port || !pp_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!(p_lcl_sock = tnet_socket_create(pc_lcl_ip, u_lcl_port, e_lcl_type))) { + TSK_DEBUG_ERROR("Failed to create socket(%s:%u$%d)", pc_lcl_ip, u_lcl_port, e_lcl_type); + return -2; + } + ret = tnet_turn_session_create(p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); + TSK_OBJECT_SAFE_FREE(p_lcl_sock); + return ret; } int tnet_turn_session_create_4(struct tnet_socket_s* p_lcl_sock, enum tnet_turn_transport_e e_req_transport, const char* pc_srv_host, uint16_t u_srv_port, enum tnet_socket_type_e e_srv_type, struct tnet_turn_session_s** pp_self) { - struct tnet_socket_s* _p_lcl_sock; - int ret; + struct tnet_socket_s* _p_lcl_sock; + int ret; - if (TNET_SOCKET_TYPE_IS_STREAM(e_srv_type)) { - // For stream the socket will be connected to the server and this is why we need to create a new socket - if (!(_p_lcl_sock = tnet_socket_create(p_lcl_sock->ip, TNET_SOCKET_PORT_ANY/*p_lcl_sock->port*/, e_srv_type))) { - return -2; - } - } - else { - // For UDP, use the socket socket - _p_lcl_sock = tsk_object_ref(p_lcl_sock); - } - ret = tnet_turn_session_create(_p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); - TSK_OBJECT_SAFE_FREE(_p_lcl_sock); - return ret; + if (TNET_SOCKET_TYPE_IS_STREAM(e_srv_type)) { + // For stream the socket will be connected to the server and this is why we need to create a new socket + if (!(_p_lcl_sock = tnet_socket_create(p_lcl_sock->ip, TNET_SOCKET_PORT_ANY/*p_lcl_sock->port*/, e_srv_type))) { + return -2; + } + } + else { + // For UDP, use the socket socket + _p_lcl_sock = tsk_object_ref(p_lcl_sock); + } + ret = tnet_turn_session_create(_p_lcl_sock, e_req_transport, pc_srv_host, u_srv_port, pp_self); + TSK_OBJECT_SAFE_FREE(_p_lcl_sock); + return ret; } int tnet_turn_session_set_cred(tnet_turn_session_t* p_self, const char* pc_usr_name, const char* pc_pwd) { - if (!p_self || !pc_usr_name || !pc_pwd) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_strupdate(&p_self->cred.p_usr_name, pc_usr_name); - tsk_strupdate(&p_self->cred.p_pwd, pc_pwd); + if (!p_self || !pc_usr_name || !pc_pwd) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_strupdate(&p_self->cred.p_usr_name, pc_usr_name); + tsk_strupdate(&p_self->cred.p_pwd, pc_pwd); - return 0; + return 0; } int tnet_turn_session_set_callback(struct tnet_turn_session_s* p_self, tnet_turn_session_callback_f f_fun, const void* pc_usr_data) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - p_self->cb.f_fun = f_fun; - p_self->cb.e.pc_usr_data = pc_usr_data; - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + p_self->cb.f_fun = f_fun; + p_self->cb.e.pc_usr_data = pc_usr_data; + return 0; } int tnet_turn_session_set_ssl_certs(struct tnet_turn_session_s* p_self, const char* path_priv, const char* path_pub, const char* path_ca, tsk_bool_t verify) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - tsk_strupdate(&p_self->ssl.path_priv, path_priv); - tsk_strupdate(&p_self->ssl.path_pub, path_pub); - tsk_strupdate(&p_self->ssl.path_ca, path_ca); - p_self->ssl.verify = verify; - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + tsk_strupdate(&p_self->ssl.path_priv, path_priv); + tsk_strupdate(&p_self->ssl.path_pub, path_pub); + tsk_strupdate(&p_self->ssl.path_ca, path_ca); + p_self->ssl.verify = verify; + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_set_proxy_auto_detect(struct tnet_turn_session_s* p_self, tsk_bool_t auto_detect) @@ -461,99 +471,99 @@ int tnet_turn_session_set_proxy_info(struct tnet_turn_session_s* p_self, struct int tnet_turn_session_prepare(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (p_self->b_prepared) { - goto bail; - } + if (p_self->b_prepared) { + goto bail; + } - p_self->e_alloc_state = tnet_stun_state_none; - p_self->e_refresh_state = tnet_stun_state_none; + p_self->e_alloc_state = tnet_stun_state_none; + p_self->e_refresh_state = tnet_stun_state_none; - p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; - p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; + p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; + p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; - p_self->timer.u_timer_id_refresh = TSK_INVALID_TIMER_ID; - p_self->u_lifetime_alloc_in_sec = kTurnAllocationTimeOutInSec; + p_self->timer.u_timer_id_refresh = TSK_INVALID_TIMER_ID; + p_self->u_lifetime_alloc_in_sec = kTurnAllocationTimeOutInSec; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); - // create timer manager - if (!p_self->timer.p_mgr && !(p_self->timer.p_mgr = tsk_timer_manager_create())) { - TSK_DEBUG_ERROR("Failed to create timer manager"); + // create timer manager + if (!p_self->timer.p_mgr && !(p_self->timer.p_mgr = tsk_timer_manager_create())) { + TSK_DEBUG_ERROR("Failed to create timer manager"); ret = -4; - goto bail; - } + goto bail; + } - // create transport + // create transport if (!p_self->p_transport) { - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - // Use the DGram socket as master - p_self->p_transport = tnet_transport_create_2(p_self->p_lcl_sock, kTurnTransportFriendlyName); - } - else { - // Use the Stream socket later and connect it - p_self->p_transport = tnet_transport_create(p_self->p_lcl_sock->ip, TNET_SOCKET_PORT_ANY, p_self->p_lcl_sock->type, kTurnTransportFriendlyName); - } - if (!p_self->p_transport) { - TSK_DEBUG_ERROR("Failed to create %s Transport", kTurnTransportFriendlyName); - ret = -5; - goto bail; - } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + // Use the DGram socket as master + p_self->p_transport = tnet_transport_create_2(p_self->p_lcl_sock, kTurnTransportFriendlyName); + } + else { + // Use the Stream socket later and connect it + p_self->p_transport = tnet_transport_create(p_self->p_lcl_sock->ip, TNET_SOCKET_PORT_ANY, p_self->p_lcl_sock->type, kTurnTransportFriendlyName); + } + if (!p_self->p_transport) { + TSK_DEBUG_ERROR("Failed to create %s Transport", kTurnTransportFriendlyName); + ret = -5; + goto bail; + } } // set transport callback - if ((ret = tnet_transport_set_callback(p_self->p_transport, TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type) ? _tnet_turn_session_transport_layer_dgram_cb : _tnet_turn_session_transport_layer_stream_cb, p_self))) { + if ((ret = tnet_transport_set_callback(p_self->p_transport, TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type) ? _tnet_turn_session_transport_layer_dgram_cb : _tnet_turn_session_transport_layer_stream_cb, p_self))) { goto bail; - } + } - p_self->b_prepared = tsk_true; + p_self->b_prepared = tsk_true; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_start(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (p_self->b_started) { - goto bail; - } - if (!p_self->b_prepared) { - TSK_DEBUG_ERROR("TURN session not prepared yet"); - ret = -2; - goto bail; - } + if (p_self->b_started) { + goto bail; + } + if (!p_self->b_prepared) { + TSK_DEBUG_ERROR("TURN session not prepared yet"); + ret = -2; + goto bail; + } - // start timer manager - if ((ret = tsk_timer_manager_start(p_self->timer.p_mgr))) { - TSK_DEBUG_ERROR("Failed to start TURN timer manager"); - goto bail; - } + // start timer manager + if ((ret = tsk_timer_manager_start(p_self->timer.p_mgr))) { + TSK_DEBUG_ERROR("Failed to start TURN timer manager"); + goto bail; + } + + // set SSL certificates + if (TNET_SOCKET_TYPE_IS_TLS(p_self->p_lcl_sock->type) || TNET_SOCKET_TYPE_IS_WSS(p_self->p_lcl_sock->type)) { + if ((ret = tnet_transport_tls_set_certs(p_self->p_transport, p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv, p_self->ssl.verify))) { + TSK_DEBUG_ERROR("Failed to set SSL certificates: '%s', '%s', '%s'", p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv); + goto bail; + } + } - // set SSL certificates - if (TNET_SOCKET_TYPE_IS_TLS(p_self->p_lcl_sock->type) || TNET_SOCKET_TYPE_IS_WSS(p_self->p_lcl_sock->type)) { - if ((ret = tnet_transport_tls_set_certs(p_self->p_transport, p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv, p_self->ssl.verify))) { - TSK_DEBUG_ERROR("Failed to set SSL certificates: '%s', '%s', '%s'", p_self->ssl.path_ca, p_self->ssl.path_pub, p_self->ssl.path_priv); - goto bail; - } - } - // Proxy info if ((ret = tnet_transport_set_proxy_auto_detect(p_self->p_transport, p_self->proxy.auto_detect))) { TSK_DEBUG_ERROR("Failed to set proxy autodetect option"); @@ -566,218 +576,218 @@ int tnet_turn_session_start(tnet_turn_session_t* p_self) } } - // start network transport - if ((ret = tnet_transport_start(p_self->p_transport))) { - TSK_DEBUG_ERROR("Failed to start TURN transport"); - goto bail; - } - - // Connect to the server - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { - tnet_fd_t fd; - p_self->b_stream_connected = tsk_false; - p_self->b_stream_error = tsk_false; - fd = tnet_transport_connectto_3(p_self->p_transport, p_self->p_lcl_sock, p_self->p_srv_host, p_self->u_srv_port, p_self->p_lcl_sock->type); - if (fd != p_self->p_lcl_sock->fd) { - TSK_DEBUG_ERROR("Failed to connect to TURN server(%s:%d)", p_self->p_srv_host, p_self->u_srv_port); - ret = -3; - goto bail; - } - TSK_DEBUG_INFO("TURN server connection fd = %d", p_self->p_lcl_sock->fd); - } + // start network transport + if ((ret = tnet_transport_start(p_self->p_transport))) { + TSK_DEBUG_ERROR("Failed to start TURN transport"); + goto bail; + } + + // Connect to the server + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { + tnet_fd_t fd; + p_self->b_stream_connected = tsk_false; + p_self->b_stream_error = tsk_false; + fd = tnet_transport_connectto_3(p_self->p_transport, p_self->p_lcl_sock, p_self->p_srv_host, p_self->u_srv_port, p_self->p_lcl_sock->type); + if (fd != p_self->p_lcl_sock->fd) { + TSK_DEBUG_ERROR("Failed to connect to TURN server(%s:%d)", p_self->p_srv_host, p_self->u_srv_port); + ret = -3; + goto bail; + } + TSK_DEBUG_INFO("TURN server connection fd = %d", p_self->p_lcl_sock->fd); + } - p_self->b_started = tsk_true; + p_self->b_started = tsk_true; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_allocate(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } - // create Allocate Request - p_self->e_alloc_state = tnet_stun_state_none; - p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_allocate_request, &p_self->p_pkt_alloc))) { - TSK_DEBUG_ERROR("Failed to create TURN Allocate request"); - goto bail; - } - // add attributes - p_self->p_pkt_alloc->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_alloc, - TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), - TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(p_self->e_req_transport), - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_alloc))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_self->timer.rtt.alloc.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.alloc.id, p_self->timer.rtt.alloc.u_timeout); - } - p_self->e_alloc_state = tnet_stun_state_trying; + // create Allocate Request + p_self->e_alloc_state = tnet_stun_state_none; + p_self->timer.rtt.alloc.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_alloc); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_allocate_request, &p_self->p_pkt_alloc))) { + TSK_DEBUG_ERROR("Failed to create TURN Allocate request"); + goto bail; + } + // add attributes + p_self->p_pkt_alloc->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_alloc, + TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), + TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(p_self->e_req_transport), + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_alloc))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_self->timer.rtt.alloc.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.alloc.id, p_self->timer.rtt.alloc.u_timeout); + } + p_self->e_alloc_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_relayed_addr(const struct tnet_turn_session_s* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6) { - int ret = 0; + int ret = 0; - if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - tsk_strupdate(pp_ip, p_self->p_rel_ip); - *pu_port = p_self->u_rel_port; - *pb_ipv6 = p_self->b_rel_ipv6; + tsk_strupdate(pp_ip, p_self->p_rel_ip); + *pu_port = p_self->u_rel_port; + *pb_ipv6 = p_self->b_rel_ipv6; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_srflx_addr(const tnet_turn_session_t* p_self, char** pp_ip, uint16_t *pu_port, tsk_bool_t *pb_ipv6) { - int ret = 0; + int ret = 0; - if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pp_ip || !pu_port || !pb_ipv6) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - tsk_strupdate(pp_ip, p_self->p_srflx_ip); - *pu_port = p_self->u_srflx_port; - *pb_ipv6 = p_self->b_srflx_ipv6; + tsk_strupdate(pp_ip, p_self->p_srflx_ip); + *pu_port = p_self->u_srflx_port; + *pb_ipv6 = p_self->b_srflx_ipv6; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_get_state_alloc(const struct tnet_turn_session_s* pc_self, enum tnet_stun_state_e *pe_state) { - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *pe_state = pc_self->e_alloc_state; - return 0; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *pe_state = pc_self->e_alloc_state; + return 0; } int tnet_turn_session_get_socket_local(struct tnet_turn_session_s* p_self, struct tnet_socket_s** pp_lcl_sock) { - if (!p_self || !pp_lcl_sock) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - *pp_lcl_sock = (struct tnet_socket_s*)tsk_object_ref(p_self->p_lcl_sock); - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self || !pp_lcl_sock) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + *pp_lcl_sock = (struct tnet_socket_s*)tsk_object_ref(p_self->p_lcl_sock); + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_get_state_createperm(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, enum tnet_stun_state_e *pe_state) { - const tnet_turn_peer_t *pc_peer; - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pe_state = pc_peer->e_createperm_state; - } - else { - *pe_state = tnet_stun_state_none; - if (u_peer_id != kTurnPeerIdInvalid) { - TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); - } - } - tsk_safeobj_unlock(pc_self); - return 0; + const tnet_turn_peer_t *pc_peer; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pe_state = pc_peer->e_createperm_state; + } + else { + *pe_state = tnet_stun_state_none; + if (u_peer_id != kTurnPeerIdInvalid) { + TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_state_connbind(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, enum tnet_stun_state_e *pe_state) { - const tnet_turn_peer_t *pc_peer; - if (!pc_self || !pe_state) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pe_state = pc_peer->e_connbind_state; - } - else { - *pe_state = tnet_stun_state_none; - if (u_peer_id != kTurnPeerIdInvalid) { - TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); - } - } - tsk_safeobj_unlock(pc_self); - return 0; + const tnet_turn_peer_t *pc_peer; + if (!pc_self || !pe_state) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + if ((pc_peer = tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pe_state = pc_peer->e_connbind_state; + } + else { + *pe_state = tnet_stun_state_none; + if (u_peer_id != kTurnPeerIdInvalid) { + TSK_DEBUG_WARN("TURN peer with id =%ld doesn't exist", u_peer_id); + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_req_transport(const struct tnet_turn_session_s* pc_self, enum tnet_turn_transport_e *pe_transport) { - if (!pc_self || !pe_transport) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pe_transport = pc_self->e_req_transport; - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pe_transport) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pe_transport = pc_self->e_req_transport; + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_get_bytes_count(const struct tnet_turn_session_s* pc_self, uint64_t* bytes_in, uint64_t* bytes_out) @@ -791,459 +801,459 @@ int tnet_turn_session_get_bytes_count(const struct tnet_turn_session_s* pc_self, int tnet_turn_session_createpermission(struct tnet_turn_session_s* p_self, const char* pc_peer_addr, uint16_t u_peer_port, tnet_turn_peer_id_t* pu_id) { - int ret = 0; - tnet_turn_peer_t *p_peer = tsk_null; + int ret = 0; + tnet_turn_peer_t *p_peer = tsk_null; - if (!p_self || !pc_peer_addr || !u_peer_port || !pu_id) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(p_self); + if (!p_self || !pc_peer_addr || !u_peer_port || !pu_id) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if ((ret = _tnet_turn_peer_create(pc_peer_addr, u_peer_port, TNET_SOCKET_TYPE_IS_IPV6(p_self->p_lcl_sock->type), &p_peer))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { - if (!p_peer->p_stream_buff_in && !(p_peer->p_stream_buff_in = tsk_buffer_create_null())) { - TSK_DEBUG_ERROR("Failed to create stream buffer for peer with id=%ld", p_peer->id); - ret = -5; - goto bail; - } - } - if ((ret = _tnet_turn_session_send_permission(p_self, p_peer))) { - goto bail; - } - *pu_id = p_peer->id; - tsk_list_push_back_data(p_self->p_list_peers, (void**)&p_peer); + tsk_safeobj_lock(p_self); + + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if ((ret = _tnet_turn_peer_create(pc_peer_addr, u_peer_port, TNET_SOCKET_TYPE_IS_IPV6(p_self->p_lcl_sock->type), &p_peer))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type)) { + if (!p_peer->p_stream_buff_in && !(p_peer->p_stream_buff_in = tsk_buffer_create_null())) { + TSK_DEBUG_ERROR("Failed to create stream buffer for peer with id=%ld", p_peer->id); + ret = -5; + goto bail; + } + } + if ((ret = _tnet_turn_session_send_permission(p_self, p_peer))) { + goto bail; + } + *pu_id = p_peer->id; + tsk_list_push_back_data(p_self->p_list_peers, (void**)&p_peer); bail: - TSK_OBJECT_SAFE_FREE(p_peer); - tsk_safeobj_unlock(p_self); - return ret; + TSK_OBJECT_SAFE_FREE(p_peer); + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_deletepermission(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_id) { - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(p_self); - tsk_list_remove_item_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_id); - tsk_safeobj_unlock(p_self); - return 0; + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(p_self); + tsk_list_remove_item_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_id); + tsk_safeobj_unlock(p_self); + return 0; } int tnet_turn_session_chanbind(tnet_turn_session_t* p_self, tnet_turn_peer_id_t u_peer_id) { - int ret = 0; - tnet_turn_peer_t *pc_peer; + int ret = 0; + tnet_turn_peer_t *pc_peer; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -5; + goto bail; + } - // ChannelBind must not be used for streams (e.g. TCP, TLS....) - if (p_self->e_req_transport != tnet_turn_transport_udp) { - TSK_DEBUG_ERROR("TURN ChannelBind not supported for stream"); - ret = -6; - goto bail; - } + // ChannelBind must not be used for streams (e.g. TCP, TLS....) + if (p_self->e_req_transport != tnet_turn_transport_udp) { + TSK_DEBUG_ERROR("TURN ChannelBind not supported for stream"); + ret = -6; + goto bail; + } - // create ChannelBind Request if doesn't exist (ChannelBind refresh *must* have same id) - pc_peer->e_chanbind_state = tnet_stun_state_none; - pc_peer->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; - if (!pc_peer->p_pkt_chanbind) { - pc_peer->u_chan_num = _tnet_turn_session_get_unique_chan_num(); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_channelbind_request, &pc_peer->p_pkt_chanbind))) { - TSK_DEBUG_ERROR("Failed to create TURN ChannelBind request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_chanbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - pc_peer->p_pkt_chanbind->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_chanbind, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_CHANNEL_NUMBER(pc_peer->u_chan_num), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_chanbind->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_chanbind))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - pc_peer->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.rtt.chanbind.id, pc_peer->timer.rtt.chanbind.u_timeout); - } - pc_peer->e_chanbind_state = tnet_stun_state_trying; + // create ChannelBind Request if doesn't exist (ChannelBind refresh *must* have same id) + pc_peer->e_chanbind_state = tnet_stun_state_none; + pc_peer->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; + if (!pc_peer->p_pkt_chanbind) { + pc_peer->u_chan_num = _tnet_turn_session_get_unique_chan_num(); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_channelbind_request, &pc_peer->p_pkt_chanbind))) { + TSK_DEBUG_ERROR("Failed to create TURN ChannelBind request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_chanbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + pc_peer->p_pkt_chanbind->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_chanbind, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_CHANNEL_NUMBER(pc_peer->u_chan_num), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_chanbind->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_chanbind))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + pc_peer->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.rtt.chanbind.id, pc_peer->timer.rtt.chanbind.u_timeout); + } + pc_peer->e_chanbind_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } // TCP-Connect rfc6062 - 4.3. Initiating a Connection int tnet_turn_session_connect(struct tnet_turn_session_s* p_self, tnet_turn_peer_id_t u_peer_id) { - int ret = 0; - tnet_turn_peer_t *pc_peer; + int ret = 0; + tnet_turn_peer_t *pc_peer; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -5; + goto bail; + } - // Connect must be used for streams (e.g. TCP, TLS....) only - if (p_self->e_req_transport != tnet_turn_transport_tcp) { - TSK_DEBUG_ERROR("TURN Connect not supported for UDP relay"); - ret = -6; - goto bail; - } + // Connect must be used for streams (e.g. TCP, TLS....) only + if (p_self->e_req_transport != tnet_turn_transport_tcp) { + TSK_DEBUG_ERROR("TURN Connect not supported for UDP relay"); + ret = -6; + goto bail; + } - // create Connect Request if doesn't exist (Connect refresh *must* have same id) - pc_peer->e_connect_state = tnet_stun_state_none; - pc_peer->e_connbind_state = tnet_stun_state_none; - if (!pc_peer->p_pkt_connect) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connect_request, &pc_peer->p_pkt_connect))) { - TSK_DEBUG_ERROR("Failed to create TURN Connect request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_connect, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - pc_peer->p_pkt_connect->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_connect, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_connect->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_connect))) { - goto bail; - } - pc_peer->e_connect_state = tnet_stun_state_trying; + // create Connect Request if doesn't exist (Connect refresh *must* have same id) + pc_peer->e_connect_state = tnet_stun_state_none; + pc_peer->e_connbind_state = tnet_stun_state_none; + if (!pc_peer->p_pkt_connect) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connect_request, &pc_peer->p_pkt_connect))) { + TSK_DEBUG_ERROR("Failed to create TURN Connect request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_connect, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + pc_peer->p_pkt_connect->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_connect, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_connect->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, pc_peer->p_pkt_connect))) { + goto bail; + } + pc_peer->e_connect_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_send_data(tnet_turn_session_t* p_self, tnet_turn_peer_id_t u_peer_id, const void* pc_data_ptr, uint16_t u_data_size) { - int ret = 0; - tnet_turn_peer_t* pc_peer; + int ret = 0; + tnet_turn_peer_t* pc_peer; - if (!p_self || !pc_data_ptr || !u_data_size) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !pc_data_ptr || !u_data_size) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -3; - goto bail; - } - if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); - ret = -4; - goto bail; - } - if (pc_peer->e_createperm_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN permission for the remote peer"); - ret = -5; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -3; + goto bail; + } + if (!(pc_peer = (tnet_turn_peer_t *)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + TSK_DEBUG_ERROR("Cannot find TURN peer with id = %ld", u_peer_id); + ret = -4; + goto bail; + } + if (pc_peer->e_createperm_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN permission for the remote peer"); + ret = -5; + goto bail; + } - /** Send Stream **/ - if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type) && p_self->e_req_transport == tnet_turn_transport_tcp) { - ret = _tnet_turn_session_send_stream_raw(p_self, pc_peer, pc_data_ptr, u_data_size); - goto bail; - } + /** Send Stream **/ + if (TNET_SOCKET_TYPE_IS_STREAM(p_self->p_lcl_sock->type) && p_self->e_req_transport == tnet_turn_transport_tcp) { + ret = _tnet_turn_session_send_stream_raw(p_self, pc_peer, pc_data_ptr, u_data_size); + goto bail; + } - /*** ChannelData ***/ - if (pc_peer->e_chanbind_state == tnet_stun_state_ok) { - ret = _tnet_turn_session_send_chandata(p_self, pc_peer, pc_data_ptr, u_data_size); - goto bail; - } + /*** ChannelData ***/ + if (pc_peer->e_chanbind_state == tnet_stun_state_ok) { + ret = _tnet_turn_session_send_chandata(p_self, pc_peer, pc_data_ptr, u_data_size); + goto bail; + } + + /*** Send indication ***/ + if (!pc_peer->p_pkt_sendind) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_send_indication, &pc_peer->p_pkt_sendind))) { + TSK_DEBUG_ERROR("Failed to create TURN SendIndication request"); + goto bail; + } + pc_peer->p_pkt_sendind->opt.dontfrag = 0; + // add authinfo + tnet_stun_pkt_auth_copy(pc_peer->p_pkt_sendind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + else { + const tnet_stun_attr_vdata_t *pc_attr_data; + if ((ret = tnet_stun_pkt_attr_find_first(pc_peer->p_pkt_sendind, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data))) { + goto bail; + } + if (!pc_attr_data) { + ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, + TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + } + else { + if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr_data, pc_data_ptr, u_data_size))) { + goto bail; + } + } + if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_sendind->transac_id))) { + goto bail; + } + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_peer->p_pkt_sendind))) { + goto bail; + } - /*** Send indication ***/ - if (!pc_peer->p_pkt_sendind) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_send_indication, &pc_peer->p_pkt_sendind))) { - TSK_DEBUG_ERROR("Failed to create TURN SendIndication request"); - goto bail; - } - pc_peer->p_pkt_sendind->opt.dontfrag = 0; - // add authinfo - tnet_stun_pkt_auth_copy(pc_peer->p_pkt_sendind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(pc_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, pc_peer->u_addr_port, &pc_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - else { - const tnet_stun_attr_vdata_t *pc_attr_data; - if ((ret = tnet_stun_pkt_attr_find_first(pc_peer->p_pkt_sendind, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data))) { - goto bail; - } - if (!pc_attr_data) { - ret = tnet_stun_pkt_attrs_add(pc_peer->p_pkt_sendind, - TNET_STUN_PKT_ATTR_ADD_DATA(pc_data_ptr, u_data_size), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - } - else { - if ((ret = tnet_stun_attr_vdata_update((tnet_stun_attr_vdata_t*)pc_attr_data, pc_data_ptr, u_data_size))) { - goto bail; - } - } - if ((ret = tnet_stun_utils_transac_id_rand(&pc_peer->p_pkt_sendind->transac_id))) { - goto bail; - } - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_peer->p_pkt_sendind))) { - goto bail; - } - bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } int tnet_turn_session_is_active(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, tsk_bool_t *pb_active) { - if (!pc_self || !pb_active) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_active = pc_self->b_started - && (pc_self->e_alloc_state == tnet_stun_state_ok); - if (*pb_active) { - const tnet_turn_peer_t* pc_peer; - if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pb_active = (pc_peer->e_createperm_state == tnet_stun_state_ok); - } - else { - *pb_active = tsk_false; - } - } - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_active) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_active = pc_self->b_started + && (pc_self->e_alloc_state == tnet_stun_state_ok); + if (*pb_active) { + const tnet_turn_peer_t* pc_peer; + if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pb_active = (pc_peer->e_createperm_state == tnet_stun_state_ok); + } + else { + *pb_active = tsk_false; + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_is_stream(const struct tnet_turn_session_s* pc_self, tsk_bool_t *pb_stream) { - if (!pc_self || !pb_stream) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_stream = TNET_SOCKET_TYPE_IS_STREAM(pc_self->p_lcl_sock->type) ? tsk_true : tsk_false; - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_stream) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_stream = TNET_SOCKET_TYPE_IS_STREAM(pc_self->p_lcl_sock->type) ? tsk_true : tsk_false; + tsk_safeobj_unlock(pc_self); + return 0; } // Check "ConnectionBind" sent and underlaying socket is connected int tnet_turn_session_is_stream_connected(const struct tnet_turn_session_s* pc_self, tnet_turn_peer_id_t u_peer_id, tsk_bool_t *pb_connected) { - if (!pc_self || !pb_connected) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - tsk_safeobj_lock(pc_self); - *pb_connected = pc_self->b_started - && (pc_self->e_alloc_state == tnet_stun_state_ok); - if (*pb_connected) { - const tnet_turn_peer_t* pc_peer; - if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { - *pb_connected = (pc_peer->conn_fd != TNET_INVALID_FD && pc_peer->b_stream_connected && pc_peer->e_connbind_state == tnet_stun_state_ok); - } - else { - *pb_connected = tsk_false; - } - } - tsk_safeobj_unlock(pc_self); - return 0; + if (!pc_self || !pb_connected) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + tsk_safeobj_lock(pc_self); + *pb_connected = pc_self->b_started + && (pc_self->e_alloc_state == tnet_stun_state_ok); + if (*pb_connected) { + const tnet_turn_peer_t* pc_peer; + if ((pc_peer = (const tnet_turn_peer_t *)tsk_list_find_object_by_pred(pc_self->p_list_peers, __pred_find_peer_by_id, &u_peer_id))) { + *pb_connected = (pc_peer->conn_fd != TNET_INVALID_FD && pc_peer->b_stream_connected && pc_peer->e_connbind_state == tnet_stun_state_ok); + } + else { + *pb_connected = tsk_false; + } + } + tsk_safeobj_unlock(pc_self); + return 0; } int tnet_turn_session_stop(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - // FIXME - // tsk_safeobj_lock(p_self); + // FIXME + // tsk_safeobj_lock(p_self); - p_self->b_stopping = tsk_true; + p_self->b_stopping = tsk_true; - if (p_self->e_alloc_state == tnet_stun_state_ok) { - // UnAlloc - p_self->u_lifetime_alloc_in_sec = 0; - _tnet_turn_session_send_refresh(p_self); - } + if (p_self->e_alloc_state == tnet_stun_state_ok) { + // UnAlloc + p_self->u_lifetime_alloc_in_sec = 0; + _tnet_turn_session_send_refresh(p_self); + } - if (p_self->timer.p_mgr) { - ret = tsk_timer_manager_stop(p_self->timer.p_mgr); - } + if (p_self->timer.p_mgr) { + ret = tsk_timer_manager_stop(p_self->timer.p_mgr); + } - // free transport to force next call to prepare() to create new one with new sockets + // free transport to force next call to prepare() to create new one with new sockets if (p_self->p_transport) { tnet_transport_shutdown(p_self->p_transport); TSK_OBJECT_SAFE_FREE(p_self->p_transport); } - // clear peers - tsk_list_clear_items(p_self->p_list_peers); + // clear peers + tsk_list_clear_items(p_self->p_list_peers); - p_self->b_prepared = tsk_false; - p_self->b_started = tsk_false; - p_self->b_stopping = tsk_false; + p_self->b_prepared = tsk_false; + p_self->b_started = tsk_false; + p_self->b_stopping = tsk_false; - // tsk_safeobj_unlock(p_self); + // tsk_safeobj_unlock(p_self); - return ret; + return ret; } static int _tnet_turn_session_peer_find_by_id(const tnet_turn_session_t* pc_self, tnet_turn_peer_id_t id, const struct tnet_turn_peer_s **ppc_peer) { - const tsk_list_item_t *pc_item; - const struct tnet_turn_peer_s *pc_peer; - if (!pc_self || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_self->p_list_peers) { - if (!(pc_peer = pc_item->data)) { - continue; - } - if (pc_peer->id == id) { - *ppc_peer = pc_peer; - break; - } - } - return 0; + const tsk_list_item_t *pc_item; + const struct tnet_turn_peer_s *pc_peer; + if (!pc_self || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_self->p_list_peers) { + if (!(pc_peer = pc_item->data)) { + continue; + } + if (pc_peer->id == id) { + *ppc_peer = pc_peer; + break; + } + } + return 0; } static int _tnet_turn_session_peer_find_by_timer(const tnet_turn_session_t* pc_self, tsk_timer_id_t id, const struct tnet_turn_peer_s **ppc_peer) { - const tsk_list_item_t *pc_item; - const struct tnet_turn_peer_s *pc_peer; - if (!pc_self || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_self->p_list_peers) { - if (!(pc_peer = pc_item->data)) { - continue; - } - if (pc_peer->timer.rtt.chanbind.id == id || pc_peer->timer.rtt.createperm.id == id) { - *ppc_peer = pc_peer; - break; - } - } - return 0; + const tsk_list_item_t *pc_item; + const struct tnet_turn_peer_s *pc_peer; + if (!pc_self || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_self->p_list_peers) { + if (!(pc_peer = pc_item->data)) { + continue; + } + if (pc_peer->timer.rtt.chanbind.id == id || pc_peer->timer.rtt.createperm.id == id) { + *ppc_peer = pc_peer; + break; + } + } + return 0; } static uint16_t _tnet_turn_session_get_unique_chan_num() { - // rfc5766 - The channel number is in the range 0x4000 through 0x7FFE (inclusive) - static long __l_chan_num = 0; - tsk_atomic_inc(&__l_chan_num); - return (__l_chan_num % (0x7FFE - 0x4000)) + 0x4000; + // rfc5766 - The channel number is in the range 0x4000 through 0x7FFE (inclusive) + static long __l_chan_num = 0; + tsk_atomic_inc(&__l_chan_num); + return (__l_chan_num % (0x7FFE - 0x4000)) + 0x4000; } static int _tnet_turn_session_send_chandata(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - int ret = 0; - tsk_size_t PadSize, NeededSize; - uint8_t* _p_buff_chandata_ptr; + int ret = 0; + tsk_size_t PadSize, NeededSize; + uint8_t* _p_buff_chandata_ptr; if (!p_self || !pc_peer || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1257,45 +1267,45 @@ static int _tnet_turn_session_send_chandata(tnet_turn_session_t* p_self, const t ret = -2; goto bail; } - if (pc_peer->e_chanbind_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN data channel for peer id = %ld", pc_peer->id); + if (pc_peer->e_chanbind_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN data channel for peer id = %ld", pc_peer->id); ret = -3; goto bail; } - // rfc5766 - 11.5. Sending a ChannelData Message - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - // Over UDP, the padding is not required but MAY be included. - PadSize = 0; - } - else { - // Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to - // a multiple of four bytes in order to ensure the alignment of subsequent messages. - PadSize = (u_buff_size & 0x03) ? (4 - (u_buff_size & 0x03)) : 0; - } - NeededSize = kStunChannelDataHdrSizeInOctets + u_buff_size + PadSize; - - if (p_self->u_buff_chandata_size < NeededSize) { - if (!(p_self->p_buff_chandata_ptr = tsk_realloc(p_self->p_buff_chandata_ptr, NeededSize))) { - p_self->u_buff_chandata_size = 0; - ret = -4; - goto bail; - } - p_self->u_buff_chandata_size = NeededSize; - } - _p_buff_chandata_ptr = (uint8_t*)p_self->p_buff_chandata_ptr; + // rfc5766 - 11.5. Sending a ChannelData Message + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + // Over UDP, the padding is not required but MAY be included. + PadSize = 0; + } + else { + // Over TCP and TLS-over-TCP, the ChannelData message MUST be padded to + // a multiple of four bytes in order to ensure the alignment of subsequent messages. + PadSize = (u_buff_size & 0x03) ? (4 - (u_buff_size & 0x03)) : 0; + } + NeededSize = kStunChannelDataHdrSizeInOctets + u_buff_size + PadSize; - *((uint16_t*)&_p_buff_chandata_ptr[0]) = tnet_htons(pc_peer->u_chan_num); // Channel Number - *((uint16_t*)&_p_buff_chandata_ptr[2]) = tnet_htons((uint16_t)u_buff_size); // Length - memcpy(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets], pc_buff_ptr, u_buff_size); // Application Data - if (PadSize) { - memset(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets + u_buff_size], 0, PadSize); // Set padding bytes to zero (not required but ease debugging) - } + if (p_self->u_buff_chandata_size < NeededSize) { + if (!(p_self->p_buff_chandata_ptr = tsk_realloc(p_self->p_buff_chandata_ptr, NeededSize))) { + p_self->u_buff_chandata_size = 0; + ret = -4; + goto bail; + } + p_self->u_buff_chandata_size = NeededSize; + } + _p_buff_chandata_ptr = (uint8_t*)p_self->p_buff_chandata_ptr; + + *((uint16_t*)&_p_buff_chandata_ptr[0]) = tnet_htons(pc_peer->u_chan_num); // Channel Number + *((uint16_t*)&_p_buff_chandata_ptr[2]) = tnet_htons((uint16_t)u_buff_size); // Length + memcpy(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets], pc_buff_ptr, u_buff_size); // Application Data + if (PadSize) { + memset(&_p_buff_chandata_ptr[kStunChannelDataHdrSizeInOctets + u_buff_size], 0, PadSize); // Set padding bytes to zero (not required but ease debugging) + } + + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_chandata_ptr, NeededSize))) { + goto bail; + } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_chandata_ptr, NeededSize))) { - goto bail; - } - bail: // unlock() tsk_safeobj_unlock(p_self); @@ -1304,7 +1314,7 @@ bail: static int _tnet_turn_session_send_stream_raw(tnet_turn_session_t* p_self, tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - int ret = 0; + int ret = 0; if (!p_self || !pc_peer || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1318,20 +1328,20 @@ static int _tnet_turn_session_send_stream_raw(tnet_turn_session_t* p_self, tnet_ ret = -2; goto bail; } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - TSK_DEBUG_ERROR("Must not call this function for non-stream transports"); + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + TSK_DEBUG_ERROR("Must not call this function for non-stream transports"); ret = -3; goto bail; - } - if (pc_peer->e_connbind_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN TCP connection for peer id = %ld", pc_peer->id); + } + if (pc_peer->e_connbind_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN TCP connection for peer id = %ld", pc_peer->id); ret = -4; goto bail; } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, pc_buff_ptr, u_buff_size))) { - goto bail; - } + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, pc_buff_ptr, u_buff_size))) { + goto bail; + } bail: // unlock() @@ -1341,202 +1351,202 @@ bail: static int _tnet_turn_session_send_refresh(tnet_turn_session_t* p_self) { - int ret = 0; + int ret = 0; - if (!p_self) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - p_self->e_refresh_state = tnet_stun_state_none; - // create RefreshIndication Request - p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_refresh_request, &p_self->p_pkt_refresh))) { - TSK_DEBUG_ERROR("Failed to create TURN RefreshIndication request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(p_self->p_pkt_refresh, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + p_self->e_refresh_state = tnet_stun_state_none; + // create RefreshIndication Request + p_self->timer.rtt.refresh.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_self->p_pkt_refresh); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_refresh_request, &p_self->p_pkt_refresh))) { + TSK_DEBUG_ERROR("Failed to create TURN RefreshIndication request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(p_self->p_pkt_refresh, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); #if 0 - if (p_self->u_lifetime_alloc_in_sec == 0) { - const tnet_stun_attr_vdata_t *pc_attr_nonce = tsk_null; - tnet_stun_pkt_attr_find_first(p_self->p_pkt_refresh, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce); - if (pc_attr_nonce) { - pc_attr_nonce->p_data_ptr[0] = 'a'; - } - } + if (p_self->u_lifetime_alloc_in_sec == 0) { + const tnet_stun_attr_vdata_t *pc_attr_nonce = tsk_null; + tnet_stun_pkt_attr_find_first(p_self->p_pkt_refresh, tnet_stun_attr_type_nonce, (const tnet_stun_attr_t**)&pc_attr_nonce); + if (pc_attr_nonce) { + pc_attr_nonce->p_data_ptr[0] = 'a'; + } + } #endif - // add attributes - ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_refresh, - TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - p_self->p_pkt_refresh->opt.dontfrag = 0; - p_self->p_pkt_refresh->opt.fingerprint = 0; - if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_refresh))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_self->timer.rtt.refresh.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.refresh.id, p_self->timer.rtt.refresh.u_timeout); - } - p_self->e_refresh_state = tnet_stun_state_trying; + // add attributes + ret = tnet_stun_pkt_attrs_add(p_self->p_pkt_refresh, + TNET_STUN_PKT_ATTR_ADD_LIFETIME(p_self->u_lifetime_alloc_in_sec), + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(kStunSoftware), // recommended for Alloc and Refresh + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + p_self->p_pkt_refresh->opt.dontfrag = 0; + p_self->p_pkt_refresh->opt.fingerprint = 0; + if ((ret = _tnet_turn_session_send_pkt(p_self, p_self->p_pkt_refresh))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_self->timer.rtt.refresh.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_self->timer.rtt.refresh.id, p_self->timer.rtt.refresh.u_timeout); + } + p_self->e_refresh_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_permission(struct tnet_turn_session_s* p_self, tnet_turn_peer_t *p_peer) { - int ret = 0; - if (!p_self || !p_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - tsk_safeobj_lock(p_self); + int ret = 0; + if (!p_self || !p_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + tsk_safeobj_lock(p_self); - // create CreatePermission Request - p_peer->e_createperm_state = tnet_stun_state_none; - p_peer->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_createpermission_request, &p_peer->p_pkt_createperm))) { - TSK_DEBUG_ERROR("Failed to create TURN CreatePermission request"); - goto bail; - } - // add authinfo - tnet_stun_pkt_auth_copy(p_peer->p_pkt_createperm, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - p_peer->p_pkt_createperm->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_createperm, - /* Must not add LIFETIME and there is no way to delete permission */ - TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - if ((ret = _tnet_turn_session_send_pkt(p_self, p_peer->p_pkt_createperm))) { - goto bail; - } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { - p_peer->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_peer->timer.rtt.createperm.id, p_peer->timer.rtt.createperm.u_timeout); - } - p_peer->e_createperm_state = tnet_stun_state_trying; + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } + + // create CreatePermission Request + p_peer->e_createperm_state = tnet_stun_state_none; + p_peer->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_createpermission_request, &p_peer->p_pkt_createperm))) { + TSK_DEBUG_ERROR("Failed to create TURN CreatePermission request"); + goto bail; + } + // add authinfo + tnet_stun_pkt_auth_copy(p_peer->p_pkt_createperm, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + p_peer->p_pkt_createperm->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_createperm, + /* Must not add LIFETIME and there is no way to delete permission */ + TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + if ((ret = _tnet_turn_session_send_pkt(p_self, p_peer->p_pkt_createperm))) { + goto bail; + } + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + p_peer->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, p_peer->timer.rtt.createperm.id, p_peer->timer.rtt.createperm.u_timeout); + } + p_peer->e_createperm_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } // TCP-Connect rfc6062 - 4.3. Initiating a Connection static int _tnet_turn_session_send_connbind(struct tnet_turn_session_s* p_self, tnet_turn_peer_t *p_peer) { - int ret = 0; + int ret = 0; - if (!p_self || !p_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!p_self || !p_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if (!p_self->b_started) { - TSK_DEBUG_ERROR("TURN session not started yet"); - ret = -3; - goto bail; - } - if (p_self->e_alloc_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN allocation yet"); - ret = -4; - goto bail; - } + if (!p_self->b_started) { + TSK_DEBUG_ERROR("TURN session not started yet"); + ret = -3; + goto bail; + } + if (p_self->e_alloc_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN allocation yet"); + ret = -4; + goto bail; + } - // ConnectionBind must be sent after Connect - if (p_peer->e_connect_state != tnet_stun_state_ok) { - TSK_DEBUG_ERROR("No active TURN connection yet"); - ret = -6; - goto bail; - } - - // Connect must be used for streams (e.g. TCP, TLS....) only - if (p_self->e_req_transport != tnet_turn_transport_tcp) { - TSK_DEBUG_ERROR("TURN ConnectionBind not supported for UDP transport"); - ret = -7; - goto bail; - } + // ConnectionBind must be sent after Connect + if (p_peer->e_connect_state != tnet_stun_state_ok) { + TSK_DEBUG_ERROR("No active TURN connection yet"); + ret = -6; + goto bail; + } - // create Connect Request if doesn't exist (Connect refresh *must* have same id) - p_peer->e_connbind_state = tnet_stun_state_none; - if (!p_peer->p_pkt_connbind) { - if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connectionbind_request, &p_peer->p_pkt_connbind))) { - TSK_DEBUG_ERROR("Failed to create TURN ConnectionBind request"); - goto bail; - } - // add authentication info - tnet_stun_pkt_auth_copy(p_peer->p_pkt_connbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); - // add attributes - p_peer->p_pkt_connbind->opt.dontfrag = 0; - ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_connbind, - // Error "420" when XOR-PEER-ADDRESS attribute is added to ConnectionBind request - /* TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), */ - TNET_STUN_PKT_ATTR_ADD_CONNECTION_ID(p_peer->u_conn_id), - TNET_STUN_PKT_ATTR_ADD_NULL()); - if (ret) { - goto bail; - } - - } - else { - if ((ret = tnet_stun_utils_transac_id_rand(&p_peer->p_pkt_connbind->transac_id))) { - goto bail; - } - } - - if ((ret = _tnet_turn_session_send_pkt_0(p_self, p_peer, p_peer->p_pkt_connbind))) { - goto bail; - } - p_peer->e_connbind_state = tnet_stun_state_trying; + // Connect must be used for streams (e.g. TCP, TLS....) only + if (p_self->e_req_transport != tnet_turn_transport_tcp) { + TSK_DEBUG_ERROR("TURN ConnectionBind not supported for UDP transport"); + ret = -7; + goto bail; + } + + // create Connect Request if doesn't exist (Connect refresh *must* have same id) + p_peer->e_connbind_state = tnet_stun_state_none; + if (!p_peer->p_pkt_connbind) { + if ((ret = tnet_stun_pkt_create_empty(tnet_stun_pkt_type_connectionbind_request, &p_peer->p_pkt_connbind))) { + TSK_DEBUG_ERROR("Failed to create TURN ConnectionBind request"); + goto bail; + } + // add authentication info + tnet_stun_pkt_auth_copy(p_peer->p_pkt_connbind, p_self->cred.p_usr_name, p_self->cred.p_pwd, p_self->p_pkt_alloc); + // add attributes + p_peer->p_pkt_connbind->opt.dontfrag = 0; + ret = tnet_stun_pkt_attrs_add(p_peer->p_pkt_connbind, + // Error "420" when XOR-PEER-ADDRESS attribute is added to ConnectionBind request + /* TNET_STUN_PKT_ATTR_ADD_XOR_PEER_ADDRESS(p_peer->b_ipv6 ? tnet_stun_address_family_ipv6 : tnet_stun_address_family_ipv4, p_peer->u_addr_port, &p_peer->addr_ip), */ + TNET_STUN_PKT_ATTR_ADD_CONNECTION_ID(p_peer->u_conn_id), + TNET_STUN_PKT_ATTR_ADD_NULL()); + if (ret) { + goto bail; + } + + } + else { + if ((ret = tnet_stun_utils_transac_id_rand(&p_peer->p_pkt_connbind->transac_id))) { + goto bail; + } + } + + if ((ret = _tnet_turn_session_send_pkt_0(p_self, p_peer, p_peer->p_pkt_connbind))) { + goto bail; + } + p_peer->e_connbind_state = tnet_stun_state_trying; bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const void* pc_buff_ptr, tsk_size_t u_buff_size) { int ret = 0; - tsk_size_t u_sent_bytes = 0; + tsk_size_t u_sent_bytes = 0; if (!p_self || !pc_buff_ptr || !u_buff_size) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; @@ -1551,28 +1561,28 @@ static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tne goto bail; } - if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { + if (TNET_SOCKET_TYPE_IS_DGRAM(p_self->p_lcl_sock->type)) { #if 1 - u_sent_bytes = tnet_transport_sendto(p_self->p_transport, p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_sendto(p_self->p_transport, p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr *)&p_self->srv_addr, pc_buff_ptr, u_buff_size); #endif } else { - if (pc_peer && pc_peer->b_stream_connected && pc_peer->conn_fd != TNET_INVALID_FD) { - // Send using Peer connection if connected - // Should never be called because for now requested transport is always equal to UDP + if (pc_peer && pc_peer->b_stream_connected && pc_peer->conn_fd != TNET_INVALID_FD) { + // Send using Peer connection if connected + // Should never be called because for now requested transport is always equal to UDP #if 1 - u_sent_bytes = tnet_transport_send(p_self->p_transport, pc_peer->conn_fd, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_send(p_self->p_transport, pc_peer->conn_fd, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_sockfd_send(pc_peer->conn_fd, pc_buff_ptr, u_buff_size, 0); + u_sent_bytes = tnet_sockfd_send(pc_peer->conn_fd, pc_buff_ptr, u_buff_size, 0); #endif - } - else { + } + else { tsk_bool_t b_delay_send = tsk_false; - // Connect if not already done - if (!p_self->b_stream_connected) { - ret = tnet_sockfd_waitUntilWritable(p_self->p_lcl_sock->fd, kTurnTransportConnectTimeout); + // Connect if not already done + if (!p_self->b_stream_connected) { + ret = tnet_sockfd_waitUntilWritable(p_self->p_lcl_sock->fd, kTurnTransportConnectTimeout); if (ret == 0) { // socket is valid but not connected (e.g. Proxy handshaking not completed yet) TSK_DEBUG_INFO("Saving %u TURN bytes and waiting for 'connected' event before sending", (unsigned)u_buff_size); if (!p_self->p_stream_buff_out && !(p_self->p_stream_buff_out = tsk_buffer_create_null())) { @@ -1594,17 +1604,17 @@ static int _tnet_turn_session_send_buff_0(tnet_turn_session_t* p_self, const tne ret = -6; goto bail; } - } - if (!b_delay_send && p_self->b_stream_connected) { + } + if (!b_delay_send && p_self->b_stream_connected) { #if 1 - u_sent_bytes = tnet_transport_send(p_self->p_transport, p_self->p_lcl_sock->fd, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_transport_send(p_self->p_transport, p_self->p_lcl_sock->fd, pc_buff_ptr, u_buff_size); #else - u_sent_bytes = tnet_socket_send_stream(p_self->p_lcl_sock, pc_buff_ptr, u_buff_size); + u_sent_bytes = tnet_socket_send_stream(p_self->p_lcl_sock, pc_buff_ptr, u_buff_size); #endif - } - } + } + } } - if (u_sent_bytes != u_buff_size) { + if (u_sent_bytes != u_buff_size) { TSK_DEBUG_ERROR("Failed to send %u bytes. Only %u sent", (unsigned)u_buff_size, (unsigned)u_sent_bytes); ret = -2; goto bail; @@ -1618,21 +1628,21 @@ bail: static int _tnet_turn_session_send_buff(tnet_turn_session_t* p_self, const void* pc_buff_ptr, tsk_size_t u_buff_size) { - return _tnet_turn_session_send_buff_0(p_self, tsk_null/*peer*/, pc_buff_ptr, u_buff_size); + return _tnet_turn_session_send_buff_0(p_self, tsk_null/*peer*/, pc_buff_ptr, u_buff_size); } static int _tnet_turn_session_send_pkt_0(tnet_turn_session_t* p_self, const tnet_turn_peer_t* pc_peer, const tnet_turn_pkt_t *pc_pkt) { - int ret; - tsk_size_t u_min_size; - if (!p_self || !pc_pkt) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + int ret; + tsk_size_t u_min_size; + if (!p_self || !pc_pkt) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tsk_safeobj_lock(p_self); + tsk_safeobj_lock(p_self); - if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_pkt, &u_min_size))) { + if ((ret = tnet_stun_pkt_get_size_in_octetunits_with_padding(pc_pkt, &u_min_size))) { goto bail; } u_min_size += kStunBuffMinPad; @@ -1649,32 +1659,32 @@ static int _tnet_turn_session_send_pkt_0(tnet_turn_session_t* p_self, const tnet if ((ret = tnet_stun_pkt_write_with_padding(pc_pkt, p_self->p_buff_send_ptr, p_self->u_buff_send_size, &u_min_size))) { goto bail; } - if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_send_ptr, u_min_size))) { - goto bail; - } + if ((ret = _tnet_turn_session_send_buff_0(p_self, pc_peer, p_self->p_buff_send_ptr, u_min_size))) { + goto bail; + } bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_send_pkt(tnet_turn_session_t* p_self, const tnet_turn_pkt_t *pc_pkt) { - return _tnet_turn_session_send_pkt_0(p_self, tsk_null/*peer*/, pc_pkt); + return _tnet_turn_session_send_pkt_0(p_self, tsk_null/*peer*/, pc_pkt); } // 420 = Unknown Attribute int _tnet_turn_session_process_err420_pkt(tnet_turn_pkt_t *p_pkt_req, const tnet_turn_pkt_t *pc_pkt_resp420) { - const tnet_stun_attr_vdata_t* pc_attr; - uint16_t u16; - int ret; - tsk_bool_t b_done = tsk_false; - if (!p_pkt_req || !pc_pkt_resp420) { - TSK_DEBUG_ERROR("Invalid parameter"); + const tnet_stun_attr_vdata_t* pc_attr; + uint16_t u16; + int ret; + tsk_bool_t b_done = tsk_false; + if (!p_pkt_req || !pc_pkt_resp420) { + TSK_DEBUG_ERROR("Invalid parameter"); return -1; - } - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { + } + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt_resp420, tnet_stun_attr_type_unknown_attrs, (const tnet_stun_attr_t**)&pc_attr))) { goto bail; } if (!pc_attr || !pc_attr->p_data_ptr || (pc_attr->u_data_size & 1)) { @@ -1682,288 +1692,284 @@ int _tnet_turn_session_process_err420_pkt(tnet_turn_pkt_t *p_pkt_req, const tnet ret = -3; goto bail; } - for (u16 = 0; u16 < pc_attr->u_data_size; u16+=2) { - switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { - case tnet_stun_attr_type_dont_fragment: - { - p_pkt_req->opt.dontfrag = 0; - b_done = tsk_true; - break; - } - case tnet_stun_attr_type_fingerprint: - { - p_pkt_req->opt.fingerprint = 0; - b_done = tsk_true; - break; - } - } - } + for (u16 = 0; u16 < pc_attr->u_data_size; u16+=2) { + switch (*((uint16_t*)&pc_attr->p_data_ptr[u16])) { + case tnet_stun_attr_type_dont_fragment: { + p_pkt_req->opt.dontfrag = 0; + b_done = tsk_true; + break; + } + case tnet_stun_attr_type_fingerprint: { + p_pkt_req->opt.fingerprint = 0; + b_done = tsk_true; + break; + } + } + } - if (b_done) { - // TRANSACTION-ID - if ((ret = tnet_stun_utils_transac_id_rand(&p_pkt_req->transac_id))) { - goto bail; - } - } + if (b_done) { + // TRANSACTION-ID + if ((ret = tnet_stun_utils_transac_id_rand(&p_pkt_req->transac_id))) { + goto bail; + } + } bail: - return ret; + return ret; } static int _tnet_turn_session_process_incoming_pkt(struct tnet_turn_session_s* p_self, const tnet_turn_pkt_t *pc_pkt, tsk_bool_t *pb_processed) { - int ret = 0; + int ret = 0; if (!p_self || !pc_pkt || !pb_processed) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - *pb_processed = tsk_false; + *pb_processed = tsk_false; // lock() tsk_safeobj_lock(p_self); - switch (pc_pkt->e_type) { - case tnet_stun_pkt_type_allocate_success_response: - case tnet_stun_pkt_type_allocate_error_response: - case tnet_stun_pkt_type_createpermission_success_response: - case tnet_stun_pkt_type_createpermission_error_response: - case tnet_stun_pkt_type_channelbind_success_response: - case tnet_stun_pkt_type_channelbind_error_response: - case tnet_stun_pkt_type_refresh_success_response: - case tnet_stun_pkt_type_refresh_error_response: - case tnet_stun_pkt_type_connect_success_response: - case tnet_stun_pkt_type_connect_error_response: - case tnet_stun_pkt_type_connectionbind_success_response: - case tnet_stun_pkt_type_connectionbind_error_response: - { - const tnet_stun_attr_error_code_t* pc_attr_err = tsk_null; - uint16_t u_code = 0; - tnet_turn_pkt_t *pc_pkt_req = tsk_null; - tnet_turn_peer_t* pc_peer = tsk_null; - + switch (pc_pkt->e_type) { + case tnet_stun_pkt_type_allocate_success_response: + case tnet_stun_pkt_type_allocate_error_response: + case tnet_stun_pkt_type_createpermission_success_response: + case tnet_stun_pkt_type_createpermission_error_response: + case tnet_stun_pkt_type_channelbind_success_response: + case tnet_stun_pkt_type_channelbind_error_response: + case tnet_stun_pkt_type_refresh_success_response: + case tnet_stun_pkt_type_refresh_error_response: + case tnet_stun_pkt_type_connect_success_response: + case tnet_stun_pkt_type_connect_error_response: + case tnet_stun_pkt_type_connectionbind_success_response: + case tnet_stun_pkt_type_connectionbind_error_response: { + const tnet_stun_attr_error_code_t* pc_attr_err = tsk_null; + uint16_t u_code = 0; + tnet_turn_pkt_t *pc_pkt_req = tsk_null; + tnet_turn_peer_t* pc_peer = tsk_null; + #define CANCEL_TIMER(parent, which) \ if (TSK_TIMER_ID_IS_VALID(parent->timer.rtt.which.id)) { \ tsk_timer_manager_cancel(p_self->timer.p_mgr, parent->timer.rtt.which.id); \ parent->timer.rtt.which.id = TSK_INVALID_TIMER_ID; \ } - // Find request - if (p_self->p_pkt_alloc && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_alloc->transac_id, pc_pkt->transac_id) == 0) { - pc_pkt_req = p_self->p_pkt_alloc; - CANCEL_TIMER(p_self, alloc); - CANCEL_TIMER(p_self, refresh); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_createperm, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_createperm; - CANCEL_TIMER(pc_peer, createperm); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_sendind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_sendind; - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_chanbind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_chanbind; - CANCEL_TIMER(pc_peer, chanbind); - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connect, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_connect; - // TCP: no timer - } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connectionbind, &pc_pkt->transac_id))) { - pc_pkt_req = pc_peer->p_pkt_connbind; - // TCP: no timer - } - else if (p_self->p_pkt_refresh && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_refresh->transac_id, pc_pkt->transac_id) == 0) { - pc_pkt_req = p_self->p_pkt_refresh; - CANCEL_TIMER(p_self, refresh); - } - - if (!pc_pkt_req) { - TSK_DEBUG_INFO("No matching request[TID=%s]", pc_pkt->transac_id); - // Not an error as the "fd" could be shared by several processes (e.g. ICE) - goto bail; - } - - /*** SUCCESS ***/ - if (TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { - // --- ALLOC --- // - if (pc_pkt_req == p_self->p_pkt_alloc) { - const tnet_stun_attr_address_t *pc_attr_addr; - tnet_ip_t ip_addr; - const tnet_stun_attr_vdata_t *pc_attr_lifetime; - // XOR-MAPPED-ADDRESS (optional) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr) { - if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr)) == 0) { - p_self->b_srflx_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); - p_self->u_srflx_port = pc_attr_addr->u_port; - tsk_strupdate(&p_self->p_srflx_ip, ip_addr); - } - } - // LIFETIME (optional) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { - p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); - } - // XOR-RELAYED-ADDRESS (required) - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_relayed_address, (const tnet_stun_attr_t**)&pc_attr_addr))) { - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - if (!pc_attr_addr) { - TSK_DEBUG_ERROR("XOR-RELAYED-ADDRESS missing in success response for Allocate"); - ret = -4; - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr))) { - _tnet_turn_session_raise_event_alloc_nok(p_self); - goto bail; - } - - // Uncomment to test [TURN Client] <-> [Turn Server] <-> [Any Client] + // Find request + if (p_self->p_pkt_alloc && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_alloc->transac_id, pc_pkt->transac_id) == 0) { + pc_pkt_req = p_self->p_pkt_alloc; + CANCEL_TIMER(p_self, alloc); + CANCEL_TIMER(p_self, refresh); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_createperm, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_createperm; + CANCEL_TIMER(pc_peer, createperm); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_sendind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_sendind; + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_chanbind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_chanbind; + CANCEL_TIMER(pc_peer, chanbind); + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connect, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_connect; + // TCP: no timer + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_self->p_list_peers, __pred_find_peer_by_transacid_connectionbind, &pc_pkt->transac_id))) { + pc_pkt_req = pc_peer->p_pkt_connbind; + // TCP: no timer + } + else if (p_self->p_pkt_refresh && tnet_stun_utils_transac_id_cmp(p_self->p_pkt_refresh->transac_id, pc_pkt->transac_id) == 0) { + pc_pkt_req = p_self->p_pkt_refresh; + CANCEL_TIMER(p_self, refresh); + } + + if (!pc_pkt_req) { + TSK_DEBUG_INFO("No matching request[TID=%s]", pc_pkt->transac_id); + // Not an error as the "fd" could be shared by several processes (e.g. ICE) + goto bail; + } + + /*** SUCCESS ***/ + if (TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { + // --- ALLOC --- // + if (pc_pkt_req == p_self->p_pkt_alloc) { + const tnet_stun_attr_address_t *pc_attr_addr; + tnet_ip_t ip_addr; + const tnet_stun_attr_vdata_t *pc_attr_lifetime; + // XOR-MAPPED-ADDRESS (optional) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_mapped_address, (const tnet_stun_attr_t**)&pc_attr_addr)) == 0 && pc_attr_addr) { + if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr)) == 0) { + p_self->b_srflx_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); + p_self->u_srflx_port = pc_attr_addr->u_port; + tsk_strupdate(&p_self->p_srflx_ip, ip_addr); + } + } + // LIFETIME (optional) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { + p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); + } + // XOR-RELAYED-ADDRESS (required) + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_relayed_address, (const tnet_stun_attr_t**)&pc_attr_addr))) { + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + if (!pc_attr_addr) { + TSK_DEBUG_ERROR("XOR-RELAYED-ADDRESS missing in success response for Allocate"); + ret = -4; + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + if ((ret = tnet_stun_utils_inet_ntop((pc_attr_addr->e_family == tnet_stun_address_family_ipv6), &pc_attr_addr->address, &ip_addr))) { + _tnet_turn_session_raise_event_alloc_nok(p_self); + goto bail; + } + + // Uncomment to test [TURN Client] <-> [Turn Server] <-> [Any Client] #if 0 - { - struct sockaddr_storage to; - tnet_sockaddr_init(ip_addr, pc_attr_addr->u_port, p_self->p_lcl_sock->type, &to); - tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data - tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data - } + { + struct sockaddr_storage to; + tnet_sockaddr_init(ip_addr, pc_attr_addr->u_port, p_self->p_lcl_sock->type, &to); + tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data + tnet_sockfd_sendto(p_self->p_lcl_sock->fd, (const struct sockaddr*)&to, "pinhole", 7); // open pinhole to allow incoming data + } #endif - // Schedule refresh - TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); - - p_self->e_alloc_state = tnet_stun_state_ok; - p_self->b_rel_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); - p_self->u_rel_port = pc_attr_addr->u_port; - tsk_strupdate(&p_self->p_rel_ip, ip_addr); - - _tnet_turn_session_raise_event_alloc_ok(p_self); - } - // --- CREATE-PERMISSION --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { - TSK_DEBUG_INFO("TURN 'CREATE-PERMISSION' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_createperm_state = tnet_stun_state_ok; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.createperm.id, pc_peer->timer.fresh.createperm.u_timeout); - _tnet_turn_session_raise_event_createperm_ok(p_self, pc_peer->id); - } - // --- CHANNEL-BIND --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { - TSK_DEBUG_INFO("TURN 'CHANNEL-BIND' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_chanbind_state = tnet_stun_state_ok; - TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.chanbind.id, pc_peer->timer.fresh.chanbind.u_timeout); - _tnet_turn_session_raise_event_chanbind_ok(p_self, pc_peer->id); - } - // --- CONNECT --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connect_request) { - TSK_DEBUG_INFO("TURN 'CONNECT' OK for peer-id = %ld", pc_peer->id); - if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { - goto bail; - } - } - // --- CONNECTION-BIND --- // - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connectionbind_request) { - TSK_DEBUG_INFO("TURN 'CONNECTION-BIND' OK for peer-id = %ld", pc_peer->id); - pc_peer->e_connbind_state = tnet_stun_state_ok; - _tnet_turn_session_raise_event_connectionbind_ok(p_self, pc_peer->id); - } - // --- REFRESH --- // - else if (pc_pkt_req == p_self->p_pkt_refresh) { - const tnet_stun_attr_vdata_t *pc_attr_lifetime; - TSK_DEBUG_INFO("TURN 'REFRESH' OK for peer-id = %ld", pc_peer ? pc_peer->id : -1); - p_self->e_refresh_state = tnet_stun_state_ok; - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { - p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); - } - TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); - _tnet_turn_session_raise_event_refresh_ok(p_self); - } - } - /*** ERROR ***/ - else { - tsk_bool_t b_nok = tsk_true; - if ((ret = tnet_stun_pkt_get_errorcode(pc_pkt, &u_code))) { - goto bail; - } - if (u_code > 299) { - tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr_err); - } - if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { - if (u_code == kStunErrCodeUnauthorized) { - // Make sure this is not an authentication failure (#2 401) - // Do not send another req to avoid endless messages - if ((tnet_stun_pkt_attr_exists(pc_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? - TSK_DEBUG_ERROR("TURN authentication failed"); - goto check_nok; - // INDICATION messages cannot receive 401 responses - } - } - if ((ret = tnet_stun_pkt_auth_prepare_2(pc_pkt_req, p_self->cred.p_usr_name, p_self->cred.p_pwd, pc_pkt))) { - goto check_nok; - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { - b_nok = tsk_false; goto check_nok; - } - } - else if (u_code == kStunErrCodeUnknownAttributes) { - if((ret = _tnet_turn_session_process_err420_pkt(pc_pkt_req, pc_pkt))) { - goto check_nok; - } - if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { - b_nok = tsk_false; goto check_nok; - } - } + // Schedule refresh + TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); + + p_self->e_alloc_state = tnet_stun_state_ok; + p_self->b_rel_ipv6 = (pc_attr_addr->e_family == tnet_stun_address_family_ipv6); + p_self->u_rel_port = pc_attr_addr->u_port; + tsk_strupdate(&p_self->p_rel_ip, ip_addr); + + _tnet_turn_session_raise_event_alloc_ok(p_self); + } + // --- CREATE-PERMISSION --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { + TSK_DEBUG_INFO("TURN 'CREATE-PERMISSION' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_createperm_state = tnet_stun_state_ok; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.createperm.id, pc_peer->timer.fresh.createperm.u_timeout); + _tnet_turn_session_raise_event_createperm_ok(p_self, pc_peer->id); + } + // --- CHANNEL-BIND --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { + TSK_DEBUG_INFO("TURN 'CHANNEL-BIND' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_chanbind_state = tnet_stun_state_ok; + TNET_TURN_SESSION_TIMER_SCHEDULE_MILLIS(p_self, pc_peer->timer.fresh.chanbind.id, pc_peer->timer.fresh.chanbind.u_timeout); + _tnet_turn_session_raise_event_chanbind_ok(p_self, pc_peer->id); + } + // --- CONNECT --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connect_request) { + TSK_DEBUG_INFO("TURN 'CONNECT' OK for peer-id = %ld", pc_peer->id); + if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { + goto bail; + } + } + // --- CONNECTION-BIND --- // + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_connectionbind_request) { + TSK_DEBUG_INFO("TURN 'CONNECTION-BIND' OK for peer-id = %ld", pc_peer->id); + pc_peer->e_connbind_state = tnet_stun_state_ok; + _tnet_turn_session_raise_event_connectionbind_ok(p_self, pc_peer->id); + } + // --- REFRESH --- // + else if (pc_pkt_req == p_self->p_pkt_refresh) { + const tnet_stun_attr_vdata_t *pc_attr_lifetime; + TSK_DEBUG_INFO("TURN 'REFRESH' OK for peer-id = %ld", pc_peer ? pc_peer->id : -1); + p_self->e_refresh_state = tnet_stun_state_ok; + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_lifetime, (const tnet_stun_attr_t**)&pc_attr_lifetime)) == 0 && pc_attr_lifetime && pc_attr_lifetime->u_data_size == 4) { + p_self->u_lifetime_alloc_in_sec = TSK_TO_UINT32(pc_attr_lifetime->p_data_ptr); + } + TNET_TURN_SESSION_TIMER_SCHEDULE_SEC(p_self, p_self->timer.u_timer_id_refresh, p_self->u_lifetime_alloc_in_sec); + _tnet_turn_session_raise_event_refresh_ok(p_self); + } + } + /*** ERROR ***/ + else { + tsk_bool_t b_nok = tsk_true; + if ((ret = tnet_stun_pkt_get_errorcode(pc_pkt, &u_code))) { + goto bail; + } + if (u_code > 299) { + tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_error_code, (const tnet_stun_attr_t**)&pc_attr_err); + } + if (u_code == kStunErrCodeUnauthorized || u_code == kStunErrCodeStaleNonce) { + if (u_code == kStunErrCodeUnauthorized) { + // Make sure this is not an authentication failure (#2 401) + // Do not send another req to avoid endless messages + if ((tnet_stun_pkt_attr_exists(pc_pkt_req, tnet_stun_attr_type_message_integrity))) { // already has a MESSAGE-INTEGRITY? + TSK_DEBUG_ERROR("TURN authentication failed"); + goto check_nok; + // INDICATION messages cannot receive 401 responses + } + } + if ((ret = tnet_stun_pkt_auth_prepare_2(pc_pkt_req, p_self->cred.p_usr_name, p_self->cred.p_pwd, pc_pkt))) { + goto check_nok; + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { + b_nok = tsk_false; + goto check_nok; + } + } + else if (u_code == kStunErrCodeUnknownAttributes) { + if((ret = _tnet_turn_session_process_err420_pkt(pc_pkt_req, pc_pkt))) { + goto check_nok; + } + if ((ret = _tnet_turn_session_send_pkt_0(p_self, pc_peer, pc_pkt_req)) == 0) { + b_nok = tsk_false; + goto check_nok; + } + } check_nok: - if (b_nok) { - TSK_DEBUG_INFO("--- TURN response code = %hu, phrase = %s, peer-id=%ld, ---", - u_code, pc_attr_err ? pc_attr_err->p_reason_phrase : "null", pc_peer ? pc_peer->id : -1); - if (pc_pkt_req == p_self->p_pkt_alloc) { - p_self->e_alloc_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_alloc_nok(p_self); - } - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { - pc_peer->e_chanbind_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_chanbind_nok(p_self, pc_peer->id); - } - else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { - pc_peer->e_createperm_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_createperm_nok(p_self, pc_peer->id); - } - else if (pc_pkt_req == p_self->p_pkt_refresh) { - p_self->e_refresh_state = tnet_stun_state_nok; - _tnet_turn_session_raise_event_refresh_nok(p_self); - } - } - } - - break; - } - case tnet_stun_pkt_type_connectionattempt_indication: - { - // Indicates we already have an active connection - const tnet_stun_attr_address_t *pc_attr_xor_peer_addr; - tnet_turn_peer_t* pc_peer = tsk_null; - // XOR-PEER-ADDRESS - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xor_peer_addr)) == 0 && pc_attr_xor_peer_addr) { - if ((ret = _tnet_turn_peer_find_by_xpeer(p_self->p_list_peers, pc_attr_xor_peer_addr, (const tnet_turn_peer_t**)&pc_peer)) == 0 && pc_peer) { - if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { - goto bail; - } - } - } - break; - } - case tnet_stun_pkt_type_data_indication: - { - TSK_DEBUG_ERROR("Unexpected code called"); // --> DATA-INDICATION must be handled in net-event - break; - } - default: - { - goto bail; - } - } + if (b_nok) { + TSK_DEBUG_INFO("--- TURN response code = %hu, phrase = %s, peer-id=%ld, ---", + u_code, pc_attr_err ? pc_attr_err->p_reason_phrase : "null", pc_peer ? pc_peer->id : -1); + if (pc_pkt_req == p_self->p_pkt_alloc) { + p_self->e_alloc_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_alloc_nok(p_self); + } + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_channelbind_request) { + pc_peer->e_chanbind_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_chanbind_nok(p_self, pc_peer->id); + } + else if (pc_pkt_req->e_type == tnet_stun_pkt_type_createpermission_request) { + pc_peer->e_createperm_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_createperm_nok(p_self, pc_peer->id); + } + else if (pc_pkt_req == p_self->p_pkt_refresh) { + p_self->e_refresh_state = tnet_stun_state_nok; + _tnet_turn_session_raise_event_refresh_nok(p_self); + } + } + } - *pb_processed = tsk_true; + break; + } + case tnet_stun_pkt_type_connectionattempt_indication: { + // Indicates we already have an active connection + const tnet_stun_attr_address_t *pc_attr_xor_peer_addr; + tnet_turn_peer_t* pc_peer = tsk_null; + // XOR-PEER-ADDRESS + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xor_peer_addr)) == 0 && pc_attr_xor_peer_addr) { + if ((ret = _tnet_turn_peer_find_by_xpeer(p_self->p_list_peers, pc_attr_xor_peer_addr, (const tnet_turn_peer_t**)&pc_peer)) == 0 && pc_peer) { + if ((ret = _tnet_turn_session_process_success_connect_pkt(p_self, pc_peer, pc_pkt))) { + goto bail; + } + } + } + break; + } + case tnet_stun_pkt_type_data_indication: { + TSK_DEBUG_ERROR("Unexpected code called"); // --> DATA-INDICATION must be handled in net-event + break; + } + default: { + goto bail; + } + } + + *pb_processed = tsk_true; bail: // unlock() @@ -1974,38 +1980,38 @@ bail: // "pc_pkt" could be "200 response" or "CONNECTATTEMP-INDICATION" int _tnet_turn_session_process_success_connect_pkt(struct tnet_turn_session_s* p_self, tnet_turn_peer_t* pc_peer, const tnet_turn_pkt_t *pc_pkt) { - int ret = 0; - const tnet_stun_attr_vdata_t *pc_attr_connection_id; + int ret = 0; + const tnet_stun_attr_vdata_t *pc_attr_connection_id; if (!p_self || !pc_peer || !pc_pkt) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - if (pc_pkt->e_type != tnet_stun_pkt_type_connectionattempt_indication && !TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { - TSK_DEBUG_ERROR("Invalid packet type"); - ret = -2; - goto bail; - } - + if (pc_pkt->e_type != tnet_stun_pkt_type_connectionattempt_indication && !TNET_STUN_PKT_RESP_IS_SUCCESS(pc_pkt)) { + TSK_DEBUG_ERROR("Invalid packet type"); + ret = -2; + goto bail; + } + // lock() tsk_safeobj_lock(p_self); - - if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_connection_id, (const tnet_stun_attr_t**)&pc_attr_connection_id)) == 0 && pc_attr_connection_id && pc_attr_connection_id->u_data_size == 4) { - pc_peer->u_conn_id = TSK_TO_UINT32(pc_attr_connection_id->p_data_ptr); - pc_peer->e_connect_state = tnet_stun_state_ok; - _tnet_turn_session_raise_event_connect_ok(p_self, pc_peer->id); - // Connect to the server and send "ConnectionBind" request using the "CONNECTION-ID" once connection is completed - pc_peer->conn_fd = tnet_transport_connectto(p_self->p_transport, p_self->p_srv_host, p_self->u_srv_port, p_self->p_transport->type); - if (pc_peer->conn_fd == TNET_INVALID_FD) { - TSK_DEBUG_ERROR("Failed to connect to %s:%d", p_self->p_srv_host, p_self->u_srv_port); - ret = -3; - goto bail; - } - } + + if ((ret = tnet_stun_pkt_attr_find_first(pc_pkt, tnet_stun_attr_type_connection_id, (const tnet_stun_attr_t**)&pc_attr_connection_id)) == 0 && pc_attr_connection_id && pc_attr_connection_id->u_data_size == 4) { + pc_peer->u_conn_id = TSK_TO_UINT32(pc_attr_connection_id->p_data_ptr); + pc_peer->e_connect_state = tnet_stun_state_ok; + _tnet_turn_session_raise_event_connect_ok(p_self, pc_peer->id); + // Connect to the server and send "ConnectionBind" request using the "CONNECTION-ID" once connection is completed + pc_peer->conn_fd = tnet_transport_connectto(p_self->p_transport, p_self->p_srv_host, p_self->u_srv_port, p_self->p_transport->type); + if (pc_peer->conn_fd == TNET_INVALID_FD) { + TSK_DEBUG_ERROR("Failed to connect to %s:%d", p_self->p_srv_host, p_self->u_srv_port); + ret = -3; + goto bail; + } + } bail: - tsk_safeobj_unlock(p_self); - return ret; + tsk_safeobj_unlock(p_self); + return ret; } static int _tnet_turn_session_transport_layer_dgram_cb(const tnet_transport_event_t* e) @@ -2015,252 +2021,252 @@ static int _tnet_turn_session_transport_layer_dgram_cb(const tnet_transport_even static int _tnet_turn_session_transport_layer_stream_cb(const tnet_transport_event_t* e) { - return _tnet_turn_session_transport_layer_process_cb(e); + return _tnet_turn_session_transport_layer_process_cb(e); } static int _tnet_turn_session_transport_layer_process_cb(const tnet_transport_event_t* e) { - tnet_turn_session_t* p_ss = (tnet_turn_session_t*)e->callback_data; - int ret = 0; - tnet_turn_pkt_t* p_pkt = tsk_null; - tsk_buffer_t* p_stream_buff_in = tsk_null; - const void* pc_data = tsk_null; - tsk_size_t u_data_size = 0; - tsk_bool_t b_stream = tsk_false, b_stream_appended = tsk_false, b_pkt_is_complete = tsk_false, b_got_msg= tsk_false; - tnet_turn_peer_t* pc_peer = tsk_null; - switch(e->type){ - case event_data: - break; - case event_brokenpipe: - tsk_safeobj_lock(p_ss); - if (p_ss->p_lcl_sock && e->local_fd == p_ss->p_lcl_sock->fd) { - tnet_fd_t broken_fd = e->local_fd; - tsk_bool_t registered_fd = !!tnet_transport_have_socket(p_ss->p_transport, broken_fd); + tnet_turn_session_t* p_ss = (tnet_turn_session_t*)e->callback_data; + int ret = 0; + tnet_turn_pkt_t* p_pkt = tsk_null; + tsk_buffer_t* p_stream_buff_in = tsk_null; + const void* pc_data = tsk_null; + tsk_size_t u_data_size = 0; + tsk_bool_t b_stream = tsk_false, b_stream_appended = tsk_false, b_pkt_is_complete = tsk_false, b_got_msg= tsk_false; + tnet_turn_peer_t* pc_peer = tsk_null; + switch(e->type) { + case event_data: + break; + case event_brokenpipe: + tsk_safeobj_lock(p_ss); + if (p_ss->p_lcl_sock && e->local_fd == p_ss->p_lcl_sock->fd) { + tnet_fd_t broken_fd = e->local_fd; + tsk_bool_t registered_fd = !!tnet_transport_have_socket(p_ss->p_transport, broken_fd); + if (registered_fd) { + tnet_transport_remove_socket(p_ss->p_transport, &broken_fd); + } + if (tnet_socket_handle_brokenpipe(p_ss->p_lcl_sock) == 0) { if (registered_fd) { - tnet_transport_remove_socket(p_ss->p_transport, &broken_fd); - } - if (tnet_socket_handle_brokenpipe(p_ss->p_lcl_sock) == 0) { - if (registered_fd) { - tnet_transport_add_socket(p_ss->p_transport, p_ss->p_lcl_sock->fd, p_ss->p_lcl_sock->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); - } + tnet_transport_add_socket(p_ss->p_transport, p_ss->p_lcl_sock->fd, p_ss->p_lcl_sock->type, tsk_false/* do not take ownership */, tsk_true/* only Meaningful for tls*/, tsk_null); } } + } + tsk_safeobj_unlock(p_ss); + return 0; + case event_connected: + if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { + tsk_safeobj_lock(p_ss); + p_ss->b_stream_connected = tsk_true; + if (p_ss->p_stream_buff_out && p_ss->p_stream_buff_out->size > 0) { + TSK_DEBUG_INFO("Sending %u TURN pending bytes", (unsigned)p_ss->p_stream_buff_out->size); + _tnet_turn_session_send_buff(p_ss, p_ss->p_stream_buff_out->data, (uint16_t)p_ss->p_stream_buff_out->size); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + } tsk_safeobj_unlock(p_ss); - return 0; - case event_connected: - if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { - tsk_safeobj_lock(p_ss); - p_ss->b_stream_connected = tsk_true; - if (p_ss->p_stream_buff_out && p_ss->p_stream_buff_out->size > 0) { - TSK_DEBUG_INFO("Sending %u TURN pending bytes", (unsigned)p_ss->p_stream_buff_out->size); - _tnet_turn_session_send_buff(p_ss, p_ss->p_stream_buff_out->data, (uint16_t)p_ss->p_stream_buff_out->size); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + } + else { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + pc_peer->b_stream_connected = tsk_true; + // Send ConnectionBind + if ((ret = _tnet_turn_session_send_connbind(p_ss, pc_peer))) { + goto bail; } - tsk_safeobj_unlock(p_ss); - } - else { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - pc_peer->b_stream_connected = tsk_true; - // Send ConnectionBind - if ((ret = _tnet_turn_session_send_connbind(p_ss, pc_peer))) { - goto bail; - } - } - tsk_safeobj_unlock(p_ss); - } - return 0; - case event_error: - case event_closed: - case event_removed: - /* case event_removed: */ - if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { - tsk_safeobj_lock(p_ss); - p_ss->b_stream_connected = tsk_false; - p_ss->b_stream_error = (e->type == event_error); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); - tsk_safeobj_unlock(p_ss); - } - else { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - pc_peer->b_stream_connected = tsk_false; - pc_peer->conn_fd = TNET_INVALID_FD; - } - tsk_safeobj_unlock(p_ss); - } - return 0; - default: - return 0; - } + } + tsk_safeobj_unlock(p_ss); + } + return 0; + case event_error: + case event_closed: + case event_removed: + /* case event_removed: */ + if (p_ss->p_lcl_sock && p_ss->p_lcl_sock->fd == e->local_fd) { + tsk_safeobj_lock(p_ss); + p_ss->b_stream_connected = tsk_false; + p_ss->b_stream_error = (e->type == event_error); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); + tsk_safeobj_unlock(p_ss); + } + else { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + pc_peer->b_stream_connected = tsk_false; + pc_peer->conn_fd = TNET_INVALID_FD; + } + tsk_safeobj_unlock(p_ss); + } + return 0; + default: + return 0; + } - /*** If the code reach this line it means we have to deal with a "NET-DATA-EVENT" ***/ + /*** If the code reach this line it means we have to deal with a "NET-DATA-EVENT" ***/ - p_ss->cb.e.pc_enet = e; - pc_data = e->data; - u_data_size = e->size; - b_stream = TNET_SOCKET_TYPE_IS_STREAM(p_ss->p_lcl_sock->type); - b_stream_appended = tsk_false; + p_ss->cb.e.pc_enet = e; + pc_data = e->data; + u_data_size = e->size; + b_stream = TNET_SOCKET_TYPE_IS_STREAM(p_ss->p_lcl_sock->type); + b_stream_appended = tsk_false; handle_data: - b_got_msg = tsk_false; - - // TODO: /!\ - // - When the requested transport is TCP/TLS then we will receive RAW data on the connected peer socket which means no way to guess the end-of-the message - // - No issue for when requested transport is UDP because we'll always have the data encapsulated in CHANNEL-DATA or DATA-INDICATION. - if (b_stream) { - if (!b_stream_appended) { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - if (pc_peer) { - p_stream_buff_in = tsk_object_ref(pc_peer->p_stream_buff_in); - } - else { - p_stream_buff_in = tsk_object_ref(p_ss->p_stream_buff_in); - } - tsk_safeobj_unlock(p_ss); - - if ((ret = tsk_buffer_append(p_stream_buff_in, e->data, e->size))) { - goto bail; - } - b_stream_appended = tsk_true; - } - // Guard - if (p_stream_buff_in->size > kTurnStreamChunckMaxSize) { - TSK_DEBUG_ERROR("Too much data in the stream buffer: %u", (unsigned)p_stream_buff_in->size); - tsk_buffer_cleanup(p_stream_buff_in); - goto bail; - } - pc_data = p_stream_buff_in->data; - u_data_size = p_stream_buff_in->size; - } + b_got_msg = tsk_false; - if (!TNET_STUN_BUFF_IS_STUN2(((const uint8_t*)pc_data), u_data_size)) { - // ChannelData ? - if (TNET_STUN_BUFF_IS_CHANNEL_DATA(((const uint8_t*)pc_data), u_data_size)) { - const uint8_t* _p_data = (const uint8_t*)pc_data; - // Channel Number in [0x4000 - 0x7FFF] - // rfc5766 - 11.6. Receiving a ChannelData Message - // rfc5766 - 11.4. The ChannelData Message - // If the message uses a value in the reserved range (0x8000 through 0xFFFF), then the message is silently discarded - static const tsk_size_t kChannelDataHdrSize = 4; // Channel Number(2 bytes) + Length (2 bytes) - uint16_t u_chan_num = tnet_ntohs_2(&_p_data[0]); - if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_channum, &u_chan_num))) { - uint16_t u_len = tnet_ntohs_2(&_p_data[2]); - if (u_len <= (u_data_size - kChannelDataHdrSize)) { - b_got_msg = tsk_true; - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer->id, &_p_data[kChannelDataHdrSize], u_len); - if (p_stream_buff_in) { - /* The padding is not reflected in the length - field of the ChannelData message, so the actual size of a ChannelData - message (including padding) is (4 + Length) rounded up to the nearest - multiple of 4. Over UDP, the padding is not required but MAY be - included. - */ - tsk_size_t u_pad_len = (u_len & 3) ? (4 - (u_len & 3)) : 0; - tsk_buffer_remove(p_stream_buff_in, 0, kChannelDataHdrSize + u_len + u_pad_len); - } - } - else { - TSK_DEBUG_INFO("TURN channel data too short"); - } - } - goto bail; - } // if (TNET_STUN_BUFF_IS_CHANNEL_DATA... - - // Must never happen: Data must be received via CHANNEL-DATA or DATA-INDICATION - TSK_DEBUG_INFO("Calling unexpected code :("); - - if (b_stream) { - tsk_safeobj_lock(p_ss); - pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - tsk_safeobj_unlock(p_ss); - } - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); - if (p_stream_buff_in) { - tsk_buffer_cleanup(p_stream_buff_in); - } - goto bail; - } // if (!TNET_STUN_BUFF_IS_STUN2... - - /*** At this step it means we have a STUN packet in the buffer ***/ - - // Make sure we have a complete packet in the buffer - if (b_stream) { - if ((ret = tnet_stun_pkt_is_complete(pc_data, u_data_size, &b_pkt_is_complete))) { - goto bail; - } - if (!b_pkt_is_complete) { - TSK_DEBUG_INFO("The stream length is too short to contains a complete STUN/TURN packet"); - goto bail; - } - } + // TODO: /!\ + // - When the requested transport is TCP/TLS then we will receive RAW data on the connected peer socket which means no way to guess the end-of-the message + // - No issue for when requested transport is UDP because we'll always have the data encapsulated in CHANNEL-DATA or DATA-INDICATION. + if (b_stream) { + if (!b_stream_appended) { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + if (pc_peer) { + p_stream_buff_in = tsk_object_ref(pc_peer->p_stream_buff_in); + } + else { + p_stream_buff_in = tsk_object_ref(p_ss->p_stream_buff_in); + } + tsk_safeobj_unlock(p_ss); - // Parse the packet - if ((ret = tnet_stun_pkt_read(pc_data, u_data_size, &p_pkt))) { - goto bail; - } + if ((ret = tsk_buffer_append(p_stream_buff_in, e->data, e->size))) { + goto bail; + } + b_stream_appended = tsk_true; + } + // Guard + if (p_stream_buff_in->size > kTurnStreamChunckMaxSize) { + TSK_DEBUG_ERROR("Too much data in the stream buffer: %u", (unsigned)p_stream_buff_in->size); + tsk_buffer_cleanup(p_stream_buff_in); + goto bail; + } + pc_data = p_stream_buff_in->data; + u_data_size = p_stream_buff_in->size; + } - // Remove the parsed data - if (p_stream_buff_in && p_pkt) { - tsk_size_t u_pad_len = (p_pkt->u_length & 3) ? (4 - (p_pkt->u_length & 3)) : 0; - tsk_buffer_remove(p_stream_buff_in, 0, kStunPktHdrSizeInOctets + p_pkt->u_length + u_pad_len); - } + if (!TNET_STUN_BUFF_IS_STUN2(((const uint8_t*)pc_data), u_data_size)) { + // ChannelData ? + if (TNET_STUN_BUFF_IS_CHANNEL_DATA(((const uint8_t*)pc_data), u_data_size)) { + const uint8_t* _p_data = (const uint8_t*)pc_data; + // Channel Number in [0x4000 - 0x7FFF] + // rfc5766 - 11.6. Receiving a ChannelData Message + // rfc5766 - 11.4. The ChannelData Message + // If the message uses a value in the reserved range (0x8000 through 0xFFFF), then the message is silently discarded + static const tsk_size_t kChannelDataHdrSize = 4; // Channel Number(2 bytes) + Length (2 bytes) + uint16_t u_chan_num = tnet_ntohs_2(&_p_data[0]); + if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_channum, &u_chan_num))) { + uint16_t u_len = tnet_ntohs_2(&_p_data[2]); + if (u_len <= (u_data_size - kChannelDataHdrSize)) { + b_got_msg = tsk_true; + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer->id, &_p_data[kChannelDataHdrSize], u_len); + if (p_stream_buff_in) { + /* The padding is not reflected in the length + field of the ChannelData message, so the actual size of a ChannelData + message (including padding) is (4 + Length) rounded up to the nearest + multiple of 4. Over UDP, the padding is not required but MAY be + included. + */ + tsk_size_t u_pad_len = (u_len & 3) ? (4 - (u_len & 3)) : 0; + tsk_buffer_remove(p_stream_buff_in, 0, kChannelDataHdrSize + u_len + u_pad_len); + } + } + else { + TSK_DEBUG_INFO("TURN channel data too short"); + } + } + goto bail; + } // if (TNET_STUN_BUFF_IS_CHANNEL_DATA... - if (p_pkt) { - b_got_msg = tsk_true; - if (p_pkt->e_type == tnet_stun_pkt_type_data_indication) { - const tnet_stun_attr_vdata_t *pc_attr_data; - const tnet_stun_attr_address_t *pc_attr_xpeer; - const tnet_turn_peer_t *pc_peer; - // XOR-PEER-ADDRESS (required) - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xpeer)) || !pc_attr_xpeer) { - TSK_DEBUG_ERROR("XOR-PEER-ADDRESS missing in DATA-INDICATION"); - ret = -4; - goto bail; - } - tsk_safeobj_lock(p_ss); // lock to make sure the list will not be modified - if ((ret = _tnet_turn_peer_find_by_xpeer(p_ss->p_list_peers, pc_attr_xpeer, &pc_peer))) { - tsk_safeobj_unlock(p_ss); - goto bail; - } - tsk_safeobj_unlock(p_ss); // unlock() - // DATA (required) - if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data)) || !pc_attr_data) { - TSK_DEBUG_ERROR("DATA missing in DATA-INDICAION"); - ret = -4; - goto bail; - } - - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_attr_data->p_data_ptr, pc_attr_data->u_data_size); - } - else { - tsk_bool_t b_processed; - if ((ret = _tnet_turn_session_process_incoming_pkt(p_ss, p_pkt, &b_processed))) { - goto bail; - } - if (!b_processed) { - const tnet_turn_peer_t *pc_peer; - tsk_safeobj_lock(p_ss); - pc_peer = (const tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); - tsk_safeobj_unlock(p_ss); // unlock() - // Forward to listeners (e.g. ICE context) - _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); - } - } - } + // Must never happen: Data must be received via CHANNEL-DATA or DATA-INDICATION + TSK_DEBUG_INFO("Calling unexpected code :("); + + if (b_stream) { + tsk_safeobj_lock(p_ss); + pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + tsk_safeobj_unlock(p_ss); + } + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); + if (p_stream_buff_in) { + tsk_buffer_cleanup(p_stream_buff_in); + } + goto bail; + } // if (!TNET_STUN_BUFF_IS_STUN2... + + /*** At this step it means we have a STUN packet in the buffer ***/ + + // Make sure we have a complete packet in the buffer + if (b_stream) { + if ((ret = tnet_stun_pkt_is_complete(pc_data, u_data_size, &b_pkt_is_complete))) { + goto bail; + } + if (!b_pkt_is_complete) { + TSK_DEBUG_INFO("The stream length is too short to contains a complete STUN/TURN packet"); + goto bail; + } + } + + // Parse the packet + if ((ret = tnet_stun_pkt_read(pc_data, u_data_size, &p_pkt))) { + goto bail; + } + + // Remove the parsed data + if (p_stream_buff_in && p_pkt) { + tsk_size_t u_pad_len = (p_pkt->u_length & 3) ? (4 - (p_pkt->u_length & 3)) : 0; + tsk_buffer_remove(p_stream_buff_in, 0, kStunPktHdrSizeInOctets + p_pkt->u_length + u_pad_len); + } + + if (p_pkt) { + b_got_msg = tsk_true; + if (p_pkt->e_type == tnet_stun_pkt_type_data_indication) { + const tnet_stun_attr_vdata_t *pc_attr_data; + const tnet_stun_attr_address_t *pc_attr_xpeer; + const tnet_turn_peer_t *pc_peer; + // XOR-PEER-ADDRESS (required) + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_xor_peer_address, (const tnet_stun_attr_t**)&pc_attr_xpeer)) || !pc_attr_xpeer) { + TSK_DEBUG_ERROR("XOR-PEER-ADDRESS missing in DATA-INDICATION"); + ret = -4; + goto bail; + } + tsk_safeobj_lock(p_ss); // lock to make sure the list will not be modified + if ((ret = _tnet_turn_peer_find_by_xpeer(p_ss->p_list_peers, pc_attr_xpeer, &pc_peer))) { + tsk_safeobj_unlock(p_ss); + goto bail; + } + tsk_safeobj_unlock(p_ss); // unlock() + // DATA (required) + if ((ret = tnet_stun_pkt_attr_find_first(p_pkt, tnet_stun_attr_type_data, (const tnet_stun_attr_t**)&pc_attr_data)) || !pc_attr_data) { + TSK_DEBUG_ERROR("DATA missing in DATA-INDICAION"); + ret = -4; + goto bail; + } + + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_attr_data->p_data_ptr, pc_attr_data->u_data_size); + } + else { + tsk_bool_t b_processed; + if ((ret = _tnet_turn_session_process_incoming_pkt(p_ss, p_pkt, &b_processed))) { + goto bail; + } + if (!b_processed) { + const tnet_turn_peer_t *pc_peer; + tsk_safeobj_lock(p_ss); + pc_peer = (const tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_fd, &e->local_fd); + tsk_safeobj_unlock(p_ss); // unlock() + // Forward to listeners (e.g. ICE context) + _tnet_turn_session_raise_event_recv_data(p_ss, pc_peer ? pc_peer->id : kTurnPeerIdInvalid, pc_data, u_data_size); + } + } + } bail: - // Handle next message in the stream buffer - if (ret == 0 && b_got_msg && b_stream && p_stream_buff_in && p_stream_buff_in->size > 0) { - goto handle_data; - } + // Handle next message in the stream buffer + if (ret == 0 && b_got_msg && b_stream && p_stream_buff_in && p_stream_buff_in->size > 0) { + goto handle_data; + } - TSK_OBJECT_SAFE_FREE(p_pkt); - TSK_OBJECT_SAFE_FREE(p_stream_buff_in); - p_ss->cb.e.pc_enet = tsk_null; + TSK_OBJECT_SAFE_FREE(p_pkt); + TSK_OBJECT_SAFE_FREE(p_stream_buff_in); + p_ss->cb.e.pc_enet = tsk_null; return ret; } @@ -2288,36 +2294,36 @@ static int _tnet_turn_session_timer_callback(const void* pc_arg, tsk_timer_id_t } tnet_turn_session_t* p_ss = (tnet_turn_session_t*)pc_arg; - tnet_turn_peer_t* pc_peer; - int ret = 0; + tnet_turn_peer_t* pc_peer; + int ret = 0; tsk_safeobj_lock(p_ss); // must - if (p_ss->timer.rtt.alloc.id == timer_id) { - RETRANSMIT(p_ss, alloc, kTurnPeerIdInvalid); + if (p_ss->timer.rtt.alloc.id == timer_id) { + RETRANSMIT(p_ss, alloc, kTurnPeerIdInvalid); } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_chanbind, &timer_id))) { - RETRANSMIT(pc_peer, chanbind, pc_peer->id); + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_chanbind, &timer_id))) { + RETRANSMIT(pc_peer, chanbind, pc_peer->id); } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_createperm, &timer_id))) { - RETRANSMIT(pc_peer, createperm, pc_peer->id); + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_rtt_createperm, &timer_id))) { + RETRANSMIT(pc_peer, createperm, pc_peer->id); } - else if (p_ss->timer.rtt.refresh.id == timer_id) { - RETRANSMIT(p_ss, refresh, kTurnPeerIdInvalid); + else if (p_ss->timer.rtt.refresh.id == timer_id) { + RETRANSMIT(p_ss, refresh, kTurnPeerIdInvalid); } - else if (p_ss->timer.u_timer_id_refresh == timer_id) { - if ((ret = _tnet_turn_session_send_refresh(p_ss))) { - goto bail; - } + else if (p_ss->timer.u_timer_id_refresh == timer_id) { + if ((ret = _tnet_turn_session_send_refresh(p_ss))) { + goto bail; + } } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_chanbind, &timer_id))) { - if ((ret = tnet_turn_session_chanbind(p_ss, pc_peer->id))) { - goto bail; - } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_chanbind, &timer_id))) { + if ((ret = tnet_turn_session_chanbind(p_ss, pc_peer->id))) { + goto bail; + } + } + else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_createperm, &timer_id))) { + if ((ret = _tnet_turn_session_send_permission(p_ss, pc_peer))) { + goto bail; + } } - else if ((pc_peer = (tnet_turn_peer_t*)tsk_list_find_object_by_pred(p_ss->p_list_peers, __pred_find_peer_by_timer_fresh_createperm, &timer_id))) { - if ((ret = _tnet_turn_session_send_permission(p_ss, pc_peer))) { - goto bail; - } - } bail: tsk_safeobj_unlock(p_ss); @@ -2326,71 +2332,71 @@ bail: static int _tnet_turn_peer_create(const char* pc_peer_ip, uint16_t u_peer_port, tsk_bool_t b_ipv6, struct tnet_turn_peer_s **pp_peer) { - extern const tsk_object_def_t *tnet_turn_peer_def_t; - static tnet_turn_peer_id_t __l_peer_id = 0; - tnet_stun_addr_t peer_addr; - int ret; - if (!pc_peer_ip || !u_peer_port || !pp_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if ((ret = tnet_stun_utils_inet_pton(b_ipv6, pc_peer_ip, &peer_addr))) { + extern const tsk_object_def_t *tnet_turn_peer_def_t; + static tnet_turn_peer_id_t __l_peer_id = 0; + tnet_stun_addr_t peer_addr; + int ret; + if (!pc_peer_ip || !u_peer_port || !pp_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if ((ret = tnet_stun_utils_inet_pton(b_ipv6, pc_peer_ip, &peer_addr))) { TSK_DEBUG_ERROR("inet_pton(%s,IPv6=%d) failed", pc_peer_ip, b_ipv6); goto bail; } - if (!(*pp_peer = tsk_object_new(tnet_turn_peer_def_t))) { - TSK_DEBUG_ERROR("Failed to create TURN peer object"); - return -2; - } - (*pp_peer)->p_addr_ip = tsk_strdup(pc_peer_ip); - memcpy((*pp_peer)->addr_ip, peer_addr, sizeof(peer_addr)); - (*pp_peer)->u_addr_port = u_peer_port; - (*pp_peer)->b_ipv6 = b_ipv6; - tsk_atomic_inc(&__l_peer_id); - (*pp_peer)->id = __l_peer_id; - (*pp_peer)->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; - (*pp_peer)->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; - (*pp_peer)->timer.fresh.chanbind.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.fresh.createperm.id = TSK_INVALID_TIMER_ID; - (*pp_peer)->timer.fresh.chanbind.u_timeout = kTurnChannelBindingTimeOutInSec * 1000; - (*pp_peer)->timer.fresh.createperm.u_timeout = kTurnPermissionTimeOutInSec * 1000; - (*pp_peer)->e_chanbind_state = tnet_stun_state_none; - (*pp_peer)->e_createperm_state = tnet_stun_state_none; + if (!(*pp_peer = tsk_object_new(tnet_turn_peer_def_t))) { + TSK_DEBUG_ERROR("Failed to create TURN peer object"); + return -2; + } + (*pp_peer)->p_addr_ip = tsk_strdup(pc_peer_ip); + memcpy((*pp_peer)->addr_ip, peer_addr, sizeof(peer_addr)); + (*pp_peer)->u_addr_port = u_peer_port; + (*pp_peer)->b_ipv6 = b_ipv6; + tsk_atomic_inc(&__l_peer_id); + (*pp_peer)->id = __l_peer_id; + (*pp_peer)->timer.rtt.chanbind.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.rtt.createperm.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.rtt.chanbind.u_timeout = kStunUdpRetransmitTimoutMinInMs; + (*pp_peer)->timer.rtt.createperm.u_timeout = kStunUdpRetransmitTimoutMinInMs; + (*pp_peer)->timer.fresh.chanbind.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.fresh.createperm.id = TSK_INVALID_TIMER_ID; + (*pp_peer)->timer.fresh.chanbind.u_timeout = kTurnChannelBindingTimeOutInSec * 1000; + (*pp_peer)->timer.fresh.createperm.u_timeout = kTurnPermissionTimeOutInSec * 1000; + (*pp_peer)->e_chanbind_state = tnet_stun_state_none; + (*pp_peer)->e_createperm_state = tnet_stun_state_none; bail: - return ret; + return ret; } static int _tnet_turn_peer_find_by_xpeer(const tnet_turn_peers_L_t* pc_peers, const tnet_stun_attr_address_t* pc_xpeer, const tnet_turn_peer_t **ppc_peer) { - const tsk_list_item_t *pc_item; - const tnet_turn_peer_t *pc_peer; - if (!pc_peers || !pc_xpeer || !ppc_peer) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - *ppc_peer = tsk_null; - tsk_list_foreach(pc_item, pc_peers) { - pc_peer = (const tnet_turn_peer_t *)pc_item->data; - if (pc_peer->u_addr_port == pc_xpeer->u_port) { - if (tnet_stun_utils_buff_cmp( - pc_peer->addr_ip, pc_peer->b_ipv6 ? 16 : 4, - pc_xpeer->address, (pc_xpeer->e_family == tnet_stun_address_family_ipv6) ? 16 : 4) == 0) { - *ppc_peer = pc_peer; - return 0; - } - } - } - return 0; + const tsk_list_item_t *pc_item; + const tnet_turn_peer_t *pc_peer; + if (!pc_peers || !pc_xpeer || !ppc_peer) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + *ppc_peer = tsk_null; + tsk_list_foreach(pc_item, pc_peers) { + pc_peer = (const tnet_turn_peer_t *)pc_item->data; + if (pc_peer->u_addr_port == pc_xpeer->u_port) { + if (tnet_stun_utils_buff_cmp( + pc_peer->addr_ip, pc_peer->b_ipv6 ? 16 : 4, + pc_xpeer->address, (pc_xpeer->e_family == tnet_stun_address_family_ipv6) ? 16 : 4) == 0) { + *ppc_peer = pc_peer; + return 0; + } + } + } + return 0; } static tsk_object_t* tnet_turn_session_ctor(tsk_object_t * self, va_list * app) { tnet_turn_session_t *p_ss = (tnet_turn_session_t *)self; if (p_ss) { - tsk_safeobj_init(p_ss); + tsk_safeobj_init(p_ss); } return self; } @@ -2398,41 +2404,41 @@ static tsk_object_t* tnet_turn_session_dtor(tsk_object_t * self) { tnet_turn_session_t *p_ss = (tnet_turn_session_t *)self; if (p_ss) { - // stop() - tnet_turn_session_stop(p_ss); - // timer.free() - TSK_OBJECT_SAFE_FREE(p_ss->timer.p_mgr); - // cred.free() - TSK_FREE(p_ss->cred.p_usr_name); - TSK_FREE(p_ss->cred.p_pwd); - // others.free() - TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_alloc); - TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_refresh); - TSK_OBJECT_SAFE_FREE(p_ss->p_lcl_sock); - - TSK_FREE(p_ss->p_buff_chandata_ptr); - TSK_FREE(p_ss->p_buff_send_ptr); - TSK_FREE(p_ss->p_rel_ip); - TSK_FREE(p_ss->p_srflx_ip); - TSK_FREE(p_ss->p_srv_host); - - if (p_ss->p_transport) { - tnet_transport_shutdown(p_ss->p_transport); - TSK_OBJECT_SAFE_FREE(p_ss->p_transport); - } - - TSK_OBJECT_SAFE_FREE(p_ss->p_list_peers); - TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_in); + // stop() + tnet_turn_session_stop(p_ss); + // timer.free() + TSK_OBJECT_SAFE_FREE(p_ss->timer.p_mgr); + // cred.free() + TSK_FREE(p_ss->cred.p_usr_name); + TSK_FREE(p_ss->cred.p_pwd); + // others.free() + TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_alloc); + TSK_OBJECT_SAFE_FREE(p_ss->p_pkt_refresh); + TSK_OBJECT_SAFE_FREE(p_ss->p_lcl_sock); + + TSK_FREE(p_ss->p_buff_chandata_ptr); + TSK_FREE(p_ss->p_buff_send_ptr); + TSK_FREE(p_ss->p_rel_ip); + TSK_FREE(p_ss->p_srflx_ip); + TSK_FREE(p_ss->p_srv_host); + + if (p_ss->p_transport) { + tnet_transport_shutdown(p_ss->p_transport); + TSK_OBJECT_SAFE_FREE(p_ss->p_transport); + } + + TSK_OBJECT_SAFE_FREE(p_ss->p_list_peers); + TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_in); TSK_OBJECT_SAFE_FREE(p_ss->p_stream_buff_out); - + TSK_OBJECT_SAFE_FREE(p_ss->proxy.info); - TSK_FREE(p_ss->ssl.path_priv); - TSK_FREE(p_ss->ssl.path_pub); - TSK_FREE(p_ss->ssl.path_ca); + TSK_FREE(p_ss->ssl.path_priv); + TSK_FREE(p_ss->ssl.path_pub); + TSK_FREE(p_ss->ssl.path_ca); - tsk_safeobj_deinit(p_ss); - TSK_DEBUG_INFO("*** TURN Session destroyed ***"); + tsk_safeobj_deinit(p_ss); + TSK_DEBUG_INFO("*** TURN Session destroyed ***"); } return self; } @@ -2456,7 +2462,7 @@ static tsk_object_t* tnet_turn_peer_ctor(tsk_object_t * self, va_list * app) { tnet_turn_peer_t *p_peer = (tnet_turn_peer_t *)self; if (p_peer) { - + } return self; } @@ -2464,13 +2470,13 @@ static tsk_object_t* tnet_turn_peer_dtor(tsk_object_t * self) { tnet_turn_peer_t *p_peer = (tnet_turn_peer_t *)self; if (p_peer) { - TSK_FREE(p_peer->p_addr_ip); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_chanbind); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_sendind); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connect); - TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connbind); - TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_in); + TSK_FREE(p_peer->p_addr_ip); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_chanbind); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_createperm); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_sendind); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connect); + TSK_OBJECT_SAFE_FREE(p_peer->p_pkt_connbind); + TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_in); TSK_OBJECT_SAFE_FREE(p_peer->p_stream_buff_out); #if PRINT_DESTROYED_MSG || 1 TSK_DEBUG_INFO("*** TURN peer destroyed ***"); diff --git a/tinyNET/src/turn/tnet_turn_session.h b/tinyNET/src/turn/tnet_turn_session.h index fa4a030..7357bb1 100755 --- a/tinyNET/src/turn/tnet_turn_session.h +++ b/tinyNET/src/turn/tnet_turn_session.h @@ -33,34 +33,33 @@ struct tnet_proxyinfo_s; enum tnet_socket_type_e; #define kTurnPeerIdInvalid -1 -typedef enum tnet_turn_session_event_type_e -{ - tnet_turn_session_event_type_alloc_ok, - tnet_turn_session_event_type_alloc_nok, - tnet_turn_session_event_type_refresh_ok, - tnet_turn_session_event_type_refresh_nok, - tnet_turn_session_event_type_perm_ok, - tnet_turn_session_event_type_perm_nok, - tnet_turn_session_event_type_recv_data, - tnet_turn_session_event_type_chanbind_ok, - tnet_turn_session_event_type_chanbind_nok, - tnet_turn_session_event_type_connect_ok, - tnet_turn_session_event_type_connect_nok, - tnet_turn_session_event_type_connectionbind_ok, - tnet_turn_session_event_type_connectionbind_nok, +typedef enum tnet_turn_session_event_type_e { + tnet_turn_session_event_type_alloc_ok, + tnet_turn_session_event_type_alloc_nok, + tnet_turn_session_event_type_refresh_ok, + tnet_turn_session_event_type_refresh_nok, + tnet_turn_session_event_type_perm_ok, + tnet_turn_session_event_type_perm_nok, + tnet_turn_session_event_type_recv_data, + tnet_turn_session_event_type_chanbind_ok, + tnet_turn_session_event_type_chanbind_nok, + tnet_turn_session_event_type_connect_ok, + tnet_turn_session_event_type_connect_nok, + tnet_turn_session_event_type_connectionbind_ok, + tnet_turn_session_event_type_connectionbind_nok, } tnet_turn_session_event_type_t; typedef struct tnet_turn_session_event_xs { - enum tnet_turn_session_event_type_e e_type; - tnet_turn_peer_id_t u_peer_id; - const void* pc_usr_data; - const struct tnet_transport_event_s* pc_enet; - struct tnet_turn_session_s* pc_session; - struct { - const void* pc_data_ptr; - tsk_size_t u_data_size; - } data; + enum tnet_turn_session_event_type_e e_type; + tnet_turn_peer_id_t u_peer_id; + const void* pc_usr_data; + const struct tnet_transport_event_s* pc_enet; + struct tnet_turn_session_s* pc_session; + struct { + const void* pc_data_ptr; + tsk_size_t u_data_size; + } data; } tnet_turn_session_event_xt; typedef int (*tnet_turn_session_callback_f)(const struct tnet_turn_session_event_xs *e); diff --git a/tinyNET/test/targetver.h b/tinyNET/test/targetver.h index 21af608..5972193 100755 --- a/tinyNET/test/targetver.h +++ b/tinyNET/test/targetver.h @@ -20,8 +20,8 @@ #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 +// 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. diff --git a/tinyNET/test/test.c b/tinyNET/test/test.c index 64e0349..d8af3a8 100755 --- a/tinyNET/test/test.c +++ b/tinyNET/test/test.c @@ -57,65 +57,65 @@ int _tmain(int argc, _TCHAR* argv[]) int main() #endif { - /* Startup the network stack. */ - if(tnet_startup()){ - return -1; - } + /* Startup the network stack. */ + if(tnet_startup()) { + return -1; + } #if RUN_TEST_LOOP - for(;;) + for(;;) #endif - { - + { + #if RUN_TEST_ALL || RUN_TEST_SOCKETS - test_sockets(); + test_sockets(); #endif #if RUN_TEST_ALL || RUN_TEST_TRANSPORT - test_transport(); + test_transport(); #endif #if RUN_TEST_ALL || RUN_TEST_AUTH - test_auth(); + test_auth(); #endif #if RUN_TEST_ALL || RUN_TEST_STUN - test_stun(); + test_stun(); #endif #if RUN_TEST_ALL || RUN_TEST_ICE - test_ice(); + test_ice(); #endif #if RUN_TEST_ALL || RUN_TEST_NAT - test_nat(); + test_nat(); #endif #if RUN_TEST_ALL || RUN_TEST_IFACES - test_ifaces(); + test_ifaces(); #endif #if RUN_TEST_ALL || RUN_TEST_DNS - test_dns(); + test_dns(); #endif #if RUN_TEST_ALL || RUN_TEST_DHCP - test_dhcp(); + test_dhcp(); #endif #if RUN_TEST_ALL || RUN_TEST_DHCP6 - test_dhcp6(); + test_dhcp6(); #endif #if RUN_TEST_ALL || RUN_TEST_TLS - test_tls(); + test_tls(); #endif - } + } - /* Cleanup the network stack */ - tnet_cleanup(); + /* Cleanup the network stack */ + tnet_cleanup(); - return 0; + return 0; } diff --git a/tinyNET/test/test_dhcp.h b/tinyNET/test/test_dhcp.h index c74e99c..ee6e767 100755 --- a/tinyNET/test/test_dhcp.h +++ b/tinyNET/test/test_dhcp.h @@ -35,84 +35,75 @@ 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; - } - + 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_OBJECT_SAFE_FREE(reply); + TSK_OBJECT_SAFE_FREE(params); - //tsk_thread_sleep(1000); + //tsk_thread_sleep(1000); } void test_dhcp() { - tnet_dhcp_ctx_t *ctx = tnet_dhcp_ctx_create(); - test_dhcp_inform(ctx); + tnet_dhcp_ctx_t *ctx = tnet_dhcp_ctx_create(); + test_dhcp_inform(ctx); - TSK_OBJECT_SAFE_FREE(ctx); + TSK_OBJECT_SAFE_FREE(ctx); } #endif /* TNET_TEST_DHCP_H */ diff --git a/tinyNET/test/test_dhcp6.h b/tinyNET/test/test_dhcp6.h index c96fd96..1844dcc 100755 --- a/tinyNET/test/test_dhcp6.h +++ b/tinyNET/test/test_dhcp6.h @@ -23,26 +23,26 @@ 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_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 */ + 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); + reply = tnet_dhcp6_requestinfo(ctx, orequest); - TSK_OBJECT_SAFE_FREE(orequest); - TSK_OBJECT_SAFE_FREE(reply); + 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); + tnet_dhcp6_ctx_t *ctx = tnet_dhcp6_ctx_create(); + test_dhcp6_requestinfo(ctx); - TSK_OBJECT_SAFE_FREE(ctx); + TSK_OBJECT_SAFE_FREE(ctx); } #endif /* TNET_TEST_DHCP6_H */ diff --git a/tinyNET/test/test_dns.h b/tinyNET/test/test_dns.h index f2ab145..83c8002 100755 --- a/tinyNET/test/test_dns.h +++ b/tinyNET/test/test_dns.h @@ -23,201 +23,199 @@ 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); + 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; + 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); - } + 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_FREE(hostname); + TSK_OBJECT_SAFE_FREE(ctx); - tsk_thread_sleep(2000); + 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; + 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); - } + 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_FREE(hostname); + TSK_OBJECT_SAFE_FREE(ctx); - tsk_thread_sleep(2000); + tsk_thread_sleep(2000); } void test_enum() { - tnet_dns_ctx_t *ctx = tnet_dns_ctx_create(); - tnet_dns_response_t* response = tsk_null; + 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); + 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; +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", + "+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", + "+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", - "urn:cid:199606121851.1@bar.example.com", "!!^urn:cid:.+@([^\\.]+\\.)(.*)$!\\2!i", "example.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("---------"); - } + 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); - } + 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(); + test_dns_naptr_srv(); + //test_dns_srv(); + //test_dns_query(); + //test_enum(); + //test_regex(); + //test_resolvconf(); } diff --git a/tinyNET/test/test_ice.h b/tinyNET/test/test_ice.h index 023a2c2..c7341b2 100755 --- a/tinyNET/test/test_ice.h +++ b/tinyNET/test/test_ice.h @@ -44,193 +44,190 @@ static struct tnet_ice_ctx_s *p_ice_ctx2 = tsk_null; static void test_ice_print_local_candidates(const struct tnet_ice_ctx_s *pc_ctx) { - tsk_size_t index = 0; - const tnet_ice_candidate_t* candidate; - char* p_str = tsk_null; - - while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) { - tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate)); - } - TSK_DEBUG_INFO("ICE LOCAL CANDIDATES:\n%s", p_str); - TSK_FREE(p_str); + tsk_size_t index = 0; + const tnet_ice_candidate_t* candidate; + char* p_str = tsk_null; + + while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) { + tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate)); + } + TSK_DEBUG_INFO("ICE LOCAL CANDIDATES:\n%s", p_str); + TSK_FREE(p_str); } static char* test_ice_get_local_candidates(const struct tnet_ice_ctx_s *pc_ctx) { - tsk_size_t index = 0; - const tnet_ice_candidate_t* candidate; - char* p_str = tsk_null; - - while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) { - if (kSkipHosts && candidate->type_e == tnet_ice_cand_type_host) { - continue; - } - if (kSkipReflexives && candidate->type_e == tnet_ice_cand_type_srflx) { - continue; - } - if (kSkipRelays && candidate->type_e == tnet_ice_cand_type_relay) { - continue; - } - if (kSkipPeers && candidate->type_e == tnet_ice_cand_type_prflx) { - continue; - } - tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate)); - } - return p_str; + tsk_size_t index = 0; + const tnet_ice_candidate_t* candidate; + char* p_str = tsk_null; + + while ((candidate = tnet_ice_ctx_get_local_candidate_at(pc_ctx, index++))) { + if (kSkipHosts && candidate->type_e == tnet_ice_cand_type_host) { + continue; + } + if (kSkipReflexives && candidate->type_e == tnet_ice_cand_type_srflx) { + continue; + } + if (kSkipRelays && candidate->type_e == tnet_ice_cand_type_relay) { + continue; + } + if (kSkipPeers && candidate->type_e == tnet_ice_cand_type_prflx) { + continue; + } + tsk_strcat_2(&p_str, "%s\r\n", tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate)); + } + return p_str; } static int test_ice_rtp_callback(const void* callback_data, const uint8_t* data_ptr, tsk_size_t data_size, tnet_fd_t local_fd, const struct sockaddr_storage* remote_addr) { - struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)callback_data; + struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)callback_data; - TSK_DEBUG_INFO("\n\nICE rtp callback (incoming data): %.*s\n\n", data_size, data_ptr); + TSK_DEBUG_INFO("\n\nICE rtp callback (incoming data): %.*s\n\n", data_size, data_ptr); #if 0 - tnet_ice_ctx_send_turn_rtp(p_ice_ctx, data_ptr, data_size); + tnet_ice_ctx_send_turn_rtp(p_ice_ctx, data_ptr, data_size); #endif - return 0; + return 0; } static int test_ice_state_callback(const tnet_ice_event_t *e) { - struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)e->ctx; - int ret = 0; - - TSK_DEBUG_INFO("ICE state callback: %s", e->phrase); - - switch(e->type) - { - case tnet_ice_event_type_gathering_completed: - { - test_ice_print_local_candidates(p_ice_ctx); - if (p_ice_ctx == p_ice_ctx1) { - if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) { - goto bail; - } - } - else { - const tnet_ice_candidate_t* candidate; - char* p_cand; - - p_cand = test_ice_get_local_candidates(p_ice_ctx2); - candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx2); - ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx1, p_cand, candidate->ufrag, candidate->pwd, tsk_true, tsk_false); - if (ret == 0) { - TSK_FREE(p_cand); - p_cand = test_ice_get_local_candidates(p_ice_ctx1); - candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx1); - ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx2, p_cand, candidate->ufrag, candidate->pwd, tsk_false, tsk_false); - TSK_FREE(p_cand); - } - } - break; - } - - case tnet_ice_event_type_conncheck_succeed: - { - const char kTurnData[] = "TURN data to send for testing"; - const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; - - // === RTP === // - ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - if (ret == 0) { - TSK_DEBUG_INFO("Nominated candidate(RTP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]", - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer), - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src), - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest)); - - if (tnet_ice_ctx_is_turn_rtp_active(p_ice_ctx)) { - tnet_ice_ctx_send_turn_rtp(p_ice_ctx, kTurnData, sizeof(kTurnData)); - } - } - // === RTCP === // - if (use_rtcp) { - ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); - if (ret == 0) { - TSK_DEBUG_INFO("Nominated candidate(RTCP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]", - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer), - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src), - tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest)); - if (tnet_ice_ctx_is_turn_rtcp_active(p_ice_ctx)) { - tnet_ice_ctx_send_turn_rtcp(p_ice_ctx, kTurnData, sizeof(kTurnData)); - } - } - } - break; - } - } + struct tnet_ice_ctx_s *p_ice_ctx = (struct tnet_ice_ctx_s *)e->ctx; + int ret = 0; + + TSK_DEBUG_INFO("ICE state callback: %s", e->phrase); + + switch(e->type) { + case tnet_ice_event_type_gathering_completed: { + test_ice_print_local_candidates(p_ice_ctx); + if (p_ice_ctx == p_ice_ctx1) { + if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) { + goto bail; + } + } + else { + const tnet_ice_candidate_t* candidate; + char* p_cand; + + p_cand = test_ice_get_local_candidates(p_ice_ctx2); + candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx2); + ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx1, p_cand, candidate->ufrag, candidate->pwd, tsk_true, tsk_false); + if (ret == 0) { + TSK_FREE(p_cand); + p_cand = test_ice_get_local_candidates(p_ice_ctx1); + candidate = tnet_ice_ctx_get_local_candidate_first(p_ice_ctx1); + ret = tnet_ice_ctx_set_remote_candidates(p_ice_ctx2, p_cand, candidate->ufrag, candidate->pwd, tsk_false, tsk_false); + TSK_FREE(p_cand); + } + } + break; + } + + case tnet_ice_event_type_conncheck_succeed: { + const char kTurnData[] = "TURN data to send for testing"; + const tnet_ice_candidate_t *candidate_offer, *candidate_answer_src, *candidate_answer_dest; + + // === RTP === // + ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + if (ret == 0) { + TSK_DEBUG_INFO("Nominated candidate(RTP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]", + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer), + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src), + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest)); + + if (tnet_ice_ctx_is_turn_rtp_active(p_ice_ctx)) { + tnet_ice_ctx_send_turn_rtp(p_ice_ctx, kTurnData, sizeof(kTurnData)); + } + } + // === RTCP === // + if (use_rtcp) { + ret = tnet_ice_ctx_get_nominated_symetric_candidates(p_ice_ctx, TNET_ICE_CANDIDATE_COMPID_RTCP, &candidate_offer, &candidate_answer_src, &candidate_answer_dest); + if (ret == 0) { + TSK_DEBUG_INFO("Nominated candidate(RTCP): Offer=[[%s]], AnswerSrc=[[%s]], AnswerDest=[[%s]]", + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_offer), + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_src), + tnet_ice_candidate_tostring((tnet_ice_candidate_t*)candidate_answer_dest)); + if (tnet_ice_ctx_is_turn_rtcp_active(p_ice_ctx)) { + tnet_ice_ctx_send_turn_rtcp(p_ice_ctx, kTurnData, sizeof(kTurnData)); + } + } + } + break; + } + } bail: - return ret; + return ret; } void test_ice() { - int ret; - static const tsk_bool_t use_ipv6 = tsk_false; - static const tsk_bool_t use_ice_jingle = tsk_false; - static const tsk_bool_t use_video = tsk_false; - - if (!(p_ice_ctx1 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) { - goto bail; - } - if (!(p_ice_ctx2 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx1, 1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx2, 1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx1, 1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx2, 1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx1, p_ice_ctx1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx2, p_ice_ctx2))) { - goto bail; - } - if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx1, test_ice_rtp_callback, p_ice_ctx1))) { - goto bail; - } - if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx2, test_ice_rtp_callback, p_ice_ctx2))) { - goto bail; - } + int ret; + static const tsk_bool_t use_ipv6 = tsk_false; + static const tsk_bool_t use_ice_jingle = tsk_false; + static const tsk_bool_t use_video = tsk_false; + + if (!(p_ice_ctx1 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) { + goto bail; + } + if (!(p_ice_ctx2 = tnet_ice_ctx_create(use_ice_jingle, use_ipv6, use_rtcp, use_video, test_ice_state_callback, tsk_null))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx1, 1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_turn_enabled(p_ice_ctx2, 1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx1, 1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_stun_enabled(p_ice_ctx2, 1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx1, p_ice_ctx1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_userdata(p_ice_ctx2, p_ice_ctx2))) { + goto bail; + } + if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx1, test_ice_rtp_callback, p_ice_ctx1))) { + goto bail; + } + if ((ret = tnet_ice_ctx_rtp_callback(p_ice_ctx2, test_ice_rtp_callback, p_ice_ctx2))) { + goto bail; + } #if 0 //@deprecated - if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx1, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) { - goto bail; - } - if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx2, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) { - goto bail; - } + if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx1, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) { + goto bail; + } + if ((ret = tnet_ice_ctx_set_stun(p_ice_ctx2, kStunServerIP, 3478, kStunSoftware, kStunUsrName, kStunPwd))) { + goto bail; + } #else - tnet_ice_ctx_add_server(p_ice_ctx1, "udp", kStunServerIP, 3478, kTurnFalse, kStunTrue, kStunUsrName, kStunPwd); // STUN-UDP - tnet_ice_ctx_add_server(p_ice_ctx1, "tcp", kStunServerIP, 3478, kTurnTrue, kStunFalse, kStunUsrName, kStunPwd); // TURN-TCP - tnet_ice_ctx_add_server(p_ice_ctx2, "udp", kStunServerIP, 3478, kTurnFalse, kStunTrue, kStunUsrName, kStunPwd); // STUN-UDP - tnet_ice_ctx_add_server(p_ice_ctx2, "tcp", kStunServerIP, 3478, kTurnTrue, kStunFalse, kStunUsrName, kStunPwd); // TURN-TCP + tnet_ice_ctx_add_server(p_ice_ctx1, "udp", kStunServerIP, 3478, kTurnFalse, kStunTrue, kStunUsrName, kStunPwd); // STUN-UDP + tnet_ice_ctx_add_server(p_ice_ctx1, "tcp", kStunServerIP, 3478, kTurnTrue, kStunFalse, kStunUsrName, kStunPwd); // TURN-TCP + tnet_ice_ctx_add_server(p_ice_ctx2, "udp", kStunServerIP, 3478, kTurnFalse, kStunTrue, kStunUsrName, kStunPwd); // STUN-UDP + tnet_ice_ctx_add_server(p_ice_ctx2, "tcp", kStunServerIP, 3478, kTurnTrue, kStunFalse, kStunUsrName, kStunPwd); // TURN-TCP #endif - if ((ret = tnet_ice_ctx_start(p_ice_ctx1))) { - goto bail; - } - // start ctx2 when we finish gathering ctx1's candidates - //if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) { - // goto bail; - //} - - getchar(); - - // ret = tnet_ice_ctx_stop(p_ice_ctx1); - // ret = tnet_ice_ctx_stop(p_ice_ctx2); + if ((ret = tnet_ice_ctx_start(p_ice_ctx1))) { + goto bail; + } + // start ctx2 when we finish gathering ctx1's candidates + //if ((ret = tnet_ice_ctx_start(p_ice_ctx2))) { + // goto bail; + //} + + getchar(); + + // ret = tnet_ice_ctx_stop(p_ice_ctx1); + // ret = tnet_ice_ctx_stop(p_ice_ctx2); bail: - TSK_OBJECT_SAFE_FREE(p_ice_ctx1); - TSK_OBJECT_SAFE_FREE(p_ice_ctx2); + TSK_OBJECT_SAFE_FREE(p_ice_ctx1); + TSK_OBJECT_SAFE_FREE(p_ice_ctx2); } diff --git a/tinyNET/test/test_ifaces.h b/tinyNET/test/test_ifaces.h index 2fd4e43..a1cf920 100755 --- a/tinyNET/test/test_ifaces.h +++ b/tinyNET/test/test_ifaces.h @@ -21,79 +21,73 @@ void test_faces_bestsource() { - tnet_ip_t source; + 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."); - } + 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."); - } + 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; + 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_list_foreach(item, ifaces) { + const tnet_interface_t *iface = item->data; + TSK_DEBUG_INFO("Interface: %s", iface->description); + } - TSK_OBJECT_SAFE_FREE(ifaces); + TSK_OBJECT_SAFE_FREE(ifaces); } void test_ifaces_dump_addresses() { - tnet_addresses_L_t* addresses = tnet_get_addresses_all(); - tsk_list_item_t *item; + 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_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); + TSK_OBJECT_SAFE_FREE(addresses); } void test_ifaces() { - test_faces_bestsource(); - test_ifaces_dump_ifaces(); - test_ifaces_dump_addresses(); + test_faces_bestsource(); + test_ifaces_dump_ifaces(); + test_ifaces_dump_addresses(); } #endif /* TNET_TEST_IFACES_H */ diff --git a/tinyNET/test/test_nat.h b/tinyNET/test/test_nat.h index 1a9bd68..c9723d0 100755 --- a/tinyNET/test/test_nat.h +++ b/tinyNET/test/test_nat.h @@ -27,55 +27,55 @@ void test_nat_stun() { - tnet_socket_t *socket1 = 0, *socket2 = 0; - struct tnet_nat_ctx_s *context = 0; + tnet_socket_t *socket1 = 0, *socket2 = 0; + struct tnet_nat_ctx_s *context = 0; - tnet_stun_binding_id_t bind_id1, bind_id2; + 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; - } + char* public_ip1 = 0, *public_ip2 = 0; + tnet_port_t public_port1 = 0, public_port2 = 0; - context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD); + 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; + } - if(tnet_nat_set_server_address(context, STUN_SERVER_IP)) { - TSK_DEBUG_ERROR("Failed to set STUN/TURN address."); - goto bail; - } + context = tnet_nat_context_create(STUN_SERVER_PROTO, STUN_USERNAME, STUN_PASSWORD); - // == BIND == // - bind_id1 = tnet_nat_stun_bind(context, socket1->fd); - bind_id2 = tnet_nat_stun_bind(context, socket2->fd); + if(tnet_nat_set_server_address(context, STUN_SERVER_IP)) { + TSK_DEBUG_ERROR("Failed to set STUN/TURN address."); + goto bail; + } - if(!bind_id1 || !bind_id2) { - TSK_DEBUG_ERROR("Failed to get public IP/port using stun"); - goto bail; - } + // == BIND == // + bind_id1 = tnet_nat_stun_bind(context, socket1->fd); + bind_id2 = tnet_nat_stun_bind(context, socket2->fd); - if (tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1) == 0) { - TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1); - } + if(!bind_id1 || !bind_id2) { + TSK_DEBUG_ERROR("Failed to get public IP/port using stun"); + goto bail; + } - if (tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2) == 0) { - TSK_DEBUG_INFO("Public IP2/Port2 ==> %s:%u", public_ip2, public_port2); - } + if (tnet_nat_stun_get_reflexive_address(context, bind_id1, &public_ip1, &public_port1) == 0) { + TSK_DEBUG_INFO("Public IP1/Port1 ==> %s:%u", public_ip1, public_port1); + } - // == UNBIND == // - tnet_nat_stun_unbind(context, bind_id1); - tnet_nat_stun_unbind(context, bind_id2); + if (tnet_nat_stun_get_reflexive_address(context, bind_id2, &public_ip2, &public_port2) == 0) { + 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_OBJECT_SAFE_FREE(socket1); + TSK_OBJECT_SAFE_FREE(socket2); - TSK_FREE(public_ip1); - TSK_FREE(public_ip1); + TSK_FREE(public_ip1); + TSK_FREE(public_ip1); - TSK_OBJECT_SAFE_FREE(context); + TSK_OBJECT_SAFE_FREE(context); } void test_nat_turn() @@ -90,7 +90,7 @@ void test_nat_turn() // 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))) // { @@ -201,9 +201,9 @@ void test_nat_turn() void test_nat() { - test_nat_stun(); - //test_nat_turn(); - //tsk_thread_sleep(1000); + test_nat_stun(); + //test_nat_turn(); + //tsk_thread_sleep(1000); } diff --git a/tinyNET/test/test_sockets.h b/tinyNET/test/test_sockets.h index 3edd1bd..857ce6b 100755 --- a/tinyNET/test/test_sockets.h +++ b/tinyNET/test/test_sockets.h @@ -21,41 +21,40 @@ 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); + 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 */ diff --git a/tinyNET/test/test_stun.h b/tinyNET/test/test_stun.h index 58fc9b1..cc9033b 100755 --- a/tinyNET/test/test_stun.h +++ b/tinyNET/test/test_stun.h @@ -65,79 +65,79 @@ static int test_stun_buff_cmp(const uint8_t* pc_buf1_ptr, tsk_size_t n_buff1_siz static void test_stun_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; - static const char __pc_username[] = "Mamadou DIOP"; - static const uint16_t __u_username = sizeof(__pc_username); - static const char __pc_integrity[TSK_SHA1_DIGEST_SIZE] = { 0 }; - static const uint16_t __u_integrity = sizeof(__pc_integrity); - static const uint32_t __u_fingerprint = 19831983; - static const uint8_t __u_error_class = 4; // (4 * 100) = 404 - static const uint8_t __u_error_number = 4; // + 4 = 404 - static const char* __pc_error_reason = "Not Found"; - tnet_stun_addr_t addr_ipv4, addr_ipv6; - static const char __pc_realm[] = "doubango.org"; - static const uint16_t __u_realm = sizeof(__pc_realm); - static const char __pc_nonce[128] = { 0 }; - static const uint16_t __u_nonce = sizeof(__pc_nonce); - static const char __pc_software[] = "tinyNET 2.0"; - static const uint16_t __u_software = sizeof(__pc_software); - static const uint32_t __u_life_time = 600; - static const uint32_t __u_req_transport = 17; // UDP + 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; + static const char __pc_username[] = "Mamadou DIOP"; + static const uint16_t __u_username = sizeof(__pc_username); + static const char __pc_integrity[TSK_SHA1_DIGEST_SIZE] = { 0 }; + static const uint16_t __u_integrity = sizeof(__pc_integrity); + static const uint32_t __u_fingerprint = 19831983; + static const uint8_t __u_error_class = 4; // (4 * 100) = 404 + static const uint8_t __u_error_number = 4; // + 4 = 404 + static const char* __pc_error_reason = "Not Found"; + tnet_stun_addr_t addr_ipv4, addr_ipv6; + static const char __pc_realm[] = "doubango.org"; + static const uint16_t __u_realm = sizeof(__pc_realm); + static const char __pc_nonce[128] = { 0 }; + static const uint16_t __u_nonce = sizeof(__pc_nonce); + static const char __pc_software[] = "tinyNET 2.0"; + static const uint16_t __u_software = sizeof(__pc_software); + static const uint32_t __u_life_time = 600; + static const uint32_t __u_req_transport = 17; // UDP (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_attrs_add(p_pkt, - TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4), - TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6), - TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4), - TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6), - TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(__pc_username), - TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_integrity, __u_integrity), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(__u_error_class, __u_error_number, __pc_error_reason), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_TRY_ALTERNATE(), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_BAD_REQUEST(), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNAUTHORIZED(), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNKNOWN_ATTRIBUTE(), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_STALE_NONCE(), - TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_SERVER_ERROR(), - TNET_STUN_PKT_ATTR_ADD_REALM_ZT(__pc_realm), - TNET_STUN_PKT_ATTR_ADD_NONCE(__pc_nonce, __u_nonce), - - TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS( - TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0001), // MAPPED-ADDRESS - TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0006), // USERNAME - TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0007), // PASSWORD - TNET_STUN_PKT_ATTR_ADD_NULL()), - - TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(__pc_software), - TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V4(__u_mapped_addr_port, &addr_ipv4), - TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V6(__u_mapped_addr_port, &addr_ipv6), - TNET_STUN_PKT_ATTR_ADD_LIFETIME(__u_life_time), - TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(__u_req_transport), - TNET_STUN_PKT_ATTR_ADD_DONT_FRAGMENT(), - - TNET_STUN_PKT_ATTR_ADD_FINGERPRINT(__u_fingerprint), - TNET_STUN_PKT_ATTR_ADD_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)); + 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_attrs_add(p_pkt, + TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4), + TNET_STUN_PKT_ATTR_ADD_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6), + TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V4(__u_mapped_addr_port, &addr_ipv4), + TNET_STUN_PKT_ATTR_ADD_XOR_MAPPED_ADDRESS_V6(__u_mapped_addr_port, &addr_ipv6), + TNET_STUN_PKT_ATTR_ADD_USERNAME_ZT(__pc_username), + TNET_STUN_PKT_ATTR_ADD_MESSAGE_INTEGRITY(__pc_integrity, __u_integrity), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE(__u_error_class, __u_error_number, __pc_error_reason), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_TRY_ALTERNATE(), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_BAD_REQUEST(), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNAUTHORIZED(), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_UNKNOWN_ATTRIBUTE(), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_STALE_NONCE(), + TNET_STUN_PKT_ATTR_ADD_ERROR_CODE_SERVER_ERROR(), + TNET_STUN_PKT_ATTR_ADD_REALM_ZT(__pc_realm), + TNET_STUN_PKT_ATTR_ADD_NONCE(__pc_nonce, __u_nonce), + + TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS( + TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0001), // MAPPED-ADDRESS + TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0006), // USERNAME + TNET_STUN_PKT_ATTR_ADD_UNKNOWN_ATTRS_VAL(0x0007), // PASSWORD + TNET_STUN_PKT_ATTR_ADD_NULL()), + + TNET_STUN_PKT_ATTR_ADD_SOFTWARE_ZT(__pc_software), + TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V4(__u_mapped_addr_port, &addr_ipv4), + TNET_STUN_PKT_ATTR_ADD_ALTERNATE_SERVER_V6(__u_mapped_addr_port, &addr_ipv6), + TNET_STUN_PKT_ATTR_ADD_LIFETIME(__u_life_time), + TNET_STUN_PKT_ATTR_ADD_REQUESTED_TRANSPORT(__u_req_transport), + TNET_STUN_PKT_ATTR_ADD_DONT_FRAGMENT(), + + TNET_STUN_PKT_ATTR_ADD_FINGERPRINT(__u_fingerprint), + TNET_STUN_PKT_ATTR_ADD_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_stun_parser...OK"); bail: - TSK_OBJECT_SAFE_FREE(p_pkt); + TSK_OBJECT_SAFE_FREE(p_pkt); } static struct tnet_turn_session_s* __pc_ss1 = tsk_null; @@ -153,103 +153,95 @@ static tnet_turn_peer_id_t __u_peer_id2 = kTurnPeerIdInvalid; static int _test_turn_session_callback(const struct tnet_turn_session_event_xs *e) { - const struct tnet_turn_session_s* pc_ss = (const struct tnet_turn_session_s*)e->pc_usr_data; - int ret = 0; - switch (e->e_type) { - case tnet_turn_session_event_type_alloc_ok: - { - uint16_t *pu_port = (pc_ss == __pc_ss2) ? &__u_rel_port_ss1 : &__u_rel_port_ss2; - char** pp_ip = (pc_ss == __pc_ss2) ? &__p_rel_ip_ss1 : &__p_rel_ip_ss2; - tsk_bool_t *pb_ipv6 = (pc_ss == __pc_ss2) ? &__b_rel_ipv6_ss1 : &__b_rel_ipv6_ss2; - tnet_turn_peer_id_t *pu_peer_id = (pc_ss == __pc_ss2) ? &__u_peer_id2 : &__u_peer_id1; - - BAIL_IF_ERR(tnet_turn_session_get_relayed_addr(pc_ss, pp_ip, pu_port, pb_ipv6)); - // BAIL_IF_ERR(tnet_turn_session_get_srflx_addr(pc_ss, pu_port, &u_port, &b_ipv6)); // get my own server reflexive address (in order to send data to myself) - BAIL_IF_ERR(tnet_turn_session_createpermission((struct tnet_turn_session_s*)pc_ss, *pp_ip, *pu_port, pu_peer_id)); // Input = ADDR(remote.candidate.relay) - break; - } - case tnet_turn_session_event_type_alloc_nok: - { - TSK_DEBUG_INFO("*** TURN ALLOC NOK ***"); - break; - } - case tnet_turn_session_event_type_perm_ok: - { - static const char __pc_data[] = { "TURN Sample Data (Send Indication)" }; - int i; - tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1; - // Bind a channel (not required). If succeed, will be used to save data. - tnet_turn_session_chanbind((struct tnet_turn_session_s*)pc_ss, u_peer_id); - // Send data (will use channel if one is active. Otherwise (no channel), SendIndications will be used) - for (i = 0; i < 10; ++i) { - BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data))); - } - break; - } - case tnet_turn_session_event_type_perm_nok: - { - TSK_DEBUG_INFO("*** TURN PERM NOK ***"); - break; - } - case tnet_turn_session_event_type_chanbind_ok: - { - static const char __pc_data[] = { "TURN Sample Data (ChannelData)" }; - int i; - tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1; - for (i = 0; i < 10; ++i) { - BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data))); - } - break; - } - case tnet_turn_session_event_type_chanbind_nok: - { - TSK_DEBUG_INFO("*** TURN CHANBIND NOK ***"); - break; - } - case tnet_turn_session_event_type_recv_data: - { - TSK_DEBUG_INFO("RECV DATA:%.*s", e->data.u_data_size, (const char*)e->data.pc_data_ptr); - break; - } - default: - { - break; - } - } + const struct tnet_turn_session_s* pc_ss = (const struct tnet_turn_session_s*)e->pc_usr_data; + int ret = 0; + switch (e->e_type) { + case tnet_turn_session_event_type_alloc_ok: { + uint16_t *pu_port = (pc_ss == __pc_ss2) ? &__u_rel_port_ss1 : &__u_rel_port_ss2; + char** pp_ip = (pc_ss == __pc_ss2) ? &__p_rel_ip_ss1 : &__p_rel_ip_ss2; + tsk_bool_t *pb_ipv6 = (pc_ss == __pc_ss2) ? &__b_rel_ipv6_ss1 : &__b_rel_ipv6_ss2; + tnet_turn_peer_id_t *pu_peer_id = (pc_ss == __pc_ss2) ? &__u_peer_id2 : &__u_peer_id1; + + BAIL_IF_ERR(tnet_turn_session_get_relayed_addr(pc_ss, pp_ip, pu_port, pb_ipv6)); + // BAIL_IF_ERR(tnet_turn_session_get_srflx_addr(pc_ss, pu_port, &u_port, &b_ipv6)); // get my own server reflexive address (in order to send data to myself) + BAIL_IF_ERR(tnet_turn_session_createpermission((struct tnet_turn_session_s*)pc_ss, *pp_ip, *pu_port, pu_peer_id)); // Input = ADDR(remote.candidate.relay) + break; + } + case tnet_turn_session_event_type_alloc_nok: { + TSK_DEBUG_INFO("*** TURN ALLOC NOK ***"); + break; + } + case tnet_turn_session_event_type_perm_ok: { + static const char __pc_data[] = { "TURN Sample Data (Send Indication)" }; + int i; + tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1; + // Bind a channel (not required). If succeed, will be used to save data. + tnet_turn_session_chanbind((struct tnet_turn_session_s*)pc_ss, u_peer_id); + // Send data (will use channel if one is active. Otherwise (no channel), SendIndications will be used) + for (i = 0; i < 10; ++i) { + BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data))); + } + break; + } + case tnet_turn_session_event_type_perm_nok: { + TSK_DEBUG_INFO("*** TURN PERM NOK ***"); + break; + } + case tnet_turn_session_event_type_chanbind_ok: { + static const char __pc_data[] = { "TURN Sample Data (ChannelData)" }; + int i; + tnet_turn_peer_id_t u_peer_id = (pc_ss == __pc_ss2) ? __u_peer_id2 : __u_peer_id1; + for (i = 0; i < 10; ++i) { + BAIL_IF_ERR(tnet_turn_session_send_data((struct tnet_turn_session_s*)pc_ss, u_peer_id, __pc_data, sizeof(__pc_data))); + } + break; + } + case tnet_turn_session_event_type_chanbind_nok: { + TSK_DEBUG_INFO("*** TURN CHANBIND NOK ***"); + break; + } + case tnet_turn_session_event_type_recv_data: { + TSK_DEBUG_INFO("RECV DATA:%.*s", e->data.u_data_size, (const char*)e->data.pc_data_ptr); + break; + } + default: { + break; + } + } bail: - return ret; + return ret; } static void test_turn_session() { - BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss1)); - BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss1, _test_turn_session_callback, __pc_ss1)); - BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss1, kStunUsrName, kStunPwd)); - BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss1)); - BAIL_IF_ERR(tnet_turn_session_start(__pc_ss1)); + BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss1)); + BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss1, _test_turn_session_callback, __pc_ss1)); + BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss1, kStunUsrName, kStunPwd)); + BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss1)); + BAIL_IF_ERR(tnet_turn_session_start(__pc_ss1)); - BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss2)); - BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss2, _test_turn_session_callback, __pc_ss2)); - BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss2, kStunUsrName, kStunPwd)); - BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss2)); - BAIL_IF_ERR(tnet_turn_session_start(__pc_ss2)); + BAIL_IF_ERR(tnet_turn_session_create_udp_ipv4(tnet_turn_transport_udp, kStunServerIP, kStunServerPort, &__pc_ss2)); + BAIL_IF_ERR(tnet_turn_session_set_callback(__pc_ss2, _test_turn_session_callback, __pc_ss2)); + BAIL_IF_ERR(tnet_turn_session_set_cred(__pc_ss2, kStunUsrName, kStunPwd)); + BAIL_IF_ERR(tnet_turn_session_prepare(__pc_ss2)); + BAIL_IF_ERR(tnet_turn_session_start(__pc_ss2)); - BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss1)); - BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss2)); + BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss1)); + BAIL_IF_ERR(tnet_turn_session_allocate(__pc_ss2)); - TSK_DEBUG_INFO("*** Press ENTER to continue ***"); - getchar(); + TSK_DEBUG_INFO("*** Press ENTER to continue ***"); + getchar(); bail: - TSK_OBJECT_SAFE_FREE(__pc_ss1); - TSK_OBJECT_SAFE_FREE(__pc_ss2); + TSK_OBJECT_SAFE_FREE(__pc_ss1); + TSK_OBJECT_SAFE_FREE(__pc_ss2); } static void test_stun() { - //test_stun_parser(); - test_turn_session(); + //test_stun_parser(); + test_turn_session(); } #endif /* TNET_TEST_STUN_H */ diff --git a/tinyNET/test/test_tls.h b/tinyNET/test/test_tls.h index 48ae865..5b1661e 100755 --- a/tinyNET/test/test_tls.h +++ b/tinyNET/test/test_tls.h @@ -36,69 +36,66 @@ 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; + 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); + 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 */ diff --git a/tinyNET/test/test_transport.h b/tinyNET/test/test_transport.h index b52b554..0384546 100755 --- a/tinyNET/test/test_transport.h +++ b/tinyNET/test/test_transport.h @@ -53,133 +53,129 @@ 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; + 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; + 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); - } - + //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; + //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() @@ -189,27 +185,27 @@ void test_transport() #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); + 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 + 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); + tsk_thread_sleep(1000000); //#else - getchar(); + getchar(); //#endif #if TEST_UDP - TSK_OBJECT_SAFE_FREE(udp); + TSK_OBJECT_SAFE_FREE(udp); #endif #if TEST_TCP - TSK_OBJECT_SAFE_FREE(tcp); + TSK_OBJECT_SAFE_FREE(tcp); #endif } |