implement front proxy & landing proxy

This commit is contained in:
arm64v8a 2023-03-18 16:46:19 +09:00
parent eec96213aa
commit bb51a38474
13 changed files with 124 additions and 46 deletions

View File

@ -2,11 +2,11 @@
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "062104587ad7088bb9926683389e995d",
"identityHash": "937a517378a0cb35dc1f8bd181683882",
"entities": [
{
"tableName": "proxy_groups",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userOrder` INTEGER NOT NULL, `ungrouped` INTEGER NOT NULL, `name` TEXT, `type` INTEGER NOT NULL, `subscription` BLOB, `order` INTEGER NOT NULL, `isSelector` INTEGER NOT NULL, `frontProxy` INTEGER NOT NULL)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userOrder` INTEGER NOT NULL, `ungrouped` INTEGER NOT NULL, `name` TEXT, `type` INTEGER NOT NULL, `subscription` BLOB, `order` INTEGER NOT NULL, `isSelector` INTEGER NOT NULL, `frontProxy` INTEGER NOT NULL, `landingProxy` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
@ -61,13 +61,19 @@
"columnName": "frontProxy",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "landingProxy",
"columnName": "landingProxy",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
],
"autoGenerate": true
]
},
"indices": [],
"foreignKeys": []
@ -222,10 +228,10 @@
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
],
"autoGenerate": true
]
},
"indices": [
{
@ -324,10 +330,10 @@
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
],
"autoGenerate": true
]
},
"indices": [],
"foreignKeys": []
@ -336,7 +342,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '062104587ad7088bb9926683389e995d')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '937a517378a0cb35dc1f8bd181683882')"
]
}
}

View File

@ -127,13 +127,14 @@ object Key {
const val ROUTE_SOURCE = "routeSource"
const val ROUTE_PROTOCOL = "routeProtocol"
const val ROUTE_OUTBOUND = "routeOutbound"
const val ROUTE_OUTBOUND_RULE = "routeOutboundRule"
const val ROUTE_PACKAGES = "routePackages"
const val GROUP_NAME = "groupName"
const val GROUP_TYPE = "groupType"
const val GROUP_ORDER = "groupOrder"
const val GROUP_IS_SELECTOR = "groupIsSelector"
const val GROUP_FRONT_PROXY = "groupFrontProxy"
const val GROUP_LANDING_PROXY = "groupLandingProxy"
const val GROUP_SUBSCRIPTION = "groupSubscription"
const val SUBSCRIPTION_LINK = "subscriptionLink"

View File

@ -13,6 +13,7 @@ import io.nekohasekai.sagernet.aidl.ISagerNetService
import io.nekohasekai.sagernet.aidl.ISagerNetServiceCallback
import io.nekohasekai.sagernet.bg.proto.ProxyInstance
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.database.ProxyEntity
import io.nekohasekai.sagernet.database.SagerDatabase
import io.nekohasekai.sagernet.ktx.*
import io.nekohasekai.sagernet.plugin.PluginManager
@ -149,14 +150,24 @@ class BaseService {
}
if (canReloadSelector()) {
var tag = ""
var ent: ProxyEntity? = null
data.proxy!!.config.trafficMap.forEach { (t, list) ->
if (list.map { it.id }.contains(DataStore.selectedProxy)) {
for (it in list) {
if (it.id == DataStore.selectedProxy) {
ent = it
tag = t
break
}
}
if (tag.isNotBlank()) {
}
if (tag.isNotBlank() && ent != null) {
val success = data.proxy!!.box.selectOutbound(tag)
Logs.d("selectOutbound $tag $success")
runOnDefaultDispatcher {
data.binder.broadcast {
it.stateChanged(-1, ent!!.displayName(), null)
}
}
}
return
}

View File

@ -53,6 +53,7 @@ class SagerConnection(private var listenForDeath: Boolean = false) : ServiceConn
private val serviceCallback = object : ISagerNetServiceCallback.Stub() {
override fun stateChanged(state: Int, profileName: String?, msg: String?) {
if (state < 0) return // skip private
val s = BaseService.State.values()[state]
DataStore.serviceState = s
val callback = callback ?: return

View File

@ -89,6 +89,9 @@ class ServiceNotification(
}
override fun stateChanged(state: Int, profileName: String?, msg: String?) {
if (state == -1) {
builder.setContentTitle(profileName)
}
}
override fun missingPlugin(profileName: String?, pluginName: String?) {

View File

@ -85,11 +85,11 @@ object DataStore : OnPreferenceDataStoreChangeListener {
var nightTheme by configurationStore.stringToInt(Key.NIGHT_THEME)
var serviceMode by configurationStore.string(Key.SERVICE_MODE) { Key.MODE_VPN }
// var domainStrategy by configurationStore.string(Key.DOMAIN_STRATEGY) { "AsIs" }
// var domainStrategy by configurationStore.string(Key.DOMAIN_STRATEGY) { "AsIs" }
var trafficSniffing by configurationStore.boolean(Key.TRAFFIC_SNIFFING) { true }
var resolveDestination by configurationStore.boolean(Key.RESOLVE_DESTINATION)
// var tcpKeepAliveInterval by configurationStore.stringToInt(Key.TCP_KEEP_ALIVE_INTERVAL) { 15 }
// var tcpKeepAliveInterval by configurationStore.stringToInt(Key.TCP_KEEP_ALIVE_INTERVAL) { 15 }
var mtu by configurationStore.stringToInt(Key.MTU) { 9000 }
var bypassLan by configurationStore.boolean(Key.BYPASS_LAN)
@ -225,9 +225,13 @@ object DataStore : OnPreferenceDataStoreChangeListener {
var routeSource by profileCacheStore.string(Key.ROUTE_SOURCE)
var routeProtocol by profileCacheStore.string(Key.ROUTE_PROTOCOL)
var routeOutbound by profileCacheStore.stringToInt(Key.ROUTE_OUTBOUND)
var routeOutboundRule by profileCacheStore.long(Key.ROUTE_OUTBOUND_RULE)
var routeOutboundRule by profileCacheStore.long(Key.ROUTE_OUTBOUND + "Long")
var routePackages by profileCacheStore.string(Key.ROUTE_PACKAGES)
var frontProxy by profileCacheStore.long(Key.GROUP_FRONT_PROXY + "Long")
var landingProxy by profileCacheStore.long(Key.GROUP_LANDING_PROXY + "Long")
var frontProxyTmp by profileCacheStore.stringToInt(Key.GROUP_FRONT_PROXY)
var landingProxyTmp by profileCacheStore.stringToInt(Key.GROUP_LANDING_PROXY)
var serverConfig by profileCacheStore.string(Key.SERVER_CONFIG)

View File

@ -20,7 +20,8 @@ data class ProxyGroup(
var subscription: SubscriptionBean? = null,
var order: Int = GroupOrder.ORIGIN,
var isSelector: Boolean = false,
var frontProxy: Long = 0L
var frontProxy: Long = -1L,
var landingProxy: Long = -1L
) : Serializable() {
@Transient

View File

@ -96,8 +96,7 @@ fun buildConfig(
val group = SagerDatabase.groupDao.getById(proxy.groupId)
var optionsToMerge = ""
fun ProxyEntity.resolveChain(): MutableList<ProxyEntity> {
val frontProxy = group?.frontProxy?.let { SagerDatabase.proxyDao.getById(it) }
fun ProxyEntity.resolveChainInternal(): MutableList<ProxyEntity> {
val bean = requireBean()
if (bean is ChainBean) {
val beans = SagerDatabase.proxyDao.getEntities(bean.proxies)
@ -105,20 +104,24 @@ fun buildConfig(
val beanList = ArrayList<ProxyEntity>()
for (proxyId in bean.proxies) {
val item = beansMap[proxyId] ?: continue
beanList.addAll(item.resolveChain())
beanList.addAll(item.resolveChainInternal())
}
return if (frontProxy == null) {
beanList.asReversed()
} else {
beanList.add(0, frontProxy)
beanList.asReversed()
return beanList.asReversed()
}
return mutableListOf(this)
}
return if (frontProxy == null) {
mutableListOf(this)
} else {
mutableListOf(this, frontProxy)
fun ProxyEntity.resolveChain(): MutableList<ProxyEntity> {
val frontProxy = group?.frontProxy?.let { SagerDatabase.proxyDao.getById(it) }
val landingProxy = group?.landingProxy?.let { SagerDatabase.proxyDao.getById(it) }
val list = resolveChainInternal()
if (frontProxy != null) {
list.add(frontProxy)
}
if (landingProxy != null) {
list.add(0, landingProxy)
}
return list
}
val extraRules = if (forTest) listOf() else SagerDatabase.rulesDao.enabledRules()

View File

@ -37,14 +37,18 @@ class GroupSettingsActivity(
OnPreferenceDataStoreChangeListener {
private lateinit var frontProxyPreference: OutboundPreference
private lateinit var landingProxyPreference: OutboundPreference
fun ProxyGroup.init() {
DataStore.groupName = name ?: ""
DataStore.groupType = type
DataStore.groupOrder = order
DataStore.groupIsSelector = isSelector
DataStore.routeOutboundRule = frontProxy
DataStore.routeOutbound = if (frontProxy >= 0) 3 else 0
DataStore.frontProxy = frontProxy
DataStore.landingProxy = landingProxy
DataStore.frontProxyTmp = if (frontProxy >= 0) 3 else 0
DataStore.landingProxyTmp = if (landingProxy >= 0) 3 else 0
val subscription = subscription ?: SubscriptionBean().applyDefaultValues()
DataStore.subscriptionLink = subscription.link
@ -61,7 +65,9 @@ class GroupSettingsActivity(
type = DataStore.groupType
order = DataStore.groupOrder
isSelector = DataStore.groupIsSelector
frontProxy = if (DataStore.routeOutbound == 3) DataStore.routeOutboundRule else -1
frontProxy = if (DataStore.frontProxyTmp == 3) DataStore.frontProxy else -1
landingProxy = if (DataStore.landingProxyTmp == 3) DataStore.landingProxy else -1
val isSubscription = type == GroupType.SUBSCRIPTION
if (isSubscription) {
@ -88,13 +94,28 @@ class GroupSettingsActivity(
) {
addPreferencesFromResource(R.xml.group_preferences)
frontProxyPreference = findPreference(Key.ROUTE_OUTBOUND)!!
frontProxyPreference = findPreference(Key.GROUP_FRONT_PROXY)!!
frontProxyPreference.apply {
entries = listOf("None", "Select...").toTypedArray()
entryValues = listOf("0", "3").toTypedArray()
setEntries(R.array.front_proxy_entry)
setEntryValues(R.array.front_proxy_value)
setOnPreferenceChangeListener { _, newValue ->
if (newValue.toString() == "3") {
selectProfileForAdd.launch(
selectProfileForAddFront.launch(
Intent(this@GroupSettingsActivity, ProfileSelectActivity::class.java)
)
false
} else {
true
}
}
}
landingProxyPreference = findPreference(Key.GROUP_LANDING_PROXY)!!
landingProxyPreference.apply {
setEntries(R.array.front_proxy_entry)
setEntryValues(R.array.front_proxy_value)
setOnPreferenceChangeListener { _, newValue ->
if (newValue.toString() == "3") {
selectProfileForAddLanding.launch(
Intent(this@GroupSettingsActivity, ProfileSelectActivity::class.java)
)
false
@ -119,8 +140,6 @@ class GroupSettingsActivity(
true
}
val subscriptionUserAgent =
findPreference<UserAgentPreference>(Key.SUBSCRIPTION_USER_AGENT)!!
val subscriptionAutoUpdate =
findPreference<SwitchPreference>(Key.SUBSCRIPTION_AUTO_UPDATE)!!
val subscriptionAutoUpdateDelay =
@ -339,20 +358,32 @@ class GroupSettingsActivity(
}
val selectProfileForAdd = registerForActivityResult(
val selectProfileForAddFront = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) runOnDefaultDispatcher {
val profile = ProfileManager.getProfile(
it.data!!.getLongExtra(
ProfileSelectActivity.EXTRA_PROFILE_ID, 0
)
it.data!!.getLongExtra(ProfileSelectActivity.EXTRA_PROFILE_ID, 0)
) ?: return@runOnDefaultDispatcher
DataStore.routeOutboundRule = profile.id
DataStore.frontProxy = profile.id
onMainDispatcher {
frontProxyPreference.value = "3"
}
}
}
val selectProfileForAddLanding = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) runOnDefaultDispatcher {
val profile = ProfileManager.getProfile(
it.data!!.getLongExtra(ProfileSelectActivity.EXTRA_PROFILE_ID, 0)
) ?: return@runOnDefaultDispatcher
DataStore.landingProxy = profile.id
onMainDispatcher {
landingProxyPreference.value = "3"
}
}
}
}

View File

@ -19,7 +19,7 @@ class OutboundPreference
override fun getSummary(): CharSequence? {
if (value == "3") {
val routeOutbound = DataStore.routeOutboundRule
val routeOutbound = DataStore.profileCacheStore.getLong(key + "Long") ?: 0
if (routeOutbound > 0) {
ProfileManager.getProfile(routeOutbound)?.displayName()?.let {
return it

View File

@ -247,6 +247,16 @@
<item>3</item>
</string-array>
<string-array name="front_proxy_entry">
<item>@string/ssh_auth_type_none</item>
<item>@string/route_profile</item>
</string-array>
<string-array name="front_proxy_value">
<item>0</item>
<item>3</item>
</string-array>
<string-array name="networks_value">
<item>tcp</item>
<item>ws</item>

View File

@ -504,5 +504,6 @@ Anyone can write advanced plugins, which can control NekoBox. please download an
<string name="need_restart">Restart APP to apply changes</string>
<string name="use_selector">Use selector</string>
<string name="front_proxy">Front proxy</string>
<string name="landing_proxy">Landing Proxy</string>
</resources>

View File

@ -22,10 +22,16 @@
<io.nekohasekai.sagernet.widget.OutboundPreference
app:icon="@drawable/ic_hardware_router"
app:key="routeOutbound"
app:key="groupFrontProxy"
app:title="@string/front_proxy"
app:useSimpleSummaryProvider="true" />
<io.nekohasekai.sagernet.widget.OutboundPreference
app:icon="@drawable/baseline_public_24"
app:key="groupLandingProxy"
app:title="@string/landing_proxy"
app:useSimpleSummaryProvider="true" />
<PreferenceCategory
app:key="groupSubscription"
app:title="@string/subscription_settings">