// Byte related function helper. // Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors. // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. /* * Created by SharpDevelop. * User: lextm * Date: 2008/5/1 * Time: 12:31 * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; namespace GSF.Net.Snmp { /// /// Helper utility that performs data conversions from/to bytes. /// public static class ByteTool { /// /// Converts decimal string to bytes. /// /// The decimal string. /// The converted bytes. /// " 16 18 " is converted to new byte[] { 0x10, 0x12 }. public static byte[] ConvertDecimal(string description) { if (description == null) { throw new ArgumentNullException(nameof(description)); } List result = new List(); string[] content = description.Trim().Split(new[] { ' ' }); foreach (string part in content) { byte temp; if (byte.TryParse(part, out temp)) { result.Add(temp); } } return result.ToArray(); } /// /// Converts the byte string to bytes. /// /// The HEX string. /// The converted bytes. /// "80 00" is converted to new byte[] { 0x80, 0x00 }. public static byte[] Convert(IEnumerable description) { if (description == null) { throw new ArgumentNullException(nameof(description)); } List result = new List(); StringBuilder buffer = new StringBuilder(2); foreach (char c in description.Where(c => !char.IsWhiteSpace(c))) { if (!char.IsLetterOrDigit(c)) { throw new ArgumentException("Illegal character found.", nameof(description)); } buffer.Append(c); if (buffer.Length != 2) { continue; } byte temp; if (byte.TryParse(buffer.ToString(), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out temp)) { result.Add(temp); } buffer.Length = 0; } if (buffer.Length != 0) { throw new ArgumentException("Not a complete byte string.", nameof(description)); } return result.ToArray(); } /// /// Converts bytes to a byte string. /// /// The bytes. /// The formatted string. /// new byte[] { 0x80, 0x00 } is converted to "80 00". public static string Convert(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } return BitConverter.ToString(buffer).Replace('-', ' '); } internal static byte[] ParseItems(params ISnmpData[] items) { if (items == null) { throw new ArgumentNullException(nameof(items)); } using (MemoryStream result = new MemoryStream()) { foreach (ISnmpData item in items) { if (item == null) { throw new ArgumentException("Item in the collection cannot be null.", nameof(items)); } item.AppendBytesTo(result); } return result.ToArray(); } } internal static byte[] ParseItems(IEnumerable items) { if (items == null) { throw new ArgumentNullException(nameof(items)); } using (MemoryStream result = new MemoryStream()) { foreach (ISnmpData item in items) { item.AppendBytesTo(result); } return result.ToArray(); } } internal static byte[] GetRawBytes(IEnumerable orig, bool negative) { if (orig == null) { throw new ArgumentNullException(nameof(orig)); } byte flag; byte sign; if (negative) { flag = 0xff; sign = 0x80; } else { flag = 0x0; sign = 0x0; } List list = new List(orig); while (list.Count > 1) { if (list[list.Count - 1] == flag) { list.RemoveAt(list.Count - 1); } else { break; } } // if sign bit is not correct, add an extra byte if ((list[list.Count - 1] & 0x80) != sign) { list.Add(flag); } list.Reverse(); return list.ToArray(); } /// /// Packs parts into a single message body. /// /// Message length. /// Message version. /// Header. /// Security parameters. /// Scope data. /// The object that represents the message body. public static Sequence PackMessage(byte[] length, VersionCode version, ISegment header, ISegment parameters, ISnmpData data) { if (header == null) { throw new ArgumentNullException(nameof(header)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } ISnmpData[] items = new[] { new Integer32((int)version), header.GetData(version), parameters.GetData(version), data }; return new Sequence(length, items); } internal static byte[] WritePayloadLength(this int length) // excluding initial octet { if (length < 0) { throw new ArgumentException("length cannot be negative.", nameof(length)); } MemoryStream stream = new MemoryStream(); if (length < 127) { stream.WriteByte((byte)length); return stream.ToArray(); } byte[] c = new byte[16]; int j = 0; while (length > 0) { c[j++] = (byte)(length & 0xff); length = length >> 8; } stream.WriteByte((byte)(0x80 | j)); while (j > 0) { int x = c[--j]; stream.WriteByte((byte)x); } return stream.ToArray(); } } }