5 Commits
Author SHA1 Message Date
RTAkland 896883a3e0 Support event hooking 2025-10-31 06:51:13 +08:00
RTAkland 2328bf7755 Add unregister function 2025-10-29 11:12:17 +08:00
RTAkland 6ab5e551e2 Update README.md 2025-10-27 10:46:51 +08:00
RTAkland 33239c6591 Update README 2025-09-30 18:02:03 +08:00
RTAkland 42651a7f81 Published to maven central 2025-09-30 17:51:11 +08:00
5 changed files with 143 additions and 31 deletions

No files matched your search

+26 -14
View File
@@ -2,7 +2,9 @@
A Kotlin multiplatform library for mdns announcer(mdns server), only broadcast is supported, A Kotlin multiplatform library for mdns announcer(mdns server), only broadcast is supported,
Also, nmdns can be compiled to shared/static lib for other language calling, see [c++ example](#cpp) Also, nmdns can be compiled to shared/static lib for other languages calling, see [c++ example](#cpp)
mDNS is usually used for Apple's AirPlay protocol family, there's an example in README.md [How to use](#How-to-use)
Supported platforms: Supported platforms:
1. windows64(mingwx64) 1. windows64(mingwx64)
@@ -12,9 +14,14 @@ Supported platforms:
5. macosX64 5. macosX64
6. jvm(11 or later) 6. jvm(11 or later)
Supported srv type Supported record type
1. A 1. A
2. PTR 2. PTR
3. SRV
4. TXT
Supported features
1. Event hooking(Kotlin only)
> AAAA is not supported > AAAA is not supported
@@ -22,16 +29,7 @@ AirPlay2(_airplay._tcp.local.) is tested
# How to use # How to use
Add maven repository > Make sure you added the mavenCentral repository in your project
```kotlin
repositories {
mavenCentral()
maven("https://repo.maven.rtast.cn/releases")
}
```
Add dependency
```kotlin ```kotlin
kotlin { kotlin {
@@ -58,10 +56,24 @@ val service = registerService(
bindAddress = "192.168.10.104", bindAddress = "192.168.10.104",
mdnsPort = 5356, mdnsPort = 5356,
txtRecords = listOf("key1=value1", "key2=value2") txtRecords = listOf("key1=value1", "key2=value2")
) ) {
// This block is optional
// Event hooking in this block
onBroadcast {
println("broadcasted")
}
onRegister {
println("reg")
}
onUnregistered {
println("unreg")
}
}
while (true) { while (true) {
service.broadcast() service.broadcast()
delay(2000L) // or use cn.rtast.nmdns.sleep1(2) sleep 2 seconds delay(2000L) // or use cn.rtast.nmdns.sleep1(2) sleep 2 seconds, this function is not a suspended function
} }
``` ```
+45 -3
View File
@@ -1,12 +1,16 @@
import com.vanniktech.maven.publish.SonatypeHost
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { plugins {
kotlin("multiplatform") version "2.2.0" kotlin("multiplatform") version "2.2.0"
id("maven-publish") id("com.vanniktech.maven.publish") version "0.31.0-rc2"
id("signing")
} }
val libVersion: String by project
group = "cn.rtast.nmdns" group = "cn.rtast.nmdns"
version = "0.1.0" version = libVersion
repositories { repositories {
mavenCentral() mavenCentral()
@@ -48,7 +52,8 @@ kotlin {
} }
} }
publishing { mavenPublishing {
publishing {
repositories { repositories {
mavenLocal() mavenLocal()
maven("https://repo.maven.rtast.cn/releases") { maven("https://repo.maven.rtast.cn/releases") {
@@ -58,6 +63,43 @@ publishing {
password = System.getenv("PUBLISH_TOKEN") password = System.getenv("PUBLISH_TOKEN")
} }
} }
mavenCentral()
}
}
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
if (System.getenv("PUBLISH_TOKEN") == null) signAllPublications()
coordinates("cn.rtast.nmdns", project.name, libVersion)
pom {
name = project.name
description = "mDNS in kotlin multiplatform"
url = "https://github.com/RTAkland/native-mdns"
developers {
developer {
id = "rtakland"
name = "RTAkland"
email = "rtakland@outlook.com"
}
}
licenses {
license {
name = "The Apache License, Version 2.0"
url = "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
scm {
url = "https://github.com/RTAkland/native-mdns"
connection = "scm:git:git://github.com/RTAkland/native-mdns.git"
developerConnection = "scm:git:ssh://git@github.com/RTAkland/native-mdns.git"
}
}
}
if (System.getenv("PUBLISH_TOKEN") == null) {
signing {
useGpgCmd()
sign(publishing.publications)
} }
} }
+1
View File
@@ -1,2 +1,3 @@
kotlin.code.style=official kotlin.code.style=official
kotlin.native.enableKlibsCrossCompilation=true kotlin.native.enableKlibsCrossCompilation=true
libVersion=0.1.2
@@ -12,6 +12,18 @@ package cn.rtast.nmdns
import kotlin.experimental.ExperimentalNativeApi import kotlin.experimental.ExperimentalNativeApi
import kotlin.native.CName import kotlin.native.CName
public fun NMDNSAnnouncer.onRegister(callback: () -> Unit) {
onRegisterCallback = callback
}
public fun NMDNSAnnouncer.onBroadcast(callback: () -> Unit) {
onBroadcastCallback = callback
}
public fun NMDNSAnnouncer.onUnregistered(callback: () -> Unit) {
onUnregisterCallback = callback
}
public data class NMDNSAnnouncer( public data class NMDNSAnnouncer(
/** /**
* service type * service type
@@ -51,6 +63,11 @@ public data class NMDNSAnnouncer(
*/ */
internal val packet: ByteArray, internal val packet: ByteArray,
) { ) {
internal var onRegisterCallback: (() -> Unit)? = null
internal var onBroadcastCallback: (() -> Unit)? = null
internal var onUnregisterCallback: (() -> Unit)? = null
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
@@ -87,11 +104,21 @@ public data class NMDNSAnnouncer(
* broadcast packet * broadcast packet
*/ */
public fun broadcast() { public fun broadcast() {
this.onBroadcastCallback?.invoke()
this.server.send(packet) this.server.send(packet)
} }
/**
* unregister service
*/
public fun unregister() {
this.onUnregisterCallback?.invoke()
this.server.destroy()
}
} }
/** /**
* broadcast packet
* export for c * export for c
*/ */
@CExport @CExport
@@ -100,6 +127,16 @@ public fun broadcast1(server: NMDNSAnnouncer) {
server.server.send(server.packet) server.server.send(server.packet)
} }
/**
* unregister service
* export for c
*/
@CExport
@CName("unregister")
public fun unregister1(server: NMDNSAnnouncer) {
server.unregister()
}
/** /**
* register service * register service
* airplay2 txt records * airplay2 txt records
@@ -121,10 +158,12 @@ public fun registerService(
mdnsPort: Int = 9872, mdnsPort: Int = 9872,
bindAddress: String, bindAddress: String,
txtRecords: List<String>, txtRecords: List<String>,
callback: NMDNSAnnouncer.() -> Unit = {},
): NMDNSAnnouncer { ): NMDNSAnnouncer {
val server = createSocket() val socket = createSocket()
.bind(bindAddress, port) .bind(bindAddress, port)
return NMDNSAnnouncer(
val server = NMDNSAnnouncer(
serviceType, serviceType,
serviceName, serviceName,
hostname, hostname,
@@ -132,9 +171,12 @@ public fun registerService(
port, port,
mdnsPort, mdnsPort,
txtRecords, txtRecords,
server, socket,
buildPacket(serviceType, "$serviceName.$serviceType", hostname, ipAddress, port, txtRecords) buildPacket(serviceType, "$serviceName.$serviceType", hostname, ipAddress, port, txtRecords),
) )
server.callback()
server.onRegisterCallback?.invoke()
return server
} }
internal fun buildPacket( internal fun buildPacket(
+16 -1
View File
@@ -7,6 +7,9 @@
package test package test
import cn.rtast.nmdns.onBroadcast
import cn.rtast.nmdns.onRegister
import cn.rtast.nmdns.onUnregistered
import cn.rtast.nmdns.randomMacAddress import cn.rtast.nmdns.randomMacAddress
import cn.rtast.nmdns.registerService import cn.rtast.nmdns.registerService
import cn.rtast.nmdns.sleep1 import cn.rtast.nmdns.sleep1
@@ -30,7 +33,19 @@ class TestLinux {
"srcvers=220.68", "srcvers=220.68",
"pk=f3769a660475d27b4f6040381d784645e13e21c53e6d2da6a8c3d757086fc336" "pk=f3769a660475d27b4f6040381d784645e13e21c53e6d2da6a8c3d757086fc336"
) )
) ) {
onBroadcast {
println(111)
}
onRegister {
println("reg")
}
onUnregistered {
println("unreg")
}
}
while (true) { while (true) {
service.broadcast() service.broadcast()
sleep1(2) sleep1(2)