Compare commits

...

7 Commits
1.6.0 ... 1.6.4

Author SHA1 Message Date
2dust
8cdc7fb3c9 Merge pull request #1001 from yuhan6665/new-storage-fix
Rollback parsed custom config
2021-04-11 19:28:47 +08:00
yuhan6665
d0a2fa0086 Rollback parsed custom config
To minimize change, the data structure for ServerConfig still stay the same
Add another table for server raw config
2021-04-10 21:30:34 -04:00
2dust
f6c54841d2 Merge pull request #990 from yuhan6665/new-storage-fix
New storage fix
2021-04-05 20:21:51 +08:00
yuhan6665
54fa356999 Add some new config for v2fly 4.37.0 2021-04-04 19:25:52 -04:00
2dust
9642b7f64f up grpc 2021-04-04 19:25:52 -04:00
yuhan6665
dd2d2c1638 Add some missing config from Xray 2021-04-04 19:25:51 -04:00
yuhan6665
e21950dbcd Improve custom config error toast 2021-04-04 19:25:51 -04:00
11 changed files with 84 additions and 41 deletions

View File

@@ -5,6 +5,7 @@ import com.google.gson.GsonBuilder
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type
@@ -19,7 +20,8 @@ data class V2rayConfig(
val api: Any? = null,
val transport: Any? = null,
val reverse: Any? = null,
val fakedns: Any? = null) {
val fakedns: Any? = null,
val browserForwarder: Any? = null) {
companion object {
const val DEFAULT_PORT = 443
const val DEFAULT_SECURITY = "auto"
@@ -34,7 +36,8 @@ data class V2rayConfig(
data class LogBean(val access: String,
val error: String,
var loglevel: String?)
var loglevel: String?,
val dnsLog: Boolean? = null)
data class InboundBean(
var tag: String,
@@ -101,6 +104,7 @@ data class V2rayConfig(
var level: Int = DEFAULT_LEVEL,
val email: String? = null,
val flow: String? = null,
val ivCheck: Boolean? = null,
var users: List<SocksUsersBean>? = null) {
@@ -121,18 +125,27 @@ data class V2rayConfig(
var tlsSettings: TlsSettingsBean? = null,
var quicSettings: QuicSettingBean? = null,
var xtlsSettings: TlsSettingsBean? = null,
val grpcSettings: Any? = null,
var grpcSettings: GrpcSettingsBean? = null,
val dsSettings: Any? = null,
val sockopt: Any? = null
) {
data class TcpSettingsBean(var header: HeaderBean = HeaderBean()) {
data class TcpSettingsBean(var header: HeaderBean = HeaderBean(),
val acceptProxyProtocol: Boolean? = null) {
data class HeaderBean(var type: String = "none",
var request: RequestBean? = null,
var response: Any? = null) {
data class RequestBean(var path: List<String> = ArrayList(),
var headers: HeadersBean = HeadersBean()) {
data class HeadersBean(var Host: List<String> = ArrayList())
var headers: HeadersBean = HeadersBean(),
val version: String? = null,
val method: String? = null) {
data class HeadersBean(var Host: List<String> = ArrayList(),
@SerializedName("User-Agent")
val userAgent: List<String>? = null,
@SerializedName("Accept-Encoding")
val acceptEncoding: List<String>? = null,
val Connection: List<String>? = null,
val Pragma: String? = null)
}
}
}
@@ -150,7 +163,10 @@ data class V2rayConfig(
}
data class WsSettingsBean(var path: String = "",
var headers: HeadersBean = HeadersBean()) {
var headers: HeadersBean = HeadersBean(),
val maxEarlyData: Int? = null,
val useBrowserForwarding: Boolean? = null,
val acceptProxyProtocol: Boolean? = null) {
data class HeadersBean(var Host: String = "")
}
@@ -160,8 +176,14 @@ data class V2rayConfig(
data class TlsSettingsBean(var allowInsecure: Boolean = false,
var serverName: String = "",
val alpn: List<String>? = null,
val minVersion: String? = null,
val maxVersion: String? = null,
val preferServerCipherSuites: Boolean? = null,
val cipherSuites: String? = null,
val fingerprint: String? = null,
val certificates: List<Any>? = null,
val disableSystemRoot: Boolean? = null)
val disableSystemRoot: Boolean? = null,
val enableSessionResumption: Boolean? = null)
data class QuicSettingBean(var security: String = "none",
var key: String = "",
@@ -169,6 +191,9 @@ data class V2rayConfig(
data class HeaderBean(var type: String = "none")
}
data class GrpcSettingsBean(var serviceName: String = "",
val multiMode: Boolean? = null)
fun populateTransportSettings(transport: String, headerType: String?, host: String?, path: String?, seed: String?,
quicSecurity: String?, key: String?): String {
var sni = ""
@@ -223,6 +248,12 @@ data class V2rayConfig(
quicsetting.header.type = headerType ?: "none"
quicSettings = quicsetting
}
"grpc" -> {
val grpcSetting = GrpcSettingsBean()
grpcSetting.serviceName = path ?: ""
sni = host ?: ""
grpcSettings = grpcSetting
}
}
return sni
}
@@ -324,6 +355,12 @@ data class V2rayConfig(
quicSetting.security,
quicSetting.key)
}
"grpc" -> {
val grpcSetting = streamSettings?.grpcSettings ?: return null
listOf("",
"",
grpcSetting.serviceName)
}
else -> null
}
}
@@ -335,6 +372,7 @@ data class V2rayConfig(
var hosts: Map<String, String>? = null,
val clientIp: String? = null,
val disableCache: Boolean? = null,
val queryStrategy: String? = null,
val tag: String? = null
) {
data class ServersBean(var address: String = "",

View File

@@ -16,6 +16,7 @@ import android.util.Log
import android.view.KeyEvent
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import com.tbruyelle.rxpermissions.RxPermissions
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
@@ -28,13 +29,13 @@ import com.v2ray.ang.service.V2RayServiceManager
import com.v2ray.ang.util.AngConfigManager
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.Utils
import com.v2ray.ang.util.V2rayConfigUtil
import com.v2ray.ang.viewmodel.MainViewModel
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import libv2ray.Libv2ray
import me.drakeet.support.toast.ToastCompat
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import java.net.URL
@@ -475,14 +476,11 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
toast(R.string.toast_none_data)
return
}
if (!V2rayConfigUtil.isValidConfig(server)) {
toast(R.string.toast_config_file_invalid)
return
}
mainViewModel.appendCustomConfigServer(server)
toast(R.string.toast_success)
adapter.notifyItemInserted(mainViewModel.serverList.lastIndex)
} catch (e: Exception) {
ToastCompat.makeText(this, "${getString(R.string.toast_malformed_josn)} ${e.cause?.message}", Toast.LENGTH_LONG).show()
e.printStackTrace()
return
}

View File

@@ -5,6 +5,7 @@ import android.support.v7.app.AlertDialog
import android.text.TextUtils
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import com.google.gson.Gson
import com.tencent.mmkv.MMKV
import com.v2ray.ang.R
@@ -15,10 +16,12 @@ import com.v2ray.ang.extension.toast
import com.v2ray.ang.util.MmkvManager
import com.v2ray.ang.util.Utils
import kotlinx.android.synthetic.main.activity_server_custom_config.*
import me.drakeet.support.toast.ToastCompat
class ServerCustomConfigActivity : BaseActivity() {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val editGuid by lazy { intent.getStringExtra("guid").orEmpty() }
private val isRunning by lazy {
intent.getBooleanExtra("isRunning", false)
@@ -45,7 +48,12 @@ class ServerCustomConfigActivity : BaseActivity() {
*/
private fun bindingServer(config: ServerConfig): Boolean {
et_remarks.text = Utils.getEditable(config.remarks)
tv_content.text = Utils.getEditable(config.fullConfig?.toPrettyPrinting().orEmpty())
val raw = serverRawStorage?.decodeString(editGuid)
if (raw.isNullOrBlank()) {
tv_content.text = Utils.getEditable(config.fullConfig?.toPrettyPrinting().orEmpty())
} else {
tv_content.text = Utils.getEditable(raw)
}
return true
}
@@ -70,7 +78,7 @@ class ServerCustomConfigActivity : BaseActivity() {
Gson().fromJson(tv_content.text.toString(), V2rayConfig::class.java)
} catch (e: Exception) {
e.printStackTrace()
toast(R.string.toast_malformed_josn)
ToastCompat.makeText(this, "${getString(R.string.toast_malformed_josn)} ${e.cause?.message}", Toast.LENGTH_LONG).show()
return false
}
@@ -79,6 +87,7 @@ class ServerCustomConfigActivity : BaseActivity() {
config.fullConfig = v2rayConfig
MmkvManager.encodeServerConfig(editGuid, config)
serverRawStorage?.encode(editGuid, tv_content.text.toString())
toast(R.string.toast_success)
finish()
return true

View File

@@ -22,6 +22,7 @@ import java.util.*
object AngConfigManager {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
private val subStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SUB, MMKV.MULTI_PROCESS_MODE) }
@@ -95,6 +96,7 @@ object AngConfigManager {
return@forEachIndexed
}
config.fullConfig = v2rayConfig
serverRawStorage?.encode(vmessBean.guid, jsonConfig)
} else {
config.outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
vnext.address = vmessBean.address

View File

@@ -9,6 +9,7 @@ import com.v2ray.ang.dto.SubscriptionItem
object MmkvManager {
const val ID_MAIN = "MAIN"
const val ID_SERVER_CONFIG = "SERVER_CONFIG"
const val ID_SERVER_RAW = "SERVER_RAW"
const val ID_SERVER_AFF = "SERVER_AFF"
const val ID_SUB = "SUB"
const val ID_SETTING = "SETTING"

View File

@@ -7,8 +7,6 @@ import com.google.gson.*
import com.tencent.mmkv.MMKV
import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.V2rayConfig
import org.json.JSONException
import org.json.JSONObject
import com.v2ray.ang.dto.EConfigType
object V2rayConfigUtil {
@@ -19,6 +17,7 @@ object V2rayConfigUtil {
// JSONObject("""{"version":"1.1","status":"200","reason":"OK","headers":{"Content-Type":["application/octet-stream","video/mpeg"],"Transfer-Encoding":["chunked"],"Connection":["keep-alive"],"Pragma":"no-cache"}}""")
// }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
private val settingsStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SETTING, MMKV.MULTI_PROCESS_MODE) }
data class Result(var status: Boolean, var content: String)
@@ -30,7 +29,12 @@ object V2rayConfigUtil {
try {
val config = MmkvManager.decodeServerConfig(guid) ?: return Result(false, "")
if (config.configType == EConfigType.CUSTOM) {
val customConfig = config.fullConfig?.toPrettyPrinting() ?: return Result(false, "")
val raw = serverRawStorage?.decodeString(guid)
val customConfig = if (raw.isNullOrBlank()) {
config.fullConfig?.toPrettyPrinting() ?: return Result(false, "")
} else {
raw
}
Log.d("V2rayConfigUtilGoLog", customConfig)
return Result(true, customConfig)
}
@@ -360,17 +364,4 @@ object V2rayConfigUtil {
}
return true
}
/**
* is valid config
*/
fun isValidConfig(conf: String): Boolean {
return try {
val jObj = JSONObject(conf)
//hasBound = (jObj.has("outbounds") and jObj.has("inbounds")) or (jObj.has("outbound") and jObj.has("inbound"))
jObj.has("outbounds") or jObj.has("outbound")
} catch (e: JSONException) {
false
}
}
}

View File

@@ -24,6 +24,7 @@ import java.util.*
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val mainStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_MAIN, MMKV.MULTI_PROCESS_MODE) }
private val serverRawStorage by lazy { MMKV.mmkvWithID(MmkvManager.ID_SERVER_RAW, MMKV.MULTI_PROCESS_MODE) }
var serverList= MmkvManager.decodeServerList()
private set
@@ -61,7 +62,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
val config = ServerConfig.create(EConfigType.CUSTOM)
config.remarks = System.currentTimeMillis().toString()
config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java)
serverList.add(MmkvManager.encodeServerConfig("", config))
val key = MmkvManager.encodeServerConfig("", config)
serverRawStorage?.encode(key, server)
serverList.add(key)
}
fun swapServer(fromPosition: Int, toPosition: Int) {

View File

@@ -43,10 +43,10 @@
<string name="server_lab_network">传输协议(network)</string>
<string name="server_lab_more_function">功能设置(不清楚则保持默认值)</string>
<string name="server_lab_head_type">伪装类型(type)</string>
<string name="server_lab_request_host">伪装域名host(host/ws host/h2 host)/QUIC 加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密密钥</string>
<string name="server_lab_stream_security">底层传输安全</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_request_host">伪装域名(host)(host/ws host/h2 host)/QUIC 加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC 加密密钥/kcp seed/grpc serviceName</string>
<string name="server_lab_stream_security">底层传输安全(tls)</string>
<string name="server_lab_allow_insecure">跳过证书验证(allowInsecure)</string>
<string name="server_lab_address3">服务器地址</string>
<string name="server_lab_port3">服务器端口</string>
<string name="server_lab_id3">密码</string>

View File

@@ -43,10 +43,10 @@
<string name="server_lab_network">網路</string>
<string name="server_lab_more_function">更多功能</string>
<string name="server_lab_head_type">標頭類型</string>
<string name="server_lab_request_host">要求主機(host/ws host/h2 host)/QUIC加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC加密密鑰</string>
<string name="server_lab_stream_security">傳輸層安全性</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_request_host">要求主機(host)(host/ws host/h2 host)/QUIC加密方式</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC加密密鑰/kcp seed/grpc serviceName</string>
<string name="server_lab_stream_security">傳輸層安全性(tls)</string>
<string name="server_lab_allow_insecure">跳過證書驗證(allowInsecure)</string>
<string name="server_lab_address3">伺服器位址</string>
<string name="server_lab_port3">伺服器埠</string>
<string name="server_lab_id3">密碼</string>

View File

@@ -24,6 +24,7 @@
<item>ws</item>
<item>h2</item>
<item>quic</item>
<item>grpc</item>
</string-array>
<string-array name="headertypes" translatable="false">

View File

@@ -44,7 +44,7 @@
<string name="server_lab_more_function">more function</string>
<string name="server_lab_head_type">head type</string>
<string name="server_lab_request_host">request host(host/ws host/h2 host)/QUIC security</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key</string>
<string name="server_lab_path">path(ws path/h2 path)/QUIC key/kcp seed/grpc serviceName</string>
<string name="server_lab_stream_security">tls</string>
<string name="server_lab_allow_insecure">allowInsecure</string>
<string name="server_lab_address3">address</string>