wangyu- 8 years ago
parent
commit
0e77b0d5ab
5 changed files with 615 additions and 525 deletions
  1. 9 0
      common.h
  2. 457 0
      connection.cpp
  3. 145 0
      connection.h
  4. 3 524
      main.cpp
  5. 1 1
      makefile

+ 9 - 0
common.h

@@ -109,6 +109,15 @@ extern unordered_map<int, const char*> raw_mode_tostring ;
 extern int socket_buf_size;
 extern int force_socket_buf;
 
+enum server_current_state_t {server_idle=0,server_handshake1,server_ready};  //server state machine
+enum client_current_state_t {client_idle=0,client_tcp_handshake,client_handshake1,client_handshake2,client_ready};//client state machine
+
+union current_state_t
+{
+	server_current_state_t server_current_state;
+	client_current_state_t client_current_state;
+};
+
 typedef u32_t id_t;
 
 typedef u64_t iv_t;

+ 457 - 0
connection.cpp

@@ -0,0 +1,457 @@
+/*
+ * connection.cpp
+ *
+ *  Created on: Sep 23, 2017
+ *      Author: root
+ */
+
+#include "connection.h"
+
+
+
+int disable_anti_replay=0;//if anti_replay windows is diabled
+
+const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
+
+const int disable_conn_clear=0;//a raw connection is called conn.
+
+
+	anti_replay_seq_t anti_replay_t::get_new_seq_for_send()
+	{
+		return anti_replay_seq++;
+	}
+	anti_replay_t::anti_replay_t()
+	{
+		max_packet_received=0;
+		anti_replay_seq=get_true_random_number_64()/10;//random first seq
+		//memset(window,0,sizeof(window)); //not necessary
+	}
+	void anti_replay_t::re_init()
+	{
+		max_packet_received=0;
+		//memset(window,0,sizeof(window));
+	}
+
+	int anti_replay_t::is_vaild(u64_t seq)
+	{
+		if(disable_anti_replay) return 1;
+		//if(disabled) return 0;
+
+		if(seq==max_packet_received) return 0;
+		else if(seq>max_packet_received)
+		{
+			if(seq-max_packet_received>=anti_replay_window_size)
+			{
+				memset(window,0,sizeof(window));
+				window[seq%anti_replay_window_size]=1;
+			}
+			else
+			{
+				for (u64_t i=max_packet_received+1;i<seq;i++)
+					window[i%anti_replay_window_size]=0;
+				window[seq%anti_replay_window_size]=1;
+			}
+			max_packet_received=seq;
+			return 1;
+		}
+		else if(seq<max_packet_received)
+		{
+			if(max_packet_received-seq>=anti_replay_window_size) return 0;
+			else
+			{
+				if (window[seq%anti_replay_window_size]==1) return 0;
+				else
+				{
+					window[seq%anti_replay_window_size]=1;
+					return 1;
+				}
+			}
+		}
+
+
+		return 0; //for complier check
+	}
+
+
+void server_clear_function(u64_t u64);
+
+conv_manager_t::conv_manager_t()
+	{
+		clear_it=conv_last_active_time.begin();
+		long long last_clear_time=0;
+		//clear_function=0;
+	}
+conv_manager_t::~conv_manager_t()
+	{
+		clear();
+	}
+	int conv_manager_t::get_size()
+	{
+		return conv_to_u64.size();
+	}
+	void conv_manager_t::reserve()
+	{
+		u64_to_conv.reserve(10007);
+		conv_to_u64.reserve(10007);
+		conv_last_active_time.reserve(10007);
+	}
+	void conv_manager_t::clear()
+	{
+		if(disable_conv_clear) return ;
+
+		if(program_mode==server_mode)
+		{
+			for(it=conv_to_u64.begin();it!=conv_to_u64.end();it++)
+			{
+				//int fd=int((it->second<<32u)>>32u);
+				server_clear_function(  it->second);
+			}
+		}
+		u64_to_conv.clear();
+		conv_to_u64.clear();
+		conv_last_active_time.clear();
+
+		clear_it=conv_last_active_time.begin();
+
+	}
+	u32_t conv_manager_t::get_new_conv()
+	{
+		u32_t conv=get_true_random_number_nz();
+		while(conv_to_u64.find(conv)!=conv_to_u64.end())
+		{
+			conv=get_true_random_number_nz();
+		}
+		return conv;
+	}
+	int conv_manager_t::is_conv_used(u32_t conv)
+	{
+		return conv_to_u64.find(conv)!=conv_to_u64.end();
+	}
+	int conv_manager_t::is_u64_used(u64_t u64)
+	{
+		return u64_to_conv.find(u64)!=u64_to_conv.end();
+	}
+	u32_t conv_manager_t::find_conv_by_u64(u64_t u64)
+	{
+		return u64_to_conv[u64];
+	}
+	u64_t conv_manager_t::find_u64_by_conv(u32_t conv)
+	{
+		return conv_to_u64[conv];
+	}
+	int conv_manager_t::update_active_time(u32_t conv)
+	{
+		return conv_last_active_time[conv]=get_current_time();
+	}
+	int conv_manager_t::insert_conv(u32_t conv,u64_t u64)
+	{
+		u64_to_conv[u64]=conv;
+		conv_to_u64[conv]=u64;
+		conv_last_active_time[conv]=get_current_time();
+		return 0;
+	}
+	int conv_manager_t::erase_conv(u32_t conv)
+	{
+		if(disable_conv_clear) return 0;
+		u64_t u64=conv_to_u64[conv];
+		if(program_mode==server_mode)
+		{
+			server_clear_function(u64);
+		}
+		conv_to_u64.erase(conv);
+		u64_to_conv.erase(u64);
+		conv_last_active_time.erase(conv);
+		return 0;
+	}
+	int conv_manager_t::clear_inactive(char * ip_port)
+	{
+		if(get_current_time()-last_clear_time>conv_clear_interval)
+		{
+			last_clear_time=get_current_time();
+			return clear_inactive0(ip_port);
+		}
+		return 0;
+	}
+	int conv_manager_t::clear_inactive0(char * ip_port)
+	{
+		if(disable_conv_clear) return 0;
+
+
+		//map<uint32_t,uint64_t>::iterator it;
+		int cnt=0;
+		it=clear_it;
+		int size=conv_last_active_time.size();
+		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);
+
+		u64_t current_time=get_current_time();
+		for(;;)
+		{
+			if(cnt>=num_to_clean) break;
+			if(conv_last_active_time.begin()==conv_last_active_time.end()) break;
+
+			if(it==conv_last_active_time.end())
+			{
+				it=conv_last_active_time.begin();
+			}
+
+			if( current_time -it->second  >conv_timeout )
+			{
+				//mylog(log_info,"inactive conv %u cleared \n",it->first);
+				old_it=it;
+				it++;
+				u32_t conv= old_it->first;
+				erase_conv(old_it->first);
+				if(ip_port==0)
+				{
+					mylog(log_info,"conv %x cleared\n",conv);
+				}
+				else
+				{
+					mylog(log_info,"[%s]conv %x cleared\n",ip_port,conv);
+				}
+			}
+			else
+			{
+				it++;
+			}
+			cnt++;
+		}
+		return 0;
+	}
+
+
+	 void conn_info_t::recover(const conn_info_t &conn_info)
+	 {
+			raw_info=conn_info.raw_info;
+			last_state_time=conn_info.last_state_time;
+			last_hb_recv_time=conn_info.last_hb_recv_time;
+			last_hb_sent_time=conn_info.last_hb_sent_time;
+			my_id=conn_info.my_id;
+			oppsite_id=conn_info.oppsite_id;
+			blob->anti_replay.re_init();
+
+			my_roller=0;//no need to set,but for easier debug,set it to zero
+			oppsite_roller=0;//same as above
+			last_oppsite_roller_time=0;
+	 }
+
+	void conn_info_t::re_init()
+	{
+		//send_packet_info.protocol=g_packet_info_send.protocol;
+		if(program_mode==server_mode)
+			state.server_current_state=server_idle;
+		else
+			state.client_current_state=client_idle;
+		last_state_time=0;
+		oppsite_const_id=0;
+
+		timer_fd=0;
+
+		my_roller=0;
+		oppsite_roller=0;
+		last_oppsite_roller_time=0;
+	}
+	conn_info_t::conn_info_t()
+	{
+		blob=0;
+		re_init();
+	}
+	void conn_info_t::prepare()
+	{
+		blob=new blob_t;
+
+	}
+	conn_info_t::conn_info_t(const conn_info_t&b)
+	{
+		//mylog(log_error,"called!!!!!!!!!!!!!\n");
+		*this=b;
+		if(blob!=0)
+		{
+			blob=new blob_t(*b.blob);
+		}
+	}
+	conn_info_t& conn_info_t::operator=(const conn_info_t& b)
+	  {
+		mylog(log_fatal,"not allowed\n");
+		myexit(-1);
+	    return *this;
+	  }
+	conn_info_t::~conn_info_t()
+	{
+		if(program_mode==server_mode)
+		{
+			if(state.server_current_state==server_ready)
+			{
+				assert(blob!=0);
+				assert(oppsite_const_id!=0);
+				//assert(conn_manager.const_id_mp.find(oppsite_const_id)!=conn_manager.const_id_mp.end()); // conn_manager 's deconstuction function  erases it
+			}
+			else
+			{
+				assert(blob==0);
+				assert(oppsite_const_id==0);
+			}
+		}
+		//if(oppsite_const_id!=0)     //do this at conn_manager 's deconstuction function
+			//conn_manager.const_id_mp.erase(oppsite_const_id);
+		if(blob!=0)
+			delete blob;
+
+		//send_packet_info.protocol=g_packet_info_send.protocol;
+	}
+
+
+	conn_manager_t::conn_manager_t()
+ {
+	 ready_num=0;
+	 mp.reserve(10007);
+	 clear_it=mp.begin();
+	 timer_fd_mp.reserve(10007);
+	 const_id_mp.reserve(10007);
+	 udp_fd_mp.reserve(100007);
+	 last_clear_time=0;
+	 //current_ready_ip=0;
+	// current_ready_port=0;
+ }
+ int conn_manager_t::exist(u32_t ip,uint16_t port)
+ {
+	 u64_t u64=0;
+	 u64=ip;
+	 u64<<=32u;
+	 u64|=port;
+	 if(mp.find(u64)!=mp.end())
+	 {
+		 return 1;
+	 }
+	 return 0;
+ }
+ /*
+ int insert(uint32_t ip,uint16_t port)
+ {
+	 uint64_t u64=0;
+	 u64=ip;
+	 u64<<=32u;
+	 u64|=port;
+	 mp[u64];
+	 return 0;
+ }*/
+ conn_info_t *& conn_manager_t::find_insert_p(u32_t ip,uint16_t port)  //be aware,the adress may change after rehash
+ {
+	 u64_t u64=0;
+	 u64=ip;
+	 u64<<=32u;
+	 u64|=port;
+	 unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
+	 if(it==mp.end())
+	 {
+		 mp[u64]=new conn_info_t;
+	 }
+	 return mp[u64];
+ }
+ conn_info_t & conn_manager_t::find_insert(u32_t ip,uint16_t port)  //be aware,the adress may change after rehash
+ {
+	 u64_t u64=0;
+	 u64=ip;
+	 u64<<=32u;
+	 u64|=port;
+	 unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
+	 if(it==mp.end())
+	 {
+		 mp[u64]=new conn_info_t;
+	 }
+	 return *mp[u64];
+ }
+ int conn_manager_t::erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it)
+ {
+		if(erase_it->second->state.server_current_state==server_ready)
+		{
+			ready_num--;
+			assert(i32_t(ready_num)!=-1);
+			assert(erase_it->second!=0);
+			assert(erase_it->second->timer_fd !=0);
+			assert(erase_it->second->oppsite_const_id!=0);
+			assert(const_id_mp.find(erase_it->second->oppsite_const_id)!=const_id_mp.end());
+			assert(timer_fd_mp.find(erase_it->second->timer_fd)!=timer_fd_mp.end());
+
+			const_id_mp.erase(erase_it->second->oppsite_const_id);
+			timer_fd_mp.erase(erase_it->second->timer_fd);
+			close(erase_it->second->timer_fd);// close will auto delte it from epoll
+			delete(erase_it->second);
+			mp.erase(erase_it->first);
+		}
+		else
+		{
+			assert(erase_it->second->blob==0);
+			assert(erase_it->second->timer_fd ==0);
+			assert(erase_it->second->oppsite_const_id==0);
+			delete(erase_it->second);
+			mp.erase(erase_it->first);
+		}
+		return 0;
+ }
+int conn_manager_t::clear_inactive()
+{
+	if(get_current_time()-last_clear_time>conn_clear_interval)
+	{
+		last_clear_time=get_current_time();
+		return clear_inactive0();
+	}
+	return 0;
+}
+int conn_manager_t::clear_inactive0()
+{
+	 unordered_map<u64_t,conn_info_t*>::iterator it;
+	 unordered_map<u64_t,conn_info_t*>::iterator old_it;
+
+	if(disable_conn_clear) return 0;
+
+	//map<uint32_t,uint64_t>::iterator it;
+	int cnt=0;
+	it=clear_it;
+	int size=mp.size();
+	int num_to_clean=size/conn_clear_ratio+conn_clear_min;   //clear 1/10 each time,to avoid latency glitch
+
+	mylog(log_trace,"mp.size() %d\n", size);
+
+	num_to_clean=min(num_to_clean,(int)mp.size());
+	u64_t current_time=get_current_time();
+
+	for(;;)
+	{
+		if(cnt>=num_to_clean) break;
+		if(mp.begin()==mp.end()) break;
+
+		if(it==mp.end())
+		{
+			it=mp.begin();
+		}
+
+		if(it->second->state.server_current_state==server_ready &&current_time - it->second->last_hb_recv_time  <=server_conn_timeout)
+		{
+				it++;
+		}
+		else if(it->second->state.server_current_state!=server_ready&& current_time - it->second->last_state_time  <=server_handshake_timeout )
+		{
+			it++;
+		}
+		else if(it->second->blob!=0&&it->second->blob->conv_manager.get_size() >0)
+		{
+			assert(it->second->state.server_current_state==server_ready);
+			it++;
+		}
+		else
+		{
+			mylog(log_info,"[%s:%d]inactive conn cleared \n",my_ntoa(it->second->raw_info.recv_info.src_ip),it->second->raw_info.recv_info.src_port);
+			old_it=it;
+			it++;
+			erase(old_it);
+		}
+		cnt++;
+	}
+	return 0;
+}
+
+
+

+ 145 - 0
connection.h

@@ -0,0 +1,145 @@
+/*
+ * 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"
+
+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;
+
+
+struct conv_manager_t  // manage the udp connections
+{
+	//typedef hash_map map;
+	unordered_map<u64_t,u32_t> u64_to_conv;  //conv and u64 are both supposed to be uniq
+	unordered_map<u32_t,u64_t> conv_to_u64;
+
+	unordered_map<u32_t,u64_t> conv_last_active_time;
+
+	unordered_map<u32_t,u64_t>::iterator clear_it;
+
+	unordered_map<u32_t,u64_t>::iterator it;
+	unordered_map<u32_t,u64_t>::iterator old_it;
+
+	//void (*clear_function)(uint64_t u64) ;
+
+	long long last_clear_time;
+
+	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);
+	int is_u64_used(u64_t u64);
+	u32_t find_conv_by_u64(u64_t u64);
+	u64_t find_u64_by_conv(u32_t conv);
+	int update_active_time(u32_t conv);
+	int insert_conv(u32_t conv,u64_t u64);
+	int erase_conv(u32_t conv);
+	int clear_inactive(char * ip_port=0);
+	int clear_inactive0(char * ip_port);
+};//g_conv_manager;
+
+struct blob_t  //used in conn_info_t.  conv_manager_t and anti_replay_t are costly data structures ,we dont allocate them until its necessary
+{
+	conv_manager_t conv_manager;
+	anti_replay_t anti_replay;
+};
+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;
+
+
+	int timer_fd;
+	id_t oppsite_const_id;
+
+	blob_t *blob;
+
+	uint8_t my_roller;
+	uint8_t oppsite_roller;
+	u64_t last_oppsite_roller_time;
+
+/*
+	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;
+
+ 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
+
+ unordered_map<id_t,conn_info_t *> const_id_mp;
+
+ unordered_map<u64_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
+
+ unordered_map<u64_t,conn_info_t*>::iterator clear_it;
+
+ long long last_clear_time;
+
+ conn_manager_t();
+ int exist(u32_t ip,uint16_t port);
+ /*
+ int insert(uint32_t ip,uint16_t port)
+ {
+	 uint64_t u64=0;
+	 u64=ip;
+	 u64<<=32u;
+	 u64|=port;
+	 mp[u64];
+	 return 0;
+ }*/
+ conn_info_t *& find_insert_p(u32_t ip,uint16_t port);  //be aware,the adress may change after rehash
+ conn_info_t & find_insert(u32_t ip,uint16_t port) ; //be aware,the adress may change after rehash
+
+ int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it);
+int clear_inactive();
+int clear_inactive0();
+
+};
+
+#endif /* CONNECTION_H_ */

+ 3 - 524
main.cpp

@@ -1,5 +1,6 @@
 #include "common.h"
 #include "network.h"
+#include "connection.h"
 #include "log.h"
 #include "lib/md5.h"
 #include "encrypt.h"
@@ -20,18 +21,6 @@ int force_source_ip=0; //if --source-ip is enabled
 id_t const_id=0;//an id used for connection recovery,its generated randomly,it never change since its generated
 
 
-const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
-
-const int disable_conn_clear=0;//a raw connection is called conn.
-
-
-enum server_current_state_t {server_idle=0,server_handshake1,server_ready};  //server state machine
-enum client_current_state_t {client_idle=0,client_tcp_handshake,client_handshake1,client_handshake2,client_ready};//client state machine
-union current_state_t
-{
-	server_current_state_t server_current_state;
-	client_current_state_t client_current_state;
-};
 
 int udp_fd=-1;  //for client only. client use this fd to listen and handle udp connection
 int bind_fd=-1; //bind only,never send or recv.  its just a dummy fd for bind,so that other program wont occupy the same port
@@ -49,7 +38,7 @@ int generate_iptables_rule=0;//if -g is set
 int generate_iptables_rule_add=0;// if --gen-add is set
 
 int debug_resend=0; // debug only
-int disable_anti_replay=0;//if anti_replay windows is diabled
+
 char key_string[1000]= "secret key";// -k option
 char key[16];//generated from key_string by md5.
 
@@ -57,520 +46,10 @@ int mtu_warn=1375;//if a packet larger than mtu warn is receviced,there will be
 
 //uint64_t current_time_rough=0;
 
-
+conn_manager_t conn_manager;
 int VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV;
 ////////==============================variable divider=============================================================
 
-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()
-	{
-		return anti_replay_seq++;
-	}
-	anti_replay_t()
-	{
-		max_packet_received=0;
-		anti_replay_seq=get_true_random_number_64()/10;//random first seq
-		//memset(window,0,sizeof(window)); //not necessary
-	}
-	void re_init()
-	{
-		max_packet_received=0;
-		//memset(window,0,sizeof(window));
-	}
-
-	int is_vaild(u64_t seq)
-	{
-		if(disable_anti_replay) return 1;
-		//if(disabled) return 0;
-
-		if(seq==max_packet_received) return 0;
-		else if(seq>max_packet_received)
-		{
-			if(seq-max_packet_received>=anti_replay_window_size)
-			{
-				memset(window,0,sizeof(window));
-				window[seq%anti_replay_window_size]=1;
-			}
-			else
-			{
-				for (u64_t i=max_packet_received+1;i<seq;i++)
-					window[i%anti_replay_window_size]=0;
-				window[seq%anti_replay_window_size]=1;
-			}
-			max_packet_received=seq;
-			return 1;
-		}
-		else if(seq<max_packet_received)
-		{
-			if(max_packet_received-seq>=anti_replay_window_size) return 0;
-			else
-			{
-				if (window[seq%anti_replay_window_size]==1) return 0;
-				else
-				{
-					window[seq%anti_replay_window_size]=1;
-					return 1;
-				}
-			}
-		}
-
-
-		return 0; //for complier check
-	}
-};//anti_replay;
-
-void server_clear_function(u64_t u64);
-struct conv_manager_t  // manage the udp connections
-{
-	//typedef hash_map map;
-	unordered_map<u64_t,u32_t> u64_to_conv;  //conv and u64 are both supposed to be uniq
-	unordered_map<u32_t,u64_t> conv_to_u64;
-
-	unordered_map<u32_t,u64_t> conv_last_active_time;
-
-	unordered_map<u32_t,u64_t>::iterator clear_it;
-
-	unordered_map<u32_t,u64_t>::iterator it;
-	unordered_map<u32_t,u64_t>::iterator old_it;
-
-	//void (*clear_function)(uint64_t u64) ;
-
-	long long last_clear_time;
-
-	conv_manager_t()
-	{
-		clear_it=conv_last_active_time.begin();
-		long long last_clear_time=0;
-		//clear_function=0;
-	}
-	~conv_manager_t()
-	{
-		clear();
-	}
-	int get_size()
-	{
-		return conv_to_u64.size();
-	}
-	void reserve()
-	{
-		u64_to_conv.reserve(10007);
-		conv_to_u64.reserve(10007);
-		conv_last_active_time.reserve(10007);
-	}
-	void clear()
-	{
-		if(disable_conv_clear) return ;
-
-		if(program_mode==server_mode)
-		{
-			for(it=conv_to_u64.begin();it!=conv_to_u64.end();it++)
-			{
-				//int fd=int((it->second<<32u)>>32u);
-				server_clear_function(  it->second);
-			}
-		}
-		u64_to_conv.clear();
-		conv_to_u64.clear();
-		conv_last_active_time.clear();
-
-		clear_it=conv_last_active_time.begin();
-
-	}
-	u32_t get_new_conv()
-	{
-		u32_t conv=get_true_random_number_nz();
-		while(conv_to_u64.find(conv)!=conv_to_u64.end())
-		{
-			conv=get_true_random_number_nz();
-		}
-		return conv;
-	}
-	int is_conv_used(u32_t conv)
-	{
-		return conv_to_u64.find(conv)!=conv_to_u64.end();
-	}
-	int is_u64_used(u64_t u64)
-	{
-		return u64_to_conv.find(u64)!=u64_to_conv.end();
-	}
-	u32_t find_conv_by_u64(u64_t u64)
-	{
-		return u64_to_conv[u64];
-	}
-	u64_t find_u64_by_conv(u32_t conv)
-	{
-		return conv_to_u64[conv];
-	}
-	int update_active_time(u32_t conv)
-	{
-		return conv_last_active_time[conv]=get_current_time();
-	}
-	int insert_conv(u32_t conv,u64_t u64)
-	{
-		u64_to_conv[u64]=conv;
-		conv_to_u64[conv]=u64;
-		conv_last_active_time[conv]=get_current_time();
-		return 0;
-	}
-	int erase_conv(u32_t conv)
-	{
-		if(disable_conv_clear) return 0;
-		u64_t u64=conv_to_u64[conv];
-		if(program_mode==server_mode)
-		{
-			server_clear_function(u64);
-		}
-		conv_to_u64.erase(conv);
-		u64_to_conv.erase(u64);
-		conv_last_active_time.erase(conv);
-		return 0;
-	}
-	int clear_inactive(char * ip_port=0)
-	{
-		if(get_current_time()-last_clear_time>conv_clear_interval)
-		{
-			last_clear_time=get_current_time();
-			return clear_inactive0(ip_port);
-		}
-		return 0;
-	}
-	int clear_inactive0(char * ip_port)
-	{
-		if(disable_conv_clear) return 0;
-
-
-		//map<uint32_t,uint64_t>::iterator it;
-		int cnt=0;
-		it=clear_it;
-		int size=conv_last_active_time.size();
-		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);
-
-		u64_t current_time=get_current_time();
-		for(;;)
-		{
-			if(cnt>=num_to_clean) break;
-			if(conv_last_active_time.begin()==conv_last_active_time.end()) break;
-
-			if(it==conv_last_active_time.end())
-			{
-				it=conv_last_active_time.begin();
-			}
-
-			if( current_time -it->second  >conv_timeout )
-			{
-				//mylog(log_info,"inactive conv %u cleared \n",it->first);
-				old_it=it;
-				it++;
-				u32_t conv= old_it->first;
-				erase_conv(old_it->first);
-				if(ip_port==0)
-				{
-					mylog(log_info,"conv %x cleared\n",conv);
-				}
-				else
-				{
-					mylog(log_info,"[%s]conv %x cleared\n",ip_port,conv);
-				}
-			}
-			else
-			{
-				it++;
-			}
-			cnt++;
-		}
-		return 0;
-	}
-};//g_conv_manager;
-struct blob_t  //used in conn_info_t.  conv_manager_t and anti_replay_t are costly data structures ,we dont allocate them until its necessary
-{
-	conv_manager_t conv_manager;
-	anti_replay_t anti_replay;
-};
-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;
-
-
-	int timer_fd;
-	id_t oppsite_const_id;
-
-	blob_t *blob;
-
-	uint8_t my_roller;
-	uint8_t oppsite_roller;
-	u64_t last_oppsite_roller_time;
-
-/*
-	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)
-	 {
-			raw_info=conn_info.raw_info;
-			last_state_time=conn_info.last_state_time;
-			last_hb_recv_time=conn_info.last_hb_recv_time;
-			last_hb_sent_time=conn_info.last_hb_sent_time;
-			my_id=conn_info.my_id;
-			oppsite_id=conn_info.oppsite_id;
-			blob->anti_replay.re_init();
-
-			my_roller=0;//no need to set,but for easier debug,set it to zero
-			oppsite_roller=0;//same as above
-			last_oppsite_roller_time=0;
-	 }
-
-	void re_init()
-	{
-		//send_packet_info.protocol=g_packet_info_send.protocol;
-		if(program_mode==server_mode)
-			state.server_current_state=server_idle;
-		else
-			state.client_current_state=client_idle;
-		last_state_time=0;
-		oppsite_const_id=0;
-
-		timer_fd=0;
-
-		my_roller=0;
-		oppsite_roller=0;
-		last_oppsite_roller_time=0;
-	}
-	conn_info_t()
-	{
-		blob=0;
-		re_init();
-	}
-	void prepare()
-	{
-		blob=new blob_t;
-
-	}
-	conn_info_t(const conn_info_t&b)
-	{
-		//mylog(log_error,"called!!!!!!!!!!!!!\n");
-		*this=b;
-		if(blob!=0)
-		{
-			blob=new blob_t(*b.blob);
-		}
-	}
-	conn_info_t& operator=(const conn_info_t& b)
-	  {
-		mylog(log_fatal,"not allowed\n");
-		myexit(-1);
-	    return *this;
-	  }
-	~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;
-
- 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
-
- unordered_map<id_t,conn_info_t *> const_id_mp;
-
- unordered_map<u64_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
-
- unordered_map<u64_t,conn_info_t*>::iterator clear_it;
-
- long long last_clear_time;
-
- conn_manager_t()
- {
-	 ready_num=0;
-	 mp.reserve(10007);
-	 clear_it=mp.begin();
-	 timer_fd_mp.reserve(10007);
-	 const_id_mp.reserve(10007);
-	 udp_fd_mp.reserve(100007);
-	 last_clear_time=0;
-	 //current_ready_ip=0;
-	// current_ready_port=0;
- }
- int exist(u32_t ip,uint16_t port)
- {
-	 u64_t u64=0;
-	 u64=ip;
-	 u64<<=32u;
-	 u64|=port;
-	 if(mp.find(u64)!=mp.end())
-	 {
-		 return 1;
-	 }
-	 return 0;
- }
- /*
- int insert(uint32_t ip,uint16_t port)
- {
-	 uint64_t u64=0;
-	 u64=ip;
-	 u64<<=32u;
-	 u64|=port;
-	 mp[u64];
-	 return 0;
- }*/
- conn_info_t *& find_insert_p(u32_t ip,uint16_t port)  //be aware,the adress may change after rehash
- {
-	 u64_t u64=0;
-	 u64=ip;
-	 u64<<=32u;
-	 u64|=port;
-	 unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
-	 if(it==mp.end())
-	 {
-		 mp[u64]=new conn_info_t;
-	 }
-	 return mp[u64];
- }
- conn_info_t & find_insert(u32_t ip,uint16_t port)  //be aware,the adress may change after rehash
- {
-	 u64_t u64=0;
-	 u64=ip;
-	 u64<<=32u;
-	 u64|=port;
-	 unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
-	 if(it==mp.end())
-	 {
-		 mp[u64]=new conn_info_t;
-	 }
-	 return *mp[u64];
- }
- int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it)
- {
-		if(erase_it->second->state.server_current_state==server_ready)
-		{
-			ready_num--;
-			assert(i32_t(ready_num)!=-1);
-			assert(erase_it->second!=0);
-			assert(erase_it->second->timer_fd !=0);
-			assert(erase_it->second->oppsite_const_id!=0);
-			assert(const_id_mp.find(erase_it->second->oppsite_const_id)!=const_id_mp.end());
-			assert(timer_fd_mp.find(erase_it->second->timer_fd)!=timer_fd_mp.end());
-
-			const_id_mp.erase(erase_it->second->oppsite_const_id);
-			timer_fd_mp.erase(erase_it->second->timer_fd);
-			close(erase_it->second->timer_fd);// close will auto delte it from epoll
-			delete(erase_it->second);
-			mp.erase(erase_it->first);
-		}
-		else
-		{
-			assert(erase_it->second->blob==0);
-			assert(erase_it->second->timer_fd ==0);
-			assert(erase_it->second->oppsite_const_id==0);
-			delete(erase_it->second);
-			mp.erase(erase_it->first);
-		}
-		return 0;
- }
-int clear_inactive()
-{
-	if(get_current_time()-last_clear_time>conn_clear_interval)
-	{
-		last_clear_time=get_current_time();
-		return clear_inactive0();
-	}
-	return 0;
-}
-int clear_inactive0()
-{
-	 unordered_map<u64_t,conn_info_t*>::iterator it;
-	 unordered_map<u64_t,conn_info_t*>::iterator old_it;
-
-	if(disable_conn_clear) return 0;
-
-	//map<uint32_t,uint64_t>::iterator it;
-	int cnt=0;
-	it=clear_it;
-	int size=mp.size();
-	int num_to_clean=size/conn_clear_ratio+conn_clear_min;   //clear 1/10 each time,to avoid latency glitch
-
-	mylog(log_trace,"mp.size() %d\n", size);
-
-	num_to_clean=min(num_to_clean,(int)mp.size());
-	u64_t current_time=get_current_time();
-
-	for(;;)
-	{
-		if(cnt>=num_to_clean) break;
-		if(mp.begin()==mp.end()) break;
-
-		if(it==mp.end())
-		{
-			it=mp.begin();
-		}
-
-		if(it->second->state.server_current_state==server_ready &&current_time - it->second->last_hb_recv_time  <=server_conn_timeout)
-		{
-				it++;
-		}
-		else if(it->second->state.server_current_state!=server_ready&& current_time - it->second->last_state_time  <=server_handshake_timeout )
-		{
-			it++;
-		}
-		else if(it->second->blob!=0&&it->second->blob->conv_manager.get_size() >0)
-		{
-			assert(it->second->state.server_current_state==server_ready);
-			it++;
-		}
-		else
-		{
-			mylog(log_info,"[%s:%d]inactive conn cleared \n",my_ntoa(it->second->raw_info.recv_info.src_ip),it->second->raw_info.recv_info.src_port);
-			old_it=it;
-			it++;
-			erase(old_it);
-		}
-		cnt++;
-	}
-	return 0;
-}
-
-}conn_manager;
-
-conn_info_t::~conn_info_t()
-{
-	if(program_mode==server_mode)
-	{
-		if(state.server_current_state==server_ready)
-		{
-			assert(blob!=0);
-			assert(oppsite_const_id!=0);
-			//assert(conn_manager.const_id_mp.find(oppsite_const_id)!=conn_manager.const_id_mp.end()); // conn_manager 's deconstuction function  erases it
-		}
-		else
-		{
-			assert(blob==0);
-			assert(oppsite_const_id==0);
-		}
-	}
-	//if(oppsite_const_id!=0)     //do this at conn_manager 's deconstuction function
-		//conn_manager.const_id_mp.erase(oppsite_const_id);
-	if(blob!=0)
-		delete blob;
-
-	//send_packet_info.protocol=g_packet_info_send.protocol;
-}
 
 int TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT;
 ////////==========================type divider=======================================================

+ 1 - 1
makefile

@@ -8,7 +8,7 @@ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
 #cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ 
 FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
 
-COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp  -lpthread
+COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp  connection.cpp -lpthread
 SOURCES= $(COMMON) lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c
 SOURCES_TINY_AES= $(COMMON) lib/aes.c
 SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)