Browse Source

Expose more properties of the connection validator context in MQTTnet.Server. Migrate return code to reason code.

release/3.x.x
Christian Kratky 5 years ago
parent
commit
0c7a5a992b
9 changed files with 73 additions and 36 deletions
  1. +24
    -0
      Source/MQTTnet.Server/Configuration/PathHelper.cs
  2. +2
    -0
      Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs
  3. +10
    -6
      Source/MQTTnet.Server/Mqtt/MqttServerConnectionValidator.cs
  4. +2
    -2
      Source/MQTTnet.Server/Mqtt/MqttServerService.cs
  5. +1
    -14
      Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs
  6. +4
    -8
      Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs
  7. +28
    -3
      Source/MQTTnet.Server/Scripts/00_sample.py
  8. +1
    -3
      Source/MQTTnet.Server/Web/Startup.cs
  9. +1
    -0
      Source/MQTTnet.Server/appsettings.json

+ 24
- 0
Source/MQTTnet.Server/Configuration/PathHelper.cs View File

@@ -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;
}
}
}

+ 2
- 0
Source/MQTTnet.Server/Configuration/ScriptingSettingsModel.cs View File

@@ -4,6 +4,8 @@ namespace MQTTnet.Server.Configuration
{ {
public class ScriptingSettingsModel public class ScriptingSettingsModel
{ {
public string ScriptsPath { get; set; }

public List<string> IncludePaths { get; set; } public List<string> IncludePaths { get; set; }
} }
} }

Source/MQTTnet.Server/Mqtt/MqttConnectionValidator.cs → Source/MQTTnet.Server/Mqtt/MqttServerConnectionValidator.cs View File

@@ -7,12 +7,12 @@ using MQTTnet.Server.Scripting;


namespace MQTTnet.Server.Mqtt namespace MQTTnet.Server.Mqtt
{ {
public class MqttConnectionValidator : IMqttServerConnectionValidator
public class MqttServerConnectionValidator : IMqttServerConnectionValidator
{ {
private readonly PythonScriptHostService _pythonScriptHostService; private readonly PythonScriptHostService _pythonScriptHostService;
private readonly ILogger _logger; private readonly ILogger _logger;


public MqttConnectionValidator(PythonScriptHostService pythonScriptHostService, ILogger<MqttConnectionValidator> logger)
public MqttServerConnectionValidator(PythonScriptHostService pythonScriptHostService, ILogger<MqttServerConnectionValidator> logger)
{ {
_pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService)); _pythonScriptHostService = pythonScriptHostService ?? throw new ArgumentNullException(nameof(pythonScriptHostService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -24,18 +24,22 @@ namespace MQTTnet.Server.Mqtt
{ {
var pythonContext = new PythonDictionary var pythonContext = new PythonDictionary
{ {
{ "client_id", context.ClientId },
{ "endpoint", context.Endpoint }, { "endpoint", context.Endpoint },
{ "is_secure_connection", context.IsSecureConnection }, { "is_secure_connection", context.IsSecureConnection },
{ "client_id", context.ClientId },
{ "username", context.Username }, { "username", context.Username },
{ "password", context.Password }, { "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); _pythonScriptHostService.InvokeOptionalFunction("on_validate_client_connection", pythonContext);


context.ReturnCode = PythonConvert.ParseEnum<MqttConnectReturnCode>((string)pythonContext["result"]);
context.ReasonCode = PythonConvert.ParseEnum<MqttConnectReasonCode>((string)pythonContext["result"]);
} }
catch (Exception exception) catch (Exception exception)
{ {

+ 2
- 2
Source/MQTTnet.Server/Mqtt/MqttServerService.cs View File

@@ -30,7 +30,7 @@ namespace MQTTnet.Server.Mqtt
private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler; private readonly MqttClientDisconnectedHandler _mqttClientDisconnectedHandler;
private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler; private readonly MqttClientSubscribedTopicHandler _mqttClientSubscribedTopicHandler;
private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler; private readonly MqttClientUnsubscribedTopicHandler _mqttClientUnsubscribedTopicHandler;
private readonly MqttConnectionValidator _mqttConnectionValidator;
private readonly MqttServerConnectionValidator _mqttConnectionValidator;
private readonly IMqttServer _mqttServer; private readonly IMqttServer _mqttServer;
private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor; private readonly MqttSubscriptionInterceptor _mqttSubscriptionInterceptor;
private readonly PythonScriptHostService _pythonScriptHostService; private readonly PythonScriptHostService _pythonScriptHostService;
@@ -43,7 +43,7 @@ namespace MQTTnet.Server.Mqtt
MqttClientDisconnectedHandler mqttClientDisconnectedHandler, MqttClientDisconnectedHandler mqttClientDisconnectedHandler,
MqttClientSubscribedTopicHandler mqttClientSubscribedTopicHandler, MqttClientSubscribedTopicHandler mqttClientSubscribedTopicHandler,
MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler, MqttClientUnsubscribedTopicHandler mqttClientUnsubscribedTopicHandler,
MqttConnectionValidator mqttConnectionValidator,
MqttServerConnectionValidator mqttConnectionValidator,
MqttSubscriptionInterceptor mqttSubscriptionInterceptor, MqttSubscriptionInterceptor mqttSubscriptionInterceptor,
MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor, MqttApplicationMessageInterceptor mqttApplicationMessageInterceptor,
MqttServerStorage mqttServerStorage, MqttServerStorage mqttServerStorage,


+ 1
- 14
Source/MQTTnet.Server/Mqtt/MqttServerStorage.cs View File

@@ -35,7 +35,7 @@ namespace MQTTnet.Server.Mqtt
return; return;
} }


_path = ExpandPath();
_path = PathHelper.ExpandPath(_mqttSettings.RetainedApplicationMessages.Path);


// The retained application messages are stored in a separate thread. // The retained application messages are stored in a separate thread.
// This is mandatory because writing them to a slow storage (like RaspberryPi SD card) // This is mandatory because writing them to a slow storage (like RaspberryPi SD card)
@@ -115,18 +115,5 @@ namespace MQTTnet.Server.Mqtt
return null; 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;
}
} }
} }

+ 4
- 8
Source/MQTTnet.Server/Scripting/PythonScriptHostService.cs View File

@@ -17,7 +17,7 @@ namespace MQTTnet.Server.Scripting
{ {
private readonly IDictionary<string, object> _proxyObjects = new ExpandoObject(); private readonly IDictionary<string, object> _proxyObjects = new ExpandoObject();
private readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>(); private readonly List<PythonScriptInstance> _scriptInstances = new List<PythonScriptInstance>();
private readonly string _scriptsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts");
private readonly string _scriptsPath;
private readonly ScriptingSettingsModel _scriptingSettings; private readonly ScriptingSettingsModel _scriptingSettings;
private readonly ILogger<PythonScriptHostService> _logger; private readonly ILogger<PythonScriptHostService> _logger;
private readonly ScriptEngine _scriptEngine; private readonly ScriptEngine _scriptEngine;
@@ -29,6 +29,8 @@ namespace MQTTnet.Server.Scripting


_scriptEngine = IronPython.Hosting.Python.CreateEngine(); _scriptEngine = IronPython.Hosting.Python.CreateEngine();
_scriptEngine.Runtime.IO.SetOutput(pythonIOStream, Encoding.UTF8); _scriptEngine.Runtime.IO.SetOutput(pythonIOStream, Encoding.UTF8);

_scriptsPath = PathHelper.ExpandPath(scriptingSettings.ScriptsPath);
} }


public void Configure() public void Configure()
@@ -186,13 +188,7 @@ namespace MQTTnet.Server.Scripting


foreach (var path in _scriptingSettings.IncludePaths) 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)) if (Directory.Exists(effectivePath))
{ {


+ 28
- 3
Source/MQTTnet.Server/Scripts/00_sample.py View File

@@ -25,20 +25,45 @@ def on_validate_client_connection(context):
print(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}) mqtt_net_server.write_shared_data(context["client_id"], {"custom_value_1": 1, "custom_value_2": True})


return 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": if context["client_id"] != "test_client":
context["result"] = "connection_refused_not_authorized"
context["result"] = "bad_user_name_or_password"
return return


if context["username"] != "bud spencer": if context["username"] != "bud spencer":
context["result"] = "connection_refused_not_authorized"
context["result"] = "bad_user_name_or_password"
return return


if context["password_string"] != "secret": if context["password_string"] != "secret":
context["result"] = "connection_refused_not_authorized"
context["result"] = "bad_user_name_or_password"


print(context) print(context)




+ 1
- 3
Source/MQTTnet.Server/Web/Startup.cs View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@@ -17,7 +16,6 @@ using MQTTnet.Server.Logging;
using MQTTnet.Server.Mqtt; using MQTTnet.Server.Mqtt;
using MQTTnet.Server.Scripting; using MQTTnet.Server.Scripting;
using MQTTnet.Server.Scripting.DataSharing; using MQTTnet.Server.Scripting.DataSharing;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;


namespace MQTTnet.Server.Web namespace MQTTnet.Server.Web
@@ -111,7 +109,7 @@ namespace MQTTnet.Server.Web
services.AddSingleton<MqttClientDisconnectedHandler>(); services.AddSingleton<MqttClientDisconnectedHandler>();
services.AddSingleton<MqttClientSubscribedTopicHandler>(); services.AddSingleton<MqttClientSubscribedTopicHandler>();
services.AddSingleton<MqttClientUnsubscribedTopicHandler>(); services.AddSingleton<MqttClientUnsubscribedTopicHandler>();
services.AddSingleton<MqttConnectionValidator>();
services.AddSingleton<MqttServerConnectionValidator>();
services.AddSingleton<MqttSubscriptionInterceptor>(); services.AddSingleton<MqttSubscriptionInterceptor>();
services.AddSingleton<MqttApplicationMessageInterceptor>(); services.AddSingleton<MqttApplicationMessageInterceptor>();




+ 1
- 0
Source/MQTTnet.Server/appsettings.json View File

@@ -48,6 +48,7 @@
"EnableDebugLogging": false "EnableDebugLogging": false
}, },
"Scripting": { "Scripting": {
"ScriptsPath": "Scripts",
"IncludePaths": [ "IncludePaths": [
"Lib", "Lib",
"/usr/lib/python2.7", "/usr/lib/python2.7",


Loading…
Cancel
Save