diff --git a/build.gradle b/build.gradle index e6f8593..399c637 100644 --- a/build.gradle +++ b/build.gradle @@ -14,8 +14,8 @@ buildscript { junitVersion = '4.13' androidTestVersion = '1.2.0' androidEspressoVersion = '3.2.0' - versionCode = 5000848 - versionName = '5.1.8-nightly' + versionCode = 5000868 + versionName = '5.1.10-nightly' resConfigs = ['ar', 'es', 'fa', 'fr', 'ja', 'ko', 'ru', 'tr', 'zh-rCN', 'zh-rTW'] } diff --git a/core/src/main/java/com/github/shadowsocks/bg/V2RayTestService.kt b/core/src/main/java/com/github/shadowsocks/bg/V2RayTestService.kt index 0b18f80..2b06b0c 100644 --- a/core/src/main/java/com/github/shadowsocks/bg/V2RayTestService.kt +++ b/core/src/main/java/com/github/shadowsocks/bg/V2RayTestService.kt @@ -62,7 +62,7 @@ class V2RayTestService : Service() , BaseService.Interface { data.connectingJob = GlobalScope.launch(Dispatchers.Main) { try { activeProfile = ProfileManager.getProfile(DataStore.profileId)!! - genStoreV2rayConfig() + ProfileManager.genStoreV2rayConfig(activeProfile,true) startV2ray() } catch (_: CancellationException) { // if the job was cancelled, it is canceller's responsibility to call stopRunner @@ -80,51 +80,8 @@ class V2RayTestService : Service() , BaseService.Interface { stopRunner() return Service.START_NOT_STICKY } - fun profileToVmessBean(profile: Profile): VmessBean { - var vmess = VmessBean() - vmess.guid=profile.id.toString() - vmess.remoteDns=profile.remoteDns - vmess.address=profile.host - vmess.alterId=profile.alterId - vmess.headerType=profile.headerType - vmess.id=profile.password - vmess.network=profile.network - vmess.path=profile.path - vmess.port=profile.remotePort - vmess.remarks= profile.name.toString() - vmess.requestHost=profile.requestHost - vmess.security=profile.method - vmess.streamSecurity=profile.streamSecurity - vmess.subid=profile.url_group - vmess.testResult=profile.elapsed.toString() - if(profile.route=="all")vmess.route="0" - else if(profile.route=="bypass-lan")vmess.route="1" - else if(profile.route=="bypass-china")vmess.route="2" - else if(profile.route=="bypass-lan-china")vmess.route="3" - else vmess.route="0" - return vmess - } - /** - * gen and store v2ray config file - */ - fun genStoreV2rayConfig(): Boolean { - try { - val result = V2rayConfigUtil.getV2rayConfig(Core.app, profileToVmessBean(activeProfile)) - if (result.status) { - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG, result.content) - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_GUID, activeProfile.id.toString()) - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_NAME, activeProfile.name) - return true - } else { - return false - } - } catch (e: Exception) { - e.printStackTrace() - return false - } - } override fun onLowMemory() { stopV2Ray() diff --git a/core/src/main/java/com/github/shadowsocks/bg/V2RayVpnService.kt b/core/src/main/java/com/github/shadowsocks/bg/V2RayVpnService.kt index 91ac0f5..e8767a8 100644 --- a/core/src/main/java/com/github/shadowsocks/bg/V2RayVpnService.kt +++ b/core/src/main/java/com/github/shadowsocks/bg/V2RayVpnService.kt @@ -134,7 +134,7 @@ class V2RayVpnService : VpnService() , BaseService.Interface{ activeProfile = ProfileManager.getProfile(DataStore.profileId)!! val proxy = V2ProxyInstance(v2rayPoint,activeProfile,activeProfile.route) data.proxy = proxy - genStoreV2rayConfig() + ProfileManager.genStoreV2rayConfig(activeProfile) startV2ray() } catch (_: CancellationException) { // if the job was cancelled, it is canceller's responsibility to call stopRunner @@ -151,53 +151,10 @@ class V2RayVpnService : VpnService() , BaseService.Interface{ } } stopRunner() + //stopRunner(false,null) return Service.START_NOT_STICKY } - fun profileToVmessBean(profile: Profile): VmessBean { - var vmess = VmessBean() - vmess.guid=profile.id.toString() - vmess.remoteDns=profile.remoteDns - vmess.address=profile.host - vmess.alterId=profile.alterId - vmess.headerType=profile.headerType - vmess.id=profile.password - vmess.network=profile.network - vmess.path=profile.path - vmess.port=profile.remotePort - vmess.remarks= profile.name.toString() - vmess.requestHost=profile.requestHost - vmess.security=profile.method - vmess.streamSecurity=profile.streamSecurity - vmess.subid=profile.url_group - vmess.testResult=profile.elapsed.toString() - - if(profile.route=="all")vmess.route="0" - else if(profile.route=="bypass-lan")vmess.route="1" - else if(profile.route=="bypass-china")vmess.route="2" - else if(profile.route=="bypass-lan-china")vmess.route="3" - else vmess.route="0" - - return vmess - } - /** - * gen and store v2ray config file - */ - fun genStoreV2rayConfig(): Boolean { - try { - val result = V2rayConfigUtil.getV2rayConfig(Core.app, profileToVmessBean(activeProfile)) - if (result.status) { - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG, result.content) - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_GUID, activeProfile.id.toString()) - defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_NAME, activeProfile.name) - return true - } else { - return false - } - } catch (e: Exception) { - e.printStackTrace() - return false - } - } + override fun onRevoke() { stopV2Ray() @@ -211,6 +168,7 @@ class V2RayVpnService : VpnService() , BaseService.Interface{ override fun onDestroy() { super.onDestroy() data.binder.close() + //stopRunner(false,null) //cancelNotification() } diff --git a/core/src/main/java/com/github/shadowsocks/database/Profile.kt b/core/src/main/java/com/github/shadowsocks/database/Profile.kt index 0aa83e7..a1776a6 100644 --- a/core/src/main/java/com/github/shadowsocks/database/Profile.kt +++ b/core/src/main/java/com/github/shadowsocks/database/Profile.kt @@ -57,10 +57,10 @@ data class Profile( var host: String = sponsored, var remotePort: Int = 8388, - var password: String = "u1rRWTssNv0p", + var password: String = "", var method: String = "aes-256-cfb", - var route: String = "bypass-lan-china", + var route: String = "all", //""bypass-lan-china" var remoteDns: String = "1.1.1.1", var proxyApps: Boolean = false, var bypass: Boolean = false, @@ -483,7 +483,7 @@ data class Profile( profile.udpdns = udpdns } - fun toUri(): Uri { + fun toSsUri(): Uri { val auth = Base64.encodeToString("$method:$password".toByteArray(), Base64.NO_PADDING or Base64.NO_WRAP or Base64.URL_SAFE) val wrappedHost = if (host.contains(':')) "[$host]" else host @@ -497,12 +497,41 @@ data class Profile( if (!name.isNullOrEmpty()) builder.fragment(name) return builder.build() } - + fun toVmessUri(): String { + if (isBuiltin()) return "" + try { + val vmess = ProfileManager.profileToVmessBean(this) + val vmessQRCode = VmessQRCode() + vmessQRCode.v = vmess.configVersion.toString() + vmessQRCode.ps = vmess.remarks + vmessQRCode.add = vmess.address + vmessQRCode.port = vmess.port.toString() + vmessQRCode.id = vmess.id + vmessQRCode.aid = vmess.alterId.toString() + vmessQRCode.net = vmess.network + vmessQRCode.type = vmess.headerType + vmessQRCode.host = vmess.requestHost + vmessQRCode.path = vmess.path + vmessQRCode.tls = vmess.streamSecurity + val json = Gson().toJson(vmessQRCode) + val conf = VMESS_PROTOCOL + encodeForVmess(json) + return conf + } catch (e: Exception) { + e.printStackTrace() + return "" + } + } fun isSameAs(other: Profile): Boolean = other.host == host - override fun toString() = toUri().toString() + override fun toString() : String { + if (profileType=="ss") + return toSsUri().toString() + else + return toVmessUri() + } fun toJson(profiles: LongSparseArray? = null): JSONObject = JSONObject().apply { + if (profileType=="vmess")return@apply put("server", host) put("server_port", remotePort) put("password", password) @@ -553,6 +582,15 @@ data class Profile( DataStore.plugin = plugin ?: "" DataStore.udpFallback = udpFallback DataStore.privateStore.remove(Key.dirty) + //add for vmess begin + DataStore.privateStore.putString(Key.profileType,profileType) + DataStore.privateStore.putString(Key.alterId,alterId.toString()) + DataStore.privateStore.putString(Key.network,network) + DataStore.privateStore.putString(Key.headerType,headerType) + DataStore.privateStore.putString(Key.requestHost,requestHost) + DataStore.privateStore.putString(Key.path,path) + DataStore.privateStore.putString(Key.streamSecurity,streamSecurity) + //add for vmess end } fun deserialize() { @@ -576,6 +614,15 @@ data class Profile( individual = DataStore.individual plugin = DataStore.plugin udpFallback = DataStore.udpFallback + //add for vmess begin + profileType=DataStore.privateStore.getString(Key.profileType) ?: "ss" + alterId=(DataStore.privateStore.getString(Key.alterId)?: "64").toInt() + network=DataStore.privateStore.getString(Key.network) ?: "tcp" + headerType=DataStore.privateStore.getString(Key.headerType) ?: "" + requestHost=DataStore.privateStore.getString(Key.requestHost) ?: "" + path=DataStore.privateStore.getString(Key.path) ?: "" + streamSecurity=DataStore.privateStore.getString(Key.streamSecurity) ?: "" + //add for vmess end } fun isBuiltin(): Boolean { return VpnEncrypt.vpnGroupName == url_group diff --git a/core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt b/core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt index c5f1da0..f81d9a6 100644 --- a/core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt +++ b/core/src/main/java/com/github/shadowsocks/database/ProfileManager.kt @@ -26,8 +26,10 @@ import android.util.Base64 import android.util.Log import android.util.LongSparseArray import com.github.shadowsocks.Core +import com.github.shadowsocks.Core.defaultDPreference import com.github.shadowsocks.preference.DataStore import com.github.shadowsocks.utils.DirectBoot +import com.github.shadowsocks.utils.V2rayConfigUtil import com.github.shadowsocks.utils.forEachTry import com.github.shadowsocks.utils.printLog import com.google.gson.JsonStreamParser @@ -314,4 +316,50 @@ object ProfileManager { return null } } + + fun profileToVmessBean(profile: Profile): VmessBean { + var vmess = VmessBean() + vmess.guid=profile.id.toString() + vmess.remoteDns=profile.remoteDns + vmess.address=profile.host + vmess.alterId=profile.alterId + vmess.headerType=profile.headerType + vmess.id=profile.password + vmess.network=profile.network + vmess.path=profile.path + vmess.port=profile.remotePort + vmess.remarks= profile.name.toString() + vmess.requestHost=profile.requestHost + vmess.security=profile.method + vmess.streamSecurity=profile.streamSecurity + vmess.subid=profile.url_group + vmess.testResult=profile.elapsed.toString() + + if(profile.route=="all")vmess.route="0" + else if(profile.route=="bypass-lan")vmess.route="1" + else if(profile.route=="bypass-china")vmess.route="2" + else if(profile.route=="bypass-lan-china")vmess.route="3" + else vmess.route="0" + + return vmess + } + /** + * gen and store v2ray config file + */ + fun genStoreV2rayConfig(activeProfile:Profile,isTest:Boolean=false): Boolean { + try { + val result = V2rayConfigUtil.getV2rayConfig(Core.app, profileToVmessBean(activeProfile),isTest) + if (result.status) { + defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG, result.content) + defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_GUID, activeProfile.id.toString()) + defaultDPreference.setPrefString(AppConfig.PREF_CURR_CONFIG_NAME, activeProfile.name) + return true + } else { + return false + } + } catch (e: Exception) { + e.printStackTrace() + return false + } + } } diff --git a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt index 9b7fdd2..828197f 100644 --- a/core/src/main/java/com/github/shadowsocks/utils/Constants.kt +++ b/core/src/main/java/com/github/shadowsocks/utils/Constants.kt @@ -28,6 +28,15 @@ object Key { const val DB_PUBLIC = "config.db" const val DB_PROFILE = "profile.db" + const val profileType = "profileType" + const val v2rayVpn = "v2rayVpn" + const val alterId = "alterId" + const val network = "network" + const val headerType = "headerType" + const val requestHost = "requestHost" + const val path = "path" + const val streamSecurity = "streamSecurity" + const val id = "profileId" const val oldId = "oldProfileId" const val name = "profileName" @@ -38,7 +47,7 @@ object Key { const val serviceMode = "serviceMode" const val modeProxy = "proxy" const val modeVpn = "vpn" - const val v2rayVpn = "v2rayVpn" + const val modeTransproxy = "transproxy" const val shareOverLan = "shareOverLan" const val portProxy = "portProxy" diff --git a/core/src/main/java/com/github/shadowsocks/utils/Utils.kt b/core/src/main/java/com/github/shadowsocks/utils/Utils.kt index ca77c4b..a5ae985 100644 --- a/core/src/main/java/com/github/shadowsocks/utils/Utils.kt +++ b/core/src/main/java/com/github/shadowsocks/utils/Utils.kt @@ -32,6 +32,7 @@ import android.os.Build import android.system.ErrnoException import android.system.Os import android.system.OsConstants +import android.util.Base64 import android.util.Log import android.util.TypedValue import androidx.annotation.AttrRes @@ -275,4 +276,16 @@ private fun Float.toShortString(): String { if (s.length <= 4) return s return s.substring(0, 4).removeSuffix(".") +} + +/** + * base64 encode + */ +fun encodeForVmess(text: String): String { + try { + return Base64.encodeToString(text.toByteArray(charset("UTF-8")), Base64.NO_WRAP) + } catch (e: Exception) { + e.printStackTrace() + return "" + } } \ No newline at end of file diff --git a/core/src/main/java/com/github/shadowsocks/utils/V2rayConfigUtil.kt b/core/src/main/java/com/github/shadowsocks/utils/V2rayConfigUtil.kt index 2f26cee..330bf14 100644 --- a/core/src/main/java/com/github/shadowsocks/utils/V2rayConfigUtil.kt +++ b/core/src/main/java/com/github/shadowsocks/utils/V2rayConfigUtil.kt @@ -31,7 +31,7 @@ object V2rayConfigUtil { /** * 生成v2ray的客户端配置文件 */ - fun getV2rayConfig(app: Application, vmess: VmessBean): Result { + fun getV2rayConfig(app: Application, vmess: VmessBean,isTest:Boolean=false): Result { var result = Result(false, "") try { //检查设置 @@ -43,7 +43,7 @@ object V2rayConfigUtil { // } if (vmess.configType == AppConfig.EConfigType.Vmess) { - result = getV2rayConfigType1(app, vmess) + result = getV2rayConfigType1(app, vmess,isTest) } else if (vmess.configType == AppConfig.EConfigType.Custom) { result = getV2rayConfigType2(app, vmess) } else if (vmess.configType == AppConfig.EConfigType.Shadowsocks) { @@ -68,7 +68,7 @@ object V2rayConfigUtil { /** * 生成v2ray的客户端配置文件 */ - private fun getV2rayConfigType1(app: Application, vmess: VmessBean): Result { + private fun getV2rayConfigType1(app: Application, vmess: VmessBean,isTest:Boolean=false): Result { val result = Result(false, "") try { //取得默认配置 @@ -88,7 +88,7 @@ object V2rayConfigUtil { outbounds(vmess, v2rayConfig, app) - routing(vmess, v2rayConfig, app) + routing(vmess, v2rayConfig, app,isTest) //if (VpnEncrypt.enableLocalDns) {customLocalDns(vmess, v2rayConfig, app) } else { customRemoteDns(vmess, v2rayConfig, app) @@ -365,7 +365,7 @@ object V2rayConfigUtil { /** * routing */ - private fun routing(vmess: VmessBean, v2rayConfig: V2rayConfig, app: Application): Boolean { + private fun routing(vmess: VmessBean, v2rayConfig: V2rayConfig, app: Application,isTest:Boolean=false): Boolean { try { routingUserRule(Core.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_AGENT, ""), AppConfig.TAG_AGENT, v2rayConfig) routingUserRule(Core.defaultDPreference.getPrefString(AppConfig.PREF_V2RAY_ROUTING_DIRECT, ""), AppConfig.TAG_DIRECT, v2rayConfig) @@ -373,7 +373,8 @@ object V2rayConfigUtil { v2rayConfig.routing.domainStrategy = VpnEncrypt.PREF_ROUTING_DOMAIN_STRATEGY //val routingMode = Core.defaultDPreference.getPrefString(vmess.route, "0") - val routingMode = vmess.route + var routingMode = "0" // vmess.route //强制全局模式,"3"时启动很慢 + if (isTest)routingMode="0" //测试时强制全局模式,"3"时启动很慢 // Hardcode googleapis.cn val googleapisRoute = V2rayConfig.RoutingBean.RulesBean( diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 62398ca..79cb020 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -1,5 +1,11 @@ + + chacha20-poly1305 + aes-128-gcm + auto + none + RC4-MD5 AES-128-CFB @@ -212,4 +218,44 @@ vpn transproxy + + + tcp + kcp + ws + h2 + quic + + + + none + http + srtp + utp + wechat-video + dtls + wireguard + + + + + tls + + + + 0 + 1 + 2 + 3 + + + + AsIs + IPIfNonMatch + IPOnDemand + + + ss + vmess + \ No newline at end of file diff --git a/gitupdate.bat b/gitupdate.bat index 245cfd9..4eebbdf 100644 --- a/gitupdate.bat +++ b/gitupdate.bat @@ -3,6 +3,6 @@ git pull origin master git add -A git commit -m "update" git push origin master -git tag -a v5.1.8.1 -m "release v5.1.8.1" +git tag -a v5.1.10 -m "release v5.1.10" git push origin --tags pause \ No newline at end of file diff --git a/libv2ray/libv2ray.aar b/libv2ray/libv2ray.aar index b48ef3d..8c91c97 100644 Binary files a/libv2ray/libv2ray.aar and b/libv2ray/libv2ray.aar differ diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index 39db249..d550327 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -33,6 +33,7 @@ + //profile.profileType=newValue.toString() + switchVmessSS(newValue.toString()) + true + } + if(profile.isBuiltin()){ + val proxyCategory:PreferenceCategory = findPreference("proxyCategory")!! + proxyCategory.isVisible=false + v2rayMoreCat.isVisible=false + pluginCategory.isVisible=false + } else { - addPreferencesFromResource(R.xml.pref_profile) findPreference(Key.remotePort)!!.setOnBindEditTextListener(EditTextPreferenceModifiers.Port) findPreference(Key.password)!!.summaryProvider = PasswordSummaryProvider } - val serviceMode = DataStore.serviceMode findPreference(Key.remoteDns)!!.isEnabled = serviceMode != Key.modeProxy findPreference(Key.ipv6)!!.isEnabled = (serviceMode == Key.modeVpn || serviceMode == Key.v2rayVpn) @@ -111,30 +167,17 @@ class ProfileConfigFragment : PreferenceFragmentCompat(), findPreference(Key.udpdns)!!.isEnabled = serviceMode != Key.modeProxy plugin = findPreference(Key.plugin)!! pluginConfigure = findPreference(Key.pluginConfigure)!! - if(thisprofile.isBuiltin()){ - plugin.isVisible=false - pluginConfigure.isVisible=false - } pluginConfigure.setOnBindEditTextListener(EditTextPreferenceModifiers.Monospace) pluginConfigure.onPreferenceChangeListener = this pluginConfiguration = PluginConfiguration(DataStore.plugin) initPlugins() udpFallback = findPreference(Key.udpFallback)!! DataStore.privateStore.registerChangeListener(this) - - val profile = ProfileManager.getProfile(profileId) ?: Profile() - if (profile.profileType=="vmess"){ - route=findPreference(Key.route)!! - route.setEntries(R.array.route_entry_v2ray) - plugin.isVisible=false - udpFallback.isVisible=false - udpFallback.isEnabled = false - } if (profile.subscription == Profile.SubscriptionStatus.Active) { findPreference(Key.name)!!.isEnabled = false findPreference(Key.host)!!.isEnabled = false findPreference(Key.password)!!.isEnabled = false - findPreference(Key.method)!!.isEnabled = false + encMethod!!.isEnabled = false findPreference(Key.remotePort)!!.isEnabled = false plugin.isEnabled = false pluginConfigure.isEnabled = false diff --git a/mobile/src/main/res/raw/about.html b/mobile/src/main/res/raw/about.html index c3d77ee..4118873 100644 --- a/mobile/src/main/res/raw/about.html +++ b/mobile/src/main/res/raw/about.html @@ -21,6 +21,7 @@

Open Source Licenses

  • Shadowsocks-android: GPLv3 
  • ShadowsocksRb: GPLv3 
  • Polipo: MIT 
  • +
  • V2rayNG: GPLv3 
  • diff --git a/mobile/src/main/res/values/arrays.xml b/mobile/src/main/res/values/arrays.xml index 30cb81d..95bbdc1 100644 --- a/mobile/src/main/res/values/arrays.xml +++ b/mobile/src/main/res/values/arrays.xml @@ -6,6 +6,12 @@ @string/route_entry_bypass_chn @string/route_entry_bypass_lan_chn + + all + bypass-lan + bypass-china + bypass-lan-china + @string/route_entry_all @string/route_entry_bypass_lan diff --git a/mobile/src/main/res/xml/pref_profile.xml b/mobile/src/main/res/xml/pref_profile.xml index c4adff1..011b91d 100644 --- a/mobile/src/main/res/xml/pref_profile.xml +++ b/mobile/src/main/res/xml/pref_profile.xml @@ -1,22 +1,27 @@ - + - - + - + + + + + + + + - -
    diff --git a/mobile/src/main/res/xml/pref_profile_vpn.xml b/mobile/src/main/res/xml/pref_profile_vpn.xml deleted file mode 100644 index a1cbc3a..0000000 --- a/mobile/src/main/res/xml/pref_profile_vpn.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mobile/src/main/res/xml/shortcuts.xml b/mobile/src/main/res/xml/shortcuts.xml index 73819c8..bdb6390 100644 --- a/mobile/src/main/res/xml/shortcuts.xml +++ b/mobile/src/main/res/xml/shortcuts.xml @@ -5,7 +5,7 @@ android:shortcutShortLabel="@string/quick_toggle" android:shortcutLongLabel="@string/quick_toggle">