Files
native-mdns/src/appleMain/kotlin/cn/rtast/nmdns/socket.apple.kt
T

69 lines
2.1 KiB
Kotlin

/*
* Copyright © 2025 RTAkland
* Author: RTAkland
* Date: 9/30/25
*/
@file:OptIn(ExperimentalForeignApi::class)
@file:Suppress("unused")
package cn.rtast.nmdns
import kotlinx.cinterop.*
import platform.darwin.inet_addr
import platform.posix.*
public actual class Socket1 internal actual constructor() {
/**
* socket fd
*/
private var socket: Int = -1
public actual fun bind(ip: String, port: Int): Socket1 {
socket = socket(AF_INET, SOCK_DGRAM, 0)
if (socket < 0) perror("Failed to create udp socket")
memScoped {
val reuse = alloc<IntVar>()
reuse.value = 1
if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, reuse.ptr, sizeOf<IntVar>().convert()) < 0) {
perror("Failed to setsocketopt SO_REUSEADDR")
}
}
memScoped {
val addr = alloc<sockaddr_in>()
addr.sin_family = AF_INET.convert()
addr.sin_port = htons(port.toUShort())
addr.sin_addr.s_addr = inet_addr(ip)
if (bind(socket, addr.ptr.reinterpret(), sizeOf<sockaddr_in>().convert()) < 0) {
perror("Failed to bind")
close(socket)
}
}
memScoped {
val mreq = alloc<ip_mreq>()
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.251")
mreq.imr_interface.s_addr = inet_addr(ip)
if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq.ptr, sizeOf<ip_mreq>().convert()) < 0) {
perror("setsockopt IP_ADD_MEMBERSHIP")
}
}
return this
}
public actual fun send(packet: ByteArray) {
memScoped {
val addr = alloc<sockaddr_in>()
addr.sin_family = AF_INET.convert()
addr.sin_port = htons(5353u)
addr.sin_addr.s_addr = inet_addr("224.0.0.251")
val cbuf = packet.refTo(0).getPointer(this)
sendto(socket, cbuf, packet.size.convert(), 0, addr.ptr.reinterpret(), sizeOf<sockaddr_in>().convert())
}
}
public actual fun destroy() {
close(socket)
}
}