Files
MyMcKesson/TomcatServer/TCMPortMapper/MiniUPnP.cs
2016-07-27 00:32:34 -04:00

322 lines
12 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Collections.Generic;
namespace TCMPortMapper
{
class MiniUPnP
{
public const int UPNPCOMMAND_SUCCESS = 0;
public const int UPNPCOMMAND_UNKNOWN_ERROR = -1;
public const int UPNPCOMMAND_INVALID_ARGS = -2;
public const int MINIUPNPC_URL_MAXSIZE = 128;
[StructLayout(LayoutKind.Sequential)]
public unsafe struct UPNPDev
{
public IntPtr pNext;
public String descURL;
public String st;
public fixed byte buffer[2];
public UPNPDev Next
{
get { return (UPNPDev)Marshal.PtrToStructure(pNext, typeof(UPNPDev)); }
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct UPNPUrls
{
public String controlURL;
public String ipcondescURL;
public String controlURL_CIF;
}
/// <summary>
/// This structure is used to avoid a SystemAccessViolation,
/// and to prevent corruption of the process' memory.
/// See issue #2 for further discussion.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public unsafe struct UPNPUrls_2
{
public char *controlURL;
public char *ipcondescURL;
public char *controlURL_CIF;
}
[StructLayout(LayoutKind.Sequential, Size = 1796, CharSet = CharSet.Ansi)]
public struct IGDdatas
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String cureltname;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
public String urlbase;
private Int32 level;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
public String controlurl_CIF;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String eventsuburl_CIF;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String scpdurl_CIF;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String servicetype_CIF;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
public String controlurl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String eventsuburl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
public String scpdurl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String serviceType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String controlurl_tmp;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String eventsuburl_tmp;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String scpdurl_tmp;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MINIUPNPC_URL_MAXSIZE)]
private String servicetype_tmp;
public String ServiceType
{
get { return serviceType; }
set { serviceType = value; }
}
}
/// <summary>
/// Discover UPnP devices on the network.
/// The discovered devices are returned as a chained list.
/// It is up to the caller to free the list with freeUPNPDevlist().
/// If available, device list will be obtained from MiniSSDPd.
/// </summary>
/// <param name="delay">
/// Delay (in milliseconds) is the maximum time for waiting any device response.
/// </param>
/// <param name="multicastif">
/// If NULL, default multicast interface for sending SSDP discover packets will be used.
/// </param>
/// <param name="minissdpdsock">
/// If null, default path for minissdpd socket will be used.
/// </param>
/// <returns>
/// A pointer to a UPNPDev structure. Free this when done.
/// Use the PtrToUPNPDev method to convert to a UPNPDev structure.
/// </returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr upnpDiscover([In] int delay,
[In] String multicastif,
[In] String minissdpdsock);
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr upnpDiscover([In] int delay,
[In] IntPtr multicastif,
[In] String minissdpdsock);
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr upnpDiscover([In] int delay,
[In] String multicastif,
[In] IntPtr minissdpdsock);
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr upnpDiscover([In] int delay,
[In] IntPtr multicastif,
[In] IntPtr minissdpdsock);
/// <summary>
/// frees list returned by upnpDiscover()
/// </summary>
/// <param name="devlistP">
/// IntPtr (pointer to UPNPDev structure) as returned by upnpDiscover().
/// </param>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void freeUPNPDevlist([In] IntPtr devlistP);
/// <summary>
/// Used when skipping the discovery process.
/// Return value:
/// 0 - Not OK
/// 1 - OK
/// </summary>
/// <param name="rootDescUrl"></param>
/// <param name="urls"></param>
/// <param name="data"></param>
/// <param name="lanAddr"></param>
/// <param name="lanAddrLength"></param>
/// <returns></returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern int UPNP_GetIGDFromUrl([In] String rootDescUrl,
[In] UPNPUrls_2 *urls,
[In, Out] ref IGDdatas datas,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] lanAddr,
[In] int lanAddrLength);
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern void FreeUPNPUrls([In] UPNPUrls_2 *urls);
/// <summary>
/// Extracts the external IP address.
/// </summary>
/// <param name="controlURL"></param>
/// <param name="serviceType"></param>
/// <param name="externalIPAddr">
/// The array to copy the external IP address bytes into.
/// The array must be 16 bytes in length.
/// </param>
/// <returns>
/// 0: SUCCESS
/// NON ZERO: ERROR Either a UPnP error code or an unknown error.
///
/// Possible UPnP Errors:
/// 402 Invalid Args - See UPnP Device Architecture section on Control.
/// 501 Action Failed - See UPnP Device Architecture section on Control.
/// </returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int UPNP_GetExternalIPAddress([In] String controlURL,
[In] String serviceType,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] externalIPAddr);
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int UPNP_GetExternalIPAddress([In] String controlURL,
[In, MarshalAs(UnmanagedType.LPArray, SizeConst = MINIUPNPC_URL_MAXSIZE)] byte[] serviceType,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] externalIPAddr);
/// <summary>
/// Description forthcoming...
/// </summary>
/// <param name="controlURL"></param>
/// <param name="serviceType"></param>
/// <param name="index"></param>
/// <param name="extPort"></param>
/// <param name="intClient"></param>
/// <param name="intPort"></param>
/// <param name="protocol"></param>
/// <param name="desc"></param>
/// <param name="enabled"></param>
/// <param name="rHost"></param>
/// <param name="duration"></param>
/// <returns>
/// UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR or a UPnP Error Code.
///
/// Possible UPNP Error codes:
/// 402 Invalid Args - See UPnP Device Architecture section on Control
/// 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds
/// </returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int UPNP_GetGenericPortMappingEntry([In] String controlURL,
[In] String serviceType,
[In] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] index,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] extPort,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] intClient,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] intPort,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 4)] byte[] protocol,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 80)] byte[] desc,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] enabled,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 64)] byte[] rHost,
[MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] duration);
/// <summary>
/// Adds a UPnP port mapping using the given information.
/// </summary>
/// <param name="controlURL"></param>
/// <param name="serviceType"></param>
/// <param name="externalPort"></param>
/// <param name="internalPort"></param>
/// <param name="internalClient"></param>
/// <param name="description"></param>
/// <param name="protocol"></param>
/// <returns>
/// Returns values:
/// Zero: SUCCESS
/// Non-Zero: ERROR. Either a UPnP error code or an unknown error.
///
/// List of possible UPnP errors:
/// 402 - Invalid Args
/// 501 - Action Failed
/// 715 - WildCardNotPermittedInSrcIP
/// 716 - WildCardNotPermittedInExtPort
/// 718 - ConflictInMappingEntry
/// The port mapping entry specified conflicts with a mapping assigned previously to another client
/// 724 - SamePortValueRequired
/// Internal and External port values must be the same
/// 725 - OnlyPermanentLeasesSupported
/// The NAT implementation only supports permanent lease times on port mappings
/// 726 - RemoteHostOnlySupportsWildcard
/// RemoteHost must be a wildcard and cannot be a specific IP address or DNS name
/// 727 - ExternalPortOnlySupportsWildcard
/// ExternalPort must be a wildcard and cannot be a specific port value
/// </returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int UPNP_AddPortMapping([In] String controlURL,
[In] String serviceType,
[In] String externalPort,
[In] String internalPort,
[In] String internalClient,
[In] String description,
[In] String protocol);
/// <summary>
/// Deletes a UPnP port mapping with the given information.
/// </summary>
/// <param name="controlURL"></param>
/// <param name="serviceType"></param>
/// <param name="externalPort"></param>
/// <param name="protocol"></param>
/// <returns>
/// Return values:
/// Zero: SUCCESS
/// Non-Zero: ERROR. Either a UPnP error code or an undefined error.
///
/// List of possible UPnP errors:
/// 402 - Invalid Args
/// 714 - NoSuchEntryInArray (Port Mapping doesn't exist)
/// </returns>
[DllImport("miniupnp.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int UPNP_DeletePortMapping([In] String controlURL,
[In] String serviceType,
[In] String externalPort,
[In] String protocol);
#region Utility Methods
public static UPNPDev PtrToUPNPDev(IntPtr devlistP)
{
return (UPNPDev)Marshal.PtrToStructure(devlistP, typeof(UPNPDev));
}
public static String NullTerminatedArrayToString(byte[] nullTerminatedStr)
{
for (int i = 0; i < nullTerminatedStr.Length; i++)
{
if (nullTerminatedStr[i] == 0)
{
return System.Text.Encoding.ASCII.GetString(nullTerminatedStr, 0, i);
}
}
return System.Text.Encoding.ASCII.GetString(nullTerminatedStr, 0, nullTerminatedStr.Length);
}
#endregion
}
}