Mochi-MQTT Server

repository·main·Indexed 23 days ago

https://github.com/mochi-mqtt/server

A high-performance, embeddable Go-based MQTT broker supporting MQTT v5 and v3.1.1. Designed for IoT and telemetry, it features a hook-based plugin system for authentication, persistence (BadgerDB, PebbleDB, Redis), and debugging, as well as an inline client for programmatic publishing and subscribing from within Go applications.

Tokens
15.5K
Snippets
34
Records
70
Agent score
82%

What's inside mochi-mqtt-server

  1. Performance Benchmarks

    main

    Mochi-MQTT performance is comparable to well-known brokers like Mosquitto and EMQX. Benchmarks are conducted using MQTT-Stresser on an Apple Macbook Air M2 using the default settings from cmd/main.go.

    Note that benchmark values represent a relative score based on mqtt-stresser calculations rather than a direct messages-per-second throughput. Higher scores indicate better performance. Results are provided as a general performance guideline and may vary based on environment and configuration.

  2. Default Message Expiry Behavior

    main
    To protect against DoS attacks on untrusted networks, server.Options.Capabilities.MaximumMessageExpiryInterval is set to 86400 (24 hours) by default. This prevents infinite accumulation of retained or pending messages. If you are in a trusted environment and require longer retention, you can override this by setting it to a larger value or 0 to disable expiry entirely.
  3. Develop with Event Hooks

    main

    Mochi-MQTT provides a wide range of event hooks to interact with the broker and client lifecycle. You can implement the mqtt.Hook interface to inject custom logic at various stages of the MQTT protocol flow.

    Key Hook Categories

    • Packet Manipulation: The most flexible hooks are OnPacketRead, OnPacketEncode, and OnPacketSent. These allow you to intercept, inspect, and modify all incoming and outgoing packets.
    • Authentication & Authorization: To implement custom security, you must use OnConnectAuthenticate (to allow or deny access) and OnACLCheck (to control access to specific topics).
    • Lifecycle Management: Hooks like OnStarted, OnStopped, OnConnect, OnDisconnect, and OnSessionEstablished allow you to react to server and client state changes.
    • Message Flow: Hooks such as OnPublish, OnSubscribe, OnUnsubscribe, and OnRetainMessage provide visibility into message routing and storage.
    • Persistence: If building a persistent storage layer, use hooks like StoredClients, StoredSubscriptions, StoredInflightMessages, and StoredRetainedMessages to manage data across restarts.

    For full function signatures and the mqtt.Hook interface definition, refer to hooks.go in the repository.

  4. Understand Mochi-MQTT Event Hooks

    main

    Mochi-MQTT uses a universal Event Hooks system that allows developers to customize or modify server functionality at various stages of the server and client lifecycles. Hooks are used for tasks such as authentication, persistent storage, and debugging.

    Key characteristics:

    • Stackable: You can add multiple hooks to a server. They execute in the order they were added.
    • Chainable: Some hooks modify values, and these modified values are passed to subsequent hooks in the chain before being returned.

    Common Hook Types:

    • Access Control: auth.AllowHook (allows everything) or auth.Auth (rule-based access).
    • Persistent Storage: storage/badger, storage/pebble, or storage/redis (Note: storage/bolt is deprecated).
    • Debugging: debug.Hook for packet trace visualization.
  5. Default Configuration: Message Expiry

    main
    By default, server.Options.Capabilities.MaximumMessageExpiryInterval is set to 86400 (24 hours). This is a security measure to prevent Denial of Service (DoS) attacks by limiting the accumulation of retained or in-flight messages. In trusted environments, you can increase this or set it to 0 to remove the limit.
  6. Use Event Hooks to extend Mochi MQTT

    main

    Mochi MQTT provides numerous hooks throughout the broker and client lifecycle. These hooks allow you to implement custom logic for authentication, authorization (ACL), persistence, and packet manipulation.

    Key Hook Categories

    • Lifecycle Hooks: OnStarted (server start), OnStopped (server shutdown), OnConnect (client connection), OnDisconnect (client disconnection).
    • Security Hooks:
      • OnConnectAuthenticate: Required for implementing custom authentication. Return true to allow access or false to deny.
      • OnACLCheck: Used to authorize a user's attempt to publish or subscribe to a specific topic filter.
    • Packet Manipulation Hooks:
      • OnPacketRead: Triggered when a packet is received from a client. Allows modifying the packet.
      • OnPacketEncode: Triggered just before an encoded packet is sent to a client. Allows modifying the packet.
      • OnAuthPacket: Allows handling and modifying MQTT v5 authentication packets.
    • Persistence Hooks: Use hooks like StoredClients, StoredSubscriptions, StoredInflightMessages, StoredRetainedMessages, and StoredSysInfo to implement custom storage backends (e.g., for database-backed persistence).
    • Message Hooks: OnPublish, OnPublished, OnRetainMessage, OnQosPublish, etc.

    For a complete list of function signatures, refer to hooks.go in the repository.

  7. Extend functionality using Event Hooks

    main

    Mochi-MQTT provides an mqtt.Hook interface to allow developers to inject custom logic into the server and client lifecycles. Hooks can be used for authentication, ACL checks, data modification, and persistence.

    Key Hook Categories

    • Data Manipulation (Most Flexible):
      • OnPacketRead: Called when a packet is received from a client. Allows packet modification.
      • OnPacketEncode: Called immediately before a packet is encoded and sent to a client. Allows packet modification.
      • OnPacketSent: Called after a packet has been sent to a client.
    • Authentication & Authorization:
      • OnConnectAuthenticate: Called when a user attempts to authenticate. Return true to allow access or false to deny. Implement this alongside OnACLCheck to build custom authentication systems.
      • OnACLCheck: Called when a user attempts to publish or subscribe to a topic to enforce Access Control List rules.
    • Lifecycle Management:
      • OnStarted / OnStopped: Called when the server starts or stops successfully.
      • OnConnect / OnDisconnect: Called when a client connects or disconnects.
      • OnSessionEstablish / OnSessionEstablished: Called during the session setup process after authentication.
    • Persistence (Storage Hooks): To implement custom persistent storage, implement hooks that return data from your database:
      • StoredClients: Returns the list of clients.
      • StoredSubscriptions: Returns all subscriptions for clients.
      • StoredInflightMessages: Returns messages that are currently in flight.
      • StoredRetainedMessages: Returns retained messages.
      • StoredSysInfo: Returns stored system state information.

    All hooks are defined in the mqtt.Hook interface.

  8. How event hooks work in Mochi MQTT

    main

    Mochi MQTT uses a universal event hooks system that allows developers to intercept and modify the server and client lifecycle. Hooks are used for implementing features like authentication, persistent storage, and debugging tools.

    Key characteristics:

    • Stackable: You can add multiple hooks to a server. They are executed in the order they were added.
    • Modifiable: Some hooks can modify values. These modified values are passed to subsequent hooks in the stack before being returned to the runtime code.
    • Extensible: Many internal server functions are exposed, allowing you to implement custom hooks by following existing patterns.
  9. Run Mochi-MQTT tests

    main

    Unit Tests

    To run the internal unit tests and check code coverage, use the standard Go test command:

    go run --cover ./...

    Paho Interoperability Test

    To verify MQTT v5 and v3 compatibility against the Eclipse Paho test suite:

    1. Start the broker using the provided example: go run examples/paho/main.go.
    2. From the interoperability folder of the Paho testing repository, run the Python test client:
    python3 client_test5.py

    Note: Some compatibility modes are enabled in the paho/main.go example to account for known false negatives in the Paho suite.

  10. Use Inline Clients to publish and subscribe from the server

    main

    Since v2.4.0, you can enable an 'Inline Client' to allow the server to act as a client itself. This allows the server to directly publish, subscribe, and unsubscribe to topics, bypassing standard ACL and topic validation checks (allowing access even to $SYS topics).

    Enable Inline Client

    Enable the feature in the mqtt.Options during server initialization:

    server := mqtt.New(&mqtt.Options{
      InlineClient: true,
    })

    Inline Publish

    Use server.Publish to send a message directly from the server:

    err := server.Publish("direct/publish", []byte("packet scheduled message"), false, 0)

    Note: The QoS level only applies to the subscribers, following the MQTT v5 specification.

    Inline Subscribe

    Use server.Subscribe with a callback function to handle incoming messages. The default QoS for inline subscriptions is 0.

    callbackFn := func(cl *mqtt.Client, sub packets.Subscription, pk packets.Packet) {
        server.Log.Info("inline client received message from subscription", "client", cl.ID, "subscriptionId", sub.Identifier, "topic", pk.TopicName, "payload", string(pk.Payload))
    }
    server.Subscribe("direct/#", 1, callbackFn)

    Inline Unsubscribe

    To stop receiving messages from an inline subscription:

    server.Unsubscribe("direct/#", 1)
  11. Guidelines for contributing to Mochi MQTT

    main

    If you wish to contribute code or feedback, please submit an issue on GitHub. When submitting a Pull Request (PR), follow these guidelines:

    • Maintain test coverage where reasonable.
    • Clearly explain the purpose and reasoning for the PR.
    • Include the appropriate SPDX headers in any new files you contribute.

    To ensure proper recognition, add an SPDX-FileContributor line for every contributor to a file. This ensures your contributions are properly attributed.

    // SPDX-License-Identifier: MIT
    // SPDX-FileCopyrightText: 2023 mochi-mqtt
    // SPDX-FileContributor: Your name or alias <optional@email.address>
    
    package name
  12. Run tests for Mochi MQTT

    main

    Unit Testing

    To run the internal unit tests and check code coverage, use:

    go run --cover ./...

    Paho Interoperability Testing

    To verify compatibility with the Paho MQTT ecosystem:

    1. Start the broker using examples/paho/main.go.
    2. Run the Python test client located in the interoperability folder:
      python3 client_test5.py
      This tests both MQTT v3 and MQTT v5 compatibility. Note that some compatibility modes may be enabled in the example to account for known issues in the Paho test suite.