diff options
Diffstat (limited to 'Emby.Common.Implementations/IO/SharpCifs/Netbios')
13 files changed, 2548 insertions, 2283 deletions
diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs index c94d0a260..7d8dd8bbf 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Lmhosts.cs @@ -21,182 +21,181 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - public class Lmhosts - { - private static readonly string Filename = Config.GetProperty("jcifs.netbios.lmhosts" - ); + public class Lmhosts + { + private static readonly string Filename = Config.GetProperty("jcifs.netbios.lmhosts"); - private static readonly Hashtable Tab = new Hashtable(); + private static readonly Hashtable Tab = new Hashtable(); - private static long _lastModified = 1L; + private static long _lastModified = 1L; - private static int _alt; + private static int _alt; - private static LogStream _log = LogStream.GetInstance(); + 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)); - } - } + /// <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)); + 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; - } - } + } + 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; + /// <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); - } - } - } - } - } - } + 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); + } + } + } + } + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs index 6c37d57a4..4166e1af8 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/Name.cs @@ -21,102 +21,110 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - public class Name - { - private const int TypeOffset = 31; + public class Name + { + private const int TypeOffset = 31; - private const int ScopeOffset = 33; + private const int ScopeOffset = 33; - private static readonly string DefaultScope = Config.GetProperty("jcifs.netbios.scope" - ); + private static readonly string DefaultScope + = Config.GetProperty("jcifs.netbios.scope"); - internal static readonly string OemEncoding = Config.GetProperty("jcifs.encoding" - , Runtime.GetProperty("file.encoding")); + internal static readonly string OemEncoding + = Config.GetProperty("jcifs.encoding", Runtime.GetProperty("file.encoding")); - public string name; + public string name; - public string Scope; + public string Scope; - public int HexCode; + public int HexCode; - internal int SrcHashCode; + internal int SrcHashCode; - public Name() - { - } + 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; - } + 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 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 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) { @@ -130,9 +138,8 @@ namespace SharpCifs.Netbios { name = Runtime.GetStringForBytes(tmp, 0, length).Trim(); } - catch (Exception ex) + catch (Exception) { - } HexCode = src[srcIndex + length]; @@ -141,129 +148,129 @@ namespace SharpCifs.Netbios } - 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 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; - } + 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 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 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(); + public override string ToString() + { + StringBuilder sb = new StringBuilder(); - //return ""; + //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(); - } - } + 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(); + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs index 646e65bf8..1e9419638 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryRequest.cs @@ -16,37 +16,37 @@ // 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 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 WriteBodyWireFormat(byte[] dst, int dstIndex) + { + return WriteQuestionSectionWireFormat(dst, dstIndex); + } - internal override int ReadBodyWireFormat(byte[] src, int srcIndex) - { - return ReadQuestionSectionWireFormat(src, srcIndex); - } + 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 WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } - internal override int ReadRDataWireFormat(byte[] src, int srcIndex) - { - return 0; - } + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + return 0; + } - public override string ToString() - { - return "NameQueryRequest[" + base.ToString() + "]"; - } - } + public override string ToString() + { + return "NameQueryRequest[" + base.ToString() + "]"; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs index c7fac8e93..2285c6e7b 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameQueryResponse.cs @@ -16,53 +16,52 @@ // 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 class NameQueryResponse : NameServicePacket + { + public NameQueryResponse() + { + RecordName = new Name(); + } - internal override int WriteBodyWireFormat(byte[] dst, int dstIndex) - { - return 0; - } + 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 ReadBodyWireFormat(byte[] src, int srcIndex) + { + return ReadResourceRecordWireFormat(src, srcIndex); + } - internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) - { - return 0; - } + 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; - } + 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 - + "]"; - } - } + public override string ToString() + { + return "NameQueryResponse[" + base.ToString() + ",addrEntry=" + AddrEntry + "]"; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs index 01700e64a..fb74c691b 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServiceClient.cs @@ -21,10 +21,13 @@ using System.Net; using System.Net.Sockets; using System.Linq; using System.Threading; +using SharpCifs.Smb; using SharpCifs.Util; +using SharpCifs.Util.DbsHelper; using SharpCifs.Util.Sharpen; using Thread = SharpCifs.Util.Sharpen.Thread; +using System.Threading.Tasks; namespace SharpCifs.Netbios { @@ -48,27 +51,29 @@ namespace SharpCifs.Netbios internal const int ResolverWins = 3; - private static readonly int SndBufSize = Config.GetInt("jcifs.netbios.snd_buf_size" - , DefaultSndBufSize); + 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 RcvBufSize + = Config.GetInt("jcifs.netbios.rcv_buf_size", DefaultRcvBufSize); - private static readonly int SoTimeout = Config.GetInt("jcifs.netbios.soTimeout", - DefaultSoTimeout); + 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 RetryCount + = Config.GetInt("jcifs.netbios.retryCount", DefaultRetryCount); - private static readonly int RetryTimeout = Config.GetInt("jcifs.netbios.retryTimeout" - , DefaultRetryTimeout); + 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 int Lport + = Config.GetInt("jcifs.netbios.lport", 137); - private static readonly IPAddress Laddr = Config.GetInetAddress("jcifs.netbios.laddr" - , null); + private static readonly IPAddress Laddr + = Config.GetInetAddress("jcifs.netbios.laddr", null); - private static readonly string Ro = Config.GetProperty("jcifs.resolveOrder"); + private static readonly string Ro + = Config.GetProperty("jcifs.resolveOrder"); private static LogStream _log = LogStream.GetInstance(); @@ -82,18 +87,20 @@ namespace SharpCifs.Netbios private byte[] _rcvBuf; - private SocketEx _socket; + private SocketEx _socketSender; private Hashtable _responseTable = new Hashtable(); private Thread _thread; - + private int _nextNameTrnId; private int[] _resolveOrder; private bool _waitResponse = true; + private bool _isActive = false; + private AutoResetEvent _autoResetWaitReceive; internal IPAddress laddr; @@ -109,13 +116,17 @@ namespace SharpCifs.Netbios { this._lport = lport; - this.laddr = laddr - ?? Config.GetLocalHost() - ?? Extensions.GetAddressesByName(Dns.GetHostName()).FirstOrDefault(); + this.laddr = laddr + ?? Config.GetLocalHost() + ?? Extensions.GetLocalAddresses()?.FirstOrDefault(); + + if (this.laddr == null) + throw new ArgumentNullException("IPAddress NOT found. if exec on localhost, set vallue to [jcifs.smb.client.laddr]"); try { - Baddr = Config.GetInetAddress("jcifs.netbios.baddr", Extensions.GetAddressByName("255.255.255.255")); + Baddr = Config.GetInetAddress("jcifs.netbios.baddr", + Extensions.GetAddressByName("255.255.255.255")); } catch (Exception ex) { @@ -161,8 +172,8 @@ namespace SharpCifs.Netbios { if (_log.Level > 1) { - _log.WriteLine("NetBIOS resolveOrder specifies WINS however the " + "jcifs.netbios.wins property has not been set" - ); + _log.WriteLine("NetBIOS resolveOrder specifies WINS however the " + + "jcifs.netbios.wins property has not been set"); } continue; } @@ -208,53 +219,93 @@ namespace SharpCifs.Netbios /// <exception cref="System.IO.IOException"></exception> internal virtual void EnsureOpen(int timeout) { + //Log.Out($"NameServiceClient.EnsureOpen"); + _closeTimeout = 0; if (SoTimeout != 0) { _closeTimeout = Math.Max(SoTimeout, timeout); } + + var localPort = (SmbConstants.Lport == 0) ? _lport : SmbConstants.Lport; + // If socket is still good, the new closeTimeout will // be ignored; see tryClose comment. - if (_socket == null) + if ( + _socketSender == null + || _socketSender.LocalEndPoint == null + || _socketSender.GetLocalPort() != localPort + || !IPAddress.Any.Equals(_socketSender.GetLocalInetAddress()) + ) { - _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 (_socketSender != null) + { + _socketSender.Dispose(); + _socketSender = null; + } + + _socketSender = new SocketEx(AddressFamily.InterNetwork, + SocketType.Dgram, + ProtocolType.Udp); + + _socketSender.Bind(new IPEndPoint(IPAddress.Any, localPort)); + if (_waitResponse) { - _thread = new Thread(this); //new Sharpen.Thread(this, "JCIFS-NameServiceClient"); + if (_thread != null) + { + _thread.Cancel(true); + _thread.Dispose(); + } + + _thread = new Thread(this); _thread.SetDaemon(true); - _thread.Start(); + _thread.Start(true); } } } internal virtual void TryClose() { + //Log.Out("NameSerciceClient.TryClose"); + + if (this._isActive) + { + //Log.Out("NameSerciceClient.TryClose - Now in Processing... Exit."); + return; + } + lock (_lock) { - if (_socket != null) + if (_socketSender != null) { - //Socket.`Close` method deleted - //_socket.Close(); - _socket.Dispose(); - _socket = null; + _socketSender.Dispose(); + _socketSender = null; + //Log.Out("NameSerciceClient.TryClose - _socketSender.Disposed"); + } + + if (_thread != null) + { + _thread.Cancel(true); + _thread.Dispose(); + _thread = null; + //Log.Out("NameSerciceClient.TryClose - _thread.Aborted"); } - _thread = null; if (_waitResponse) { _responseTable.Clear(); - } else + } + else { _autoResetWaitReceive.Set(); } } } + + private int _recievedLength = -1; public virtual void Run() { int nameTrnId; @@ -262,12 +313,38 @@ namespace SharpCifs.Netbios try { - - while (_thread == Thread.CurrentThread()) + while (Thread.CurrentThread().Equals(_thread)) { - _socket.SoTimeOut = _closeTimeout; + if (_thread.IsCanceled) + break; + + var localPort = (SmbConstants.Lport == 0) ? _lport : SmbConstants.Lport; + + var sockEvArg = new SocketAsyncEventArgs(); + sockEvArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, localPort); + sockEvArg.SetBuffer(_rcvBuf, 0, RcvBufSize); + sockEvArg.Completed += this.OnReceiveCompleted; + + _socketSender.SoTimeOut = _closeTimeout; + + this._recievedLength = -1; + + //Log.Out($"NameServiceClient.Run - Wait Recieve: {IPAddress.Any}: {localPort}"); + _socketSender.ReceiveFromAsync(sockEvArg); + + while (this._recievedLength == -1) + { + if (_thread.IsCanceled) + break; + + Task.Delay(300).GetAwaiter().GetResult(); + } + + sockEvArg?.Dispose(); - int len = _socket.Receive(_rcvBuf, 0, RcvBufSize); + + if (_thread.IsCanceled) + break; if (_log.Level > 3) { @@ -284,12 +361,15 @@ namespace SharpCifs.Netbios lock (response) { + if (_thread.IsCanceled) + break; + response.ReadWireFormat(_rcvBuf, 0); if (_log.Level > 3) { _log.WriteLine(response); - Hexdump.ToHexdump(_log, _rcvBuf, 0, len); + Hexdump.ToHexdump(_log, _rcvBuf, 0, this._recievedLength); } if (response.IsResponse) @@ -300,7 +380,6 @@ namespace SharpCifs.Netbios } } } - } catch (TimeoutException) { } catch (Exception ex) @@ -316,10 +395,21 @@ namespace SharpCifs.Netbios } } + + private void OnReceiveCompleted(object sender, SocketAsyncEventArgs e) + { + //Log.Out("NameServiceClient.OnReceiveCompleted"); + this._recievedLength = e.BytesTransferred; + } + + /// <exception cref="System.IO.IOException"></exception> - internal virtual void Send(NameServicePacket request, NameServicePacket response, - int timeout) + internal virtual void Send(NameServicePacket request, + NameServicePacket response, + int timeout) { + //Log.Out("NameSerciceClient.Send - Start"); + int nid = 0; int max = NbtAddress.Nbns.Length; if (max == 0) @@ -329,6 +419,7 @@ namespace SharpCifs.Netbios lock (response) { + this._isActive = true; while (max-- > 0) { @@ -338,45 +429,75 @@ namespace SharpCifs.Netbios { request.NameTrnId = GetNextNameTrnId(); nid = request.NameTrnId; + response.Received = false; _responseTable.Put(nid, response); + + //Log.Out($"NameSerciceClient.Send - timeout = {timeout}"); EnsureOpen(timeout + 1000); + int requestLenght = request.WriteWireFormat(_sndBuf, 0); - _socket.Send(_sndBuf, 0, requestLenght, new IPEndPoint(request.Addr, _lport)); + byte[] msg = new byte[requestLenght]; + Array.Copy(_sndBuf, msg, requestLenght); + + _socketSender.SetSocketOption(SocketOptionLevel.Socket, + SocketOptionName.Broadcast, + request.IsBroadcast + ? 1 + : 0); + + _socketSender.SendTo(msg, new IPEndPoint(request.Addr, _lport)); + //Log.Out("NameSerciceClient.Send - Sended"); + if (_log.Level > 3) { _log.WriteLine(request); Hexdump.ToHexdump(_log, _sndBuf, 0, requestLenght); } - } + if (_waitResponse) { long start = Runtime.CurrentTimeMillis(); + var isRecieved = false; + var startTime = DateTime.Now; while (timeout > 0) { Runtime.Wait(response, timeout); if (response.Received && request.QuestionType == response.RecordType) { - return; + //return; + isRecieved = true; + break; } response.Received = false; timeout -= (int)(Runtime.CurrentTimeMillis() - start); + + //if (timeout <= 0) + //{ + // Log.Out($"NameSerciceClient.Send Timeout! - {(DateTime.Now - startTime).TotalMilliseconds} msec"); + //} } + + if (isRecieved) + break; } } catch (Exception ie) { + if (_waitResponse) + _responseTable.Remove(nid); + + //Log.Out("NameSerciceClient.Send - IOException"); + throw new IOException(ie.Message); } finally { - //Sharpen.Collections.Remove(responseTable, nid); if (_waitResponse) - { _responseTable.Remove(nid); - } } + if (_waitResponse) { lock (_lock) @@ -393,17 +514,24 @@ namespace SharpCifs.Netbios } } } + + this._isActive = false; + //Log.Out("NameSerciceClient.Send - Normaly Ended."); } } /// <exception cref="UnknownHostException"></exception> internal virtual NbtAddress[] GetAllByName(Name name, IPAddress addr) { + //Log.Out("NameSerciceClient.GetAllByName"); + int n; NameQueryRequest request = new NameQueryRequest(name); NameQueryResponse response = new NameQueryResponse(); request.Addr = addr ?? NbtAddress.GetWinsAddress(); - request.IsBroadcast = request.Addr == null; + request.IsBroadcast = (request.Addr == null + || request.Addr.ToString() == Baddr.ToString()); + if (request.IsBroadcast) { request.Addr = Baddr; @@ -440,10 +568,12 @@ namespace SharpCifs.Netbios /// <exception cref="UnknownHostException"></exception> internal virtual NbtAddress GetByName(Name name, IPAddress addr) { - int n; + //Log.Out("NameSerciceClient.GetByName"); + int n; NameQueryRequest request = new NameQueryRequest(name); NameQueryResponse response = new NameQueryResponse(); + if (addr != null) { request.Addr = addr; @@ -463,7 +593,9 @@ namespace SharpCifs.Netbios } throw new UnknownHostException(ioe); } - if (response.Received && response.ResultCode == 0 + + if (response.Received + && response.ResultCode == 0 && response.IsResponse) { int last = response.AddrEntry.Length - 1; @@ -471,9 +603,11 @@ namespace SharpCifs.Netbios return response.AddrEntry[last]; } } + while (--n > 0 && request.IsBroadcast); throw new UnknownHostException(); } + for (int i = 0; i < _resolveOrder.Length; i++) { try @@ -496,8 +630,9 @@ namespace SharpCifs.Netbios case ResolverWins: case ResolverBcast: { - if (_resolveOrder[i] == ResolverWins && name.name != NbtAddress.MasterBrowserName - && name.HexCode != unchecked(0x1d)) + if (_resolveOrder[i] == ResolverWins + && name.name != NbtAddress.MasterBrowserName + && name.HexCode != unchecked(0x1d)) { request.Addr = NbtAddress.GetWinsAddress(); request.IsBroadcast = false; @@ -522,11 +657,12 @@ namespace SharpCifs.Netbios } throw new UnknownHostException(ioe); } - if (response.Received && response.ResultCode == 0 + if (response.Received + && response.ResultCode == 0 && response.IsResponse) { - - response.AddrEntry[0].HostName.SrcHashCode = request.Addr.GetHashCode(); + response.AddrEntry[0].HostName.SrcHashCode + = request.Addr.GetHashCode(); return response.AddrEntry[0]; } if (_resolveOrder[i] == ResolverWins) @@ -542,12 +678,15 @@ namespace SharpCifs.Netbios { } } + throw new UnknownHostException(); } /// <exception cref="UnknownHostException"></exception> internal virtual NbtAddress[] GetNodeStatus(NbtAddress addr) { + //Log.Out("NameSerciceClient.GetNodeStatus"); + int n; int srcHashCode; NodeStatusRequest request; @@ -556,6 +695,7 @@ namespace SharpCifs.Netbios request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x00), null)); request.Addr = addr.GetInetAddress(); n = RetryCount; + while (n-- > 0) { try @@ -585,6 +725,8 @@ namespace SharpCifs.Netbios internal virtual NbtAddress[] GetHosts() { + //Log.Out("NbtServiceClient.GetHosts"); + try { _waitResponse = false; @@ -593,6 +735,8 @@ namespace SharpCifs.Netbios for (int i = 1; i <= 254; i++) { + //Log.Out($"NbtServiceClient.GetHosts - {i}"); + NodeStatusRequest request; NodeStatusResponse response; @@ -605,49 +749,59 @@ namespace SharpCifs.Netbios 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)); + response = new NodeStatusResponse( + new NbtAddress(NbtAddress.UnknownName, + BitConverter.ToInt32(addr.GetAddressBytes(), 0), + false, + 0x20) + ); + + request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, + unchecked(0x20), + null)) + { + Addr = addr + }; - request = new NodeStatusRequest(new Name(NbtAddress.AnyHostsName, unchecked(0x20), null)); - request.Addr = addr; Send(request, response, 0); } - } catch (IOException ioe) { + //Log.Out(ioe); + if (_log.Level > 1) { Runtime.PrintStackTrace(ioe, _log); } throw new UnknownHostException(ioe); } - + _autoResetWaitReceive = new AutoResetEvent(false); - _thread = new Thread(this); + + if (_thread != null) + { + _thread.Cancel(true); + _thread.Dispose(); + } + + _thread = new Thread(this); _thread.SetDaemon(true); - _thread.Start(); + _thread.Start(true); - _autoResetWaitReceive.WaitOne(); + _autoResetWaitReceive.WaitOne(); - List<NbtAddress> result = new List<NbtAddress>(); + var result = new List<NbtAddress>(); foreach (var key in _responseTable.Keys) { - NodeStatusResponse resp = (NodeStatusResponse)_responseTable[key]; + var resp = (NodeStatusResponse)_responseTable[key]; - if (resp.Received && resp.ResultCode == 0) - { - foreach (var entry in resp.AddressArray) - { - if (entry.HostName.HexCode == 0x20) - { - result.Add(entry); - } - } - } + if (!resp.Received || resp.ResultCode != 0) + continue; + + result.AddRange(resp.AddressArray + .Where(entry => entry.HostName.HexCode == 0x20)); } _responseTable.Clear(); diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs index 28e98406e..1ac258a4e 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NameServicePacket.cs @@ -20,429 +20,474 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - internal abstract class NameServicePacket - { - internal const int Query = 0; + internal abstract class NameServicePacket + { + internal const int Query = 0; - internal const int Wack = 7; + internal const int Wack = 7; - internal const int FmtErr = 0x1; + internal const int FmtErr = 0x1; - internal const int SrvErr = 0x2; + internal const int SrvErr = 0x2; - internal const int ImpErr = 0x4; + internal const int ImpErr = 0x4; - internal const int RfsErr = 0x5; + internal const int RfsErr = 0x5; - internal const int ActErr = 0x6; + internal const int ActErr = 0x6; - internal const int CftErr = 0x7; + internal const int CftErr = 0x7; - internal const int NbIn = 0x00200001; + internal const int NbIn = 0x00200001; - internal const int NbstatIn = 0x00210001; + internal const int NbstatIn = 0x00210001; - internal const int Nb = 0x0020; + internal const int Nb = 0x0020; - internal const int Nbstat = 0x0021; + internal const int Nbstat = 0x0021; - internal const int In = 0x0001; + internal const int In = 0x0001; - internal const int A = 0x0001; + internal const int A = 0x0001; - internal const int Ns = 0x0002; + internal const int Ns = 0x0002; - internal const int Null = 0x000a; + internal const int Null = 0x000a; - internal const int HeaderLength = 12; + internal const int HeaderLength = 12; - internal const int OpcodeOffset = 2; + internal const int OpcodeOffset = 2; - internal const int QuestionOffset = 4; + internal const int QuestionOffset = 4; - internal const int AnswerOffset = 6; + internal const int AnswerOffset = 6; - internal const int AuthorityOffset = 8; + internal const int AuthorityOffset = 8; - internal const int AdditionalOffset = 10; + 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))); - } + // 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 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 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 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 static int ReadNameTrnId(byte[] src, int srcIndex) + { + return ReadInt2(src, srcIndex); + } - internal int AddrIndex; + internal int AddrIndex; - internal NbtAddress[] AddrEntry; + internal NbtAddress[] AddrEntry; - internal int NameTrnId; + internal int NameTrnId; - internal int OpCode; + internal int OpCode; - internal int ResultCode; + internal int ResultCode; - internal int QuestionCount; + internal int QuestionCount; - internal int AnswerCount; + internal int AnswerCount; - internal int AuthorityCount; + internal int AuthorityCount; - internal int AdditionalCount; + internal int AdditionalCount; - internal bool Received; + internal bool Received; - internal bool IsResponse; + internal bool IsResponse; - internal bool IsAuthAnswer; + internal bool IsAuthAnswer; - internal bool IsTruncated; + internal bool IsTruncated; - internal bool IsRecurDesired; + internal bool IsRecurDesired; - internal bool IsRecurAvailable; + internal bool IsRecurAvailable; - internal bool IsBroadcast; + internal bool IsBroadcast; - internal Name QuestionName; + 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; - } - } + 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; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs index c64d385f1..34f70d27b 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtAddress.cs @@ -18,903 +18,949 @@ using System; using System.Linq; using System.Net; using SharpCifs.Util; +using SharpCifs.Util.DbsHelper; 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 - { + /// <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)) + }; + + private 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; + } + } + + private 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) - { + } + 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 + ); + */ + try + { + localHostname = Dns.GetHostName(); + } + catch (Exception) + { + 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); + } + + private 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); + } + + private 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.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); + if (entry == null) + { + entry = new CacheEntry(hostName, addr, expiration); + AddressCache.Put(hostName, entry); + } + else + { + entry.Address = addr; + entry.Expiration = expiration; + } + } + } + + private 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; + } + } + } + } + + private 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> + private 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(); - } - } + 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() + { + //Log.Out("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(); + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs index e785c9943..9ade0e67c 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NbtException.cs @@ -19,146 +19,147 @@ 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); - } - } + 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); + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs index 66d3bb3e5..b7922eb84 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusRequest.cs @@ -16,44 +16,44 @@ // 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 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 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 ReadBodyWireFormat(byte[] src, int srcIndex) + { + return 0; + } - internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) - { - return 0; - } + internal override int WriteRDataWireFormat(byte[] dst, int dstIndex) + { + return 0; + } - internal override int ReadRDataWireFormat(byte[] src, int srcIndex) - { - return 0; - } + internal override int ReadRDataWireFormat(byte[] src, int srcIndex) + { + return 0; + } - public override string ToString() - { - return "NodeStatusRequest[" + base.ToString() + "]"; - } - } + public override string ToString() + { + return "NodeStatusRequest[" + base.ToString() + "]"; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs index aa3214419..ac0210217 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/NodeStatusResponse.cs @@ -19,122 +19,140 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - internal class NodeStatusResponse : NameServicePacket - { - private NbtAddress _queryAddress; + internal class NodeStatusResponse : NameServicePacket + { + private NbtAddress _queryAddress; - private int _numberOfNames; + private int _numberOfNames; - private byte[] _macAddress; + private byte[] _macAddress; - private byte[] _stats; + private byte[] _stats; - internal NbtAddress[] AddressArray; + internal NbtAddress[] AddressArray; - internal NodeStatusResponse(NbtAddress queryAddress) - { - this._queryAddress = queryAddress; - RecordName = new Name(); - _macAddress = new byte[6]; - } + 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 WriteBodyWireFormat(byte[] dst, int dstIndex) + { + return 0; + } - internal override int ReadBodyWireFormat(byte[] src, int srcIndex) - { - return ReadResourceRecordWireFormat(src, srcIndex); - } + 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 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; - } + 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; - } + 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() + "]"; - } - } + public override string ToString() + { + return "NodeStatusResponse[" + base.ToString() + "]"; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs index a5243f7aa..0f4d7e5e2 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRequestPacket.cs @@ -19,45 +19,44 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - public class SessionRequestPacket : SessionServicePacket - { - private Name _calledName; + public class SessionRequestPacket : SessionServicePacket + { + private Name _calledName; - private Name _callingName; + private Name _callingName; - public SessionRequestPacket() - { - _calledName = new Name(); - _callingName = new Name(); - } + public SessionRequestPacket() + { + _calledName = new Name(); + _callingName = new Name(); + } - public SessionRequestPacket(Name calledName, Name callingName) - { - Type = SessionRequest; - this._calledName = calledName; - this._callingName = callingName; - } + 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; - } + 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; - } - } + /// <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; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs index c901c6e26..48c772bae 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionRetargetResponsePacket.cs @@ -19,36 +19,35 @@ using SharpCifs.Util.Sharpen; namespace SharpCifs.Netbios { - internal class SessionRetargetResponsePacket : SessionServicePacket - { - private NbtAddress _retargetAddress; + internal class SessionRetargetResponsePacket : SessionServicePacket + { + private NbtAddress _retargetAddress; - private int _retargetPort; + private int _retargetPort; - public SessionRetargetResponsePacket() - { - Type = SessionRetargetResponse; - Length = 6; - } + public SessionRetargetResponsePacket() + { + Type = SessionRetargetResponse; + Length = 6; + } - internal override int WriteTrailerWireFormat(byte[] dst, int dstIndex) - { - return 0; - } + 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; - } - } + /// <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; + } + } } diff --git a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs index c8d194222..795dff9bd 100644 --- a/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs +++ b/Emby.Common.Implementations/IO/SharpCifs/Netbios/SessionServicePacket.cs @@ -19,138 +19,136 @@ 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 - ); - } + 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); + } } |
