LLUDPZeroEncoder.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Runtime.CompilerServices;
  29. using OpenSim.Framework;
  30. using OpenMetaverse;
  31. namespace OpenSim.Region.ClientStack.LindenUDP
  32. {
  33. public class LLUDPZeroEncoder
  34. {
  35. private byte[] m_dest;
  36. private int zerocount;
  37. private int pos;
  38. public LLUDPZeroEncoder()
  39. {
  40. }
  41. public LLUDPZeroEncoder(byte[] data)
  42. {
  43. m_dest = data;
  44. zerocount = 0;
  45. }
  46. public byte[] Data
  47. {
  48. get
  49. {
  50. return m_dest;
  51. }
  52. set
  53. {
  54. m_dest = value;
  55. }
  56. }
  57. public int ZeroCount
  58. {
  59. get
  60. {
  61. return zerocount;
  62. }
  63. set
  64. {
  65. zerocount = value;
  66. }
  67. }
  68. public int Position
  69. {
  70. get
  71. {
  72. return pos;
  73. }
  74. set
  75. {
  76. pos = value;
  77. }
  78. }
  79. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  80. public unsafe void AddZeros(int len)
  81. {
  82. zerocount += len;
  83. while (zerocount > 0xff)
  84. {
  85. m_dest[pos++] = 0x00;
  86. m_dest[pos++] = 0xff;
  87. zerocount -= 256;
  88. }
  89. }
  90. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  91. public unsafe int Finish()
  92. {
  93. if (zerocount > 0)
  94. {
  95. m_dest[pos++] = 0x00;
  96. m_dest[pos++] = (byte)zerocount;
  97. }
  98. return pos;
  99. }
  100. public unsafe void AddBytes(byte[] src, int srclen)
  101. {
  102. for (int i = 0; i < srclen; ++i)
  103. {
  104. if (src[i] == 0x00)
  105. {
  106. if (zerocount != 0xff)
  107. zerocount++;
  108. else
  109. {
  110. m_dest[pos++] = 0x00;
  111. m_dest[pos++] = 0xff;
  112. zerocount = 1;
  113. }
  114. }
  115. else
  116. {
  117. if (zerocount != 0)
  118. {
  119. m_dest[pos++] = 0x00;
  120. m_dest[pos++] = (byte)zerocount;
  121. zerocount = 0;
  122. }
  123. m_dest[pos++] = src[i];
  124. }
  125. }
  126. }
  127. public unsafe void AddBytes(byte* src, int srclen)
  128. {
  129. for (int i = 0; i < srclen; ++i)
  130. {
  131. if (src[i] == 0x00)
  132. {
  133. if (zerocount != 0xff)
  134. zerocount++;
  135. else
  136. {
  137. m_dest[pos++] = 0x00;
  138. m_dest[pos++] = 0xff;
  139. zerocount = 1;
  140. }
  141. }
  142. else
  143. {
  144. if (zerocount != 0)
  145. {
  146. m_dest[pos++] = 0x00;
  147. m_dest[pos++] = (byte)zerocount;
  148. zerocount = 0;
  149. }
  150. m_dest[pos++] = src[i];
  151. }
  152. }
  153. }
  154. public unsafe void AddByte(byte v)
  155. {
  156. if (v == 0x00)
  157. {
  158. if (zerocount != 0xff)
  159. zerocount++;
  160. else
  161. {
  162. m_dest[pos++] = 0x00;
  163. m_dest[pos++] = 0xff;
  164. zerocount = 1;
  165. }
  166. }
  167. else
  168. {
  169. if (zerocount != 0)
  170. {
  171. m_dest[pos++] = 0x00;
  172. m_dest[pos++] = (byte)zerocount;
  173. zerocount = 0;
  174. }
  175. m_dest[pos++] = v;
  176. }
  177. }
  178. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  179. public unsafe void AddInt16(short v)
  180. {
  181. if (v == 0)
  182. AddZeros(2);
  183. else
  184. {
  185. byte* b = stackalloc byte[2];
  186. Utils.Int16ToBytes(v, b);
  187. AddBytes(b, 2);
  188. }
  189. }
  190. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  191. public unsafe void AddUInt16(ushort v)
  192. {
  193. if (v == 0)
  194. AddZeros(2);
  195. else
  196. {
  197. byte* b = stackalloc byte[2];
  198. Utils.UInt16ToBytes(v, b);
  199. AddBytes(b, 2);
  200. }
  201. }
  202. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  203. public unsafe void AddInt(int v)
  204. {
  205. if (v == 0)
  206. AddZeros(4);
  207. else
  208. {
  209. byte* b = stackalloc byte[4];
  210. Utils.IntToBytes(v, b);
  211. AddBytes(b, 4);
  212. }
  213. }
  214. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  215. public unsafe void AddUInt(uint v)
  216. {
  217. if (v == 0)
  218. AddZeros(4);
  219. else
  220. {
  221. byte* b = stackalloc byte[4];
  222. Utils.UIntToBytes(v, b);
  223. AddBytes(b, 4);
  224. }
  225. }
  226. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  227. public unsafe void AddFloatToUInt16(float v, float range)
  228. {
  229. byte* b = stackalloc byte[2];
  230. Utils.FloatToUInt16Bytes(v, range, b);
  231. AddBytes(b, 2);
  232. }
  233. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  234. public unsafe void AddFloat(float v)
  235. {
  236. if (v == 0f)
  237. AddZeros(4);
  238. else
  239. {
  240. byte* b = stackalloc byte[4];
  241. Utils.FloatToBytes(v, b);
  242. AddBytes(b, 4);
  243. }
  244. }
  245. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  246. public unsafe void AddInt64(long v)
  247. {
  248. if (v == 0)
  249. AddZeros(8);
  250. else
  251. {
  252. byte* b = stackalloc byte[8];
  253. Utils.Int64ToBytes(v, b);
  254. AddBytes(b, 8);
  255. }
  256. }
  257. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  258. public unsafe void AddUInt64(ulong v)
  259. {
  260. if (v == 0)
  261. AddZeros(8);
  262. else
  263. {
  264. byte* b = stackalloc byte[8];
  265. Utils.UInt64ToBytes(v, b);
  266. AddBytes(b, 8);
  267. }
  268. }
  269. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  270. public unsafe void AddVector3(Vector3 v)
  271. {
  272. if (v.IsZero())
  273. AddZeros(12);
  274. else
  275. {
  276. byte* b = stackalloc byte[12];
  277. v.ToBytes(b);
  278. AddBytes(b, 12);
  279. }
  280. }
  281. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  282. public unsafe void AddVector4(Vector4 v)
  283. {
  284. if (v.IsZero())
  285. AddZeros(16);
  286. else
  287. {
  288. byte* b = stackalloc byte[16];
  289. v.ToBytes(b);
  290. AddBytes(b, 16);
  291. }
  292. }
  293. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  294. public unsafe void AddNormQuat(Quaternion v)
  295. {
  296. byte* b = stackalloc byte[12];
  297. v.ToBytes(b);
  298. AddBytes(b, 12);
  299. }
  300. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  301. public unsafe void AddUUID(UUID v)
  302. {
  303. byte* b = stackalloc byte[16];
  304. v.ToBytes(b);
  305. AddBytes(b, 16);
  306. }
  307. // maxlen <= 255 and includes null termination byte
  308. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  309. public unsafe void AddShortString(string str, int maxlen)
  310. {
  311. if (String.IsNullOrEmpty(str))
  312. {
  313. AddZeros(1);
  314. return;
  315. }
  316. byte* data = stackalloc byte[maxlen];
  317. int len = Util.osUTF8Getbytes(str, data, maxlen, true);
  318. if (len == 0)
  319. {
  320. AddZeros(1);
  321. return;
  322. }
  323. AddByte((byte)(len));
  324. AddBytes(data, len);
  325. }
  326. // maxlen <= 255 and includes null termination byte, maxchars == max len of utf16 source
  327. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  328. public unsafe void AddShortString(string str, int maxchars, int maxlen)
  329. {
  330. if (String.IsNullOrEmpty(str))
  331. {
  332. AddZeros(1);
  333. return;
  334. }
  335. if (str.Length > maxchars)
  336. str = str.Substring(0, maxchars);
  337. byte* data = stackalloc byte[maxlen];
  338. int len = Util.osUTF8Getbytes(str, data, maxlen, true);
  339. if (len == 0)
  340. {
  341. AddZeros(1);
  342. return;
  343. }
  344. AddByte((byte)(len));
  345. AddBytes(data, len);
  346. }
  347. // maxlen <= 254 because null termination byte
  348. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  349. public unsafe void AddShortLimitedUTF8(osUTF8 str)
  350. {
  351. if (str == null)
  352. {
  353. AddZeros(1);
  354. return;
  355. }
  356. int len = str.Length;
  357. if (len == 0)
  358. {
  359. AddZeros(1);
  360. return;
  361. }
  362. AddByte((byte)(len + 1)); // add null
  363. AddBytes(str.GetArray(), len);
  364. AddZeros(1);
  365. }
  366. }
  367. public unsafe class LLUDPUnsafeZeroEncoder
  368. {
  369. private byte* m_destStart;
  370. private int m_zerocount;
  371. private byte* m_dest;
  372. public LLUDPUnsafeZeroEncoder()
  373. {
  374. }
  375. public LLUDPUnsafeZeroEncoder(byte* data)
  376. {
  377. m_destStart = data;
  378. m_dest = data;
  379. m_zerocount = 0;
  380. }
  381. public byte* Data
  382. {
  383. get
  384. {
  385. return m_destStart;
  386. }
  387. set
  388. {
  389. m_destStart = value;
  390. m_dest = value;
  391. }
  392. }
  393. public int ZeroCount
  394. {
  395. get
  396. {
  397. return m_zerocount;
  398. }
  399. set
  400. {
  401. m_zerocount = value;
  402. }
  403. }
  404. public int Position
  405. {
  406. get
  407. {
  408. return (int)(m_dest - m_destStart);
  409. }
  410. set
  411. {
  412. m_dest = m_destStart + value;
  413. }
  414. }
  415. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  416. public unsafe void AddZeros(int len)
  417. {
  418. m_zerocount += len;
  419. while (m_zerocount > 0xff)
  420. {
  421. *m_dest++ = 0x00;
  422. *m_dest++ = 0xff;
  423. m_zerocount -= 256;
  424. }
  425. }
  426. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  427. public unsafe int Finish()
  428. {
  429. if (m_zerocount > 0)
  430. {
  431. *m_dest++ = 0x00;
  432. *m_dest++ = (byte)m_zerocount;
  433. }
  434. return (int)(m_dest - m_destStart);
  435. }
  436. public unsafe void AddBytes(byte[] src, int srclen)
  437. {
  438. for (int i = 0; i < srclen; ++i)
  439. {
  440. if (src[i] == 0x00)
  441. {
  442. if (m_zerocount != 0xff)
  443. m_zerocount++;
  444. else
  445. {
  446. *m_dest++ = 0x00;
  447. *m_dest++ = 0xff;
  448. m_zerocount = 1;
  449. }
  450. }
  451. else
  452. {
  453. if (m_zerocount != 0)
  454. {
  455. *m_dest++ = 0x00;
  456. *m_dest++ = (byte)m_zerocount;
  457. m_zerocount = 0;
  458. }
  459. *m_dest++ = src[i];
  460. }
  461. }
  462. }
  463. public unsafe void AddBytes(byte* src, int srclen)
  464. {
  465. for (int i = 0; i < srclen; ++i)
  466. {
  467. if (src[i] == 0x00)
  468. {
  469. if (m_zerocount != 0xff)
  470. m_zerocount++;
  471. else
  472. {
  473. *m_dest++ = 0x00;
  474. *m_dest++ = 0xff;
  475. m_zerocount = 1;
  476. }
  477. }
  478. else
  479. {
  480. if (m_zerocount != 0)
  481. {
  482. *m_dest++ = 0x00;
  483. *m_dest++ = (byte)m_zerocount;
  484. m_zerocount = 0;
  485. }
  486. *m_dest++ = src[i];
  487. }
  488. }
  489. }
  490. public unsafe void AddByte(byte v)
  491. {
  492. if (v == 0x00)
  493. {
  494. if (m_zerocount != 0xff)
  495. m_zerocount++;
  496. else
  497. {
  498. *m_dest++ = 0x00;
  499. *m_dest++ = 0xff;
  500. m_zerocount = 1;
  501. }
  502. }
  503. else
  504. {
  505. if (m_zerocount != 0)
  506. {
  507. *m_dest++ = 0x00;
  508. *m_dest++ = (byte)m_zerocount;
  509. m_zerocount = 0;
  510. }
  511. *m_dest++ = v;
  512. }
  513. }
  514. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  515. public void AddInt16(short v)
  516. {
  517. if (v == 0)
  518. AddZeros(2);
  519. else
  520. {
  521. byte* b = stackalloc byte[2];
  522. Utils.Int16ToBytes(v, b);
  523. AddBytes(b, 2);
  524. }
  525. }
  526. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  527. public void AddUInt16(ushort v)
  528. {
  529. if (v == 0)
  530. AddZeros(2);
  531. else
  532. {
  533. byte* b = stackalloc byte[2];
  534. Utils.UInt16ToBytes(v, b);
  535. AddBytes(b, 2);
  536. }
  537. }
  538. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  539. public void AddInt(int v)
  540. {
  541. if (v == 0)
  542. AddZeros(4);
  543. else
  544. {
  545. byte* b = stackalloc byte[4];
  546. Utils.IntToBytes(v, b);
  547. AddBytes(b, 4);
  548. }
  549. }
  550. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  551. public unsafe void AddUInt(uint v)
  552. {
  553. if (v == 0)
  554. AddZeros(4);
  555. else
  556. {
  557. byte* b = stackalloc byte[4];
  558. Utils.UIntToBytes(v, b);
  559. AddBytes(b, 4);
  560. }
  561. }
  562. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  563. public void AddFloatToUInt16(float v, float range)
  564. {
  565. byte* b = stackalloc byte[2];
  566. Utils.FloatToUInt16Bytes(v, range, b);
  567. AddBytes(b, 2);
  568. }
  569. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  570. public void AddFloat(float v)
  571. {
  572. if (v == 0f)
  573. AddZeros(4);
  574. else
  575. {
  576. byte* b = stackalloc byte[4];
  577. Utils.FloatToBytes(v, b);
  578. AddBytes(b, 4);
  579. }
  580. }
  581. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  582. public void AddInt64(long v)
  583. {
  584. if (v == 0)
  585. AddZeros(8);
  586. else
  587. {
  588. byte* b = stackalloc byte[8];
  589. Utils.Int64ToBytes(v, b);
  590. AddBytes(b, 8);
  591. }
  592. }
  593. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  594. public void AddUInt64(ulong v)
  595. {
  596. if (v == 0)
  597. AddZeros(8);
  598. else
  599. {
  600. byte* b = stackalloc byte[8];
  601. Utils.UInt64ToBytes(v, b);
  602. AddBytes(b, 8);
  603. }
  604. }
  605. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  606. public void AddVector3(Vector3 v)
  607. {
  608. if (v.IsZero())
  609. AddZeros(12);
  610. else
  611. {
  612. byte* b = stackalloc byte[12];
  613. v.ToBytes(b);
  614. AddBytes(b, 12);
  615. }
  616. }
  617. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  618. public void AddVector4(Vector4 v)
  619. {
  620. if (v.IsZero())
  621. AddZeros(16);
  622. else
  623. {
  624. byte* b = stackalloc byte[16];
  625. v.ToBytes(b);
  626. AddBytes(b, 16);
  627. }
  628. }
  629. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  630. public void AddNormQuat(Quaternion v)
  631. {
  632. byte* b = stackalloc byte[12];
  633. v.ToBytes(b);
  634. AddBytes(b, 12);
  635. }
  636. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  637. public void AddUUID(UUID v)
  638. {
  639. byte* b = stackalloc byte[16];
  640. v.ToBytes(b);
  641. AddBytes(b, 16);
  642. }
  643. // maxlen <= 255 and includes null termination byte
  644. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  645. public unsafe void AddShortString(string str, int maxlen)
  646. {
  647. if (String.IsNullOrEmpty(str))
  648. {
  649. AddZeros(1);
  650. return;
  651. }
  652. byte* data = stackalloc byte[maxlen];
  653. int len = Util.osUTF8Getbytes(str, data, maxlen, true);
  654. if (len == 0)
  655. {
  656. AddZeros(1);
  657. return;
  658. }
  659. AddByte((byte)(len));
  660. AddBytes(data, len);
  661. }
  662. // maxlen <= 255 and includes null termination byte, maxchars == max len of utf16 source
  663. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  664. public unsafe void AddShortString(string str, int maxchars, int maxlen)
  665. {
  666. if (String.IsNullOrEmpty(str))
  667. {
  668. AddZeros(1);
  669. return;
  670. }
  671. if (str.Length > maxchars)
  672. str = str.Substring(0, maxchars);
  673. byte* data = stackalloc byte[maxlen];
  674. int len = Util.osUTF8Getbytes(str, data, maxlen, true);
  675. if (len == 0)
  676. {
  677. AddZeros(1);
  678. return;
  679. }
  680. AddByte((byte)(len));
  681. AddBytes(data, len);
  682. }
  683. // maxlen <= 254 because null termination byte
  684. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  685. public unsafe void AddShortLimitedUTF8(osUTF8 str)
  686. {
  687. if (str == null)
  688. {
  689. AddZeros(1);
  690. return;
  691. }
  692. int len = str.Length;
  693. if (len == 0)
  694. {
  695. AddZeros(1);
  696. return;
  697. }
  698. AddByte((byte)(len + 1)); // add null
  699. AddBytes(str.GetArray(), len);
  700. AddZeros(1);
  701. }
  702. }
  703. }