Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
bannedbook committed Jun 16, 2020
1 parent 210d01c commit f8a72e8
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 78 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ buildscript {
junitVersion = '4.13'
androidTestVersion = '1.2.0'
androidEspressoVersion = '3.2.0'
versionCode = 5000908
versionName = '5.1.14-nightly'
versionCode = 5000918
versionName = '5.1.15-nightly'
resConfigs = ['ar', 'es', 'fa', 'fr', 'ja', 'ko', 'ru', 'tr', 'zh-rCN', 'zh-rTW']
}

Expand Down
6 changes: 6 additions & 0 deletions core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
android:directBootAware="true"
android:exported="false">
</service>
<service
android:name="com.github.shadowsocks.bg.V2RayProxyService"
android:process=":bg"
android:directBootAware="true"
android:exported="false">
</service>
<service
android:name="com.github.shadowsocks.bg.ProxyTestService"
android:process=":bg"
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/com/github/shadowsocks/Core.kt
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ object Core {
else NotificationManager.IMPORTANCE_LOW), // #1355
NotificationChannel("service-proxy", app.getText(R.string.service_proxy),
NotificationManager.IMPORTANCE_LOW),
NotificationChannel("service-v2proxy", app.getText(R.string.service_proxy),
NotificationManager.IMPORTANCE_LOW),
NotificationChannel("service-transproxy", app.getText(R.string.service_transproxy),
NotificationManager.IMPORTANCE_LOW),
SubscriptionService.notificationChannel))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class VpnRequestActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (DataStore.serviceMode != Key.modeVpn && DataStore.serviceMode != Key.v2rayVpn) {
if (DataStore.serviceMode != Key.modeVpn) {
finish()
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ class ShadowsocksConnection(private val handler: Handler = Handler(),
ServiceConnection, IBinder.DeathRecipient {
companion object {
val serviceClass get() = when (DataStore.serviceMode) {
Key.v2rayVpn -> V2RayVpnService::class
Key.modeProxy -> ProxyService::class
Key.modeVpn -> VpnService::class
Key.modeTransproxy -> TransproxyService::class
Key.modeProxy -> if (DataStore.serviceVmess) V2RayProxyService::class else ProxyService::class
Key.modeVpn -> if (DataStore.serviceVmess) V2RayVpnService::class else VpnService::class
Key.modeTransproxy -> if (DataStore.serviceVmess) V2RayVpnService::class else TransproxyService::class
else -> throw UnknownError()
}.java
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/github/shadowsocks/bg/Executable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ object Executable {
const val REDSOCKS = "libredsocks.so"
const val SS_LOCAL = "libss-local.so"
const val TUN2SOCKS = "libtun2socks.so"
const val POLIPO = "libpolipo.so"
//const val POLIPO = "libpolipo.so"

private val EXECUTABLES = setOf(SS_LOCAL, REDSOCKS, TUN2SOCKS,POLIPO)
private val EXECUTABLES = setOf(SS_LOCAL, REDSOCKS, TUN2SOCKS)

fun killAll() {
for (process in File("/proc").listFiles { _, name -> TextUtils.isDigitsOnly(name) } ?: return) {
Expand Down
9 changes: 7 additions & 2 deletions core/src/main/java/com/github/shadowsocks/bg/ProxyService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import java.io.*
* Shadowsocks service at its minimum.
*/
open class ProxyService : Service(), BaseService.Interface {
companion object {
var polipoThread : Thread? = null
}
override val data = BaseService.Data(this)
override val tag: String get() = "ShadowsocksProxyService"
override fun createNotification(profileName: String): ServiceNotification =
Expand Down Expand Up @@ -60,8 +63,10 @@ open class ProxyService : Service(), BaseService.Interface {

val file = File(configFile)
if (!file.exists()) copyAssets(confFilename, toPath)

Thread(Runnable { NativeCall.execPolipo(configFile) }).start()
if (polipoThread==null) {
polipoThread = Thread(Runnable { NativeCall.execPolipo(configFile) })
polipoThread?.start()
}
}

private fun copyAssets(configFile: String, toPath: String) {
Expand Down
33 changes: 11 additions & 22 deletions core/src/main/java/com/github/shadowsocks/bg/ProxyTestService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,31 @@
package com.github.shadowsocks.bg

import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.github.shadowsocks.BootReceiver
import com.github.shadowsocks.Core
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.bg.BaseService.Interface
import com.github.shadowsocks.core.R
import com.github.shadowsocks.net.HostsFile
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.printLog
import com.github.shadowsocks.utils.readableMessage
import kotlinx.coroutines.*
import java.io.IOException
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.net.UnknownHostException

/**
* Shadowsocks service at its minimum.
*/
class ProxyTestService : ProxyService(), Interface {
class ProxyTestService : ProxyService() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int{
val data = data
if (data.state != BaseService.State.Stopped) return Service.START_NOT_STICKY
val profilePair = Core.currentProfile
this as Context
if (profilePair == null) {
// gracefully shutdown: https://stackoverflow.com/q/47337857/2245107
stopRunner(false, getString(R.string.profile_empty))
Expand All @@ -57,7 +55,7 @@ class ProxyTestService : ProxyService(), Interface {
profile.name = profile.formattedName // save name for later queries
val proxy = ProxyInstance(profile)
data.proxy = proxy
data.udpFallback = if (fallback == null) null else ProxyInstance(fallback, profile.route)
data.udpFallback = null

BootReceiver.enabled = DataStore.persistAcrossReboot
if (!data.closeReceiverRegistered) {
Expand All @@ -75,25 +73,14 @@ class ProxyTestService : ProxyService(), Interface {
preInit()
val hosts = HostsFile(DataStore.publicStore.getString(Key.hosts) ?: "")
proxy.init(this@ProxyTestService, hosts)
data.udpFallback?.init(this@ProxyTestService, hosts)
if (profile.route == Acl.CUSTOM_RULES) try {
withContext(Dispatchers.IO) {
Acl.customRules.flatten(10, this@ProxyTestService::openConnection).also {
Acl.save(Acl.CUSTOM_RULES, it)
}
}
} catch (e: IOException) {
throw BaseService.ExpectedExceptionWrapper(e)
}

data.processes = GuardedProcessPool {
printLog(it)
stopRunner(false, it.readableMessage)
}
startProcesses(hosts)

proxy.scheduleUpdate()
data.udpFallback?.scheduleUpdate()
//proxy.scheduleUpdate()
//data.udpFallback?.scheduleUpdate()

data.changeState(BaseService.State.Connected)
} catch (_: CancellationException) {
Expand All @@ -110,7 +97,9 @@ class ProxyTestService : ProxyService(), Interface {
return Service.START_NOT_STICKY
}
override fun startRunner() {
this as Context
startService(Intent(this, javaClass))
}
override fun onCreate() {
if (polipoThread==null)super.onCreate()
}
}
213 changes: 213 additions & 0 deletions core/src/main/java/com/github/shadowsocks/bg/V2RayProxyService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package com.github.shadowsocks.bg
import SpeedUpVPN.VpnEncrypt
import android.app.Service
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.ParcelFileDescriptor
import android.os.StrictMode
import android.util.Log
import com.github.shadowsocks.BootReceiver
import com.github.shadowsocks.Core.defaultDPreference
import com.github.shadowsocks.core.R
import com.github.shadowsocks.database.AppConfig
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Action
import com.github.shadowsocks.utils.packagePath
import com.github.shadowsocks.utils.printLog
import com.github.shadowsocks.utils.readableMessage
import go.Seq
import kotlinx.coroutines.*
import libv2ray.Libv2ray
import libv2ray.V2RayVPNServiceSupportsSet
import java.net.UnknownHostException

class V2RayProxyService : Service() , BaseService.Interface {
//for BaseService.Interface start
override val data = BaseService.Data(this)
override val tag: String get() = "SSV2Service"
override fun createNotification(profileName: String): ServiceNotification =
ServiceNotification(this, profileName, "service-v2proxy", true)
override fun onBind(intent: Intent) = super.onBind(intent)
//for BaseService.Interface stop

private val v2rayPoint = Libv2ray.newV2RayPoint(V2RayCallback())
private lateinit var configContent: String
private lateinit var mInterface: ParcelFileDescriptor
private var listeningForDefaultNetwork = false
lateinit var activeProfile: Profile
override fun onCreate() {
super.onCreate()
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
StrictMode.setThreadPolicy(policy)
v2rayPoint.packageName = packagePath(applicationContext)
Seq.setContext(applicationContext)
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
data.connectingJob = GlobalScope.launch(Dispatchers.Main) {
try {
activeProfile = ProfileManager.getProfile(DataStore.profileId)!!
val proxy = V2ProxyInstance(v2rayPoint,activeProfile,activeProfile.route)
data.proxy = proxy
ProfileManager.genStoreV2rayConfig(activeProfile)
startV2ray()
} catch (_: CancellationException) {
// if the job was cancelled, it is canceller's responsibility to call stopRunner
} catch (_: UnknownHostException) {
stopRunner(false, getString(R.string.invalid_server))
} catch (exc: Throwable) {
if (exc is BaseService.ExpectedException) exc.printStackTrace() else printLog(exc)
stopRunner(false, "${getString(R.string.service_failed)}: ${exc.readableMessage}")
} finally {
data.connectingJob = null
}
}
return START_NOT_STICKY
stopRunner()
return Service.START_NOT_STICKY
}

override fun onLowMemory() {
stopV2Ray()
super.onLowMemory()
}

override fun onDestroy() {
super.onDestroy()
data.binder.close()
//android.os.Process.killProcess(android.os.Process.myPid())
}

fun shutdown() {
stopV2Ray(true)
}

private fun startV2ray() {
if (!v2rayPoint.isRunning) {
val broadname="$packageName.SERVICE"
if (!data.closeReceiverRegistered) {
registerReceiver(data.closeReceiver, IntentFilter().apply {
addAction(Action.RELOAD)
addAction(Intent.ACTION_SHUTDOWN)
addAction(Action.CLOSE)
}, broadname, null)
data.closeReceiverRegistered = true
}
data.notification = createNotification(activeProfile.formattedName)
data.changeState(BaseService.State.Connecting)

configContent = defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG, "")
v2rayPoint.configureFileContent = configContent
v2rayPoint.enableLocalDNS = VpnEncrypt.enableLocalDns
v2rayPoint.forwardIpv6 = activeProfile.ipv6
v2rayPoint.domainName = defaultDPreference.getPrefString(AppConfig.PREF_CURR_CONFIG_DOMAIN, "")

try {
v2rayPoint.runLoop()
} catch (e: Exception) {
Log.d(packageName, e.toString())
}

if (v2rayPoint.isRunning) {
data.changeState(BaseService.State.Connected)
} else {
//MessageUtil.sendMsg2UI(this, AppConfig.MSG_STATE_START_FAILURE, "")
//cancelNotification()
}
}
else{
Log.e("startV2ray","v2rayPoint isRunning already.")
}
}
override fun stopRunner(restart: Boolean , msg: String? ) {
Log.e("v2stopRunner",msg.toString())
if (data.state == BaseService.State.Stopping) return
// channge the state
data.changeState(BaseService.State.Stopping)
GlobalScope.launch(Dispatchers.Main.immediate) {
data.connectingJob?.cancelAndJoin() // ensure stop connecting first
// clean up receivers
val data = data
if (data.closeReceiverRegistered) {
unregisterReceiver(data.closeReceiver)
data.closeReceiverRegistered = false
}
data.notification?.destroy()
data.notification = null
stopV2Ray()
val ids = listOfNotNull(data.proxy, data.udpFallback).map {
it.shutdown(this)
it.profile.id
}
data.binder.trafficPersisted(ids)
data.proxy = null
data.udpFallback = null
// change the state
data.changeState(BaseService.State.Stopped, msg)

// stop the service if nothing has bound to it
if (restart) startRunner() else {
BootReceiver.enabled = false
stopSelf()
}
}
}
private fun stopV2Ray(isForced: Boolean = true) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (listeningForDefaultNetwork) {
listeningForDefaultNetwork = false
}
}
if (v2rayPoint.isRunning) {
try {
v2rayPoint.stopLoop()
} catch (e: Exception) {
Log.d(packageName, e.toString())
}
}

if (isForced) {
//stopSelf has to be called ahead of mInterface.close(). otherwise v2ray core cannot be stooped
//It's strage but true.
//This can be verified by putting stopself() behind and call stopLoop and startLoop
//in a row for several times. You will find that later created v2ray core report port in use
//which means the first v2ray core somehow failed to stop and release the port.
stopSelf()
}
}

private inner class V2RayCallback : V2RayVPNServiceSupportsSet {
override fun shutdown(): Long {
// called by go
// shutdown the whole vpn service
try {
this@V2RayProxyService.shutdown()
return 0
} catch (e: Exception) {
Log.d(packageName, e.toString())
return -1
}
}

override fun prepare(): Long {
return 0
}

override fun protect(l: Long) = 1.toLong()

override fun onEmitStatus(l: Long, s: String?): Long {
return 0
}

override fun setup(s: String): Long {
return 0
}
override fun sendFd(): Long {
return 0
}
}
}

Loading

0 comments on commit f8a72e8

Please sign in to comment.