Commit fb8e18c8 authored by Mygod's avatar Mygod

Clean up unused code

parent 91632d10
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
path = core/src/main/jni/badvpn path = core/src/main/jni/badvpn
url = https://github.com/shadowsocks/badvpn.git url = https://github.com/shadowsocks/badvpn.git
branch = shadowsocks-android branch = shadowsocks-android
[submodule "core/src/main/jni/libancillary"]
path = core/src/main/jni/libancillary
url = https://github.com/shadowsocks/libancillary.git
[submodule "core/src/main/jni/libevent"] [submodule "core/src/main/jni/libevent"]
path = core/src/main/jni/libevent path = core/src/main/jni/libevent
url = https://github.com/shadowsocks/libevent.git url = https://github.com/shadowsocks/libevent.git
...@@ -10,12 +13,6 @@ ...@@ -10,12 +13,6 @@
path = core/src/main/jni/redsocks path = core/src/main/jni/redsocks
url = https://github.com/shadowsocks/redsocks.git url = https://github.com/shadowsocks/redsocks.git
branch = shadowsocks-android branch = shadowsocks-android
[submodule "core/src/main/jni/re2"]
path = core/src/main/jni/re2
url = https://github.com/google/re2.git
[submodule "core/src/main/rust/shadowsocks-rust"] [submodule "core/src/main/rust/shadowsocks-rust"]
path = core/src/main/rust/shadowsocks-rust path = core/src/main/rust/shadowsocks-rust
url = https://github.com/madeye/shadowsocks-rust url = https://github.com/madeye/shadowsocks-rust
[submodule "core/src/main/jni/libancillary"]
path = core/src/main/jni/libancillary
url = https://github.com/shadowsocks/libancillary.git
/*******************************************************************************
* *
* Copyright (C) 2020 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2020 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package com.github.shadowsocks.acl
import androidx.test.core.app.ApplicationProvider
import com.github.shadowsocks.Core
import com.github.shadowsocks.utils.parseNumericAddress
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.BeforeClass
import org.junit.Test
class AclMatcherTest {
companion object {
@BeforeClass
@JvmStatic
fun setup() {
Core.app = ApplicationProvider.getApplicationContext()
}
}
@Test
fun emptyFile() {
runBlocking {
AclMatcher().apply {
init(AclTest.BYPASS_BASE.reader())
Assert.assertTrue(shouldBypassIpv4(ByteArray(4)))
Assert.assertTrue(shouldBypassIpv6(ByteArray(16)))
Assert.assertNull(shouldBypass("www.google.com"))
}
}
}
@Test
fun basic() {
runBlocking {
AclMatcher().apply {
init(AclTest.INPUT1.reader())
Assert.assertTrue(shouldBypassIpv4("0.1.2.3".parseNumericAddress()!!.address))
Assert.assertFalse(shouldBypassIpv4("1.0.1.2".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypassIpv4("1.0.3.2".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypassIpv6("::".parseNumericAddress()!!.address))
Assert.assertFalse(shouldBypassIpv6("2020::2020".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypassIpv6("fe80::2020".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypass("4tern.com") == false)
Assert.assertTrue(shouldBypass("www.4tern.com") == false)
Assert.assertNull(shouldBypass("www.google.com"))
}
}
}
@Test
fun bypassList() {
runBlocking {
AclMatcher().apply {
init(AclTest.INPUT2.reader())
Assert.assertFalse(shouldBypassIpv4("0.1.2.3".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypassIpv4("10.0.1.2".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypassIpv4("10.10.1.2".parseNumericAddress()!!.address))
Assert.assertFalse(shouldBypassIpv4("11.0.1.2".parseNumericAddress()!!.address))
Assert.assertTrue(shouldBypass("chrome.com") == true)
Assert.assertTrue(shouldBypass("about.google") == false)
Assert.assertNull(shouldBypass("www.google.com"))
}
}
}
}
/*******************************************************************************
* *
* Copyright (C) 2019 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2019 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package com.github.shadowsocks.acl
import com.github.shadowsocks.Core
import com.github.shadowsocks.net.Subnet
import java.io.Reader
import java.net.Inet4Address
import java.net.Inet6Address
class AclMatcher : AutoCloseable {
companion object {
init {
System.loadLibrary("jni-helper")
}
@JvmStatic private external fun init(): Long
@JvmStatic private external fun close(handle: Long)
@JvmStatic private external fun addBypassDomain(handle: Long, regex: String): Boolean
@JvmStatic private external fun addProxyDomain(handle: Long, regex: String): Boolean
@JvmStatic private external fun build(handle: Long, memoryLimit: Long): String?
@JvmStatic private external fun matchHost(handle: Long, host: String): Int
}
class Re2Exception(message: String) : IllegalArgumentException(message)
private var handle = 0L
override fun close() {
if (handle != 0L) {
close(handle)
handle = 0L
}
}
private var subnetsIpv4 = emptyList<Subnet.Immutable>()
private var subnetsIpv6 = emptyList<Subnet.Immutable>()
private var bypass = false
suspend fun init(id: String) = init(Acl.getFile(id).bufferedReader())
suspend fun init(reader: Reader) {
fun Sequence<Subnet>.dedup() = sequence {
val iterator = map { it.toImmutable() }.sortedWith(Subnet.Immutable).iterator()
var current: Subnet.Immutable? = null
while (iterator.hasNext()) {
val next = iterator.next()
if (current?.matches(next) == true) continue
yield(next)
current = next
}
}.toList()
check(handle == 0L)
handle = init()
try {
val (bypass, subnets) = Acl.parse(reader, {
check(addBypassDomain(handle, it))
}, {
check(addProxyDomain(handle, it))
})
build(handle, if (Core.activity.isLowRamDevice) 8 shl 20 else 64 shl 20)?.also { throw Re2Exception(it) }
subnetsIpv4 = subnets.asSequence().filter { it.address is Inet4Address }.dedup()
subnetsIpv6 = subnets.asSequence().filter { it.address is Inet6Address }.dedup()
this.bypass = bypass
} catch (e: Exception) {
close()
throw e
}
}
private fun quickMatches(subnets: List<Subnet.Immutable>, ip: ByteArray): Boolean {
val i = subnets.binarySearch(Subnet.Immutable(ip), Subnet.Immutable)
return i >= 0 || i < -1 && subnets[-i - 2].matches(ip)
}
fun shouldBypassIpv4(ip: ByteArray) = bypass xor quickMatches(subnetsIpv4, ip)
fun shouldBypassIpv6(ip: ByteArray) = bypass xor quickMatches(subnetsIpv6, ip)
fun shouldBypass(host: String) = when (val e = matchHost(handle, host)) {
0 -> null
1 -> true
2 -> false
else -> error("matchHost -> $e")
}
}
...@@ -31,15 +31,12 @@ import android.system.ErrnoException ...@@ -31,15 +31,12 @@ import android.system.ErrnoException
import android.system.Os import android.system.Os
import android.system.OsConstants import android.system.OsConstants
import com.github.shadowsocks.Core import com.github.shadowsocks.Core
import com.github.shadowsocks.net.LocalDnsServer
import com.github.shadowsocks.utils.closeQuietly import com.github.shadowsocks.utils.closeQuietly
import com.github.shadowsocks.utils.int import com.github.shadowsocks.utils.int
import com.github.shadowsocks.utils.parseNumericAddress import com.github.shadowsocks.utils.parseNumericAddress
import com.github.shadowsocks.utils.printLog import com.github.shadowsocks.utils.printLog
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.xbill.DNS.Message import org.xbill.DNS.*
import org.xbill.DNS.Opcode
import org.xbill.DNS.Type
import java.io.FileDescriptor import java.io.FileDescriptor
import java.io.IOException import java.io.IOException
import java.net.Inet4Address import java.net.Inet4Address
...@@ -102,6 +99,20 @@ sealed class DnsResolverCompat { ...@@ -102,6 +99,20 @@ sealed class DnsResolverCompat {
override suspend fun resolveOnActiveNetwork(host: String) = instance.resolveOnActiveNetwork(host) override suspend fun resolveOnActiveNetwork(host: String) = instance.resolveOnActiveNetwork(host)
override suspend fun resolveRaw(network: Network, query: ByteArray) = instance.resolveRaw(network, query) override suspend fun resolveRaw(network: Network, query: ByteArray) = instance.resolveRaw(network, query)
override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = instance.resolveRawOnActiveNetwork(query) override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = instance.resolveRawOnActiveNetwork(query)
// additional platform-independent DNS helpers
/**
* TTL returned from localResolver is set to 120. Android API does not provide TTL,
* so we suppose Android apps should not care about TTL either.
*/
private const val TTL = 120L
fun prepareDnsResponse(request: Message) = Message(request.header.id).apply {
header.setFlag(Flags.QR.toInt()) // this is a response
if (request.header.getFlag(Flags.RD.toInt())) header.setFlag(Flags.RD.toInt())
request.question?.also { addRecord(it, Section.QUESTION) }
}
} }
@Throws(IOException::class) @Throws(IOException::class)
...@@ -167,9 +178,16 @@ sealed class DnsResolverCompat { ...@@ -167,9 +178,16 @@ sealed class DnsResolverCompat {
else -> throw UnsupportedOperationException("Unsupported query type $type") else -> throw UnsupportedOperationException("Unsupported query type $type")
} }
val host = question.name.canonicalize().toString(true) val host = question.name.canonicalize().toString(true)
return LocalDnsServer.cookDnsResponse(request, hostResolver(host).asIterable().run { return prepareDnsResponse(request).apply {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>() header.setFlag(Flags.RA.toInt()) // recursion available
}) for (address in hostResolver(host).asIterable().run {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>()
}) addRecord(when (address) {
is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address)
is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address)
else -> error("Unsupported address $address")
}, Section.ANSWER)
}.toWire()
} }
override suspend fun resolveRaw(network: Network, query: ByteArray) = override suspend fun resolveRaw(network: Network, query: ByteArray) =
resolveRaw(query) { resolve(network, it) } resolveRaw(query) { resolve(network, it) }
......
...@@ -5,7 +5,6 @@ import android.util.Log ...@@ -5,7 +5,6 @@ import android.util.Log
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.Core import com.github.shadowsocks.Core
import com.github.shadowsocks.net.ConcurrentLocalSocketListener import com.github.shadowsocks.net.ConcurrentLocalSocketListener
import com.github.shadowsocks.net.LocalDnsServer
import com.github.shadowsocks.utils.printLog import com.github.shadowsocks.utils.printLog
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
...@@ -37,7 +36,7 @@ class LocalDnsWorker(private val resolver: suspend (ByteArray) -> ByteArray) : C ...@@ -37,7 +36,7 @@ class LocalDnsWorker(private val resolver: suspend (ByteArray) -> ByteArray) : C
else -> printLog(e) else -> printLog(e)
} }
try { try {
LocalDnsServer.prepareDnsResponse(Message(query)).apply { DnsResolverCompat.prepareDnsResponse(Message(query)).apply {
header.rcode = Rcode.SERVFAIL header.rcode = Rcode.SERVFAIL
}.toWire() }.toWire()
} catch (_: IOException) { } catch (_: IOException) {
......
/*******************************************************************************
* *
* Copyright (C) 2019 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2019 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
package com.github.shadowsocks.net
import android.util.Log
import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.acl.AclMatcher
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.printLog
import kotlinx.coroutines.*
import org.xbill.DNS.*
import java.io.IOException
import java.net.*
import java.nio.ByteBuffer
import java.nio.channels.DatagramChannel
import java.nio.channels.SelectionKey
import java.nio.channels.SocketChannel
/**
* A simple DNS conditional forwarder.
*
* No cache is provided as localResolver may change from time to time. We expect DNS clients to do cache themselves.
*
* Based on:
* https://github.com/bitcoinj/httpseed/blob/809dd7ad9280f4bc98a356c1ffb3d627bf6c7ec5/src/main/kotlin/dns.kt
* https://github.com/shadowsocks/overture/tree/874f22613c334a3b78e40155a55479b7b69fee04
*/
class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAddress>,
private val hosts: HostsFile) : CoroutineScope {
companion object {
private const val TAG = "LocalDnsServer"
private const val TIMEOUT = 10_000L
/**
* TTL returned from localResolver is set to 120. Android API does not provide TTL,
* so we suppose Android apps should not care about TTL either.
*/
private const val TTL = 120L
private const val UDP_PACKET_SIZE = 512
fun emptyDnsResponse() = Message().apply {
header.setFlag(Flags.QR.toInt()) // this is a response
}
fun prepareDnsResponse(request: Message) = Message(request.header.id).apply {
header.setFlag(Flags.QR.toInt()) // this is a response
if (request.header.getFlag(Flags.RD.toInt())) header.setFlag(Flags.RD.toInt())
request.question?.also { addRecord(it, Section.QUESTION) }
}
fun cookDnsResponse(request: Message, results: Iterable<InetAddress>) = prepareDnsResponse(request).apply {
header.setFlag(Flags.RA.toInt()) // recursion available
for (address in results) addRecord(when (address) {
is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address)
is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address)
else -> error("Unsupported address $address")
}, Section.ANSWER)
}.toWire()
}
private val monitor = ChannelMonitor()
override val coroutineContext = SupervisorJob() + CoroutineExceptionHandler { _, t ->
if (t is IOException) Crashlytics.log(Log.WARN, TAG, t.message) else printLog(t)
}
suspend fun start(listen: SocketAddress) = DatagramChannel.open().run {
configureBlocking(false)
try {
socket().bind(listen)
} catch (e: BindException) {
throw BaseService.ExpectedExceptionWrapper(e)
}
monitor.register(this, SelectionKey.OP_READ) { handlePacket(this) }
}
private fun handlePacket(channel: DatagramChannel) {
val buffer = ByteBuffer.allocateDirect(UDP_PACKET_SIZE)
val source = channel.receive(buffer)!!
buffer.flip()
launch {
val reply = resolve(buffer)
while (channel.send(reply, source) <= 0) monitor.wait(channel, SelectionKey.OP_WRITE)
}
}
private suspend fun resolve(packet: ByteBuffer): ByteBuffer {
val request = try {
Message(packet)
} catch (e: IOException) { // we cannot parse the message, do not attempt to handle it at all
Crashlytics.log(Log.WARN, TAG, e.message)
return ByteBuffer.wrap(emptyDnsResponse().apply {
header.rcode = Rcode.SERVFAIL
}.toWire())
}
val question = request.question
val isIpv6 = when (question?.type) {
Type.A -> false
Type.AAAA -> true
else -> return ByteBuffer.wrap(prepareDnsResponse(request).apply {
header.rcode = Rcode.SERVFAIL
}.toWire())
}
val host = question.name.canonicalize().toString(true)
val hostsResults = hosts.resolve(host)
if (hostsResults.isNotEmpty()) {
return ByteBuffer.wrap(cookDnsResponse(request, hostsResults.run {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>()
}))
}
Log.d("dns", "host: " + host)
val localResults = try {
withTimeout(TIMEOUT) { localResolver(host) }
} catch (e: java.lang.Exception) {
when (e) {
is TimeoutCancellationException -> Crashlytics.log(Log.WARN, TAG, "Remote resolving timed out")
is CancellationException -> { } // ignore
is IOException -> Crashlytics.log(Log.WARN, TAG, e.message)
else -> printLog(e)
}
return ByteBuffer.wrap(prepareDnsResponse(request).apply {
header.rcode = Rcode.SERVFAIL
}.toWire())
}
val filtered = if (isIpv6) {
localResults.filterIsInstance<Inet6Address>()
} else {
localResults.filterIsInstance<Inet4Address>()
}
return ByteBuffer.wrap(cookDnsResponse(request, filtered))
}
fun shutdown(scope: CoroutineScope) {
cancel()
monitor.close(scope)
scope.launch {
this@LocalDnsServer.coroutineContext[Job]!!.join()
}
}
}
...@@ -73,39 +73,6 @@ LOCAL_CFLAGS := -std=gnu99 -DUSE_IPTABLES \ ...@@ -73,39 +73,6 @@ LOCAL_CFLAGS := -std=gnu99 -DUSE_IPTABLES \
include $(BUILD_SHARED_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
########################################################
## jni-helper
########################################################
include $(CLEAR_VARS)
LOCAL_MODULE:= jni-helper
LOCAL_C_INCLUDES := $(LOCAL_PATH)/re2
LOCAL_CFLAGS := -std=c++17
LOCAL_SRC_FILES := jni-helper.cpp \
$(LOCAL_PATH)/re2/re2/bitstate.cc \
$(LOCAL_PATH)/re2/re2/compile.cc \
$(LOCAL_PATH)/re2/re2/dfa.cc \
$(LOCAL_PATH)/re2/re2/nfa.cc \
$(LOCAL_PATH)/re2/re2/onepass.cc \
$(LOCAL_PATH)/re2/re2/parse.cc \
$(LOCAL_PATH)/re2/re2/perl_groups.cc \
$(LOCAL_PATH)/re2/re2/prog.cc \
$(LOCAL_PATH)/re2/re2/re2.cc \
$(LOCAL_PATH)/re2/re2/regexp.cc \
$(LOCAL_PATH)/re2/re2/simplify.cc \
$(LOCAL_PATH)/re2/re2/stringpiece.cc \
$(LOCAL_PATH)/re2/re2/tostring.cc \
$(LOCAL_PATH)/re2/re2/unicode_casefold.cc \
$(LOCAL_PATH)/re2/re2/unicode_groups.cc \
$(LOCAL_PATH)/re2/util/rune.cc \
$(LOCAL_PATH)/re2/util/strutil.cc
include $(BUILD_SHARED_LIBRARY)
######################################################## ########################################################
## tun2socks ## tun2socks
######################################################## ########################################################
......
/*******************************************************************************
* *
* Copyright (C) 2019 by Max Lv <max.c.lv@gmail.com> *
* Copyright (C) 2019 by Mygod Studio <contact-shadowsocks-android@mygod.be> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#include <sstream>
#include "jni.h"
#include "re2/re2.h"
using namespace std;
struct AclMatcher {
stringstream bypassDomainsBuilder, proxyDomainsBuilder;
RE2 *bypassDomains, *proxyDomains;
~AclMatcher() {
if (bypassDomains) delete bypassDomains;
if (proxyDomains) delete proxyDomains;
}
};
bool addDomain(JNIEnv *env, stringstream &domains, jstring regex) {
const char *regexChars = env->GetStringUTFChars(regex, nullptr);
if (regexChars == nullptr) return false;
if (domains.rdbuf()->in_avail()) domains << '|';
domains << regexChars;
env->ReleaseStringUTFChars(regex, regexChars);
return true;
}
const char *buildRE2(stringstream &domains, RE2 *&out, const RE2::Options &options) {
if (domains.rdbuf()->in_avail()) {
out = new RE2(domains.str(), options);
domains.clear();
if (!out->ok()) return out->error().c_str();
} else {
delete out;
out = nullptr;
}
return nullptr;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
extern "C" {
JNIEXPORT jlong JNICALL Java_com_github_shadowsocks_acl_AclMatcher_init(JNIEnv *env, jclass clazz) {
return reinterpret_cast<jlong>(new AclMatcher());
}
JNIEXPORT void JNICALL
Java_com_github_shadowsocks_acl_AclMatcher_close(JNIEnv *env, jclass clazz, jlong handle) {
delete reinterpret_cast<AclMatcher *>(handle);
}
JNIEXPORT jboolean JNICALL
Java_com_github_shadowsocks_acl_AclMatcher_addBypassDomain(JNIEnv *env, jclass clazz, jlong handle,
jstring regex) {
return static_cast<jboolean>(handle &&
::addDomain(env, reinterpret_cast<AclMatcher *>(handle)->bypassDomainsBuilder, regex));
}
JNIEXPORT jboolean JNICALL
Java_com_github_shadowsocks_acl_AclMatcher_addProxyDomain(JNIEnv *env, jclass clazz, jlong handle,
jstring regex) {
return static_cast<jboolean>(handle &&
::addDomain(env, reinterpret_cast<AclMatcher *>(handle)->proxyDomainsBuilder, regex));
}
JNIEXPORT jstring JNICALL
Java_com_github_shadowsocks_acl_AclMatcher_build(JNIEnv *env, jclass clazz, jlong handle,
jlong memory_limit) {
if (!handle) return env->NewStringUTF("AclMatcher closed");
auto matcher = reinterpret_cast<AclMatcher *>(handle);
RE2::Options options;
options.set_max_mem(memory_limit);
options.set_never_capture(true);
const char *e = ::buildRE2(matcher->bypassDomainsBuilder, matcher->bypassDomains, options);
if (e) return env->NewStringUTF(e);
e = ::buildRE2(matcher->proxyDomainsBuilder, matcher->proxyDomains, options);
if (e) return env->NewStringUTF(e);
return nullptr;
}
JNIEXPORT jint JNICALL
Java_com_github_shadowsocks_acl_AclMatcher_matchHost(JNIEnv *env, jclass clazz, jlong handle,
jstring host) {
if (!handle) return -1;
auto matcher = reinterpret_cast<const AclMatcher *>(handle);
const char *hostChars = env->GetStringUTFChars(host, nullptr);
jint result = 0;
if (matcher->bypassDomains && RE2::PartialMatch(hostChars, *matcher->bypassDomains)) result = 1;
else if (matcher->proxyDomains && RE2::PartialMatch(hostChars, *matcher->proxyDomains)) result = 2;
env->ReleaseStringUTFChars(host, hostChars);
return result;
}
}
Subproject commit bb8e777557ddbdeabdedea4f23613c5021ffd7b1
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