SphynxTransport.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. * Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. * Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. * Neither the name of LibCat nor the names of its contributors may be used
  11. to endorse or promote products derived from this software without
  12. specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  14. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  17. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  23. POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef CAT_SPHYNX_TRANSPORT_HPP
  26. #define CAT_SPHYNX_TRANSPORT_HPP
  27. #include <cat/net/ThreadPoolSockets.hpp>
  28. #include <cat/threads/Mutex.hpp>
  29. #include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
  30. #include <cat/parse/BufferStream.hpp>
  31. namespace cat {
  32. namespace sphynx {
  33. /*
  34. Based on what I have envisioned needing for my game, the following protocol is being
  35. used after spending weeks looking at alternatives and false-starts. It provides signaled
  36. disconnects, fragmentation, MTU discovery, time synchronization, three reliable ordered
  37. streams, one unordered reliable stream, and unreliable delivery.
  38. The Transport object that implements a sender/receiver in the protocol requires 276 bytes
  39. of memory per server connection, plus 32 bytes per message fragment in flight, plus buffers
  40. for queued send/recv packets, and it keeps two mutexes for thread-safety. A lockless memory
  41. allocator is used to allocate all buffers except the fragmented message reassembly buffer.
  42. Packet format on top of UDP header:
  43. E { HDR(2 bytes)|ACK-ID(3 bytes)|DATA || ... || MAC(8 bytes) } || IV(3 bytes)
  44. E: ChaCha-12 stream cipher.
  45. IV: Initialization vector used by security layer (Randomly initialized).
  46. MAC: Message authentication code used by security layer (HMAC-MD5).
  47. HDR|ACK-ID|DATA: A message block inside the datagram. The HDR and ACK-ID
  48. fields employ compression to use as little as 1 byte together.
  49. Each message follows the same format. A two-byte header followed by data:
  50. --- Message Header (16 bits) ---
  51. 0 1 2 3 4 5 6 7 8 9 a b c d e f
  52. <-- LSB ----------------- MSB -->
  53. | BHI |I|R| SOP | BLO |
  54. ---------------------------------
  55. DATA_BYTES: BHI | BLO = Number of bytes in data part of message.
  56. If BHI = "111"b, the BLO byte is omitted and the receiver can
  57. assume that the rest of the packet contains just one message.
  58. I: 1=Followed by ACK-ID field. 0=ACK-ID is one higher than the last.
  59. R: 1=Reliable. 0=Unreliable.
  60. SOP: Super opcodes:
  61. 0=Data (reliable or unreliable)
  62. 1=Fragment (reliable)
  63. 2=ACK (unreliable)
  64. 3=MTU Probe (unreliable)
  65. 4=MTU Set (unordered reliable)
  66. 5=Time Ping (unreliable)
  67. 6=Time Pong (unreliable)
  68. 7=Disconnect (unreliable)
  69. When the I bit is set, the data part is preceded by an ACK-ID,
  70. which is then applied to all following reliable messages.
  71. This additional size is NOT accounted for in the DATA_BYTES field.
  72. When the FRAG opcode used for the first time in an ordered stream,
  73. the data part begins with a 16-bit Fragment Header.
  74. This additional size IS accounted for in the DATA_BYTES field.
  75. Often times there is just one message in a datagram. To compress
  76. the header in this case, when BHI = 7 the receiver assumes that
  77. only one message is in the packet and uses the payload length to
  78. determine the length of the single message. BLO byte is omitted.
  79. This *could* also be used on the final message in a cluster,
  80. but it cannot be done without a memcpy to cover up the extra
  81. header byte, which I don't consider worthwhile...
  82. ------------- ACK-ID Field (24 bits) ------------
  83. 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
  84. <-- LSB --------------------------------- MSB -->
  85. | S | IDA (5) |C| IDB (7) |C| IDC (8) |
  86. -------------------------------------------------
  87. C: 1=Continues to next byte.
  88. S: 0=Unordered stream, 1-3: Ordered streams.
  89. ID: IDC | IDB | IDA (20 bits)
  90. On retransmission, the ACK-ID field uses no compression
  91. since the receiver state cannot be determined.
  92. --- Fragment Header (16 bits) ---
  93. 0 1 2 3 4 5 6 7 8 9 a b c d e f
  94. <-- LSB ----------------- MSB -->
  95. | TOTAL_BYTES(16) |
  96. ---------------------------------
  97. TOTAL_BYTES: Total bytes in data part of fragmented message,
  98. not including this header.
  99. */
  100. /*
  101. ACK message format:
  102. Header: I=0, R=0, SOP=SOP_ACK
  103. Data: ROLLUP(3) || RANGE1 || RANGE2 || ... ROLLUP(3) || RANGE1 || RANGE2 || ...
  104. ROLLUP = Next expected ACK-ID. Acknowledges every ID before this one.
  105. RANGE1:
  106. START || END
  107. START = First inclusive ACK-ID in a range to acknowledge.
  108. END = Final inclusive ACK-ID in a range to acknowledge.
  109. Negative acknowledgment can be inferred from the holes in the RANGEs.
  110. ------------ ROLLUP Field (24 bits) -------------
  111. 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
  112. <-- LSB --------------------------------- MSB -->
  113. |1| S | IDA (5) | IDB (8) | IDC (8) |
  114. -------------------------------------------------
  115. 1: Indicates start of ROLLUP field.
  116. S: 0=Unordered stream, 1-3: Ordered streams.
  117. ID: IDC | IDB | IDA (21 bits)
  118. ROLLUP is always 3 bytes since we cannot tell how far ahead the remote host is now.
  119. --------- RANGE START Field (24 bits) -----------
  120. 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
  121. <-- LSB --------------------------------- MSB -->
  122. |0|E| IDA (5) |C| IDB (7) |C| IDC (8) |
  123. -------------------------------------------------
  124. 0: Indicates start of RANGE field.
  125. C: 1=Continues to next byte.
  126. E: 1=Has end field. 0=One ID in range.
  127. ID: IDC | IDB | IDA (20 bits) + last ack id in message
  128. ---------- RANGE END Field (24 bits) ------------
  129. 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
  130. <-- LSB --------------------------------- MSB -->
  131. | IDA (7) |C| IDB (7) |C| IDC (8) |
  132. -------------------------------------------------
  133. C: 1=Continues to next byte.
  134. ID: IDC | IDB | IDA (22 bits) + START.ID
  135. */
  136. class Connexion;
  137. class Map;
  138. class Server;
  139. class ServerWorker;
  140. class ServerTimer;
  141. class Client;
  142. class Transport;
  143. #if defined(CAT_WORD_32)
  144. #define CAT_PACK_TRANSPORT_STATE_STRUCTURES /* For 32-bit version, this allows fragments to fit in 32 bytes */
  145. #else // 64-bit version:
  146. //#define CAT_PACK_TRANSPORT_STATE_STRUCTURES /* No advantage for 64-bit version */
  147. #endif
  148. //#define CAT_TRANSPORT_DEBUG_LOGGING /* Enables info messages on console */
  149. #define CAT_VERBOSE_VALIDATION /* Enables input error messages on console */
  150. // Protocol constants
  151. static const u32 PROTOCOL_MAGIC = 0xC47D0001;
  152. static const int PUBLIC_KEY_BYTES = 64;
  153. static const int PRIVATE_KEY_BYTES = 32;
  154. static const int CHALLENGE_BYTES = PUBLIC_KEY_BYTES;
  155. static const int ANSWER_BYTES = PUBLIC_KEY_BYTES*2;
  156. static const int HASH_TABLE_SIZE = 32768; // Power-of-2
  157. static const int HASH_TABLE_MASK = HASH_TABLE_SIZE - 1;
  158. static const int MAX_POPULATION = HASH_TABLE_SIZE / 2;
  159. // (multiplier-1) divisible by all prime factors of table size
  160. // (multiplier-1) is a multiple of 4 if table size is a multiple of 4
  161. // These constants are from Press, Teukolsky, Vetterling and Flannery's
  162. // "Numerical Recipes in FORTRAN: The Art of Scientific Computing"
  163. static const u32 COLLISION_MULTIPLIER = 71*5861 * 4 + 1;
  164. static const u32 COLLISION_INCREMENTER = 1013904223;
  165. // If multiplier changes, this needs to be recalculated (multiplicative inverse of above)
  166. static const u32 COLLISION_MULTINVERSE = 4276115653;
  167. static const u32 COLLISION_INCRINVERSE = 0 - COLLISION_INCREMENTER;
  168. // Handshake types
  169. enum HandshakeType
  170. {
  171. C2S_HELLO,
  172. S2C_COOKIE,
  173. C2S_CHALLENGE,
  174. S2C_ANSWER,
  175. S2C_ERROR
  176. };
  177. // Handshake errors
  178. enum HandshakeError
  179. {
  180. ERR_SERVER_FULL
  181. };
  182. // Stream modes
  183. enum StreamMode
  184. {
  185. STREAM_UNORDERED = 0, // Reliable, unordered stream 0
  186. STREAM_1 = 1, // Reliable, ordered stream 1
  187. STREAM_2 = 2, // Reliable, ordered stream 2
  188. STREAM_3 = 3 // Reliable, ordered stream 3
  189. };
  190. // Super Opcodes
  191. enum SuperOpcode
  192. {
  193. SOP_DATA, // 0=Data (reliable or unreliable)
  194. SOP_FRAG, // 1=Fragment (reliable)
  195. SOP_ACK, // 2=ACK (unreliable)
  196. SOP_MTU_PROBE, // 3=MTU Probe (unreliable)
  197. SOP_MTU_SET, // 4=MTU Set (unordered reliable)
  198. SOP_TIME_PING, // 5=Time Ping (unreliable)
  199. SOP_TIME_PONG, // 6=Time Pong (unreliable)
  200. SOP_DISCO, // 7=Disconnect (unreliable)
  201. };
  202. //// sphynx::Transport
  203. #if defined(CAT_PACK_TRANSPORT_STATE_STRUCTURES)
  204. #pragma pack(push)
  205. #pragma pack(1)
  206. #endif // CAT_PACK_TRANSPORT_STATE_STRUCTURES
  207. // Receive state: Receive queue
  208. struct RecvQueue
  209. {
  210. static const u32 FRAG_FLAG = 0x80000000;
  211. static const u32 BYTE_MASK = 0x7fffffff;
  212. RecvQueue *next; // Next in queue
  213. RecvQueue *prev; // Previous in queue
  214. u32 id; // Acknowledgment id
  215. u32 bytes; // High bit: Fragment?
  216. // Message contents follow
  217. };
  218. // Send state: Send queue
  219. struct SendQueue
  220. {
  221. SendQueue *next; // Next in queue
  222. SendQueue *prev; // Previous in queue
  223. u32 ts_firstsend; // Millisecond-resolution timestamp when it was first sent
  224. u32 ts_lastsend; // Millisecond-resolution timestamp when it was last sent
  225. union
  226. {
  227. u32 sent_bytes; // In send queue: Number of sent bytes while fragmenting a large message
  228. u32 id; // In sent list: Acknowledgment id
  229. };
  230. u16 bytes; // Data bytes
  231. u16 frag_count; // Number of fragments remaining to be delivered
  232. u16 sop; // Super opcode of message
  233. // Message contents follow
  234. };
  235. struct SendFrag : public SendQueue
  236. {
  237. SendQueue *full_data; // Object containing message data
  238. u16 offset; // Fragment data offset
  239. };
  240. // Temporary send node structure, nestled in the encryption overhead of outgoing packets
  241. struct TempSendNode // Size <= 11 bytes = AuthenticatedEncryption::OVERHEAD_BYTES
  242. {
  243. static const u32 SINGLE_FLAG = 0x8000;
  244. static const u32 BYTE_MASK = 0x7fff;
  245. TempSendNode *next;
  246. u16 negative_offset; // Number of bytes before this structure, and single flag
  247. };
  248. #if defined(CAT_PACK_TRANSPORT_STATE_STRUCTURES)
  249. #pragma pack(pop)
  250. #endif // CAT_PACK_TRANSPORT_STATE_STRUCTURES
  251. class Transport
  252. {
  253. protected:
  254. static const u8 BHI_MASK = 7;
  255. static const u8 BHI_SINGLE_MESSAGE = 7;
  256. static const u8 I_MASK = 1 << 3;
  257. static const u8 R_MASK = 1 << 4;
  258. static const u32 SOP_SHIFT = 5;
  259. static const u32 NUM_STREAMS = 4; // Number of reliable streams
  260. static const u32 MIN_RTT = 50; // Minimum milliseconds for RTT
  261. static const int TIMEOUT_DISCONNECT = 15000; // 15 seconds
  262. static const int SILENCE_LIMIT = 9333; // 9.333 seconds: Time silent before sending a keep-alive (0-length unordered reliable message)
  263. static const int TICK_RATE = 20; // 20 milliseconds
  264. static const u32 MINIMUM_MTU = 576; // Dialup
  265. static const u32 MEDIUM_MTU = 1400; // Highspeed with unexpected overhead, maybe VPN
  266. static const u32 MAXIMUM_MTU = 1500; // Highspeed
  267. static const u32 IPV6_OPTIONS_BYTES = 40; // TODO: Not sure about this
  268. static const u32 IPV6_HEADER_BYTES = 40 + IPV6_OPTIONS_BYTES;
  269. static const u32 IPV4_OPTIONS_BYTES = 40;
  270. static const u32 IPV4_HEADER_BYTES = 20 + IPV4_OPTIONS_BYTES;
  271. static const u32 UDP_HEADER_BYTES = 8;
  272. static const u32 FRAG_THRESHOLD = 32; // Fragment if FRAG_THRESHOLD bytes would be in each fragment
  273. static const u32 MAX_MESSAGE_DATALEN = 65535-1; // Maximum number of bytes in the data part of a message (-1 for the opcode)
  274. protected:
  275. // Maximum transfer unit (MTU) in UDP payload bytes, excluding the IP and UDP headers and encryption overhead
  276. u32 _max_payload_bytes;
  277. public:
  278. void InitializePayloadBytes(bool ip6);
  279. protected:
  280. // Receive state: Next expected ack id to receive
  281. u32 _next_recv_expected_id[NUM_STREAMS];
  282. // Receive state: Synchronization objects
  283. volatile bool _got_reliable[NUM_STREAMS];
  284. Mutex _recv_lock; // Just needs to protect writes OnDatagram() from messing up reads on tick
  285. // Receive state: Fragmentation
  286. u8 *_fragment_buffer[NUM_STREAMS]; // Buffer for accumulating fragment
  287. u32 _fragment_length[NUM_STREAMS]; // Number of bytes in fragment buffer
  288. u32 _fragment_offset[NUM_STREAMS]; // Current write offset in buffer
  289. static const u32 FRAG_MIN = 0; // Min bytes for a fragmented message
  290. static const u32 FRAG_MAX = 65535; // Max bytes for a fragmented message
  291. // Receive state: Receive queue head
  292. RecvQueue *_recv_queue_head[NUM_STREAMS], *_recv_queue_tail[NUM_STREAMS];
  293. private:
  294. void RunQueue(ThreadPoolLocalStorage *tls, u32 ack_id, u32 stream);
  295. void QueueRecv(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes, u32 ack_id, u32 stream, u32 super_opcode);
  296. protected:
  297. // Send state: Synchronization objects
  298. Mutex _send_lock;
  299. // Send state: Next ack id to use
  300. u32 _next_send_id[NUM_STREAMS];
  301. // Send state: Estimated round-trip time
  302. u32 _rtt; // milliseconds
  303. // Send state: Last rollup ack id from remote receiver
  304. u32 _send_next_remote_expected[NUM_STREAMS];
  305. // Send state: Combined writes
  306. u8 *_send_buffer;
  307. u32 _send_buffer_bytes;
  308. u32 _send_buffer_stream, _send_buffer_ack_id; // Used to compress ACK-ID by setting I=0 after the first reliable message
  309. u32 _send_buffer_msg_count; // Used to compress datagrams with a single message by omitting the header's BLO field
  310. // Queue of messages that are waiting to be sent
  311. SendQueue *_send_queue_head[NUM_STREAMS], *_send_queue_tail[NUM_STREAMS];
  312. // List of messages that are waiting to be acknowledged
  313. SendQueue *_sent_list_head[NUM_STREAMS], *_sent_list_tail[NUM_STREAMS];
  314. bool _disconnected;
  315. private:
  316. void TransmitQueued();
  317. void Retransmit(u32 stream, SendQueue *node, u32 now); // Does not hold the send lock!
  318. void WriteACK();
  319. void OnACK(u8 *data, u32 data_bytes);
  320. void OnMTUSet(u8 *data, u32 data_bytes);
  321. public:
  322. Transport();
  323. virtual ~Transport();
  324. public:
  325. // ata_bytes: Length of msg_data
  326. bool WriteUnreliable(u8 msg_opcode, const void *msg_data = 0, u32 data_bytes = 0);
  327. bool WriteReliable(StreamMode, u8 msg_opcode, const void *msg_data = 0, u32 data_bytes = 0, SuperOpcode super_opcode = SOP_DATA);
  328. void FlushWrite();
  329. protected:
  330. // Notify transport layer of disconnect to halt message processing
  331. CAT_INLINE void TransportDisconnected() { _disconnected = true; }
  332. CAT_INLINE bool IsDisconnected() { return _disconnected; }
  333. void TickTransport(ThreadPoolLocalStorage *tls, u32 now);
  334. void OnDatagram(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes);
  335. private:
  336. void OnFragment(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes, u32 stream);
  337. void CombineNextWrite();
  338. protected:
  339. // skip_bytes: Number of bytes to skip at the start of the buffer
  340. // buf_bytes and msg_bytes contain the skipped bytes
  341. virtual bool PostPacket(u8 *data, u32 buf_bytes, u32 msg_bytes, u32 skip_bytes) = 0;
  342. virtual void OnTimestampDeltaUpdate(u32 rtt, s32 delta) {}
  343. virtual void OnMessage(ThreadPoolLocalStorage *tls, BufferStream msg, u32 bytes) = 0;
  344. virtual void OnDisconnect() = 0;
  345. protected:
  346. bool PostMTUProbe(ThreadPoolLocalStorage *tls, u16 payload_bytes);
  347. bool PostTimePing();
  348. bool PostTimePong(u32 client_ts);
  349. bool PostDisconnect();
  350. };
  351. } // namespace sphynx
  352. } // namespace cat
  353. #endif // CAT_SPHYNX_TRANSPORT_HPP
粤ICP备19079148号