Commit d35c3e4a authored by chenhuaqing's avatar chenhuaqing

adapted android code for server

parent b71f5595
......@@ -15,7 +15,7 @@ android {
consumerProguardFiles("proguard-rules.pro")
externalNativeBuild.ndkBuild {
abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
abiFilters("armeabi-v7a", "arm64-v8a")
arguments("-j${Runtime.getRuntime().availableProcessors()}")
}
......@@ -35,11 +35,11 @@ android {
cargo {
module = "src/main/rust/shadowsocks-rust"
libname = "sslocal"
targets = listOf("arm", "arm64", "x86", "x86_64")
targets = listOf("arm", "arm64")
profile = findProperty("CARGO_PROFILE")?.toString() ?: currentFlavor
extraCargoBuildArguments = listOf("--bin", libname!!)
featureSpec.noDefaultBut(arrayOf(
"stream-cipher",
// "stream-cipher",
"aead-cipher-extra",
"logging",
"local-flow-stat",
......
......@@ -24,6 +24,7 @@ import android.content.Context
import com.github.shadowsocks.Core.app
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.AclSyncer
import com.github.shadowsocks.core.BuildConfig
import com.github.shadowsocks.core.R
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.plugin.PluginConfiguration
......@@ -32,6 +33,7 @@ import com.github.shadowsocks.preference.DataStore
import kotlinx.coroutines.CoroutineScope
import org.json.JSONArray
import org.json.JSONObject
import timber.log.Timber
import java.io.File
import java.net.URI
import java.net.URISyntaxException
......@@ -99,6 +101,8 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
})
configFile.writeText(config.toString())
Timber.d("prepare start service with config: $config")
// build the command line
val cmd = arrayListOf(
File((service as Context).applicationInfo.nativeLibraryDir, Executable.SS_LOCAL).absolutePath,
......@@ -113,6 +117,13 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
cmd += Acl.getFile(route).absolutePath
}
if (BuildConfig.DEBUG) {
cmd += "-v"
cmd += "-v"
cmd += "-v"
cmd += "-v"
}
service.data.processes!!.start(cmd)
}
......
......@@ -54,10 +54,15 @@ data class Profile(
// user configurable fields
var name: String? = "",
var host: String = "example.shadowsocks.org",
var remotePort: Int = 8388,
var host: String = "124.156.143.65",
var remotePort: Int = 8390,
var password: String = "u1rRWTssNv0p",
var method: String = "aes-256-cfb",
var token: String? = null,
var method: String = "aes-128-gcm",
var authTimeout: Int = 10,
var beatsInterval: Int = 10,
var retryLimit: Int = 3,
var route: String = "all",
var remoteDns: String = "dns.google",
......@@ -313,6 +318,12 @@ data class Profile(
put("server_port", remotePort)
put("password", password)
put("method", method)
if (token != null) {
put("token", token)
}
put("auth_timeout", authTimeout)
put("beats_interval", beatsInterval)
put("retry_limit", retryLimit)
if (profiles == null) return@apply
PluginConfiguration(plugin ?: "").getOptions().also {
if (it.id.isNotEmpty()) {
......@@ -344,6 +355,10 @@ data class Profile(
DataStore.privateStore.putString(Key.host, host)
DataStore.privateStore.putString(Key.remotePort, remotePort.toString())
DataStore.privateStore.putString(Key.password, password)
DataStore.privateStore.putString(Key.token, token)
DataStore.privateStore.putInt(Key.authTimeout, authTimeout)
DataStore.privateStore.putInt(Key.beatsInterval, beatsInterval)
DataStore.privateStore.putInt(Key.retryLimit, retryLimit)
DataStore.privateStore.putString(Key.route, route)
DataStore.privateStore.putString(Key.remoteDns, remoteDns)
DataStore.privateStore.putString(Key.method, method)
......@@ -367,6 +382,10 @@ data class Profile(
host = (DataStore.privateStore.getString(Key.host) ?: "").trim()
remotePort = parsePort(DataStore.privateStore.getString(Key.remotePort), 8388, 1)
password = DataStore.privateStore.getString(Key.password) ?: ""
token = DataStore.privateStore.getString(Key.token) ?: ""
authTimeout = DataStore.privateStore.getInt(Key.authTimeout) ?: 10
beatsInterval = DataStore.privateStore.getInt(Key.beatsInterval) ?: 10
retryLimit = DataStore.privateStore.getInt(Key.retryLimit) ?: 3
method = DataStore.privateStore.getString(Key.method) ?: ""
route = DataStore.privateStore.getString(Key.route) ?: ""
remoteDns = DataStore.privateStore.getString(Key.remoteDns) ?: ""
......
......@@ -54,6 +54,10 @@ object Key {
const val host = "proxy"
const val password = "sitekey"
const val token = "token"
const val authTimeout = "authTimeout"
const val beatsInterval = "beatsInterval"
const val retryLimit = "retryLimit"
const val method = "encMethod"
const val remotePort = "remotePortNum"
const val remoteDns = "remoteDns"
......
......@@ -25,4 +25,5 @@ dependencies {
implementation("com.takisoft.preferencex:preferencex-simplemenu:1.1.0")
implementation("com.twofortyfouram:android-plugin-api-for-locale:1.0.4")
implementation("me.zhanghai.android.fastscroll:library:1.1.7")
implementation("com.android.volley:volley:1.2.0")
}
......@@ -12,8 +12,11 @@
<uses-feature android:name="android.hardware.camera"
android:required="false"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".App"
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="MissingTvBanner">
<activity
......
......@@ -21,6 +21,7 @@
package com.github.shadowsocks
import android.content.ActivityNotFoundException
import android.os.Build
import android.os.Bundle
import android.os.RemoteException
import android.view.KeyCharacterMap
......@@ -36,11 +37,19 @@ import androidx.core.net.toUri
import androidx.core.view.*
import androidx.drawerlayout.widget.DrawerLayout
import androidx.preference.PreferenceDataStore
import com.android.volley.Request
import com.android.volley.RequestQueue
import com.android.volley.toolbox.RequestFuture
import com.android.volley.toolbox.StringRequest
import com.android.volley.toolbox.Volley
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.CustomRulesFragment
import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.ShadowsocksConnection
import com.github.shadowsocks.aidl.TrafficStats
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.preference.OnPreferenceDataStoreChangeListener
import com.github.shadowsocks.subscription.SubscriptionFragment
......@@ -54,6 +63,11 @@ import com.google.android.material.snackbar.Snackbar
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase
import com.google.gson.JsonStreamParser
import timber.log.Timber
import java.io.File
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPreferenceDataStoreChangeListener,
NavigationView.OnNavigationItemSelectedListener {
......@@ -114,7 +128,62 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
stateListener?.invoke(state)
}
private fun toggle() = if (state.canStop) Core.stopService() else connect.launch(null)
private fun toggle() = if (state.canStop) {
Core.stopService()
} else {
if (state == BaseService.State.Stopped) {
val profileId = 1L
val profile = ProfileManager.getProfile(profileId) ?: Profile()
profile.token = "e38daf39db56471cb8bfe2776b24059c"
profile.remotePort = 8398
profile.proxyApps = true
profile.individual = "com.sec.android.app.sbrowser"
profile.route = Acl.BYPASS_LAN_CHN
profile.password = "barfoo!"
profile.method = "none"
profile.beatsInterval = 60
ProfileManager.updateProfile(profile)
Timber.d("update to latest config: ${profile.toJson()}")
}
connect.launch(null)
}
private lateinit var queue: RequestQueue
private fun stateListener(state: BaseService.State) {
if (state == BaseService.State.Connected) {
thread(name = "update-config") {
val context =
if (Build.VERSION.SDK_INT < 24 || Core.user.isUserUnlocked) Core.app else Core.deviceStorage
val configFile = File(context.noBackupFilesDir, BaseService.CONFIG_FILE)
val configJson = JsonStreamParser(configFile.readText()).asSequence()
.single().asJsonObject
val tokenFuture: RequestFuture<String> = RequestFuture.newFuture()
val retryLimit = 3
var reqCount = 1
while (state == BaseService.State.Connected) {
val tokenRequest =
StringRequest(Request.Method.GET, "http://10.3.0.34:9000", tokenFuture, tokenFuture)
queue.add(tokenRequest)
val token = try {
tokenFuture.get()
} catch (e: Exception) {
Timber.e(e, "get latest config failed")
if (reqCount == retryLimit) {
Core.stopService()
return@thread
}
reqCount++
Thread.sleep(TimeUnit.SECONDS.toMillis(3))
continue
}
configJson.addProperty("token", token)
Timber.d("recv latest config: $configJson")
configFile.writeText(configJson.toString())
Thread.sleep(TimeUnit.SECONDS.toMillis(3))
}
}
}
}
private val connection = ShadowsocksConnection(true)
override fun onServiceConnected(service: IShadowsocksService) = changeState(try {
......@@ -148,6 +217,9 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Callback, OnPref
displayFragment(ProfilesFragment())
}
queue = Volley.newRequestQueue(this)
stateListener = this::stateListener
fab = findViewById(R.id.fab)
fab.initProgress(findViewById(R.id.fabProgress))
fab.setOnClickListener { toggle() }
......
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.137.1</domain>
<domain includeSubdomains="true">10.3.0.34</domain>
</domain-config>
</network-security-config>
\ No newline at end of file
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