connection.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * connection.h
  3. *
  4. * Created on: Sep 23, 2017
  5. * Author: root
  6. */
  7. #ifndef CONNECTION_H_
  8. #define CONNECTION_H_
  9. extern int disable_anti_replay;
  10. #include "connection.h"
  11. #include "common.h"
  12. #include "log.h"
  13. #include "network.h"
  14. #include "misc.h"
  15. const int disable_conv_clear = 0; // a udp connection in the multiplexer is called conversation in this program,conv for short.
  16. struct anti_replay_t // its for anti replay attack,similar to openvpn/ipsec 's anti replay window
  17. {
  18. u64_t max_packet_received;
  19. char window[anti_replay_window_size];
  20. anti_replay_seq_t anti_replay_seq;
  21. anti_replay_seq_t get_new_seq_for_send();
  22. anti_replay_t();
  23. void re_init();
  24. int is_vaild(u64_t seq);
  25. }; // anti_replay;
  26. void server_clear_function(u64_t u64);
  27. #include <type_traits>
  28. template <class T>
  29. struct conv_manager_t // manage the udp connections
  30. {
  31. // typedef hash_map map;
  32. unordered_map<T, u32_t> data_to_conv; // conv and u64 are both supposed to be uniq
  33. unordered_map<u32_t, T> conv_to_data;
  34. lru_collector_t<u32_t> lru;
  35. // unordered_map<u32_t,u64_t> conv_last_active_time;
  36. // unordered_map<u32_t,u64_t>::iterator clear_it;
  37. void (*additional_clear_function)(T data) = 0;
  38. long long last_clear_time;
  39. conv_manager_t() {
  40. // clear_it=conv_last_active_time.begin();
  41. long long last_clear_time = 0;
  42. additional_clear_function = 0;
  43. }
  44. ~conv_manager_t() {
  45. clear();
  46. }
  47. int get_size() {
  48. return conv_to_data.size();
  49. }
  50. void reserve() {
  51. data_to_conv.reserve(10007);
  52. conv_to_data.reserve(10007);
  53. // conv_last_active_time.reserve(10007);
  54. lru.mp.reserve(10007);
  55. }
  56. void clear() {
  57. if (disable_conv_clear) return;
  58. if (additional_clear_function != 0) {
  59. for (auto it = conv_to_data.begin(); it != conv_to_data.end(); it++) {
  60. // int fd=int((it->second<<32u)>>32u);
  61. additional_clear_function(it->second);
  62. }
  63. }
  64. data_to_conv.clear();
  65. conv_to_data.clear();
  66. lru.clear();
  67. // conv_last_active_time.clear();
  68. // clear_it=conv_last_active_time.begin();
  69. }
  70. u32_t get_new_conv() {
  71. u32_t conv = get_true_random_number_nz();
  72. while (conv_to_data.find(conv) != conv_to_data.end()) {
  73. conv = get_true_random_number_nz();
  74. }
  75. return conv;
  76. }
  77. int is_conv_used(u32_t conv) {
  78. return conv_to_data.find(conv) != conv_to_data.end();
  79. }
  80. int is_data_used(T data) {
  81. return data_to_conv.find(data) != data_to_conv.end();
  82. }
  83. u32_t find_conv_by_data(T data) {
  84. return data_to_conv[data];
  85. }
  86. T find_data_by_conv(u32_t conv) {
  87. return conv_to_data[conv];
  88. }
  89. int update_active_time(u32_t conv) {
  90. // return conv_last_active_time[conv]=get_current_time();
  91. lru.update(conv);
  92. return 0;
  93. }
  94. int insert_conv(u32_t conv, T data) {
  95. data_to_conv[data] = conv;
  96. conv_to_data[conv] = data;
  97. // conv_last_active_time[conv]=get_current_time();
  98. lru.new_key(conv);
  99. return 0;
  100. }
  101. int erase_conv(u32_t conv) {
  102. if (disable_conv_clear) return 0;
  103. T data = conv_to_data[conv];
  104. if (additional_clear_function != 0) {
  105. additional_clear_function(data);
  106. }
  107. conv_to_data.erase(conv);
  108. data_to_conv.erase(data);
  109. // conv_last_active_time.erase(conv);
  110. lru.erase(conv);
  111. return 0;
  112. }
  113. int clear_inactive(char *info = 0) {
  114. if (get_current_time() - last_clear_time > conv_clear_interval) {
  115. last_clear_time = get_current_time();
  116. return clear_inactive0(info);
  117. }
  118. return 0;
  119. }
  120. int clear_inactive0(char *info) {
  121. if (disable_conv_clear) return 0;
  122. unordered_map<u32_t, u64_t>::iterator it;
  123. unordered_map<u32_t, u64_t>::iterator old_it;
  124. // map<uint32_t,uint64_t>::iterator it;
  125. int cnt = 0;
  126. // it=clear_it;
  127. int size = lru.size();
  128. int num_to_clean = size / conv_clear_ratio + conv_clear_min; // clear 1/10 each time,to avoid latency glitch
  129. num_to_clean = min(num_to_clean, size);
  130. my_time_t current_time = get_current_time();
  131. for (;;) {
  132. if (cnt >= num_to_clean) break;
  133. if (lru.empty()) break;
  134. u32_t conv;
  135. my_time_t ts = lru.peek_back(conv);
  136. if (current_time - ts < conv_timeout) break;
  137. erase_conv(conv);
  138. if (info == 0) {
  139. mylog(log_info, "conv %x cleared\n", conv);
  140. } else {
  141. mylog(log_info, "[%s]conv %x cleared\n", info, conv);
  142. }
  143. cnt++;
  144. }
  145. return 0;
  146. }
  147. /*
  148. conv_manager_t();
  149. ~conv_manager_t();
  150. int get_size();
  151. void reserve();
  152. void clear();
  153. u32_t get_new_conv();
  154. int is_conv_used(u32_t conv);
  155. int is_u64_used(T u64);
  156. u32_t find_conv_by_u64(T u64);
  157. T find_u64_by_conv(u32_t conv);
  158. int update_active_time(u32_t conv);
  159. int insert_conv(u32_t conv,T u64);
  160. int erase_conv(u32_t conv);
  161. int clear_inactive(char * ip_port=0);
  162. int clear_inactive0(char * ip_port);*/
  163. }; // g_conv_manager;
  164. struct blob_t : not_copy_able_t // used in conn_info_t.
  165. {
  166. union tmp_union_t // conv_manager_t is here to avoid copying when a connection is recovered
  167. {
  168. conv_manager_t<address_t> c;
  169. conv_manager_t<u64_t> s;
  170. // avoid templates here and there, avoid pointer and type cast
  171. tmp_union_t() {
  172. if (program_mode == client_mode) {
  173. new (&c) conv_manager_t<address_t>();
  174. } else {
  175. assert(program_mode == server_mode);
  176. new (&s) conv_manager_t<u64_t>();
  177. }
  178. }
  179. ~tmp_union_t() {
  180. if (program_mode == client_mode) {
  181. c.~conv_manager_t<address_t>();
  182. } else {
  183. assert(program_mode == server_mode);
  184. s.~conv_manager_t<u64_t>();
  185. }
  186. }
  187. } conv_manager;
  188. anti_replay_t anti_replay; // anti_replay_t is here bc its huge,its allocation is delayed.
  189. };
  190. struct conn_info_t // stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can
  191. // handle multiple clients
  192. {
  193. current_state_t state;
  194. raw_info_t raw_info;
  195. u64_t last_state_time;
  196. u64_t last_hb_sent_time; // client re-use this for retry
  197. u64_t last_hb_recv_time;
  198. // long long last_resent_time;
  199. my_id_t my_id;
  200. my_id_t oppsite_id;
  201. fd64_t timer_fd64;
  202. fd64_t udp_fd64;
  203. my_id_t oppsite_const_id;
  204. blob_t *blob;
  205. uint8_t my_roller;
  206. uint8_t oppsite_roller;
  207. u64_t last_oppsite_roller_time;
  208. // ip_port_t ip_port;
  209. /*
  210. const uint32_t &ip=raw_info.recv_info.src_ip;
  211. const uint16_t &port=raw_info.recv_info.src_port;
  212. */
  213. void recover(const conn_info_t &conn_info);
  214. void re_init();
  215. conn_info_t();
  216. void prepare();
  217. conn_info_t(const conn_info_t &b);
  218. conn_info_t &operator=(const conn_info_t &b);
  219. ~conn_info_t();
  220. }; // g_conn_info;
  221. struct conn_manager_t // manager for connections. for client,we dont need conn_manager since there is only one connection.for server we use one conn_manager for all connections
  222. {
  223. u32_t ready_num;
  224. // unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
  225. // unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
  226. unordered_map<my_id_t, conn_info_t *> const_id_mp;
  227. unordered_map<address_t, conn_info_t *> mp; // put it at end so that it de-consturcts first
  228. // lru_collector_t<address_t> lru;
  229. unordered_map<address_t, conn_info_t *>::iterator clear_it;
  230. long long last_clear_time;
  231. conn_manager_t();
  232. int exist(address_t addr);
  233. /*
  234. int insert(uint32_t ip,uint16_t port)
  235. {
  236. uint64_t u64=0;
  237. u64=ip;
  238. u64<<=32u;
  239. u64|=port;
  240. mp[u64];
  241. return 0;
  242. }*/
  243. conn_info_t *&find_insert_p(address_t addr); // be aware,the adress may change after rehash //not true?
  244. conn_info_t &find_insert(address_t addr); // be aware,the adress may change after rehash
  245. int erase(unordered_map<address_t, conn_info_t *>::iterator erase_it);
  246. int clear_inactive();
  247. int clear_inactive0();
  248. };
  249. extern conn_manager_t conn_manager;
  250. void server_clear_function(u64_t u64);
  251. int send_bare(raw_info_t &raw_info, const char *data, int len); // send function with encryption but no anti replay,this is used when client and server verifys each other
  252. // you have to design the protocol carefully, so that you wont be affect by relay attack
  253. // int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
  254. int recv_bare(raw_info_t &raw_info, char *&data, int &len); // recv function with encryption but no anti replay,this is used when client and server verifys each other
  255. // you have to design the protocol carefully, so that you wont be affect by relay attack
  256. int send_handshake(raw_info_t &raw_info, my_id_t id1, my_id_t id2, my_id_t id3); // a warp for send_bare for sending handshake(this is not tcp handshake) easily
  257. int send_safer(conn_info_t &conn_info, char type, const char *data, int len); // safer transfer function with anti-replay,when mutually verification is done.
  258. int send_data_safer(conn_info_t &conn_info, const char *data, int len, u32_t conv_num); // a wrap for send_safer for transfer data.
  259. // int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
  260. // int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
  261. int recv_safer_multi(conn_info_t &conn_info, vector<char> &type_arr, vector<string> &data_arr); // new api for handle gro
  262. #endif /* CONNECTION_H_ */