diff --git a/Source/MQTTnet.Server/Configuration/PathHelper.cs b/Source/MQTTnet.Server/Configuration/PathHelper.cs new file mode 100644 index 0000000..84327ac --- /dev/null +++ b/Source/MQTTnet.Server/Configuration/PathHelper.cs @@ -0,0 +1,24 @@ +using System; +using System.IO; + +namespace MQTTnet.Server.Configuration +{ + public static class PathHelper + { + public static string ExpandPath(string path) + { + if (path == null) + { + return null; + } + + var uri = new Uri(path, UriKind.RelativeOrAbsolute); + if (!uri.IsAbsoluteUri) + { + return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path); + } + + return path; + } + } +} diff --git a/Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs b/Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs index bb71a15..702ef63 100644 --- a/Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs +++ b/Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs @@ -4,6 +4,8 @@ namespace MQTTnet.Server.Configuration { public class ScriptingSettingsModel { + public string ScriptsPath { get; set; } + public List IncludePaths { get; set; } } } diff --git a/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs b/Source/MQTTnet.Server/Mqtt/MqttServerConnectionValidator.cs similarity index 69% rename from Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs rename to Source/MQTTnet.Server/Mqtt/MqttServerConnectionValidator.cs index fd27d76..4e13c83 100644 --- a/Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs +++ b/Source/MQTTnet.Server/Mqtt/MqttServerConnectionValidator.cs @@ -7,12 +7,12 @@ using MQTTnet.Server.Scripting; namespace MQTTnet.Server.Mqtt { - public class MqttConnectionValidator : IMqttServerConnectionValidator + public class MqttServerConnectionValidator : IMqttServerConnectionValidator { private readonly PythonScriptHostService _pythonScriptHostService; private readonly ILogger _logger; - public MqttConnectionValidator(PythonScriptHostService pythonScriptHostService, ILogger logger) + public MqttServerConnectionValidator(PythonScriptHostService pythonScriptHostService, ILogger logger) { _pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); @@ -24,18 +24,22 @@ namespace MQTTnet.Server.Mqtt { var pythonContext = new PythonDictionary { - { "client_id", context.ClientId }, { "endpoint", context.Endpoint }, { "is_secure_connection", context.IsSecureConnection }, + { "client_id", context.ClientId }, { "username", context.Username }, { "password", context.Password }, - { "raw_password", context.RawPassword }, - { "result", PythonConvert.Pythonfy(context.ReturnCode) } + { "raw_password", new Bytes(context.RawPassword) }, + { "clean_session", context.CleanSession}, + { "authentication_method", context.AuthenticationMethod}, + { "authentication_data", new Bytes(context.AuthenticationData)}, + + { "result", PythonConvert.Pythonfy(context.ReasonCode) } }; _pythonScriptHostService.InvokeOptionalFunction("on_validate_client_connection", pythonContext); - context.ReturnCode = PythonConvert.ParseEnum((string)pythonContext["result"]); + context.ReasonCode = PythonConvert.ParseEnum((string)pythonContext["result"]); } catch (Exception exception) { diff --git a/Source/MQTTnet.Server/Mqtt/MqttServerService.cs b/Source/MQTTnet.Server/Mqtt/MqttServerService.cs index ce34031..6323738 100644 --- a/Source/MQTTnet.Server/Mqtt/MqttServerService.cs +++ b/Source/MQTTnet.Server/Mqtt/MqttServerService.cs @@ -30,7 +30,7 @@ namespace MQTTnet.Server.Mqtt private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler; private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler; private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler; - private readonly MqttConnectionValidator _mqttConnectionValidator; + private readonly MqttServerConnectionValidator _mqttConnectionValidator; private readonly IMqttServer _mqttServer; private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor; private readonly PythonScriptHostService _pythonScriptHostService; @@ -43,7 +43,7 @@ namespace MQTTnet.Server.Mqtt MqttClientDisconnectedHandler mqttClientDisconnectedHandler, MqttClientSubscribedTopicHandler mqttClientSubscribedTopicHandler, MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler, - MqttConnectionValidator mqttConnectionValidator, + MqttServerConnectionValidator mqttConnectionValidator, MqttSubscriptionInterceptor mqttSubscriptionInterceptor, MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor, MqttServerStorage mqttServerStorage, diff --git a/Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs b/Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs index 49875be..a287884 100644 --- a/Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs +++ b/Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs @@ -35,7 +35,7 @@ namespace MQTTnet.Server.Mqtt return; } - _path = ExpandPath(); + _path = PathHelper.ExpandPath(_mqttSettings.RetainedApplicationMessages.Path); // The retained application messages are stored in a separate thread. // This is mandatory because writing them to a slow storage (like RaspberryPi SD card) @@ -115,18 +115,5 @@ namespace MQTTnet.Server.Mqtt return null; } } - - private string ExpandPath() - { - var path = _mqttSettings.RetainedApplicationMessages.Path; - - var uri = new Uri(path, UriKind.RelativeOrAbsolute); - if (!uri.IsAbsoluteUri) - { - path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path); - } - - return path; - } } } diff --git a/Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs b/Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs index 23cb531..c521d9d 100644 --- a/Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs +++ b/Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs @@ -17,7 +17,7 @@ namespace MQTTnet.Server.Scripting { private readonly IDictionary _proxyObjects = new ExpandoObject(); private readonly List _scriptInstances = new List(); - private readonly string _scriptsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts"); + private readonly string _scriptsPath; private readonly ScriptingSettingsModel _scriptingSettings; private readonly ILogger _logger; private readonly ScriptEngine _scriptEngine; @@ -29,6 +29,8 @@ namespace MQTTnet.Server.Scripting _scriptEngine = IronPython.Hosting.Python.CreateEngine(); _scriptEngine.Runtime.IO.SetOutput(pythonIOStream, Encoding.UTF8); + + _scriptsPath = PathHelper.ExpandPath(scriptingSettings.ScriptsPath); } public void Configure() @@ -186,13 +188,7 @@ namespace MQTTnet.Server.Scripting foreach (var path in _scriptingSettings.IncludePaths) { - var effectivePath = path; - - var uri = new Uri(effectivePath, UriKind.RelativeOrAbsolute); - if (!uri.IsAbsoluteUri) - { - effectivePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, effectivePath); - } + var effectivePath = PathHelper.ExpandPath(path); if (Directory.Exists(effectivePath)) { diff --git a/Source/MQTTnet.Server/Scripts/00_sample.py b/Source/MQTTnet.Server/Scripts/00_sample.py index ce508a9..fb6c290 100644 --- a/Source/MQTTnet.Server/Scripts/00_sample.py +++ b/Source/MQTTnet.Server/Scripts/00_sample.py @@ -25,20 +25,45 @@ def on_validate_client_connection(context): print(context) + # Access some custom data here which was inserted upon connect and may use it for validation. mqtt_net_server.write_shared_data(context["client_id"], {"custom_value_1": 1, "custom_value_2": True}) return + + # Supported results: + # * success + # * unspecified_error + # * malformed_packet + # * protocol_error + # * implementation_specific_error + # * unsupported_protocol_version + # * client_identifier_not_valid + # * bad_user_name_or_password + # * not_authorized + # * server_unavailable + # * server_busy + # * banned + # * bad_authentication_method + # * topic_name_invalid + # * packet_too_large + # * quota_exceeded + # * payload_format_invalid + # * retain_not_supported + # * qos_not_supported + # * use_another_server + # * server_moved + # * connection_rate_exceeded if context["client_id"] != "test_client": - context["result"] = "connection_refused_not_authorized" + context["result"] = "bad_user_name_or_password" return if context["username"] != "bud spencer": - context["result"] = "connection_refused_not_authorized" + context["result"] = "bad_user_name_or_password" return if context["password_string"] != "secret": - context["result"] = "connection_refused_not_authorized" + context["result"] = "bad_user_name_or_password" print(context) diff --git a/Source/MQTTnet.Server/Web/Startup.cs b/Source/MQTTnet.Server/Web/Startup.cs index d9db0fb..8ef622e 100644 --- a/Source/MQTTnet.Server/Web/Startup.cs +++ b/Source/MQTTnet.Server/Web/Startup.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; @@ -17,7 +16,6 @@ using MQTTnet.Server.Logging; using MQTTnet.Server.Mqtt; using MQTTnet.Server.Scripting; using MQTTnet.Server.Scripting.DataSharing; -using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerUI; namespace MQTTnet.Server.Web @@ -111,7 +109,7 @@ namespace MQTTnet.Server.Web services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Source/MQTTnet.Server/appsettings.json b/Source/MQTTnet.Server/appsettings.json index 1008a13..9a9ce0d 100644 --- a/Source/MQTTnet.Server/appsettings.json +++ b/Source/MQTTnet.Server/appsettings.json @@ -48,6 +48,7 @@ "EnableDebugLogging": false }, "Scripting": { + "ScriptsPath": "Scripts", "IncludePaths": [ "Lib", "/usr/lib/python2.7",