2017-09-23 02:40:23 -05:00
/*
* connection . h
*
* Created on : Sep 23 , 2017
* Author : root
*/
# ifndef CONNECTION_H_
# define CONNECTION_H_
extern int disable_anti_replay ;
# include "connection.h"
# include "common.h"
# include "log.h"
# include "network.h"
2017-09-23 03:35:28 -05:00
# include "misc.h"
2018-07-19 01:23:25 -05:00
const int disable_conv_clear = 0 ; //a udp connection in the multiplexer is called conversation in this program,conv for short.
2017-09-23 03:35:28 -05:00
2017-09-23 02:40:23 -05:00
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
{
u64_t max_packet_received ;
char window [ anti_replay_window_size ] ;
anti_replay_seq_t anti_replay_seq ;
anti_replay_seq_t get_new_seq_for_send ( ) ;
anti_replay_t ( ) ;
void re_init ( ) ;
int is_vaild ( u64_t seq ) ;
} ; //anti_replay;
2018-07-19 01:23:25 -05:00
void server_clear_function ( u64_t u64 ) ;
# include <type_traits>
2017-09-23 02:40:23 -05:00
2018-07-19 01:23:25 -05:00
template < class T >
2017-09-23 02:40:23 -05:00
struct conv_manager_t // manage the udp connections
{
//typedef hash_map map;
2018-07-19 01:23:25 -05:00
unordered_map < T , u32_t > data_to_conv ; //conv and u64 are both supposed to be uniq
unordered_map < u32_t , T > conv_to_data ;
2017-09-23 02:40:23 -05:00
2018-07-19 03:18:07 -05:00
lru_collector_t < u32_t > lru ;
//unordered_map<u32_t,u64_t> conv_last_active_time;
2017-09-23 02:40:23 -05:00
2018-07-19 03:18:07 -05:00
//unordered_map<u32_t,u64_t>::iterator clear_it;
2017-09-23 02:40:23 -05:00
2018-07-19 01:23:25 -05:00
void ( * additional_clear_function ) ( T data ) = 0 ;
2017-09-23 02:40:23 -05:00
long long last_clear_time ;
2018-07-19 01:23:25 -05:00
conv_manager_t ( )
{
2018-07-19 03:18:07 -05:00
//clear_it=conv_last_active_time.begin();
2018-07-19 01:23:25 -05:00
long long last_clear_time = 0 ;
additional_clear_function = 0 ;
}
~ conv_manager_t ( )
{
clear ( ) ;
}
int get_size ( )
{
return conv_to_data . size ( ) ;
}
void reserve ( )
{
data_to_conv . reserve ( 10007 ) ;
conv_to_data . reserve ( 10007 ) ;
2018-07-19 03:18:07 -05:00
//conv_last_active_time.reserve(10007);
lru . mp . reserve ( 10007 ) ;
2018-07-19 01:23:25 -05:00
}
void clear ( )
{
if ( disable_conv_clear ) return ;
if ( additional_clear_function ! = 0 )
{
for ( auto it = conv_to_data . begin ( ) ; it ! = conv_to_data . end ( ) ; it + + )
{
//int fd=int((it->second<<32u)>>32u);
additional_clear_function ( it - > second ) ;
}
}
data_to_conv . clear ( ) ;
conv_to_data . clear ( ) ;
2018-07-19 03:18:07 -05:00
lru . clear ( ) ;
//conv_last_active_time.clear();
//clear_it=conv_last_active_time.begin();
2018-07-19 01:23:25 -05:00
}
u32_t get_new_conv ( )
{
u32_t conv = get_true_random_number_nz ( ) ;
while ( conv_to_data . find ( conv ) ! = conv_to_data . end ( ) )
{
conv = get_true_random_number_nz ( ) ;
}
return conv ;
}
int is_conv_used ( u32_t conv )
{
return conv_to_data . find ( conv ) ! = conv_to_data . end ( ) ;
}
int is_data_used ( T data )
{
return data_to_conv . find ( data ) ! = data_to_conv . end ( ) ;
}
u32_t find_conv_by_data ( T data )
{
return data_to_conv [ data ] ;
}
2018-07-19 05:32:25 -05:00
T find_data_by_conv ( u32_t conv )
2018-07-19 01:23:25 -05:00
{
return conv_to_data [ conv ] ;
}
int update_active_time ( u32_t conv )
{
2018-07-19 03:18:07 -05:00
//return conv_last_active_time[conv]=get_current_time();
lru . update ( conv ) ;
return 0 ;
2018-07-19 01:23:25 -05:00
}
2018-07-19 05:32:25 -05:00
int insert_conv ( u32_t conv , T data )
2018-07-19 01:23:25 -05:00
{
2018-07-19 05:32:25 -05:00
data_to_conv [ data ] = conv ;
conv_to_data [ conv ] = data ;
2018-07-19 03:18:07 -05:00
//conv_last_active_time[conv]=get_current_time();
lru . new_key ( conv ) ;
2018-07-19 01:23:25 -05:00
return 0 ;
}
int erase_conv ( u32_t conv )
{
if ( disable_conv_clear ) return 0 ;
2018-07-19 05:32:25 -05:00
T data = conv_to_data [ conv ] ;
if ( additional_clear_function ! = 0 )
2018-07-19 01:23:25 -05:00
{
2018-07-19 05:32:25 -05:00
additional_clear_function ( data ) ;
2018-07-19 01:23:25 -05:00
}
conv_to_data . erase ( conv ) ;
2018-07-19 05:32:25 -05:00
data_to_conv . erase ( data ) ;
2018-07-19 03:18:07 -05:00
//conv_last_active_time.erase(conv);
lru . erase ( conv ) ;
2018-07-19 01:23:25 -05:00
return 0 ;
}
2018-07-19 03:18:07 -05:00
int clear_inactive ( char * info = 0 )
2018-07-19 01:23:25 -05:00
{
if ( get_current_time ( ) - last_clear_time > conv_clear_interval )
{
last_clear_time = get_current_time ( ) ;
2018-07-19 03:18:07 -05:00
return clear_inactive0 ( info ) ;
2018-07-19 01:23:25 -05:00
}
return 0 ;
}
2018-07-19 03:18:07 -05:00
int clear_inactive0 ( char * info )
2018-07-19 01:23:25 -05:00
{
if ( disable_conv_clear ) return 0 ;
unordered_map < u32_t , u64_t > : : iterator it ;
unordered_map < u32_t , u64_t > : : iterator old_it ;
//map<uint32_t,uint64_t>::iterator it;
int cnt = 0 ;
2018-07-19 03:18:07 -05:00
//it=clear_it;
int size = lru . size ( ) ;
2018-07-19 01:23:25 -05:00
int num_to_clean = size / conv_clear_ratio + conv_clear_min ; //clear 1/10 each time,to avoid latency glitch
num_to_clean = min ( num_to_clean , size ) ;
2018-07-19 03:18:07 -05:00
my_time_t current_time = get_current_time ( ) ;
2018-07-19 01:23:25 -05:00
for ( ; ; )
{
if ( cnt > = num_to_clean ) break ;
2018-07-19 03:18:07 -05:00
if ( lru . empty ( ) ) break ;
2018-07-19 01:23:25 -05:00
2018-07-19 03:18:07 -05:00
u32_t conv ;
my_time_t ts = lru . peek_back ( conv ) ;
if ( current_time - ts < conv_timeout ) break ;
2018-07-19 01:23:25 -05:00
2018-07-19 03:18:07 -05:00
erase_conv ( conv ) ;
if ( info = = 0 )
2018-07-19 01:23:25 -05:00
{
2018-07-19 03:18:07 -05:00
mylog ( log_info , " conv %x cleared \n " , conv ) ;
2018-07-19 01:23:25 -05:00
}
else
{
2018-07-19 03:18:07 -05:00
mylog ( log_info , " [%s]conv %x cleared \n " , info , conv ) ;
2018-07-19 01:23:25 -05:00
}
cnt + + ;
}
return 0 ;
}
/*
2017-09-23 02:40:23 -05:00
conv_manager_t ( ) ;
~ conv_manager_t ( ) ;
int get_size ( ) ;
void reserve ( ) ;
void clear ( ) ;
u32_t get_new_conv ( ) ;
int is_conv_used ( u32_t conv ) ;
2018-07-19 01:23:25 -05:00
int is_u64_used ( T u64 ) ;
u32_t find_conv_by_u64 ( T u64 ) ;
T find_u64_by_conv ( u32_t conv ) ;
2017-09-23 02:40:23 -05:00
int update_active_time ( u32_t conv ) ;
2018-07-19 01:23:25 -05:00
int insert_conv ( u32_t conv , T u64 ) ;
2017-09-23 02:40:23 -05:00
int erase_conv ( u32_t conv ) ;
int clear_inactive ( char * ip_port = 0 ) ;
2018-07-19 01:23:25 -05:00
int clear_inactive0 ( char * ip_port ) ; */
2017-09-23 02:40:23 -05:00
} ; //g_conv_manager;
2018-07-20 03:44:53 -05:00
struct blob_t : not_copy_able_t //used in conn_info_t.
2017-09-23 02:40:23 -05:00
{
2018-07-20 03:44:53 -05:00
struct //conv_manager_t is here to avoid copying when a connection is recovered
//TODO maybe an unconstrained union is better, but struct is okay since conv_manger is small when no data is filled in.
2018-07-19 01:23:25 -05:00
{
2018-07-19 05:32:25 -05:00
conv_manager_t < address_t > c ;
2018-07-19 01:23:25 -05:00
conv_manager_t < u64_t > s ;
2018-07-20 03:44:53 -05:00
//avoid templates here and there, avoid pointer and type cast
2018-07-19 01:23:25 -05:00
} conv_manager ;
2018-07-20 03:44:53 -05:00
anti_replay_t anti_replay ; //anti_replay_t is here bc its huge,its allocation is delayed.
2017-09-23 02:40:23 -05:00
} ;
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
//handle multiple clients
{
current_state_t state ;
raw_info_t raw_info ;
u64_t last_state_time ;
u64_t last_hb_sent_time ; //client re-use this for retry
u64_t last_hb_recv_time ;
//long long last_resent_time;
id_t my_id ;
id_t oppsite_id ;
2017-10-30 07:21:27 -05:00
fd64_t timer_fd64 ;
2017-09-23 02:40:23 -05:00
id_t oppsite_const_id ;
blob_t * blob ;
uint8_t my_roller ;
uint8_t oppsite_roller ;
u64_t last_oppsite_roller_time ;
2017-11-01 08:25:50 -05:00
// ip_port_t ip_port;
2017-10-30 07:21:27 -05:00
2017-09-23 02:40:23 -05:00
/*
const uint32_t & ip = raw_info . recv_info . src_ip ;
const uint16_t & port = raw_info . recv_info . src_port ;
*/
void recover ( const conn_info_t & conn_info ) ;
void re_init ( ) ;
conn_info_t ( ) ;
void prepare ( ) ;
conn_info_t ( const conn_info_t & b ) ;
conn_info_t & operator = ( const conn_info_t & b ) ;
~ conn_info_t ( ) ;
} ; //g_conn_info;
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
{
u32_t ready_num ;
2017-10-30 07:21:27 -05:00
//unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
//unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
2017-09-23 02:40:23 -05:00
unordered_map < id_t , conn_info_t * > const_id_mp ;
2018-07-20 03:44:53 -05:00
unordered_map < address_t , conn_info_t * > mp ; //put it at end so that it de-consturcts first
2017-09-23 02:40:23 -05:00
2018-07-20 03:44:53 -05:00
lru_collector_t < address_t > lru ;
//unordered_map<u64_t,conn_info_t*>::iterator clear_it;
2017-09-23 02:40:23 -05:00
long long last_clear_time ;
conn_manager_t ( ) ;
2018-07-20 03:44:53 -05:00
int exist ( address_t addr ) ;
2017-09-23 02:40:23 -05:00
/*
int insert ( uint32_t ip , uint16_t port )
{
uint64_t u64 = 0 ;
u64 = ip ;
u64 < < = 32u ;
u64 | = port ;
mp [ u64 ] ;
return 0 ;
} */
2018-07-20 03:44:53 -05:00
conn_info_t * & find_insert_p ( address_t addr ) ; //be aware,the adress may change after rehash //not true?
conn_info_t & find_insert ( address_t addr ) ; //be aware,the adress may change after rehash
2017-09-23 02:40:23 -05:00
2018-07-20 03:44:53 -05:00
int erase ( unordered_map < address_t , conn_info_t * > : : iterator erase_it ) ;
2017-09-23 02:40:23 -05:00
int clear_inactive ( ) ;
int clear_inactive0 ( ) ;
} ;
2017-09-23 03:35:28 -05:00
extern conn_manager_t conn_manager ;
void server_clear_function ( u64_t u64 ) ;
2017-09-23 03:05:23 -05:00
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
//you have to design the protocol carefully, so that you wont be affect by relay attack
2018-02-24 17:26:29 -06:00
//int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
2017-09-23 03:05:23 -05:00
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
//you have to design the protocol carefully, so that you wont be affect by relay attack
int send_handshake ( raw_info_t & raw_info , id_t id1 , id_t id2 , id_t id3 ) ; // a warp for send_bare for sending handshake(this is not tcp handshake) easily
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.
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.
2018-02-24 17:26:29 -06:00
//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
2017-09-23 03:05:23 -05:00
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.
2017-09-23 02:40:23 -05:00
# endif /* CONNECTION_H_ */