PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/tnl2/net_connection.h

https://github.com/nardo/tnl2
C Header | 395 lines | 289 code | 66 blank | 40 comment | 19 complexity | 8e2e65ad646ae70c82928858db127e6d MD5 | raw file
  1. class net_connection : public ref_object
  2. {
  3. public:
  4. declare_dynamic_class()
  5. void set_connection_state(uint32 new_state)
  6. {
  7. _state = new_state;
  8. }
  9. uint32 get_connection_state()
  10. {
  11. return _state;
  12. }
  13. uint32 _state;
  14. enum
  15. {
  16. state_start,
  17. state_awaiting_challenge_response,
  18. state_requesting_connection,
  19. state_accepted,
  20. state_established,
  21. state_rejected,
  22. state_timed_out,
  23. state_disconnected,
  24. };
  25. /// Rate management structure used specify the rate at which packets are sent and the maximum size of each packet.
  26. struct net_rate
  27. {
  28. uint32 min_packet_send_period; ///< Minimum millisecond delay (maximum rate) between packet sends.
  29. uint32 min_packet_recv_period; ///< Minimum millisecond delay the remote host should allow between sends.
  30. uint32 max_send_bandwidth; ///< Number of bytes per second we can send over the connection.
  31. uint32 max_recv_bandwidth; ///< Number of bytes per second max that the remote instance should send.
  32. };
  33. /// Structure used to track what was sent in an individual packet for processing
  34. /// upon notification of delivery success or failure.
  35. struct packet_notify
  36. {
  37. // packet stream notify stuff:
  38. bool rate_changed; ///< True if this packet requested a change of rate.
  39. net::time send_time; ///< getRealMilliseconds() when packet was sent.
  40. uint32 sequence;
  41. packet_notify *next_packet; ///< Pointer to the next packet sent on this connection
  42. packet_notify()
  43. {
  44. rate_changed = false;
  45. }
  46. };
  47. void connect(net_interface *the_interface, const SOCKADDR *remote_address);
  48. virtual void write_connect_request(bit_stream &connect_stream)
  49. {
  50. }
  51. virtual bool read_connect_request(bit_stream &request_stream, bit_stream &response_stream)
  52. {
  53. return true;
  54. }
  55. virtual void on_challenge_response(bit_stream &challenge_response, byte_buffer_ptr &public_key)
  56. {
  57. }
  58. virtual void write_connect_accept(bit_stream &accept_stream)
  59. {
  60. }
  61. virtual bool read_connect_accept(bit_stream &accept_stream, bit_stream &response_stream)
  62. {
  63. return true;
  64. }
  65. virtual void on_connection_rejected(bit_stream &reject_stream)
  66. {
  67. }
  68. virtual void on_connection_disconnected(bit_stream &disconnect_stream)
  69. {
  70. }
  71. virtual void on_connection_timed_out()
  72. {
  73. }
  74. virtual void on_connection_established()
  75. {
  76. }
  77. net::time _highest_acked_send_time;
  78. virtual void on_packet_notify(uint32 send_sequence, bool recvd)
  79. {
  80. TorqueLogMessageFormatted(LogNetConnection, ("connection %d: NOTIFY %d %s", _connection, send_sequence, recvd ? "RECVD" : "DROPPED"));
  81. packet_notify *note = _notify_queue_head;
  82. assert(note != NULL);
  83. _notify_queue_head = _notify_queue_head->next_packet;
  84. if(note->rate_changed && !recvd)
  85. _local_rate_changed = true;
  86. if(recvd)
  87. {
  88. _highest_acked_send_time = note->send_time;
  89. // Running average of roundTrip time
  90. if(_highest_acked_send_time != net::time(0))
  91. {
  92. net::time round_trip_delta = _interface->get_process_start_time() - (_highest_acked_send_time + _last_received_send_delay);
  93. _round_trip_time = _round_trip_time * 0.9f + round_trip_delta.get_milliseconds() * 0.1f;
  94. if(_round_trip_time < 0)
  95. _round_trip_time = 0;
  96. }
  97. packet_received(note);
  98. }
  99. else
  100. {
  101. packet_dropped(note);
  102. }
  103. delete note;
  104. }
  105. torque_connection_id get_torque_connection()
  106. {
  107. return _connection;
  108. }
  109. void set_torque_connection(torque_connection_id connection)
  110. {
  111. _connection = connection;
  112. }
  113. /// Called when the packet associated with the specified notify is known to have been received by the remote host. Packets are guaranteed to be notified in the order in which they were sent.
  114. virtual void packet_received(packet_notify *note)
  115. {
  116. }
  117. /// Called when the packet associated with the specified notify is known to have been not received by the remote host. Packets are guaranteed to be notified in the order in which they were sent.
  118. virtual void packet_dropped(packet_notify *note)
  119. {
  120. }
  121. /// Returns true if this connection has data to transmit.
  122. ///
  123. /// The adaptive rate protocol needs to be able to tell if there is data
  124. /// ready to be sent, so that it can avoid sending unnecessary packets.
  125. /// Each subclass of connection may need to send different data - events,
  126. /// ghost updates, or other things. Therefore, this hook is provided so
  127. /// that child classes can overload it and let the adaptive protocol
  128. /// function properly.
  129. ///
  130. /// @note Make sure this calls to its parents - the accepted idiom is:
  131. /// @code
  132. /// return Parent::is_data_to_transmit() || localConditions();
  133. /// @endcode
  134. virtual bool is_data_to_transmit() { return false; }
  135. /// Checks to see if a packet should be sent at the currentTime to the remote host.
  136. ///
  137. /// If force is true and there is space in the window, it will always send a packet.
  138. void check_packet_send(bool force, net::time current_time)
  139. {
  140. if(window_full() || !is_data_to_transmit())
  141. return;
  142. net::time delay = net::time( _current_packet_send_period );
  143. if(!force)
  144. {
  145. if(current_time - _last_update_time + _send_delay_credit < delay)
  146. return;
  147. _send_delay_credit = current_time - (_last_update_time + delay - _send_delay_credit);
  148. if(_send_delay_credit > net::time(1000))
  149. _send_delay_credit = net::time(1000);
  150. }
  151. prepare_write_packet();
  152. net::packet_stream stream(_current_packet_send_size);
  153. _last_update_time = current_time;
  154. packet_notify *note = alloc_notify();
  155. if(!_notify_queue_head)
  156. _notify_queue_head = note;
  157. else
  158. _notify_queue_tail->next_packet = note;
  159. _notify_queue_tail = note;
  160. note->next_packet = NULL;
  161. note->send_time = _interface->get_process_start_time();
  162. write_packet_rate_info(stream, note);
  163. int32 start = stream.get_bit_position();
  164. TorqueLogMessageFormatted(LogNetConnection, ("connection %d: START", _connection) );
  165. net::time send_delay = _interface->get_process_start_time() - _last_packet_recv_time;
  166. if(send_delay > net::time(2047))
  167. send_delay = net::time(2047);
  168. stream.write_integer(uint32(send_delay.get_milliseconds() >> 3), 8);
  169. write_packet(stream, note);
  170. TorqueLogMessageFormatted(LogNetConnection, ("connection %d: END - %llu bits", _connection, stream.get_bit_position() - start) );
  171. logprintf("NC packet write data: %s", net::buffer_encode_base_16(stream.get_buffer(), stream.get_next_byte_position())->get_buffer());
  172. _last_send_sequence = _interface->get_socket_interface()->send_to_connection(_interface->get_socket(), _connection, stream.get_next_byte_position(), stream.get_buffer());
  173. //torque_connection_send_to(_connection, stream.get_next_byte_position(), stream.get_buffer(), &_last_send_sequence);
  174. _notify_queue_tail->sequence = _last_send_sequence;
  175. }
  176. virtual void on_packet(uint32 sequence, bit_stream &data)
  177. {
  178. read_packet_rate_info(data);
  179. _last_received_send_delay = net::time((data.read_integer(8) << 3) + 4);
  180. _last_packet_recv_time = _interface->get_process_start_time();
  181. logprintf("NC packet read data: %s", net::buffer_encode_base_16(data.get_buffer(), data.get_next_byte_position())->get_buffer());
  182. read_packet(data);
  183. }
  184. /// Called to prepare the connection for packet writing.
  185. virtual void prepare_write_packet() {}
  186. ///
  187. /// Any setup work to determine if there is_data_to_transmit() should happen in
  188. /// this function. prepare_write_packet should _always_ call the Parent:: function.
  189. /// Called to write a subclass's packet data into the packet.Information about what the instance wrote into the packet can be attached to the notify ref_object.
  190. virtual void write_packet(bit_stream &bstream, packet_notify *note) {}
  191. /// Called to read a subclass's packet data from the packet.
  192. virtual void read_packet(bit_stream &bstream) {}
  193. /// Allocates a data record to track data sent on an individual packet. If you need to track additional notification information, you'll have to override this so you allocate a subclass of packet_notify with extra fields.
  194. virtual packet_notify *alloc_notify() { return new packet_notify; }
  195. /// sets the fixed rate send and receive data sizes, and sets the connection to not behave as an adaptive rate connection
  196. void set_fixed_rate_parameters( uint32 min_packet_send_period, uint32 min_packet_recv_period, uint32 max_send_bandwidth, uint32 max_recv_bandwidth )
  197. {
  198. _local_rate.max_recv_bandwidth = max_recv_bandwidth;
  199. _local_rate.max_send_bandwidth = max_send_bandwidth;
  200. _local_rate.min_packet_recv_period = min_packet_recv_period;
  201. _local_rate.min_packet_send_period = min_packet_send_period;
  202. _local_rate_changed = true;
  203. compute_negotiated_rate();
  204. }
  205. /// Returns the running average packet round trip time.
  206. float32 get_round_trip_time()
  207. {
  208. return _round_trip_time;
  209. }
  210. /// Returns have of the average of the round trip packet time.
  211. float32 get_one_way_time()
  212. {
  213. return _round_trip_time * 0.5f;
  214. }
  215. /// Writes any packet send rate change information into the packet.
  216. void write_packet_rate_info(bit_stream &bstream, packet_notify *note)
  217. {
  218. note->rate_changed = _local_rate_changed;
  219. _local_rate_changed = false;
  220. if(bstream.write_bool(note->rate_changed))
  221. {
  222. bstream.write_ranged_uint32(_local_rate.max_recv_bandwidth, 0, max_fixed_bandwidth);
  223. bstream.write_ranged_uint32(_local_rate.max_send_bandwidth, 0, max_fixed_bandwidth);
  224. bstream.write_ranged_uint32(_local_rate.min_packet_recv_period, 1, max_fixed_send_period);
  225. bstream.write_ranged_uint32(_local_rate.min_packet_send_period, 1, max_fixed_send_period);
  226. }
  227. }
  228. /// Reads any packet send rate information requests from the packet.
  229. void read_packet_rate_info(bit_stream &bstream)
  230. {
  231. if(bstream.read_bool())
  232. {
  233. _remote_rate.max_recv_bandwidth = bstream.read_ranged_uint32(0, max_fixed_bandwidth);
  234. _remote_rate.max_send_bandwidth = bstream.read_ranged_uint32(0, max_fixed_bandwidth);
  235. _remote_rate.min_packet_recv_period = bstream.read_ranged_uint32(1, max_fixed_send_period);
  236. _remote_rate.min_packet_send_period = bstream.read_ranged_uint32(1, max_fixed_send_period);
  237. compute_negotiated_rate();
  238. }
  239. }
  240. /// Called internally when the local or remote rate changes.
  241. void compute_negotiated_rate()
  242. {
  243. _current_packet_send_period = max(_local_rate.min_packet_send_period, _remote_rate.min_packet_recv_period);
  244. uint32 max_bandwidth = min(_local_rate.max_send_bandwidth, _remote_rate.max_recv_bandwidth);
  245. _current_packet_send_size = uint32(max_bandwidth * _current_packet_send_period * 0.001f);
  246. // make sure we don't try to overwrite the maximum packet size
  247. if(_current_packet_send_size > net::udp_socket::max_datagram_size)
  248. _current_packet_send_size = net::udp_socket::max_datagram_size;
  249. }
  250. /// Returns the notify structure for the current packet write, or last written packet.
  251. packet_notify *get_current_write_packet_notify()
  252. {
  253. return _notify_queue_tail;
  254. }
  255. bool window_full()
  256. {
  257. return _notify_queue_head && (_last_send_sequence - _notify_queue_head->sequence >= torque_sockets_packet_window_size - 2);
  258. }
  259. /// Clears out the pending notify list.
  260. void _clear_all_packet_notifies()
  261. {
  262. while(_notify_queue_head)
  263. on_packet_notify(0, false);
  264. }
  265. bool is_connection_host()
  266. {
  267. return !_is_initiator;
  268. }
  269. bool is_connection_initiator()
  270. {
  271. return _is_initiator;
  272. }
  273. net_connection(bool is_initiator = false)
  274. {
  275. _is_initiator = is_initiator;
  276. _round_trip_time = 0;
  277. _send_delay_credit = time(0);
  278. _last_update_time = time(0);
  279. _notify_queue_head = _notify_queue_tail = 0;
  280. _local_rate.max_recv_bandwidth = default_fixed_bandwidth;
  281. _local_rate.max_send_bandwidth = default_fixed_bandwidth;
  282. _local_rate.min_packet_recv_period = default_fixed_send_period;
  283. _local_rate.min_packet_send_period = default_fixed_send_period;
  284. _remote_rate = _local_rate;
  285. _local_rate_changed = true;
  286. compute_negotiated_rate();
  287. _last_send_sequence = 0;
  288. _state = state_start;
  289. }
  290. void set_interface(net_interface *interface)
  291. {
  292. _interface = interface;
  293. }
  294. net_interface *get_interface()
  295. {
  296. return _interface;
  297. }
  298. virtual ~net_connection()
  299. {
  300. _clear_all_packet_notifies();
  301. assert(_notify_queue_head == NULL);
  302. }
  303. protected:
  304. enum rate_defaults {
  305. default_fixed_bandwidth = 2500, ///< The default send/receive bandwidth - 2.5 Kb per second.
  306. default_fixed_send_period = 200, ///< The default delay between each packet send - approx 5 packets per second.
  307. max_fixed_bandwidth = 65535, ///< The maximum bandwidth for a connection using the fixed rate transmission method.
  308. max_fixed_send_period = 2047, ///< The maximum period between packets in the fixed rate send transmission method.
  309. };
  310. enum {
  311. minimum_padding_bits = 32, ///< ask subclasses to reserve at least this much.
  312. };
  313. bool _is_initiator;
  314. net_rate _local_rate; ///< Current communications rate negotiated for this connection.
  315. net_rate _remote_rate; ///< Maximum allowable communications rate for this connection.
  316. bool _local_rate_changed; ///< Set to true when the local connection's rate has changed.
  317. uint32 _current_packet_send_size; ///< Current size of each packet sent to the remote host.
  318. uint32 _current_packet_send_period; ///< Millisecond delay between sent packets.
  319. packet_notify *_notify_queue_head; ///< Linked list of structures representing the data in sent packets
  320. packet_notify *_notify_queue_tail; ///< Tail of the notify queue linked list. New packets are added to the end of the tail.
  321. torque_connection_id _connection;
  322. net::time _last_packet_recv_time; ///< time of the receipt of the last data packet.
  323. float32 _round_trip_time; ///< Running average round trip time.
  324. net::time _send_delay_credit; ///< Metric to help compensate for irregularities on fixed rate packet sends.
  325. net::time _last_update_time;
  326. safe_ptr<net_interface> _interface;
  327. uint32 _last_send_sequence;
  328. net::time _last_received_send_delay;
  329. };