68 lines
3.2 KiB
Kotlin
68 lines
3.2 KiB
Kotlin
/*******************************************************************************
|
|
* *
|
|
* Copyright (C) 2017 by Max Lv <max.c.lv@gmail.com> *
|
|
* Copyright (C) 2017 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.utils
|
|
|
|
import java.net.InetAddress
|
|
import java.util.*
|
|
|
|
class Subnet(val address: InetAddress, val prefixSize: Int) : Comparable<Subnet> {
|
|
companion object {
|
|
@Throws(IllegalArgumentException::class)
|
|
fun fromString(value: String): Subnet {
|
|
val parts = value.split('/')
|
|
val addr = parts[0].parseNumericAddress()
|
|
return when (parts.size) {
|
|
1 -> Subnet(addr, addr.address.size shl 3)
|
|
2 -> Subnet(addr, parts[1].toInt())
|
|
else -> throw IllegalArgumentException()
|
|
}
|
|
}
|
|
}
|
|
|
|
private val addressLength get() = address.address.size shl 3
|
|
|
|
init {
|
|
if (prefixSize < 0 || prefixSize > addressLength) throw IllegalArgumentException()
|
|
}
|
|
|
|
override fun toString(): String =
|
|
if (prefixSize == addressLength) address.hostAddress else address.hostAddress + '/' + prefixSize
|
|
|
|
private fun Byte.unsigned() = toInt() and 0xFF
|
|
override fun compareTo(other: Subnet): Int {
|
|
val addrThis = address.address
|
|
val addrThat = other.address.address
|
|
var result = addrThis.size.compareTo(addrThat.size) // IPv4 address goes first
|
|
if (result != 0) return result
|
|
for ((x, y) in addrThis zip addrThat) {
|
|
result = x.unsigned().compareTo(y.unsigned()) // undo sign extension of signed byte
|
|
if (result != 0) return result
|
|
}
|
|
return prefixSize.compareTo(other.prefixSize)
|
|
}
|
|
|
|
override fun equals(other: Any?): Boolean {
|
|
val that = other as? Subnet
|
|
return address == that?.address && prefixSize == that.prefixSize
|
|
}
|
|
override fun hashCode(): Int = Objects.hash(address, prefixSize)
|
|
}
|