Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
383e9404
Commit
383e9404
authored
Nov 24, 2014
by
Max Lv
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Run tun2socks in seprate process for now
parent
16d2cd9a
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
298 additions
and
318 deletions
+298
-318
.gitignore
.gitignore
+1
-0
.travis.yml
.travis.yml
+1
-0
README.md
README.md
+6
-0
build.sh
build.sh
+1
-1
project/plugins.sbt
project/plugins.sbt
+3
-1
src/main/AndroidManifest.xml
src/main/AndroidManifest.xml
+2
-3
src/main/java/com/github/shadowsocks/Tun2Socks.java
src/main/java/com/github/shadowsocks/Tun2Socks.java
+1
-1
src/main/jni/Android.mk
src/main/jni/Android.mk
+3
-3
src/main/jni/badvpn/tun2socks/tun2socks.c
src/main/jni/badvpn/tun2socks/tun2socks.c
+260
-291
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+1
-1
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
.../scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+19
-17
No files found.
.gitignore
View file @
383e9404
...
...
@@ -23,6 +23,7 @@ local.sbt
out/
#NDK
src/main/obj
src/main/libs
src/main/assets/armeabi
src/main/assets/armeabi-v7a
...
...
.travis.yml
View file @
383e9404
...
...
@@ -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
README.md
View file @
383e9404
...
...
@@ -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
```
...
...
build.sh
View file @
383e9404
...
...
@@ -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/
...
...
project/plugins.sbt
View file @
383e9404
...
...
@@ -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"
)
src/main/AndroidManifest.xml
View file @
383e9404
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.github.shadowsocks"
android:versionCode=
"8
4
"
android:versionName=
"2.4.
4
"
>
android:versionCode=
"8
5
"
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"
...
...
src/main/java/com/github/shadowsocks/Tun2Socks.java
View file @
383e9404
...
...
@@ -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
);
...
...
src/main/jni/Android.mk
View file @
383e9404
...
...
@@ -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,
\
...
...
src/main/jni/badvpn/tun2socks/tun2socks.c
View file @
383e9404
...
...
@@ -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
);
}
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
View file @
383e9404
...
...
@@ -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
)
{
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
View file @
383e9404
...
...
@@ -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. */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment