mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-09-14 00:35:08 +00:00
Tag sockets via OkHttp EventListener to cover proxied routes
The SocketFactory-based tagging missed SOCKS proxy (Tor) connections: ConnectPlan.connectSocket builds those sockets with Socket(proxy) directly, bypassing the configured SocketFactory, so the raw fd was created untagged on the TaskRunner thread and tripped StrictMode's UntaggedSocketViolation. The TaggingInterceptor didn't help either — it runs on the call/dispatch thread, not the connect thread. Replace TaggedSocketFactory, TaggedDns, and TaggingInterceptor with a single TrafficStatsEventListener that sets the thread stats tag in dnsStart/connectStart. Those callbacks fire on the exact thread that then opens the socket, for every route type (direct, HTTP, and SOCKS), so one listener covers them all. Wire it into the shared root client and the WebDav client. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1a40be3efa
commit
1318f0ae60
@@ -25,8 +25,6 @@ import com.greenart7c3.nostrsigner.Amber
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Proxy
|
||||
import java.time.Duration
|
||||
import javax.net.SocketFactory
|
||||
import okhttp3.Dns
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
object HttpClientManager {
|
||||
@@ -35,9 +33,7 @@ object HttpClientManager {
|
||||
.Builder()
|
||||
.followRedirects(true)
|
||||
.followSslRedirects(true)
|
||||
.socketFactory(TaggedSocketFactory(SocketFactory.getDefault()))
|
||||
.dns(TaggedDns(Dns.SYSTEM))
|
||||
.addInterceptor(TaggingInterceptor())
|
||||
.eventListener(TrafficStatsEventListener())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.greenart7c3.nostrsigner.okhttp
|
||||
|
||||
import android.net.TrafficStats
|
||||
import java.net.InetAddress
|
||||
import okhttp3.Dns
|
||||
|
||||
class TaggedDns(private val delegate: Dns) : Dns {
|
||||
override fun lookup(hostname: String): List<InetAddress> {
|
||||
if (TrafficStats.getThreadStatsTag() == -1) {
|
||||
TrafficStats.setThreadStatsTag(0x0001)
|
||||
}
|
||||
return delegate.lookup(hostname)
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.greenart7c3.nostrsigner.okhttp
|
||||
|
||||
import android.net.TrafficStats
|
||||
import java.net.InetAddress
|
||||
import java.net.Socket
|
||||
import javax.net.SocketFactory
|
||||
|
||||
class TaggedSocketFactory(private val delegate: SocketFactory) : SocketFactory() {
|
||||
private fun tag() {
|
||||
if (TrafficStats.getThreadStatsTag() == -1) {
|
||||
TrafficStats.setThreadStatsTag(0x0001)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createSocket(): Socket {
|
||||
tag()
|
||||
return delegate.createSocket()
|
||||
}
|
||||
|
||||
override fun createSocket(host: String?, port: Int): Socket {
|
||||
tag()
|
||||
val socket = delegate.createSocket(host, port)
|
||||
tagSocket(socket)
|
||||
return socket
|
||||
}
|
||||
|
||||
override fun createSocket(host: String?, port: Int, localHost: InetAddress?, localPort: Int): Socket {
|
||||
tag()
|
||||
val socket = delegate.createSocket(host, port, localHost, localPort)
|
||||
tagSocket(socket)
|
||||
return socket
|
||||
}
|
||||
|
||||
override fun createSocket(host: InetAddress?, port: Int): Socket {
|
||||
tag()
|
||||
val socket = delegate.createSocket(host, port)
|
||||
tagSocket(socket)
|
||||
return socket
|
||||
}
|
||||
|
||||
override fun createSocket(address: InetAddress?, port: Int, localAddress: InetAddress?, localPort: Int): Socket {
|
||||
tag()
|
||||
val socket = delegate.createSocket(address, port, localAddress, localPort)
|
||||
tagSocket(socket)
|
||||
return socket
|
||||
}
|
||||
|
||||
private fun tagSocket(socket: Socket) {
|
||||
if (socket.isConnected || socket.isBound) {
|
||||
TrafficStats.tagSocket(socket)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.greenart7c3.nostrsigner.okhttp
|
||||
|
||||
import android.net.TrafficStats
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
class TaggingInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
if (TrafficStats.getThreadStatsTag() == -1) {
|
||||
TrafficStats.setThreadStatsTag(0x0001)
|
||||
}
|
||||
return chain.proceed(chain.request())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.greenart7c3.nostrsigner.okhttp
|
||||
|
||||
import android.net.TrafficStats
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Proxy
|
||||
import okhttp3.Call
|
||||
import okhttp3.EventListener
|
||||
|
||||
/**
|
||||
* Tags the calling thread with a TrafficStats stats tag so the sockets OkHttp
|
||||
* opens are attributed to us, keeping StrictMode's untagged-socket detector
|
||||
* quiet.
|
||||
*
|
||||
* `dnsStart`/`connectStart` fire from OkHttp's route-planning and
|
||||
* `ConnectPlan.connectTcp` on the *same* (TaskRunner) thread that immediately
|
||||
* goes on to open the DNS/raw socket fd — and they fire for every route type,
|
||||
* including SOCKS proxies, where OkHttp builds the socket via `Socket(proxy)`
|
||||
* directly and bypasses the configured SocketFactory. A SocketFactory only
|
||||
* covers DIRECT routes; an EventListener covers them all.
|
||||
*/
|
||||
class TrafficStatsEventListener : EventListener() {
|
||||
private fun tagThread() {
|
||||
if (TrafficStats.getThreadStatsTag() == -1) {
|
||||
TrafficStats.setThreadStatsTag(0x0001)
|
||||
}
|
||||
}
|
||||
|
||||
override fun dnsStart(call: Call, domainName: String) = tagThread()
|
||||
|
||||
override fun connectStart(call: Call, inetSocketAddress: InetSocketAddress, proxy: Proxy) = tagThread()
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.greenart7c3.nostrsigner.service
|
||||
|
||||
import com.greenart7c3.nostrsigner.okhttp.TaggedSocketFactory
|
||||
import com.greenart7c3.nostrsigner.okhttp.TrafficStatsEventListener
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.net.SocketFactory
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
@@ -17,7 +16,7 @@ object WebDavService {
|
||||
.connectTimeout(30, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(60, TimeUnit.SECONDS)
|
||||
.socketFactory(TaggedSocketFactory(SocketFactory.getDefault()))
|
||||
.eventListener(TrafficStatsEventListener())
|
||||
.build()
|
||||
|
||||
fun uploadFile(
|
||||
|
||||
Reference in New Issue
Block a user