LeOS-Genesis/external/badvpn/tun2socks/SocksUdpGwClient.c

229 lines
7.3 KiB
C

/*
* Copyright (C) Ambroz Bizjak <ambrop7@gmail.com>
* Contributions:
* Transparent DNS: Copyright (C) Kerem Hadimli <kerem.hadimli@gmail.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <misc/debug.h>
#include <base/BLog.h>
#include <tun2socks/SocksUdpGwClient.h>
#include <generated/blog_channel_SocksUdpGwClient.h>
static void free_socks (SocksUdpGwClient *o);
static void try_connect (SocksUdpGwClient *o);
static void reconnect_timer_handler (SocksUdpGwClient *o);
static void socks_client_handler (SocksUdpGwClient *o, int event);
static void udpgw_handler_servererror (SocksUdpGwClient *o);
static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len);
static void free_socks (SocksUdpGwClient *o)
{
ASSERT(o->have_socks)
// disconnect udpgw client from SOCKS
if (o->socks_up) {
UdpGwClient_DisconnectServer(&o->udpgw_client);
}
// free SOCKS client
BSocksClient_Free(&o->socks_client);
// set have no SOCKS
o->have_socks = 0;
}
static void try_connect (SocksUdpGwClient *o)
{
ASSERT(!o->have_socks)
ASSERT(!BTimer_IsRunning(&o->reconnect_timer))
// init SOCKS client
if (!BSocksClient_Init(&o->socks_client, o->socks_server_addr, o->auth_info, o->num_auth_info, o->remote_udpgw_addr, (BSocksClient_handler)socks_client_handler, o, o->reactor)) {
BLog(BLOG_ERROR, "BSocksClient_Init failed");
goto fail0;
}
// set have SOCKS
o->have_socks = 1;
// set SOCKS not up
o->socks_up = 0;
return;
fail0:
// set reconnect timer
BReactor_SetTimer(o->reactor, &o->reconnect_timer);
}
static void reconnect_timer_handler (SocksUdpGwClient *o)
{
DebugObject_Access(&o->d_obj);
ASSERT(!o->have_socks)
// try connecting
try_connect(o);
}
static void socks_client_handler (SocksUdpGwClient *o, int event)
{
DebugObject_Access(&o->d_obj);
ASSERT(o->have_socks)
switch (event) {
case BSOCKSCLIENT_EVENT_UP: {
ASSERT(!o->socks_up)
BLog(BLOG_INFO, "SOCKS up");
// connect udpgw client to SOCKS
if (!UdpGwClient_ConnectServer(&o->udpgw_client, BSocksClient_GetSendInterface(&o->socks_client), BSocksClient_GetRecvInterface(&o->socks_client))) {
BLog(BLOG_ERROR, "UdpGwClient_ConnectServer failed");
goto fail0;
}
// set SOCKS up
o->socks_up = 1;
return;
fail0:
// free SOCKS
free_socks(o);
// set reconnect timer
BReactor_SetTimer(o->reactor, &o->reconnect_timer);
} break;
case BSOCKSCLIENT_EVENT_ERROR:
case BSOCKSCLIENT_EVENT_ERROR_CLOSED: {
BLog(BLOG_INFO, "SOCKS error");
// free SOCKS
free_socks(o);
// set reconnect timer
BReactor_SetTimer(o->reactor, &o->reconnect_timer);
} break;
default: ASSERT(0);
}
}
static void udpgw_handler_servererror (SocksUdpGwClient *o)
{
DebugObject_Access(&o->d_obj);
ASSERT(o->have_socks)
ASSERT(o->socks_up)
BLog(BLOG_ERROR, "client reports server error");
// free SOCKS
free_socks(o);
// set reconnect timer
BReactor_SetTimer(o->reactor, &o->reconnect_timer);
}
static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len)
{
DebugObject_Access(&o->d_obj);
// submit to user
o->handler_received(o->user, local_addr, remote_addr, data, data_len);
return;
}
int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections, int send_buffer_size, btime_t keepalive_time,
BAddr socks_server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info,
BAddr remote_udpgw_addr, btime_t reconnect_time, BReactor *reactor, void *user,
SocksUdpGwClient_handler_received handler_received)
{
// see asserts in UdpGwClient_Init
ASSERT(!BAddr_IsInvalid(&socks_server_addr))
ASSERT(remote_udpgw_addr.type == BADDR_TYPE_IPV4 || remote_udpgw_addr.type == BADDR_TYPE_IPV6)
// init arguments
o->udp_mtu = udp_mtu;
o->socks_server_addr = socks_server_addr;
o->auth_info = auth_info;
o->num_auth_info = num_auth_info;
o->remote_udpgw_addr = remote_udpgw_addr;
o->reactor = reactor;
o->user = user;
o->handler_received = handler_received;
// init udpgw client
if (!UdpGwClient_Init(&o->udpgw_client, udp_mtu, max_connections, send_buffer_size, keepalive_time, o->reactor, o,
(UdpGwClient_handler_servererror)udpgw_handler_servererror,
(UdpGwClient_handler_received)udpgw_handler_received
)) {
goto fail0;
}
// init reconnect timer
BTimer_Init(&o->reconnect_timer, reconnect_time, (BTimer_handler)reconnect_timer_handler, o);
// set have no SOCKS
o->have_socks = 0;
// try connecting
try_connect(o);
DebugObject_Init(&o->d_obj);
return 1;
fail0:
return 0;
}
void SocksUdpGwClient_Free (SocksUdpGwClient *o)
{
DebugObject_Free(&o->d_obj);
// free SOCKS
if (o->have_socks) {
free_socks(o);
}
// free reconnect timer
BReactor_RemoveTimer(o->reactor, &o->reconnect_timer);
// free udpgw client
UdpGwClient_Free(&o->udpgw_client);
}
void SocksUdpGwClient_SubmitPacket (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, int is_dns, const uint8_t *data, int data_len)
{
DebugObject_Access(&o->d_obj);
// see asserts in UdpGwClient_SubmitPacket
// submit to udpgw client
UdpGwClient_SubmitPacket(&o->udpgw_client, local_addr, remote_addr, is_dns, data, data_len);
}