Built a small SSDP Client.
This commit is contained in:
parent
a79c8a5f20
commit
887d983594
94
Documentation/UPnP-XSD/device.xsd
Normal file
94
Documentation/UPnP-XSD/device.xsd
Normal file
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema
|
||||
targetNamespace="urn:schemas-upnp-org:device-1-0"
|
||||
xmlns:tns="urn:schemas-upnp-org:device-1-0"
|
||||
xmlns="urn:schemas-upnp-org:device-1-0"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:dlna="urn:schemas-dlna-org:device-1-0"
|
||||
attributeFormDefault="qualified" elementFormDefault="qualified">
|
||||
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
XML Schema for UPnP device descriptions in real XSD format
|
||||
(not like the XDR one from Microsoft)
|
||||
Created by Michael Weinrich 2007
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:element name="root">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="specVersion" type="SpecVersionType" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="URLBase" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="device" type="DeviceType" minOccurs="1" maxOccurs="1" />
|
||||
</xs:all>
|
||||
<xs:anyAttribute/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<xs:complexType name="SpecVersionType">
|
||||
<xs:all>
|
||||
<xs:element name="major" type="xs:int" minOccurs="1" />
|
||||
<xs:element name="minor" type="xs:int" minOccurs="1"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="DeviceType">
|
||||
<xs:all>
|
||||
<xs:element name="deviceType" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="friendlyName" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="manufacturer" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="manufacturerURL" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="modelDescription" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="modelName" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="modelNumber" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="modelURL" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="serialNumber" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="UDN" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="UPC" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="iconList" type="IconListType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="serviceList" type="ServiceListType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="deviceList" type="DeviceListType" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="presentationURL" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="IconListType">
|
||||
<xs:sequence>
|
||||
<xs:element name="icon" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="mimetype" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="width" type="xs:int" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="height" type="xs:int" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="depth" type="xs:int" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="url" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="ServiceListType">
|
||||
<xs:sequence>
|
||||
<xs:element name="service" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="serviceType" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="serviceId" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="SCPDURL" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="controlURL" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
<xs:element name="eventSubURL" type="xs:string" minOccurs="1" maxOccurs="1" />
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="DeviceListType">
|
||||
<xs:sequence>
|
||||
<xs:element name="device" type="DeviceType" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
@ -39,7 +39,13 @@ namespace skyscraper5
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static void IntegrationTest()
|
||||
{
|
||||
//List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
|
||||
List<SsdpDevice> 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("/");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// This is an URL to an XML file
|
||||
/// </summary>
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This just says what software is running on the device, not what it actually is.
|
||||
/// </summary>
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This can only be used to identify one specific device, not a device type.
|
||||
/// </summary>
|
||||
public string UniqueServiceName { get; set; }
|
||||
|
||||
public string SearchTarget { get; set; }
|
||||
|
||||
public string CacheControl { get; private set; }
|
||||
|
||||
public int HttpStatusCode { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user