From 1b7ad04c246e7ef8452d6f036f653ee634f11a99 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Mon, 15 Jun 2020 11:42:29 +0200 Subject: [PATCH] Init --- .gitignore | 3 + dns-sd-tester.sln | 25 +++++ dns-sd-tester/Program.cs | 141 +++++++++++++++++++++++++++++ dns-sd-tester/WebRequestor.cs | 62 +++++++++++++ dns-sd-tester/dns-sd-tester.csproj | 13 +++ 5 files changed, 244 insertions(+) create mode 100644 .gitignore create mode 100644 dns-sd-tester.sln create mode 100644 dns-sd-tester/Program.cs create mode 100644 dns-sd-tester/WebRequestor.cs create mode 100644 dns-sd-tester/dns-sd-tester.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a356172 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.vs +/dns-sd-tester/obj +/dns-sd-tester/bin diff --git a/dns-sd-tester.sln b/dns-sd-tester.sln new file mode 100644 index 0000000..a916170 --- /dev/null +++ b/dns-sd-tester.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29806.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dns-sd-tester", "dns-sd-tester\dns-sd-tester.csproj", "{0C9A06D3-AF6B-4DA2-8A50-9B98D30E4B42}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0C9A06D3-AF6B-4DA2-8A50-9B98D30E4B42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C9A06D3-AF6B-4DA2-8A50-9B98D30E4B42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C9A06D3-AF6B-4DA2-8A50-9B98D30E4B42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C9A06D3-AF6B-4DA2-8A50-9B98D30E4B42}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {652E9673-D449-4290-8C87-B5E9564FB4A7} + EndGlobalSection +EndGlobal diff --git a/dns-sd-tester/Program.cs b/dns-sd-tester/Program.cs new file mode 100644 index 0000000..36d3210 --- /dev/null +++ b/dns-sd-tester/Program.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text.Json; +using System.Threading.Tasks; + +using Makaretu.Dns; + +namespace dns_sd_tester { + class Program { + + private Dictionary DiscoverMulticastService(String address) { + Console.WriteLine($"Make Request for '{address}'"); + Message query = new Message(); + query.Questions.Add(new Question { Name = address, Type = DnsType.ANY }); + MulticastService mdns = new MulticastService(); + mdns.Start(); + Task answer = mdns.ResolveAsync(query); + List data = new List(); + data.AddRange(answer.Result.Answers); + data.AddRange(answer.Result.AdditionalRecords); + + Dictionary ret = new Dictionary(); + + Console.WriteLine("Get answer for the request"); + if(answer.Status == TaskStatus.RanToCompletion) { + foreach(ResourceRecord item in data) { + Console.WriteLine($"{item.Type}: " + item); + if(!ret.ContainsKey(item.Type)) { + ret.Add(item.Type, item); + } + } + Console.WriteLine(); + } + return ret; + } + + private String ParseDNSAnswer(Dictionary answer) { + Console.WriteLine("Parse the DNS Answer"); + if((answer.ContainsKey(DnsType.A) || answer.ContainsKey(DnsType.AAAA)) && answer.ContainsKey(DnsType.SRV) && answer.ContainsKey(DnsType.TXT)) { + TXTRecord txt_item = answer[DnsType.TXT] as TXTRecord; + Dictionary text_dic = new Dictionary(); + foreach(String item in txt_item.Strings) { + String[] item_split = item.Split("="); + text_dic.Add(item_split[0], item_split[1]); + } + if(text_dic.ContainsKey("td")) { + Console.WriteLine($"{txt_item.Type}: " + $"'{txt_item.Name}' {String.Join(" ", txt_item.Strings.ToArray())}"); + + Boolean using_a = false; + if(answer.ContainsKey(DnsType.A)) { + using_a = true; + } + + AddressRecord aa_item; + if(using_a) { + aa_item = answer[DnsType.A] as AddressRecord; + Console.WriteLine($"{aa_item.Type}: " + $"host '{aa_item.Name}' at '{aa_item.Address}'"); + } else { + aa_item = answer[DnsType.AAAA] as AddressRecord; + Console.WriteLine($"{aa_item.Type}: " + $"host '{aa_item.Name}' at '{aa_item.Address}'"); + } + + SRVRecord srv_item = answer[DnsType.SRV] as SRVRecord; + Console.WriteLine($"{srv_item.Type}: " + $"service '{srv_item.Name}' on '{srv_item.Target}' at '{srv_item.Port}'"); + + String ret = $"http://{aa_item.Address}:{srv_item.Port}{text_dic["td"]}"; + Console.WriteLine($"Combine Answer to {ret}\n"); + return ret; + } + } + return ""; + } + + private String GetTDJson(String guid = "") { + Dictionary jsonobject = new Dictionary() { + { "@context", "https://www.w3.org/2019/wot/td/v1" }, + { "title", "DNS-SD Test Entry" }, + { "securityDefinitions", new Dictionary() { { "nosec_sc", new Dictionary() { { "scheme", "nosec" } } } } }, + { "security", new List () { "nosec_sc" } }, + { "events", new Dictionary() { + { "sensordata", new Dictionary() { + { "data", new Dictionary () { + { "type", "object" } + } }, + { "forms", new List() { + new Dictionary () { + { "href", "mqtt://mqtt.example.org:1883/esp8266/sensor/" }, + { "contentType", "text/plain" }, + { "op", "subscribeevent" } + } + } } + } } + } } + }; + if(guid != "") { + jsonobject.Add("id", guid); + } + return JsonSerializer.Serialize(jsonobject); + } + + + public Program() { + String conn = this.ParseDNSAnswer(this.DiscoverMulticastService("_wot._tcp.local")); + String guid = $"urn:dev:ops:{Environment.MachineName}_dns-sd-tester"; + + /*Console.WriteLine("Read Registerd devices:"); + Console.WriteLine(WebRequestor.GetInstance(conn).Interact("").Result); + */ + + Console.WriteLine("Read registerd devices:"); + String jsonresult = WebRequestor.GetInstance(conn).Interact("").Result; + Console.WriteLine(jsonresult); + + Console.WriteLine("\nDelete every registerd devices:"); + Dictionary queryresult = (Dictionary)JsonSerializer.Deserialize(jsonresult, typeof(Dictionary)); + foreach(JsonElement item in queryresult["items"].EnumerateArray()) { + foreach(JsonProperty props in item.EnumerateObject()) { + if(props.Name.ToLower() == "id") { + Console.WriteLine($"Delete Device {props.Value.GetString()}: " + WebRequestor.GetInstance(conn).Interact($"/{props.Value.GetString()}", "", true, WebRequestor.RequestMethod.DELETE, false).Result); + } + } + } + + Console.WriteLine("\nCreates new Thing Description with system-generated ID"); + Console.WriteLine(WebRequestor.GetInstance(conn).Interact("/", this.GetTDJson(), true, WebRequestor.RequestMethod.POST).Result); + + Console.WriteLine($"Creates new Thing Description with {guid} ID"); + Console.WriteLine(WebRequestor.GetInstance(conn).Interact($"/{guid}", this.GetTDJson(guid), true, WebRequestor.RequestMethod.PUT).Result); + + Console.WriteLine("\nQuery all id's from Elements with Test in title."); + String jsonidlist = WebRequestor.GetInstance(conn).Interact("?jsonpath=$[?(@.title =~ /Test/i)].id").Result; + Console.WriteLine(jsonidlist); + + JsonElement idlist = (JsonElement)JsonSerializer.Deserialize(jsonidlist, typeof(JsonElement)); + + } + + public static void Main() => new Program(); + } +} diff --git a/dns-sd-tester/WebRequestor.cs b/dns-sd-tester/WebRequestor.cs new file mode 100644 index 0000000..9126368 --- /dev/null +++ b/dns-sd-tester/WebRequestor.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; + +namespace dns_sd_tester { + public class WebRequestor { + private readonly HttpClient client = new HttpClient(); + private static readonly Dictionary instances = new Dictionary(); + + private String Server { + get; + } + + public enum RequestMethod { + GET, + POST, + PUT, + DELETE + } + + public static WebRequestor GetInstance(String server) { + if(!instances.ContainsKey(server)) { + instances.Add(server, new WebRequestor(server)); + } + return instances[server]; + } + + private WebRequestor(String server) => this.Server = server; + + public async Task Interact(String address, String json = "", Boolean withoutput = true, RequestMethod method = RequestMethod.GET, Boolean exeptionOnNotSuccess = true) { + String ret = null; + try { + HttpResponseMessage response = null; + if(method == RequestMethod.POST || method == RequestMethod.PUT) { + HttpContent content = new StringContent(json); + content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); + if(method == RequestMethod.POST) { + response = await this.client.PostAsync(this.Server + address, content); + } else if(method == RequestMethod.PUT) { + response = await this.client.PutAsync(this.Server + address, content); + } + content.Dispose(); + } else if(method == RequestMethod.GET) { + response = await this.client.GetAsync(this.Server + address); + } else if(method == RequestMethod.DELETE) { + response = await this.client.DeleteAsync(this.Server + address); + } + if(!response.IsSuccessStatusCode && exeptionOnNotSuccess) { + throw new Exception(response.StatusCode + ": " + response.ReasonPhrase); + } + if(withoutput && response != null) { + ret = await response.Content.ReadAsStringAsync(); + } + } catch(Exception e) { + throw new WebException($"Error while accessing resource '{address}' on Server '{this.Server}' with method '{method}' and data '{json}'. Error: \n'{e.Message}'"); + } + return ret; + } + } +} diff --git a/dns-sd-tester/dns-sd-tester.csproj b/dns-sd-tester/dns-sd-tester.csproj new file mode 100644 index 0000000..d26bafc --- /dev/null +++ b/dns-sd-tester/dns-sd-tester.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp3.1 + dns_sd_tester + + + + + + +