Has anyone written a function to get a device's ip...
# kotlin-native
s
Has anyone written a function to get a device's ip address when targeting iOS? I know it can be done by calling the same APIs as used here: https://stackoverflow.com/questions/6807788/how-to-get-ip-address-of-iphone-programmatically Just hoping someone's already done it before I sink time into actually digesting the pain which is objective C ­čść
m
I have no specific experience with this, however, if I were to go with the cinterop, I would try the following: https://docs.libuv.org/en/v1.x/guide/networking.html#network-interfaces
e
that's really all C code, no need to know Objective-C. on Linux you can do
Copy code
import kotlinx.cinterop.ByteVar
import kotlinx.cinterop.allocArray
import kotlinx.cinterop.allocPointerTo
import kotlinx.cinterop.convert
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.pointed
import kotlinx.cinterop.ptr
import kotlinx.cinterop.reinterpret
import kotlinx.cinterop.toKString
import kotlinx.cinterop.value
import platform.linux.freeifaddrs
import platform.linux.getifaddrs
import platform.linux.ifaddrs
import platform.linux.inet_ntop
import platform.posix.AF_INET
import platform.posix.AF_INET6
import platform.posix.INET6_ADDRSTRLEN
import platform.posix.INET_ADDRSTRLEN
import platform.posix.sa_family_t
import platform.posix.sockaddr_in
import platform.posix.sockaddr_in6

fun getIPAddresses(): List<String> {
    val (status, interfaces) = memScoped {
        val ifap = allocPointerTo<ifaddrs>()
        getifaddrs(ifap.ptr) to ifap.value
    }
    return try {
        generateSequence(interfaces.takeIf { status == 0 }) { it.pointed.ifa_next }
            .mapNotNull { it.pointed.ifa_addr }
            .mapNotNull {
                val addr = when (it.pointed.sa_family) {
                    AF_INET.convert<sa_family_t>() -> it.reinterpret<sockaddr_in>().pointed.sin_addr
                    AF_INET6.convert<sa_family_t>() -> it.reinterpret<sockaddr_in6>().pointed.sin6_addr
                    else -> return@mapNotNull null
                }
                memScoped {
                    val len = maxOf(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)
                    val dst = allocArray<ByteVar>(len)
                    inet_ntop(it.pointed.sa_family.convert(), addr.ptr, dst, len.convert())?.toKString()
                }
            }
            .toList()
    } finally {
        freeifaddrs(interfaces)
    }
}
and it should be similar on Darwin
s
That's fantastic thank you so much!
e
I don't have an iOS development environment but just tested on macos; the same works if you just swap
platform.linux.*
to
platform.darwin.*
by the way,
inet_ntoa
in the stackoverflow answer only works for IPv4 and is deprecated;
inet_ntop
works for IPv4 and IPv6
304 Views