bytebeamio / rumqtt

The MQTT ecosystem in rust
Apache License 2.0
1.64k stars 252 forks source link

rumqttd: external auth should be async #797

Closed swanandx closed 9 months ago

swanandx commented 9 months ago

currently, the external authentication function is synchronous:

https://github.com/bytebeamio/rumqtt/blob/0266b85bd5986f556b3eaedc806c964e906232b8/rumqttd/src/lib.rs#L46

Issue

this means we have to use blocking functions, so lets say we have to sleep for some duration, we have to use std::thread::sleep(). Issue with this is that it will block the whole thread, thus no client will be able to make any progress!

for examples: c1 -> running fine, doing its job c2 -> tries to connect, but auth handler gets blocked c1 -> won't recv any incoming messages as server is blocked! and will have no clue why it isn't receiving anyting! c2 -> on client side, it will get network timeout, but on server, it will still be blocked.

Solution

Make external authentication asynchronous! e.g.

pub type AuthHandler = Arc<
    dyn Fn(ClientId, AuthUser, AuthPass) -> Pin<Box<dyn std::future::Future<Output = bool> + Send>>
        + Send
        + Sync
        + 'static,
>;

this will allow users to set async fns as auth handler and give them privilege to use non-blocking code for auth.

note: as the type is complex, it would be nice to have a helper method like set_auth_handler(_) which would take the fn and wrap it in Pin<Box<_>> [ method can be implemented on ConnectionSettings / ServerSettings or both :) ], similar to how we implement request_modifier in rumqttc.

ps: if someone still uses blocking code in async fn, the issue will still arise.