PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/liquidwar6/src/lib/cnx/cnx.h

#
C Header | 278 lines | 91 code | 15 blank | 172 comment | 0 complexity | 6b65196b10d7065f684e7c6b98ad0c95 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-4.0
  1. /*
  2. Liquid War 6 is a unique multiplayer wargame.
  3. Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Christian Mauduit <ufoot@ufoot.org>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. Liquid War 6 homepage : http://www.gnu.org/software/liquidwar6/
  15. Contact author : ufoot@ufoot.org
  16. */
  17. #ifndef LIQUIDWAR6CNX_H
  18. #define LIQUIDWAR6CNX_H
  19. #include "../sys/sys.h"
  20. #include "../glb/glb.h"
  21. #define LW6CNX_WORST_PING_MSEC 3600000
  22. //#define LW6CNX_TICKET_TABLE_ACK_MSEC 30000
  23. /**
  24. * Used to hold generic client/server properties, set up by the backend,
  25. * can then be queried by the caller.
  26. */
  27. typedef struct lw6cnx_properties_s
  28. {
  29. /**
  30. * Gives an idea of what timeout one can expect with this backend,
  31. * this is not necessarly the exact timeout but it gives an order
  32. * of magnitude. Unit is seconds.
  33. */
  34. int hint_timeout;
  35. /**
  36. * Modifies the ping returned by terrain experience, this is a
  37. * way to help some kind of connections to be preferred over others.
  38. * Set it to N to add N milliseconds to the real ping. Adding a
  39. * few msecs, such as 1 or 5 will just give an advantage to a
  40. * given connection while not giving really wrong results.
  41. * High values like 50 or 100 seriously penalizes some kind of
  42. * connections, which is whishable, think of the httpd way to
  43. * send things for instance.
  44. */
  45. int ping_alter_base;
  46. /**
  47. * Modifies the ping returned by terrain experience, this is a
  48. * way to help some kind of connections to be preferred over others.
  49. * Set it to 100 for default value, means 100% of real ping delay,
  50. * set it to 50 to make the algorithm believe lag is twice lower
  51. * (this means, connection twice faster) and set it to 1000 to
  52. * make believe that everything is slow. In practice only a
  53. * slight alteration should be required, one should still favor
  54. * really fast connections when it's proved in real life that they
  55. * are faster!
  56. */
  57. int ping_alter_percent;
  58. /**
  59. * Wether this connexion is to be considered reliable or not.
  60. * Well, in LW6, all connexions are unrealiable since LW6 will
  61. * drop packets on purpose to simulate problems, but however,
  62. * some are well-known to be unreliable (UDP...) while others
  63. * are OK.
  64. */
  65. int reliable;
  66. /**
  67. * The backend id, beware, this is a static string, must
  68. * not be freed, and depends on backend library to be here,
  69. * if this one is unloaded, will point to nowhere.
  70. */
  71. const char *backend_id;
  72. }
  73. lw6cnx_properties_t;
  74. typedef struct lw6cnx_connection_s *lw6cnx_connection_p;
  75. /**
  76. * This structure holds all data associated to a physical connexion
  77. * with a remote peer. This includes informations about the local node,
  78. * informations about the peer, and protocol specific details. Depending
  79. * on which backend is used to handle the connection, it will behave
  80. * differently. If you search for attributes such as socket id, search
  81. * for them in backend_specific_data which is, in fact, handle by the
  82. * backend code.
  83. */
  84. typedef struct lw6cnx_connection_s
  85. {
  86. /// URL of our local node.
  87. char *local_url;
  88. /// URL of the remote node.
  89. char *remote_url;
  90. /// IP address of the remote node.
  91. char *remote_ip;
  92. /// IP port of the remote node.
  93. int remote_port;
  94. /// Password as clear text.
  95. char *password;
  96. /// Password as a checksum, what will be sent on the network.
  97. char *password_send_checksum;
  98. /// ID of the local node, as an unsigned 64-bit integer.
  99. u_int64_t local_id_int;
  100. /// ID of the local node, as an hexa string.
  101. char *local_id_str;
  102. /// ID of the remote node, as an unsigned 64-bit integer.
  103. u_int64_t remote_id_int;
  104. /// ID of the local node, as an hexa string.
  105. char *remote_id_str;
  106. /**
  107. * Will be set to 1 if the peer domain name is the same
  108. * as the one reported in the URL. For instance, if we
  109. * get a connection from 23.45.23.45, but this host claims
  110. * to be on www.foo.bar and DNS reports www.foo.bar as being
  111. * 111.222.111.222 then there's something strange. It could
  112. * just be someone doing NAT, but in all cases it's worth
  113. * mentionning, so we keep the information here. Having 0
  114. * here is a bad point for the connection.
  115. */
  116. int dns_ok;
  117. /**
  118. * The higher, the most reliable message sending will be.
  119. * It can never be perfect, LW6 will always drop some packets
  120. * from time to time, just to simulate real packet loss and
  121. * be sure if it happens, it's handled nicely.
  122. */
  123. int network_reliability;
  124. /// Properties got from the backend.
  125. lw6cnx_properties_t properties;
  126. /**
  127. * List of messages received. This is a list_r and not a plain
  128. * list because it can typically be filled and consumed in
  129. * different threads.
  130. */
  131. lw6sys_list_r_t *recv_list;
  132. /**
  133. * Send mutex, this will be used so that sending operations
  134. * are properly serialized. Indeed, threads that respond on the
  135. * fly could be likely to call this concurrently.
  136. */
  137. lw6sys_mutex_t *send_mutex;
  138. /**
  139. * This is used to handle keepalive. Actually, the protocol
  140. * is that from time to time FOO key is sent and then each
  141. * connection (in a tentacle object, typically) is supposed
  142. * to respond BAR key to show it has received the latest message.
  143. * This field just stores the value so that when we receive
  144. * a BAR message we know which key to check against.
  145. */
  146. u_int32_t foo_bar_key;
  147. /// The last time FOO was sent.
  148. int64_t last_send_foo_timestamp;
  149. /// The next time FOO needs to be sent.
  150. int64_t next_send_foo_timestamp;
  151. /// The current ping, updated when receiving BAR message.
  152. int ping_msec;
  153. /// Number of sent messages on this cnx
  154. int sent_nb_total;
  155. /// Number of successfully sent messages on this cnx
  156. int sent_nb_success;
  157. /// Number of failed sent messages on this cnx
  158. int sent_nb_fail;
  159. /// Last time something was received on this connection.
  160. int64_t last_recv_timestamp;
  161. /**
  162. * Store backend data, this is when, for instance, a socket handle
  163. * will be kept, or a library handle (CURL, to name it). Common
  164. * code does not know what's in there.
  165. */
  166. void *backend_specific_data;
  167. }
  168. lw6cnx_connection_t;
  169. /**
  170. * A common, shared table, to store all the tickets associated with
  171. * various connections. This needs to be in-memory and quite fast
  172. * for it's called very often (at each message, in fact) to perform
  173. * sanity checks and avoid fakes/cheaters.
  174. */
  175. typedef struct lw6cnx_ticket_table_s
  176. {
  177. /// Lock for the recv_table hash.
  178. lw6sys_spinlock_t *recv_spinlock;
  179. /// Lock for the recv_ack_table hash.
  180. lw6sys_spinlock_t *recv_ack_spinlock;
  181. /// Lock for the send_table hash.
  182. lw6sys_spinlock_t *send_spinlock;
  183. /**
  184. * Hash table containing the tickets for recv operations.
  185. * This table is auto-generated, if one asks for a ticket
  186. * for an unknown host, one is generated.
  187. * The key is the ID (64-bit integer) of the host, as an hexa string.
  188. */
  189. lw6sys_hash_t *recv_table;
  190. /**
  191. * Hash table containing wether the send ticket was received
  192. * by a given host. The data is just a NULL pointer, only if the
  193. * key is present, we know we don't need to resend our key to the peer.
  194. * An easy way to know that the key was sent is if the peer was abled
  195. * to produce a valid message/checksum.
  196. * The key is the ID (64-bit integer) of the host, as an hexa string.
  197. */
  198. lw6sys_hash_t *recv_ack_table;
  199. /**
  200. * Hash table containing the tickets for send operations.
  201. * Those tickets are typically received from the peers themselves
  202. * who generate them on the fly.
  203. * The key is the ID (64-bit integer) of the host, as an hexa string.
  204. */
  205. lw6sys_hash_t *send_table;
  206. }
  207. lw6cnx_ticket_table_t;
  208. /**
  209. * Used to hold a network message plus some metadata, such
  210. * as who it is for, and who emitted the message.
  211. */
  212. typedef struct lw6cnx_packet_s
  213. {
  214. /// Logical signature for the packet.
  215. u_int32_t logical_ticket_sig;
  216. /// Physical signature for the packet.
  217. u_int32_t physical_ticket_sig;
  218. /// Logical sender.
  219. u_int64_t logical_from_id;
  220. /// Logical receiver.
  221. u_int64_t logical_to_id;
  222. char *msg;
  223. } lw6cnx_packet_t;
  224. /* cnx-connection.c */
  225. extern lw6cnx_connection_t *lw6cnx_connection_new (lw6sys_context_t * sys_context, const char *local_url,
  226. const char *remote_url,
  227. const char *remote_ip,
  228. int remote_port,
  229. const char *password, u_int64_t local_id, u_int64_t remote_id, int dns_ok, int network_reliability);
  230. extern void lw6cnx_connection_free (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection);
  231. extern int lw6cnx_connection_should_send_foo (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection, int64_t now);
  232. extern void lw6cnx_connection_init_foo_bar_key (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection, int64_t now, int next_foo_delay);
  233. extern int lw6cnx_connection_lock_send (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection);
  234. extern void lw6cnx_connection_unlock_send (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection);
  235. extern int lw6cnx_connection_reliability_filter (lw6sys_context_t * sys_context, lw6cnx_connection_t * connection);
  236. /* cnx-packet.c */
  237. extern lw6cnx_packet_t *lw6cnx_packet_new (lw6sys_context_t * sys_context, u_int32_t logical_ticket_sig,
  238. u_int32_t physical_ticket_sig, u_int64_t logical_from_id, u_int64_t logical_to_id, const char *msg);
  239. extern void lw6cnx_packet_free (lw6sys_context_t * sys_context, lw6cnx_packet_t * packet);
  240. extern u_int32_t lw6cnx_packet_checksum (lw6sys_context_t * sys_context, const lw6cnx_packet_t * packet);
  241. extern int lw6cnx_packet_compare (lw6sys_context_t * sys_context, const lw6cnx_packet_t * a, const lw6cnx_packet_t * b);
  242. extern int lw6cnx_packet_sort_callback (lw6sys_context_t * sys_context, void *func_data, const void *ptr_a, const void *ptr_b);
  243. /* cnx-password.c */
  244. extern char *lw6cnx_password_checksum (lw6sys_context_t * sys_context, const char *seed, const char *password);
  245. extern int lw6cnx_password_verify (lw6sys_context_t * sys_context, const char *seed, const char *password_here, const char *password_received);
  246. /* cnx-test.c */
  247. extern int lw6cnx_test_register (lw6sys_context_t * sys_context, int mode);
  248. extern int lw6cnx_test_run (lw6sys_context_t * sys_context, int mode);
  249. /* cnx-tickettable.c */
  250. extern void lw6cnx_ticket_table_zero (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table);
  251. extern int lw6cnx_ticket_table_init (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, int hash_size);
  252. extern void lw6cnx_ticket_table_clear (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table);
  253. extern u_int64_t lw6cnx_ticket_table_get_recv (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, const char *peer_id);
  254. extern void lw6cnx_ticket_table_ack_recv (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, const char *peer_id, int ack_delay_msec);
  255. extern int lw6cnx_ticket_table_was_recv_exchanged (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, const char *peer_id);
  256. extern u_int64_t lw6cnx_ticket_table_get_send (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, const char *peer_id);
  257. extern void lw6cnx_ticket_table_set_send (lw6sys_context_t * sys_context, lw6cnx_ticket_table_t * ticket_table, const char *peer_id, u_int64_t send_ticket);
  258. #endif