Commit 383e9404 authored by Max Lv's avatar Max Lv

Run tun2socks in seprate process for now

parent 16d2cd9a
......@@ -23,6 +23,7 @@ local.sbt
out/
#NDK
src/main/obj
src/main/libs
src/main/assets/armeabi
src/main/assets/armeabi-v7a
......
......@@ -18,5 +18,6 @@ install:
- echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
script:
- cp local.properties.travis local.properties
- ./build.sh
- sbt android:package-release
- exit 0
......@@ -28,6 +28,9 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
```bash
git submodule update --init
# Build native binaries
./build.sh
# Build the App
sbt clean android:package-release
......@@ -47,6 +50,9 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
```bash
git submodule update --init
# Build native binaries
./build.sh
# Build the apk
sbt clean android:package-release
```
......
......@@ -15,7 +15,7 @@ rm -rf assets/armeabi-v7a
rm -rf assets/x86
mkdir -p assets/armeabi-v7a
mkdir -p assets/x86
for app in pdnsd redsocks ss-local ss-tunnel tun2socks
for app in pdnsd redsocks ss-local ss-tunnel
do
try mv libs/armeabi-v7a/$app assets/armeabi-v7a/
try mv libs/x86/$app assets/x86/
......
......@@ -2,4 +2,6 @@ resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifact
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.3.10")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
resolvers += Resolver.sbtPluginRepo("snapshots")
addSbtPlugin("com.hanhuy.sbt" % "sbt-idea" % "1.7.0-SNAPSHOT")
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.shadowsocks"
android:versionCode="84"
android:versionName="2.4.4">
android:versionCode="85"
android:versionName="2.4.5">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
......@@ -18,7 +18,6 @@
<application
android:allowBackup="true"
android:debuggable="true"
android:name=".ShadowsocksApplication"
android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher"
......
......@@ -40,7 +40,7 @@ package com.github.shadowsocks;
public class Tun2Socks {
static {
java.lang.System.loadLibrary("tun2socks-jni");
java.lang.System.loadLibrary("tun2socks");
}
public static native void start(String[] cmd);
......
......@@ -214,7 +214,7 @@ LOCAL_CFLAGS += -DBADVPN_THREADWORK_USE_PTHREAD -DBADVPN_LINUX -DBADVPN_BREACTOR
LOCAL_CFLAGS += -DBADVPN_USE_SELFPIPE -DBADVPN_USE_EPOLL
LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN -DBADVPN_THREAD_SAFE
LOCAL_CFLAGS += -DNDEBUG -DANDROID
#LOCAL_CFLAGS += -DTUN2SOCKS_JNI
LOCAL_CFLAGS += -DTUN2SOCKS_JNI
LOCAL_C_INCLUDES:= \
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv4 \
......@@ -288,9 +288,9 @@ LOCAL_MODULE := tun2socks
LOCAL_LDLIBS := -ldl -llog
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES))
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES)) tun2socks-jni.cpp
include $(BUILD_EXECUTABLE)
include $(BUILD_SHARED_LIBRARY)
# OpenSSL
openssl_subdirs := $(addprefix $(LOCAL_PATH)/openssl/,$(addsuffix /Android.mk, \
......
......@@ -2,7 +2,7 @@
* 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
......@@ -13,7 +13,7 @@
* 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
......@@ -183,8 +183,6 @@ sock_fd_write(int sock, void *buf, ssize_t buflen, int fd)
size = sendmsg(sock, &msg, 0);
if (size < 0)
perror ("sendmsg");
return size;
}
......@@ -213,7 +211,6 @@ sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd)
msg.msg_controllen = sizeof(cmsgu.control);
size = recvmsg (sock, &msg, 0);
if (size < 0) {
perror ("recvmsg");
return -1;
}
cmsg = CMSG_FIRSTHDR(&msg);
......@@ -450,7 +447,7 @@ static void daemonize(const char* path) {
/* Change the file mode mask */
umask(0);
/* Open any logs here */
/* Open any logs here */
/* Create a new SID for the child process */
sid = setsid();
......@@ -474,10 +471,9 @@ static void daemonize(const char* path) {
int
recv_tun_fd (void)
{
int s_fd, c_fd, fd_to_read;
int s_fd, fd_to_read;
struct sockaddr_un addr;
socklen_t addr_len;
char buf[16];
s_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (s_fd < 0) {
......@@ -490,42 +486,25 @@ recv_tun_fd (void)
addr_len = sizeof(struct sockaddr_un);
memset(&addr, 0, addr_len);
addr.sun_family = AF_UNIX;
snprintf(addr.sun_path + 1, 14, "tun2socks");
addr.sun_path[0] = '\0';
strcpy(addr.sun_path+1, "tun2socks");
if (bind(s_fd, (struct sockaddr *) &addr, addr_len) != 0)
if (connect(s_fd, (struct sockaddr *)&addr, addr_len) != -1)
{
BLog(BLOG_ERROR, "Error to bind local socket");
close(s_fd);
return -1;
}
char buf[16];
BLog(BLOG_NOTICE, "Bind socket");
BLog(BLOG_NOTICE, "Connected");
if (listen(s_fd, 5) != 0)
{
BLog(BLOG_ERROR, "Error to listen on local socket");
close(s_fd);
return -1;
}
BLog(BLOG_NOTICE, "Listen on socket");
if ((c_fd = accept(s_fd, (struct sockaddr *)&addr, &addr_len)) != -1)
{
char buf[1];
BLog(BLOG_NOTICE, "Accept a connection");
read(c_fd, buf, 1);
sock_fd_read(c_fd, buf, sizeof(buf), &fd_to_read);
read(s_fd, buf, 1);
sock_fd_read(s_fd, buf, sizeof(buf), &fd_to_read);
buf[0] = 0;
write(c_fd, buf, 1);
close(c_fd);
write(s_fd, buf, 1);
close(s_fd);
}
else
{
BLog(BLOG_ERROR, "Error to accept socket");
BLog(BLOG_ERROR, "Error to connect: %s", strerror(errno));
close(s_fd);
return -1;
}
......@@ -543,17 +522,17 @@ int main (int argc, char **argv)
if (argc <= 0) {
return 1;
}
// open standard streams
open_standard_streams();
// parse command-line arguments
if (!parse_arguments(argc, argv)) {
fprintf(stderr, "Failed to parse arguments\n");
print_help(argv[0]);
goto fail0;
}
// handle --help and --version
if (options.help) {
print_version();
......@@ -581,7 +560,7 @@ int main (int argc, char **argv)
default:
ASSERT(0);
}
// configure logger channels
for (int i = 0; i < BLOG_NUM_CHANNELS; i++) {
if (options.loglevels[i] >= 0) {
......@@ -598,52 +577,41 @@ int main (int argc, char **argv)
if (options.pid) {
daemonize(options.pid);
}
BLog(BLOG_NOTICE, "Receiving the tun fd");
// Wait to recevie tun fd
if (recv_tun_fd() == -1) {
BLog(BLOG_ERROR, "Failed to recv tun fd");
return -1;
}
BLog(BLOG_NOTICE, "Received the tun fd successfully");
#endif
// clear password contents pointer
password_file_contents = NULL;
// initialize network
if (!BNetwork_GlobalInit()) {
BLog(BLOG_ERROR, "BNetwork_GlobalInit failed");
goto fail1;
}
// process arguments
if (!process_arguments()) {
BLog(BLOG_ERROR, "Failed to process arguments");
goto fail1;
}
// init time
BTime_Init();
// init reactor
if (!BReactor_Init(&ss)) {
BLog(BLOG_ERROR, "BReactor_Init failed");
goto fail1;
}
// set not quitting
quitting = 0;
// setup signal handler
if (!BSignal_Init(&ss, signal_handler, NULL)) {
BLog(BLOG_ERROR, "BSignal_Init failed");
goto fail2;
}
#ifdef ANDROID
// use supplied file descriptor
......@@ -652,7 +620,7 @@ int main (int argc, char **argv)
init_data.init_type = BTAP_INIT_FD;
init_data.init.fd.fd = options.tun_fd;
init_data.init.fd.mtu = options.tun_mtu;
if (!BTap_Init2(&device, &ss, init_data, device_error_handler, NULL)) {
BLog(BLOG_ERROR, "BTap_Init2 failed");
goto fail3;
......@@ -664,19 +632,19 @@ int main (int argc, char **argv)
goto fail3;
}
#endif
// NOTE: the order of the following is important:
// first device writing must evaluate,
// then lwip (so it can send packets to the device),
// then device reading (so it can pass received packets to lwip).
// init device reading
PacketPassInterface_Init(&device_read_interface, BTap_GetMTU(&device), device_read_handler_send, NULL, BReactor_PendingGroup(&ss));
if (!SinglePacketBuffer_Init(&device_read_buffer, BTap_GetOutput(&device), &device_read_interface, BReactor_PendingGroup(&ss))) {
BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
goto fail4;
}
if (options.udpgw_remote_server_addr) {
// compute maximum UDP payload size we need to pass through udpgw
udp_mtu = BTap_GetMTU(&device) - (int)(sizeof(struct ipv4_header) + sizeof(struct udp_header));
......@@ -689,14 +657,14 @@ int main (int argc, char **argv)
if (udp_mtu < 0) {
udp_mtu = 0;
}
// make sure our UDP payloads aren't too large for udpgw
int udpgw_mtu = udpgw_compute_mtu(udp_mtu);
if (udpgw_mtu < 0 || udpgw_mtu > PACKETPROTO_MAXPAYLOAD) {
BLog(BLOG_ERROR, "device MTU is too large for UDP");
goto fail4a;
}
// init udpgw client
if (!SocksUdpGwClient_Init(&udpgw_client, udp_mtu, DEFAULT_UDPGW_MAX_CONNECTIONS, options.udpgw_connection_buffer_size, UDPGW_KEEPALIVE_TIME,
socks_server_addr, socks_auth_info, socks_num_auth_info,
......@@ -706,46 +674,46 @@ int main (int argc, char **argv)
goto fail4a;
}
}
// init lwip init job
BPending_Init(&lwip_init_job, BReactor_PendingGroup(&ss), lwip_init_job_hadler, NULL);
BPending_Set(&lwip_init_job);
// init device write buffer
if (!(device_write_buf = (uint8_t *)BAlloc(BTap_GetMTU(&device)))) {
BLog(BLOG_ERROR, "BAlloc failed");
goto fail5;
}
// init TCP timer
// it won't trigger before lwip is initialized, becuase the lwip init is a job
BTimer_Init(&tcp_timer, TCP_TMR_INTERVAL, tcp_timer_handler, NULL);
BReactor_SetTimer(&ss, &tcp_timer);
// set no netif
have_netif = 0;
// set no listener
listener = NULL;
listener_ip6 = NULL;
// init clients list
LinkedList1_Init(&tcp_clients);
// init number of clients
num_clients = 0;
// enter event loop
BLog(BLOG_NOTICE, "entering event loop");
BReactor_Exec(&ss);
// free clients
LinkedList1Node *node;
while (node = LinkedList1_GetFirst(&tcp_clients)) {
struct tcp_client *client = UPPER_OBJECT(node, struct tcp_client, list_node);
client_murder(client);
}
// free listener
if (listener_ip6) {
tcp_close(listener_ip6);
......@@ -753,22 +721,23 @@ int main (int argc, char **argv)
if (listener) {
tcp_close(listener);
}
// free netif
if (have_netif) {
netif_remove(&netif);
}
BReactor_RemoveTimer(&ss, &tcp_timer);
BFree(device_write_buf);
#ifdef ANDROID
BLog(BLOG_NOTICE, "Free TCP connections");
tcp_remove(tcp_bound_pcbs);
tcp_remove(tcp_active_pcbs);
tcp_remove(tcp_tw_pcbs);
free_connections();
#endif
BReactor_RemoveTimer(&ss, &tcp_timer);
BFree(device_write_buf);
fail5:
BPending_Free(&lwip_init_job);
if (options.udpgw_remote_server_addr) {
......@@ -789,19 +758,19 @@ fail1:
BLog_Free();
fail0:
DebugObjectGlobal_Finish();
return 1;
}
void terminate (void)
{
ASSERT(!quitting)
BLog(BLOG_NOTICE, "tearing down");
// set quitting
quitting = 1;
// exit event loop
BReactor_Quit(&ss, 1);
}
......@@ -862,7 +831,7 @@ int parse_arguments (int argc, char *argv[])
if (argc <= 0) {
return 0;
}
options.help = 0;
options.version = 0;
options.logger = LOGGER_STDOUT;
......@@ -893,7 +862,7 @@ int parse_arguments (int argc, char *argv[])
options.udpgw_max_connections = DEFAULT_UDPGW_MAX_CONNECTIONS;
options.udpgw_connection_buffer_size = DEFAULT_UDPGW_CONNECTION_BUFFER_SIZE;
options.udpgw_transparent_dns = 0;
int i;
for (i = 1; i < argc; i++) {
char *arg = argv[i];
......@@ -1078,7 +1047,7 @@ int parse_arguments (int argc, char *argv[])
else if (!strcmp(arg, "--append-source-to-username")) {
options.append_source_to_username = 1;
}
#ifdef ANDROID
#ifdef ANDROID
else if (!strcmp(arg, "--enable-udprelay")) {
options.udpgw_remote_server_addr = "0.0.0.0:0";
#else
......@@ -1127,38 +1096,38 @@ int parse_arguments (int argc, char *argv[])
return 0;
}
}
if (options.help || options.version) {
return 1;
}
if (!options.netif_ipaddr) {
fprintf(stderr, "--netif-ipaddr is required\n");
return 0;
}
if (!options.netif_netmask) {
fprintf(stderr, "--netif-netmask is required\n");
return 0;
}
if (!options.socks_server_addr) {
fprintf(stderr, "--socks-server-addr is required\n");
return 0;
}
if (options.username) {
if (!options.password && !options.password_file) {
fprintf(stderr, "username given but password not given\n");
return 0;
}
if (options.password && options.password_file) {
fprintf(stderr, "--password and --password-file cannot both be given\n");
return 0;
}
}
return 1;
}
......@@ -1175,7 +1144,7 @@ int process_arguments (void)
BLog(BLOG_ERROR, "netif ipaddr: must be an IPv4 address");
return 0;
}
// resolve netif netmask
if (!BIPAddr_Resolve(&netif_netmask, options.netif_netmask, 0)) {
BLog(BLOG_ERROR, "netif netmask: BIPAddr_Resolve failed");
......@@ -1185,7 +1154,7 @@ int process_arguments (void)
BLog(BLOG_ERROR, "netif netmask: must be an IPv4 address");
return 0;
}
// parse IP6 address
if (options.netif_ip6addr) {
if (!ipaddr6_parse_ipv6_addr(options.netif_ip6addr, &netif_ip6addr)) {
......@@ -1193,17 +1162,17 @@ int process_arguments (void)
return 0;
}
}
// resolve SOCKS server address
if (!BAddr_Parse2(&socks_server_addr, options.socks_server_addr, NULL, 0, 0)) {
BLog(BLOG_ERROR, "socks server addr: BAddr_Parse2 failed");
return 0;
}
// add none socks authentication method
socks_auth_info[0] = BSocksClient_auth_none();
socks_num_auth_info = 1;
// add password socks authentication method
if (options.username) {
const char *password;
......@@ -1218,13 +1187,13 @@ int process_arguments (void)
}
password = (char *)password_file_contents;
}
socks_auth_info[socks_num_auth_info++] = BSocksClient_auth_password(
options.username, strlen(options.username),
password, password_len
);
}
// resolve remote udpgw server address
if (options.udpgw_remote_server_addr) {
if (!BAddr_Parse2(&udpgw_remote_server_addr, options.udpgw_remote_server_addr, NULL, 0, 0)) {
......@@ -1250,16 +1219,16 @@ int process_arguments (void)
}
}
#endif
return 1;
}
void signal_handler (void *unused)
{
ASSERT(!quitting)
BLog(BLOG_NOTICE, "termination requested");
terminate();
}
......@@ -1282,15 +1251,15 @@ void lwip_init_job_hadler (void *unused)
ASSERT(!have_netif)
ASSERT(!listener)
ASSERT(!listener_ip6)
BLog(BLOG_DEBUG, "lwip init");
// NOTE: the device may fail during this, but there's no harm in not checking
// for that at every step
// init lwip
lwip_init();
// make addresses for netif
ip_addr_t addr;
addr.addr = netif_ipaddr.ipv4;
......@@ -1298,77 +1267,77 @@ void lwip_init_job_hadler (void *unused)
netmask.addr = netif_netmask.ipv4;
ip_addr_t gw;
ip_addr_set_any(&gw);
// init netif
if (!netif_add(&netif, &addr, &netmask, &gw, NULL, netif_init_func, netif_input_func)) {
BLog(BLOG_ERROR, "netif_add failed");
goto fail;
}
have_netif = 1;
// set netif up
netif_set_up(&netif);
// set netif pretend TCP
netif_set_pretend_tcp(&netif, 1);
// set netif default
netif_set_default(&netif);
if (options.netif_ip6addr) {
// add IPv6 address
memcpy(netif_ip6_addr(&netif, 0), netif_ip6addr.bytes, sizeof(netif_ip6addr.bytes));
netif_ip6_addr_set_state(&netif, 0, IP6_ADDR_VALID);
}
// init listener
struct tcp_pcb *l = tcp_new();
if (!l) {
BLog(BLOG_ERROR, "tcp_new failed");
goto fail;
}
// bind listener
if (tcp_bind_to_netif(l, "ho0") != ERR_OK) {
BLog(BLOG_ERROR, "tcp_bind_to_netif failed");
tcp_close(l);
goto fail;
}
// listen listener
if (!(listener = tcp_listen(l))) {
BLog(BLOG_ERROR, "tcp_listen failed");
tcp_close(l);
goto fail;
}
// setup listener accept handler
tcp_accept(listener, listener_accept_func);
if (options.netif_ip6addr) {
struct tcp_pcb *l_ip6 = tcp_new_ip6();
if (!l_ip6) {
BLog(BLOG_ERROR, "tcp_new_ip6 failed");
goto fail;
}
if (tcp_bind_to_netif(l_ip6, "ho0") != ERR_OK) {
BLog(BLOG_ERROR, "tcp_bind_to_netif failed");
tcp_close(l_ip6);
goto fail;
}
if (!(listener_ip6 = tcp_listen(l_ip6))) {
BLog(BLOG_ERROR, "tcp_listen failed");
tcp_close(l_ip6);
goto fail;
}
tcp_accept(listener_ip6, listener_accept_func);
}
return;
fail:
if (!quitting) {
terminate();
......@@ -1378,13 +1347,13 @@ fail:
void tcp_timer_handler (void *unused)
{
ASSERT(!quitting)
BLog(BLOG_DEBUG, "TCP timer");
// schedule next timer
// TODO: calculate timeout so we don't drift
BReactor_SetTimer(&ss, &tcp_timer);
tcp_tmr();
return;
}
......@@ -1392,9 +1361,9 @@ void tcp_timer_handler (void *unused)
void device_error_handler (void *unused)
{
ASSERT(!quitting)
BLog(BLOG_ERROR, "device error");
terminate();
return;
}
......@@ -1403,9 +1372,9 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
{
ASSERT(!quitting)
ASSERT(data_len >= 0)
BLog(BLOG_DEBUG, "device: received packet");
// accept packet
PacketPassInterface_Done(&device_read_interface);
......@@ -1415,12 +1384,12 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
return;
}
#endif
// process UDP directly
if (process_device_udp_packet(data, data_len)) {
return;
}
// obtain pbuf
if (data_len > UINT16_MAX) {
BLog(BLOG_WARNING, "device read: packet too large");
......@@ -1431,10 +1400,10 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
BLog(BLOG_WARNING, "device read: pbuf_alloc failed");
return;
}
// write packet to pbuf
ASSERT_FORCE(pbuf_take(p, data, data_len) == ERR_OK)
// pass pbuf to input
if (netif.input(p, &netif) != ERR_OK) {
BLog(BLOG_WARNING, "device read: input failed");
......@@ -1446,42 +1415,42 @@ void device_read_handler_send (void *unused, uint8_t *data, int data_len)
int process_device_dns_packet (uint8_t *data, int data_len)
{
ASSERT(data_len >= 0)
// do nothing if we don't have dnsgw
if (!options.dnsgw) {
goto fail;
}
static int init = 0;
int to_dns;
int from_dns;
int packet_length = 0;
uint8_t ip_version = 0;
if (data_len > 0) {
ip_version = (data[0] >> 4);
}
switch (ip_version) {
case 4: {
// ignore non-UDP packets
if (data_len < sizeof(struct ipv4_header) || data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) {
goto fail;
}
// parse IPv4 header
struct ipv4_header ipv4_header;
if (!ipv4_check(data, data_len, &ipv4_header, &data, &data_len)) {
goto fail;
}
// parse UDP
struct udp_header udp_header;
if (!udp_check(data, data_len, &udp_header, &data, &data_len)) {
goto fail;
}
// verify UDP checksum
uint16_t checksum_in_packet = udp_header.checksum;
udp_header.checksum = 0;
......@@ -1550,7 +1519,7 @@ int process_device_dns_packet (uint8_t *data, int data_len)
goto fail;
}
}
// update IPv4 header's checksum
ipv4_header.checksum = hton16(0);
ipv4_header.checksum = ipv4_checksum(&ipv4_header, NULL, 0);
......@@ -1567,22 +1536,22 @@ int process_device_dns_packet (uint8_t *data, int data_len)
packet_length = sizeof(ipv4_header) + sizeof(udp_header) + data_len;
} break;
case 6: {
// TODO: support IPv6 DNS Gateway
goto fail;
} break;
default: {
goto fail;
} break;
}
// submit packet
BTap_Send(&device, device_write_buf, packet_length);
return 1;
fail:
return 0;
}
......@@ -1591,40 +1560,40 @@ fail:
int process_device_udp_packet (uint8_t *data, int data_len)
{
ASSERT(data_len >= 0)
// do nothing if we don't have udpgw
if (!options.udpgw_remote_server_addr) {
goto fail;
}
BAddr local_addr;
BAddr remote_addr;
int is_dns;
uint8_t ip_version = 0;
if (data_len > 0) {
ip_version = (data[0] >> 4);
}
switch (ip_version) {
case 4: {
// ignore non-UDP packets
if (data_len < sizeof(struct ipv4_header) || data[offsetof(struct ipv4_header, protocol)] != IPV4_PROTOCOL_UDP) {
goto fail;
}
// parse IPv4 header
struct ipv4_header ipv4_header;
if (!ipv4_check(data, data_len, &ipv4_header, &data, &data_len)) {
goto fail;
}
// parse UDP
struct udp_header udp_header;
if (!udp_check(data, data_len, &udp_header, &data, &data_len)) {
goto fail;
}
// verify UDP checksum
uint16_t checksum_in_packet = udp_header.checksum;
udp_header.checksum = 0;
......@@ -1632,43 +1601,43 @@ int process_device_udp_packet (uint8_t *data, int data_len)
if (checksum_in_packet != checksum_computed) {
goto fail;
}
BLog(BLOG_INFO, "UDP: from device %d bytes", data_len);
// construct addresses
BAddr_InitIPv4(&local_addr, ipv4_header.source_address, udp_header.source_port);
BAddr_InitIPv4(&remote_addr, ipv4_header.destination_address, udp_header.dest_port);
// if transparent DNS is enabled, any packet arriving at out netif
// address to port 53 is considered a DNS packet
is_dns = (options.udpgw_transparent_dns &&
ipv4_header.destination_address == netif_ipaddr.ipv4 &&
udp_header.dest_port == hton16(53));
} break;
case 6: {
// ignore if IPv6 support is disabled
if (!options.netif_ip6addr) {
goto fail;
}
// ignore non-UDP packets
if (data_len < sizeof(struct ipv6_header) || data[offsetof(struct ipv6_header, next_header)] != IPV6_NEXT_UDP) {
goto fail;
}
// parse IPv6 header
struct ipv6_header ipv6_header;
if (!ipv6_check(data, data_len, &ipv6_header, &data, &data_len)) {
goto fail;
}
// parse UDP
struct udp_header udp_header;
if (!udp_check(data, data_len, &udp_header, &data, &data_len)) {
goto fail;
}
// verify UDP checksum
uint16_t checksum_in_packet = udp_header.checksum;
udp_header.checksum = 0;
......@@ -1676,33 +1645,33 @@ int process_device_udp_packet (uint8_t *data, int data_len)
if (checksum_in_packet != checksum_computed) {
goto fail;
}
BLog(BLOG_INFO, "UDP/IPv6: from device %d bytes", data_len);
// construct addresses
BAddr_InitIPv6(&local_addr, ipv6_header.source_address, udp_header.source_port);
BAddr_InitIPv6(&remote_addr, ipv6_header.destination_address, udp_header.dest_port);
// TODO dns
is_dns = 0;
} break;
default: {
goto fail;
} break;
}
// check payload length
if (data_len > udp_mtu) {
BLog(BLOG_ERROR, "packet is too large, cannot send to udpgw");
goto fail;
}
// submit packet to udpgw
SocksUdpGwClient_SubmitPacket(&udpgw_client, local_addr, remote_addr, is_dns, data, data_len);
return 1;
fail:
return 0;
}
......@@ -1710,12 +1679,12 @@ fail:
err_t netif_init_func (struct netif *netif)
{
BLog(BLOG_DEBUG, "netif func init");
netif->name[0] = 'h';
netif->name[1] = 'o';
netif->output = netif_output_func;
netif->output_ip6 = netif_output_ip6_func;
return ERR_OK;
}
......@@ -1732,20 +1701,20 @@ err_t netif_output_ip6_func (struct netif *netif, struct pbuf *p, ip6_addr_t *ip
err_t common_netif_output (struct netif *netif, struct pbuf *p)
{
SYNC_DECL
BLog(BLOG_DEBUG, "device write: send packet");
if (quitting) {
return ERR_OK;
}
// if there is just one chunk, send it directly, else via buffer
if (!p->next) {
if (p->len > BTap_GetMTU(&device)) {
BLog(BLOG_WARNING, "netif func output: no space left");
goto out;
}
SYNC_FROMHERE
BTap_Send(&device, (uint8_t *)p->payload, p->len);
SYNC_COMMIT
......@@ -1759,12 +1728,12 @@ err_t common_netif_output (struct netif *netif, struct pbuf *p)
memcpy(device_write_buf + len, p->payload, p->len);
len += p->len;
} while (p = p->next);
SYNC_FROMHERE
BTap_Send(&device, device_write_buf, len);
SYNC_COMMIT
}
out:
return ERR_OK;
}
......@@ -1775,7 +1744,7 @@ err_t netif_input_func (struct pbuf *p, struct netif *inp)
if (p->len > 0) {
ip_version = (((uint8_t *)p->payload)[0] >> 4);
}
switch (ip_version) {
case 4: {
return ip_input(p, inp);
......@@ -1786,7 +1755,7 @@ err_t netif_input_func (struct pbuf *p, struct netif *inp)
}
} break;
}
pbuf_free(p);
return ERR_OK;
}
......@@ -1797,7 +1766,7 @@ void client_logfunc (struct tcp_client *client)
BAddr_Print(&client->local_addr, local_addr_s);
char remote_addr_s[BADDR_MAX_PRINT_LEN];
BAddr_Print(&client->remote_addr, remote_addr_s);
BLog_Append("%05d (%s %s): ", num_clients, local_addr_s, remote_addr_s);
}
......@@ -1812,11 +1781,11 @@ void client_log (struct tcp_client *client, int level, const char *fmt, ...)
err_t listener_accept_func (void *arg, struct tcp_pcb *newpcb, err_t err)
{
ASSERT(err == ERR_OK)
// signal accepted
struct tcp_pcb *this_listener = (PCB_ISIPV6(newpcb) ? listener_ip6 : listener);
tcp_accepted(this_listener);
// allocate client structure
struct tcp_client *client = (struct tcp_client *)malloc(sizeof(*client));
if (!client) {
......@@ -1824,20 +1793,20 @@ err_t listener_accept_func (void *arg, struct tcp_pcb *newpcb, err_t err)
goto fail0;
}
client->socks_username = NULL;
SYNC_DECL
SYNC_FROMHERE
// read addresses
client->local_addr = baddr_from_lwip(PCB_ISIPV6(newpcb), &newpcb->local_ip, newpcb->local_port);
client->remote_addr = baddr_from_lwip(PCB_ISIPV6(newpcb), &newpcb->remote_ip, newpcb->remote_port);
// get destination address
BAddr addr = client->local_addr;
#ifdef OVERRIDE_DEST_ADDR
ASSERT_FORCE(BAddr_Parse2(&addr, OVERRIDE_DEST_ADDR, NULL, 0, 1))
#endif
// add source address to username if requested
if (options.username && options.append_source_to_username) {
char addr_str[BADDR_MAX_PRINT_LEN];
......@@ -1849,56 +1818,56 @@ err_t listener_accept_func (void *arg, struct tcp_pcb *newpcb, err_t err)
socks_auth_info[1].password.username = client->socks_username;
socks_auth_info[1].password.username_len = strlen(client->socks_username);
}
// init SOCKS
if (!BSocksClient_Init(&client->socks_client, socks_server_addr, socks_auth_info, socks_num_auth_info,
addr, (BSocksClient_handler)client_socks_handler, client, &ss)) {
BLog(BLOG_ERROR, "listener accept: BSocksClient_Init failed");
goto fail1;
}
// init dead vars
DEAD_INIT(client->dead);
DEAD_INIT(client->dead_client);
// add to linked list
LinkedList1_Append(&tcp_clients, &client->list_node);
// increment counter
ASSERT(num_clients >= 0)
num_clients++;
// set pcb
client->pcb = newpcb;
// set client not closed
client->client_closed = 0;
// setup handler argument
tcp_arg(client->pcb, client);
// setup handlers
tcp_err(client->pcb, client_err_func);
tcp_recv(client->pcb, client_recv_func);
// setup buffer
client->buf_used = 0;
// set SOCKS not up, not closed
client->socks_up = 0;
client->socks_closed = 0;
client_log(client, BLOG_INFO, "accepted");
DEAD_ENTER(client->dead_client)
SYNC_COMMIT
DEAD_LEAVE2(client->dead_client)
if (DEAD_KILLED) {
return ERR_ABRT;
}
return ERR_OK;
fail1:
SYNC_BREAK
free(client->socks_username);
......@@ -1910,15 +1879,15 @@ fail0:
void client_handle_freed_client (struct tcp_client *client)
{
ASSERT(!client->client_closed)
// pcb was taken care of by the caller
// kill client dead var
DEAD_KILL(client->dead_client);
// set client closed
client->client_closed = 1;
// if we have data to be sent to SOCKS and can send it, keep sending
if (client->buf_used > 0 && !client->socks_closed) {
client_log(client, BLOG_INFO, "waiting untill buffered data is sent to SOCKS");
......@@ -1934,41 +1903,41 @@ void client_handle_freed_client (struct tcp_client *client)
void client_free_client (struct tcp_client *client)
{
ASSERT(!client->client_closed)
// remove callbacks
tcp_err(client->pcb, NULL);
tcp_recv(client->pcb, NULL);
tcp_sent(client->pcb, NULL);
// free pcb
err_t err = tcp_close(client->pcb);
if (err != ERR_OK) {
client_log(client, BLOG_ERROR, "tcp_close failed (%d)", err);
tcp_abort(client->pcb);
}
client_handle_freed_client(client);
}
void client_abort_client (struct tcp_client *client)
{
ASSERT(!client->client_closed)
// remove callbacks
tcp_err(client->pcb, NULL);
tcp_recv(client->pcb, NULL);
tcp_sent(client->pcb, NULL);
// free pcb
tcp_abort(client->pcb);
client_handle_freed_client(client);
}
void client_free_socks (struct tcp_client *client)
{
ASSERT(!client->socks_closed)
// stop sending to SOCKS
if (client->socks_up) {
// stop receiving from client
......@@ -1976,13 +1945,13 @@ void client_free_socks (struct tcp_client *client)
tcp_recv(client->pcb, NULL);
}
}
// free SOCKS
BSocksClient_Free(&client->socks_client);
// set SOCKS closed
client->socks_closed = 1;
// if we have data to be sent to the client and we can send it, keep sending
if (client->socks_up && (client->socks_recv_buf_used >= 0 || client->socks_recv_tcp_pending > 0) && !client->client_closed) {
client_log(client, BLOG_INFO, "waiting until buffered data is sent to client");
......@@ -2003,26 +1972,26 @@ void client_murder (struct tcp_client *client)
tcp_err(client->pcb, NULL);
tcp_recv(client->pcb, NULL);
tcp_sent(client->pcb, NULL);
// abort
tcp_abort(client->pcb);
// kill client dead var
DEAD_KILL(client->dead_client);
// set client closed
client->client_closed = 1;
}
// free SOCKS
if (!client->socks_closed) {
// free SOCKS
BSocksClient_Free(&client->socks_client);
// set SOCKS closed
client->socks_closed = 1;
}
// dealloc entry
client_dealloc(client);
}
......@@ -2031,17 +2000,17 @@ void client_dealloc (struct tcp_client *client)
{
ASSERT(client->client_closed)
ASSERT(client->socks_closed)
// decrement counter
ASSERT(num_clients > 0)
num_clients--;
// remove client entry
LinkedList1_Remove(&tcp_clients, &client->list_node);
// kill dead var
DEAD_KILL(client->dead);
// free memory
free(client->socks_username);
free(client);
......@@ -2051,9 +2020,9 @@ void client_err_func (void *arg, err_t err)
{
struct tcp_client *client = (struct tcp_client *)arg;
ASSERT(!client->client_closed)
client_log(client, BLOG_INFO, "client error (%d)", (int)err);
// the pcb was taken care of by the caller
client_handle_freed_client(client);
}
......@@ -2064,29 +2033,29 @@ err_t client_recv_func (void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t e
ASSERT(!client->client_closed)
ASSERT(err == ERR_OK) // checked in lwIP source. Otherwise, I've no idea what should
// be done with the pbuf in case of an error.
if (!p) {
client_log(client, BLOG_INFO, "client closed");
client_free_client(client);
return ERR_ABRT;
}
ASSERT(p->tot_len > 0)
// check if we have enough buffer
if (p->tot_len > sizeof(client->buf) - client->buf_used) {
client_log(client, BLOG_ERROR, "no buffer for data !?!");
return ERR_MEM;
}
// copy data to buffer
ASSERT_EXECUTE(pbuf_copy_partial(p, client->buf + client->buf_used, p->tot_len, 0) == p->tot_len)
client->buf_used += p->tot_len;
// if there was nothing in the buffer before, and SOCKS is up, start send data
if (client->buf_used == p->tot_len && client->socks_up) {
ASSERT(!client->socks_closed) // this callback is removed when SOCKS is closed
SYNC_DECL
SYNC_FROMHERE
client_send_to_socks(client);
......@@ -2097,33 +2066,33 @@ err_t client_recv_func (void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t e
return ERR_ABRT;
}
}
// free pbuff
pbuf_free(p);
return ERR_OK;
}
void client_socks_handler (struct tcp_client *client, int event)
{
ASSERT(!client->socks_closed)
switch (event) {
case BSOCKSCLIENT_EVENT_ERROR: {
client_log(client, BLOG_INFO, "SOCKS error");
client_free_socks(client);
} break;
case BSOCKSCLIENT_EVENT_UP: {
ASSERT(!client->socks_up)
client_log(client, BLOG_INFO, "SOCKS up");
// init sending
client->socks_send_if = BSocksClient_GetSendInterface(&client->socks_client);
StreamPassInterface_Sender_Init(client->socks_send_if, (StreamPassInterface_handler_done)client_socks_send_handler_done, client);
// init receiving
client->socks_recv_if = BSocksClient_GetRecvInterface(&client->socks_client);
StreamRecvInterface_Receiver_Init(client->socks_recv_if, (StreamRecvInterface_handler_done)client_socks_recv_handler_done, client);
......@@ -2132,29 +2101,29 @@ void client_socks_handler (struct tcp_client *client, int event)
if (!client->client_closed) {
tcp_sent(client->pcb, client_sent_func);
}
// set up
client->socks_up = 1;
// start sending data if there is any
if (client->buf_used > 0) {
client_send_to_socks(client);
}
// start receiving data if client is still up
if (!client->client_closed) {
client_socks_recv_initiate(client);
}
} break;
case BSOCKSCLIENT_EVENT_ERROR_CLOSED: {
ASSERT(client->socks_up)
client_log(client, BLOG_INFO, "SOCKS closed");
client_free_socks(client);
} break;
default:
ASSERT(0);
}
......@@ -2165,7 +2134,7 @@ void client_send_to_socks (struct tcp_client *client)
ASSERT(!client->socks_closed)
ASSERT(client->socks_up)
ASSERT(client->buf_used > 0)
// schedule sending
StreamPassInterface_Sender_Send(client->socks_send_if, client->buf, client->buf_used);
}
......@@ -2177,16 +2146,16 @@ void client_socks_send_handler_done (struct tcp_client *client, int data_len)
ASSERT(client->buf_used > 0)
ASSERT(data_len > 0)
ASSERT(data_len <= client->buf_used)
// remove sent data from buffer
memmove(client->buf, client->buf + data_len, client->buf_used - data_len);
client->buf_used -= data_len;
if (!client->client_closed) {
// confirm sent data
tcp_recved(client->pcb, data_len);
}
if (client->buf_used > 0) {
// send any further data
StreamPassInterface_Sender_Send(client->socks_send_if, client->buf, client->buf_used);
......@@ -2194,7 +2163,7 @@ void client_socks_send_handler_done (struct tcp_client *client, int data_len)
else if (client->client_closed) {
// client was closed we've sent everything we had buffered; we're done with it
client_log(client, BLOG_INFO, "removing after client went down");
client_free_socks(client);
}
}
......@@ -2205,7 +2174,7 @@ void client_socks_recv_initiate (struct tcp_client *client)
ASSERT(!client->socks_closed)
ASSERT(client->socks_up)
ASSERT(client->socks_recv_buf_used == -1)
StreamRecvInterface_Receiver_Recv(client->socks_recv_if, client->socks_recv_buf, sizeof(client->socks_recv_buf));
}
......@@ -2216,22 +2185,22 @@ void client_socks_recv_handler_done (struct tcp_client *client, int data_len)
ASSERT(!client->socks_closed)
ASSERT(client->socks_up)
ASSERT(client->socks_recv_buf_used == -1)
// if client was closed, stop receiving
if (client->client_closed) {
return;
}
// set amount of data in buffer
client->socks_recv_buf_used = data_len;
client->socks_recv_buf_sent = 0;
client->socks_recv_waiting = 0;
// send to client
if (client_socks_recv_send_out(client) < 0) {
return;
}
// continue receiving if needed
if (client->socks_recv_buf_used == -1) {
client_socks_recv_initiate(client);
......@@ -2245,89 +2214,89 @@ int client_socks_recv_send_out (struct tcp_client *client)
ASSERT(client->socks_recv_buf_used > 0)
ASSERT(client->socks_recv_buf_sent < client->socks_recv_buf_used)
ASSERT(!client->socks_recv_waiting)
// return value -1 means tcp_abort() was done,
// 0 means it wasn't and the client (pcb) is still up
do {
int to_write = bmin_int(client->socks_recv_buf_used - client->socks_recv_buf_sent, tcp_sndbuf(client->pcb));
if (to_write == 0) {
break;
}
err_t err = tcp_write(client->pcb, client->socks_recv_buf + client->socks_recv_buf_sent, to_write, TCP_WRITE_FLAG_COPY);
if (err != ERR_OK) {
if (err == ERR_MEM) {
break;
}
client_log(client, BLOG_INFO, "tcp_write failed (%d)", (int)err);
client_abort_client(client);
return -1;
}
client->socks_recv_buf_sent += to_write;
client->socks_recv_tcp_pending += to_write;
} while (client->socks_recv_buf_sent < client->socks_recv_buf_used);
// start sending now
err_t err = tcp_output(client->pcb);
if (err != ERR_OK) {
client_log(client, BLOG_INFO, "tcp_output failed (%d)", (int)err);
client_abort_client(client);
return -1;
}
// more data to queue?
if (client->socks_recv_buf_sent < client->socks_recv_buf_used) {
if (client->socks_recv_tcp_pending == 0) {
client_log(client, BLOG_ERROR, "can't queue data, but all data was confirmed !?!");
client_abort_client(client);
return -1;
}
// set waiting, continue in client_sent_func
client->socks_recv_waiting = 1;
return 0;
}
// everything was queued
client->socks_recv_buf_used = -1;
return 0;
}
err_t client_sent_func (void *arg, struct tcp_pcb *tpcb, u16_t len)
{
struct tcp_client *client = (struct tcp_client *)arg;
ASSERT(!client->client_closed)
ASSERT(client->socks_up)
ASSERT(len > 0)
ASSERT(len <= client->socks_recv_tcp_pending)
// decrement pending
client->socks_recv_tcp_pending -= len;
// continue queuing
if (client->socks_recv_buf_used > 0) {
ASSERT(client->socks_recv_waiting)
ASSERT(client->socks_recv_buf_sent < client->socks_recv_buf_used)
// set not waiting
client->socks_recv_waiting = 0;
// possibly send more data
if (client_socks_recv_send_out(client) < 0) {
return ERR_ABRT;
}
// we just queued some data, so it can't have been confirmed yet
ASSERT(client->socks_recv_tcp_pending > 0)
// continue receiving if needed
if (client->socks_recv_buf_used == -1 && !client->socks_closed) {
SYNC_DECL
......@@ -2340,17 +2309,17 @@ err_t client_sent_func (void *arg, struct tcp_pcb *tpcb, u16_t len)
return ERR_ABRT;
}
}
return ERR_OK;
}
// have we sent everything after SOCKS was closed?
if (client->socks_closed && client->socks_recv_tcp_pending == 0) {
client_log(client, BLOG_INFO, "removing after SOCKS went down");
client_free_client(client);
return ERR_ABRT;
}
return ERR_OK;
}
......@@ -2360,9 +2329,9 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
ASSERT(local_addr.type == BADDR_TYPE_IPV4 || local_addr.type == BADDR_TYPE_IPV6)
ASSERT(local_addr.type == remote_addr.type)
ASSERT(data_len >= 0)
int packet_length = 0;
switch (local_addr.type) {
case BADDR_TYPE_IPV4: {
#ifdef ANDROID
......@@ -2370,14 +2339,14 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
#else
BLog(BLOG_INFO, "UDP: from udpgw %d bytes", data_len);
#endif
if (data_len > UINT16_MAX - (sizeof(struct ipv4_header) + sizeof(struct udp_header)) ||
data_len > BTap_GetMTU(&device) - (int)(sizeof(struct ipv4_header) + sizeof(struct udp_header))
) {
BLog(BLOG_ERROR, "UDP: packet is too large");
return;
}
// build IP header
struct ipv4_header iph;
iph.version4_ihl4 = IPV4_MAKE_VERSION_IHL(sizeof(iph));
......@@ -2391,7 +2360,7 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
iph.source_address = remote_addr.ipv4.ip;
iph.destination_address = local_addr.ipv4.ip;
iph.checksum = ipv4_checksum(&iph, NULL, 0);
// build UDP header
struct udp_header udph;
udph.source_port = remote_addr.ipv4.port;
......@@ -2399,21 +2368,21 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
udph.length = hton16(sizeof(udph) + data_len);
udph.checksum = hton16(0);
udph.checksum = udp_checksum(&udph, data, data_len, iph.source_address, iph.destination_address);
// write packet
memcpy(device_write_buf, &iph, sizeof(iph));
memcpy(device_write_buf + sizeof(iph), &udph, sizeof(udph));
memcpy(device_write_buf + sizeof(iph) + sizeof(udph), data, data_len);
packet_length = sizeof(iph) + sizeof(udph) + data_len;
} break;
case BADDR_TYPE_IPV6: {
#ifdef ANDROID
BLog(BLOG_INFO, "UDP/IPv6: from udprelay %d bytes", data_len);
#else
BLog(BLOG_INFO, "UDP/IPv6: from udpgw %d bytes", data_len);
#endif
if (!options.netif_ip6addr) {
#ifdef ANDROID
BLog(BLOG_ERROR, "got IPv6 packet from udprelay but IPv6 is disabled");
......@@ -2422,14 +2391,14 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
#endif
return;
}
if (data_len > UINT16_MAX - sizeof(struct udp_header) ||
data_len > BTap_GetMTU(&device) - (int)(sizeof(struct ipv6_header) + sizeof(struct udp_header))
) {
BLog(BLOG_ERROR, "UDP/IPv6: packet is too large");
return;
}
// build IPv6 header
struct ipv6_header iph;
iph.version4_tc4 = hton8((6 << 4));
......@@ -2440,7 +2409,7 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
iph.hop_limit = hton8(64);
memcpy(iph.source_address, remote_addr.ipv6.ip, 16);
memcpy(iph.destination_address, local_addr.ipv6.ip, 16);
// build UDP header
struct udp_header udph;
udph.source_port = remote_addr.ipv6.port;
......@@ -2448,7 +2417,7 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
udph.length = hton16(sizeof(udph) + data_len);
udph.checksum = hton16(0);
udph.checksum = udp_ip6_checksum(&udph, data, data_len, iph.source_address, iph.destination_address);
// write packet
memcpy(device_write_buf, &iph, sizeof(iph));
memcpy(device_write_buf + sizeof(iph), &udph, sizeof(udph));
......@@ -2456,7 +2425,7 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
packet_length = sizeof(iph) + sizeof(udph) + data_len;
} break;
}
// submit packet
BTap_Send(&device, device_write_buf, packet_length);
}
......@@ -123,7 +123,7 @@ object Shadowsocks {
val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps,
Key.isUdpDns, Key.isAutoConnect)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, Executable.TUN2SOCKS)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL)
// Helper functions
def updateListPreference(pref: Preference, value: String) {
......
......@@ -45,7 +45,7 @@ import java.net.InetAddress
import android.app._
import android.content._
import android.content.pm.{PackageInfo, PackageManager}
import android.net.{VpnService, LocalSocket, LocalSocketAddress}
import android.net.{LocalServerSocket, VpnService, LocalSocket, LocalSocketAddress}
import android.os._
import android.support.v4.app.NotificationCompat
import android.util.Log
......@@ -322,23 +322,25 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runCommand(cmd)
Tun2Socks.start(cmd.split(" "))
}
Thread.sleep(300)
// try {
val localSocket = new LocalSocket()
localSocket.setFileDescriptorsForSend(Array(conn.getFileDescriptor))
val localAddr = new LocalSocketAddress("tun2socks")
localSocket.connect(localAddr)
val output = localSocket.getOutputStream
output.write(1)
output.flush()
output.close()
localSocket.close()
// } catch {
// case ex: Exception => // Ignored
// }
def startTunFdServer() {
spawn {
val fdServer = new LocalServerSocket("tun2socks")
try {
val localSocket = fdServer.accept()
localSocket.setFileDescriptorsForSend(Array(conn.getFileDescriptor))
val output = localSocket.getOutputStream
output.write(1)
output.flush()
output.close()
localSocket.close()
fdServer.close()
} catch {
case ex: Exception => Log.e(TAG, "Exception", ex) // Ignored
}
}
}
/** Called when the activity is first created. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment