Commit ee11c896 authored by Mygod's avatar Mygod

Optimize Subnet.matches

parent cd744cb4
...@@ -25,14 +25,16 @@ import java.net.Inet4Address ...@@ -25,14 +25,16 @@ import java.net.Inet4Address
import java.net.Inet6Address import java.net.Inet6Address
class AclMatcher(acl: Acl) { class AclMatcher(acl: Acl) {
private val subnetsIpv4 = acl.subnets.asIterable().filter { it.address is Inet4Address } private val subnetsIpv4 =
private val subnetsIpv6 = acl.subnets.asIterable().filter { it.address is Inet6Address } acl.subnets.asIterable().filter { it.address is Inet4Address }.map { it to it.address.address }
private val subnetsIpv6 =
acl.subnets.asIterable().filter { it.address is Inet6Address }.map { it to it.address.address }
private val bypassDomains = acl.bypassHostnames.asIterable().map { it.toRegex() } private val bypassDomains = acl.bypassHostnames.asIterable().map { it.toRegex() }
private val proxyDomains = acl.proxyHostnames.asIterable().map { it.toRegex() } private val proxyDomains = acl.proxyHostnames.asIterable().map { it.toRegex() }
private val bypass = acl.bypass private val bypass = acl.bypass
fun shouldBypass(ip: Inet4Address) = bypass xor subnetsIpv4.any { it.matches(ip) } fun shouldBypassIpv4(ip: ByteArray) = bypass xor subnetsIpv4.any { (subnet, subnetIp) -> subnet.matches(subnetIp, ip) }
fun shouldBypass(ip: Inet6Address) = bypass xor subnetsIpv6.any { it.matches(ip) } fun shouldBypassIpv6(ip: ByteArray) = bypass xor subnetsIpv6.any { (subnet, subnetIp) -> subnet.matches(subnetIp, ip) }
fun shouldBypass(host: String): Boolean? { fun shouldBypass(host: String): Boolean? {
if (bypassDomains.any { it.matches(host) }) return true if (bypassDomains.any { it.matches(host) }) return true
if (proxyDomains.any { it.matches(host) }) return false if (proxyDomains.any { it.matches(host) }) return false
......
...@@ -145,14 +145,14 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd ...@@ -145,14 +145,14 @@ class LocalDnsServer(private val localResolver: suspend (String) -> Array<InetAd
if (isIpv6) { if (isIpv6) {
val filtered = localResults.filterIsInstance<Inet6Address>() val filtered = localResults.filterIsInstance<Inet6Address>()
if (useLocal) return@supervisorScope cookDnsResponse(request, filtered) if (useLocal) return@supervisorScope cookDnsResponse(request, filtered)
if (filtered.any { acl.shouldBypass(it) }) { if (filtered.any { acl.shouldBypassIpv6(it.address) }) {
remote.cancel() remote.cancel()
cookDnsResponse(request, filtered) cookDnsResponse(request, filtered)
} else remote.await() } else remote.await()
} else { } else {
val filtered = localResults.filterIsInstance<Inet4Address>() val filtered = localResults.filterIsInstance<Inet4Address>()
if (useLocal) return@supervisorScope cookDnsResponse(request, filtered) if (useLocal) return@supervisorScope cookDnsResponse(request, filtered)
if (filtered.any { acl.shouldBypass(it) }) { if (filtered.any { acl.shouldBypassIpv4(it.address) }) {
remote.cancel() remote.cancel()
cookDnsResponse(request, filtered) cookDnsResponse(request, filtered)
} else remote.await() } else remote.await()
......
...@@ -45,11 +45,12 @@ class Subnet(val address: InetAddress, val prefixSize: Int) : Comparable<Subnet> ...@@ -45,11 +45,12 @@ class Subnet(val address: InetAddress, val prefixSize: Int) : Comparable<Subnet>
require(prefixSize in 0..addressLength) { "prefixSize $prefixSize not in 0..$addressLength" } require(prefixSize in 0..addressLength) { "prefixSize $prefixSize not in 0..$addressLength" }
} }
fun matches(other: InetAddress): Boolean { /**
if (address.javaClass != other.javaClass) return false * Optimized version of matches.
// TODO optimize? * a corresponds to this address and b is the address in question.
val a = address.address */
val b = other.address fun matches(a: ByteArray, b: ByteArray): Boolean {
if (a.size != b.size) return false
var i = 0 var i = 0
while (i * 8 < prefixSize && i * 8 + 8 <= prefixSize) { while (i * 8 < prefixSize && i * 8 + 8 <= prefixSize) {
if (a[i] != b[i]) return false if (a[i] != b[i]) return false
......
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