Cleanup uPnP a bit

This commit is contained in:
UnknownShadow200 2017-06-20 09:52:29 +10:00
parent ccd9c33d98
commit 40fde5c892

View File

@ -27,17 +27,18 @@ namespace MCGalaxy.Core {
public sealed class UPnP {
public static bool CanUseUpnp { get { return Discover(); } }
public static TimeSpan Timeout = TimeSpan.FromSeconds(3);
private const string req = "M-SEARCH * HTTP/1.1\r\n" +
const string req =
"M-SEARCH * HTTP/1.1\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"ST:upnp:rootdevice\r\n" +
"MAN:\"ssdp:discover\"\r\n" +
"MX:3\r\n\r\n";
static TimeSpan _timeout = new TimeSpan(0, 0, 0, 3);
public static TimeSpan TimeOut { get { return _timeout; } set { _timeout = value; } }
"MX:3\r\n" +
"\r\n";
static string _serviceUrl;
private static bool Discover() {
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
@ -75,7 +76,7 @@ namespace MCGalaxy.Core {
}
}
} while (length > 0);
} while (start.Subtract(DateTime.UtcNow) < _timeout);
} while (start.Subtract(DateTime.UtcNow) < Timeout);
return false;
}
catch {
@ -83,7 +84,7 @@ namespace MCGalaxy.Core {
}
}
private static string GetServiceUrl(string resp) {
static string GetServiceUrl(string resp) {
#if !DEBUG
try {
#endif
@ -98,60 +99,51 @@ namespace MCGalaxy.Core {
XmlNode node = desc.SelectSingleNode("//tns:service[tns:serviceType=\"urn:schemas-upnp-org:service:WANIPConnection:1\"]/tns:controlURL/text()", nsMgr);
if ( node == null )
return null;
XmlNode eventnode = desc.SelectSingleNode("//tns:service[tns:serviceType=\"urn:schemas-upnp-org:service:WANIPConnection:1\"]/tns:eventSubURL/text()", nsMgr);
return CombineUrls(resp, node.Value);
#if !DEBUG
}
catch { return null; }
} catch { return null; }
#endif
}
private static string CombineUrls(string resp, string p) {
static string CombineUrls(string resp, string p) {
int n = resp.IndexOf("://");
n = resp.IndexOf('/', n + 3);
return resp.Substring(0, n) + p;
}
public static void ForwardPort(int port, ProtocolType protocol, string description) {
if ( string.IsNullOrEmpty(_serviceUrl) )
if (String.IsNullOrEmpty(_serviceUrl) )
throw new InvalidOperationException("No UPnP service available or Discover() has not been called");
XmlDocument xdoc = SOAPRequest(_serviceUrl, "<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"<NewRemoteHost></NewRemoteHost><NewExternalPort>" + port.ToString() + "</NewExternalPort><NewProtocol>" + protocol.ToString().ToUpper() + "</NewProtocol>" +
"<NewInternalPort>" + port.ToString() + "</NewInternalPort><NewInternalClient>" + GetLocalIP() +
"</NewInternalClient><NewEnabled>1</NewEnabled><NewPortMappingDescription>" + description +
"</NewPortMappingDescription><NewLeaseDuration>0</NewLeaseDuration></u:AddPortMapping>", "AddPortMapping");
XmlDocument xdoc = SOAPRequest(_serviceUrl,
"<u:AddPortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"<NewRemoteHost></NewRemoteHost>" +
"<NewExternalPort>" + port.ToString() + "</NewExternalPort>" +
"<NewProtocol>" + protocol.ToString().ToUpper() + "</NewProtocol>" +
"<NewInternalPort>" + port.ToString() + "</NewInternalPort>" +
"<NewInternalClient>" + GetLocalIP() + "</NewInternalClient>" +
"<NewEnabled>1</NewEnabled>" +
"<NewPortMappingDescription>" + description + "</NewPortMappingDescription>" +
"<NewLeaseDuration>0</NewLeaseDuration>" +
"</u:AddPortMapping>", "AddPortMapping");
}
public static void DeleteForwardingRule(int port, ProtocolType protocol) {
if ( string.IsNullOrEmpty(_serviceUrl) )
if (String.IsNullOrEmpty(_serviceUrl) )
throw new InvalidOperationException("No UPnP service available or Discover() has not been called");
XmlDocument xdoc = SOAPRequest(_serviceUrl,
"<u:DeletePortMapping xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"<NewRemoteHost>" +
"</NewRemoteHost>" +
"<NewRemoteHost>"</NewRemoteHost>" +
"<NewExternalPort>" + port + "</NewExternalPort>" +
"<NewProtocol>" + protocol.ToString().ToUpper() + "</NewProtocol>" +
"</u:DeletePortMapping>", "DeletePortMapping");
}
[DebuggerStepThrough]
public static IPAddress GetExternalIP() {
if ( string.IsNullOrEmpty(_serviceUrl) )
throw new InvalidOperationException("No UPnP service available or Discover() has not been called");
XmlDocument xdoc = SOAPRequest(_serviceUrl, "<u:GetExternalIPAddress xmlns:u=\"urn:schemas-upnp-org:service:WANIPConnection:1\">" +
"</u:GetExternalIPAddress>", "GetExternalIPAddress");
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
nsMgr.AddNamespace("tns", "urn:schemas-upnp-org:device-1-0");
string IP = xdoc.SelectSingleNode("//NewExternalIPAddress/text()", nsMgr).Value;
return IPAddress.Parse(IP);
}
[DebuggerStepThrough]
public static string GetLocalIP() {
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList) {
if (ip.AddressFamily == AddressFamily.InterNetwork) {
localIP = ip.ToString();
@ -160,21 +152,22 @@ namespace MCGalaxy.Core {
return localIP;
}
private static XmlDocument SOAPRequest(string url, string soap, string function) {
static XmlDocument SOAPRequest(string url, string soap, string function) {
string req = "<?xml version=\"1.0\"?>" +
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" +
"<s:Body>" +
soap +
"</s:Body>" +
"<s:Body>" + soap + "</s:Body>" +
"</s:Envelope>";
WebRequest r = HttpWebRequest.Create(url);
r.Method = "POST";
byte[] b = Encoding.UTF8.GetBytes(req);
r.Headers.Add("SOAPACTION", "\"urn:schemas-upnp-org:service:WANIPConnection:1#" + function + "\"");
r.ContentType = "text/xml; charset=\"utf-8\"";
byte[] b = Encoding.UTF8.GetBytes(req);
r.ContentLength = b.Length;
r.GetRequestStream().Write(b, 0, b.Length);
XmlDocument resp = new XmlDocument();
WebResponse wres = r.GetResponse();
Stream ress = wres.GetResponseStream();