Skip to main content

Quick Start

This guide will walk you through creating a simple "Hello World" plugin for YedMQ. We will use Python for this example, but you can use any language that supports Unix Sockets or Named Pipes.

The goal is to create a plugin that handles the client authentication hook, printing a message when a client tries to connect.

1. Project Structure​

First, create a folder for your plugin. All your plugin files, including the executable and the configuration, will be stored here.

|- my-first-plugin/
| |- plugin.toml
| |- main.py

2. Plugin Configuration (plugin.toml)​

This file tells YedMQ how to run your plugin. Create a plugin.toml file with the following content:

[plugin]
name = "my-first-plugin"
author = "Your Name"
description = "A simple example plugin"
version = "0.0.1"
priority = 1000

[runtime]
type = "process"
# This command assumes you run the broker from the root of your project.
# 'python3' should be in your system's PATH.
executable = "python3"
args = ["my-first-plugin/main.py"]
  • executable: We set this to python3 to run our script.
  • args: We pass the path to our Python script as an argument.

3. The Plugin Script (main.py)​

The core of your plugin is the executable script. This script needs to:

  1. Parse command-line arguments to get the --auth-code and --socket-path.
  2. Connect to the IPC socket provided by the broker.
  3. Handle the Initialize request/response handshake.
  4. Listen for incoming messages (hooks) and respond to them.

Here is a simplified example using Python. Note that in a real-world scenario, you would use a Protobuf library to generate code for message serialization and deserialization. For simplicity, this example will focus on the logic and use pseudo-code for Protobuf handling.

# main.py
import socket
import sys
import argparse
import time

# In a real implementation, you would use generated Protobuf classes.
# from your_generated_protobuf_files import ProtocolMessage, InitializeRequest, InitializeResponse

def main():
parser = argparse.ArgumentParser()
parser.add_argument("--auth-code", required=True, help="Security token from YedMQ broker")
parser.add_argument("--socket-path", required=True, help="Path to the IPC socket")
args = parser.parse_args()

auth_code = args.auth_code
socket_path = args.socket_path

# 1. Connect to the socket
# On Linux/macOS, this will be a Unix Domain Socket.
# On Windows, you would use a library to connect to a Named Pipe.
client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
client_socket.connect(socket_path)
except socket.error as msg:
# You should write errors to stderr for the broker to capture
sys.stderr.write(f"Failed to connect to socket: {msg}\n")
sys.exit(1)

# 2. Perform the initialization handshake
# This is a simplified representation. You must construct a proper
# binary frame (Magic + Version + Length + Payload).

# First, the broker sends an InitializeRequest
# We need to read the message from the socket.
# raw_request = read_protocol_message(client_socket)
# request_message = ProtocolMessage.FromString(raw_request)

# Assume we received the InitializeRequest. Now, we send a response.
# initialize_response = InitializeResponse(
# status="ready",
# capabilities=["authentication"],
# hooks=[Hook(name="authenticate", priority=100)],
# auth_code=auth_code # IMPORTANT: Send back the auth_code
# )
# response_message = ProtocolMessage(
# type=MESSAGE_TYPE_RESPONSE,
# id="some-uuid",
# result=Any.pack(initialize_response)
# )
# send_protocol_message(client_socket, response_message)

# For this simple example, let's just log that we are "initialized"
sys.stdout.write("Plugin initialized successfully (simulation).\n")
sys.stdout.flush()


# 3. Main loop to handle incoming hook calls
while True:
# In a real plugin, you would continuously read from the socket
# for new messages from the broker.

# raw_message = read_protocol_message(client_socket)
# message = ProtocolMessage.FromString(raw_message)

# if message.method == METHOD_AUTHENTICATE:
# auth_request = AuthenticateRequest()
# message.params.Unpack(auth_request)
# print(f"Received authentication request for client: {auth_request.client_id}")

# # Respond that authentication is successful
# auth_response = AuthenticateResponse(authenticated=True, tenant_id="default")
# response = ProtocolMessage(...)
# send_protocol_message(client_socket, response)

# This is a placeholder loop
time.sleep(10)


if __name__ == "__main__":
# Add a small delay to simulate startup work
time.sleep(1)
main()

Note: The code above is a conceptual illustration. A real implementation requires:

  • A Protobuf library for your language to generate code from the .proto definitions. See the Protocol Definition page for the full schema and source file location.
  • A robust implementation for reading and writing the binary protocol frames to the socket.

4. Deploy the Plugin​

To deploy the plugin, you need to place its folder inside the YedMQ plugins directory.

Assuming your YedMQ installation is at /opt/yedmq, the structure would look like this:

/opt/yedmq/
β”œβ”€β”€ plugins/
β”‚ └── my-first-plugin/
β”‚ β”œβ”€β”€ plugin.toml
β”‚ └── main.py
└── ... (other YedMQ files)

5. Start YedMQ​

Now, start the YedMQ broker. If everything is configured correctly, the broker will:

  1. Read my-first-plugin/plugin.toml.
  2. Execute python3 my-first-plugin/main.py --auth-code ... --socket-path ....
  3. Establish an IPC connection.
  4. Perform the initialization handshake.
  5. Your plugin is now running and ready to receive hook calls.

You should see the "Plugin initialized successfully (simulation)." message in your broker's logs (or wherever you redirect your plugin's stdout). When a client connects, your plugin's METHOD_AUTHENTICATE handler would be called.