eclipse / mosquitto

Eclipse Mosquitto - An open source MQTT broker
https://mosquitto.org
Other
8.93k stars 2.37k forks source link

Improve plugin documentation #2219

Open Tejpbit opened 3 years ago

Tejpbit commented 3 years ago

Hey. I've been working on a rust-bindings library for plugins for a while now. (This one: https://github.com/TotalKrill/mosquitto_plugin). And while I was researching how stuff works I've stumbled upon a few cases where documentation is lacking.

I thought I would create an issue here to ask all the questions I've had along the way with the answers I've dug up(or guessed). After we've had some back and forth to determine what's what we can create a PR or two to update the documentation in a few relevant places.

The event enums

Descriptions of what these enums mean for the mosquitto_callback_register Most of these are obvious but some are not. I'll put my best guesses here and we can work from there.

MOSQ_EVT_RELOAD Triggered when the config file is reloaded during runtime with the SIGHUP signal.

MOSQ_EVT_ACL_CHECK Triggered for every subscribe, write and read. Return value determines if the action is allowed. (What are the expected return values? I'm guessing only a few in the mosq_err_t enum are handled while the rest are treated as a default case. E.g. MOSQ_ERR_SUCCESS, MOSQ_ERR_PLUGIN_DEFER, MOSQ_ERR_ACL_DENIED have meaning but the rest just default to deny.)

MOSQ_EVT_BASIC_AUTH Triggered on a new connection. (Same here, expected return values? I'm guessing MOSQ_ERR_SUCCESS is the only one that means something. Anything else is a failed authentication.)

MOSQ_EVT_EXT_AUTH_START I'm guessing this in combination with MOSQ_EVT_EXT_AUTH_CONTINUE works the same as the v4 mosquitto_auth_start. How does it interact with the basic auth check? Both are called if they are registered? There's no logic to separate these inside mosquitto. It's all up to the implementer of the plugin? (I later found this in man mosquitto.conf 5 "It is possible to support multiple authentication schemes at once. A config could be created that had a listener for all of the different encryption options described above and hence a large number of ways of authenticating.")

MOSQ_EVT_EXT_AUTH_CONTINUE see previous

MOSQ_EVT_CONTROL I'm guessing this is used by the dynamic security plugin? Things that are published on the $CONTROL/# topic can be listened to by plugins. It's for explicit communication from a client to the broker so we don't need to hook onto special prefixes in the MOSQ_EVT_ACL_CHECK check or the MOSQ_EVT_MESSAGE.

MOSQ_EVT_MESSAGE Triggered for all messages sent on the broker. So this doesn't trigger if the acl check doesn't go through, right?

MOSQ_EVT_PSK_KEY Called by the broker when a client connects using TLS/PSK based auth, right? The plugin should input the correct key into the key field of the _mosquitto_evt_pskkey struct. The broker compares that key to what was provided by the client. This event callback allows us to maintain the identity to key mapping in somethis else than the psk_file. Would be nice with some more insights to what the fields in mosquitto_evt_psk_key are. But I guess most of them transfer from the v4 mosquitto_psk_key_get struct mosquitto_evt_psk_key { void future; struct mosquitto client; // the connecting mqtt client. const char hint; // write a hint for the connecting client (is there a max length to this?) const char identity; // the identity string provided by the client char key; // a string where the hex PSK should be copied by the plugin which is then compared to the key the client has provided. int max_key_len; // maximum length of the key that the plugin can write to the key field. void *future2[4]; };

MOSQ_EVT_TICK Hook onto the broker's regular execution loop. A place to do things you would otherwise need your own thread for.

MOSQ_EVT_DISCONNECT Client disconnect callback. This callback wasn't possible with the v4 plugin interface.

When registering for all of these events the callback signature requires the callback to return a success status. However, all of the events callbacks does not care about the returned status, right? For example, the MOSQ_EVT_DISCONNECT. You can return whatever int you want here. The broker will just ignore it. And as I understood it from some other thread I read. In C11 you are allowed to not return anything even if the signature wants an int returned. As long as the program doesn't look at the return value it is allowed behaviour. I'm assuming that is what is happening in the example given in this issue: https://github.com/eclipse/mosquitto/issues/2073#issuecomment-773677323

The userdata

In v4 mosquitto_auth_plugin_init the broker hands us a user_data where the plugin can hand the broker a pointer to any stateful data. This pointer is then sent to all event callbacks. In v5 we have this same user_data parameter in the mosquitto_plugin_init. I'm not sure where this is used after handing it to the broker. The mosquitto_callback_register has its own userdata parameter that I'm assuming is handed to the registered callback. But why isn't it a userdata? Moreover a question about the mosquitto_callback_unregister. What's up with the signature of this function? If we can only have only callback per event type. Why do I need to send a pointer to the function I want to unregister? Also, what is the userdata used for in this function call? Why isn't it enough with just the identifier reference of the plugin and the event type I want to unregister?

I know there are a ton of questions in this text and a lot of guesswork on my part. I'll probably return with my own answers about the userdata in the different callbacks when I get a bit further into implementation.

ralight commented 3 years ago

Thanks for the questions, I'm aware the documentation is lacking for the new plugin interface. I'll get you some answers when I can.

Tejpbit commented 3 years ago

Some answers to my own questions about user_data. The user_data parameter that you write to in the mosquitto_plugin_init is handed to the mosquitto_plugin_cleanup. While all the event callbacks have their own separate user_data it is likely (at least it's the case for me) that you use the same pointer for all the callbacks to share state between them. But that memory still needs to be cleaned up.. in the mosquitto_plugin_cleanup.

guydingmike commented 8 months ago

I have the same questions.