Code Monkey home page Code Monkey logo

kmqtt's Introduction

KMQTT

KMQTT is a Kotlin Multiplatform MQTT 3.1.1/5.0 Client and Broker, with the objective of targeting the most possible build targets.

Client features

❌ = To Do
✅ = Supported
➕ = Work In Progress

Platform MQTT 3.1.1 MQTT 5.0 TCP TLS Websocket
JVM
Windows X64
Linux X64
Linux ARM64
Node.js
iOS X64
iOS ARM64
iOS Simulator ARM64
macOS X64
macOS ARM64
tvOS X64
tvOS ARM64
tvOS Simulator ARM64
watchOS X64
watchOS ARM32
watchOS ARM64
watchOS Simulator ARM64

Broker features

❌ = To Do
✅ = Supported
➕ = Work In Progress

Platform MQTT 3.1.1 MQTT 5.0 TCP TLS Websocket Clustering
JVM
Windows X64
Linux X64
Linux ARM64
Node.js
macOS X64
macOS ARM64

Getting Started with the client

Library

Gradle

If you are getting an error saying that OpenSSL hasn't been found, please copy the correct file from https://github.com/davidepianca98/KMQTT/tree/master/kmqtt-common/src/nativeInterop in your project's main directory.

Kotlin Multiplatform plugin

On the Kotlin Multiplatform plugin you only need to require the dependency on the common source set and the platform specific parts will be automatically imported.

repositories {
    mavenCentral()
}

kotlin {
    jvm()
    mingwX64()
    macosX64()

    sourceSets {
        commonMain {
            dependencies {
                implementation("io.github.davidepianca98:kmqtt-common:0.4.7")
                implementation("io.github.davidepianca98:kmqtt-client:0.4.7")
            }
        }
    }
}
Single platform project
repositories {
    mavenCentral()
}
dependencies {
    implementation("io.github.davidepianca98:kmqtt-common-jvm:0.4.7")
    implementation("io.github.davidepianca98:kmqtt-client-jvm:0.4.7")
}

Replace jvm with js, linuxx64, linuxarm64, mingwx64, macosx64, macosarm64, iosarm64, iosX64, iossimulatorarm64, tvossimulatorarm64, tvosx64, tvosarm64, watchosarm32, watchosarm64, watchosx64, watchossimulatorarm64 based on the desired target.

Quick start code example

This code starts the MQTT client on port 1883 without TLS encryption. You can play with MQTTClient() constructor parameters to set the various settings

fun main() {
    val client = MQTTClient(
        MQTTVersion.MQTT5,
        "test.mosquitto.org",
        1883,
        null
    ) {
        println(it.payload?.toByteArray()?.decodeToString())
    }
    client.subscribe(listOf(Subscription("/randomTopic", SubscriptionOptions(Qos.EXACTLY_ONCE))))
    client.publish(false, Qos.EXACTLY_ONCE, "/randomTopic", "hello".encodeToByteArray().toUByteArray())
    client.run() // Blocking method, use step() if you don't want to block the thread
}

TLS code example

The certificates and key must be in PEM format, and they can be either a path to the PEM file or the actual PEM string. The password can be null if the private key has no protection.

fun main() {
    val client = MQTTClient(
        MQTTVersion.MQTT5,
        "test.mosquitto.org",
        8883,
        TLSClientSettings(
            serverCertificate = "mosquitto.org.crt",
        )
    ) {
        println(it.payload?.toByteArray()?.decodeToString())
    }
    client.subscribe(listOf(Subscription("/randomTopic", SubscriptionOptions(Qos.EXACTLY_ONCE))))
    client.publish(false, Qos.EXACTLY_ONCE, "/randomTopic", "hello".encodeToByteArray().toUByteArray())
    client.run() // Blocking method, use step() if you don't want to block the thread
}

Getting Started with the broker

Executables

You can download the executables for your platform under the release tab

Program Arguments

Argument Default Value Description
-h 127.0.0.1 Interface address to bind the server to
-p 1883 Server port to listen to
--max-connections 128 The maximum number of TCP connections to support
--key-store null The path to the PKCS12 keystore containing the private key and the certificate for TLS, if null TLS is disabled
--key-store-psw null The password of the PKCS12 keystore indicated in --key-store, if the keystore has no password set, don't set the option
--wsp null The WebSocket port to listen to

Library

Gradle

If you are getting an error saying that OpenSSL hasn't been found, please copy the correct file from https://github.com/davidepianca98/KMQTT/tree/master/kmqtt-common/src/nativeInterop in your project's main directory.

Kotlin Multiplatform plugin

On the Kotlin Multiplatform plugin you only need to require the dependency on the common source set and the platform specific parts will be automatically imported.

repositories {
    mavenCentral()
}

kotlin {
    jvm()
    mingwX64()
    macosX64()
    sourceSets {
        commonMain {
            dependencies {
                implementation("io.github.davidepianca98:kmqtt-common:0.4.7")
                implementation("io.github.davidepianca98:kmqtt-broker:0.4.7")
            }
        }
    }
}
Single platform project
repositories {
    mavenCentral()
}
dependencies {
    implementation("io.github.davidepianca98:kmqtt-common-jvm:0.4.7")
    implementation("io.github.davidepianca98:kmqtt-broker-jvm:0.4.7")
}

Replace jvm with js, linuxx64, linuxarm64, macosarm64, macosx64, mingwx64 based on the desired target.

Quick start code example

This code starts the MQTT broker on port 1883 without TLS encryption. You can play with Broker() constructor parameters to set the various settings

fun main() {
    Broker().listen()
}

TLS code example

The keystore must be in PKCS12 format, the keystore password can be null

fun main() {
    val broker = Broker(
        tlsSettings = TLSSettings(keyStoreFilePath = "keyStore.p12", keyStorePassword = "password"),
        port = 8883
    ).listen()
    broker.listen()
}

Authentication code example

fun main() {
    val broker = Broker(authentication = object : Authentication {
        override fun authenticate(clientId: String, username: String?, password: UByteArray?): Boolean {
            // TODO Implement your authentication method    
            return username == "user" && password?.toByteArray()?.decodeToString() == "pass"
        }
    })
    broker.listen() // Blocking method, use step() if you don't want to block the thread
}

Authorization code example

fun main() {
    val broker = Broker(authorization = object : Authorization {
        override fun authorize(
            clientId: String,
            username: String?,
            password: UByteArray?, // != null only if savePassword set to true in the broker constructor
            topicName: String,
            isSubscription: Boolean,
            payload: UByteArray?
        ): Boolean {
            // TODO Implement your authorization method    
            return topicName == "$clientId/topic"
        }
    })
    broker.listen() // Blocking method, use step() if you don't want to block the thread
}

Message interceptor code example

fun main() {
    val broker = Broker(packetInterceptor = object : PacketInterceptor {
        override fun packetReceived(clientId: String, username: String?, password: UByteArray?, packet: MQTTPacket) {
            when (packet) {
                is MQTTConnect -> println(packet.protocolName)
                is MQTTPublish -> println(packet.topicName)
            }
        }
    })
    broker.listen() // Blocking method, use step() if you don't want to block the thread
}

Internal publish code example

fun main() {
    val broker = Broker()
    broker.publish(
        retain = false,
        topicName = "test/",
        qos = Qos.AT_MOST_ONCE,
        properties = MQTTProperties(),
        "testPayload".toByteArray().toUByteArray()
    )
    broker.listen() // Blocking method, use step() if you don't want to block the thread
}

Other advanced functionality

MQTT5 Enhanced Authentication: set the enhancedAuthenticationProviders Broker constructor parameter, implementing the provider interface EnhancedAuthenticationProvider.

Session persistence: set the persistence Broker constructor parameter, implementing Persistence interface.

Bytes metrics: set the bytesMetrics Broker constructor parameter, implementing BytesMetrics interface.

kmqtt's People

Contributors

annalabellarte avatar davidepianca98 avatar pbearson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

kmqtt's Issues

Recurring crash of Client on JVM

Example client runs on JVM, after around 1 minute the app crashes.
I'm using mosquitto broker. It emits 30 to 60 events per second.

Exception in thread "main" socket.SocketClosedException
   at socket.tcp.Socket.readToBuffer(Socket.kt:47)
   at socket.tcp.Socket.read--5HJl4c(Socket.kt:57)
   at ClientSocket.read--5HJl4c(ClientSocket.kt:32)
   at MQTTClient.check(MQTTClient.kt:312)
   at MQTTClient.step(MQTTClient.kt:376)
   at MQTTClient.run(MQTTClient.kt:385)
   at MainKt.main(Main.kt:16)
   at MainKt.main(Main.kt)


Error in recv: 9 on disconnect()

Ciao @davidepianca98 👋 ,

While testing a feature using KMM I noticed I get the following error:

--- Error: socket.IOException: Error in recv: 9
    at 0   Sdk                              0x121e217af        kfun:socket.tcp.Socket#read(){}kotlin.UByteArray? + 943 
    at 1   Sdk                              0x121e28baf        kfun:ClientSocket#read(){}kotlin.UByteArray? + 511 
    at 2   Sdk                              0x121f33a37        kfun:socket.SocketInterface#read(){}kotlin.UByteArray?-trampoline + 207 
    at 3   Sdk                              0x121e238bb        kfun:MQTTClient.check#internal + 235 
    at 4   Sdk                              0x121e2c1a7        kfun:kmp.backend.calls.MyMqttClientImpl.$subscribe$lambda$2$FUNCTION_REFERENCE$2.invoke#internal + 939 
    at 5   Sdk                              0x121f034b7        kfun:kotlin.Function2#invoke(1:0;1:1){}1:2-trampoline + 207 
    at 6   Sdk                              0x121a8b417        kfun:kotlin.coroutines.intrinsics.object-3.invokeSuspend#internal + 451 
    at 7   Sdk                              0x121a8a33b        kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 171 
    at 8   Sdk                              0x121b6710b        kfun:kotlinx.coroutines.DispatchedTask#run(){} + 471 
    at 9   Sdk                              0x121b789d7        kfun:kotlinx.coroutines.DarwinGlobalQueueDispatcher.$dispatch$lambda$0$FUNCTION_REFERENCE$0.$<bridge-UNN>invoke(){}#internal + 83 
    at 10  Sdk                              0x121f01443        kfun:kotlin.Function0#invoke(){}1:0-trampoline + 207 
    at 11  Sdk                              0x1221d3797        ___6f72672e6a6574627261696e732e6b6f746c696e783a6b6f746c696e782d636f726f7574696e65732d636f72652f6f70742f6275696c644167656e742f776f726b2f343465633665383530643563363366302f6b6f746c696e782d636f726f7574696e65732d636f72652f6e617469766544617277696e2f7372632f44697370617463686572732e6b74_knbridge2_block_invoke + 231 
    at 12  libdispatch.dylib                   0x110c1453b        _dispatch_call_block_and_release + 31 
    at 13  libdispatch.dylib                   0x110c15fef        _dispatch_client_callout + 19 
    at 14  libdispatch.dylib                   0x110c18b27        _dispatch_queue_override_invoke + 1051 
    at 15  libdispatch.dylib                   0x110c2a467        _dispatch_root_queue_drain + 407 
    at 16  libdispatch.dylib                   0x110c2ae63        _dispatch_worker_thread2 + 195 
    at 17  libsystem_pthread.dylib             0x1f733cdbb        _pthread_wqthread + 227 
    at 18  libsystem_pthread.dylib             0x1f733cb97        start_wqthread + 7 
 

It happens only when this line is present:

client.disconnect(ReasonCode.SUCCESS)

Also it only happens on iOS :/ It doesn't happen on Android.

Do you have any idea about how to fix this? Are we doing anything wrong? Can it be tied to the prebuilt .klibs we're bundling in the project for iOS to work?

Thanks in advance for your work

Delay in Publishing message

Hi All,

When I publish a message with 0.4.6 version.
It takes like 20 seconds or more.

while (isActive) {
                    client?.run()
                    delay(200)
                }

I've done that but even it takes too much time.

Any fix?

Seeking help

Hello, thank you very much for open-sourcing this project. It has been incredibly helpful to me. I have a few questions. I noticed that there are some TODOs in the source code. Will those be completed in the future? Additionally, I couldn't find any callbacks or notifications regarding the connection status in the Client. Do you have any suggestions for how to know the connection status?

Artifact publication on Maven Central?

Hi! First, thanks a lot for this project. It rocks!

Are you considering the publication of the libraries on Maven Central?
Would you accept a PR setting up the required Gradle boilerplate?

Provide the Client ID inside MQTTDisconnect

MQTTConnect offers a lot of data about the client that connected to the MQTT broker, but MQTTDisconnect does not provide any information at all beside that some unidentified session was closed.

It would be useful if MQTTDisconnect would provide at least the Client ID of the client that disconnected from the broker.

HTTP header matching should be case insensitive to support more clients

Some MQTT clients, such as HiveMQ uses all lowercase in the HTTP headers during a websocket handshake.

KMQTT does a case sensitive regex match against, for example, Sec-WebSocket-Protocol. Due to this it's not possible to use WebSockets to connect to KMQTT from a client using on HiveMQ.

It would be great if case insensitive matching could be used when matching against http headers.

For reference, here's an example of what the request and response looks like during the handshake:

GET / HTTP/1.1
host: 192.168.22.52:1884
upgrade: websocket
connection: upgrade
sec-websocket-key: GDDymPLXlAntP0fSTArBCg==
origin: http://192.168.22.52:1884
sec-websocket-protocol: mqtt
sec-websocket-version: 13

HTTP/1.1 400 Bad Request

Suggestions

Make internal fun getSession(clientId: String?): ISession? public,
and it would be nice to have a onDisconnect event that would trigger whenever a client has disconnected or timed out.

Kotlin native could not find "openssl"

I am trying to create project using this library with kotlin native on linux 64bit, but i am getting strange error about missing openssl. I have installed openssl and libssl-dev but the error still persists.

e: Could not find "openssl" in [/home/fjerabek/mqttTest, /home/fjerabek/.konan/klib, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/common, /home/fjerabek/.konan/kotlin-native-prebuilt-linux-x86_64-1.7.0/klib/platform/linux_x64]

Execution failed for task ':compileKotlinNative'.
> Compilation finished with errors

Am i missing some other library on my system ?

Expose the list of the connected client IDs

It would be useful to have access to the list of connected clients of the broker. This would be very simple to implement: just create a function that returns the sessions.keys of the Broker class:

public fun getConnectedClients(): ListString = sessions.keys

Failing to compile with Kotlin and Gradle KTS

Hi,

Thanks for creating this library. I was trying to test it locally and I am finding an issue when downloading the dependency. If you could please point me in the right direction it would be great. From what I understood Gradle is not finding the "jvm" variant of the lib.

Here is the error from Gradle:

Execution failed for task ':compileKotlin'.
> Could not resolve all files for configuration ':compileClasspath'.
   > Could not resolve com.github.davidepianca98.KMQTT:KMQTT-linuxarm32hfp:0.2.3.
     Required by:
         project : > com.github.davidepianca98:KMQTT:0.2.3
      > No matching variant of com.github.davidepianca98.KMQTT:KMQTT-linuxarm32hfp:0.2.3 was found. The consumer was configured to find an API of a library compatible with Java 8, preferably in the form of class files, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but:
          - Variant 'linuxArm32Hfp-api' capability com.github.davidepianca98.KMQTT:KMQTT-linuxarm32hfp:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
          - Variant 'metadata-api' capability com.github.davidepianca98.KMQTT:KMQTT-linuxarm32hfp:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
          - Variant 'metadata-commonMainMetadataElements' capability com.github.davidepianca98.KMQTT:KMQTT-linuxarm32hfp:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
   > Could not resolve com.github.davidepianca98.KMQTT:KMQTT-linuxx64:0.2.3.
     Required by:
         project : > com.github.davidepianca98:KMQTT:0.2.3
      > No matching variant of com.github.davidepianca98.KMQTT:KMQTT-linuxx64:0.2.3 was found. The consumer was configured to find an API of a library compatible with Java 8, preferably in the form of class files, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but:
          - Variant 'linuxX64-api' capability com.github.davidepianca98.KMQTT:KMQTT-linuxx64:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'native' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
          - Variant 'metadata-api' capability com.github.davidepianca98.KMQTT:KMQTT-linuxx64:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
          - Variant 'metadata-commonMainMetadataElements' capability com.github.davidepianca98.KMQTT:KMQTT-linuxx64:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
   > Could not resolve com.github.davidepianca98.KMQTT:KMQTT-metadata:0.2.3.
     Required by:
         project : > com.github.davidepianca98:KMQTT:0.2.3
      > No matching variant of com.github.davidepianca98.KMQTT:KMQTT-metadata:0.2.3 was found. The consumer was configured to find an API of a library compatible with Java 8, preferably in the form of class files, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm' but:
          - Variant 'metadata-api' capability com.github.davidepianca98.KMQTT:KMQTT-metadata:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-metadata' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)
          - Variant 'metadata-commonMainMetadataElements' capability com.github.davidepianca98.KMQTT:KMQTT-metadata:0.2.3:
              - Incompatible because this component declares a usage of 'kotlin-api' of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'common' and the consumer needed an API of a component, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'
              - Other compatible attributes:
                  - Doesn't say anything about its component category (required a library)
                  - Doesn't say anything about how its dependencies are found (required its dependencies declared externally)
                  - Doesn't say anything about its target Java version (required compatibility with Java 8)
                  - Doesn't say anything about its elements (required them preferably in the form of class files)

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.


And here is the build.gradle.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.4.31"
}

group = "com.myorg"
version = "1.0"

repositories {
    mavenCentral()
    jcenter()
    maven(url = "https://jitpack.io")
}

dependencies {
    implementation("com.github.davidepianca98:KMQTT:0.2.3")
    testImplementation(kotlin("test-junit5"))
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile>() {
    kotlinOptions.jvmTarget = "1.8"
}

Can't subscribe to topics after invoking client.run()

Hi, thanks for your library.

I don't know if it's intended behavior, but I'm having issues subscribing to some MQTT topics after I already invoked client.run().

Usually, when I call later client.subscribe(...) I end up with a socket.IOException: Connection reset by peer.

All seems to work fine if I call in this specific order client.subscribe(...) and then client.run().

Let me know if you need a repro, if so I'll try to extract the logic from my project.

Edit: I'm running on JVM (Android).

Thanks.

Can't download iOS dependencies (KMM)

Hello,

First of all, thank you for providing this library to the KMM community.

I'm working on a KMM project and I wanted to test the tool on it but I wasn't able to do so. The project has targets for Android and iOS (iosX64, iosArm64, iosSimulatorArm64). I took a look in JitPack and apparently, I can't find a kmqtt-common for the mentioned iOS targets.

Am I missing something or is it something from the library side?

Kotlin version - 1.8.10

Error from Gradle

* What went wrong:
Could not determine the dependencies of task ':shared:transformIosMainCInteropDependenciesMetadataForIde'.
> Could not resolve all task dependencies for configuration ':shared:allSourceSetsRuntimeDependenciesMetadata'.
   > Could not resolve com.github.davidepianca98.KMQTT:kmqtt-common:0.4.1.
     Required by:
         project :shared
      > Could not resolve com.github.davidepianca98.KMQTT:kmqtt-common:0.4.1.
         > Could not get resource 'https://my_artifactory_link/github/davidepianca98/KMQTT/kmqtt-common/0.4.1/kmqtt-common-0.4.1.pom'.
            > Could not GET 'https://my_artifactory_link//github/davidepianca98/KMQTT/kmqtt-common/0.4.1/kmqtt-common-0.4.1.pom'. Received status code 403 from server: Forbidden
   > Could not resolve com.github.davidepianca98.KMQTT:kmqtt-client:0.4.1.
     Required by:
         project :shared
      > Could not resolve com.github.davidepianca98.KMQTT:kmqtt-clien:0.4.1.
         > Could not get resource 'https://my_artifactory_link/github/davidepianca98/KMQTT/kmqtt-client/0.4.1/kmqtt-client-0.4.1.pom'.
            > Could not GET 'https://my_artifactory_link/com/github/davidepianca98/KMQTT/kmqtt-client/0.4.1/kmqtt-client-0.4.1.pom'. Received status code 403 from server: Forbidden

build.gradle.kts

sourceSets {
        val commonMain by getting {
            dependencies {
                   implementation(com.github.davidepianca98.KMQTT:kmqtt-common:0.4.1)
                   implementation(com.github.davidepianca98.KMQTT:kmqtt-client:0.4.1)
            }
        }
    }

java.nio.BufferOverflowException when calling

This only happens on my CI instance, which is a bit less powerful than my desktop. I wonder if there's a race?

01-11 17:17:51.247  2605  2633 E TestRunner: java.nio.BufferOverflowException
01-11 17:17:51.247  2605  2633 E TestRunner:    at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:164)
01-11 17:17:51.247  2605  2633 E TestRunner:    at java.nio.ByteBuffer.put(ByteBuffer.java:732)
01-11 17:17:51.247  2605  2633 E TestRunner:    at socket.tcp.Socket.send-GBYM_sE(Socket.kt:19)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.ClientConnection.writePacket$kmqtt_broker(ClientConnection.kt:103)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Session.publish$kmqtt_broker(Session.kt:120)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Session.publish-dKY7gkk(Session.kt:168)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Broker.publishNormal-Doz7y5Q(Broker.kt:111)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Broker.publish-WrwqGuM$kmqtt_broker(Broker.kt:180)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Broker.publish-WrwqGuM$kmqtt_broker$default(Broker.kt:121)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Broker.publish-dKY7gkk(Broker.kt:224)
01-11 17:17:51.247  2605  2633 E TestRunner:    at mqtt.broker.Broker.publish-XKAnP-8(Broker.kt:244)
01-11 17:17:51.247  2605  2633 E TestRunner:    at org.owntracks.android.testutils.TestWithAnMQTTBrokerImpl.sendFromBroker(TestWithAnMQTTBrokerImpl.kt:46)

I'm calling publish on multiple messages, a bit like this:

    @RunWith(AndroidJUnit4::class)
    class MyTest {
        @Test
        fun myTest() {
            listOf(
                MessageLocation(),
                MessageCard()
            }.sendFromBroker(broker)
        }

        fun <E : MessageBase> Collection<E>.sendFromBroker(
            broker: Broker,
            topicName: String = "owntracks/someuser/somedevice",
            retain: Boolean = false
        ) = forEach { it.sendFromBroker(broker, topicName, retain) }

        fun MessageBase.sendFromBroker(
            broker: Broker,
            topicName: String = "testTopic",
            retain: Boolean
        ) {            
            this.toJsonBytes()
                .run {
                    broker.publish(
                        true,
                        actualTopic,
                        Qos.AT_LEAST_ONCE,
                        MQTT5Properties(),
                        toUByteArray()
                    )
                }
        }
    }

This same code works fine with either:

  • KMQTT 0.3.3, fails on 0.4.x.
  • Setting the QoS to AT_MOST_ONCE

Ability to subscribe after broker connected

Hi, thanks for the great work, making the mqtt client, supporting multiplatform.

I was able to run the sample codes, that is subscribe before calling client.run.

Just like to share that I also tried to use client.subscribe after the client.run was called. However, it seems like the subscription was not registered.

Appreciate if you can advise on why this is happening. The objective is to allow the client to subscribe to a topic after client is connected to the broker.

Thanks.

connect to activemq

Hi,

Trying to connect to an activemq instance on aws,
Here is my source code:

val client = MQTTClient(
                    5,
                    "id.mq.eu-central-1.amazonaws.com",
                    8883,
                    TLSClientSettings()
                ) {
                    Logger.debug(TAG, "test ${it.payload?.toByteArray()?.decodeToString()}")
                }
                client.publish(
                    false,
                    Qos.AT_MOST_ONCE,
                    "/toto",
                    "hello".encodeToByteArray().toUByteArray()
                )
                client.step()
                client.run()

Exception trapped

socket.SocketClosedException
at socket.tls.TLSSocket.read0(TLSSocket.kt:152)
at socket.tls.TLSSocket.read--5HJl4c(TLSSocket.kt:172)
at TLSClientSocket.read--5HJl4c(TLSClientSocket.kt:117)
at MQTTClient.check(MQTTClient.kt:283)
at MQTTClient.step(MQTTClient.kt:346)
at MQTTClient.run(MQTTClient.kt:355)

Using jitpack version 0.4.1

Please could you test on your side using amazon mq instance on mqtt protocol ?

Thanks

Socket connection error on windows native

I am currently implementing a Kotlin multiplatform Project and when I run the Windows 11 native I get a a Socket.IOException: Socket connect failed, error 10047, that I believe to be the win11 socket error 'Address family not supported by protocol family'.

the error comes up when i try to execute

client.publish(
                     retain = true,
                    Qos.EXACTLY_ONCE,
                    topic,
                    message.toUByteArray(),
                    MQTT5Properties(
                        serverKeepAlive = 5000u,
                        retainAvailable = 1u,))

where client is:

client = MQTTClient(
                    MQTTVersion.MQTT5,
                    host,
                    port,
                    tls = null,
                    userName = username,
                    password = password?.encodeToByteArray()?.toUByteArray(),
                    keepAlive = 5000,
                    cleanStart = false,
                )

I run the test locally using mosquitto and the same tests are working fine on JVM and Linux Native

iOSBuild failed with Could not find 'openssl-its-simulator-arm64'

Hi,

I have successfully integrated you MQTT library on my KMM project.

On Android it works and I can subscribe & publish to topics.
On iOS it fails building my iOS application and it does not event start in my simulator.
The build error is:
> Task :shared:compileKotlinIosSimulatorArm64 FAILED error: Could not find "openssl-ios-simulator-arm64" in [/Users/MyUser/path/to/project, /Users/MyUser/.konan/klib, /Users/MyUser/.konan/kotlin-native-prebuilt-macos-aarch64-1.9.10/klib/common, /Users/MyUser/.konan/kotlin-native-prebuilt-macos-aarch64-1.9.10/klib/platform/ios_simulator_arm64] error: Compilation finished with errors

Do you have any idea what's causing this?

PS: Excluding your mqtt lib and all relevant code from my app fixes building iOS app.

Thanks
Jan

ssl server certificate not found (IOS only)

Hello,

Trying to connect on IOS simulator (also a real phone) to mqtt broker with SSL.

My MQTT broker trusts the certificate on device directly, so no need to set any path on Android..

if (tlsSettings.serverCertificatePath != null) {
    if (SSL_CTX_load_verify_locations(sslContext, tlsSettings.serverCertificatePath, null) != 1) {
        throw Exception("Server certificate path not found")
    }
} else {
    if (SSL_CTX_load_verify_locations(sslContext, null, getenv(X509_get_default_cert_dir_env()?.toKString())?.toKString()) != 1) {
        throw Exception("Server certificate path not found") //Fail HERE
    }
}
 

But in IOS it throws on the "else" branch, any idea ?

Thanks for help.. it's really blocking.

Can't use client library for macos arm 64

I cloned the repo and published common and client to maven local.

My project script is just one file

    kotlin("multiplatform") version "1.9.0"
}

group = "me.alex"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
    mavenLocal()
}

kotlin {
    macosArm64("macos") {
        binaries {
            executable {
                entryPoint = "main"
            }
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("com.github.davidepianca98:kmqtt-client:0.4.1")
                implementation("com.github.davidepianca98:kmqtt-common:0.4.1")
            }
        }
        val macosMain by getting {
            dependencies {
                implementation("com.github.davidepianca98:kmqtt-common-macosarm64:0.4.1")
                implementation("com.github.davidepianca98:kmqtt-client-macosarm64:0.4.1")
            }
        }
    }
}

I have my main function in src/commonMain/kotlin/Main

Intellij indexer shows that I can import the MQTT library. Project compilation fails with
e: Could not find "openssl-macos-arm64" in [projectDir, /Users/alex/.konan/klib, /Users/alex/.konan/kotlin-native-prebuilt-macos-aarch64-1.9.0/klib/common, /Users/alex/.konan/kotlin-native-prebuilt-macos-aarch64-1.9.0/klib/platform/macos_arm64]

  1. Is my set up correct?
  2. what's the issue with open ssl? What to do here?
  3. I also want to build for an other target linuxarm64 (Raspberry Pi). Is this project compatable?

"Unable to parse TLS packet header"-error caused by 0-byte-channel-read

Description

Function putOrEnlarge() in src/jvmMain/kotlin/socket/tls/TLSSocket.kt:123 does not handle the case when 0 bytes have been received from super.readToBuffer() into the receiveBuffer.
Although nothing has been received, we still try to put into the cacheReceiveBuffer - for some reason, this causes a BufferOverflowException :-(
Following that, we will enlarge the buffer and try to unwrap the data which leads to an "Unable to parse TLS packet header" error eventually.

Files

src/jvmMain/kotlin/socket/tls/TLSSocket.kt
src/jvmMain/kotlin/socket/tcp/Socket.kt

To Reproduce

I'm running KMQTT broker using TLS on an android device together with a raspberry pi running mosquitto as client. TLS certificates need to be in place.

Every time I try to publish or subscribe to the broker, i get this "Unable to parse TLS packet header". During debugging, I found out, that i don't get this "0-byte-channel-read" when i set a breakpoint on tcpEventHandler.read() in the do-while-loop in handleEvent() in ServersocketLoop.kt:33. I guess that this "0-byte-channel-read" only happens if the broker sends a message to the client but the client is not fast enough to deliver a complete answer.

Unable to import MQTTClient in KMM project

Hi, this is an AWESOME project. I'm trying to import the kmqtt-client library in my own kmm library which is oriented to the Android/iOS platform. As I added the following lines in commonMain dependencies:

implementation("com.github.davidepianca98:kmqtt-common:0.4.2") 
implementation("com.github.davidepianca98:kmqtt-client:0.4.2")

I still cannot use the MQTTClient class in my code, it was appeared as unresolved reference.

One more question, is kmqtt-client planning to support Android platform?

Source and JavaDoc missing from JVM artifacts

I just want to report that the source code and JavaDoc are not available for the JVM artifacts when fetched from mavenCentral.

I'm using them on a single platform project:

dependencies {
    implementation("io.github.davidepianca98:kmqtt-common-jvm:0.4.3")
    implementation("io.github.davidepianca98:kmqtt-broker-jvm:0.4.3")
}

image

I'm on IntelliJ IDEA 2023.3.2 (Ultimate Edition).

Please let me know if you are able to reproduce the issue or if I should provide a reproduction project.

Username and Password in the PacketInterceptor

Hi,

Is it possible to get the authentication information in the packet interceptor? My use case would be to validate that certain user can send information for a topic or validate the payload.

Thanks!

Connecting to a home broker with TCP_PORT & MQTT_PORT

Hello. I wrote my home broker with access to the external Internet and cannot connect to it, since the path to it looks like this: tcp://ХХ.ХХ.Х.ХХХ:TCP_PORT:MQTT_PORT. That is, I have a separate port for TCP and for MQTT. How can I connect to my broker using your library?

TLSClientSettings from String instead of file path

Do you think there will be a possibility to make all file path based settings for TLSClientSettings to have also a String based settings ?
I know it's possible on JVM based platform but i don't know if other platform can take a String argument ?

public data class TLSClientSettings(
    val version: String = "TLS",
    val serverCertificatePath: String? = null,
    val clientCertificatePath: String? = null,
    val clientCertificateKeyPath: String? = null,
    val clientCertificatePassword: String? = null
)

Delay in receiving published messages

While testing the MQTT publish and subscribe functions in KMM I'm seeing a delay of more than 1-3 minutes. Please guide me on how this can be fixed.

kmqtt-broker - Error on TLS javax.net.ssl.SSLException : Unable to parse TLS packet header

I have been getting error like this whenever I have tried to connect to the MQTT Broker from some client with TLS enabled. Can anyone point me in the right direction please.

javax.net.ssl.SSLException: Unable to parse TLS packet header
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:807)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:747)
at com.android.org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:712)
at com.android.org.conscrypt.Java8EngineWrapper.unwrap(Java8EngineWrapper.java:237)
at socket.tls.TLSSocket.read0(TLSSocket.kt:136)
at socket.tls.TLSSocket.runHandshake(TLSSocket.kt:122)
at socket.tls.TLSSocket.<init>(TLSSocket.kt:28)
at socket.tls.TLSServerSocket.createSocket(TLSServerSocket.kt:78)
at socket.ServerSocket.accept(ServerSocket.kt:107)
at socket.ServerSocket.select(ServerSocket.kt:138)
at socket.ServerSocketLoop.run(ServerSocketLoop.kt:22)
at mqtt.broker.Broker.listen(Broker.kt:68)
at com.example.headphonetest.broker.MqttBrokerManager$startBroker$1.invokeSuspend(MqttBrokerManager.kt:106)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)
socket.SocketClosedException
at socket.tls.TLSSocket.send0-GBYM_sE(TLSSocket.kt:81)
at socket.tls.TLSSocket.read0(TLSSocket.kt:162)
at socket.tls.TLSSocket.runHandshake(TLSSocket.kt:122)
at socket.tls.TLSSocket.<init>(TLSSocket.kt:28)
at socket.tls.TLSServerSocket.createSocket(TLSServerSocket.kt:78)
at socket.ServerSocket.accept(ServerSocket.kt:107)
at socket.ServerSocket.select(ServerSocket.kt:138)
at socket.ServerSocketLoop.run(ServerSocketLoop.kt:22)
at mqtt.broker.Broker.listen(Broker.kt:68)
at com.example.headphonetest.broker.MqttBrokerManager$startBroker$1.invokeSuspend(MqttBrokerManager.kt:106)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)

I have a PKCS12 file (containing both the self - signed certificate and private key) stored in the android project's raw folder. The CA that signed the certificate is installed on both the MQTT client and broker device. Except for the warning of key length being 1024 -bits, ssl- checker shows the certificate as valid.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.