Embeddable and standalone Kotlin Multiplatform MQTT broker

Overview

KMQTT

Release

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

Features

✖️ = TODO
✔️ = Supported
= Experimental

Platform MQTT 3.1.1 MQTT 5.0 Clustering TCP TLS Websocket
JVM ✔️ ✔️ ✔️ ✔️ ✖️
Windows X64 ✔️ ✔️ ✖️ ✔️ ✔️ ✖️
Windows X86 ✔️ ✔️ ✖️ ✔️ ✔️ ✖️
Linux X64 ✔️ ✔️ ✖️ ✔️ ✔️ ✖️
Linux ARM32 ✔️ ✔️ ✖️ ✔️ ✔️ ✖️
Linux ARM64 ✔️ ✔️ ✖️ ✔️ ✔️ ✖️
Node.js ✔️ ✔️ ✖️ ✔️ ✖️ ✖️

Getting Started

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

Library

Gradle Maven

Global dependencies
repositories {
    jcenter()
    maven { url "https://jitpack.io" }
}
dependencies {
    implementation 'com.github.davidepianca98.KMQTT:kmqtt-jvm:0.2.9'
}

Replace jvm with linuxx64 or linuxarm32hfp based on the target. mingwx64 target is not yet available through JitPack.

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 automatically be required

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

kotlin {
    jvm()
    mingwX64("mingw")
    sourceSets {
        commonMain {
            dependencies {
                implementation 'com.github.davidepianca98:KMQTT:0.2.9'
            }
        }
    }
}

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()
}

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()
}

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()
}

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()
}

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.

Comments
  • Suggestions

    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.

    enhancement 
    opened by Z0lid 7
  • "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.

    opened by jayc2111 4
  • Failing to compile with Kotlin and Gradle KTS

    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"
    }
    
    opened by thiagonuic 4
  • HTTP header matching should be case insensitive to support more clients

    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
    
    opened by nibarius 2
  • Username and Password in the PacketInterceptor

    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!

    opened by thiagonuic 1
  • Kotlin native could not find

    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 ?

    opened by FJerabek 7
Releases(0.3.2)
Owner
Davide Pianca
Davide Pianca
TCP-capable MQTT client for react native

Quito A TCP-capable MQTT client for React Native. The module provides a Typescript API for native MQTT clients on iOS and Android. on Android, quito r

Kevin 5 Dec 3, 2022
Ktorfit - a HTTP client/Kotlin Symbol Processor for Kotlin Multiplatform (Js, Jvm, Android, iOS, Linux) using KSP and Ktor clients inspired by Retrofit

Ktorfit is a HTTP client/Kotlin Symbol Processor for Kotlin Multiplatform (Js, Jvm, Android, iOS, Linux) using KSP and Ktor clients inspired by Retrofit

Jens Klingenberg 637 Dec 25, 2022
Multiplatform coroutine-based HTTP client wrapper for Kotlin

networkinkt This is a lightweight HTTP client for Kotlin. It relies on coroutines on both JS & JVM platforms. Here is a simple GET request: val text =

Egor Zhdan 31 Jul 27, 2022
WebRTC Kotlin Multiplatform SDK

WebRTC Kotlin Multiplatform SDK

Alex Shepeliev 65 Dec 27, 2022
A gRPC Kotlin based server and client starter that builds with Gradle and runs on the JVM

gRPC Kotlin starter Overview This directory contains a simple bar service written as a Kotlin gRPC example. You can find detailed instructions for bui

Hypto 8 Sep 19, 2022
A product registration service using the Kotlin language and the Micronaut and Grpc framework

A product registration service using the Kotlin language and the Micronaut and Grpc framework

Mateus Araújo 30 Nov 2, 2022
Kotlin-echo-client - Echo client using Kotlin with Ktor networking library

Overview This repository contains an echo server implemented with Kotlin and kto

Elliot Barlas 2 Sep 1, 2022
Kotlin-REST-Retrofit - Simple client to consume a REST API with Retrofit using Kotlin

Kotlin REST Retrofit Sencillo cliente para consumir una API REST con Retrofit us

José Luis González Sánchez 5 Nov 4, 2022
Monitoring water tanker level using NodeMCU ESP8266 and HC-SR04P Ultrasonic Sensor and broadcasting it using a simple HTTP server inside NodeMCU ESP8266 and show data in an Android App

WaterLevel Preface This project aims to finding a tanker water level using NodeMCU with ESP8266 core and HC-SR04P Ultrasonic sensor and broadcasting i

YaMiN 12 Dec 20, 2022
HttpMocker is a simple HTTP mocking library written in Kotlin to quickly and easily handle offline modes in your apps

HttpMocker HttpMocker is a very lightweight Kotlin library that allows to mock HTTP calls relying on either OkHttp or the Ktor client libraries. It ca

David Blanc 174 Nov 28, 2022
An RPC library for Kotlin services that strives to balance developer productivity and performance.

IndieRpc An RPC library for Kotlin services that strives to balance developer productivity and performance. IndieRpc is inspired by Golang's net/rpc p

Asad Awadia 3 Nov 30, 2021
gRPC-Kotlin/JVM - An RPC library and framework

gRPC-Kotlin/JVM - An RPC library and framework A Kotlin/JVM implementation of gRPC: A high performance, open source, general RPC framework that puts m

null 2 Nov 25, 2021
Starter code for getting and saving data from the Internet using Kotlin.

Doggos Description Doggos is an app that fetches (pun intended) information from a third party API. The API returns data about a random dog that conta

Latifah President 0 Nov 4, 2021
LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

马天宇 829 Dec 29, 2022
Pluto is a on-device debugger for Android applications, which helps in inspection of HTTP requests/responses, capture Crashes and ANRs and manipulating application data on-the-go.

Pluto Pluto is a on-device debugger for Android applications, which helps in inspection of HTTP requests/responses, capture Crashes and ANRs and manip

Mocklets 8 Aug 22, 2022
Write your asynchronous Network / IO call painlessly in Kotlin !!

Asynkio : Write asynced IO/ Network calls painlessly on android | | | Documentation Write your network requests, IO calls in android with Kotlin seaml

Nikhil Chaudhari 82 Jan 26, 2022
Kotlin HTTP requests library. Similar to Python requests.

khttp khttp is a simple library for HTTP requests in Kotlin. It functions similarly to Python's requests module. import khttp.get fun main(args: Arra

Anna Clemens 466 Dec 20, 2022
Kotlin DSL http client

Introduction Kotlin DSL http client Features ?? Developers Experience-driven library without verbosity. ?? Native way to use http client in Kotlin. ??

Sergei Rybalkin 461 Dec 13, 2022
The easiest HTTP networking library for Kotlin/Android

Fuel The easiest HTTP networking library for Kotlin/Android. You are looking at the documentation for 2.x.y.. If you are looking for the documentation

Kittinun Vantasin 4.3k Jan 8, 2023