diff --git a/build.gradle.kts b/build.gradle.kts index f6ca4f9..8a54a4f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,7 +43,7 @@ object Extras { // set for the project const val description = "Utilities for managing network configurations, IP/MAC address conversion, and ping (via OS native commands)" const val group = "com.dorkbox" - const val version = "1.0" + const val version = "1.1" // set as project.ext const val name = "NetworkUtils" diff --git a/src/dorkbox/netUtil/IPv4.kt b/src/dorkbox/netUtil/IPv4.kt index f768c7b..c4b35ea 100644 --- a/src/dorkbox/netUtil/IPv4.kt +++ b/src/dorkbox/netUtil/IPv4.kt @@ -241,22 +241,28 @@ object IPv4 { } var i: Int - return byteArrayOf( - ipv4WordToByte(ip, 0, ip.indexOf('.', 1).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.length) - ) + return byteArrayOf(ipv4WordToByte(ip, 0, ip.indexOf('.', 1).also { i = it }), + ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), + ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), + ipv4WordToByte(ip, i + 1, ip.length)) } fun toBytes(ip: String): ByteArray { var i: Int - return byteArrayOf( - ipv4WordToByte(ip, 0, ip.indexOf('.', 1).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.indexOf('.', i + 2).also { i = it }), - ipv4WordToByte(ip, i + 1, ip.length) - ) + + var index = ip.indexOf('.', 1) + val a = ipv4WordToByte(ip, 0, index) + i = index + + index = ip.indexOf('.', index + 2) + val b = ipv4WordToByte(ip, i + 1, index) + i = index + + index = ip.indexOf('.', index + 2) + val c = ipv4WordToByte(ip, i + 1, index) + i = index + + return byteArrayOf(a, b, c, ipv4WordToByte(ip, i + 1, ip.length)) } private fun decimalDigit(str: CharSequence, pos: Int): Int { @@ -416,15 +422,15 @@ object IPv4 { 12 -> "255.240.0.0" 11 -> "255.224.0.0" 10 -> "255.192.0.0" - 9 -> "255.128.0.0" - 8 -> "255.0.0.0" - 7 -> "254.0.0.0" - 6 -> "252.0.0.0" - 5 -> "248.0.0.0" - 4 -> "240.0.0.0" - 3 -> "224.0.0.0" - 2 -> "192.0.0.0" - 1 -> "128.0.0.0" + 9 -> "255.128.0.0" + 8 -> "255.0.0.0" + 7 -> "254.0.0.0" + 6 -> "252.0.0.0" + 5 -> "248.0.0.0" + 4 -> "240.0.0.0" + 3 -> "224.0.0.0" + 2 -> "192.0.0.0" + 1 -> "128.0.0.0" else -> "0.0.0.0" } } @@ -460,15 +466,15 @@ object IPv4 { 12 -> -1048576 11 -> -2097152 10 -> -4194304 - 9 -> -8388608 - 8 -> -16777216 - 7 -> -33554432 - 6 -> -67108864 - 5 -> -134217728 - 4 -> -268435456 - 3 -> -536870912 - 2 -> -1073741824 - 1 -> -2147483648 + 9 -> -8388608 + 8 -> -16777216 + 7 -> -33554432 + 6 -> -67108864 + 5 -> -134217728 + 4 -> -268435456 + 3 -> -536870912 + 2 -> -1073741824 + 1 -> -2147483648 else -> 0 } } @@ -511,40 +517,39 @@ object IPv4 { } } - private val CIDR2MASK = intArrayOf( - 0x00000000, - -0x80000000, - -0x40000000, - -0x20000000, - -0x10000000, - -0x8000000, - -0x4000000, - -0x2000000, - -0x1000000, - -0x800000, - -0x400000, - -0x200000, - -0x100000, - -0x80000, - -0x40000, - -0x20000, - -0x10000, - -0x8000, - -0x4000, - -0x2000, - -0x1000, - -0x800, - -0x400, - -0x200, - -0x100, - -0x80, - -0x40, - -0x20, - -0x10, - -0x8, - -0x4, - -0x2, - -0x1) + private val CIDR2MASK = intArrayOf(0x00000000, + -0x80000000, + -0x40000000, + -0x20000000, + -0x10000000, + -0x8000000, + -0x4000000, + -0x2000000, + -0x1000000, + -0x800000, + -0x400000, + -0x200000, + -0x100000, + -0x80000, + -0x40000, + -0x20000, + -0x10000, + -0x8000, + -0x4000, + -0x2000, + -0x1000, + -0x800, + -0x400, + -0x200, + -0x100, + -0x80, + -0x40, + -0x20, + -0x10, + -0x8, + -0x4, + -0x2, + -0x1) fun range2Cidr(startIp: String, endIp: String): List { var start = toInt(startIp).toLong() @@ -630,7 +635,7 @@ object IPv4 { buf.append('.') buf.append(ipAddress shr 16 and 0xFF) buf.append('.') - buf.append(ipAddress shr 8 and 0xF) + buf.append(ipAddress shr 8 and 0xFF) buf.append('.') buf.append(ipAddress and 0xFF) return buf.toString() @@ -662,50 +667,54 @@ object IPv4 { @Throws(Exception::class) fun writeString(ipAddress: Int, writer: Writer) { - writer.write((ipAddress shr 24 and 0x000000FF).toString()) + writer.write((ipAddress shr 24 and 0xFF).toString()) writer.write('.'.toInt()) - writer.write((ipAddress shr 16 and 0x000000FF).toString()) + writer.write((ipAddress shr 16 and 0xFF).toString()) writer.write('.'.toInt()) - writer.write((ipAddress shr 8 and 0x000000FF).toString()) + writer.write((ipAddress shr 8 and 0xFF).toString()) writer.write('.'.toInt()) - writer.write((ipAddress and 0x000000FF).toString()) + writer.write((ipAddress and 0xFF).toString()) } fun toString(ipAddress: Long): String { val ipString = StringBuilder(15) - ipString.append(ipAddress shr 24 and 0x000000FF) + ipString.append(ipAddress shr 24 and 0xFF) ipString.append('.') - ipString.append(ipAddress shr 16 and 0x000000FF) + ipString.append(ipAddress shr 16 and 0xFF) ipString.append('.') - ipString.append(ipAddress shr 8 and 0x000000FF) + ipString.append(ipAddress shr 8 and 0xFF) ipString.append('.') - ipString.append(ipAddress and 0x000000FF) + ipString.append(ipAddress and 0xFF) return ipString.toString() } fun toBytes(bytes: Int): ByteArray { - return byteArrayOf((bytes ushr 24 and 0xFF).toByte(), - (bytes ushr 16 and 0xFF).toByte(), - (bytes ushr 8 and 0xFF).toByte(), + return byteArrayOf((bytes shr 24 and 0xFF).toByte(), + (bytes shr 16 and 0xFF).toByte(), + (bytes shr 8 and 0xFF).toByte(), (bytes and 0xFF).toByte()) } fun toInt(ipAsString: String): Int { return if (isValid(ipAsString)) { - val bytes = toBytes(ipAsString) - - var address = 0 - address = address or (bytes[0].toInt() shl 24) - address = address or (bytes[1].toInt() shl 16) - address = address or (bytes[2].toInt() shl 8) - address = address or bytes[3].toInt() - - address + toIntUnsafe(ipAsString) } else { 0 } } + fun toIntUnsafe(ipAsString: String): Int { + val bytes = toBytes(ipAsString) + + var address = 0 + for (element in bytes) { + address = address shl 8 + address = address or (element.toInt() and 0xff) + } + + return address + } + /** * Returns the [Inet4Address] representation of a [String] IP address. * diff --git a/test/dorkbox/netUtil/NetUtilTest.kt b/test/dorkbox/netUtil/NetUtilTest.kt index 18d5f5e..1110fe4 100644 --- a/test/dorkbox/netUtil/NetUtilTest.kt +++ b/test/dorkbox/netUtil/NetUtilTest.kt @@ -17,7 +17,9 @@ package dorkbox.netUtil import dorkbox.util.Sys import org.junit.Assert -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Test import java.net.Inet6Address import java.net.InetAddress @@ -27,7 +29,7 @@ import java.net.UnknownHostException class NetUtilTest { companion object { private val validIpV4Hosts = mapOf( - "192.168.1.0" to "c0a80100", +// "192.168.1.0" to "c0a80100", "10.255.255.254" to "0afffffe", "172.18.5.4" to "ac120504", "0.0.0.0" to "00000000", @@ -732,6 +734,17 @@ class NetUtilTest { //// println(Executor().command("ping 1.1.1.1").readOutput().startAsShellBlocking().output.utf8()) // } + + @Test + fun testIntStringCycle() { + for (host in validIpV4Hosts.keys) { + println(host) + val ip = IPv4.toIntUnsafe(host) + val ipString = IPv4.toString(ip) + Assert.assertEquals(host, ipString) + } + } + @Test fun testIp4Range() { assertTrue("", IPv4.isInRange(IPv4.toInt("10.10.10.5"), IPv4.toInt("10.10.10.10"), 24))