Skip to content

Commit

Permalink
Sennheiser message parsing and writing + Bug Fixes:
Browse files Browse the repository at this point in the history
 - Fixed mDNS socket binding issue
 - Fixed mDNS runnings out of query IDs
 - Implemented Sennheiser SSC json parsing for RX and TX
 - Implemented Sennheiser SSC RF scanning
 - Improved application termination
 - Added clamping to certain value setters
 - ASP NET command line options can now be passed in without being eaten
 - Fixed LockMode enum JSON encoding
 - Fixed WebSocket API serialization naming rules
 - Other small improvements
  • Loading branch information
space928 committed Jul 4, 2024
1 parent 267e8ca commit 9bbc219
Show file tree
Hide file tree
Showing 14 changed files with 1,231 additions and 104 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,4 @@ FodyWeavers.xsd

# Default save directory
WirelessMicSuiteServer/save/
/WirelessMicSuiteServer/wwwroot
12 changes: 9 additions & 3 deletions WirelessMicSuiteServer.Test/TestMDNSClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,25 @@ internal static void Test()
Task.Run(() =>
{
MDNSClient client = new();
client.OnMDNSMessage += (msg) =>
{
Log($"Received mDNS response: \n{string.Join('\n', msg.answers.Select(a => $"\t{a.name} [{a.type}] \n{a.record}"))}");
};

client.SendQuery(new DNSRecordMessage("_ssc._udp.local"));
//client.SendQuery(new DNSRecordMessage("_ssc._udp.local"));
//client.SendQuery(new MDNSQuery("_ssc-https._tcp.local"), 0x3920);

while (true)
{
Thread.Sleep(100);
client.SendQuery(new DNSRecordMessage("_ssc._udp.local"));

Thread.Sleep(1000);
}
});
}

private static void Log(object message, LogSeverity severity = LogSeverity.Info, [CallerMemberName] string? caller = null)
{
Program.Log(message, severity, caller, nameof(ShureUHFREmulator));
Program.Log(message, severity, caller, nameof(TestMDNSClient));
}
}
5 changes: 3 additions & 2 deletions WirelessMicSuiteServer/CommandLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ public void ParseArgs(string[] args)

if (option == null)
{
Log($"Unrecognised command line argument '{arg}'!", LogSeverity.Error);
/*Log($"Unrecognised command line argument '{arg}'!", LogSeverity.Error);
Console.WriteLine();
PrintHelp();
parsedArgs.TryAdd("--help", null);
return;
return;*/
continue;
}

try
Expand Down
17 changes: 11 additions & 6 deletions WirelessMicSuiteServer/IWirelessMicReceiver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,15 @@ public enum DiversityIndicator
/// Represents what type of UI lock is enabled on a wireless transmitter.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter<LockMode>))]
[Flags]
//[Flags]
public enum LockMode
{
None,
Mute = 1 << 0,
Power = 1 << 1,
Frequency = 1 << 2,
FrequencyPower = Power | Frequency,
All = Mute | Power | Frequency
//Mute = 1,
Power = 2,
Frequency = 3,
FrequencyPower = 4,
All = 5
}

/// <summary>
Expand All @@ -223,6 +223,10 @@ public struct MeteringData(float rssiA, float rssiB, float audioLevel, Diversity
public readonly float RssiB => rssiB;
public readonly float AudioLevel => audioLevel;
public readonly DiversityIndicator Diversity => diversity;

public MeteringData(MeteringData other) :
this(other.rssiA, other.rssiB, other.audioLevel, other.diversity)
{ }
}

/// <summary>
Expand Down Expand Up @@ -515,6 +519,7 @@ public MACAddress(string str) : this(str.AsSpan()) { }
/// <exception cref="ArgumentException"></exception>
public MACAddress(ReadOnlySpan<char> str)
{
// TODO: Handle MAC addresses which don't have 2 chars per byte (including 1 and 0 chars per byte) ie: ff:a::22:1:1
if (str.Length < 6 * 2 + 5)
throw new ArgumentException($"Input string '{str}' is too short to parse as a MAC address!");

Expand Down
8 changes: 5 additions & 3 deletions WirelessMicSuiteServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ public static void Main(string[] args)
Log($"Version: {assembly.GetName().Version}; {copyright}");

int meterInterval = 50;
if (cli.ParsedArgs.TryGetValue("--meter-interval", out object? arg))
meterInterval = (int)(uint)arg!;
Log($"List options: \n{string.Join('\n', cli.ParsedArgs.Select(x => $"\t{x.Key} = {x.Value}"))}");
if (cli.ParsedArgs.TryGetValue("--meter-interval", out object? meterIntervalArg))
meterInterval = (int)(uint)meterIntervalArg!;
Log($"List options: ");
foreach (var a in cli.ParsedArgs)
Log($"\t{a.Key} = {a.Value}");

WirelessMicManager micManager = new([
new ShureUHFRManager() { PollingPeriodMS = meterInterval },
Expand Down
45 changes: 27 additions & 18 deletions WirelessMicSuiteServer/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:21763",
"sslPort": 44315
}
},
{
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://*:5106",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"dotnetRunMessages": true,
"applicationUrl": "http://*:5106"
},
"https": {
//"commandLineArgs": "-m",
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7221;http://localhost:5106",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7221;http://localhost:5106"
},
"IIS Express": {
"commandName": "IISExpress",
Expand All @@ -37,6 +27,25 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WSL": {
"commandName": "WSL2",
"launchBrowser": true,
"launchUrl": "https://localhost:7221/swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS": "https://localhost:7221;http://localhost:5106"
},
"distributionName": ""
}
},
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:21763",
"sslPort": 44315
}
}
}
}
89 changes: 81 additions & 8 deletions WirelessMicSuiteServer/SennheiserSSC/MDNSClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Concurrent;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
Expand All @@ -24,7 +25,7 @@ public class MDNSClient : IDisposable
private readonly CancellationToken cancellationToken;
private readonly CancellationTokenSource cancellationTokenSource;
private readonly ConcurrentQueue<ByteMessage> txPipe;
private readonly ConcurrentDictionary<ushort, ushort> activeQueries;
private readonly ConcurrentDictionary<ushort, DateTime> activeQueries;
private readonly SemaphoreSlim txAvailableSem;

public event Action<MDNSMessage>? OnMDNSMessage;
Expand All @@ -45,10 +46,22 @@ public MDNSClient()
Log($"Starting MDNS discovery server...");

socket = new(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
//socket.Bind(new IPEndPoint(IPAddress.Any, UdpPort));
//socket.Connect(new IPEndPoint(broadcastAddress, UdpPort));
socket.Bind(new IPEndPoint(IPAddress.Any, 0));
//socket.ReceiveTimeout = 1000;
Log("List network interfaces: ");
List<IPAddress> addresses = [];
IPAddress? addr = null;
foreach (var nic in NetworkInterface.GetAllNetworkInterfaces())
{
var nicAddr = nic.GetIPProperties().UnicastAddresses.Select(x => x.Address);
addresses.AddRange(nicAddr);
if (nicAddr.FirstOrDefault(x => x.AddressFamily == AddressFamily.InterNetwork) is IPAddress naddr)
addr ??= naddr;
Log($"\t{nic.Name}: {string.Join(", ", nicAddr)}");
}
//socket.Bind(new IPEndPoint(IPAddress.Any, 0));
socket.Bind(new IPEndPoint(addr ?? IPAddress.Any, 0));
//socket.SendTo([0, 0, 0, 0], new IPEndPoint(broadcastAddress, UdpPort));
Log($"mDNS client bound to {socket.LocalEndPoint}.");
rxTask = Task.Run(RXTask);
txTask = Task.Run(TXTask);
}
Expand All @@ -62,7 +75,7 @@ public void Log(string? message, LogSeverity severity = LogSeverity.Info)
public void Dispose()
{
cancellationTokenSource.Cancel();
Task.WaitAll([rxTask, txTask], 1000);
//Task.WaitAll([rxTask, txTask], 1000);
rxTask.Dispose();
txTask.Dispose();
socket.Dispose();
Expand Down Expand Up @@ -139,7 +152,7 @@ private void TXTask()
while (!cancellationToken.IsCancellationRequested)
{
ByteMessage msg;
while (!txPipe.TryDequeue(out msg))
while (!txPipe.TryDequeue(out msg) && !cancellationToken.IsCancellationRequested)
txAvailableSem.Wait(1000);
try
{
Expand All @@ -156,8 +169,18 @@ private void TXTask()
public void SendQuery(DNSRecordMessage query, ushort? transactionID = null)
{
transactionID ??= (ushort)(Random.Shared.Next() & ushort.MaxValue);
if (!activeQueries.TryAdd(transactionID.Value, transactionID.Value))
if (!activeQueries.TryAdd(transactionID.Value, DateTime.UtcNow))
{
throw new ArgumentException($"Transaction ID {transactionID.Value} is still active and can't be reused.", nameof(transactionID));
}
if (activeQueries.Count > 32)
{
var now = DateTime.UtcNow;
var timeout = TimeSpan.FromSeconds(10);
foreach (var kvp in activeQueries)
if (now - kvp.Value > timeout)
activeQueries.TryRemove(kvp.Key, out _);
}

var header = new MDNSMessageHeader(transactionID.Value, MDNSFlags.None, 1, 0, 0, 0);
int len = MDNSMessageHeader.HEADER_LENGTH + query.length;
Expand Down Expand Up @@ -518,6 +541,11 @@ public DNS_CNAME(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
name = DNSRecordMessage.ParseDomainName(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_CNAME {{\n\t{name}\n}}";
}
}

public readonly struct DNS_HINFO : IDNSRData
Expand All @@ -535,6 +563,11 @@ public DNS_HINFO(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
os = DNSRecordMessage.ParseCharacterString(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_HINFO {{\n\tcpu={cpu}\n\tos={os}\n}}";
}
}

public readonly struct DNS_MB : IDNSRData
Expand Down Expand Up @@ -644,6 +677,11 @@ public DNS_MX(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
exchange = DNSRecordMessage.ParseDomainName(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_MX {{\n\tpreference={preference}\n\texchange={exchange}\n}}";
}
}

public readonly struct DNS_NULL : IDNSRData
Expand All @@ -659,6 +697,11 @@ public DNS_NULL(ReadOnlySpan<byte> data, int offset, int end, Decoder? utf8Decod
data[offset..end].CopyTo(this.data);
Length = this.data.Length;
}

public override string ToString()
{
return $"DNS_NULL {{\n\t{Convert.ToHexString(data)}\n}}";
}
}

public readonly struct DNS_NS : IDNSRData
Expand All @@ -674,6 +717,11 @@ public DNS_NS(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
nsDName = DNSRecordMessage.ParseDomainName(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_NS {{\n\tnsDName={nsDName}\n}}";
}
}

public readonly struct DNS_PTR : IDNSRData
Expand All @@ -689,6 +737,11 @@ public DNS_PTR(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
ptrDName = DNSRecordMessage.ParseDomainName(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_PTR {{\n\tptrDName={ptrDName}\n}}";
}
}

public readonly struct DNS_SOA : IDNSRData
Expand Down Expand Up @@ -736,6 +789,11 @@ public DNS_TXT(ReadOnlySpan<byte> data, int offset, int end, Decoder? utf8Decode
txtData = [.. strings];
Length = end - offset;
}

public override string ToString()
{
return $"DNS_TXT {{\n\t{string.Join("\n\t", txtData)}\n}}";
}
}

public readonly struct DNS_A : IDNSRData
Expand All @@ -751,6 +809,11 @@ public DNS_A(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
address = new IPAddress(data[dataPtr..(dataPtr+4)]);dataPtr += 4;
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_A {{\n\t{address}\n}}";
}
}

public readonly struct DNS_AAAA : IDNSRData
Expand All @@ -766,6 +829,11 @@ public DNS_AAAA(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
address = new IPAddress(data[dataPtr..(dataPtr+16)]); dataPtr += 16;
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_AAAA {{\n\t{address}\n}}";
}
}

public readonly struct DNS_WKS : IDNSRData
Expand Down Expand Up @@ -808,6 +876,11 @@ public DNS_SRV(ReadOnlySpan<byte> data, int offset, Decoder? utf8Decoder)
target = DNSRecordMessage.ParseDomainName(data, utf8Decoder, ref dataPtr);
Length = dataPtr;
}

public override string ToString()
{
return $"DNS_SRV {{\n\tpriority={priority}\n\tweight={weight}\n\tport={port}\n\ttarget={target}\n}}";
}
}
#endregion

Expand Down
Loading

0 comments on commit 9bbc219

Please sign in to comment.