diff --git a/common.cpp b/common.cpp index 5993a38..caafe12 100644 --- a/common.cpp +++ b/common.cpp @@ -329,3 +329,73 @@ void get_true_random_chars(char * s,int len) exit(-1); } } + +int random_between(u32_t a,u32_t b) +{ + if(a>b) + { + mylog(log_fatal,"min >max?? %d %d\n",a ,b); + myexit(1); + } + if(a==b)return a; + else return a+get_true_random_number()%(b+1-a); +} + + +int set_timer_ms(int epollfd,int &timer_fd,u32_t timer_interval) +{ + int ret; + epoll_event ev; + + itimerspec its; + memset(&its,0,sizeof(its)); + + if((timer_fd=timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0) + { + mylog(log_fatal,"timer_fd create error\n"); + myexit(1); + } + its.it_interval.tv_sec=(timer_interval/1000); + its.it_interval.tv_nsec=(timer_interval%1000)*1000ll*1000ll; + its.it_value.tv_nsec=1; //imidiately + timerfd_settime(timer_fd,0,&its,0); + + + ev.events = EPOLLIN; + ev.data.fd = timer_fd; + + ret=epoll_ctl(epollfd, EPOLL_CTL_ADD, timer_fd, &ev); + if (ret < 0) { + mylog(log_fatal,"epoll_ctl return %d\n", ret); + myexit(-1); + } + return 0; +} + +int create_new_udp(int &new_udp_fd,int remote_address_uint32,int remote_port) +{ + struct sockaddr_in remote_addr_in; + + socklen_t slen = sizeof(sockaddr_in); + memset(&remote_addr_in, 0, sizeof(remote_addr_in)); + remote_addr_in.sin_family = AF_INET; + remote_addr_in.sin_port = htons(remote_port); + remote_addr_in.sin_addr.s_addr = remote_address_uint32; + + new_udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (new_udp_fd < 0) { + mylog(log_warn, "create udp_fd error\n"); + return -1; + } + setnonblocking(new_udp_fd); + set_buf_size(new_udp_fd); + + mylog(log_debug, "created new udp_fd %d\n", new_udp_fd); + int ret = connect(new_udp_fd, (struct sockaddr *) &remote_addr_in, slen); + if (ret != 0) { + mylog(log_warn, "udp fd connect fail %d %s\n",ret,strerror(errno)); + close(new_udp_fd); + return -1; + } + return 0; +} diff --git a/common.h b/common.h index 80778a0..1f9242a 100644 --- a/common.h +++ b/common.h @@ -157,5 +157,10 @@ int add_iptables_rule(char *); int clear_iptables_rule(); void get_true_random_chars(char * s,int len); +int random_between(u32_t a,u32_t b); + +int set_timer_ms(int epollfd,int &timer_fd,u32_t timer_interval); + +int create_new_udp(int &new_udp_fd,int remote_address_uint32,int remote_port); #endif /* COMMON_H_ */ diff --git a/conn_manager.cpp b/conn_manager.cpp new file mode 100644 index 0000000..45d2fc6 --- /dev/null +++ b/conn_manager.cpp @@ -0,0 +1,134 @@ +/* + * conn_manager.cpp + * + * Created on: Sep 15, 2017 + * Author: root + */ + +#include "conn_manager.h" + +int disable_conv_clear=0; + +conn_manager_t::conn_manager_t() { + clear_it = fd_last_active_time.begin(); + long long last_clear_time = 0; + rehash(); + //clear_function=0; +} +conn_manager_t::~conn_manager_t() { + clear(); +} +int conn_manager_t::get_size() { + return fd_to_u64.size(); +} +void conn_manager_t::rehash() { + u64_to_fd.rehash(10007); + fd_to_u64.rehash(10007); + fd_last_active_time.rehash(10007); +} +void conn_manager_t::clear() { + if (disable_conv_clear) + return; + + for (it = fd_to_u64.begin(); it != fd_to_u64.end(); it++) { + //int fd=int((it->second<<32u)>>32u); + close(it->first); + } + u64_to_fd.clear(); + fd_to_u64.clear(); + fd_last_active_time.clear(); + + clear_it = fd_last_active_time.begin(); + +} +int conn_manager_t::exist_fd(u32_t fd) { + return fd_to_u64.find(fd) != fd_to_u64.end(); +} +int conn_manager_t::exist_u64(u64_t u64) { + return u64_to_fd.find(u64) != u64_to_fd.end(); +} +u32_t conn_manager_t::find_fd_by_u64(u64_t u64) { + return u64_to_fd[u64]; +} +u64_t conn_manager_t::find_u64_by_fd(u32_t fd) { + return fd_to_u64[fd]; +} +int conn_manager_t::update_active_time(u32_t fd) { + return fd_last_active_time[fd] = get_current_time(); +} +int conn_manager_t::insert_fd(u32_t fd, u64_t u64) { + u64_to_fd[u64] = fd; + fd_to_u64[fd] = u64; + fd_last_active_time[fd] = get_current_time(); + return 0; +} +int conn_manager_t::erase_fd(u32_t fd) { + if (disable_conv_clear) + return 0; + u64_t u64 = fd_to_u64[fd]; + + u32_t ip = (u64 >> 32u); + + int port = uint16_t((u64 << 32u) >> 32u); + + mylog(log_info, "fd %d cleared,assocated adress %s,%d\n", fd, my_ntoa(ip), + port); + + close(fd); + + fd_to_u64.erase(fd); + u64_to_fd.erase(u64); + fd_last_active_time.erase(fd); + return 0; +} +void conn_manager_t::check_clear_list() { + while (!clear_list.empty()) { + int fd = *clear_list.begin(); + clear_list.pop_front(); + erase_fd(fd); + } +} +int conn_manager_t::clear_inactive() { + if (get_current_time() - last_clear_time > conv_clear_interval) { + last_clear_time = get_current_time(); + return clear_inactive0(); + } + return 0; +} +int conn_manager_t::clear_inactive0() { + if (disable_conv_clear) + return 0; + + //map::iterator it; + int cnt = 0; + it = clear_it; + int size = fd_last_active_time.size(); + int num_to_clean = size / conv_clear_ratio + conv_clear_min; //clear 1/10 each time,to avoid latency glitch + + u64_t current_time = get_current_time(); + for (;;) { + if (cnt >= num_to_clean) + break; + if (fd_last_active_time.begin() == fd_last_active_time.end()) + break; + + if (it == fd_last_active_time.end()) { + it = fd_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 fd = old_it->first; + erase_fd(old_it->first); + + } else { + it++; + } + cnt++; + } + return 0; +} + + diff --git a/conn_manager.h b/conn_manager.h new file mode 100644 index 0000000..c4a2dce --- /dev/null +++ b/conn_manager.h @@ -0,0 +1,52 @@ +/* + * conn_manager.h + * + * Created on: Sep 15, 2017 + * Author: root + */ + +#ifndef CONN_MANAGER_H_ +#define CONN_MANAGER_H_ + +#include "common.h" +#include "log.h" + +extern int disable_conv_clear; + +struct conn_manager_t //TODO change map to unordered map +{ + //typedef hash_map map; + unordered_map u64_to_fd; //conv and u64 are both supposed to be uniq + unordered_map fd_to_u64; + + unordered_map fd_last_active_time; + + unordered_map::iterator clear_it; + + unordered_map::iterator it; + unordered_map::iterator old_it; + + //void (*clear_function)(uint64_t u64) ; + + long long last_clear_time; + list clear_list; + conn_manager_t(); + ~conn_manager_t(); + int get_size(); + void rehash(); + void clear(); + int exist_fd(u32_t fd); + int exist_u64(u64_t u64); + u32_t find_fd_by_u64(u64_t u64); + u64_t find_u64_by_fd(u32_t fd); + int update_active_time(u32_t fd); + int insert_fd(u32_t fd,u64_t u64); + int erase_fd(u32_t fd); + void check_clear_list(); + int clear_inactive(); + int clear_inactive0(); + +}; + + +#endif /* CONN_MANAGER_H_ */ diff --git a/lib/fec.h b/lib/fec.h index 871af50..dab12b6 100644 --- a/lib/fec.h +++ b/lib/fec.h @@ -46,7 +46,7 @@ void fec_free(void *p) ; void * fec_new(int k, int n) ;//n>=k -void init_fec() ; +void init_fec() ; //if you never called this,it will be automatically called in fec_new() void fec_encode(void *code, void *src[], void *dst, int index, int sz) ; int fec_decode(void *code, void *pkt[], int index[], int sz) ; diff --git a/main.cpp b/main.cpp index 1ab0e1a..9b39265 100644 --- a/main.cpp +++ b/main.cpp @@ -2,6 +2,8 @@ #include "log.h" #include "git_version.h" #include "lib/rs.h" +#include "packet.h" +#include "conn_manager.h" using namespace std; typedef unsigned long long u64_t; //this works on most platform,avoid using the PRId64 @@ -10,8 +12,8 @@ typedef long long i64_t; typedef unsigned int u32_t; typedef int i32_t; -typedef u64_t anti_replay_seq_t; -int disable_replay_filter=0; + + int dup_num=1; int dup_delay_min=20; //0.1ms int dup_delay_max=20; @@ -20,8 +22,6 @@ int dup_delay_max=20; int jitter_min=0; int jitter_max=0; -int iv_min=2; -int iv_max=16;//< 256; int random_number_fd=-1; int remote_fd=-1; @@ -29,257 +29,32 @@ int local_fd=-1; int is_client = 0, is_server = 0; int local_listen_fd=-1; -int disable_conv_clear=0; + int mtu_warn=1350; u32_t remote_address_uint32=0; char local_address[100], remote_address[100]; int local_port = -1, remote_port = -1; int multi_process_mode=0; -const u32_t anti_replay_buff_size=10000; -char key_string[1000]= "secret key"; + + int random_drop=0; u64_t last_report_time=0; int report_interval=0; -u64_t packet_send_count=0; -u64_t dup_packet_send_count=0; -u64_t packet_recv_count=0; -u64_t dup_packet_recv_count=0; + int max_pending_packet=0; -int random_between(u32_t a,u32_t b) -{ - if(a>b) - { - mylog(log_fatal,"min >max?? %d %d\n",a ,b); - myexit(1); - } - if(a==b)return a; - else return a+get_true_random_number()%(b+1-a); -} +conn_manager_t conn_manager; + int VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV; -struct anti_replay_t -{ - u64_t max_packet_received; - u64_t replay_buffer[anti_replay_buff_size]; - unordered_set st; - u32_t const_id; - u32_t anti_replay_seq; - int index; - anti_replay_seq_t get_new_seq_for_send() - { - anti_replay_seq_t res=const_id; - res<<=32u; - anti_replay_seq++; - res|=anti_replay_seq; - return res; - } - void prepare() - { - anti_replay_seq=get_true_random_number();//random first seq - const_id=get_true_random_number_nz(); - } - anti_replay_t() - { - memset(replay_buffer,0,sizeof(replay_buffer)); - st.rehash(anti_replay_buff_size*10); - max_packet_received=0; - index=0; - } - - int is_vaild(u64_t seq) - { - //if(disable_replay_filter) return 1; - if(seq==0) - { - mylog(log_debug,"seq=0\n"); - return 0; - } - if(st.find(seq)!=st.end() ) - { - mylog(log_trace,"seq %llx exist\n",seq); - return 0; - } - - if(replay_buffer[index]!=0) - { - assert(st.find(replay_buffer[index])!=st.end()); - st.erase(replay_buffer[index]); - } - replay_buffer[index]=seq; - st.insert(seq); - index++; - if(index==int(anti_replay_buff_size)) index=0; - - return 1; //for complier check - } -}anti_replay; -struct conn_manager_t //TODO change map to unordered map -{ - //typedef hash_map map; - unordered_map u64_to_fd; //conv and u64 are both supposed to be uniq - unordered_map fd_to_u64; - - unordered_map fd_last_active_time; - - unordered_map::iterator clear_it; - - unordered_map::iterator it; - unordered_map::iterator old_it; - - //void (*clear_function)(uint64_t u64) ; - - long long last_clear_time; - list clear_list; - conn_manager_t() - { - clear_it=fd_last_active_time.begin(); - long long last_clear_time=0; - rehash(); - //clear_function=0; - } - ~conn_manager_t() - { - clear(); - } - int get_size() - { - return fd_to_u64.size(); - } - void rehash() - { - u64_to_fd.rehash(10007); - fd_to_u64.rehash(10007); - fd_last_active_time.rehash(10007); - } - void clear() - { - if(disable_conv_clear) return ; - - for(it=fd_to_u64.begin();it!=fd_to_u64.end();it++) - { - //int fd=int((it->second<<32u)>>32u); - close( it->first); - } - u64_to_fd.clear(); - fd_to_u64.clear(); - fd_last_active_time.clear(); - - clear_it=fd_last_active_time.begin(); - - } - int exist_fd(u32_t fd) - { - return fd_to_u64.find(fd)!=fd_to_u64.end(); - } - int exist_u64(u64_t u64) - { - return u64_to_fd.find(u64)!=u64_to_fd.end(); - } - u32_t find_fd_by_u64(u64_t u64) - { - return u64_to_fd[u64]; - } - u64_t find_u64_by_fd(u32_t fd) - { - return fd_to_u64[fd]; - } - int update_active_time(u32_t fd) - { - return fd_last_active_time[fd]=get_current_time(); - } - int insert_fd(u32_t fd,u64_t u64) - { - u64_to_fd[u64]=fd; - fd_to_u64[fd]=u64; - fd_last_active_time[fd]=get_current_time(); - return 0; - } - int erase_fd(u32_t fd) - { - if(disable_conv_clear) return 0; - u64_t u64=fd_to_u64[fd]; - - u32_t ip= (u64 >> 32u); - - int port= uint16_t((u64 << 32u) >> 32u); - - mylog(log_info,"fd %d cleared,assocated adress %s,%d\n",fd,my_ntoa(ip),port); - - close(fd); - - fd_to_u64.erase(fd); - u64_to_fd.erase(u64); - fd_last_active_time.erase(fd); - return 0; - } - void check_clear_list() - { - while(!clear_list.empty()) - { - int fd=*clear_list.begin(); - clear_list.pop_front(); - erase_fd(fd); - } - } - int clear_inactive() - { - if(get_current_time()-last_clear_time>conv_clear_interval) - { - last_clear_time=get_current_time(); - return clear_inactive0(); - } - return 0; - } - int clear_inactive0() - { - if(disable_conv_clear) return 0; - - - //map::iterator it; - int cnt=0; - it=clear_it; - int size=fd_last_active_time.size(); - int num_to_clean=size/conv_clear_ratio+conv_clear_min; //clear 1/10 each time,to avoid latency glitch - - u64_t current_time=get_current_time(); - for(;;) - { - if(cnt>=num_to_clean) break; - if(fd_last_active_time.begin()==fd_last_active_time.end()) break; - - if(it==fd_last_active_time.end()) - { - it=fd_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 fd= old_it->first; - erase_fd(old_it->first); - - - } - else - { - it++; - } - cnt++; - } - return 0; - } -}conn_manager; typedef u64_t my_time_t; @@ -383,112 +158,7 @@ void handler(int num) { } } -void encrypt_0(char * input,int &len,char *key) -{ - int i,j; - if(key[0]==0) return; - for(i=0,j=0;i 65535||in_len<0) - return -1; - int iv_len=iv_min+rand()%(iv_max-iv_min); - get_true_random_chars(output,iv_len); - memcpy(output+iv_len,input,in_len); - - output[iv_len+in_len]=(uint8_t)iv_len; - - output[iv_len+in_len]^=output[0]; - output[iv_len+in_len]^=key_string[0]; - - for(i=0,j=0,k=1;i 65535||in_len<0) - { - mylog(log_debug,"in_len > 65535||in_len<0 , %d",in_len); - return -1; - } - int iv_len= int ((uint8_t)(input[in_len-1]^input[0]^key_string[0]) ); - out_len=in_len-1-iv_len; - if(out_len<0) - { - mylog(log_debug,"%d %d\n",in_len,out_len); - return -1; - } - for(i=0,j=0,k=1;i st; + u32_t const_id; + u32_t anti_replay_seq; + int index; + anti_replay_seq_t get_new_seq_for_send() + { + if(const_id==0) prepare(); + anti_replay_seq_t res=const_id; + res<<=32u; + anti_replay_seq++; + res|=anti_replay_seq; + const_id=0; + return res; + } + void prepare() + { + anti_replay_seq=get_true_random_number();//random first seq + const_id=get_true_random_number_nz(); + } + anti_replay_t() + { + memset(replay_buffer,0,sizeof(replay_buffer)); + st.rehash(anti_replay_buff_size*10); + max_packet_received=0; + index=0; + } + + int is_vaild(u64_t seq) + { + if(const_id==0) prepare(); + //if(disable_replay_filter) return 1; + if(seq==0) + { + mylog(log_debug,"seq=0\n"); + return 0; + } + if(st.find(seq)!=st.end() ) + { + mylog(log_trace,"seq %llx exist\n",seq); + return 0; + } + + if(replay_buffer[index]!=0) + { + assert(st.find(replay_buffer[index])!=st.end()); + st.erase(replay_buffer[index]); + } + replay_buffer[index]=seq; + st.insert(seq); + index++; + if(index==int(anti_replay_buff_size)) index=0; + + return 1; //for complier check + } +}anti_replay; + +void encrypt_0(char * input,int &len,char *key) +{ + int i,j; + if(key[0]==0) return; + for(i=0,j=0;i 65535||in_len<0) + return -1; + int iv_len=iv_min+rand()%(iv_max-iv_min); + get_true_random_chars(output,iv_len); + memcpy(output+iv_len,input,in_len); + + output[iv_len+in_len]=(uint8_t)iv_len; + + output[iv_len+in_len]^=output[0]; + output[iv_len+in_len]^=key_string[0]; + + for(i=0,j=0,k=1;i 65535||in_len<0) + { + mylog(log_debug,"in_len > 65535||in_len<0 , %d",in_len); + return -1; + } + int iv_len= int ((uint8_t)(input[in_len-1]^input[0]^key_string[0]) ); + out_len=in_len-1-iv_len; + if(out_len<0) + { + mylog(log_debug,"%d %d\n",in_len,out_len); + return -1; + } + for(i=0,j=0,k=1;i