mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 09:04:42 +01:00
merge common implementations and server implementations
This commit is contained in:
202
Emby.Server.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs
Normal file
202
Emby.Server.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
// 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.IO;
|
||||
using SharpCifs.Smb;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
public class Lmhosts
|
||||
{
|
||||
private static readonly string Filename = Config.GetProperty("jcifs.netbios.lmhosts"
|
||||
);
|
||||
|
||||
private static readonly Hashtable Tab = new Hashtable();
|
||||
|
||||
private static long _lastModified = 1L;
|
||||
|
||||
private static int _alt;
|
||||
|
||||
private static LogStream _log = LogStream.GetInstance();
|
||||
|
||||
/// <summary>
|
||||
/// This is really just for
|
||||
/// <see cref="SharpCifs.UniAddress">Jcifs.UniAddress</see>
|
||||
/// . It does
|
||||
/// not throw an
|
||||
/// <see cref="UnknownHostException">Sharpen.UnknownHostException</see>
|
||||
/// because this
|
||||
/// is queried frequently and exceptions would be rather costly to
|
||||
/// throw on a regular basis here.
|
||||
/// </summary>
|
||||
public static NbtAddress GetByName(string host)
|
||||
{
|
||||
lock (typeof(Lmhosts))
|
||||
{
|
||||
return GetByName(new Name(host, 0x20, null));
|
||||
}
|
||||
}
|
||||
|
||||
internal static NbtAddress GetByName(Name name)
|
||||
{
|
||||
lock (typeof(Lmhosts))
|
||||
{
|
||||
NbtAddress result = null;
|
||||
try
|
||||
{
|
||||
if (Filename != null)
|
||||
{
|
||||
FilePath f = new FilePath(Filename);
|
||||
long lm;
|
||||
if ((lm = f.LastModified()) > _lastModified)
|
||||
{
|
||||
_lastModified = lm;
|
||||
Tab.Clear();
|
||||
_alt = 0;
|
||||
|
||||
//path -> fileStream
|
||||
//Populate(new FileReader(f));
|
||||
Populate(new FileReader(new FileStream(f, FileMode.Open)));
|
||||
}
|
||||
result = (NbtAddress)Tab[name];
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException fnfe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
_log.WriteLine("lmhosts file: " + Filename);
|
||||
Runtime.PrintStackTrace(fnfe, _log);
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 0)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal static void Populate(StreamReader r)
|
||||
{
|
||||
string line;
|
||||
BufferedReader br = new BufferedReader((InputStreamReader)r);
|
||||
while ((line = br.ReadLine()) != null)
|
||||
{
|
||||
line = line.ToUpper().Trim();
|
||||
if (line.Length == 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line[0] == '#')
|
||||
{
|
||||
if (line.StartsWith("#INCLUDE "))
|
||||
{
|
||||
line = Runtime.Substring(line, line.IndexOf('\\'));
|
||||
string url = "smb:" + line.Replace('\\', '/');
|
||||
if (_alt > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
Populate(new InputStreamReader(new SmbFileInputStream(url)));
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
_log.WriteLine("lmhosts URL: " + url);
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
continue;
|
||||
}
|
||||
_alt--;
|
||||
while ((line = br.ReadLine()) != null)
|
||||
{
|
||||
line = line.ToUpper().Trim();
|
||||
if (line.StartsWith("#END_ALTERNATE"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Populate(new InputStreamReader(new SmbFileInputStream(url)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line.StartsWith("#BEGIN_ALTERNATE"))
|
||||
{
|
||||
_alt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line.StartsWith("#END_ALTERNATE") && _alt > 0)
|
||||
{
|
||||
_alt--;
|
||||
throw new IOException("no lmhosts alternate includes loaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (char.IsDigit(line[0]))
|
||||
{
|
||||
char[] data = line.ToCharArray();
|
||||
int ip;
|
||||
int i;
|
||||
int j;
|
||||
Name name;
|
||||
NbtAddress addr;
|
||||
char c;
|
||||
c = '.';
|
||||
ip = i = 0;
|
||||
for (; i < data.Length && c == '.'; i++)
|
||||
{
|
||||
int b = unchecked(0x00);
|
||||
for (; i < data.Length && (c = data[i]) >= 48 && c <= 57; i++)
|
||||
{
|
||||
b = b * 10 + c - '0';
|
||||
}
|
||||
ip = (ip << 8) + b;
|
||||
}
|
||||
while (i < data.Length && char.IsWhiteSpace(data[i]))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
j = i;
|
||||
while (j < data.Length && char.IsWhiteSpace(data[j]) == false)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
name = new Name(Runtime.Substring(line, i, j), unchecked(0x20), null
|
||||
);
|
||||
addr = new NbtAddress(name, ip, false, NbtAddress.BNode, false, false, true, true
|
||||
, NbtAddress.UnknownMacAddress);
|
||||
Tab.Put(name, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
269
Emby.Server.Implementations/IO/SharpCifs/Netbios/Name.cs
Normal file
269
Emby.Server.Implementations/IO/SharpCifs/Netbios/Name.cs
Normal file
@@ -0,0 +1,269 @@
|
||||
// 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.Text;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
public class Name
|
||||
{
|
||||
private const int TypeOffset = 31;
|
||||
|
||||
private const int ScopeOffset = 33;
|
||||
|
||||
private static readonly string DefaultScope = Config.GetProperty("jcifs.netbios.scope"
|
||||
);
|
||||
|
||||
internal static readonly string OemEncoding = Config.GetProperty("jcifs.encoding"
|
||||
, Runtime.GetProperty("file.encoding"));
|
||||
|
||||
public string name;
|
||||
|
||||
public string Scope;
|
||||
|
||||
public int HexCode;
|
||||
|
||||
internal int SrcHashCode;
|
||||
|
||||
public Name()
|
||||
{
|
||||
}
|
||||
|
||||
public Name(string name, int hexCode, string scope)
|
||||
{
|
||||
if (name.Length > 15)
|
||||
{
|
||||
name = Runtime.Substring(name, 0, 15);
|
||||
}
|
||||
this.name = name.ToUpper();
|
||||
this.HexCode = hexCode;
|
||||
this.Scope = !string.IsNullOrEmpty(scope) ? scope : DefaultScope;
|
||||
SrcHashCode = 0;
|
||||
}
|
||||
|
||||
internal virtual int WriteWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
// write 0x20 in first byte
|
||||
dst[dstIndex] = unchecked(0x20);
|
||||
// write name
|
||||
try
|
||||
{
|
||||
byte[] tmp = Runtime.GetBytesForString(name, OemEncoding
|
||||
);
|
||||
int i;
|
||||
for (i = 0; i < tmp.Length; i++)
|
||||
{
|
||||
dst[dstIndex + (2 * i + 1)] = unchecked((byte)(((tmp[i] & unchecked(0xF0))
|
||||
>> 4) + unchecked(0x41)));
|
||||
dst[dstIndex + (2 * i + 2)] = unchecked((byte)((tmp[i] & unchecked(0x0F))
|
||||
+ unchecked(0x41)));
|
||||
}
|
||||
for (; i < 15; i++)
|
||||
{
|
||||
dst[dstIndex + (2 * i + 1)] = unchecked(unchecked(0x43));
|
||||
dst[dstIndex + (2 * i + 2)] = unchecked(unchecked(0x41));
|
||||
}
|
||||
dst[dstIndex + TypeOffset] = unchecked((byte)(((HexCode & unchecked(0xF0)
|
||||
) >> 4) + unchecked(0x41)));
|
||||
dst[dstIndex + TypeOffset + 1] = unchecked((byte)((HexCode & unchecked(0x0F)) + unchecked(0x41)));
|
||||
}
|
||||
catch (UnsupportedEncodingException)
|
||||
{
|
||||
}
|
||||
return ScopeOffset + WriteScopeWireFormat(dst, dstIndex + ScopeOffset);
|
||||
}
|
||||
|
||||
internal virtual int ReadWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
byte[] tmp = new byte[ScopeOffset];
|
||||
int length = 15;
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
tmp[i] = unchecked((byte)(((src[srcIndex + (2 * i + 1)] & unchecked(0xFF))
|
||||
- unchecked(0x41)) << 4));
|
||||
tmp[i] |= unchecked((byte)(((src[srcIndex + (2 * i + 2)] & unchecked(0xFF)
|
||||
) - unchecked(0x41)) & unchecked(0x0F)));
|
||||
if (tmp[i] != unchecked((byte)' '))
|
||||
{
|
||||
length = i + 1;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
name = Runtime.GetStringForBytes(tmp, 0, length, OemEncoding
|
||||
);
|
||||
}
|
||||
catch (UnsupportedEncodingException)
|
||||
{
|
||||
}
|
||||
HexCode = ((src[srcIndex + TypeOffset] & unchecked(0xFF)) - unchecked(0x41)) << 4;
|
||||
HexCode |= ((src[srcIndex + TypeOffset + 1] & unchecked(0xFF)) - unchecked(
|
||||
0x41)) & unchecked(0x0F);
|
||||
return ScopeOffset + ReadScopeWireFormat(src, srcIndex + ScopeOffset);
|
||||
}
|
||||
|
||||
internal int ReadWireFormatDos(byte[] src, int srcIndex)
|
||||
{
|
||||
|
||||
int length = 15;
|
||||
byte[] tmp = new byte[length];
|
||||
|
||||
Array.Copy(src, srcIndex, tmp, 0, length);
|
||||
|
||||
try
|
||||
{
|
||||
name = Runtime.GetStringForBytes(tmp, 0, length).Trim();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HexCode = src[srcIndex + length];
|
||||
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
|
||||
internal virtual int WriteScopeWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
if (Scope == null)
|
||||
{
|
||||
dst[dstIndex] = unchecked(unchecked(0x00));
|
||||
return 1;
|
||||
}
|
||||
// copy new scope in
|
||||
dst[dstIndex++] = unchecked((byte)('.'));
|
||||
try
|
||||
{
|
||||
Array.Copy(Runtime.GetBytesForString(Scope, OemEncoding
|
||||
), 0, dst, dstIndex, Scope.Length);
|
||||
}
|
||||
catch (UnsupportedEncodingException)
|
||||
{
|
||||
}
|
||||
dstIndex += Scope.Length;
|
||||
dst[dstIndex++] = unchecked(unchecked(0x00));
|
||||
// now go over scope backwards converting '.' to label length
|
||||
int i = dstIndex - 2;
|
||||
int e = i - Scope.Length;
|
||||
int c = 0;
|
||||
do
|
||||
{
|
||||
if (dst[i] == '.')
|
||||
{
|
||||
dst[i] = unchecked((byte)c);
|
||||
c = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c++;
|
||||
}
|
||||
}
|
||||
while (i-- > e);
|
||||
return Scope.Length + 2;
|
||||
}
|
||||
|
||||
internal virtual int ReadScopeWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
int n;
|
||||
StringBuilder sb;
|
||||
if ((n = src[srcIndex++] & unchecked(0xFF)) == 0)
|
||||
{
|
||||
Scope = null;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
sb = new StringBuilder(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding));
|
||||
srcIndex += n;
|
||||
while ((n = src[srcIndex++] & unchecked(0xFF)) != 0)
|
||||
{
|
||||
sb.Append('.').Append(Runtime.GetStringForBytes(src, srcIndex, n, OemEncoding));
|
||||
srcIndex += n;
|
||||
}
|
||||
Scope = sb.ToString();
|
||||
}
|
||||
catch (UnsupportedEncodingException)
|
||||
{
|
||||
}
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int result;
|
||||
result = name.GetHashCode();
|
||||
result += 65599 * HexCode;
|
||||
result += 65599 * SrcHashCode;
|
||||
if (Scope != null && Scope.Length != 0)
|
||||
{
|
||||
result += Scope.GetHashCode();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Name n;
|
||||
if (!(obj is Name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
n = (Name)obj;
|
||||
if (Scope == null && n.Scope == null)
|
||||
{
|
||||
return name.Equals(n.name) && HexCode == n.HexCode;
|
||||
}
|
||||
return name.Equals(n.name) && HexCode == n.HexCode && Scope.Equals(n.Scope);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
//return "";
|
||||
|
||||
string n = name;
|
||||
// fix MSBROWSE name
|
||||
if (n == null)
|
||||
{
|
||||
n = "null";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n[0] == unchecked(0x01))
|
||||
{
|
||||
char[] c = n.ToCharArray();
|
||||
c[0] = '.';
|
||||
c[1] = '.';
|
||||
c[14] = '.';
|
||||
n = new string(c);
|
||||
}
|
||||
}
|
||||
sb.Append(n).Append("<").Append(Hexdump.ToHexString(HexCode, 2)).Append(">");
|
||||
if (Scope != null)
|
||||
{
|
||||
sb.Append(".").Append(Scope);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class NameQueryRequest : NameServicePacket
|
||||
{
|
||||
internal NameQueryRequest(Name name)
|
||||
{
|
||||
QuestionName = name;
|
||||
QuestionType = Nb;
|
||||
}
|
||||
|
||||
internal override int WriteBodyWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return WriteQuestionSectionWireFormat(dst, dstIndex);
|
||||
}
|
||||
|
||||
internal override int ReadBodyWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return ReadQuestionSectionWireFormat(src, srcIndex);
|
||||
}
|
||||
|
||||
internal override int WriteRDataWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadRDataWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "NameQueryRequest[" + base.ToString() + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class NameQueryResponse : NameServicePacket
|
||||
{
|
||||
public NameQueryResponse()
|
||||
{
|
||||
RecordName = new Name();
|
||||
}
|
||||
|
||||
internal override int WriteBodyWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadBodyWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return ReadResourceRecordWireFormat(src, srcIndex);
|
||||
}
|
||||
|
||||
internal override int WriteRDataWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadRDataWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
if (ResultCode != 0 || OpCode != Query)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
bool groupName = ((src[srcIndex] & unchecked(0x80)) == unchecked(0x80)) ? true : false;
|
||||
int nodeType = (src[srcIndex] & unchecked(0x60)) >> 5;
|
||||
srcIndex += 2;
|
||||
int address = ReadInt4(src, srcIndex);
|
||||
if (address != 0)
|
||||
{
|
||||
AddrEntry[AddrIndex] = new NbtAddress(RecordName, address, groupName, nodeType);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddrEntry[AddrIndex] = null;
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "NameQueryResponse[" + base.ToString() + ",addrEntry=" + AddrEntry
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,660 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
using Thread = SharpCifs.Util.Sharpen.Thread;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class NameServiceClient : IRunnable
|
||||
{
|
||||
internal const int DefaultSoTimeout = 5000;
|
||||
|
||||
internal const int DefaultRcvBufSize = 576;
|
||||
|
||||
internal const int DefaultSndBufSize = 576;
|
||||
|
||||
internal const int NameServiceUdpPort = 137;
|
||||
|
||||
internal const int DefaultRetryCount = 2;
|
||||
|
||||
internal const int DefaultRetryTimeout = 3000;
|
||||
|
||||
internal const int ResolverLmhosts = 1;
|
||||
|
||||
internal const int ResolverBcast = 2;
|
||||
|
||||
internal const int ResolverWins = 3;
|
||||
|
||||
private static readonly int SndBufSize = Config.GetInt("jcifs.netbios.snd_buf_size"
|
||||
, DefaultSndBufSize);
|
||||
|
||||
private static readonly int RcvBufSize = Config.GetInt("jcifs.netbios.rcv_buf_size"
|
||||
, DefaultRcvBufSize);
|
||||
|
||||
private static readonly int SoTimeout = Config.GetInt("jcifs.netbios.soTimeout",
|
||||
DefaultSoTimeout);
|
||||
|
||||
private static readonly int RetryCount = Config.GetInt("jcifs.netbios.retryCount"
|
||||
, DefaultRetryCount);
|
||||
|
||||
private static readonly int RetryTimeout = Config.GetInt("jcifs.netbios.retryTimeout"
|
||||
, DefaultRetryTimeout);
|
||||
|
||||
private static readonly int Lport = Config.GetInt("jcifs.netbios.lport", 137);
|
||||
|
||||
private static readonly IPAddress Laddr = Config.GetInetAddress("jcifs.netbios.laddr"
|
||||
, null);
|
||||
|
||||
private static readonly string Ro = Config.GetProperty("jcifs.resolveOrder");
|
||||
|
||||
private static LogStream _log = LogStream.GetInstance();
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private int _lport;
|
||||
|
||||
private int _closeTimeout;
|
||||
|
||||
private byte[] _sndBuf;
|
||||
|
||||
private byte[] _rcvBuf;
|
||||
|
||||
private SocketEx _socket;
|
||||
|
||||
private Hashtable _responseTable = new Hashtable();
|
||||
|
||||
private Thread _thread;
|
||||
|
||||
private int _nextNameTrnId;
|
||||
|
||||
private int[] _resolveOrder;
|
||||
|
||||
private bool _waitResponse = true;
|
||||
|
||||
private AutoResetEvent _autoResetWaitReceive;
|
||||
|
||||
internal IPAddress laddr;
|
||||
|
||||
internal IPAddress Baddr;
|
||||
|
||||
public NameServiceClient()
|
||||
: this(Lport, Laddr)
|
||||
{
|
||||
}
|
||||
|
||||
internal NameServiceClient(int lport, IPAddress laddr)
|
||||
{
|
||||
this._lport = lport;
|
||||
|
||||
this.laddr = laddr
|
||||
?? Config.GetLocalHost()
|
||||
?? Extensions.GetAddressesByName(Dns.GetHostName()).FirstOrDefault();
|
||||
|
||||
try
|
||||
{
|
||||
Baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName("255.255.255.255"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
|
||||
_sndBuf = new byte[SndBufSize];
|
||||
_rcvBuf = new byte[RcvBufSize];
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(Ro))
|
||||
{
|
||||
if (NbtAddress.GetWinsAddress() == null)
|
||||
{
|
||||
_resolveOrder = new int[2];
|
||||
_resolveOrder[0] = ResolverLmhosts;
|
||||
_resolveOrder[1] = ResolverBcast;
|
||||
}
|
||||
else
|
||||
{
|
||||
_resolveOrder = new int[3];
|
||||
_resolveOrder[0] = ResolverLmhosts;
|
||||
_resolveOrder[1] = ResolverWins;
|
||||
_resolveOrder[2] = ResolverBcast;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] tmp = new int[3];
|
||||
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 (NbtAddress.GetWinsAddress() == null)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
_log.WriteLine("NetBIOS 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"))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
_log.WriteLine("unknown resolver method: " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_resolveOrder = new int[i];
|
||||
Array.Copy(tmp, 0, _resolveOrder, 0, i);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual int GetNextNameTrnId()
|
||||
{
|
||||
if ((++_nextNameTrnId & unchecked(0xFFFF)) == 0)
|
||||
{
|
||||
_nextNameTrnId = 1;
|
||||
}
|
||||
return _nextNameTrnId;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal virtual void EnsureOpen(int timeout)
|
||||
{
|
||||
_closeTimeout = 0;
|
||||
if (SoTimeout != 0)
|
||||
{
|
||||
_closeTimeout = Math.Max(SoTimeout, timeout);
|
||||
}
|
||||
// If socket is still good, the new closeTimeout will
|
||||
// be ignored; see tryClose comment.
|
||||
if (_socket == null)
|
||||
{
|
||||
_socket = new SocketEx(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
|
||||
//IPAddress.`Address` property deleted
|
||||
//_socket.Bind(new IPEndPoint(laddr.Address, _lport));
|
||||
_socket.Bind(new IPEndPoint(laddr, _lport));
|
||||
|
||||
if (_waitResponse)
|
||||
{
|
||||
_thread = new Thread(this); //new Sharpen.Thread(this, "JCIFS-NameServiceClient");
|
||||
_thread.SetDaemon(true);
|
||||
_thread.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void TryClose()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_socket != null)
|
||||
{
|
||||
//Socket.`Close` method deleted
|
||||
//_socket.Close();
|
||||
_socket.Dispose();
|
||||
_socket = null;
|
||||
}
|
||||
_thread = null;
|
||||
|
||||
if (_waitResponse)
|
||||
{
|
||||
_responseTable.Clear();
|
||||
} else
|
||||
{
|
||||
_autoResetWaitReceive.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Run()
|
||||
{
|
||||
int nameTrnId;
|
||||
NameServicePacket response;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
while (_thread == Thread.CurrentThread())
|
||||
{
|
||||
_socket.SoTimeOut = _closeTimeout;
|
||||
|
||||
int len = _socket.Receive(_rcvBuf, 0, RcvBufSize);
|
||||
|
||||
if (_log.Level > 3)
|
||||
{
|
||||
_log.WriteLine("NetBIOS: new data read from socket");
|
||||
}
|
||||
nameTrnId = NameServicePacket.ReadNameTrnId(_rcvBuf, 0);
|
||||
response = (NameServicePacket)_responseTable.Get(nameTrnId);
|
||||
|
||||
|
||||
if (response == null || response.Received)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lock (response)
|
||||
{
|
||||
response.ReadWireFormat(_rcvBuf, 0);
|
||||
|
||||
if (_log.Level > 3)
|
||||
{
|
||||
_log.WriteLine(response);
|
||||
Hexdump.ToHexdump(_log, _rcvBuf, 0, len);
|
||||
}
|
||||
|
||||
if (response.IsResponse)
|
||||
{
|
||||
response.Received = true;
|
||||
|
||||
Runtime.Notify(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (TimeoutException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (_log.Level > 2)
|
||||
{
|
||||
Runtime.PrintStackTrace(ex, _log);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryClose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal virtual void Send(NameServicePacket request, NameServicePacket response,
|
||||
int timeout)
|
||||
{
|
||||
int nid = 0;
|
||||
int max = NbtAddress.Nbns.Length;
|
||||
if (max == 0)
|
||||
{
|
||||
max = 1;
|
||||
}
|
||||
|
||||
lock (response)
|
||||
{
|
||||
|
||||
while (max-- > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
request.NameTrnId = GetNextNameTrnId();
|
||||
nid = request.NameTrnId;
|
||||
response.Received = false;
|
||||
_responseTable.Put(nid, response);
|
||||
EnsureOpen(timeout + 1000);
|
||||
int requestLenght = request.WriteWireFormat(_sndBuf, 0);
|
||||
_socket.Send(_sndBuf, 0, requestLenght, new IPEndPoint(request.Addr, _lport));
|
||||
if (_log.Level > 3)
|
||||
{
|
||||
_log.WriteLine(request);
|
||||
Hexdump.ToHexdump(_log, _sndBuf, 0, requestLenght);
|
||||
}
|
||||
|
||||
}
|
||||
if (_waitResponse)
|
||||
{
|
||||
long start = Runtime.CurrentTimeMillis();
|
||||
while (timeout > 0)
|
||||
{
|
||||
Runtime.Wait(response, timeout);
|
||||
if (response.Received && request.QuestionType == response.RecordType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
response.Received = false;
|
||||
timeout -= (int)(Runtime.CurrentTimeMillis() - start);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ie)
|
||||
{
|
||||
throw new IOException(ie.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Sharpen.Collections.Remove(responseTable, nid);
|
||||
if (_waitResponse)
|
||||
{
|
||||
_responseTable.Remove(nid);
|
||||
}
|
||||
}
|
||||
if (_waitResponse)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (NbtAddress.IsWins(request.Addr) == false)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (request.Addr == NbtAddress.GetWinsAddress())
|
||||
{
|
||||
NbtAddress.SwitchWins();
|
||||
}
|
||||
request.Addr = NbtAddress.GetWinsAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal virtual NbtAddress[] GetAllByName(Name name, IPAddress addr)
|
||||
{
|
||||
int n;
|
||||
NameQueryRequest request = new NameQueryRequest(name);
|
||||
NameQueryResponse response = new NameQueryResponse();
|
||||
request.Addr = addr ?? NbtAddress.GetWinsAddress();
|
||||
request.IsBroadcast = request.Addr == null;
|
||||
if (request.IsBroadcast)
|
||||
{
|
||||
request.Addr = Baddr;
|
||||
n = RetryCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.IsBroadcast = false;
|
||||
n = 1;
|
||||
}
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
Send(request, response, RetryTimeout);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
throw new UnknownHostException(ioe);
|
||||
}
|
||||
if (response.Received && response.ResultCode == 0)
|
||||
{
|
||||
return response.AddrEntry;
|
||||
}
|
||||
}
|
||||
while (--n > 0 && request.IsBroadcast);
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal virtual NbtAddress GetByName(Name name, IPAddress addr)
|
||||
{
|
||||
int n;
|
||||
|
||||
NameQueryRequest request = new NameQueryRequest(name);
|
||||
NameQueryResponse response = new NameQueryResponse();
|
||||
if (addr != null)
|
||||
{
|
||||
request.Addr = addr;
|
||||
request.IsBroadcast = (addr.GetAddressBytes()[3] == unchecked(unchecked(0xFF)));
|
||||
n = RetryCount;
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
Send(request, response, RetryTimeout);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
throw new UnknownHostException(ioe);
|
||||
}
|
||||
if (response.Received && response.ResultCode == 0
|
||||
&& response.IsResponse)
|
||||
{
|
||||
int last = response.AddrEntry.Length - 1;
|
||||
response.AddrEntry[last].HostName.SrcHashCode = addr.GetHashCode();
|
||||
return response.AddrEntry[last];
|
||||
}
|
||||
}
|
||||
while (--n > 0 && request.IsBroadcast);
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
for (int i = 0; i < _resolveOrder.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (_resolveOrder[i])
|
||||
{
|
||||
case ResolverLmhosts:
|
||||
{
|
||||
NbtAddress ans = Lmhosts.GetByName(name);
|
||||
if (ans != null)
|
||||
{
|
||||
ans.HostName.SrcHashCode = 0;
|
||||
// just has to be different
|
||||
// from other methods
|
||||
return ans;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ResolverWins:
|
||||
case ResolverBcast:
|
||||
{
|
||||
if (_resolveOrder[i] == ResolverWins && name.name != NbtAddress.MasterBrowserName
|
||||
&& name.HexCode != unchecked(0x1d))
|
||||
{
|
||||
request.Addr = NbtAddress.GetWinsAddress();
|
||||
request.IsBroadcast = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
request.Addr = Baddr;
|
||||
request.IsBroadcast = true;
|
||||
}
|
||||
n = RetryCount;
|
||||
while (n-- > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
Send(request, response, RetryTimeout);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
throw new UnknownHostException(ioe);
|
||||
}
|
||||
if (response.Received && response.ResultCode == 0
|
||||
&& response.IsResponse)
|
||||
{
|
||||
|
||||
response.AddrEntry[0].HostName.SrcHashCode = request.Addr.GetHashCode();
|
||||
return response.AddrEntry[0];
|
||||
}
|
||||
if (_resolveOrder[i] == ResolverWins)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal virtual NbtAddress[] GetNodeStatus(NbtAddress addr)
|
||||
{
|
||||
int n;
|
||||
int srcHashCode;
|
||||
NodeStatusRequest request;
|
||||
NodeStatusResponse response;
|
||||
response = new NodeStatusResponse(addr);
|
||||
request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x00), null));
|
||||
request.Addr = addr.GetInetAddress();
|
||||
n = RetryCount;
|
||||
while (n-- > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
Send(request, response, RetryTimeout);
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
throw new UnknownHostException(ioe);
|
||||
}
|
||||
if (response.Received && response.ResultCode == 0)
|
||||
{
|
||||
srcHashCode = request.Addr.GetHashCode();
|
||||
for (int i = 0; i < response.AddressArray.Length; i++)
|
||||
{
|
||||
response.AddressArray[i].HostName.SrcHashCode = srcHashCode;
|
||||
}
|
||||
return response.AddressArray;
|
||||
}
|
||||
}
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
|
||||
internal virtual NbtAddress[] GetHosts()
|
||||
{
|
||||
try
|
||||
{
|
||||
_waitResponse = false;
|
||||
|
||||
byte[] bAddrBytes = laddr.GetAddressBytes();
|
||||
|
||||
for (int i = 1; i <= 254; i++)
|
||||
{
|
||||
NodeStatusRequest request;
|
||||
NodeStatusResponse response;
|
||||
|
||||
byte[] addrBytes = {
|
||||
bAddrBytes[0],
|
||||
bAddrBytes[1],
|
||||
bAddrBytes[2],
|
||||
(byte)i
|
||||
};
|
||||
|
||||
IPAddress addr = new IPAddress(addrBytes);
|
||||
|
||||
//response = new NodeStatusResponse(new NbtAddress(NbtAddress.UnknownName,
|
||||
// (int)addr.Address, false, 0x20));
|
||||
response = new NodeStatusResponse(new NbtAddress(NbtAddress.UnknownName,
|
||||
BitConverter.ToInt32(addr.GetAddressBytes(), 0) , false, 0x20));
|
||||
|
||||
request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x20), null));
|
||||
request.Addr = addr;
|
||||
Send(request, response, 0);
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (_log.Level > 1)
|
||||
{
|
||||
Runtime.PrintStackTrace(ioe, _log);
|
||||
}
|
||||
throw new UnknownHostException(ioe);
|
||||
}
|
||||
|
||||
_autoResetWaitReceive = new AutoResetEvent(false);
|
||||
_thread = new Thread(this);
|
||||
_thread.SetDaemon(true);
|
||||
_thread.Start();
|
||||
|
||||
_autoResetWaitReceive.WaitOne();
|
||||
|
||||
List<NbtAddress> result = new List<NbtAddress>();
|
||||
|
||||
foreach (var key in _responseTable.Keys)
|
||||
{
|
||||
NodeStatusResponse resp = (NodeStatusResponse)_responseTable[key];
|
||||
|
||||
if (resp.Received && resp.ResultCode == 0)
|
||||
{
|
||||
foreach (var entry in resp.AddressArray)
|
||||
{
|
||||
if (entry.HostName.HexCode == 0x20)
|
||||
{
|
||||
result.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_responseTable.Clear();
|
||||
|
||||
_waitResponse = true;
|
||||
|
||||
return result.Count > 0 ? result.ToArray() : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
// 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.Net;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal abstract class NameServicePacket
|
||||
{
|
||||
internal const int Query = 0;
|
||||
|
||||
internal const int Wack = 7;
|
||||
|
||||
internal const int FmtErr = 0x1;
|
||||
|
||||
internal const int SrvErr = 0x2;
|
||||
|
||||
internal const int ImpErr = 0x4;
|
||||
|
||||
internal const int RfsErr = 0x5;
|
||||
|
||||
internal const int ActErr = 0x6;
|
||||
|
||||
internal const int CftErr = 0x7;
|
||||
|
||||
internal const int NbIn = 0x00200001;
|
||||
|
||||
internal const int NbstatIn = 0x00210001;
|
||||
|
||||
internal const int Nb = 0x0020;
|
||||
|
||||
internal const int Nbstat = 0x0021;
|
||||
|
||||
internal const int In = 0x0001;
|
||||
|
||||
internal const int A = 0x0001;
|
||||
|
||||
internal const int Ns = 0x0002;
|
||||
|
||||
internal const int Null = 0x000a;
|
||||
|
||||
internal const int HeaderLength = 12;
|
||||
|
||||
internal const int OpcodeOffset = 2;
|
||||
|
||||
internal const int QuestionOffset = 4;
|
||||
|
||||
internal const int AnswerOffset = 6;
|
||||
|
||||
internal const int AuthorityOffset = 8;
|
||||
|
||||
internal const int AdditionalOffset = 10;
|
||||
|
||||
// opcode
|
||||
// rcode
|
||||
// type/class
|
||||
// header field offsets
|
||||
internal static void WriteInt2(int val, byte[] dst, int dstIndex)
|
||||
{
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
|
||||
dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
|
||||
}
|
||||
|
||||
internal static void WriteInt4(int val, byte[] dst, int dstIndex)
|
||||
{
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 24) & unchecked(0xFF)));
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 16) & unchecked(0xFF)));
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
|
||||
dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
|
||||
}
|
||||
|
||||
internal static int ReadInt2(byte[] src, int srcIndex)
|
||||
{
|
||||
return ((src[srcIndex] & unchecked(0xFF)) << 8) + (src[srcIndex + 1] & unchecked(
|
||||
0xFF));
|
||||
}
|
||||
|
||||
internal static int ReadInt4(byte[] src, int srcIndex)
|
||||
{
|
||||
return ((src[srcIndex] & unchecked(0xFF)) << 24) + ((src[srcIndex + 1] & unchecked(
|
||||
0xFF)) << 16) + ((src[srcIndex + 2] & unchecked(0xFF)) << 8) + (src
|
||||
[srcIndex + 3] & unchecked(0xFF));
|
||||
}
|
||||
|
||||
internal static int ReadNameTrnId(byte[] src, int srcIndex)
|
||||
{
|
||||
return ReadInt2(src, srcIndex);
|
||||
}
|
||||
|
||||
internal int AddrIndex;
|
||||
|
||||
internal NbtAddress[] AddrEntry;
|
||||
|
||||
internal int NameTrnId;
|
||||
|
||||
internal int OpCode;
|
||||
|
||||
internal int ResultCode;
|
||||
|
||||
internal int QuestionCount;
|
||||
|
||||
internal int AnswerCount;
|
||||
|
||||
internal int AuthorityCount;
|
||||
|
||||
internal int AdditionalCount;
|
||||
|
||||
internal bool Received;
|
||||
|
||||
internal bool IsResponse;
|
||||
|
||||
internal bool IsAuthAnswer;
|
||||
|
||||
internal bool IsTruncated;
|
||||
|
||||
internal bool IsRecurDesired;
|
||||
|
||||
internal bool IsRecurAvailable;
|
||||
|
||||
internal bool IsBroadcast;
|
||||
|
||||
internal Name QuestionName;
|
||||
|
||||
internal Name RecordName;
|
||||
|
||||
internal int QuestionType;
|
||||
|
||||
internal int QuestionClass;
|
||||
|
||||
internal int RecordType;
|
||||
|
||||
internal int RecordClass;
|
||||
|
||||
internal int Ttl;
|
||||
|
||||
internal int RDataLength;
|
||||
|
||||
internal IPAddress Addr;
|
||||
|
||||
public NameServicePacket()
|
||||
{
|
||||
IsRecurDesired = true;
|
||||
IsBroadcast = true;
|
||||
QuestionCount = 1;
|
||||
QuestionClass = In;
|
||||
}
|
||||
|
||||
internal virtual int WriteWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int start = dstIndex;
|
||||
dstIndex += WriteHeaderWireFormat(dst, dstIndex);
|
||||
dstIndex += WriteBodyWireFormat(dst, dstIndex);
|
||||
return dstIndex - start;
|
||||
}
|
||||
|
||||
internal virtual int ReadWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
srcIndex += ReadHeaderWireFormat(src, srcIndex);
|
||||
srcIndex += ReadBodyWireFormat(src, srcIndex);
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int start = dstIndex;
|
||||
WriteInt2(NameTrnId, dst, dstIndex);
|
||||
dst[dstIndex + OpcodeOffset] = unchecked((byte)((IsResponse ? unchecked(0x80) : unchecked(0x00)) + ((OpCode << 3) & unchecked(0x78)) + (IsAuthAnswer
|
||||
? unchecked(0x04) : unchecked(0x00)) + (IsTruncated ? unchecked(0x02) : unchecked(0x00)) + (IsRecurDesired ? unchecked(0x01)
|
||||
: unchecked(0x00))));
|
||||
dst[dstIndex + OpcodeOffset + 1] = unchecked((byte)((IsRecurAvailable ? unchecked(
|
||||
0x80) : unchecked(0x00)) + (IsBroadcast ? unchecked(0x10) :
|
||||
unchecked(0x00)) + (ResultCode & unchecked(0x0F))));
|
||||
WriteInt2(QuestionCount, dst, start + QuestionOffset);
|
||||
WriteInt2(AnswerCount, dst, start + AnswerOffset);
|
||||
WriteInt2(AuthorityCount, dst, start + AuthorityOffset);
|
||||
WriteInt2(AdditionalCount, dst, start + AdditionalOffset);
|
||||
return HeaderLength;
|
||||
}
|
||||
|
||||
internal virtual int ReadHeaderWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
NameTrnId = ReadInt2(src, srcIndex);
|
||||
IsResponse = ((src[srcIndex + OpcodeOffset] & unchecked(0x80)) == 0) ? false
|
||||
: true;
|
||||
OpCode = (src[srcIndex + OpcodeOffset] & unchecked(0x78)) >> 3;
|
||||
IsAuthAnswer = ((src[srcIndex + OpcodeOffset] & unchecked(0x04)) == 0) ?
|
||||
false : true;
|
||||
IsTruncated = ((src[srcIndex + OpcodeOffset] & unchecked(0x02)) == 0) ? false
|
||||
: true;
|
||||
IsRecurDesired = ((src[srcIndex + OpcodeOffset] & unchecked(0x01)) == 0) ?
|
||||
false : true;
|
||||
IsRecurAvailable = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x80))
|
||||
== 0) ? false : true;
|
||||
IsBroadcast = ((src[srcIndex + OpcodeOffset + 1] & unchecked(0x10)) == 0)
|
||||
? false : true;
|
||||
ResultCode = src[srcIndex + OpcodeOffset + 1] & unchecked(0x0F);
|
||||
QuestionCount = ReadInt2(src, srcIndex + QuestionOffset);
|
||||
AnswerCount = ReadInt2(src, srcIndex + AnswerOffset);
|
||||
AuthorityCount = ReadInt2(src, srcIndex + AuthorityOffset);
|
||||
AdditionalCount = ReadInt2(src, srcIndex + AdditionalOffset);
|
||||
return HeaderLength;
|
||||
}
|
||||
|
||||
internal virtual int WriteQuestionSectionWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int start = dstIndex;
|
||||
dstIndex += QuestionName.WriteWireFormat(dst, dstIndex);
|
||||
WriteInt2(QuestionType, dst, dstIndex);
|
||||
dstIndex += 2;
|
||||
WriteInt2(QuestionClass, dst, dstIndex);
|
||||
dstIndex += 2;
|
||||
return dstIndex - start;
|
||||
}
|
||||
|
||||
internal virtual int ReadQuestionSectionWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
srcIndex += QuestionName.ReadWireFormat(src, srcIndex);
|
||||
QuestionType = ReadInt2(src, srcIndex);
|
||||
srcIndex += 2;
|
||||
QuestionClass = ReadInt2(src, srcIndex);
|
||||
srcIndex += 2;
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
internal virtual int WriteResourceRecordWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int start = dstIndex;
|
||||
if (RecordName == QuestionName)
|
||||
{
|
||||
dst[dstIndex++] = unchecked(unchecked(0xC0));
|
||||
// label string pointer to
|
||||
dst[dstIndex++] = unchecked(unchecked(0x0C));
|
||||
}
|
||||
else
|
||||
{
|
||||
// questionName (offset 12)
|
||||
dstIndex += RecordName.WriteWireFormat(dst, dstIndex);
|
||||
}
|
||||
WriteInt2(RecordType, dst, dstIndex);
|
||||
dstIndex += 2;
|
||||
WriteInt2(RecordClass, dst, dstIndex);
|
||||
dstIndex += 2;
|
||||
WriteInt4(Ttl, dst, dstIndex);
|
||||
dstIndex += 4;
|
||||
RDataLength = WriteRDataWireFormat(dst, dstIndex + 2);
|
||||
WriteInt2(RDataLength, dst, dstIndex);
|
||||
dstIndex += 2 + RDataLength;
|
||||
return dstIndex - start;
|
||||
}
|
||||
|
||||
internal virtual int ReadResourceRecordWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
int end;
|
||||
if ((src[srcIndex] & unchecked(0xC0)) == unchecked(0xC0))
|
||||
{
|
||||
RecordName = QuestionName;
|
||||
// label string pointer to questionName
|
||||
srcIndex += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
srcIndex += RecordName.ReadWireFormat(src, srcIndex);
|
||||
}
|
||||
RecordType = ReadInt2(src, srcIndex);
|
||||
srcIndex += 2;
|
||||
RecordClass = ReadInt2(src, srcIndex);
|
||||
srcIndex += 2;
|
||||
Ttl = ReadInt4(src, srcIndex);
|
||||
srcIndex += 4;
|
||||
RDataLength = ReadInt2(src, srcIndex);
|
||||
srcIndex += 2;
|
||||
AddrEntry = new NbtAddress[RDataLength / 6];
|
||||
end = srcIndex + RDataLength;
|
||||
for (AddrIndex = 0; srcIndex < end; AddrIndex++)
|
||||
{
|
||||
srcIndex += ReadRDataWireFormat(src, srcIndex);
|
||||
}
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
internal abstract int WriteBodyWireFormat(byte[] dst, int dstIndex);
|
||||
|
||||
internal abstract int ReadBodyWireFormat(byte[] src, int srcIndex);
|
||||
|
||||
internal abstract int WriteRDataWireFormat(byte[] dst, int dstIndex);
|
||||
|
||||
internal abstract int ReadRDataWireFormat(byte[] src, int srcIndex);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string opCodeString;
|
||||
string resultCodeString;
|
||||
string questionTypeString;
|
||||
string recordTypeString;
|
||||
|
||||
switch (OpCode)
|
||||
{
|
||||
case Query:
|
||||
{
|
||||
opCodeString = "QUERY";
|
||||
break;
|
||||
}
|
||||
|
||||
case Wack:
|
||||
{
|
||||
opCodeString = "WACK";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
opCodeString = Extensions.ToString(OpCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (ResultCode)
|
||||
{
|
||||
case FmtErr:
|
||||
{
|
||||
resultCodeString = "FMT_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
case SrvErr:
|
||||
{
|
||||
resultCodeString = "SRV_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
case ImpErr:
|
||||
{
|
||||
resultCodeString = "IMP_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
case RfsErr:
|
||||
{
|
||||
resultCodeString = "RFS_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
case ActErr:
|
||||
{
|
||||
resultCodeString = "ACT_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
case CftErr:
|
||||
{
|
||||
resultCodeString = "CFT_ERR";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
resultCodeString = "0x" + Hexdump.ToHexString(ResultCode, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (QuestionType)
|
||||
{
|
||||
case Nb:
|
||||
{
|
||||
questionTypeString = "NB";
|
||||
break;
|
||||
}
|
||||
|
||||
case Nbstat:
|
||||
{
|
||||
questionTypeString = "NBSTAT";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
questionTypeString = "0x" + Hexdump.ToHexString(QuestionType, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (RecordType)
|
||||
{
|
||||
case A:
|
||||
{
|
||||
recordTypeString = "A";
|
||||
break;
|
||||
}
|
||||
|
||||
case Ns:
|
||||
{
|
||||
recordTypeString = "NS";
|
||||
break;
|
||||
}
|
||||
|
||||
case Null:
|
||||
{
|
||||
recordTypeString = "NULL";
|
||||
break;
|
||||
}
|
||||
|
||||
case Nb:
|
||||
{
|
||||
recordTypeString = "NB";
|
||||
break;
|
||||
}
|
||||
|
||||
case Nbstat:
|
||||
{
|
||||
recordTypeString = "NBSTAT";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
recordTypeString = "0x" + Hexdump.ToHexString(RecordType, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "nameTrnId=" + NameTrnId + ",isResponse=" + IsResponse + ",opCode="
|
||||
+ opCodeString + ",isAuthAnswer=" + IsAuthAnswer + ",isTruncated=" + IsTruncated
|
||||
+ ",isRecurAvailable=" + IsRecurAvailable + ",isRecurDesired=" + IsRecurDesired
|
||||
+ ",isBroadcast=" + IsBroadcast + ",resultCode=" + ResultCode + ",questionCount="
|
||||
+ QuestionCount + ",answerCount=" + AnswerCount + ",authorityCount=" + AuthorityCount
|
||||
+ ",additionalCount=" + AdditionalCount + ",questionName=" + QuestionName + ",questionType="
|
||||
+ questionTypeString + ",questionClass=" + (QuestionClass == In ? "IN" : "0x" +
|
||||
Hexdump.ToHexString(QuestionClass, 4)) + ",recordName=" + RecordName + ",recordType="
|
||||
+ recordTypeString + ",recordClass=" + (RecordClass == In ? "IN" : "0x" + Hexdump
|
||||
.ToHexString(RecordClass, 4)) + ",ttl=" + Ttl + ",rDataLength=" + RDataLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
920
Emby.Server.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs
Normal file
920
Emby.Server.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs
Normal file
@@ -0,0 +1,920 @@
|
||||
// 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.Linq;
|
||||
using System.Net;
|
||||
using SharpCifs.Util;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
using Extensions = SharpCifs.Util.Sharpen.Extensions;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
/// <summary>This class represents a NetBIOS over TCP/IP address.</summary>
|
||||
/// <remarks>
|
||||
/// This class represents a NetBIOS over TCP/IP address. Under normal
|
||||
/// conditions, users of jCIFS need not be concerned with this class as
|
||||
/// name resolution and session services are handled internally by the smb package.
|
||||
/// <p> Applications can use the methods <code>getLocalHost</code>,
|
||||
/// <code>getByName</code>, and
|
||||
/// <code>getAllByAddress</code> to create a new NbtAddress instance. This
|
||||
/// class is symmetric with
|
||||
/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
|
||||
/// .
|
||||
/// <p><b>About NetBIOS:</b> The NetBIOS name
|
||||
/// service is a dynamic distributed service that allows hosts to resolve
|
||||
/// names by broadcasting a query, directing queries to a server such as
|
||||
/// Samba or WINS. NetBIOS is currently the primary networking layer for
|
||||
/// providing name service, datagram service, and session service to the
|
||||
/// Microsoft Windows platform. A NetBIOS name can be 15 characters long
|
||||
/// and hosts usually registers several names on the network. From a
|
||||
/// Windows command prompt you can see
|
||||
/// what names a host registers with the nbtstat command.
|
||||
/// <p><blockquote><pre>
|
||||
/// C:\>nbtstat -a 192.168.1.15
|
||||
/// NetBIOS Remote Machine Name Table
|
||||
/// Name Type Status
|
||||
/// ---------------------------------------------
|
||||
/// JMORRIS2 <00> UNIQUE Registered
|
||||
/// BILLING-NY <00> GROUP Registered
|
||||
/// JMORRIS2 <03> UNIQUE Registered
|
||||
/// JMORRIS2 <20> UNIQUE Registered
|
||||
/// BILLING-NY <1E> GROUP Registered
|
||||
/// JMORRIS <03> UNIQUE Registered
|
||||
/// MAC Address = 00-B0-34-21-FA-3B
|
||||
/// </blockquote></pre>
|
||||
/// <p> The hostname of this machine is <code>JMORRIS2</code>. It is
|
||||
/// a member of the group(a.k.a workgroup and domain) <code>BILLING-NY</code>. To
|
||||
/// obtain an
|
||||
/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
|
||||
/// for a host one might do:
|
||||
/// <pre>
|
||||
/// InetAddress addr = NbtAddress.getByName( "jmorris2" ).getInetAddress();
|
||||
/// </pre>
|
||||
/// <p>From a UNIX platform with Samba installed you can perform similar
|
||||
/// diagnostics using the <code>nmblookup</code> utility.
|
||||
/// </remarks>
|
||||
/// <author>Michael B. Allen</author>
|
||||
/// <seealso cref="System.Net.IPAddress">System.Net.IPAddress</seealso>
|
||||
/// <since>jcifs-0.1</since>
|
||||
public sealed class NbtAddress
|
||||
{
|
||||
internal static readonly string AnyHostsName = "*\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000";
|
||||
|
||||
/// <summary>
|
||||
/// This is a special name for querying the master browser that serves the
|
||||
/// list of hosts found in "Network Neighborhood".
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a special name for querying the master browser that serves the
|
||||
/// list of hosts found in "Network Neighborhood".
|
||||
/// </remarks>
|
||||
public static readonly string MasterBrowserName = "\u0001\u0002__MSBROWSE__\u0002";
|
||||
|
||||
/// <summary>
|
||||
/// A special generic name specified when connecting to a host for which
|
||||
/// a name is not known.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A special generic name specified when connecting to a host for which
|
||||
/// a name is not known. Not all servers respond to this name.
|
||||
/// </remarks>
|
||||
public static readonly string SmbserverName = "*SMBSERVER ";
|
||||
|
||||
/// <summary>A B node only broadcasts name queries.</summary>
|
||||
/// <remarks>
|
||||
/// A B node only broadcasts name queries. This is the default if a
|
||||
/// nameserver such as WINS or Samba is not specified.
|
||||
/// </remarks>
|
||||
public const int BNode = 0;
|
||||
|
||||
/// <summary>
|
||||
/// A Point-to-Point node, or P node, unicasts queries to a nameserver
|
||||
/// only.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A Point-to-Point node, or P node, unicasts queries to a nameserver
|
||||
/// only. Natrually the <code>jcifs.netbios.nameserver</code> property must
|
||||
/// be set.
|
||||
/// </remarks>
|
||||
public const int PNode = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Try Broadcast queries first, then try to resolve the name using the
|
||||
/// nameserver.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Try Broadcast queries first, then try to resolve the name using the
|
||||
/// nameserver.
|
||||
/// </remarks>
|
||||
public const int MNode = 2;
|
||||
|
||||
/// <summary>A Hybrid node tries to resolve a name using the nameserver first.</summary>
|
||||
/// <remarks>
|
||||
/// A Hybrid node tries to resolve a name using the nameserver first. If
|
||||
/// that fails use the broadcast address. This is the default if a nameserver
|
||||
/// is provided. This is the behavior of Microsoft Windows machines.
|
||||
/// </remarks>
|
||||
public const int HNode = 3;
|
||||
|
||||
internal static readonly IPAddress[] Nbns = Config.GetInetAddressArray("jcifs.netbios.wins"
|
||||
, ",", new IPAddress[0]);
|
||||
|
||||
private static readonly NameServiceClient Client = new NameServiceClient();
|
||||
|
||||
private const int DefaultCachePolicy = 30;
|
||||
|
||||
private static readonly int CachePolicy = Config.GetInt("jcifs.netbios.cachePolicy"
|
||||
, DefaultCachePolicy);
|
||||
|
||||
private const int Forever = -1;
|
||||
|
||||
private static int _nbnsIndex;
|
||||
|
||||
private static readonly Hashtable AddressCache = new Hashtable();
|
||||
|
||||
private static readonly Hashtable LookupTable = new Hashtable();
|
||||
|
||||
internal static readonly Name UnknownName = new Name("0.0.0.0", unchecked(0x00), null);
|
||||
|
||||
internal static readonly NbtAddress UnknownAddress = new NbtAddress
|
||||
(UnknownName, 0, false, BNode);
|
||||
|
||||
internal static readonly byte[] UnknownMacAddress = { unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)), unchecked(unchecked(0x00)) };
|
||||
|
||||
internal sealed class CacheEntry
|
||||
{
|
||||
internal Name HostName;
|
||||
|
||||
internal NbtAddress Address;
|
||||
|
||||
internal long Expiration;
|
||||
|
||||
internal CacheEntry(Name hostName, NbtAddress address, long expiration)
|
||||
{
|
||||
this.HostName = hostName;
|
||||
this.Address = address;
|
||||
this.Expiration = expiration;
|
||||
}
|
||||
}
|
||||
|
||||
internal static NbtAddress Localhost;
|
||||
|
||||
static NbtAddress()
|
||||
{
|
||||
IPAddress localInetAddress;
|
||||
string localHostname;
|
||||
Name localName;
|
||||
AddressCache.Put(UnknownName, new CacheEntry(UnknownName, UnknownAddress
|
||||
, Forever));
|
||||
localInetAddress = Client.laddr;
|
||||
if (localInetAddress == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
localInetAddress = Extensions.GetAddressByName("127.0.0.1");
|
||||
}
|
||||
catch (UnknownHostException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
localHostname = Config.GetProperty("jcifs.netbios.hostname", null);
|
||||
if (string.IsNullOrEmpty(localHostname))
|
||||
{
|
||||
byte[] addr = localInetAddress.GetAddressBytes();
|
||||
|
||||
/*localHostname = "JCIFS" + (addr[2] & unchecked((int)(0xFF))) + "_" + (addr[3] & unchecked(
|
||||
(int)(0xFF))) + "_" + Hexdump.ToHexString((int)(new Random().NextDouble() * (double)unchecked(
|
||||
(int)(0xFF))), 2);*/
|
||||
localHostname = "JCIFS_127_0_0_1";
|
||||
}
|
||||
localName = new Name(localHostname, unchecked(0x00), Config.GetProperty("jcifs.netbios.scope"
|
||||
, null));
|
||||
Localhost = new NbtAddress(localName, localInetAddress.GetHashCode(), false, BNode
|
||||
, false, false, true, false, UnknownMacAddress);
|
||||
CacheAddress(localName, Localhost, Forever);
|
||||
}
|
||||
|
||||
internal static void CacheAddress(Name hostName, NbtAddress addr)
|
||||
{
|
||||
if (CachePolicy == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
long expiration = -1;
|
||||
if (CachePolicy != Forever)
|
||||
{
|
||||
expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000;
|
||||
}
|
||||
CacheAddress(hostName, addr, expiration);
|
||||
}
|
||||
|
||||
internal static void CacheAddress(Name hostName, NbtAddress addr, long expiration
|
||||
)
|
||||
{
|
||||
if (CachePolicy == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (AddressCache)
|
||||
{
|
||||
CacheEntry entry = (CacheEntry)AddressCache.Get(hostName);
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new CacheEntry(hostName, addr, expiration);
|
||||
AddressCache.Put(hostName, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.Address = addr;
|
||||
entry.Expiration = expiration;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void CacheAddressArray(NbtAddress[] addrs)
|
||||
{
|
||||
if (CachePolicy == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
long expiration = -1;
|
||||
if (CachePolicy != Forever)
|
||||
{
|
||||
expiration = Runtime.CurrentTimeMillis() + CachePolicy * 1000;
|
||||
}
|
||||
lock (AddressCache)
|
||||
{
|
||||
for (int i = 0; i < addrs.Length; i++)
|
||||
{
|
||||
CacheEntry entry = (CacheEntry)AddressCache.Get(addrs[i].HostName
|
||||
);
|
||||
if (entry == null)
|
||||
{
|
||||
entry = new CacheEntry(addrs[i].HostName, addrs[i], expiration);
|
||||
AddressCache.Put(addrs[i].HostName, entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.Address = addrs[i];
|
||||
entry.Expiration = expiration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static NbtAddress GetCachedAddress(Name hostName)
|
||||
{
|
||||
if (CachePolicy == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
lock (AddressCache)
|
||||
{
|
||||
CacheEntry entry = (CacheEntry)AddressCache.Get(hostName);
|
||||
if (entry != null && entry.Expiration < Runtime.CurrentTimeMillis() && entry.Expiration
|
||||
>= 0)
|
||||
{
|
||||
entry = null;
|
||||
}
|
||||
return entry != null ? entry.Address : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal static NbtAddress DoNameQuery(Name name, IPAddress svr)
|
||||
{
|
||||
NbtAddress addr;
|
||||
if (name.HexCode == unchecked(0x1d) && svr == null)
|
||||
{
|
||||
svr = Client.Baddr;
|
||||
}
|
||||
// bit of a hack but saves a lookup
|
||||
name.SrcHashCode = svr != null ? svr.GetHashCode() : 0;
|
||||
addr = GetCachedAddress(name);
|
||||
if (addr == null)
|
||||
{
|
||||
if ((addr = (NbtAddress)CheckLookupTable(name)) == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
addr = Client.GetByName(name, svr);
|
||||
}
|
||||
catch (UnknownHostException)
|
||||
{
|
||||
addr = UnknownAddress;
|
||||
}
|
||||
finally
|
||||
{
|
||||
CacheAddress(name, addr);
|
||||
UpdateLookupTable(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addr == UnknownAddress)
|
||||
{
|
||||
throw new UnknownHostException(name.ToString());
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
private static object CheckLookupTable(Name name)
|
||||
{
|
||||
object obj;
|
||||
lock (LookupTable)
|
||||
{
|
||||
if (LookupTable.ContainsKey(name) == false)
|
||||
{
|
||||
LookupTable.Put(name, name);
|
||||
return null;
|
||||
}
|
||||
while (LookupTable.ContainsKey(name))
|
||||
{
|
||||
try
|
||||
{
|
||||
Runtime.Wait(LookupTable);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
obj = GetCachedAddress(name);
|
||||
if (obj == null)
|
||||
{
|
||||
lock (LookupTable)
|
||||
{
|
||||
LookupTable.Put(name, name);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static void UpdateLookupTable(Name name)
|
||||
{
|
||||
lock (LookupTable)
|
||||
{
|
||||
//Sharpen.Collections.Remove(LOOKUP_TABLE, name);
|
||||
LookupTable.Remove(name);
|
||||
Runtime.NotifyAll(LookupTable);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the local host address.</summary>
|
||||
/// <remarks>Retrieves the local host address.</remarks>
|
||||
/// <exception cref="UnknownHostException">
|
||||
/// This is not likely as the IP returned
|
||||
/// by <code>InetAddress</code> should be available
|
||||
/// </exception>
|
||||
public static NbtAddress GetLocalHost()
|
||||
{
|
||||
return Localhost;
|
||||
}
|
||||
|
||||
public static NbtAddress[] GetHosts()
|
||||
{
|
||||
return new NameServiceClient().GetHosts();
|
||||
}
|
||||
|
||||
public static Name GetLocalName()
|
||||
{
|
||||
return Localhost.HostName;
|
||||
}
|
||||
|
||||
/// <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 NetBIOS name like
|
||||
/// "freto" or an IP address like "192.168.1.15". It cannot be a DNS name;
|
||||
/// the analygous
|
||||
/// <see cref="SharpCifs.UniAddress">Jcifs.UniAddress</see>
|
||||
/// or
|
||||
/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
|
||||
/// <code>getByName</code> methods can be used for that.
|
||||
/// </remarks>
|
||||
/// <param name="host">hostname to resolve</param>
|
||||
/// <exception cref="UnknownHostException">if there is an error resolving the name
|
||||
/// </exception>
|
||||
public static NbtAddress GetByName(string host)
|
||||
{
|
||||
return GetByName(host, unchecked(0x00), null);
|
||||
}
|
||||
|
||||
/// <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. NetBIOS
|
||||
/// names also have a <code>type</code>. Types(aka Hex Codes)
|
||||
/// are used to distiquish the various services on a host. <a
|
||||
/// href="../../../nbtcodes.html">Here</a> is
|
||||
/// a fairly complete list of NetBIOS hex codes. Scope is not used but is
|
||||
/// still functional in other NetBIOS products and so for completeness it has been
|
||||
/// implemented. A <code>scope</code> of <code>null</code> or <code>""</code>
|
||||
/// signifies no scope.
|
||||
/// </remarks>
|
||||
/// <param name="host">the name to resolve</param>
|
||||
/// <param name="type">the hex code of the name</param>
|
||||
/// <param name="scope">the scope of the name</param>
|
||||
/// <exception cref="UnknownHostException">if there is an error resolving the name
|
||||
/// </exception>
|
||||
public static NbtAddress GetByName(string host, int type, string scope)
|
||||
{
|
||||
return GetByName(host, type, scope, null);
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
public static NbtAddress GetByName(string host, int type, string scope, IPAddress
|
||||
svr)
|
||||
{
|
||||
if (string.IsNullOrEmpty(host))
|
||||
{
|
||||
return GetLocalHost();
|
||||
}
|
||||
if (!char.IsDigit(host[0]))
|
||||
{
|
||||
return DoNameQuery(new Name(host, type, scope), svr);
|
||||
}
|
||||
int ip = unchecked(0x00);
|
||||
int hitDots = 0;
|
||||
char[] data = host.ToCharArray();
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
char c = data[i];
|
||||
if (c < 48 || c > 57)
|
||||
{
|
||||
return DoNameQuery(new Name(host, type, scope), svr);
|
||||
}
|
||||
int b = unchecked(0x00);
|
||||
while (c != '.')
|
||||
{
|
||||
if (c < 48 || c > 57)
|
||||
{
|
||||
return DoNameQuery(new Name(host, type, scope), svr);
|
||||
}
|
||||
b = b * 10 + c - '0';
|
||||
if (++i >= data.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
c = data[i];
|
||||
}
|
||||
if (b > unchecked(0xFF))
|
||||
{
|
||||
return DoNameQuery(new Name(host, type, scope), svr);
|
||||
}
|
||||
ip = (ip << 8) + b;
|
||||
hitDots++;
|
||||
}
|
||||
if (hitDots != 4 || host.EndsWith("."))
|
||||
{
|
||||
return DoNameQuery(new Name(host, type, scope), svr);
|
||||
}
|
||||
return new NbtAddress(UnknownName, ip, false, BNode);
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
public static NbtAddress[] GetAllByName(string host, int type, string scope, IPAddress
|
||||
svr)
|
||||
{
|
||||
return Client.GetAllByName(new Name(host, type, scope), svr);
|
||||
}
|
||||
|
||||
/// <summary>Retrieve all addresses of a host by it's address.</summary>
|
||||
/// <remarks>
|
||||
/// Retrieve all addresses of a host by it's address. NetBIOS hosts can
|
||||
/// have many names for a given IP address. The name and IP address make the
|
||||
/// NetBIOS address. This provides a way to retrieve the other names for a
|
||||
/// host with the same IP address.
|
||||
/// </remarks>
|
||||
/// <param name="host">hostname to lookup all addresses for</param>
|
||||
/// <exception cref="UnknownHostException">if there is an error resolving the name
|
||||
/// </exception>
|
||||
public static NbtAddress[] GetAllByAddress(string host)
|
||||
{
|
||||
return GetAllByAddress(GetByName(host, unchecked(0x00), null));
|
||||
}
|
||||
|
||||
/// <summary>Retrieve all addresses of a host by it's address.</summary>
|
||||
/// <remarks>
|
||||
/// Retrieve all addresses of a host by it's address. NetBIOS hosts can
|
||||
/// have many names for a given IP address. The name and IP address make
|
||||
/// the NetBIOS address. This provides a way to retrieve the other names
|
||||
/// for a host with the same IP address. See
|
||||
/// <see cref="GetByName(string)">GetByName(string)</see>
|
||||
/// for a description of <code>type</code>
|
||||
/// and <code>scope</code>.
|
||||
/// </remarks>
|
||||
/// <param name="host">hostname to lookup all addresses for</param>
|
||||
/// <param name="type">the hexcode of the name</param>
|
||||
/// <param name="scope">the scope of the name</param>
|
||||
/// <exception cref="UnknownHostException">if there is an error resolving the name
|
||||
/// </exception>
|
||||
public static NbtAddress[] GetAllByAddress(string host, int type, string scope)
|
||||
{
|
||||
return GetAllByAddress(GetByName(host, type, scope));
|
||||
}
|
||||
|
||||
/// <summary>Retrieve all addresses of a host by it's address.</summary>
|
||||
/// <remarks>
|
||||
/// Retrieve all addresses of a host by it's address. NetBIOS hosts can
|
||||
/// have many names for a given IP address. The name and IP address make the
|
||||
/// NetBIOS address. This provides a way to retrieve the other names for a
|
||||
/// host with the same IP address.
|
||||
/// </remarks>
|
||||
/// <param name="addr">the address to query</param>
|
||||
/// <exception cref="UnknownHostException">if address cannot be resolved</exception>
|
||||
public static NbtAddress[] GetAllByAddress(NbtAddress addr)
|
||||
{
|
||||
try
|
||||
{
|
||||
NbtAddress[] addrs = Client.GetNodeStatus(addr);
|
||||
CacheAddressArray(addrs);
|
||||
return addrs;
|
||||
}
|
||||
catch (UnknownHostException)
|
||||
{
|
||||
throw new UnknownHostException("no name with type 0x" + Hexdump.ToHexString(addr.
|
||||
HostName.HexCode, 2) + (((addr.HostName.Scope == null) || (addr.HostName.Scope.Length
|
||||
== 0)) ? " with no scope" : " with scope " + addr.HostName.Scope) + " for host "
|
||||
+ addr.GetHostAddress());
|
||||
}
|
||||
}
|
||||
|
||||
public static IPAddress GetWinsAddress()
|
||||
{
|
||||
return Nbns.Length == 0 ? null : Nbns[_nbnsIndex];
|
||||
}
|
||||
|
||||
public static bool IsWins(IPAddress svr)
|
||||
{
|
||||
for (int i = 0; svr != null && i < Nbns.Length; i++)
|
||||
{
|
||||
if (svr.GetHashCode() == Nbns[i].GetHashCode())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static IPAddress SwitchWins()
|
||||
{
|
||||
_nbnsIndex = (_nbnsIndex + 1) < Nbns.Length ? _nbnsIndex + 1 : 0;
|
||||
return Nbns.Length == 0 ? null : Nbns[_nbnsIndex];
|
||||
}
|
||||
|
||||
internal Name HostName;
|
||||
|
||||
internal int Address;
|
||||
|
||||
internal int NodeType;
|
||||
|
||||
internal bool GroupName;
|
||||
|
||||
internal bool isBeingDeleted;
|
||||
|
||||
internal bool isInConflict;
|
||||
|
||||
internal bool isActive;
|
||||
|
||||
internal bool isPermanent;
|
||||
|
||||
internal bool IsDataFromNodeStatus;
|
||||
|
||||
internal byte[] MacAddress;
|
||||
|
||||
internal string CalledName;
|
||||
|
||||
internal NbtAddress(Name hostName, int address, bool groupName, int nodeType)
|
||||
{
|
||||
this.HostName = hostName;
|
||||
this.Address = address;
|
||||
this.GroupName = groupName;
|
||||
this.NodeType = nodeType;
|
||||
}
|
||||
|
||||
internal NbtAddress(Name hostName, int address, bool groupName, int nodeType, bool
|
||||
isBeingDeleted, bool isInConflict, bool isActive, bool isPermanent, byte[] macAddress
|
||||
)
|
||||
{
|
||||
this.HostName = hostName;
|
||||
this.Address = address;
|
||||
this.GroupName = groupName;
|
||||
this.NodeType = nodeType;
|
||||
this.isBeingDeleted = isBeingDeleted;
|
||||
this.isInConflict = isInConflict;
|
||||
this.isActive = isActive;
|
||||
this.isPermanent = isPermanent;
|
||||
this.MacAddress = macAddress;
|
||||
IsDataFromNodeStatus = true;
|
||||
}
|
||||
|
||||
public string FirstCalledName()
|
||||
{
|
||||
CalledName = HostName.name;
|
||||
if (char.IsDigit(CalledName[0]))
|
||||
{
|
||||
int i;
|
||||
int len;
|
||||
int dots;
|
||||
char[] data;
|
||||
i = dots = 0;
|
||||
len = CalledName.Length;
|
||||
data = CalledName.ToCharArray();
|
||||
while (i < len && char.IsDigit(data[i++]))
|
||||
{
|
||||
if (i == len && dots == 3)
|
||||
{
|
||||
// probably an IP address
|
||||
CalledName = SmbserverName;
|
||||
break;
|
||||
}
|
||||
if (i < len && data[i] == '.')
|
||||
{
|
||||
dots++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (HostName.HexCode)
|
||||
{
|
||||
case unchecked(0x1B):
|
||||
case unchecked(0x1C):
|
||||
case unchecked(0x1D):
|
||||
{
|
||||
CalledName = SmbserverName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return CalledName;
|
||||
}
|
||||
|
||||
public string NextCalledName()
|
||||
{
|
||||
if (CalledName == HostName.name)
|
||||
{
|
||||
CalledName = SmbserverName;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CalledName == SmbserverName)
|
||||
{
|
||||
NbtAddress[] addrs;
|
||||
try
|
||||
{
|
||||
addrs = Client.GetNodeStatus(this);
|
||||
if (HostName.HexCode == unchecked(0x1D))
|
||||
{
|
||||
for (int i = 0; i < addrs.Length; i++)
|
||||
{
|
||||
if (addrs[i].HostName.HexCode == unchecked(0x20))
|
||||
{
|
||||
return addrs[i].HostName.name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (IsDataFromNodeStatus)
|
||||
{
|
||||
CalledName = null;
|
||||
return HostName.name;
|
||||
}
|
||||
}
|
||||
catch (UnknownHostException)
|
||||
{
|
||||
CalledName = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CalledName = null;
|
||||
}
|
||||
}
|
||||
return CalledName;
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal void CheckData()
|
||||
{
|
||||
if (HostName == UnknownName)
|
||||
{
|
||||
GetAllByAddress(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
internal void CheckNodeStatusData()
|
||||
{
|
||||
if (IsDataFromNodeStatus == false)
|
||||
{
|
||||
GetAllByAddress(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Determines if the address is a group address.</summary>
|
||||
/// <remarks>
|
||||
/// Determines if the address is a group address. This is also
|
||||
/// known as a workgroup name or group name.
|
||||
/// </remarks>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public bool IsGroupAddress()
|
||||
{
|
||||
CheckData();
|
||||
return GroupName;
|
||||
}
|
||||
|
||||
/// <summary>Checks the node type of this address.</summary>
|
||||
/// <remarks>Checks the node type of this address.</remarks>
|
||||
/// <returns>
|
||||
///
|
||||
/// <see cref="BNode">B_NODE</see>
|
||||
/// ,
|
||||
/// <see cref="PNode">P_NODE</see>
|
||||
/// ,
|
||||
/// <see cref="MNode">M_NODE</see>
|
||||
/// ,
|
||||
/// <see cref="HNode">H_NODE</see>
|
||||
/// </returns>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public int GetNodeType()
|
||||
{
|
||||
CheckData();
|
||||
return NodeType;
|
||||
}
|
||||
|
||||
/// <summary>Determines if this address in the process of being deleted.</summary>
|
||||
/// <remarks>Determines if this address in the process of being deleted.</remarks>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public bool IsBeingDeleted()
|
||||
{
|
||||
CheckNodeStatusData();
|
||||
return isBeingDeleted;
|
||||
}
|
||||
|
||||
/// <summary>Determines if this address in conflict with another address.</summary>
|
||||
/// <remarks>Determines if this address in conflict with another address.</remarks>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public bool IsInConflict()
|
||||
{
|
||||
CheckNodeStatusData();
|
||||
return isInConflict;
|
||||
}
|
||||
|
||||
/// <summary>Determines if this address is active.</summary>
|
||||
/// <remarks>Determines if this address is active.</remarks>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public bool IsActive()
|
||||
{
|
||||
CheckNodeStatusData();
|
||||
return isActive;
|
||||
}
|
||||
|
||||
/// <summary>Determines if this address is set to be permanent.</summary>
|
||||
/// <remarks>Determines if this address is set to be permanent.</remarks>
|
||||
/// <exception cref="UnknownHostException">if the host cannot be resolved to find out.
|
||||
/// </exception>
|
||||
public bool IsPermanent()
|
||||
{
|
||||
CheckNodeStatusData();
|
||||
return isPermanent;
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the MAC address of the remote network interface.</summary>
|
||||
/// <remarks>Retrieves the MAC address of the remote network interface. Samba returns all zeros.
|
||||
/// </remarks>
|
||||
/// <returns>the MAC address as an array of six bytes</returns>
|
||||
/// <exception cref="UnknownHostException">
|
||||
/// if the host cannot be resolved to
|
||||
/// determine the MAC address.
|
||||
/// </exception>
|
||||
public byte[] GetMacAddress()
|
||||
{
|
||||
CheckNodeStatusData();
|
||||
return MacAddress;
|
||||
}
|
||||
|
||||
/// <summary>The hostname of this address.</summary>
|
||||
/// <remarks>
|
||||
/// The hostname of this address. If the hostname is null the local machines
|
||||
/// IP address is returned.
|
||||
/// </remarks>
|
||||
/// <returns>the text representation of the hostname associated with this address</returns>
|
||||
public string GetHostName()
|
||||
{
|
||||
if (HostName == UnknownName)
|
||||
{
|
||||
return GetHostAddress();
|
||||
}
|
||||
return HostName.name;
|
||||
}
|
||||
|
||||
/// <summary>Returns the raw IP address of this NbtAddress.</summary>
|
||||
/// <remarks>
|
||||
/// Returns the raw IP address of this NbtAddress. The result is in network
|
||||
/// byte order: the highest order byte of the address is in getAddress()[0].
|
||||
/// </remarks>
|
||||
/// <returns>a four byte array</returns>
|
||||
public byte[] GetAddress()
|
||||
{
|
||||
byte[] addr = new byte[4];
|
||||
addr[0] = unchecked((byte)(((int)(((uint)Address) >> 24)) & unchecked(0xFF
|
||||
)));
|
||||
addr[1] = unchecked((byte)(((int)(((uint)Address) >> 16)) & unchecked(0xFF
|
||||
)));
|
||||
addr[2] = unchecked((byte)(((int)(((uint)Address) >> 8)) & unchecked(0xFF)
|
||||
));
|
||||
addr[3] = unchecked((byte)(Address & unchecked(0xFF)));
|
||||
return addr;
|
||||
}
|
||||
|
||||
/// <summary>To convert this address to an <code>InetAddress</code>.</summary>
|
||||
/// <remarks>To convert this address to an <code>InetAddress</code>.</remarks>
|
||||
/// <returns>
|
||||
/// the
|
||||
/// <see cref="System.Net.IPAddress">System.Net.IPAddress</see>
|
||||
/// representation of this address.
|
||||
/// </returns>
|
||||
/// <exception cref="UnknownHostException"></exception>
|
||||
public IPAddress GetInetAddress()
|
||||
{
|
||||
return Extensions.GetAddressByName(GetHostAddress());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns this IP adress as a
|
||||
/// <see cref="string">string</see>
|
||||
/// in the form "%d.%d.%d.%d".
|
||||
/// </summary>
|
||||
public string GetHostAddress()
|
||||
{
|
||||
return (((int)(((uint)Address) >> 24)) & unchecked(0xFF)) + "." + (((int)(
|
||||
((uint)Address) >> 16)) & unchecked(0xFF)) + "." + (((int)(((uint)Address
|
||||
) >> 8)) & unchecked(0xFF)) + "." + (((int)(((uint)Address) >> 0)) & unchecked(
|
||||
0xFF));
|
||||
}
|
||||
|
||||
/// <summary>Returned the hex code associated with this name(e.g.</summary>
|
||||
/// <remarks>Returned the hex code associated with this name(e.g. 0x20 is for the file service)
|
||||
/// </remarks>
|
||||
public int GetNameType()
|
||||
{
|
||||
return HostName.HexCode;
|
||||
}
|
||||
|
||||
/// <summary>Returns a hashcode for this IP address.</summary>
|
||||
/// <remarks>
|
||||
/// Returns a hashcode for this IP address. The hashcode comes from the IP address
|
||||
/// and is not generated from the string representation. So because NetBIOS nodes
|
||||
/// can have many names, all names associated with an IP will have the same
|
||||
/// hashcode.
|
||||
/// </remarks>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Address;
|
||||
}
|
||||
|
||||
/// <summary>Determines if this address is equal two another.</summary>
|
||||
/// <remarks>
|
||||
/// Determines if this address is equal two another. Only the IP Addresses
|
||||
/// are compared. Similar to the
|
||||
/// <see cref="GetHashCode()">GetHashCode()</see>
|
||||
/// method, the comparison
|
||||
/// is based on the integer IP address and not the string representation.
|
||||
/// </remarks>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj != null) && (obj is NbtAddress) && (((NbtAddress)obj).Address == Address
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the
|
||||
/// <see cref="string">string</see>
|
||||
/// representaion of this address.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return HostName + "/" + GetHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
164
Emby.Server.Implementations/IO/SharpCifs/Netbios/NbtException.cs
Normal file
164
Emby.Server.Implementations/IO/SharpCifs/Netbios/NbtException.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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.IO;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
|
||||
public class NbtException : IOException
|
||||
{
|
||||
public const int Success = 0;
|
||||
|
||||
public const int ErrNamSrvc = unchecked(0x01);
|
||||
|
||||
public const int ErrSsnSrvc = unchecked(0x02);
|
||||
|
||||
public const int FmtErr = unchecked(0x1);
|
||||
|
||||
public const int SrvErr = unchecked(0x2);
|
||||
|
||||
public const int ImpErr = unchecked(0x4);
|
||||
|
||||
public const int RfsErr = unchecked(0x5);
|
||||
|
||||
public const int ActErr = unchecked(0x6);
|
||||
|
||||
public const int CftErr = unchecked(0x7);
|
||||
|
||||
public const int ConnectionRefused = -1;
|
||||
|
||||
public const int NotListeningCalled = unchecked(0x80);
|
||||
|
||||
public const int NotListeningCalling = unchecked(0x81);
|
||||
|
||||
public const int CalledNotPresent = unchecked(0x82);
|
||||
|
||||
public const int NoResources = unchecked(0x83);
|
||||
|
||||
public const int Unspecified = unchecked(0x8F);
|
||||
|
||||
public int ErrorClass;
|
||||
|
||||
public int ErrorCode;
|
||||
|
||||
// error classes
|
||||
// name service error codes
|
||||
// session service error codes
|
||||
public static string GetErrorString(int errorClass, int errorCode)
|
||||
{
|
||||
string result = string.Empty;
|
||||
switch (errorClass)
|
||||
{
|
||||
case Success:
|
||||
{
|
||||
result += "SUCCESS";
|
||||
break;
|
||||
}
|
||||
|
||||
case ErrNamSrvc:
|
||||
{
|
||||
result += "ERR_NAM_SRVC/";
|
||||
switch (errorCode)
|
||||
{
|
||||
case FmtErr:
|
||||
{
|
||||
result += "FMT_ERR: Format Error";
|
||||
goto default;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
result += "Unknown error code: " + errorCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ErrSsnSrvc:
|
||||
{
|
||||
result += "ERR_SSN_SRVC/";
|
||||
switch (errorCode)
|
||||
{
|
||||
case ConnectionRefused:
|
||||
{
|
||||
result += "Connection refused";
|
||||
break;
|
||||
}
|
||||
|
||||
case NotListeningCalled:
|
||||
{
|
||||
result += "Not listening on called name";
|
||||
break;
|
||||
}
|
||||
|
||||
case NotListeningCalling:
|
||||
{
|
||||
result += "Not listening for calling name";
|
||||
break;
|
||||
}
|
||||
|
||||
case CalledNotPresent:
|
||||
{
|
||||
result += "Called name not present";
|
||||
break;
|
||||
}
|
||||
|
||||
case NoResources:
|
||||
{
|
||||
result += "Called name present, but insufficient resources";
|
||||
break;
|
||||
}
|
||||
|
||||
case Unspecified:
|
||||
{
|
||||
result += "Unspecified error";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
result += "Unknown error code: " + errorCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
result += "unknown error class: " + errorClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public NbtException(int errorClass, int errorCode) : base(GetErrorString(errorClass
|
||||
, errorCode))
|
||||
{
|
||||
this.ErrorClass = errorClass;
|
||||
this.ErrorCode = errorCode;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "errorClass=" + ErrorClass + ",errorCode=" + ErrorCode + ",errorString="
|
||||
+ GetErrorString(ErrorClass, ErrorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// 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
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class NodeStatusRequest : NameServicePacket
|
||||
{
|
||||
internal NodeStatusRequest(Name name)
|
||||
{
|
||||
QuestionName = name;
|
||||
QuestionType = Nbstat;
|
||||
IsRecurDesired = false;
|
||||
IsBroadcast = false;
|
||||
}
|
||||
|
||||
internal override int WriteBodyWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int tmp = QuestionName.HexCode;
|
||||
QuestionName.HexCode = unchecked(0x00);
|
||||
// type has to be 0x00 for node status
|
||||
int result = WriteQuestionSectionWireFormat(dst, dstIndex);
|
||||
QuestionName.HexCode = tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override int ReadBodyWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int WriteRDataWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadRDataWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "NodeStatusRequest[" + base.ToString() + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
// 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 SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class NodeStatusResponse : NameServicePacket
|
||||
{
|
||||
private NbtAddress _queryAddress;
|
||||
|
||||
private int _numberOfNames;
|
||||
|
||||
private byte[] _macAddress;
|
||||
|
||||
private byte[] _stats;
|
||||
|
||||
internal NbtAddress[] AddressArray;
|
||||
|
||||
internal NodeStatusResponse(NbtAddress queryAddress)
|
||||
{
|
||||
this._queryAddress = queryAddress;
|
||||
RecordName = new Name();
|
||||
_macAddress = new byte[6];
|
||||
}
|
||||
|
||||
internal override int WriteBodyWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadBodyWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
return ReadResourceRecordWireFormat(src, srcIndex);
|
||||
}
|
||||
|
||||
internal override int WriteRDataWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal override int ReadRDataWireFormat(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
_numberOfNames = src[srcIndex] & unchecked(0xFF);
|
||||
int namesLength = _numberOfNames * 18;
|
||||
int statsLength = RDataLength - namesLength - 1;
|
||||
_numberOfNames = src[srcIndex++] & unchecked(0xFF);
|
||||
// gotta read the mac first so we can populate addressArray with it
|
||||
Array.Copy(src, srcIndex + namesLength, _macAddress, 0, 6);
|
||||
srcIndex += ReadNodeNameArray(src, srcIndex);
|
||||
_stats = new byte[statsLength];
|
||||
Array.Copy(src, srcIndex, _stats, 0, statsLength);
|
||||
srcIndex += statsLength;
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
private int ReadNodeNameArray(byte[] src, int srcIndex)
|
||||
{
|
||||
int start = srcIndex;
|
||||
AddressArray = new NbtAddress[_numberOfNames];
|
||||
string n;
|
||||
int hexCode;
|
||||
string scope = _queryAddress.HostName.Scope;
|
||||
bool groupName;
|
||||
int ownerNodeType;
|
||||
bool isBeingDeleted;
|
||||
bool isInConflict;
|
||||
bool isActive;
|
||||
bool isPermanent;
|
||||
int j;
|
||||
bool addrFound = false;
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < _numberOfNames; srcIndex += 18, i++)
|
||||
{
|
||||
for (j = srcIndex + 14; src[j] == unchecked(0x20); j--)
|
||||
{
|
||||
}
|
||||
n = Runtime.GetStringForBytes(src, srcIndex, j - srcIndex + 1, Name.OemEncoding
|
||||
);
|
||||
hexCode = src[srcIndex + 15] & unchecked(0xFF);
|
||||
groupName = ((src[srcIndex + 16] & unchecked(0x80)) == unchecked(0x80)) ? true : false;
|
||||
ownerNodeType = (src[srcIndex + 16] & unchecked(0x60)) >> 5;
|
||||
isBeingDeleted = ((src[srcIndex + 16] & unchecked(0x10)) == unchecked(0x10)) ? true : false;
|
||||
isInConflict = ((src[srcIndex + 16] & unchecked(0x08)) == unchecked(0x08)) ? true : false;
|
||||
isActive = ((src[srcIndex + 16] & unchecked(0x04)) == unchecked(0x04)) ? true : false;
|
||||
isPermanent = ((src[srcIndex + 16] & unchecked(0x02)) == unchecked(0x02)) ? true : false;
|
||||
if (!addrFound && _queryAddress.HostName.HexCode == hexCode && (_queryAddress.HostName
|
||||
== NbtAddress.UnknownName || _queryAddress.HostName.name.Equals(n)))
|
||||
{
|
||||
if (_queryAddress.HostName == NbtAddress.UnknownName)
|
||||
{
|
||||
_queryAddress.HostName = new Name(n, hexCode, scope);
|
||||
}
|
||||
_queryAddress.GroupName = groupName;
|
||||
_queryAddress.NodeType = ownerNodeType;
|
||||
_queryAddress.isBeingDeleted = isBeingDeleted;
|
||||
_queryAddress.isInConflict = isInConflict;
|
||||
_queryAddress.isActive = isActive;
|
||||
_queryAddress.isPermanent = isPermanent;
|
||||
_queryAddress.MacAddress = _macAddress;
|
||||
_queryAddress.IsDataFromNodeStatus = true;
|
||||
addrFound = true;
|
||||
AddressArray[i] = _queryAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressArray[i] = new NbtAddress(new Name(n, hexCode, scope), _queryAddress.Address
|
||||
, groupName, ownerNodeType, isBeingDeleted, isInConflict, isActive, isPermanent,
|
||||
_macAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnsupportedEncodingException)
|
||||
{
|
||||
}
|
||||
return srcIndex - start;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "NodeStatusResponse[" + base.ToString() + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// 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.IO;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
public class SessionRequestPacket : SessionServicePacket
|
||||
{
|
||||
private Name _calledName;
|
||||
|
||||
private Name _callingName;
|
||||
|
||||
public SessionRequestPacket()
|
||||
{
|
||||
_calledName = new Name();
|
||||
_callingName = new Name();
|
||||
}
|
||||
|
||||
public SessionRequestPacket(Name calledName, Name callingName)
|
||||
{
|
||||
Type = SessionRequest;
|
||||
this._calledName = calledName;
|
||||
this._callingName = callingName;
|
||||
}
|
||||
|
||||
internal override int WriteTrailerWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
int start = dstIndex;
|
||||
dstIndex += _calledName.WriteWireFormat(dst, dstIndex);
|
||||
dstIndex += _callingName.WriteWireFormat(dst, dstIndex);
|
||||
return dstIndex - start;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal override int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex
|
||||
)
|
||||
{
|
||||
int start = bufferIndex;
|
||||
if (@in.Read(buffer, bufferIndex, Length) != Length)
|
||||
{
|
||||
throw new IOException("invalid session request wire format");
|
||||
}
|
||||
bufferIndex += _calledName.ReadWireFormat(buffer, bufferIndex);
|
||||
bufferIndex += _callingName.ReadWireFormat(buffer, bufferIndex);
|
||||
return bufferIndex - start;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// 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.IO;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
internal class SessionRetargetResponsePacket : SessionServicePacket
|
||||
{
|
||||
private NbtAddress _retargetAddress;
|
||||
|
||||
private int _retargetPort;
|
||||
|
||||
public SessionRetargetResponsePacket()
|
||||
{
|
||||
Type = SessionRetargetResponse;
|
||||
Length = 6;
|
||||
}
|
||||
|
||||
internal override int WriteTrailerWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal override int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex
|
||||
)
|
||||
{
|
||||
if (@in.Read(buffer, bufferIndex, Length) != Length)
|
||||
{
|
||||
throw new IOException("unexpected EOF reading netbios retarget session response");
|
||||
}
|
||||
int addr = ReadInt4(buffer, bufferIndex);
|
||||
bufferIndex += 4;
|
||||
_retargetAddress = new NbtAddress(null, addr, false, NbtAddress.BNode);
|
||||
_retargetPort = ReadInt2(buffer, bufferIndex);
|
||||
return Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// 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.IO;
|
||||
using SharpCifs.Util.Sharpen;
|
||||
|
||||
namespace SharpCifs.Netbios
|
||||
{
|
||||
public abstract class SessionServicePacket
|
||||
{
|
||||
internal const int SessionMessage = unchecked(0x00);
|
||||
|
||||
internal const int SessionRequest = unchecked(0x81);
|
||||
|
||||
public const int PositiveSessionResponse = unchecked(0x82);
|
||||
|
||||
public const int NegativeSessionResponse = unchecked(0x83);
|
||||
|
||||
internal const int SessionRetargetResponse = unchecked(0x84);
|
||||
|
||||
internal const int SessionKeepAlive = unchecked(0x85);
|
||||
|
||||
internal const int MaxMessageSize = unchecked(0x0001FFFF);
|
||||
|
||||
internal const int HeaderLength = 4;
|
||||
|
||||
// session service packet types
|
||||
internal static void WriteInt2(int val, byte[] dst, int dstIndex)
|
||||
{
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
|
||||
dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
|
||||
}
|
||||
|
||||
internal static void WriteInt4(int val, byte[] dst, int dstIndex)
|
||||
{
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 24) & unchecked(0xFF)));
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 16) & unchecked(0xFF)));
|
||||
dst[dstIndex++] = unchecked((byte)((val >> 8) & unchecked(0xFF)));
|
||||
dst[dstIndex] = unchecked((byte)(val & unchecked(0xFF)));
|
||||
}
|
||||
|
||||
internal static int ReadInt2(byte[] src, int srcIndex)
|
||||
{
|
||||
return ((src[srcIndex] & unchecked(0xFF)) << 8) + (src[srcIndex + 1] & unchecked(
|
||||
0xFF));
|
||||
}
|
||||
|
||||
internal static int ReadInt4(byte[] src, int srcIndex)
|
||||
{
|
||||
return ((src[srcIndex] & unchecked(0xFF)) << 24) + ((src[srcIndex + 1] & unchecked(
|
||||
0xFF)) << 16) + ((src[srcIndex + 2] & unchecked(0xFF)) << 8) + (src
|
||||
[srcIndex + 3] & unchecked(0xFF));
|
||||
}
|
||||
|
||||
internal static int ReadLength(byte[] src, int srcIndex)
|
||||
{
|
||||
srcIndex++;
|
||||
return ((src[srcIndex++] & unchecked(0x01)) << 16) + ((src[srcIndex++] & unchecked(
|
||||
0xFF)) << 8) + (src[srcIndex++] & unchecked(0xFF));
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal static int Readn(InputStream @in, byte[] b, int off, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int n;
|
||||
while (i < len)
|
||||
{
|
||||
n = @in.Read(b, off + i, len - i);
|
||||
if (n <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal static int ReadPacketType(InputStream @in, byte[] buffer, int bufferIndex
|
||||
)
|
||||
{
|
||||
int n;
|
||||
if ((n = Readn(@in, buffer, bufferIndex, HeaderLength)) != HeaderLength)
|
||||
{
|
||||
if (n == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
throw new IOException("unexpected EOF reading netbios session header");
|
||||
}
|
||||
int t = buffer[bufferIndex] & unchecked(0xFF);
|
||||
return t;
|
||||
}
|
||||
|
||||
internal int Type;
|
||||
|
||||
internal int Length;
|
||||
|
||||
public virtual int WriteWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
Length = WriteTrailerWireFormat(dst, dstIndex + HeaderLength);
|
||||
WriteHeaderWireFormat(dst, dstIndex);
|
||||
return HeaderLength + Length;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal virtual int ReadWireFormat(InputStream @in, byte[] buffer, int bufferIndex
|
||||
)
|
||||
{
|
||||
ReadHeaderWireFormat(@in, buffer, bufferIndex);
|
||||
return HeaderLength + ReadTrailerWireFormat(@in, buffer, bufferIndex);
|
||||
}
|
||||
|
||||
internal virtual int WriteHeaderWireFormat(byte[] dst, int dstIndex)
|
||||
{
|
||||
dst[dstIndex++] = unchecked((byte)Type);
|
||||
if (Length > unchecked(0x0000FFFF))
|
||||
{
|
||||
dst[dstIndex] = unchecked(unchecked(0x01));
|
||||
}
|
||||
dstIndex++;
|
||||
WriteInt2(Length, dst, dstIndex);
|
||||
return HeaderLength;
|
||||
}
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal virtual int ReadHeaderWireFormat(InputStream @in, byte[] buffer, int bufferIndex
|
||||
)
|
||||
{
|
||||
Type = buffer[bufferIndex++] & unchecked(0xFF);
|
||||
Length = ((buffer[bufferIndex] & unchecked(0x01)) << 16) + ReadInt2(buffer
|
||||
, bufferIndex + 1);
|
||||
return HeaderLength;
|
||||
}
|
||||
|
||||
internal abstract int WriteTrailerWireFormat(byte[] dst, int dstIndex);
|
||||
|
||||
/// <exception cref="System.IO.IOException"></exception>
|
||||
internal abstract int ReadTrailerWireFormat(InputStream @in, byte[] buffer, int bufferIndex
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user