mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-30 13:56:31 +01:00
merge common implementations and server implementations
This commit is contained in:
591
Emby.Server.Implementations/IO/SharpCifs/UniAddress.cs
Normal file
591
Emby.Server.Implementations/IO/SharpCifs/UniAddress.cs
Normal file
@@ -0,0 +1,591 @@
|
||||
// This code is derived from jcifs smb client library <jcifs at samba dot org>
|
||||
// Ported by J. Arturo <webmaster at komodosoft dot net>
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using SharpCifs.Netbios;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
using Extensions = SharpCifs.Util.Sharpen.Extensions;
|
||||
|
||||
namespace SharpCifs
|
||||
{
|
||||
/// <summary>
|
||||
/// <p>Under normal conditions it is not necessary to use
|
||||
/// this class to use jCIFS properly.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>Under normal conditions it is not necessary to use
|
||||
/// this class to use jCIFS properly. Name resolusion is
|
||||
/// handled internally to the <code>jcifs.smb</code> package.
|
||||
/// <p>
|
||||
/// This class is a wrapper for both
|
||||
/// <see cref="Jcifs.Netbios.NbtAddress">Jcifs.Netbios.NbtAddress</see>
|
||||
/// and
|
||||
/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
|
||||
/// . The name resolution mechanisms
|
||||
/// used will systematically query all available configured resolution
|
||||
/// services including WINS, broadcasts, DNS, and LMHOSTS. See
|
||||
/// <a href="../../resolver.html">Setting Name Resolution Properties</a>
|
||||
/// and the <code>jcifs.resolveOrder</code> property. Changing
|
||||
/// jCIFS name resolution properties can greatly affect the behavior of
|
||||
/// the client and may be necessary for proper operation.
|
||||
/// <p>
|
||||
/// This class should be used in favor of <tt>InetAddress</tt> to resolve
|
||||
/// hostnames on LANs and WANs that support a mixture of NetBIOS/WINS and
|
||||
/// DNS resolvable hosts.
|
||||
/// </remarks>
|
||||
public class UniAddress
|
||||
{
|
||||
private const int ResolverWins = 0;
|
||||
|
||||
private const int ResolverBcast = 1;
|
||||
|
||||
private const int ResolverDns = 2;
|
||||
|
||||
private const int ResolverLmhosts = 3;
|
||||
|
||||
private static int[] _resolveOrder;
|
||||
|
||||
private static IPAddress _baddr;
|
||||
|
||||
private static LogStream _log = LogStream.GetInstance();
|
||||
|
||||
static UniAddress()
|
||||
{
|
||||
string ro = Config.GetProperty("jcifs.resolveOrder");
|
||||
IPAddress nbns = NbtAddress.GetWinsAddress();
|
||||
try
|
||||
{
|
||||
_baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName
|
||||
("255.255.255.255"));
|
||||
}
|
||||
catch (UnknownHostException)
|
||||
{
|
||||
}
|
||||
if (string.IsNullOrEmpty(ro))
|
||||
{
|
||||
if (nbns == null)
|
||||
{
|
||||
_resolveOrder = new int[3];
|
||||
_resolveOrder[0] = ResolverLmhosts;
|
||||
_resolveOrder[1] = ResolverDns;
|
||||
_resolveOrder[2] = ResolverBcast;
|
||||
}
|
||||
else
|
||||
{
|
||||
_resolveOrder = new int[4];
|
||||
_resolveOrder[0] = ResolverLmhosts;
|
||||
_resolveOrder[1] = ResolverWins;
|
||||
_resolveOrder[2] = ResolverDns;
|
||||
_resolveOrder[3] = ResolverBcast;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] tmp = new int[4];
|
||||
StringTokenizer st = new StringTokenizer(ro, ",");
|
||||
int i = 0;
|
||||
while (st.HasMoreTokens())
|
||||
{
|
||||
string s = st.NextToken().Trim();
|
||||
if (Runtime.EqualsIgnoreCase(s, "LMHOSTS"))
|
||||
{
|
||||
tmp[i++] = ResolverLmhosts;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Runtime.EqualsIgnoreCase(s, "WINS"))
|
||||
{
|
||||
if (nbns == null)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
_log.WriteLine("UniAddress resolveOrder specifies WINS however the " + "jcifs.netbios.wins property has not been set"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
tmp[i++] = ResolverWins;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Runtime.EqualsIgnoreCase(s, "BCAST"))
|
||||
{
|
||||
tmp[i++] = ResolverBcast;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Runtime.EqualsIgnoreCase(s, "DNS"))
|
||||
{
|
||||
tmp[i++] = ResolverDns;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
_log.WriteLine("unknown resolver method: " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_resolveOrder = new int[i];
|
||||
Array.Copy(tmp, 0, _resolveOrder, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
internal class Sem
|
||||
{
|
||||
internal Sem(int count)
|
||||
{
|
||||
this.Count = count;
|
||||
}
|
||||
|
||||
internal int Count;
|
||||
}
|
||||
|
||||
internal class QueryThread : Thread
|
||||
{
|
||||
internal Sem Sem;
|
||||
|
||||
internal string Host;
|
||||
|
||||
internal string Scope;
|
||||
|
||||
internal int Type;
|
||||
|
||||
internal NbtAddress[] Ans;
|
||||
|
||||
internal IPAddress Svr;
|
||||
|
||||
internal UnknownHostException Uhe;
|
||||
|
||||
internal QueryThread(Sem sem, string host, int type, string scope, IPAddress
|
||||
svr) : base("JCIFS-QueryThread: " + host)
|
||||
{
|
||||
this.Sem = sem;
|
||||
this.Host = host;
|
||||
this.Type = type;
|
||||
this.Scope = scope;
|
||||
this.Svr = svr;
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Ans = new [] { NbtAddress.GetByName(Host, Type, Scope, Svr) };
|
||||
Ans = NbtAddress.GetAllByName(Host, Type, Scope, Svr);
|
||||
}
|
||||
catch (UnknownHostException uhe)
|
||||
{
|
||||
this.Uhe = uhe;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Uhe = new UnknownHostException(ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock (Sem)
|
||||
{
|
||||
Sem.Count--;
|
||||
Runtime.Notify(Sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal static NbtAddress[] LookupServerOrWorkgroup(string name, IPAddress svr)
|
||||
{
|
||||
Sem sem = new Sem(2);
|
||||
int type = NbtAddress.IsWins(svr) ? unchecked(0x1b) : unchecked(0x1d);
|
||||
QueryThread q1X = new QueryThread(sem, name, type, null, svr
|
||||
);
|
||||
QueryThread q20 = new QueryThread(sem, name, unchecked(0x20), null, svr);
|
||||
q1X.SetDaemon(true);
|
||||
q20.SetDaemon(true);
|
||||
try
|
||||
{
|
||||
lock (sem)
|
||||
{
|
||||
q1X.Start();
|
||||
q20.Start();
|
||||
while (sem.Count > 0 && q1X.Ans == null && q20.Ans == null)
|
||||
{
|
||||
Runtime.Wait(sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new UnknownHostException(name);
|
||||
}
|
||||
if (q1X.Ans != null)
|
||||
{
|
||||
return q1X.Ans;
|
||||
}
|
||||
if (q20.Ans != null)
|
||||
{
|
||||
return q20.Ans;
|
||||
}
|
||||
throw q1X.Uhe;
|
||||
}
|
||||
|
||||
/// <summary>Determines the address of a host given it's host name.</summary>
|
||||
/// <remarks>
|
||||
/// Determines the address of a host given it's host name. The name can be a
|
||||
/// machine name like "jcifs.samba.org", or an IP address like "192.168.1.15".
|
||||
/// </remarks>
|
||||
/// <param name="hostname">NetBIOS or DNS hostname to resolve</param>
|
||||
/// <exception cref="UnknownHostException">if there is an error resolving the name
|
||||
/// </exception>
|
||||
public static UniAddress GetByName(string hostname)
|
||||
{
|
||||
return GetByName(hostname, false);
|
||||
}
|
||||
|
||||
internal static bool IsDotQuadIp(string hostname)
|
||||
{
|
||||
if (char.IsDigit(hostname[0]))
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
int dots;
|
||||
char[] data;
|
||||
i = dots = 0;
|
||||
len = hostname.Length;
|
||||
data = hostname.ToCharArray();
|
||||
while (i < len && char.IsDigit(data[i++]))
|
||||
{
|
||||
if (i == len && dots == 3)
|
||||
{
|
||||
// probably an IP address
|
||||
return true;
|
||||
}
|
||||
if (i < len && data[i] == '.')
|
||||
{
|
||||
dots++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool IsAllDigits(string hostname)
|
||||
{
|
||||
for (int i = 0; i < hostname.Length; i++)
|
||||
{
|
||||
if (char.IsDigit(hostname[i]) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>.</summary>
|
||||
/// <remarks>
|
||||
/// Lookup <tt>hostname</tt> and return it's <tt>UniAddress</tt>. If the
|
||||
/// <tt>possibleNTDomainOrWorkgroup</tt> parameter is <tt>true</tt> an
|
||||
/// addtional name query will be performed to locate a master browser.
|
||||
/// </remarks>
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
public static UniAddress GetByName(string hostname, bool possibleNtDomainOrWorkgroup
|
||||
)
|
||||
{
|
||||
UniAddress[] addrs = GetAllByName(hostname, possibleNtDomainOrWorkgroup
|
||||
);
|
||||
return addrs[0];
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
public static UniAddress[] GetAllByName(string hostname, bool possibleNtDomainOrWorkgroup
|
||||
)
|
||||
{
|
||||
object addr;
|
||||
int i;
|
||||
if (string.IsNullOrEmpty(hostname))
|
||||
{
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
if (IsDotQuadIp(hostname))
|
||||
{
|
||||
UniAddress[] addrs = new UniAddress[1];
|
||||
addrs[0] = new UniAddress(NbtAddress.GetByName(hostname));
|
||||
return addrs;
|
||||
}
|
||||
for (i = 0; i < _resolveOrder.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (_resolveOrder[i])
|
||||
{
|
||||
case ResolverLmhosts:
|
||||
{
|
||||
if ((addr = Lmhosts.GetByName(hostname)) == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolverWins:
|
||||
{
|
||||
if (hostname == NbtAddress.MasterBrowserName || hostname.Length > 15)
|
||||
{
|
||||
// invalid netbios name
|
||||
continue;
|
||||
}
|
||||
if (possibleNtDomainOrWorkgroup)
|
||||
{
|
||||
addr = LookupServerOrWorkgroup(hostname, NbtAddress.GetWinsAddress());
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, NbtAddress.GetWinsAddress
|
||||
());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolverBcast:
|
||||
{
|
||||
if (hostname.Length > 15)
|
||||
{
|
||||
// invalid netbios name
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (possibleNtDomainOrWorkgroup)
|
||||
{
|
||||
NbtAddress[] iaddrs = LookupServerOrWorkgroup(hostname, _baddr);
|
||||
|
||||
UniAddress[] addrs = new UniAddress[iaddrs.Length];
|
||||
for (int ii = 0; ii < iaddrs.Length; ii++)
|
||||
{
|
||||
addrs[ii] = new UniAddress(iaddrs[ii]);
|
||||
}
|
||||
return addrs;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = NbtAddress.GetByName(hostname, unchecked(0x20), null, _baddr);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (i == _resolveOrder.Length - 1)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolverDns:
|
||||
{
|
||||
if (IsAllDigits(hostname))
|
||||
{
|
||||
throw new UnknownHostException(hostname);
|
||||
}
|
||||
|
||||
IPAddress[] iaddrs = Extensions.GetAddressesByName(hostname);
|
||||
|
||||
if (iaddrs == null || iaddrs.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return iaddrs.Select(iaddr => new UniAddress(iaddr)).ToArray();
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Success
|
||||
throw new UnknownHostException(hostname);
|
||||
}
|
||||
}
|
||||
UniAddress[] addrs1 = new UniAddress[1];
|
||||
addrs1[0] = new UniAddress(addr);
|
||||
return addrs1;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
// Success
|
||||
// Failure
|
||||
throw new UnknownHostException(hostname);
|
||||
}
|
||||
|
||||
internal object Addr;
|
||||
|
||||
internal string CalledName;
|
||||
|
||||
/// <summary>
|
||||
/// Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or
|
||||
/// <tt>NbtAddress</tt>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Create a <tt>UniAddress</tt> by wrapping an <tt>InetAddress</tt> or
|
||||
/// <tt>NbtAddress</tt>.
|
||||
/// </remarks>
|
||||
public UniAddress(object addr)
|
||||
{
|
||||
if (addr == null)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
this.Addr = addr;
|
||||
}
|
||||
|
||||
/// <summary>Return the IP address of this address as a 32 bit integer.</summary>
|
||||
/// <remarks>Return the IP address of this address as a 32 bit integer.</remarks>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Addr.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>Compare two addresses for equality.</summary>
|
||||
/// <remarks>
|
||||
/// Compare two addresses for equality. Two <tt>UniAddress</tt>s are equal
|
||||
/// if they are both <tt>UniAddress</tt>' and refer to the same IP address.
|
||||
/// </remarks>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is UniAddress && Addr.Equals(((UniAddress)obj).Addr);
|
||||
}
|
||||
|
||||
/// <summary>Guess first called name to try for session establishment.</summary>
|
||||
/// <remarks>
|
||||
/// Guess first called name to try for session establishment. This
|
||||
/// method is used exclusively by the <tt>jcifs.smb</tt> package.
|
||||
/// </remarks>
|
||||
public virtual string FirstCalledName()
|
||||
{
|
||||
if (Addr is NbtAddress)
|
||||
{
|
||||
return ((NbtAddress)Addr).FirstCalledName();
|
||||
}
|
||||
CalledName = ((IPAddress) Addr).GetHostAddress();
|
||||
if (IsDotQuadIp(CalledName))
|
||||
{
|
||||
CalledName = NbtAddress.SmbserverName;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = CalledName.IndexOf('.');
|
||||
if (i > 1 && i < 15)
|
||||
{
|
||||
CalledName = Runtime.Substring(CalledName, 0, i).ToUpper();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CalledName.Length > 15)
|
||||
{
|
||||
CalledName = NbtAddress.SmbserverName;
|
||||
}
|
||||
else
|
||||
{
|
||||
CalledName = CalledName.ToUpper();
|
||||
}
|
||||
}
|
||||
}
|
||||
return CalledName;
|
||||
}
|
||||
|
||||
/// <summary>Guess next called name to try for session establishment.</summary>
|
||||
/// <remarks>
|
||||
/// Guess next called name to try for session establishment. This
|
||||
/// method is used exclusively by the <tt>jcifs.smb</tt> package.
|
||||
/// </remarks>
|
||||
public virtual string NextCalledName()
|
||||
{
|
||||
if (Addr is NbtAddress)
|
||||
{
|
||||
return ((NbtAddress)Addr).NextCalledName();
|
||||
}
|
||||
if (CalledName != NbtAddress.SmbserverName)
|
||||
{
|
||||
CalledName = NbtAddress.SmbserverName;
|
||||
return CalledName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.</summary>
|
||||
/// <remarks>Return the underlying <tt>NbtAddress</tt> or <tt>InetAddress</tt>.</remarks>
|
||||
public virtual object GetAddress()
|
||||
{
|
||||
return Addr;
|
||||
}
|
||||
|
||||
/// <summary>Return the hostname of this address such as "MYCOMPUTER".</summary>
|
||||
/// <remarks>Return the hostname of this address such as "MYCOMPUTER".</remarks>
|
||||
public virtual string GetHostName()
|
||||
{
|
||||
if (Addr is NbtAddress)
|
||||
{
|
||||
return ((NbtAddress)Addr).GetHostName();
|
||||
}
|
||||
return ((IPAddress) Addr).GetHostAddress();
|
||||
}
|
||||
|
||||
/// <summary>Return the IP address as text such as "192.168.1.15".</summary>
|
||||
/// <remarks>Return the IP address as text such as "192.168.1.15".</remarks>
|
||||
public virtual string GetHostAddress()
|
||||
{
|
||||
if (Addr is NbtAddress)
|
||||
{
|
||||
return ((NbtAddress)Addr).GetHostAddress();
|
||||
}
|
||||
return ((IPAddress)Addr).GetHostAddress();
|
||||
}
|
||||
|
||||
public virtual IPAddress GetHostIpAddress()
|
||||
{
|
||||
return (IPAddress) Addr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the a text representation of this address such as
|
||||
/// <tt>MYCOMPUTER/192.168.1.15</tt>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Return the a text representation of this address such as
|
||||
/// <tt>MYCOMPUTER/192.168.1.15</tt>.
|
||||
/// </remarks>
|
||||
public override string ToString()
|
||||
{
|
||||
return Addr.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user