Segment.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using System.IO;
  2. namespace kcp2k
  3. {
  4. // KCP Segment Definition
  5. internal class Segment
  6. {
  7. internal uint conv; // conversation
  8. internal uint cmd; // command, e.g. Kcp.CMD_ACK etc.
  9. // fragment (sent as 1 byte).
  10. // 0 if unfragmented, otherwise fragment numbers in reverse: N,..,32,1,0
  11. // this way the first received segment tells us how many fragments there are.
  12. internal uint frg;
  13. internal uint wnd; // window size that the receive can currently receive
  14. internal uint ts; // timestamp
  15. internal uint sn; // sequence number
  16. internal uint una;
  17. internal uint resendts; // resend timestamp
  18. internal int rto;
  19. internal uint fastack;
  20. internal uint xmit; // retransmit count
  21. // we need an auto scaling byte[] with a WriteBytes function.
  22. // MemoryStream does that perfectly, no need to reinvent the wheel.
  23. // note: no need to pool it, because Segment is already pooled.
  24. // -> default MTU as initial capacity to avoid most runtime resizing/allocations
  25. //
  26. // .data is only used for Encode(), which always fits it into a buffer.
  27. // the buffer is always Kcp.buffer. Kcp ctor creates the buffer of size:
  28. // (mtu + OVERHEAD) * 3 bytes.
  29. // in other words, Encode only ever writes up to the above amount of bytes.
  30. internal MemoryStream data = new MemoryStream(Kcp.MTU_DEF);
  31. // ikcp_encode_seg
  32. // encode a segment into buffer.
  33. // buffer is always Kcp.buffer. Kcp ctor creates the buffer of size:
  34. // (mtu + OVERHEAD) * 3 bytes.
  35. // in other words, Encode only ever writes up to the above amount of bytes.
  36. internal int Encode(byte[] ptr, int offset)
  37. {
  38. int previousPosition = offset;
  39. offset += Utils.Encode32U(ptr, offset, conv);
  40. offset += Utils.Encode8u(ptr, offset, (byte)cmd);
  41. // IMPORTANT kcp encodes 'frg' as 1 byte.
  42. // so we can only support up to 255 fragments.
  43. // (which limits max message size to around 288 KB)
  44. offset += Utils.Encode8u(ptr, offset, (byte)frg);
  45. offset += Utils.Encode16U(ptr, offset, (ushort)wnd);
  46. offset += Utils.Encode32U(ptr, offset, ts);
  47. offset += Utils.Encode32U(ptr, offset, sn);
  48. offset += Utils.Encode32U(ptr, offset, una);
  49. offset += Utils.Encode32U(ptr, offset, (uint)data.Position);
  50. int written = offset - previousPosition;
  51. return written;
  52. }
  53. // reset to return a fresh segment to the pool
  54. internal void Reset()
  55. {
  56. conv = 0;
  57. cmd = 0;
  58. frg = 0;
  59. wnd = 0;
  60. ts = 0;
  61. sn = 0;
  62. una = 0;
  63. rto = 0;
  64. xmit = 0;
  65. resendts = 0;
  66. fastack = 0;
  67. // keep buffer for next pool usage, but reset length (= bytes written)
  68. data.SetLength(0);
  69. }
  70. }
  71. }