Commit b9828bfe authored by chenhuaqing's avatar chenhuaqing Committed by hanakeichen

fix test latency

parent 38f8993c
......@@ -34,5 +34,5 @@ class AccVpnService {
}
interface TestLatencyCallback {
fun onLatency(latency: Int)
fun onLatency(latency: Int): Boolean
}
\ No newline at end of file
......@@ -17,8 +17,8 @@ object NetworkAdapter {
var wifiNetwork: Network? = null
var cellularNetwork: Network? = null
var bindNetwork: Network? = null
private var bindNetwork: Network? = null
private val FD_FIELD: Field
val wifiRequest: NetworkRequest = NetworkRequest.Builder()
......
package com.github.shadowsocks.bg
import android.net.Network
import android.os.Build
import com.ccnet.acc.AccVpn
import com.ccnet.acc.NetworkAdapter
import com.github.shadowsocks.Core
......@@ -10,7 +9,6 @@ import com.github.shadowsocks.database.ProfileManager
import com.github.shadowsocks.http.*
import com.github.shadowsocks.preference.DataStore
import com.google.gson.Gson
import com.google.gson.JsonStreamParser
import com.google.gson.reflect.TypeToken
import com.tencent.mmkv.MMKV
import kotlinx.coroutines.*
......@@ -20,8 +18,8 @@ import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import timber.log.Timber
import java.io.File
import java.io.IOException
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Socket
import java.security.SecureRandom
......@@ -39,7 +37,7 @@ object AuthManager {
var scheduleAtFixedRate: ScheduledFuture<*>? = null
var scheduleAtFixedRate1: ScheduledFuture<*>? = null
val okHttpClient: OkHttpClient
private val okHttpClient: OkHttpClient
val gson: Gson
val mmkv = MMKV.mmkvWithID("InterProcessKV", MMKV.MULTI_PROCESS_MODE)
......@@ -47,13 +45,13 @@ object AuthManager {
init {
okHttpClient = OkHttpClient().newBuilder()
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
//https支持
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(initSSLSocketFactory(), initTrustManager())
.build()
.readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间
.writeTimeout(60, TimeUnit.SECONDS)//设置写的超时时间
.connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间
//https支持
.hostnameVerifier { hostname, session -> true }
.sslSocketFactory(initSSLSocketFactory(), initTrustManager())
.build()
gson = Gson()
}
......@@ -103,7 +101,7 @@ object AuthManager {
withContext(Dispatchers.IO) {
val gameId: Int = gameId?.toInt() ?: throw AuthException("游戏不存在")
val lineConfigResult =
postSync<LineConfig>("/api/acc/line", authToken, LineConfigReq(gameId, area))
postSync<LineConfig>("/api/acc/line", authToken, LineConfigReq(gameId, area))
if (lineConfigResult.isSuccessful()) {
val lineConfig = lineConfigResult.unwrapData()
profile.host = lineConfig.host
......@@ -126,15 +124,15 @@ object AuthManager {
if (data.state != BaseService.State.Connected) {
return
}
NetworkAdapter.initNetworks(Core.deviceStorage)
NetworkAdapter.initNetworks(Core.app)
scheduleAtFixedRate?.cancel(false)
var failedCount: Int = 0
scheduleAtFixedRate = executor.scheduleAtFixedRate({
if (data.state == BaseService.State.Connected) {
data.proxy?.let { proxyInstance ->
val refreshTokenResult = postSync<RefreshTokenRes>(
"/api/acc/line/refresh", authToken,
RefreshTokenReq(proxyInstance.profile.token ?: "")
"/api/acc/line/refresh", authToken,
RefreshTokenReq(proxyInstance.profile.token ?: "")
)
Timber.d("refreshTokenResult: $refreshTokenResult")
if (refreshTokenResult.isSuccessful()) {
......@@ -161,26 +159,28 @@ object AuthManager {
}, 1, 1, TimeUnit.MINUTES)
scheduleAtFixedRate1?.cancel(false)
scheduleAtFixedRate1 = executor.scheduleAtFixedRate(
{
Timber.d("testLatency")
GlobalScope.launch {
testLatency()
if (wifiLatencyList.size == 5) {
val wifiavg = wifiLatencyList.average().toInt()
val celavg = cellularLatencyList.average().toInt()
if (wifiavg > celavg && wifiavg > 200 && celavg != -1) {
NetworkAdapter.useCellular(Core.deviceStorage)
} else if (celavg > wifiavg && wifiavg != -1) {
NetworkAdapter.useWifi(Core.deviceStorage)
{
Timber.d("testLatency")
GlobalScope.launch {
testLatency()
if (wifiLatencyList.size == 5) {
val wifiavg = wifiLatencyList.average().toInt()
val celavg = cellularLatencyList.average().toInt()
if (wifiavg > celavg && wifiavg > 200 && celavg != -1) {
NetworkAdapter.useCellular(Core.deviceStorage)
Timber.d("switch to cellular")
} else if (celavg > wifiavg && wifiavg != -1) {
NetworkAdapter.useWifi(Core.deviceStorage)
Timber.d("switch to wifi")
}
wifiLatencyList.clear()
cellularLatencyList.clear()
}
wifiLatencyList.clear()
cellularLatencyList.clear()
}
}
},
20,
20,
TimeUnit.SECONDS
},
1,
1,
TimeUnit.SECONDS
)
}
......@@ -189,18 +189,18 @@ object AuthManager {
private suspend fun testLatency() {
val networkAutoSwitch =
isSmartAccOpen // 根据用户设置测试延迟 ,过高时切换 connection.bindNetwork(NetworkMode.CELLULAR.code)
isSmartAccOpen // 根据用户设置测试延迟 ,过高时切换 connection.bindNetwork(NetworkMode.CELLULAR.code)
if (networkAutoSwitch) {
val wifiLatency: Int = doTestLatency(
"114.114.114.114",
53,
NetworkAdapter.wifiNetwork
"114.114.114.114",
53,
NetworkAdapter.wifiNetwork
)
wifiLatencyList.add(wifiLatency)
val cellularLatency: Int = doTestLatency(
"114.114.114.114",
53,
NetworkAdapter.cellularNetwork
"114.114.114.114",
53,
NetworkAdapter.cellularNetwork
)
cellularLatencyList.add(cellularLatency)
Timber.d("wifi latency: $wifiLatency, cellular latency: $cellularLatency")
......@@ -208,10 +208,10 @@ object AuthManager {
}
private suspend fun doTestLatency(
pingHost: String,
pingPort: Int,
network: Network?,
systemNetwork: Boolean = false
pingHost: String,
pingPort: Int,
network: Network?,
systemNetwork: Boolean = false
): Int {
return withTimeoutOrNull(DataStore.pingTimeoutMillis.toLong()) {
try {
......@@ -228,8 +228,8 @@ object AuthManager {
}
val start = System.currentTimeMillis()
socketAddress.connect(
InetSocketAddress(pingHost, pingPort),
DataStore.pingTimeoutMillis
InetSocketAddress(pingHost, pingPort),
DataStore.pingTimeoutMillis
)
(System.currentTimeMillis() - start).toInt()
} catch (_: Exception) {
......@@ -240,17 +240,17 @@ object AuthManager {
var loginAuthToken: String = "1"
val jsonType get() = "application/json; charset=utf-8".toMediaTypeOrNull()
private val jsonType get() = "application/json; charset=utf-8".toMediaTypeOrNull()
inline fun <reified T> postSync(
url: String,
token: String?,
params: Any
private inline fun <reified T> postSync(
url: String,
token: String?,
params: Any
): ApiResult<T> {
val body: RequestBody = gson.toJson(params).toString().toRequestBody(jsonType)
val request = Request.Builder()
.url(if (url.startsWith("http")) url else HttpConfig.baseUrl + url)
.post(body)
.url(if (url.startsWith("http")) url else HttpConfig.baseUrl + url)
.post(body)
token?.let {
request.addHeader("Authorization", it)
}
......@@ -274,15 +274,69 @@ object AuthManager {
sslContext = SSLContext.getInstance("SSL")
val xTrustArray = arrayOf(initTrustManager())
sslContext.init(
null,
xTrustArray, SecureRandom()
null,
xTrustArray, SecureRandom()
)
} catch (e: Exception) {
e.printStackTrace()
}
return sslContext!!.socketFactory
return AutoSwitchNetworkSocketFactory(sslContext!!.socketFactory)
}
private class AutoSwitchNetworkSocketFactory(private val delegate: SSLSocketFactory) : SSLSocketFactory() {
override fun createSocket(s: Socket?, host: String?, port: Int, autoClose: Boolean): Socket {
val bindNetwork = NetworkAdapter.bindNetwork
val createSocket = delegate.createSocket(s, host, port, autoClose)
bindNetwork?.bindSocket(createSocket)
return createSocket
}
override fun createSocket(host: String?, port: Int): Socket {
val bindNetwork = NetworkAdapter.bindNetwork
return if (bindNetwork != null) {
bindNetwork.socketFactory.createSocket(host, port)
} else {
delegate.createSocket(host, port)
}
}
override fun createSocket(host: String?, port: Int, localHost: InetAddress?, localPort: Int): Socket {
val bindNetwork = NetworkAdapter.bindNetwork
return if (bindNetwork != null) {
bindNetwork.socketFactory.createSocket(host, port, localHost, localPort)
} else {
delegate.createSocket(host, port, localHost, localPort)
}
}
override fun createSocket(host: InetAddress?, port: Int): Socket {
val bindNetwork = NetworkAdapter.bindNetwork
return if (bindNetwork != null) {
bindNetwork.socketFactory.createSocket(host, port)
} else {
delegate.createSocket(host, port)
}
}
override fun createSocket(address: InetAddress?, port: Int, localAddress: InetAddress?, localPort: Int): Socket {
val bindNetwork = NetworkAdapter.bindNetwork
return if (bindNetwork != null) {
bindNetwork.socketFactory.createSocket(address, port, localAddress, localPort)
} else {
delegate.createSocket(address, port, localAddress, localPort)
}
}
override fun getDefaultCipherSuites(): Array<String> {
return delegate.defaultCipherSuites
}
override fun getSupportedCipherSuites(): Array<String> {
return delegate.supportedCipherSuites
}
}
private fun initTrustManager(): X509TrustManager {
......
......@@ -23,6 +23,7 @@ package com.github.shadowsocks.bg
import android.net.LocalSocket
import android.os.SystemClock
import com.ccnet.acc.AccVpnService
import com.ccnet.acc.NetworkAdapter
import com.ccnet.acc.TestLatencyCallback
import com.github.shadowsocks.aidl.TrafficStats
import com.github.shadowsocks.database.ProfileManager
......@@ -72,6 +73,7 @@ class TrafficMonitor(statFile: File?) {
override fun run() {
Timber.d("TrafficMonitor-NativePing prepare test ${DataStore.pingAccHost}:${DataStore.pingAccPort}")
var bindNetwork = NetworkAdapter.bindNetwork
while (running) {
val resultCode = AccVpnService.instance.testLatency(
DataStore.pingProxyServer,
......@@ -80,10 +82,15 @@ class TrafficMonitor(statFile: File?) {
DataStore.pingIntervalSec,
DataStore.pingTimeoutMillis,
object : TestLatencyCallback {
override fun onLatency(latency: Int) {
override fun onLatency(latency: Int): Boolean {
Timber.d("TrafficMonitor-NativeTcpPing test ${current.latency}")
current.latency = latency
dirty = true
val cont = bindNetwork == NetworkAdapter.bindNetwork
if (!cont) {
bindNetwork = NetworkAdapter.bindNetwork
}
return cont
}
}
)
......
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