Skip to content

Commit 6fdba95

Browse files
authored
KTOR-8490 Do not parse ipString (#4912)
1 parent 9a045e8 commit 6fdba95

File tree

15 files changed

+91
-157
lines changed

15 files changed

+91
-157
lines changed

ktor-io/posix/src/io/ktor/utils/io/errors/PosixErrors.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
package io.ktor.utils.io.errors
66

7-
import kotlinx.cinterop.*
8-
import kotlinx.io.*
7+
import kotlinx.cinterop.ExperimentalForeignApi
8+
import kotlinx.cinterop.memScoped
9+
import kotlinx.cinterop.toKString
910
import platform.posix.*
10-
import kotlin.native.concurrent.*
1111

1212
private val KnownPosixErrors = mapOf(
1313
EBADF to "EBADF",
@@ -78,7 +78,7 @@ public sealed class PosixException(public val errno: Int, message: String) : Exc
7878
*
7979
* [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.utils.io.errors.PosixException.Companion.forErrno)
8080
*
81-
* @param errno error code returned by [posix.platform.errno]
81+
* @param errno error code returned by [platform.posix.errno]
8282
* @param posixFunctionName optional function name to be included to the exception message
8383
* @return an instance of [PosixException] or it's subtype
8484
*/

ktor-network/common/src/io/ktor/network/sockets/SocketAddress.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,12 @@ public expect class InetSocketAddress(
5151
/**
5252
* Returns the raw IP address bytes of this socket address.
5353
*
54-
* The returned array is 4 bytes for IPv4 addresses and 16 bytes for IPv6 addresses.
55-
* Returns null if the address cannot be resolved or is not a valid IP address.
54+
* The returned array is 4-bytes for IPv4 addresses and 16-bytes for IPv6 addresses.
55+
* Returns `null` if the address cannot be resolved or is not a valid IP address.
5656
*
57-
* Always returns null for wasm/js targets.
57+
* Always returns `null` for Kotlin/JS and Kotlin/Wasm targets.
5858
*
59-
* [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.network.sockets.InetSocketAddress.address)
59+
* [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.network.sockets.InetSocketAddress.resolveAddress)
6060
*/
6161
public fun resolveAddress(): ByteArray?
6262

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2014-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.network.sockets.tests
6+
7+
import io.ktor.network.sockets.*
8+
import io.ktor.util.*
9+
import kotlin.test.BeforeTest
10+
import kotlin.test.Test
11+
import kotlin.test.assertContentEquals
12+
13+
class InetSocketAddressTest {
14+
15+
@BeforeTest
16+
fun setUp() {
17+
initSocketsIfNeeded()
18+
}
19+
20+
@Test
21+
fun testResolveAddress() {
22+
// Address resolving is not supported on JS and WASM platforms
23+
if (PlatformUtils.IS_JS || PlatformUtils.IS_WASM_JS) return
24+
25+
val testCases = listOf(
26+
"127.0.0.1" to byteArrayOf(127, 0, 0, 1),
27+
"::1" to byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1),
28+
)
29+
30+
for ((hostname, expectedBytes) in testCases) {
31+
val address = InetSocketAddress(hostname, 8080)
32+
val resolved = address.resolveAddress()
33+
assertContentEquals(expectedBytes, resolved, "Unexpected bytes for the address '$hostname'")
34+
}
35+
}
36+
}

ktor-network/common/test/io/ktor/network/sockets/tests/TestUtils.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ internal fun createTempFilePath(basename: String): String {
3535
internal fun removeFile(path: String) {
3636
SystemFileSystem.delete(Path(path), mustExist = false)
3737
}
38+
39+
internal expect fun initSocketsIfNeeded()

ktor-network/jsAndWasmShared/test/io/ktor/network/sockets/tests/TestUtils.jsAndWasmShared.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
package io.ktor.network.sockets.tests
66

77
internal actual fun Throwable.isPosixException(): Boolean = false
8+
9+
actual fun initSocketsIfNeeded() {}

ktor-network/jvm/test/io/ktor/network/sockets/tests/TestUtilsJvm.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
package io.ktor.network.sockets.tests
66

77
internal actual fun Throwable.isPosixException(): Boolean = false
8+
9+
actual fun initSocketsIfNeeded() {}

ktor-network/nix/src/io/ktor/network/util/NativeSocketAddressNix.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ internal actual class NativeIPv4SocketAddress(
2828
}
2929
}
3030

31+
@OptIn(ExperimentalForeignApi::class)
32+
actual override val rawAddressBytes: ByteArray
33+
get() = cValue<in_addr> { s_addr = address }.getBytes()
34+
3135
@OptIn(ExperimentalForeignApi::class)
3236
actual override val ipString: String
3337
get() = memScoped {
@@ -45,18 +49,17 @@ internal actual class NativeIPv4SocketAddress(
4549
}
4650
}
4751

48-
@OptIn(UnsafeNumber::class)
52+
@OptIn(UnsafeNumber::class, ExperimentalForeignApi::class)
4953
internal actual class NativeIPv6SocketAddress(
5054
family: UByte,
51-
private val rawAddress: in6_addr,
55+
private val rawAddress: CValue<in6_addr>,
5256
port: Int,
5357
private val flowInfo: uint32_t,
5458
private val scopeId: uint32_t
5559
) : NativeInetSocketAddress(family, port) {
5660

5761
override fun toString(): String = "NativeIPv6SocketAddress[$ipString:$port]"
5862

59-
@OptIn(ExperimentalForeignApi::class)
6063
actual override fun nativeAddress(block: (address: CPointer<sockaddr>, size: UInt) -> Unit) {
6164
cValue<sockaddr_in6> {
6265
sin6_family = family.convert()
@@ -68,7 +71,9 @@ internal actual class NativeIPv6SocketAddress(
6871
}
6972
}
7073

71-
@OptIn(ExperimentalForeignApi::class)
74+
actual override val rawAddressBytes: ByteArray
75+
get() = rawAddress.getBytes()
76+
7277
actual override val ipString: String
7378
get() = memScoped {
7479
val string = allocArray<ByteVar>(INET6_ADDRSTRLEN)

ktor-network/nix/src/io/ktor/network/util/SocketUtils.nix.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ internal actual fun sockaddr.toNativeSocketAddress(): NativeSocketAddress = when
5959
val address = ptr.reinterpret<sockaddr_in6>().pointed
6060
NativeIPv6SocketAddress(
6161
address.sin6_family.convert(),
62-
address.sin6_addr,
62+
address.sin6_addr.readValue(),
6363
networkToHostOrder(address.sin6_port).toInt(),
6464
address.sin6_flowinfo,
6565
address.sin6_scope_id

ktor-network/posix/src/io/ktor/network/sockets/SocketAddress.nonJvm.posix.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,12 @@
44

55
package io.ktor.network.sockets
66

7-
import io.ktor.network.util.NativeIPv4SocketAddress
8-
import io.ktor.network.util.NativeIPv6SocketAddress
9-
import io.ktor.network.util.parseIPv4String
10-
import io.ktor.network.util.parseIPv6String
11-
import io.ktor.network.util.resolve
7+
import io.ktor.network.util.*
128

139
internal actual fun InetSocketAddress.platformResolveAddress(): ByteArray? {
1410
return this.resolve().firstOrNull()?.let {
1511
when (it) {
16-
is NativeIPv4SocketAddress -> parseIPv4String(it.ipString)
17-
is NativeIPv6SocketAddress -> parseIPv6String(it.ipString)
12+
is NativeInetSocketAddress -> it.rawAddressBytes
1813
else -> null
1914
}
2015
}

ktor-network/posix/src/io/ktor/network/util/NativeSocketAddress.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
package io.ktor.network.util
66

77
import io.ktor.network.sockets.*
8-
import kotlinx.cinterop.*
9-
import platform.posix.*
8+
import kotlinx.cinterop.CPointer
9+
import kotlinx.cinterop.ExperimentalForeignApi
10+
import kotlinx.cinterop.convert
11+
import platform.posix.sockaddr
1012

1113
/**
1214
* Represents a native socket address.
@@ -23,18 +25,21 @@ internal abstract class NativeInetSocketAddress(
2325
family: UByte,
2426
val port: Int
2527
) : NativeSocketAddress(family) {
26-
internal abstract val ipString: String
28+
abstract val rawAddressBytes: ByteArray
29+
abstract val ipString: String
2730
}
2831

2932
internal expect class NativeIPv4SocketAddress : NativeInetSocketAddress {
3033
@OptIn(ExperimentalForeignApi::class)
3134
override fun nativeAddress(block: (address: CPointer<sockaddr>, size: UInt) -> Unit)
35+
override val rawAddressBytes: ByteArray
3236
override val ipString: String
3337
}
3438

3539
internal expect class NativeIPv6SocketAddress : NativeInetSocketAddress {
3640
@OptIn(ExperimentalForeignApi::class)
3741
override fun nativeAddress(block: (address: CPointer<sockaddr>, size: UInt) -> Unit)
42+
override val rawAddressBytes: ByteArray
3843
override val ipString: String
3944
}
4045

0 commit comments

Comments
 (0)