diff --git a/Documentation/UPnP-XSD/device.xsd b/Documentation/UPnP-XSD/device.xsd
new file mode 100644
index 0000000..e3b8b85
--- /dev/null
+++ b/Documentation/UPnP-XSD/device.xsd
@@ -0,0 +1,94 @@
+
+
+
+
+
+ XML Schema for UPnP device descriptions in real XSD format
+ (not like the XDR one from Microsoft)
+ Created by Michael Weinrich 2007
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/skyscraper8/Program.cs b/skyscraper8/Program.cs
index cccc75f..9e6acfa 100644
--- a/skyscraper8/Program.cs
+++ b/skyscraper8/Program.cs
@@ -39,7 +39,13 @@ namespace skyscraper5
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private static void IntegrationTest()
{
- //List ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
+ List ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
+ foreach (SsdpDevice ssdpDevice in ssdpDevices)
+ {
+ Console.WriteLine("SSDP device: {0}", ssdpDevice.Server);
+ }
+
+ Console.WriteLine("yeet!");
/*RtspClient rtspClient = new RtspClient("172.20.20.121", 554);
rtspClient.AutoReconnect = true;
RtspOptionsResponse options = rtspClient.GetOptions("/");
diff --git a/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpClient.cs b/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpClient.cs
index 9d75bb6..8933343 100644
--- a/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpClient.cs
+++ b/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpClient.cs
@@ -44,6 +44,7 @@ namespace skyscraper8.SimpleServiceDiscoveryProtocol
DateTime timeStarted = DateTime.Now;
while (true)
{
+ bool yielded = false;
for (int i = 0; i < udpSockets.Length; i++)
{
if (udpSockets[i] == null)
@@ -57,12 +58,16 @@ namespace skyscraper8.SimpleServiceDiscoveryProtocol
if (recvBytes > 0)
{
string s = Encoding.UTF8.GetString(buffer, 0, recvBytes);
- Console.WriteLine(s);
+ //Console.WriteLine(s);
yield return new SsdpDevice(s);
+ yielded = true;
}
}
}
+ if (yielded)
+ continue;
+
Thread.Sleep(1);
if ((DateTime.Now - timeStarted).TotalMilliseconds >= timeout)
break;
diff --git a/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpDevice.cs b/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpDevice.cs
index 6adaaa7..4358fff 100644
--- a/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpDevice.cs
+++ b/skyscraper8/SimpleServiceDiscoveryProtocol/SsdpDevice.cs
@@ -1,17 +1,125 @@
-using System;
+using log4net;
+using skyscraper5.Skyscraper;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.SimpleServiceDiscoveryProtocol
{
- internal class SsdpDevice
+ internal class SsdpDevice : Validatable
{
+ private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
+
public SsdpDevice(string notification)
{
StringReader sr = new StringReader(notification);
- throw new NotImplementedException(notification);
+ string httpHeaderLine = sr.ReadLine();
+ int indexOf = httpHeaderLine.IndexOf(' ');
+ string protocol = httpHeaderLine.Substring(0, indexOf);
+ httpHeaderLine = httpHeaderLine.Substring(indexOf + 1);
+ if (!protocol.StartsWith("HTTP"))
+ {
+ Valid = false;
+ return;
+ }
+
+ HttpStatusCode = int.Parse(httpHeaderLine.Substring(0, 3));
+ httpHeaderLine = httpHeaderLine.Substring(4);
+
+ string line = httpHeaderLine;
+ while (!string.IsNullOrEmpty(line = sr.ReadLine()))
+ {
+ int seperator = line.IndexOf(": ");
+ if (seperator == -1)
+ continue;
+ string key = line.Substring(0, seperator);
+ string value = line.Substring(seperator + 2);
+ key = key.ToLowerInvariant();
+ switch (key)
+ {
+ case "cache-control":
+ this.CacheControl = value;
+ break;
+ case "st":
+ this.SearchTarget = value;
+ break;
+ case "usn":
+ this.UniqueServiceName = value;
+ break;
+ case "server":
+ Server = value;
+ break;
+ case "location":
+ Location = value;
+ break;
+ case "opt":
+ Options = value;
+ break;
+ case "01-nls":
+ //Same as BOOT ID
+ break;
+ case "bootid.upnp.org":
+ BootId = value;
+ break;
+ case "configid.upnp.org":
+ ConfigId = value;
+ break;
+ case "deviceid.ses.com":
+ SatIpDeviceId = value;
+ break;
+ case "date":
+ Date = value;
+ break;
+ case "x-user-agent":
+ UserAgent = value;
+ break;
+ case "content-length":
+ //Irrelevant. Always 0, because these thingies dont contain any http payload.
+ break;
+ default:
+ logger.WarnFormat("Don't know how to format: {0}", line);
+ break;
+ }
+ }
+
+ Valid = true;
}
+
+ public string UserAgent { get; set; }
+
+ public string Date { get; set; }
+
+ public string SatIpDeviceId { get; set; }
+
+ public string ConfigId { get; set; }
+
+ public string BootId { get; set; }
+
+
+ public string Options { get; set; }
+
+ ///
+ /// This is an URL to an XML file
+ ///
+ public string Location { get; set; }
+
+ ///
+ /// This just says what software is running on the device, not what it actually is.
+ ///
+ public string Server { get; set; }
+
+ ///
+ /// This can only be used to identify one specific device, not a device type.
+ ///
+ public string UniqueServiceName { get; set; }
+
+ public string SearchTarget { get; set; }
+
+ public string CacheControl { get; private set; }
+
+ public int HttpStatusCode { get; private set; }
}
}