Extensions.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using System;
  2. using System.Collections.Generic;
  3. #if !SILVERLIGHT
  4. using System.Diagnostics;
  5. #endif
  6. using System.Globalization;
  7. using System.Net;
  8. using Renci.SshNet.Messages;
  9. using Renci.SshNet.Messages.Connection;
  10. namespace Renci.SshNet.Common
  11. {
  12. /// <summary>
  13. /// Collection of different extension method
  14. /// </summary>
  15. internal static partial class Extensions
  16. {
  17. internal static byte[] ToArray(this GlobalRequestName globalRequestName)
  18. {
  19. switch (globalRequestName)
  20. {
  21. case GlobalRequestName.TcpIpForward:
  22. return SshData.Ascii.GetBytes("tcpip-forward");
  23. case GlobalRequestName.CancelTcpIpForward:
  24. return SshData.Ascii.GetBytes("cancel-tcpip-forward");
  25. default:
  26. throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", globalRequestName));
  27. }
  28. }
  29. internal static byte[] ToArray(this ServiceName serviceName)
  30. {
  31. switch (serviceName)
  32. {
  33. case ServiceName.UserAuthentication:
  34. return SshData.Ascii.GetBytes("ssh-userauth");
  35. case ServiceName.Connection:
  36. return SshData.Ascii.GetBytes("ssh-connection");
  37. default:
  38. throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", serviceName));
  39. }
  40. }
  41. internal static ServiceName ToServiceName(this byte[] data)
  42. {
  43. var sshServiceName = SshData.Ascii.GetString(data, 0, data.Length);
  44. switch (sshServiceName)
  45. {
  46. case "ssh-userauth":
  47. return ServiceName.UserAuthentication;
  48. case "ssh-connection":
  49. return ServiceName.Connection;
  50. default:
  51. throw new NotSupportedException(string.Format("Service name '{0}' is not supported.", sshServiceName));
  52. }
  53. }
  54. internal static GlobalRequestName ToGlobalRequestName(this byte[] data)
  55. {
  56. var sshGlobalRequestName = SshData.Ascii.GetString(data, 0, data.Length);
  57. switch (sshGlobalRequestName)
  58. {
  59. case "tcpip-forward":
  60. return GlobalRequestName.TcpIpForward;
  61. case "cancel-tcpip-forward":
  62. return GlobalRequestName.CancelTcpIpForward;
  63. default:
  64. throw new NotSupportedException(string.Format("Global request name '{0}' is not supported.", sshGlobalRequestName));
  65. }
  66. }
  67. #if TUNING
  68. internal static BigInteger ToBigInteger(this byte[] data)
  69. {
  70. var reversed = new byte[data.Length];
  71. Buffer.BlockCopy(data, 0, reversed, 0, data.Length);
  72. return new BigInteger(reversed.Reverse());
  73. }
  74. /// <summary>
  75. /// Reverses the sequence of the elements in the entire one-dimensional <see cref="Array"/>.
  76. /// </summary>
  77. /// <param name="array">The one-dimensional <see cref="Array"/> to reverse.</param>
  78. /// <returns>
  79. /// The <see cref="Array"/> with its elements reversed.
  80. /// </returns>
  81. internal static T[] Reverse<T>(this T[] array)
  82. {
  83. Array.Reverse(array);
  84. return array;
  85. }
  86. #endif
  87. /// <summary>
  88. /// Checks whether a collection is the same as another collection
  89. /// </summary>
  90. /// <param name="value">The current instance object</param>
  91. /// <param name="compareList">The collection to compare with</param>
  92. /// <param name="comparer">The comparer object to use to compare each item in the collection. If null uses EqualityComparer(T).Default</param>
  93. /// <returns>True if the two collections contain all the same items in the same order</returns>
  94. internal static bool IsEqualTo<TSource>(this IEnumerable<TSource> value, IEnumerable<TSource> compareList, IEqualityComparer<TSource> comparer)
  95. {
  96. if (value == compareList)
  97. return true;
  98. if (value == null || compareList == null)
  99. return false;
  100. if (comparer == null)
  101. {
  102. comparer = EqualityComparer<TSource>.Default;
  103. }
  104. var enumerator1 = value.GetEnumerator();
  105. var enumerator2 = compareList.GetEnumerator();
  106. var enum1HasValue = enumerator1.MoveNext();
  107. var enum2HasValue = enumerator2.MoveNext();
  108. try
  109. {
  110. while (enum1HasValue && enum2HasValue)
  111. {
  112. if (!comparer.Equals(enumerator1.Current, enumerator2.Current))
  113. {
  114. return false;
  115. }
  116. enum1HasValue = enumerator1.MoveNext();
  117. enum2HasValue = enumerator2.MoveNext();
  118. }
  119. return !(enum1HasValue || enum2HasValue);
  120. }
  121. finally
  122. {
  123. enumerator1.Dispose();
  124. enumerator2.Dispose();
  125. }
  126. }
  127. /// <summary>
  128. /// Checks whether a collection is the same as another collection
  129. /// </summary>
  130. /// <param name="value">The current instance object</param>
  131. /// <param name="compareList">The collection to compare with</param>
  132. /// <returns>True if the two collections contain all the same items in the same order</returns>
  133. internal static bool IsEqualTo<TSource>(this IEnumerable<TSource> value, IEnumerable<TSource> compareList)
  134. {
  135. return IsEqualTo(value, compareList, null);
  136. }
  137. #if SILVERLIGHT
  138. #else
  139. /// <summary>
  140. /// Prints out
  141. /// </summary>
  142. /// <param name="bytes">The bytes.</param>
  143. internal static void DebugPrint(this IEnumerable<byte> bytes)
  144. {
  145. foreach (var b in bytes)
  146. {
  147. Debug.Write(string.Format(CultureInfo.CurrentCulture, "0x{0:x2}, ", b));
  148. }
  149. Debug.WriteLine(string.Empty);
  150. }
  151. #endif
  152. /// <summary>
  153. /// Trims the leading zero from bytes array.
  154. /// </summary>
  155. /// <param name="data">The data.</param>
  156. /// <returns>Data without leading zeros.</returns>
  157. internal static IEnumerable<byte> TrimLeadingZero(this IEnumerable<byte> data)
  158. {
  159. var leadingZero = true;
  160. foreach (var item in data)
  161. {
  162. if (item == 0 & leadingZero)
  163. {
  164. continue;
  165. }
  166. leadingZero = false;
  167. yield return item;
  168. }
  169. }
  170. /// <summary>
  171. /// Creates an instance of the specified type using that type's default constructor.
  172. /// </summary>
  173. /// <typeparam name="T">The type to create.</typeparam>
  174. /// <param name="type">Type of the instance to create.</param>
  175. /// <returns>A reference to the newly created object.</returns>
  176. internal static T CreateInstance<T>(this Type type) where T : class
  177. {
  178. if (type == null)
  179. return null;
  180. return Activator.CreateInstance(type) as T;
  181. }
  182. /// <summary>
  183. /// Returns the specified 16-bit unsigned integer value as an array of bytes.
  184. /// </summary>
  185. /// <param name="value">The number to convert.</param>
  186. /// <returns>An array of bytes with length 2.</returns>
  187. internal static byte[] GetBytes(this UInt16 value)
  188. {
  189. return new[] {(byte) (value >> 8), (byte) (value & 0xFF)};
  190. }
  191. /// <summary>
  192. /// Returns the specified 32-bit unsigned integer value as an array of bytes.
  193. /// </summary>
  194. /// <param name="value">The number to convert.</param>
  195. /// <returns>An array of bytes with length 4.</returns>
  196. internal static byte[] GetBytes(this UInt32 value)
  197. {
  198. #if TUNING
  199. var buffer = new byte[4];
  200. value.Write(buffer, 0);
  201. return buffer;
  202. #else
  203. return new[] {(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)};
  204. #endif
  205. }
  206. /// <summary>
  207. /// Returns the specified 32-bit unsigned integer value as an array of bytes.
  208. /// </summary>
  209. /// <param name="value">The number to convert.</param>
  210. /// <param name="buffer">The array of bytes to write <paramref name="value"/> to.</param>
  211. /// <param name="offset">The zero-based offset in <paramref name="buffer"/> at which to begin writing.</param>
  212. internal static void Write(this uint value, byte[] buffer, int offset)
  213. {
  214. buffer[offset++] = (byte) (value >> 24);
  215. buffer[offset++] = (byte) (value >> 16);
  216. buffer[offset++] = (byte)(value >> 8);
  217. buffer[offset] = (byte) (value & 0xFF);
  218. }
  219. /// <summary>
  220. /// Returns the specified 64-bit unsigned integer value as an array of bytes.
  221. /// </summary>
  222. /// <param name="value">The number to convert.</param>
  223. /// <returns>An array of bytes with length 8.</returns>
  224. internal static byte[] GetBytes(this UInt64 value)
  225. {
  226. return new[]
  227. {
  228. (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
  229. (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
  230. };
  231. }
  232. /// <summary>
  233. /// Returns the specified 64-bit signed integer value as an array of bytes.
  234. /// </summary>
  235. /// <param name="value">The number to convert.</param>
  236. /// <returns>An array of bytes with length 8.</returns>
  237. internal static byte[] GetBytes(this Int64 value)
  238. {
  239. return new[]
  240. {
  241. (byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
  242. (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) (value & 0xFF)
  243. };
  244. }
  245. internal static void ValidatePort(this uint value, string argument)
  246. {
  247. if (value > IPEndPoint.MaxPort)
  248. throw new ArgumentOutOfRangeException(argument,
  249. string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
  250. IPEndPoint.MaxPort));
  251. }
  252. internal static void ValidatePort(this int value, string argument)
  253. {
  254. if (value < IPEndPoint.MinPort)
  255. throw new ArgumentOutOfRangeException(argument,
  256. string.Format(CultureInfo.InvariantCulture, "Specified value cannot be less than {0}.",
  257. IPEndPoint.MinPort));
  258. if (value > IPEndPoint.MaxPort)
  259. throw new ArgumentOutOfRangeException(argument,
  260. string.Format(CultureInfo.InvariantCulture, "Specified value cannot be greater than {0}.",
  261. IPEndPoint.MaxPort));
  262. }
  263. /// <summary>
  264. /// Returns a specified number of contiguous bytes from a given offset.
  265. /// </summary>
  266. /// <param name="data">The array to return a number of bytes from.</param>
  267. /// <param name="offset">The zero-based offset in <paramref name="data"/> at which to begin taking bytes.</param>
  268. /// <param name="length">The number of bytes to take from <paramref name="data"/>.</param>
  269. /// <returns>
  270. /// A <see cref="byte"/> array that contains the specified number of bytes at the specified offset
  271. /// of the input array.
  272. /// </returns>
  273. internal static byte[] Take(this byte[] data, int offset, int length)
  274. {
  275. var taken = new byte[length];
  276. Buffer.BlockCopy(data, offset, taken, 0, length);
  277. return taken;
  278. }
  279. }
  280. }