Extensions.cs 13 KB

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