You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 lines
11 KiB

4 years ago
  1. #if MYSQL_6_10
  2. // Copyright © 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  3. //
  4. // MySQL Connector/NET is licensed under the terms of the GPLv2
  5. // <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
  6. // MySQL Connectors. There are special exceptions to the terms and
  7. // conditions of the GPLv2 as it is applied to this software, see the
  8. // FLOSS License Exception
  9. // <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
  10. //
  11. // This program is free software; you can redistribute it and/or modify
  12. // it under the terms of the GNU General Public License as published
  13. // by the Free Software Foundation; version 2 of the License.
  14. //
  15. // This program is distributed in the hope that it will be useful, but
  16. // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  18. // for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License along
  21. // with this program; if not, write to the Free Software Foundation, Inc.,
  22. // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. using System;
  24. using System.Diagnostics;
  25. using System.IO;
  26. using System.Text;
  27. using Externals.MySql.Data.Common;
  28. namespace Externals.MySql.Data.MySqlClient
  29. {
  30. class MySqlPacket
  31. {
  32. private byte[] _tempBuffer = new byte[256];
  33. private Encoding _encoding;
  34. private readonly MemoryStream _buffer = new MemoryStream(5);
  35. private MySqlPacket()
  36. {
  37. Clear();
  38. }
  39. public MySqlPacket(Encoding enc)
  40. : this()
  41. {
  42. Encoding = enc;
  43. }
  44. public MySqlPacket(MemoryStream stream)
  45. : this()
  46. {
  47. _buffer = stream;
  48. }
  49. #region Properties
  50. public Encoding Encoding
  51. {
  52. get { return _encoding; }
  53. set
  54. {
  55. Debug.Assert(value != null);
  56. _encoding = value;
  57. }
  58. }
  59. public bool HasMoreData
  60. {
  61. get { return _buffer.Position < _buffer.Length; }
  62. }
  63. public int Position
  64. {
  65. get { return (int)_buffer.Position; }
  66. set { _buffer.Position = (long)value; }
  67. }
  68. public int Length
  69. {
  70. get { return (int)_buffer.Length; }
  71. set { _buffer.SetLength(value); }
  72. }
  73. public bool IsLastPacket
  74. {
  75. get
  76. {
  77. #if !NETSTANDARD1_3
  78. byte[] bits = _buffer.GetBuffer();
  79. return bits[0] == 0xfe && Length <= 5;
  80. #else
  81. ArraySegment<byte> bits;
  82. _buffer.TryGetBuffer(out bits);
  83. return bits.Array[0] == 0xfe && Length <= 5;
  84. #endif
  85. }
  86. }
  87. public byte[] Buffer
  88. {
  89. get
  90. {
  91. #if !NETSTANDARD1_3
  92. byte[] bits = _buffer.GetBuffer();
  93. return bits;
  94. #else
  95. ArraySegment<byte> bits;
  96. _buffer.TryGetBuffer(out bits);
  97. return bits.Array;
  98. #endif
  99. }
  100. }
  101. public DBVersion Version { get; set; }
  102. #endregion
  103. public void Clear()
  104. {
  105. Position = 4;
  106. }
  107. #region Byte methods
  108. public byte ReadByte()
  109. {
  110. return (byte)_buffer.ReadByte();
  111. }
  112. public int Read(byte[] byteBuffer, int offset, int count)
  113. {
  114. return _buffer.Read(byteBuffer, offset, count);
  115. }
  116. public void WriteByte(byte b)
  117. {
  118. _buffer.WriteByte(b);
  119. }
  120. public void Write(byte[] bytesToWrite)
  121. {
  122. Write(bytesToWrite, 0, bytesToWrite.Length);
  123. }
  124. public void Write(byte[] bytesToWrite, int offset, int countToWrite)
  125. {
  126. _buffer.Write(bytesToWrite, offset, countToWrite);
  127. }
  128. public int ReadNBytes()
  129. {
  130. byte c = ReadByte();
  131. if (c < 1 || c > 4)
  132. throw new MySqlException(Resources.IncorrectTransmission);
  133. return ReadInteger(c);
  134. }
  135. public void SetByte(long position, byte value)
  136. {
  137. long currentPosition = _buffer.Position;
  138. _buffer.Position = position;
  139. _buffer.WriteByte(value);
  140. _buffer.Position = currentPosition;
  141. }
  142. #endregion
  143. #region Integer methods
  144. public long ReadFieldLength()
  145. {
  146. byte c = ReadByte();
  147. switch (c)
  148. {
  149. case 251: return -1;
  150. case 252: return ReadInteger(2);
  151. case 253: return ReadInteger(3);
  152. case 254: return ReadLong(8);
  153. default: return c;
  154. }
  155. }
  156. public ulong ReadBitValue(int numbytes)
  157. {
  158. ulong value = 0;
  159. int pos = (int)_buffer.Position;
  160. #if !NETSTANDARD1_3
  161. byte[] bits = _buffer.GetBuffer();
  162. #else
  163. ArraySegment<byte> bytes;
  164. _buffer.TryGetBuffer(out bytes);
  165. byte[] bits = bytes.Array;
  166. #endif
  167. int shift = 0;
  168. for (int i = 0; i < numbytes; i++)
  169. {
  170. value <<= shift;
  171. value |= bits[pos++];
  172. shift = 8;
  173. }
  174. _buffer.Position += numbytes;
  175. return value;
  176. }
  177. public long ReadLong(int numbytes)
  178. {
  179. Debug.Assert((_buffer.Position + numbytes) <= _buffer.Length);
  180. #if !NETSTANDARD1_3
  181. byte[] bits = _buffer.GetBuffer();
  182. #else
  183. ArraySegment<byte> bytes;
  184. _buffer.TryGetBuffer(out bytes);
  185. byte[] bits = bytes.Array;
  186. #endif
  187. int pos = (int)_buffer.Position;
  188. _buffer.Position += numbytes;
  189. switch (numbytes)
  190. {
  191. case 2: return BitConverter.ToUInt16(bits, pos);
  192. case 4: return BitConverter.ToUInt32(bits, pos);
  193. case 8: return BitConverter.ToInt64(bits, pos);
  194. }
  195. throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported");
  196. }
  197. public ulong ReadULong(int numbytes)
  198. {
  199. Debug.Assert((_buffer.Position + numbytes) <= _buffer.Length);
  200. #if !NETSTANDARD1_3
  201. byte[] bits = _buffer.GetBuffer();
  202. #else
  203. ArraySegment<byte> bytes;
  204. _buffer.TryGetBuffer(out bytes);
  205. byte[] bits = bytes.Array;
  206. #endif
  207. int pos = (int)_buffer.Position;
  208. _buffer.Position += numbytes;
  209. switch (numbytes)
  210. {
  211. case 2: return BitConverter.ToUInt16(bits, pos);
  212. case 4: return BitConverter.ToUInt32(bits, pos);
  213. case 8: return BitConverter.ToUInt64(bits, pos);
  214. }
  215. throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported");
  216. }
  217. public int Read3ByteInt()
  218. {
  219. int value = 0;
  220. int pos = (int)_buffer.Position;
  221. #if !NETSTANDARD1_3
  222. byte[] bits = _buffer.GetBuffer();
  223. #else
  224. ArraySegment<byte> bytes;
  225. _buffer.TryGetBuffer(out bytes);
  226. byte[] bits = bytes.Array;
  227. #endif
  228. int shift = 0;
  229. for (int i = 0; i < 3; i++)
  230. {
  231. value |= (int)(bits[pos++] << shift);
  232. shift += 8;
  233. }
  234. _buffer.Position += 3;
  235. return value;
  236. }
  237. public int ReadInteger(int numbytes)
  238. {
  239. if (numbytes == 3)
  240. return Read3ByteInt();
  241. Debug.Assert(numbytes <= 4);
  242. return (int)ReadLong(numbytes);
  243. }
  244. /// <summary>
  245. /// WriteInteger
  246. /// </summary>
  247. /// <param name="v"></param>
  248. /// <param name="numbytes"></param>
  249. public void WriteInteger(long v, int numbytes)
  250. {
  251. long val = v;
  252. Debug.Assert(numbytes > 0 && numbytes < 9);
  253. for (int x = 0; x < numbytes; x++)
  254. {
  255. _tempBuffer[x] = (byte)(val & 0xff);
  256. val >>= 8;
  257. }
  258. Write(_tempBuffer, 0, numbytes);
  259. }
  260. public int ReadPackedInteger()
  261. {
  262. byte c = ReadByte();
  263. switch (c)
  264. {
  265. case 251: return -1;
  266. case 252: return ReadInteger(2);
  267. case 253: return ReadInteger(3);
  268. case 254: return ReadInteger(4);
  269. default: return c;
  270. }
  271. }
  272. public void WriteLength(long length)
  273. {
  274. if (length < 251)
  275. WriteByte((byte)length);
  276. else if (length < 65536L)
  277. {
  278. WriteByte(252);
  279. WriteInteger(length, 2);
  280. }
  281. else if (length < 16777216L)
  282. {
  283. WriteByte(253);
  284. WriteInteger(length, 3);
  285. }
  286. else
  287. {
  288. WriteByte(254);
  289. WriteInteger(length, 4);
  290. }
  291. }
  292. #endregion
  293. #region String methods
  294. public void WriteLenString(string s)
  295. {
  296. byte[] bytes = _encoding.GetBytes(s);
  297. WriteLength(bytes.Length);
  298. Write(bytes, 0, bytes.Length);
  299. }
  300. public void WriteStringNoNull(string v)
  301. {
  302. byte[] bytes = _encoding.GetBytes(v);
  303. Write(bytes, 0, bytes.Length);
  304. }
  305. public void WriteString(string v)
  306. {
  307. WriteStringNoNull(v);
  308. WriteByte(0);
  309. }
  310. public string ReadLenString()
  311. {
  312. long len = ReadPackedInteger();
  313. return ReadString(len);
  314. }
  315. public string ReadAsciiString(long length)
  316. {
  317. if (length == 0)
  318. return String.Empty;
  319. // byte[] buf = new byte[length];
  320. Read(_tempBuffer, 0, (int)length);
  321. return Encoding.GetEncoding("us-ascii").GetString(_tempBuffer, 0, (int)length);
  322. //return encoding.GetString(tempBuffer, 0, (int)length); //buf.Length);
  323. }
  324. public string ReadString(long length)
  325. {
  326. if (length == 0)
  327. return String.Empty;
  328. if (_tempBuffer == null || length > _tempBuffer.Length)
  329. _tempBuffer = new byte[length];
  330. Read(_tempBuffer, 0, (int)length);
  331. return _encoding.GetString(_tempBuffer, 0, (int)length);
  332. }
  333. public string ReadString()
  334. {
  335. return ReadString(_encoding);
  336. }
  337. public string ReadString(Encoding theEncoding)
  338. {
  339. byte[] bytes = ReadStringAsBytes();
  340. string s = theEncoding.GetString(bytes, 0, bytes.Length);
  341. return s;
  342. }
  343. public byte[] ReadStringAsBytes()
  344. {
  345. byte[] readBytes;
  346. #if !NETSTANDARD1_3
  347. byte[] bits = _buffer.GetBuffer();
  348. #else
  349. ArraySegment<byte> bytes;
  350. _buffer.TryGetBuffer(out bytes);
  351. byte[] bits = bytes.Array;
  352. #endif
  353. int end = (int)_buffer.Position;
  354. byte[] tempBuffer = bits;
  355. while (end < (int)_buffer.Length &&
  356. tempBuffer[end] != 0 && (int)tempBuffer[end] != -1)
  357. end++;
  358. readBytes = new byte[end - _buffer.Position];
  359. Array.Copy(tempBuffer, (int)_buffer.Position, readBytes, 0, (int)(end - _buffer.Position));
  360. _buffer.Position = end + 1;
  361. return readBytes;
  362. }
  363. #endregion
  364. }
  365. }
  366. #endif