Commit ee11c896 authored by Mygod's avatar Mygod

Optimize Subnet.matches

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