Преглед на файлове

fix indent problem with clang-format

yancey преди 2 години
родител
ревизия
41cac842a8
променени са 24 файла, в които са добавени 4662 реда и са изтрити 5469 реда
  1. 464 551
      common.cpp
  2. 325 360
      common.h
  3. 99 122
      connection.cpp
  4. 273 334
      connection.h
  5. 80 99
      delay_manager.cpp
  6. 107 109
      delay_manager.h
  7. 43 54
      fd_manager.cpp
  8. 19 20
      fd_manager.h
  9. 729 859
      fec_manager.cpp
  10. 391 448
      fec_manager.h
  11. 45 57
      lib/rs.cpp
  12. 4 10
      lib/rs.h
  13. 41 47
      log.cpp
  14. 26 32
      log.h
  15. 107 124
      main.cpp
  16. 859 1069
      misc.cpp
  17. 8 13
      misc.h
  18. 0 1
      my_ev.h
  19. 7 5
      my_ev_common.h
  20. 291 339
      packet.cpp
  21. 20 21
      packet.h
  22. 0 1
      tunnel.h
  23. 357 388
      tunnel_client.cpp
  24. 367 406
      tunnel_server.cpp

Файловите разлики са ограничени, защото са твърде много
+ 464 - 551
common.cpp


+ 325 - 360
common.h

@@ -10,17 +10,17 @@
 //#define __STDC_FORMAT_MACROS 1
 #include <inttypes.h>
 
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
-#include<getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
 
-#include<unistd.h>
-#include<errno.h>
+#include <unistd.h>
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <stdlib.h> //for exit(0);
-#include <errno.h> //For errno - the error number
+#include <stdlib.h>  //for exit(0);
+#include <errno.h>   //For errno - the error number
 //#include <netinet/tcp.h>   //Provides declarations for tcp header
 //#include <netinet/udp.h>
 //#include <netinet/ip.h>    //Provides declarations for ip header
@@ -44,24 +44,22 @@
 #include <ws2tcpip.h>
 typedef int socklen_t;
 #else
-#include <sys/socket.h> 
+#include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #endif
 
+#include <unordered_map>
+#include <unordered_set>
+#include <map>
+#include <list>
+#include <string>
+#include <vector>
+using namespace std;
 
-#include<unordered_map>
-#include<unordered_set>
-#include<map>
-#include<list>
-#include<string>
-#include<vector>
-using  namespace std;
-
-
-typedef unsigned long long u64_t;   //this works on most platform,avoid using the PRId64
+typedef unsigned long long u64_t;  // this works on most platform,avoid using the PRId64
 typedef long long i64_t;
 
 typedef unsigned int u32_t;
@@ -70,11 +68,10 @@ typedef int i32_t;
 typedef unsigned short u16_t;
 typedef short i16_t;
 
-
 #if defined(__MINGW32__)
 int inet_pton(int af, const char *src, void *dst);
 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
-#define setsockopt(a,b,c,d,e) setsockopt(a,b,c,(const char *)(d),e)
+#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char *)(d), e)
 #endif
 
 char *get_sock_error();
@@ -83,39 +80,36 @@ int init_ws();
 
 #if defined(__MINGW32__)
 typedef SOCKET my_fd_t;
-inline int sock_close(my_fd_t fd)
-{
-	return closesocket(fd);
+inline int sock_close(my_fd_t fd) {
+    return closesocket(fd);
 }
 #else
 typedef int my_fd_t;
-inline int sock_close(my_fd_t fd)
-{
-	return close(fd);
+inline int sock_close(my_fd_t fd) {
+    return close(fd);
 }
 
 #endif
 
-
 struct my_itimerspec {
-	struct timespec it_interval;  /* Timer interval */
-	struct timespec it_value;     /* Initial expiration */
+    struct timespec it_interval; /* Timer interval */
+    struct timespec it_value;    /* Initial expiration */
 };
 
 typedef u64_t my_time_t;
 
-const int max_addr_len=100;
-const int max_data_len=3600;
-const int buf_len=max_data_len+200;
+const int max_addr_len = 100;
+const int max_data_len = 3600;
+const int buf_len = max_data_len + 200;
 
-const int default_mtu=1250;
+const int default_mtu = 1250;
 
-//const u32_t timer_interval=400;
+// const u32_t timer_interval=400;
 ////const u32_t conv_timeout=180000;
-//const u32_t conv_timeout=40000;//for test
-const u32_t conv_timeout=180000;
-const int max_conv_num=10000;
-const int max_conn_num=200;
+// const u32_t conv_timeout=40000;//for test
+const u32_t conv_timeout = 180000;
+const int max_conv_num = 10000;
+const int max_conn_num = 200;
 
 /*
 const u32_t max_handshake_conn_num=10000;
@@ -128,46 +122,50 @@ const u32_t client_retry_interval=1000;
 
 const u32_t server_handshake_timeout=10000;// this should be much longer than clients. client retry initially ,server retry passtively*/
 
-const int conv_clear_ratio=30;  //conv grabage collecter check 1/30 of all conv one time
-const int conn_clear_ratio=50;
-const int conv_clear_min=1;
-const int conn_clear_min=1;
-
-const u32_t conv_clear_interval=1000;
-const u32_t conn_clear_interval=1000;
+const int conv_clear_ratio = 30;  // conv grabage collecter check 1/30 of all conv one time
+const int conn_clear_ratio = 50;
+const int conv_clear_min = 1;
+const int conn_clear_min = 1;
 
+const u32_t conv_clear_interval = 1000;
+const u32_t conn_clear_interval = 1000;
 
-const i32_t max_fail_time=0;//disable
+const i32_t max_fail_time = 0;  // disable
 
-const u32_t heartbeat_interval=1000;
+const u32_t heartbeat_interval = 1000;
 
-const u32_t timer_interval=400;//this should be smaller than heartbeat_interval and retry interval;
+const u32_t timer_interval = 400;  // this should be smaller than heartbeat_interval and retry interval;
 
-//const uint32_t conv_timeout=120000; //120 second
-//const u32_t conv_timeout=120000; //for test
+// const uint32_t conv_timeout=120000; //120 second
+// const u32_t conv_timeout=120000; //for test
 
-const u32_t client_conn_timeout=10000;
-const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;
-
-//const uint32_t server_conn_timeout=conv_timeout+60000;//this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
-const u32_t server_conn_timeout=conv_timeout+20000;//for test
+const u32_t client_conn_timeout = 10000;
+const u32_t client_conn_uplink_timeout = client_conn_timeout + 2000;
 
+// const uint32_t server_conn_timeout=conv_timeout+60000;//this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
+const u32_t server_conn_timeout = conv_timeout + 20000;  // for test
 
 extern int about_to_exit;
 
-enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end};
+enum raw_mode_t { mode_faketcp = 0,
+                  mode_udp,
+                  mode_icmp,
+                  mode_end };
 extern raw_mode_t raw_mode;
-enum program_mode_t {unset_mode=0,client_mode,server_mode};
+enum program_mode_t { unset_mode = 0,
+                      client_mode,
+                      server_mode };
 extern program_mode_t program_mode;
-extern unordered_map<int, const char*> raw_mode_tostring ;
+extern unordered_map<int, const char *> raw_mode_tostring;
 
-enum working_mode_t {unset_working_mode=0,tunnel_mode,tun_dev_mode};
+enum working_mode_t { unset_working_mode = 0,
+                      tunnel_mode,
+                      tun_dev_mode };
 extern working_mode_t working_mode;
 
 extern int socket_buf_size;
 
-
-//typedef u32_t id_t;
+// typedef u32_t id_t;
 
 typedef u64_t iv_t;
 
@@ -177,31 +175,35 @@ typedef u64_t anti_replay_seq_t;
 
 typedef u64_t fd64_t;
 
-//enum dest_type{none=0,type_fd64_ip_port,type_fd64,type_fd64_ip_port_conv,type_fd64_conv/*,type_fd*/};
-enum dest_type{none=0,type_fd64_addr,type_fd64,type_fd,type_write_fd,type_fd_addr/*,type_fd*/};
+// enum dest_type{none=0,type_fd64_ip_port,type_fd64,type_fd64_ip_port_conv,type_fd64_conv/*,type_fd*/};
+enum dest_type { none = 0,
+                 type_fd64_addr,
+                 type_fd64,
+                 type_fd,
+                 type_write_fd,
+                 type_fd_addr /*,type_fd*/ };
 
 /*
 struct ip_port_t
 {
-	u32_t ip;
-	int port;
-	void from_u64(u64_t u64);
-	u64_t to_u64();
-	char * to_s();
+        u32_t ip;
+        int port;
+        void from_u64(u64_t u64);
+        u64_t to_u64();
+        char * to_s();
 };
 
 struct fd64_ip_port_t
 {
-	fd64_t fd64;
-	ip_port_t ip_port;
+        fd64_t fd64;
+        ip_port_t ip_port;
 };
 struct fd_ip_port_t
 {
-	int fd;
-	ip_port_t ip_port;
+        int fd;
+        ip_port_t ip_port;
 };*/
 
-
 struct pseudo_header {
     u32_t source_address;
     u32_t dest_address;
@@ -210,205 +212,181 @@ struct pseudo_header {
     unsigned short tcp_length;
 };
 
-u32_t djb2(unsigned char *str,int len);
-u32_t sdbm(unsigned char *str,int len);
+u32_t djb2(unsigned char *str, int len);
+u32_t sdbm(unsigned char *str, int len);
 
-struct address_t  //TODO scope id
+struct address_t  // TODO scope id
 {
-	struct hash_function
-	{
-	    u32_t operator()(const address_t &key) const
-		{
-	    	return sdbm((unsigned char*)&key.inner,sizeof(key.inner));
-		}
-	};
-
-	union storage_t //sockaddr_storage is too huge, we dont use it.
-	{
-		sockaddr_in ipv4;
-		sockaddr_in6 ipv6;
-	};
-	storage_t inner;
-
-	/*address_t()
-	{
-		clear();
-	}*/
-	void clear()
-	{
-		memset(&inner,0,sizeof(inner));
-	}
-	/*
-	int from_ip_port(u32_t  ip, int port)
-	{
-		clear();
-		inner.ipv4.sin_family=AF_INET;
-		inner.ipv4.sin_port=htons(port);
-		inner.ipv4.sin_addr.s_addr=ip;
-		return 0;
-	}*/
-
-	int from_ip_port_new(int type, void *  ip, int port)
-	{
-		clear();
-		if(type==AF_INET)
-		{
-			inner.ipv4.sin_family=AF_INET;
-			inner.ipv4.sin_port=htons(port);
-			inner.ipv4.sin_addr.s_addr=*((u32_t *)ip);
-		}
-		else if(type==AF_INET6)
-		{
-			inner.ipv6.sin6_family=AF_INET6;
-			inner.ipv6.sin6_port=htons(port);
-			inner.ipv6.sin6_addr=*((in6_addr*)ip);
-		}
-		return 0;
-	}
-
-	int from_str(char * str);
-
-	int from_str_ip_only(char * str);
-
-	int from_sockaddr(sockaddr *,socklen_t);
-
-	char* get_str();
-	void to_str(char *);
-
-	inline int is_vaild()
-	{
-		u32_t ret=((sockaddr*)&inner)->sa_family;
-		return (ret==AF_INET||ret==AF_INET6);
-	}
-
-	inline u32_t get_type()
-	{
-		assert(is_vaild());
-		u32_t ret=((sockaddr*)&inner)->sa_family;
-		return ret;
-	}
-
-	inline u32_t get_len()
-	{
-		u32_t type=get_type();
-		switch(type)
-		{
-			case AF_INET:
-				return sizeof(sockaddr_in);
-			case AF_INET6:
-				return sizeof(sockaddr_in6);
-			default:
-				assert(0==1);
-		}
-		return -1;
-	}
-
-	inline u32_t get_port()
-	{
-		u32_t type=get_type();
-		switch(type)
-		{
-			case AF_INET:
-				return ntohs(inner.ipv4.sin_port);
-			case AF_INET6:
-				return ntohs(inner.ipv6.sin6_port);
-			default:
-				assert(0==1);
-		}
-		return -1;
-	}
-
-	inline void set_port(int port)
-	{
-		u32_t type=get_type();
-		switch(type)
-		{
-			case AF_INET:
-				inner.ipv4.sin_port=htons(port);
-				break;
-			case AF_INET6:
-				inner.ipv6.sin6_port=htons(port);
-				break;
-			default:
-				assert(0==1);
-		}
-		return ;
-	}
-
-    bool operator == (const address_t &b) const
+    struct hash_function {
+        u32_t operator()(const address_t &key) const {
+            return sdbm((unsigned char *)&key.inner, sizeof(key.inner));
+        }
+    };
+
+    union storage_t  // sockaddr_storage is too huge, we dont use it.
+    {
+        sockaddr_in ipv4;
+        sockaddr_in6 ipv6;
+    };
+    storage_t inner;
+
+    /*address_t()
+    {
+            clear();
+    }*/
+    void clear() {
+        memset(&inner, 0, sizeof(inner));
+    }
+    /*
+    int from_ip_port(u32_t  ip, int port)
     {
-    	//return this->data==b.data;
-        return memcmp(&this->inner,&b.inner,sizeof(this->inner))==0;
+            clear();
+            inner.ipv4.sin_family=AF_INET;
+            inner.ipv4.sin_port=htons(port);
+            inner.ipv4.sin_addr.s_addr=ip;
+            return 0;
+    }*/
+
+    int from_ip_port_new(int type, void *ip, int port) {
+        clear();
+        if (type == AF_INET) {
+            inner.ipv4.sin_family = AF_INET;
+            inner.ipv4.sin_port = htons(port);
+            inner.ipv4.sin_addr.s_addr = *((u32_t *)ip);
+        } else if (type == AF_INET6) {
+            inner.ipv6.sin6_family = AF_INET6;
+            inner.ipv6.sin6_port = htons(port);
+            inner.ipv6.sin6_addr = *((in6_addr *)ip);
+        }
+        return 0;
+    }
+
+    int from_str(char *str);
+
+    int from_str_ip_only(char *str);
+
+    int from_sockaddr(sockaddr *, socklen_t);
+
+    char *get_str();
+    void to_str(char *);
+
+    inline int is_vaild() {
+        u32_t ret = ((sockaddr *)&inner)->sa_family;
+        return (ret == AF_INET || ret == AF_INET6);
+    }
+
+    inline u32_t get_type() {
+        assert(is_vaild());
+        u32_t ret = ((sockaddr *)&inner)->sa_family;
+        return ret;
+    }
+
+    inline u32_t get_len() {
+        u32_t type = get_type();
+        switch (type) {
+            case AF_INET:
+                return sizeof(sockaddr_in);
+            case AF_INET6:
+                return sizeof(sockaddr_in6);
+            default:
+                assert(0 == 1);
+        }
+        return -1;
+    }
+
+    inline u32_t get_port() {
+        u32_t type = get_type();
+        switch (type) {
+            case AF_INET:
+                return ntohs(inner.ipv4.sin_port);
+            case AF_INET6:
+                return ntohs(inner.ipv6.sin6_port);
+            default:
+                assert(0 == 1);
+        }
+        return -1;
+    }
+
+    inline void set_port(int port) {
+        u32_t type = get_type();
+        switch (type) {
+            case AF_INET:
+                inner.ipv4.sin_port = htons(port);
+                break;
+            case AF_INET6:
+                inner.ipv6.sin6_port = htons(port);
+                break;
+            default:
+                assert(0 == 1);
+        }
+        return;
+    }
+
+    bool operator==(const address_t &b) const {
+        // return this->data==b.data;
+        return memcmp(&this->inner, &b.inner, sizeof(this->inner)) == 0;
     }
 
     int new_connected_udp_fd();
 
-    char* get_ip();
+    char *get_ip();
 };
 
 namespace std {
 template <>
- struct hash<address_t>
- {
-   std::size_t operator()(const address_t& key) const
-   {
-
-	 //return address_t::hash_function(k);
-	   return sdbm((unsigned char*)&key.inner,sizeof(key.inner));
-   }
- };
-}
+struct hash<address_t> {
+    std::size_t operator()(const address_t &key) const {
+        // return address_t::hash_function(k);
+        return sdbm((unsigned char *)&key.inner, sizeof(key.inner));
+    }
+};
+}  // namespace std
 
-struct fd64_addr_t
-{
-	fd64_t fd64;
-	address_t addr;
+struct fd64_addr_t {
+    fd64_t fd64;
+    address_t addr;
 };
-struct fd_addr_t
-{
-	int fd;
-	address_t addr;
+struct fd_addr_t {
+    int fd;
+    address_t addr;
 };
-union inner_t
-{
-	fd64_t fd64;
-	int fd;
-	fd64_addr_t fd64_addr;
-	fd_addr_t fd_addr;
+union inner_t {
+    fd64_t fd64;
+    int fd;
+    fd64_addr_t fd64_addr;
+    fd_addr_t fd_addr;
 };
-struct dest_t
-{
-	dest_type type;
-	inner_t inner;
-	u32_t conv;
-	int cook=0;
+struct dest_t {
+    dest_type type;
+    inner_t inner;
+    u32_t conv;
+    int cook = 0;
 };
 
-struct fd_info_t
-{
-	address_t addr;
-	ev_io io_watcher;
+struct fd_info_t {
+    address_t addr;
+    ev_io io_watcher;
 };
 
 u64_t get_current_time();
-//u64_t get_current_time_rough();
+// u64_t get_current_time_rough();
 u64_t get_current_time_us();
-u64_t pack_u64(u32_t a,u32_t b);
+u64_t pack_u64(u32_t a, u32_t b);
 
 u32_t get_u64_h(u64_t a);
 
 u32_t get_u64_l(u64_t a);
 
-void write_u16(char *,u16_t a);
+void write_u16(char *, u16_t a);
 u16_t read_u16(char *);
 
-void write_u32(char *,u32_t a);
+void write_u32(char *, u32_t a);
 u32_t read_u32(char *);
 
-void write_u64(char *,u64_t a);
+void write_u64(char *, u64_t a);
 u64_t read_uu64(char *);
 
-char * my_ntoa(u32_t ip);
+char *my_ntoa(u32_t ip);
 
 void myexit(int a);
 void init_random_number_fd();
@@ -417,148 +395,135 @@ u32_t get_fake_random_number();
 u32_t get_fake_random_number_nz();
 u64_t ntoh64(u64_t a);
 u64_t hton64(u64_t a);
-bool larger_than_u16(uint16_t a,uint16_t b);
-bool larger_than_u32(u32_t a,u32_t b);
+bool larger_than_u16(uint16_t a, uint16_t b);
+bool larger_than_u32(u32_t a, u32_t b);
 void setnonblocking(int sock);
-int set_buf_size(int fd,int socket_buf_size);
+int set_buf_size(int fd, int socket_buf_size);
 
-unsigned short csum(const unsigned short *ptr,int nbytes);
-unsigned short tcp_csum(const pseudo_header & ph,const unsigned short *ptr,int nbytes);
+unsigned short csum(const unsigned short *ptr, int nbytes);
+unsigned short tcp_csum(const pseudo_header &ph, const unsigned short *ptr, int nbytes);
 
-void  signal_handler(int sig);
-//int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
-//int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
+void signal_handler(int sig);
+// int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
+// int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
 
 void myexit(int a);
 
 int add_iptables_rule(char *);
 
 int clear_iptables_rule();
-void get_fake_random_chars(char * s,int len);
-int random_between(u32_t a,u32_t b);
+void get_fake_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 set_timer_ms(int epollfd, int &timer_fd, u32_t timer_interval);
 
-int round_up_div(int a,int b);
+int round_up_div(int a, int b);
 
-int create_fifo(char * file);
+int create_fifo(char *file);
 /*
 int create_new_udp(int &new_udp_fd,int remote_address_uint32,int remote_port);
 */
 
-int new_listen_socket(int &fd,u32_t ip,int port);
+int new_listen_socket(int &fd, u32_t ip, int port);
 
-int new_connected_socket(int &fd,u32_t ip,int port);
+int new_connected_socket(int &fd, u32_t ip, int port);
 
-int new_listen_socket2(int &fd,address_t &addr);
-int new_connected_socket2(int &fd,address_t &addr,address_t *bind_addr,char *out_interface);
+int new_listen_socket2(int &fd, address_t &addr);
+int new_connected_socket2(int &fd, address_t &addr, address_t *bind_addr, char *out_interface);
 
-struct not_copy_able_t
-{
-	not_copy_able_t()
-	{
-
-	}
-	not_copy_able_t(const not_copy_able_t &other)
-	{
-		assert(0==1);
-	}
-	const not_copy_able_t & operator=(const not_copy_able_t &other)
-	{
-		assert(0==1);
-		return other;
-	}
+struct not_copy_able_t {
+    not_copy_able_t() {
+    }
+    not_copy_able_t(const not_copy_able_t &other) {
+        assert(0 == 1);
+    }
+    const not_copy_able_t &operator=(const not_copy_able_t &other) {
+        assert(0 == 1);
+        return other;
+    }
 };
 
-
 template <class key_t>
-struct lru_collector_t:not_copy_able_t
-{
-	//typedef void* key_t;
-//#define key_t void*
-	struct lru_pair_t
-	{
-		key_t key;
-		my_time_t ts;
-	};
-
-	unordered_map<key_t,typename list<lru_pair_t>::iterator> mp;
-
-	list<lru_pair_t> q;
-	int update(key_t key)
-	{
-		assert(mp.find(key)!=mp.end());
-		auto it=mp[key];
-		q.erase(it);
-
-		my_time_t value=get_current_time();
-		if(!q.empty())
-		{
-			assert(value >=q.front().ts);
-		}
-		lru_pair_t tmp; tmp.key=key; tmp.ts=value;
-		q.push_front( tmp);
-		mp[key]=q.begin();
-
-		return 0;
-	}
-	int new_key(key_t key)
-	{
-		assert(mp.find(key)==mp.end());
-
-		my_time_t value=get_current_time();
-		if(!q.empty())
-		{
-			assert(value >=q.front().ts);
-		}
-		lru_pair_t tmp; tmp.key=key; tmp.ts=value;
-		q.push_front( tmp);
-		mp[key]=q.begin();
-
-		return 0;
-	}
-	int size()
-	{
-		return q.size();
-	}
-	int empty()
-	{
-		return q.empty();
-	}
-	void clear()
-	{
-		mp.clear(); q.clear();
-	}
-	my_time_t ts_of(key_t key)
-	{
-		assert(mp.find(key)!=mp.end());
-		return mp[key]->ts;
-	}
-
-	my_time_t peek_back(key_t &key)
-	{
-		assert(!q.empty());
-		auto it=q.end(); it--;
-		key=it->key;
-		return it->ts;
-	}
-	void erase(key_t key)
-	{
-		assert(mp.find(key)!=mp.end());
-		q.erase(mp[key]);
-		mp.erase(key);
-	}
-	/*
-	void erase_back()
-	{
-		assert(!q.empty());
-		auto it=q.end(); it--;
-		key_t key=it->key;
-		erase(key);
-	}*/
-};
+struct lru_collector_t : not_copy_able_t {
+    // typedef void* key_t;
+    //#define key_t void*
+    struct lru_pair_t {
+        key_t key;
+        my_time_t ts;
+    };
+
+    unordered_map<key_t, typename list<lru_pair_t>::iterator> mp;
+
+    list<lru_pair_t> q;
+    int update(key_t key) {
+        assert(mp.find(key) != mp.end());
+        auto it = mp[key];
+        q.erase(it);
+
+        my_time_t value = get_current_time();
+        if (!q.empty()) {
+            assert(value >= q.front().ts);
+        }
+        lru_pair_t tmp;
+        tmp.key = key;
+        tmp.ts = value;
+        q.push_front(tmp);
+        mp[key] = q.begin();
+
+        return 0;
+    }
+    int new_key(key_t key) {
+        assert(mp.find(key) == mp.end());
+
+        my_time_t value = get_current_time();
+        if (!q.empty()) {
+            assert(value >= q.front().ts);
+        }
+        lru_pair_t tmp;
+        tmp.key = key;
+        tmp.ts = value;
+        q.push_front(tmp);
+        mp[key] = q.begin();
+
+        return 0;
+    }
+    int size() {
+        return q.size();
+    }
+    int empty() {
+        return q.empty();
+    }
+    void clear() {
+        mp.clear();
+        q.clear();
+    }
+    my_time_t ts_of(key_t key) {
+        assert(mp.find(key) != mp.end());
+        return mp[key]->ts;
+    }
 
+    my_time_t peek_back(key_t &key) {
+        assert(!q.empty());
+        auto it = q.end();
+        it--;
+        key = it->key;
+        return it->ts;
+    }
+    void erase(key_t key) {
+        assert(mp.find(key) != mp.end());
+        q.erase(mp[key]);
+        mp.erase(key);
+    }
+    /*
+    void erase_back()
+    {
+            assert(!q.empty());
+            auto it=q.end(); it--;
+            key_t key=it->key;
+            erase(key);
+    }*/
+};
 
-vector<string> string_to_vec(const char * s,const char * sp) ;
+vector<string> string_to_vec(const char *s, const char *sp);
 
 #endif /* COMMON_H_ */

+ 99 - 122
connection.cpp

@@ -7,147 +7,124 @@
 
 #include "connection.h"
 
-//const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
+// 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.
+const int disable_conn_clear = 0;  // a raw connection is called conn.
 
-int report_interval=0;
+int report_interval = 0;
 
-void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
-//so we have to close the fd when conv expires
+void server_clear_function(u64_t u64)  // used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
+// so we have to close the fd when conv expires
 {
-	fd64_t fd64=u64;
-	assert(fd_manager.exist(fd64));
-	ev_io &watcher= fd_manager.get_info(fd64).io_watcher;
+    fd64_t fd64 = u64;
+    assert(fd_manager.exist(fd64));
+    ev_io &watcher = fd_manager.get_info(fd64).io_watcher;
 
-	address_t &addr=fd_manager.get_info(fd64).addr;//
-	assert(conn_manager.exist(addr));//
-	struct ev_loop *loop =conn_manager.find_insert(addr).loop;  // overkill ? should we just use ev_default_loop(0)?
+    address_t &addr = fd_manager.get_info(fd64).addr;            //
+    assert(conn_manager.exist(addr));                            //
+    struct ev_loop *loop = conn_manager.find_insert(addr).loop;  // overkill ? should we just use ev_default_loop(0)?
 
-	ev_io_stop(loop,&watcher);
-
-	fd_manager.fd64_close(fd64);
+    ev_io_stop(loop, &watcher);
 
+    fd_manager.fd64_close(fd64);
 }
 
-
 ////////////////////////////////////////////////////////////////////
 
-conn_manager_t::conn_manager_t()
-{
-	 mp.reserve(10007);
-	 last_clear_time=0;
+conn_manager_t::conn_manager_t() {
+    mp.reserve(10007);
+    last_clear_time = 0;
 }
-int conn_manager_t::exist(address_t addr)
-{
-
-	 if(mp.find(addr)!=mp.end())
-	 {
-		 return 1;
-	 }
-	 return 0;
+int conn_manager_t::exist(address_t addr) {
+    if (mp.find(addr) != mp.end()) {
+        return 1;
+    }
+    return 0;
 }
 
-conn_info_t *& conn_manager_t::find_insert_p(address_t addr)  //be aware,the adress may change after rehash
+conn_info_t *&conn_manager_t::find_insert_p(address_t addr)  // be aware,the adress may change after rehash
 {
-// u64_t u64=0;
- //u64=ip;
- //u64<<=32u;
- //u64|=port;
- unordered_map<address_t,conn_info_t*>::iterator it=mp.find(addr);
-	 if(it==mp.end())
-	 {
-		 mp[addr]=new conn_info_t;
-		 //lru.new_key(addr);
-	 }
-	 else
-	 {
-		 //lru.update(addr);
-	 }
-	 return mp[addr];
+    // u64_t u64=0;
+    // u64=ip;
+    // u64<<=32u;
+    // u64|=port;
+    unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);
+    if (it == mp.end()) {
+        mp[addr] = new conn_info_t;
+        // lru.new_key(addr);
+    } else {
+        // lru.update(addr);
+    }
+    return mp[addr];
 }
-conn_info_t & conn_manager_t::find_insert(address_t addr)  //be aware,the adress may change after rehash
+conn_info_t &conn_manager_t::find_insert(address_t addr)  // be aware,the adress may change after rehash
 {
- //u64_t u64=0;
- //u64=ip;
- //u64<<=32u;
- //u64|=port;
- unordered_map<address_t,conn_info_t*>::iterator it=mp.find(addr);
-	 if(it==mp.end())
-	 {
-		 mp[addr]=new conn_info_t;
-		 //lru.new_key(addr);
-	 }
-	 else
-	 {
-		 //lru.update(addr);
-	 }
-	 return *mp[addr];
+    // u64_t u64=0;
+    // u64=ip;
+    // u64<<=32u;
+    // u64|=port;
+    unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);
+    if (it == mp.end()) {
+        mp[addr] = new conn_info_t;
+        // lru.new_key(addr);
+    } else {
+        // lru.update(addr);
+    }
+    return *mp[addr];
 }
-int conn_manager_t::erase(unordered_map<address_t,conn_info_t*>::iterator erase_it)
-{
-	delete(erase_it->second);
-	mp.erase(erase_it->first);
-	return 0;
+int conn_manager_t::erase(unordered_map<address_t, conn_info_t *>::iterator erase_it) {
+    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_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()
-{
-//mylog(log_info,"called\n");
-	 unordered_map<address_t,conn_info_t*>::iterator it;
-	 unordered_map<address_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;//TODO,write it back
-	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();
-
-	//mylog(log_info,"here size=%d\n",(int)mp.size());
-	for(;;)
-	{
-		if(cnt>=num_to_clean) break;
-		if(mp.begin()==mp.end()) break;
-		if(it==mp.end())
-		{
-			it=mp.begin();
-		}
-
-		if(it->second->conv_manager.s.get_size() >0)
-		{
-			//mylog(log_info,"[%s:%d]size %d \n",my_ntoa(get_u64_h(it->first)),get_u64_l(it->first),(int)it->second->conv_manager.get_size());
-			it++;
-		}
-		else if(current_time<it->second->last_active_time+server_conn_timeout)
-		{
-			it++;
-		}
-		else
-		{
-			address_t tmp_addr=it->first;// avoid making get_str() const;
-			mylog(log_info,"{%s} inactive conn cleared \n",tmp_addr.get_str());
-			old_it=it;
-			it++;
-			erase(old_it);
-		}
-		cnt++;
-	}
-	clear_it=it;
-	return 0;
+int conn_manager_t::clear_inactive0() {
+    // mylog(log_info,"called\n");
+    unordered_map<address_t, conn_info_t *>::iterator it;
+    unordered_map<address_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;  // TODO,write it back
+    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();
+
+    // mylog(log_info,"here size=%d\n",(int)mp.size());
+    for (;;) {
+        if (cnt >= num_to_clean) break;
+        if (mp.begin() == mp.end()) break;
+        if (it == mp.end()) {
+            it = mp.begin();
+        }
+
+        if (it->second->conv_manager.s.get_size() > 0) {
+            // mylog(log_info,"[%s:%d]size %d \n",my_ntoa(get_u64_h(it->first)),get_u64_l(it->first),(int)it->second->conv_manager.get_size());
+            it++;
+        } else if (current_time < it->second->last_active_time + server_conn_timeout) {
+            it++;
+        } else {
+            address_t tmp_addr = it->first;  // avoid making get_str() const;
+            mylog(log_info, "{%s} inactive conn cleared \n", tmp_addr.get_str());
+            old_it = it;
+            it++;
+            erase(old_it);
+        }
+        cnt++;
+    }
+    clear_it = it;
+    return 0;
 }

+ 273 - 334
connection.h

@@ -19,365 +19,304 @@ extern int disable_anti_replay;
 
 extern int report_interval;
 
-const int disable_conv_clear=0;
+const int disable_conv_clear = 0;
 
 void server_clear_function(u64_t u64);
 
-template  <class T>
+template <class T>
 struct conv_manager_t  // manage the udp connections
 {
-	//typedef hash_map map;
-	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;
-
-	lru_collector_t<u32_t> lru;
-	//unordered_map<u32_t,u64_t> conv_last_active_time;
-
-	//unordered_map<u32_t,u64_t>::iterator clear_it;
-
-	void (*additional_clear_function)(T data) =0;
-
-	long long last_clear_time;
-
-	conv_manager_t()
-		{
-			//clear_it=conv_last_active_time.begin();
-			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);
-			//conv_last_active_time.reserve(10007);
-
-			lru.mp.reserve(10007);
-		}
-		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();
-
-			lru.clear();
-			//conv_last_active_time.clear();
-
-			//clear_it=conv_last_active_time.begin();
-
-		}
-		u32_t get_new_conv()
-		{
-			u32_t conv=get_fake_random_number_nz();
-			while(conv_to_data.find(conv)!=conv_to_data.end())
-			{
-				conv=get_fake_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];
-		}
-		T find_data_by_conv(u32_t conv)
-		{
-			return conv_to_data[conv];
-		}
-		int update_active_time(u32_t conv)
-		{
-			//return conv_last_active_time[conv]=get_current_time();
-			lru.update(conv);
-			return 0;
-		}
-		int insert_conv(u32_t conv,T data)
-		{
-			data_to_conv[data]=conv;
-			conv_to_data[conv]=data;
-			//conv_last_active_time[conv]=get_current_time();
-			lru.new_key(conv);
-			return 0;
-		}
-		int erase_conv(u32_t conv)
-		{
-			if(disable_conv_clear) return 0;
-			T data=conv_to_data[conv];
-			if(additional_clear_function!=0)
-			{
-				additional_clear_function(data);
-			}
-			conv_to_data.erase(conv);
-			data_to_conv.erase(data);
-			//conv_last_active_time.erase(conv);
-			lru.erase(conv);
-			return 0;
-		}
-		int clear_inactive(char * info=0)
-		{
-			if(get_current_time()-last_clear_time>conv_clear_interval)
-			{
-				last_clear_time=get_current_time();
-				return clear_inactive0(info);
-			}
-			return 0;
-		}
-		int clear_inactive0(char * info)
-		{
-			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;
-			//it=clear_it;
-			int size=lru.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);
-
-			my_time_t current_time=get_current_time();
-			for(;;)
-			{
-				if(cnt>=num_to_clean) break;
-				if(lru.empty()) break;
-
-				u32_t conv;
-				my_time_t ts=lru.peek_back(conv);
-
-				if(current_time- ts < conv_timeout) break;
-
-				erase_conv(conv);
-				if(info==0)
-				{
-					mylog(log_info,"conv %x cleared\n",conv);
-				}
-				else
-				{
-					mylog(log_info,"[%s]conv %x cleared\n",info,conv);
-				}
-				cnt++;
-			}
-			return 0;
-		}
-
-
-		/*
-	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(T u64);
-	u32_t find_conv_by_u64(T u64);
-	T find_u64_by_conv(u32_t conv);
-	int update_active_time(u32_t conv);
-	int insert_conv(u32_t conv,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 inner_stat_t
-{
-	u64_t input_packet_num;
-	u64_t input_packet_size;
-	u64_t output_packet_num;
-	u64_t output_packet_size;
+    // typedef hash_map map;
+    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;
+
+    lru_collector_t<u32_t> lru;
+    // unordered_map<u32_t,u64_t> conv_last_active_time;
+
+    // unordered_map<u32_t,u64_t>::iterator clear_it;
+
+    void (*additional_clear_function)(T data) = 0;
+
+    long long last_clear_time;
+
+    conv_manager_t() {
+        // clear_it=conv_last_active_time.begin();
+        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);
+        // conv_last_active_time.reserve(10007);
+
+        lru.mp.reserve(10007);
+    }
+    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();
+
+        lru.clear();
+        // conv_last_active_time.clear();
+
+        // clear_it=conv_last_active_time.begin();
+    }
+    u32_t get_new_conv() {
+        u32_t conv = get_fake_random_number_nz();
+        while (conv_to_data.find(conv) != conv_to_data.end()) {
+            conv = get_fake_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];
+    }
+    T find_data_by_conv(u32_t conv) {
+        return conv_to_data[conv];
+    }
+    int update_active_time(u32_t conv) {
+        // return conv_last_active_time[conv]=get_current_time();
+        lru.update(conv);
+        return 0;
+    }
+    int insert_conv(u32_t conv, T data) {
+        data_to_conv[data] = conv;
+        conv_to_data[conv] = data;
+        // conv_last_active_time[conv]=get_current_time();
+        lru.new_key(conv);
+        return 0;
+    }
+    int erase_conv(u32_t conv) {
+        if (disable_conv_clear) return 0;
+        T data = conv_to_data[conv];
+        if (additional_clear_function != 0) {
+            additional_clear_function(data);
+        }
+        conv_to_data.erase(conv);
+        data_to_conv.erase(data);
+        // conv_last_active_time.erase(conv);
+        lru.erase(conv);
+        return 0;
+    }
+    int clear_inactive(char *info = 0) {
+        if (get_current_time() - last_clear_time > conv_clear_interval) {
+            last_clear_time = get_current_time();
+            return clear_inactive0(info);
+        }
+        return 0;
+    }
+    int clear_inactive0(char *info) {
+        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;
+        // it=clear_it;
+        int size = lru.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);
+
+        my_time_t current_time = get_current_time();
+        for (;;) {
+            if (cnt >= num_to_clean) break;
+            if (lru.empty()) break;
+
+            u32_t conv;
+            my_time_t ts = lru.peek_back(conv);
+
+            if (current_time - ts < conv_timeout) break;
+
+            erase_conv(conv);
+            if (info == 0) {
+                mylog(log_info, "conv %x cleared\n", conv);
+            } else {
+                mylog(log_info, "[%s]conv %x cleared\n", info, conv);
+            }
+            cnt++;
+        }
+        return 0;
+    }
+
+    /*
+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(T u64);
+u32_t find_conv_by_u64(T u64);
+T find_u64_by_conv(u32_t conv);
+int update_active_time(u32_t conv);
+int insert_conv(u32_t conv,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 inner_stat_t {
+    u64_t input_packet_num;
+    u64_t input_packet_size;
+    u64_t output_packet_num;
+    u64_t output_packet_size;
 };
-struct stat_t
-{
-	u64_t last_report_time;
-	inner_stat_t normal_to_fec;
-	inner_stat_t fec_to_normal;
-	stat_t()
-	{
-		memset(this,0,sizeof(stat_t));
-	}
-	void report_as_client()
-	{
-		if(report_interval!=0 &&get_current_time()-last_report_time>u64_t(report_interval)*1000)
-		{
-			last_report_time=get_current_time();
-			inner_stat_t &a=normal_to_fec;
-			inner_stat_t &b=fec_to_normal;
-			mylog(log_info,"[report]client-->server:(original:%llu pkt;%llu byte) (fec:%llu pkt,%llu byte)  server-->client:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)\n",
-					a.input_packet_num,a.input_packet_size,a.output_packet_num,a.output_packet_size,
-					b.output_packet_num,b.output_packet_size,b.input_packet_num,b.input_packet_size
-					);
-		}
-	}
-	void report_as_server(address_t &addr)
-	{
-		if(report_interval!=0 &&get_current_time()-last_report_time>u64_t(report_interval)*1000)
-		{
-			last_report_time=get_current_time();
-			inner_stat_t &a=fec_to_normal;
-			inner_stat_t &b=normal_to_fec;
-			mylog(log_info,"[report][%s]client-->server:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)  server-->client:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)\n",
-					addr.get_str(),
-					a.output_packet_num,a.output_packet_size,a.input_packet_num,a.input_packet_size,
-					b.input_packet_num,b.input_packet_size,b.output_packet_num,b.output_packet_size
-					);
-		}
-	}
+struct stat_t {
+    u64_t last_report_time;
+    inner_stat_t normal_to_fec;
+    inner_stat_t fec_to_normal;
+    stat_t() {
+        memset(this, 0, sizeof(stat_t));
+    }
+    void report_as_client() {
+        if (report_interval != 0 && get_current_time() - last_report_time > u64_t(report_interval) * 1000) {
+            last_report_time = get_current_time();
+            inner_stat_t &a = normal_to_fec;
+            inner_stat_t &b = fec_to_normal;
+            mylog(log_info, "[report]client-->server:(original:%llu pkt;%llu byte) (fec:%llu pkt,%llu byte)  server-->client:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)\n",
+                  a.input_packet_num, a.input_packet_size, a.output_packet_num, a.output_packet_size,
+                  b.output_packet_num, b.output_packet_size, b.input_packet_num, b.input_packet_size);
+        }
+    }
+    void report_as_server(address_t &addr) {
+        if (report_interval != 0 && get_current_time() - last_report_time > u64_t(report_interval) * 1000) {
+            last_report_time = get_current_time();
+            inner_stat_t &a = fec_to_normal;
+            inner_stat_t &b = normal_to_fec;
+            mylog(log_info, "[report][%s]client-->server:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)  server-->client:(original:%llu pkt;%llu byte) (fec:%llu pkt;%llu byte)\n",
+                  addr.get_str(),
+                  a.output_packet_num, a.output_packet_size, a.input_packet_num, a.input_packet_size,
+                  b.input_packet_num, b.input_packet_size, b.output_packet_num, b.output_packet_size);
+        }
+    }
 };
 
-
-struct conn_info_t:not_copy_able_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
+struct conn_info_t : not_copy_able_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
 {
-	union  tmp_union_t
-	{
-		conv_manager_t<address_t> c;
-		conv_manager_t<u64_t> s;
-		//avoid templates here and there, avoid pointer and type cast
-		tmp_union_t()
-		{
-			if(program_mode==client_mode)
-			{
-				new( &c ) conv_manager_t<address_t>();
-			}
-			else
-			{
-				assert(program_mode==server_mode);
-				new( &s ) conv_manager_t<u64_t>();
-			}
-		}
-		~tmp_union_t()
-		{
-			if(program_mode==client_mode)
-			{
-				c.~conv_manager_t<address_t>();
-			}
-			else
-			{
-				assert(program_mode==server_mode);
-				s.~conv_manager_t<u64_t>();
-			}
-		}
-	}conv_manager;
-
-
-	fec_encode_manager_t fec_encode_manager;
-	fec_decode_manager_t fec_decode_manager;
-	ev_timer timer;
-	//my_timer_t timer;
-
-	u64_t last_active_time;
-	stat_t stat;
-
-	struct ev_loop* loop=0;
-	int local_listen_fd;
-
-	int remote_fd;  //only used for client
-	fd64_t remote_fd64;//only used for client
-
-	//ip_port_t ip_port;
-	address_t  addr;//only used for server
-
-	conn_info_t()
-	{
-		if(program_mode==server_mode)
-		{
-			conv_manager.s.additional_clear_function=server_clear_function;
-		}
-		else
-		{
-			assert(program_mode==client_mode);
-		}
-	}
-
-	~conn_info_t()
-	{
-		if(loop)
-			ev_timer_stop(loop,&timer);
-	}
-	void update_active_time()
-	{
-		last_active_time=get_current_time();
-	}
-	/*
-	conn_info_t(const conn_info_t &b)
-	{
-		assert(0==1);
-	}*/
+    union tmp_union_t {
+        conv_manager_t<address_t> c;
+        conv_manager_t<u64_t> s;
+        // avoid templates here and there, avoid pointer and type cast
+        tmp_union_t() {
+            if (program_mode == client_mode) {
+                new (&c) conv_manager_t<address_t>();
+            } else {
+                assert(program_mode == server_mode);
+                new (&s) conv_manager_t<u64_t>();
+            }
+        }
+        ~tmp_union_t() {
+            if (program_mode == client_mode) {
+                c.~conv_manager_t<address_t>();
+            } else {
+                assert(program_mode == server_mode);
+                s.~conv_manager_t<u64_t>();
+            }
+        }
+    } conv_manager;
+
+    fec_encode_manager_t fec_encode_manager;
+    fec_decode_manager_t fec_decode_manager;
+    ev_timer timer;
+    // my_timer_t timer;
+
+    u64_t last_active_time;
+    stat_t stat;
+
+    struct ev_loop *loop = 0;
+    int local_listen_fd;
+
+    int remote_fd;       // only used for client
+    fd64_t remote_fd64;  // only used for client
+
+    // ip_port_t ip_port;
+    address_t addr;  // only used for server
+
+    conn_info_t() {
+        if (program_mode == server_mode) {
+            conv_manager.s.additional_clear_function = server_clear_function;
+        } else {
+            assert(program_mode == client_mode);
+        }
+    }
+
+    ~conn_info_t() {
+        if (loop)
+            ev_timer_stop(loop, &timer);
+    }
+    void update_active_time() {
+        last_active_time = get_current_time();
+    }
+    /*
+    conn_info_t(const conn_info_t &b)
+    {
+            assert(0==1);
+    }*/
 };
 /*
 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
 {
 
-	unordered_map<u64_t,conn_info_t*> mp;//<ip,port> to conn_info_t;
-	unordered_map<u64_t,conn_info_t*>::iterator clear_it;
-	long long last_clear_time;
+        unordered_map<u64_t,conn_info_t*> mp;//<ip,port> to conn_info_t;
+        unordered_map<u64_t,conn_info_t*>::iterator clear_it;
+        long long last_clear_time;
 
-	conn_manager_t();
-	conn_manager_t(const conn_info_t &b)
-	{
-		assert(0==1);
-	}
-	int exist(ip_port_t);
-	conn_info_t *& find_p(ip_port_t);  //be aware,the adress may change after rehash
-	conn_info_t & find(ip_port_t) ; //be aware,the adress may change after rehash
-	int insert(ip_port_t);
+        conn_manager_t();
+        conn_manager_t(const conn_info_t &b)
+        {
+                assert(0==1);
+        }
+        int exist(ip_port_t);
+        conn_info_t *& find_p(ip_port_t);  //be aware,the adress may change after rehash
+        conn_info_t & find(ip_port_t) ; //be aware,the adress may change after rehash
+        int insert(ip_port_t);
 
-	int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it);
-	int clear_inactive();
-	int clear_inactive0();
+        int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it);
+        int clear_inactive();
+        int clear_inactive0();
 
 };*/
 
-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
+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
 {
+    unordered_map<address_t, conn_info_t *> mp;  // put it at end so that it de-consturcts first
+    unordered_map<address_t, conn_info_t *>::iterator clear_it;
 
+    long long last_clear_time;
 
- unordered_map<address_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
- unordered_map<address_t,conn_info_t*>::iterator clear_it;
-
- long long last_clear_time;
-
- conn_manager_t();
- int exist(address_t addr);
- 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
-
- int erase(unordered_map<address_t,conn_info_t*>::iterator erase_it);
-int clear_inactive();
-int clear_inactive0();
+    conn_manager_t();
+    int exist(address_t addr);
+    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
 
+    int erase(unordered_map<address_t, conn_info_t *>::iterator erase_it);
+    int clear_inactive();
+    int clear_inactive0();
 };
 
-
-
 extern conn_manager_t conn_manager;
 
-
 #endif /* CONNECTION_H_ */

+ 80 - 99
delay_manager.cpp

@@ -8,125 +8,106 @@
 #include "log.h"
 #include "packet.h"
 
-int delay_data_t::handle()
-{
-	return my_send(dest,data,len)>=0;
+int delay_data_t::handle() {
+    return my_send(dest, data, len) >= 0;
 }
 
+delay_manager_t::delay_manager_t() {
+    capacity = 0;
 
-delay_manager_t::delay_manager_t()
-{
-	capacity=0;
-
-	//if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
-	//{
-	//	mylog(log_fatal,"timer_fd create error");
-	//	myexit(1);
-	//}
-
-	//itimerspec zero_its;
-	//memset(&zero_its, 0, sizeof(zero_its));
+    // if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
+    //{
+    //	mylog(log_fatal,"timer_fd create error");
+    //	myexit(1);
+    // }
 
-	//timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &zero_its, 0);
+    // itimerspec zero_its;
+    // memset(&zero_its, 0, sizeof(zero_its));
 
+    // timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &zero_its, 0);
 }
-delay_manager_t::~delay_manager_t()
-{
-	//TODO ,we currently dont need to deconstruct it
+delay_manager_t::~delay_manager_t() {
+    // TODO ,we currently dont need to deconstruct it
 }
 
 /*
 int delay_manager_t::get_timer_fd()
 {
-	return timer_fd;
+        return timer_fd;
 }*/
 
-//int add(my_time_t delay,const dest_t &dest,const char *data,int len);
-int delay_manager_t::add(my_time_t delay,const dest_t &dest,char *data,int len)
-{
-	delay_data_t delay_data;
-	delay_data.dest=dest;
-	//delay_data.data=data;
-	delay_data.len=len;
-
-	if(capacity!=0&&int(delay_mp.size()) >=capacity)
-	{
-		mylog(log_warn,"max pending packet reached,ignored\n");
-		return -1;
-	}
-	if(delay==0)
-	{
-		static char buf[buf_len];
-		delay_data.data=buf;
-		memcpy(buf,data,len);
-		int ret=delay_data.handle();
-		if (ret != 0) {
-			mylog(log_trace, "handle() return %d\n", ret);
-		}
-		return 0;
-	}
-
-	delay_data_t tmp=delay_data;
-	tmp.data=(char *)malloc(delay_data.len+100);
-    if(!tmp.data)
-    {
+// int add(my_time_t delay,const dest_t &dest,const char *data,int len);
+int delay_manager_t::add(my_time_t delay, const dest_t &dest, char *data, int len) {
+    delay_data_t delay_data;
+    delay_data.dest = dest;
+    // delay_data.data=data;
+    delay_data.len = len;
+
+    if (capacity != 0 && int(delay_mp.size()) >= capacity) {
+        mylog(log_warn, "max pending packet reached,ignored\n");
+        return -1;
+    }
+    if (delay == 0) {
+        static char buf[buf_len];
+        delay_data.data = buf;
+        memcpy(buf, data, len);
+        int ret = delay_data.handle();
+        if (ret != 0) {
+            mylog(log_trace, "handle() return %d\n", ret);
+        }
+        return 0;
+    }
+
+    delay_data_t tmp = delay_data;
+    tmp.data = (char *)malloc(delay_data.len + 100);
+    if (!tmp.data) {
         mylog(log_warn, "malloc() returned null in delay_manager_t::add()");
         return -1;
     }
-	memcpy(tmp.data,data,delay_data.len);
+    memcpy(tmp.data, data, delay_data.len);
 
-	my_time_t tmp_time=get_current_time_us();
-	tmp_time+=delay;
+    my_time_t tmp_time = get_current_time_us();
+    tmp_time += delay;
 
-	delay_mp.insert(make_pair(tmp_time,tmp));
+    delay_mp.insert(make_pair(tmp_time, tmp));
 
-	////check();  check everytime when add, is it better ??
+    ////check();  check everytime when add, is it better ??
 
-	return 0;
+    return 0;
 }
 
-int delay_manager_t::check()
-{
-	if(!delay_mp.empty())
-	{
-		my_time_t current_time;
-
-		multimap<my_time_t,delay_data_t>::iterator it;
-		while(1)
-		{
-			int ret=0;
-			it=delay_mp.begin();
-			if(it==delay_mp.end()) break;
-
-			current_time=get_current_time_us();
-			if(it->first <= current_time)
-			{
-				ret=it->second.handle();
-				if (ret != 0) {
-					mylog(log_trace, "handle() return %d\n", ret);
-				}
-				free(it->second.data);
-				delay_mp.erase(it);
-			}
-			else
-			{
-				break;
-			}
-
-		}
-		if(!delay_mp.empty())
-		{
-			const double m=1000*1000;
-			double timer_value=delay_mp.begin()->first/m -get_current_time_us()/m; // be aware of negative value, and be aware of uint
-			if(timer_value<0) timer_value=0; // set it to 0 if negative, although libev support negative value
-			ev_timer_stop(loop, &timer);
-			ev_timer_set(&timer, timer_value,0 );
-			ev_timer_start(loop, &timer);
-		}
-		else
-		{
-			ev_timer_stop(loop, &timer); //not necessary
-		}
-	}
-	return 0;
+int delay_manager_t::check() {
+    if (!delay_mp.empty()) {
+        my_time_t current_time;
+
+        multimap<my_time_t, delay_data_t>::iterator it;
+        while (1) {
+            int ret = 0;
+            it = delay_mp.begin();
+            if (it == delay_mp.end()) break;
+
+            current_time = get_current_time_us();
+            if (it->first <= current_time) {
+                ret = it->second.handle();
+                if (ret != 0) {
+                    mylog(log_trace, "handle() return %d\n", ret);
+                }
+                free(it->second.data);
+                delay_mp.erase(it);
+            } else {
+                break;
+            }
+        }
+        if (!delay_mp.empty()) {
+            const double m = 1000 * 1000;
+            double timer_value = delay_mp.begin()->first / m - get_current_time_us() / m;  // be aware of negative value, and be aware of uint
+            if (timer_value < 0) timer_value = 0;                                          // set it to 0 if negative, although libev support negative value
+            ev_timer_stop(loop, &timer);
+            ev_timer_set(&timer, timer_value, 0);
+            ev_timer_start(loop, &timer);
+        } else {
+            ev_timer_stop(loop, &timer);  // not necessary
+        }
+    }
+    return 0;
 }

+ 107 - 109
delay_manager.h

@@ -12,132 +12,130 @@
 #include "packet.h"
 #include "log.h"
 
-//enum delay_type_t {none=0,enum_sendto_u64,enum_send_fd,client_to_local,client_to_remote,server_to_local,server_to_remote};
+// enum delay_type_t {none=0,enum_sendto_u64,enum_send_fd,client_to_local,client_to_remote,server_to_local,server_to_remote};
 
 /*
 struct fd_ip_port_t
 {
-	int fd;
-	u32_t ip;
-	u32_t port;
+        int fd;
+        u32_t ip;
+        u32_t port;
 };
 union dest_t
 {
-	fd_ip_port_t fd_ip_port;
-	int fd;
-	u64_t u64;
+        fd_ip_port_t fd_ip_port;
+        int fd;
+        u64_t u64;
 };
 */
 /*
 struct my_timer_t
 {
-	int timer_fd;
-	fd64_t timer_fd64;
-	my_timer_t()
-	{
-		if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
-		{
-			mylog(log_fatal,"timer_fd create error");
-			myexit(1);
-		}
-		timer_fd64=fd_manager.create(timer_fd);
-	}
-	my_timer_t(const my_timer_t &b)
-	{
-		assert(0==1);
-	}
-	~my_timer_t()
-	{
-		fd_manager.fd64_close(timer_fd64);
-	}
-	int add_fd_to_epoll(int epoll_fd)
-	{
-		epoll_event ev;;
-		ev.events = EPOLLIN;
-		ev.data.u64 = timer_fd;
-		int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &ev);
-		if (ret!= 0) {
-			mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
-			myexit(-1);
-		}
-		return 0;
-	}
-	int add_fd64_to_epoll(int epoll_fd)
-	{
-		epoll_event ev;;
-		ev.events = EPOLLIN;
-		ev.data.u64 = timer_fd64;
-		int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &ev);
-		if (ret!= 0) {
-			mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
-			myexit(-1);
-		}
-		return 0;
-	}
-	int get_timer_fd()
-	{
-		return timer_fd;
-	}
-	fd64_t get_timer_fd64()
-	{
-		return timer_fd64;
-	}
-	int set_timer_repeat_us(my_time_t my_time)
-	{
-		itimerspec its;
-		memset(&its,0,sizeof(its));
-		its.it_interval.tv_sec=my_time/1000000llu;
-		its.it_interval.tv_nsec=my_time%1000000llu*1000llu;
-		its.it_value.tv_nsec=1; //imidiately
-		timerfd_settime(timer_fd,0,&its,0);
-		return 0;
-	}
-	int set_timer_abs_us(my_time_t my_time)
-	{
-		itimerspec its;
-		memset(&its,0,sizeof(its));
-		its.it_value.tv_sec=my_time/1000000llu;
-		its.it_value.tv_nsec=my_time%1000000llu*1000llu;
-		timerfd_settime(timer_fd,TFD_TIMER_ABSTIME,&its,0);
-		return 0;
-	}
+        int timer_fd;
+        fd64_t timer_fd64;
+        my_timer_t()
+        {
+                if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
+                {
+                        mylog(log_fatal,"timer_fd create error");
+                        myexit(1);
+                }
+                timer_fd64=fd_manager.create(timer_fd);
+        }
+        my_timer_t(const my_timer_t &b)
+        {
+                assert(0==1);
+        }
+        ~my_timer_t()
+        {
+                fd_manager.fd64_close(timer_fd64);
+        }
+        int add_fd_to_epoll(int epoll_fd)
+        {
+                epoll_event ev;;
+                ev.events = EPOLLIN;
+                ev.data.u64 = timer_fd;
+                int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &ev);
+                if (ret!= 0) {
+                        mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
+                        myexit(-1);
+                }
+                return 0;
+        }
+        int add_fd64_to_epoll(int epoll_fd)
+        {
+                epoll_event ev;;
+                ev.events = EPOLLIN;
+                ev.data.u64 = timer_fd64;
+                int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, timer_fd, &ev);
+                if (ret!= 0) {
+                        mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
+                        myexit(-1);
+                }
+                return 0;
+        }
+        int get_timer_fd()
+        {
+                return timer_fd;
+        }
+        fd64_t get_timer_fd64()
+        {
+                return timer_fd64;
+        }
+        int set_timer_repeat_us(my_time_t my_time)
+        {
+                itimerspec its;
+                memset(&its,0,sizeof(its));
+                its.it_interval.tv_sec=my_time/1000000llu;
+                its.it_interval.tv_nsec=my_time%1000000llu*1000llu;
+                its.it_value.tv_nsec=1; //imidiately
+                timerfd_settime(timer_fd,0,&its,0);
+                return 0;
+        }
+        int set_timer_abs_us(my_time_t my_time)
+        {
+                itimerspec its;
+                memset(&its,0,sizeof(its));
+                its.it_value.tv_sec=my_time/1000000llu;
+                its.it_value.tv_nsec=my_time%1000000llu*1000llu;
+                timerfd_settime(timer_fd,TFD_TIMER_ABSTIME,&its,0);
+                return 0;
+        }
 };*/
 
-
-struct delay_data_t
-{
-	dest_t dest;
-	//int left_time;//
-	char * data;
-	int len;
-	int handle();
+struct delay_data_t {
+    dest_t dest;
+    // int left_time;//
+    char *data;
+    int len;
+    int handle();
 };
 
-struct delay_manager_t
-{
-	ev_timer timer;
-	struct ev_loop *loop=0;
-	void (*cb) (struct ev_loop *loop, struct ev_timer *watcher, int revents)=0;
+struct delay_manager_t {
+    ev_timer timer;
+    struct ev_loop *loop = 0;
+    void (*cb)(struct ev_loop *loop, struct ev_timer *watcher, int revents) = 0;
 
-	//int timer_fd;
-	int capacity;
-	multimap<my_time_t,delay_data_t> delay_mp;  //unit us,1 us=0.001ms
-	delay_manager_t();
-	delay_manager_t(delay_manager_t &b)
-	{
-		assert(0==1);
-	}
-	void set_loop_and_cb(struct ev_loop *loop,void (*cb) (struct ev_loop *loop, struct ev_timer *watcher, int revents))
-	{
-		this->loop=loop;
-		this->cb=cb;
-		ev_init(&timer,cb);
-	}
-	int set_capacity(int a){capacity=a;return 0;}
-	~delay_manager_t();
-	ev_timer& get_timer();
-	int check();
-	int add(my_time_t delay,const dest_t &dest,char *data,int len);
+    // int timer_fd;
+    int capacity;
+    multimap<my_time_t, delay_data_t> delay_mp;  // unit us,1 us=0.001ms
+    delay_manager_t();
+    delay_manager_t(delay_manager_t &b) {
+        assert(0 == 1);
+    }
+    void set_loop_and_cb(struct ev_loop *loop, void (*cb)(struct ev_loop *loop, struct ev_timer *watcher, int revents)) {
+        this->loop = loop;
+        this->cb = cb;
+        ev_init(&timer, cb);
+    }
+    int set_capacity(int a) {
+        capacity = a;
+        return 0;
+    }
+    ~delay_manager_t();
+    ev_timer &get_timer();
+    int check();
+    int add(my_time_t delay, const dest_t &dest, char *data, int len);
 };
 
 #endif /* DELAY_MANAGER_H_ */

+ 43 - 54
fd_manager.cpp

@@ -5,59 +5,48 @@
  *      Author: root
  */
 
-
 #include "fd_manager.h"
-int fd_manager_t::fd_exist(int fd)
-{
-	return fd_to_fd64_mp.find(fd)!=fd_to_fd64_mp.end();
-}
-int fd_manager_t::exist(fd64_t fd64)
-{
-	return fd64_to_fd_mp.find(fd64)!=fd64_to_fd_mp.end();
-}
-int fd_manager_t::to_fd(fd64_t fd64)
-{
-	assert(exist(fd64));
-	return fd64_to_fd_mp[fd64];
-}
-void fd_manager_t::fd64_close(fd64_t fd64)
-{
-	assert(exist(fd64));
-	int fd=fd64_to_fd_mp[fd64];
-	fd64_to_fd_mp.erase(fd64);
-	fd_to_fd64_mp.erase(fd);
-	if(exist_info(fd64))
-	{
-		fd_info_mp.erase(fd64);
-	}
-	sock_close(fd);
-}
-void fd_manager_t::reserve(int n)
-{
-	fd_to_fd64_mp.reserve(n);
-	fd64_to_fd_mp.reserve(n);
-	fd_info_mp.reserve(n);
-}
-u64_t fd_manager_t::create(int fd)
-{
-	assert(!fd_exist(fd));
-	fd64_t fd64=counter++;
-	fd_to_fd64_mp[fd]=fd64;
-	fd64_to_fd_mp[fd64]=fd;
-	return fd64;
-}
-fd_manager_t::fd_manager_t()
-{
-	counter=u32_t(-1);
-	counter+=100;
-	reserve(10007);
-}
-fd_info_t & fd_manager_t::get_info(fd64_t fd64)
-{
-	assert(exist(fd64));
-	return fd_info_mp[fd64];
-}
-int fd_manager_t::exist_info(fd64_t fd64)
-{
-	return fd_info_mp.find(fd64)!=fd_info_mp.end();
+int fd_manager_t::fd_exist(int fd) {
+    return fd_to_fd64_mp.find(fd) != fd_to_fd64_mp.end();
+}
+int fd_manager_t::exist(fd64_t fd64) {
+    return fd64_to_fd_mp.find(fd64) != fd64_to_fd_mp.end();
+}
+int fd_manager_t::to_fd(fd64_t fd64) {
+    assert(exist(fd64));
+    return fd64_to_fd_mp[fd64];
+}
+void fd_manager_t::fd64_close(fd64_t fd64) {
+    assert(exist(fd64));
+    int fd = fd64_to_fd_mp[fd64];
+    fd64_to_fd_mp.erase(fd64);
+    fd_to_fd64_mp.erase(fd);
+    if (exist_info(fd64)) {
+        fd_info_mp.erase(fd64);
+    }
+    sock_close(fd);
+}
+void fd_manager_t::reserve(int n) {
+    fd_to_fd64_mp.reserve(n);
+    fd64_to_fd_mp.reserve(n);
+    fd_info_mp.reserve(n);
+}
+u64_t fd_manager_t::create(int fd) {
+    assert(!fd_exist(fd));
+    fd64_t fd64 = counter++;
+    fd_to_fd64_mp[fd] = fd64;
+    fd64_to_fd_mp[fd64] = fd;
+    return fd64;
+}
+fd_manager_t::fd_manager_t() {
+    counter = u32_t(-1);
+    counter += 100;
+    reserve(10007);
+}
+fd_info_t& fd_manager_t::get_info(fd64_t fd64) {
+    assert(exist(fd64));
+    return fd_info_mp[fd64];
+}
+int fd_manager_t::exist_info(fd64_t fd64) {
+    return fd_info_mp.find(fd64) != fd_info_mp.end();
 }

+ 19 - 20
fd_manager.h

@@ -11,27 +11,26 @@
 #include "common.h"
 #include "packet.h"
 
-
-
-struct fd_manager_t   //conver fd to a uniq 64bit number,avoid fd value conflict caused by close and re-create
-//this class is not strictly necessary,it just makes epoll fd handling easier
+struct fd_manager_t  // conver fd to a uniq 64bit number,avoid fd value conflict caused by close and re-create
+// this class is not strictly necessary,it just makes epoll fd handling easier
 {
-	fd_info_t & get_info(fd64_t fd64);
-	int exist_info(fd64_t);
-	int exist(fd64_t fd64);
-	int to_fd(fd64_t);
-	void fd64_close(fd64_t fd64);
-	void reserve(int n);
-	u64_t create(int fd);
-	fd_manager_t();
-private:
-	u64_t counter;
-	unordered_map<int,fd64_t> fd_to_fd64_mp;
-	unordered_map<fd64_t,int> fd64_to_fd_mp;
-	unordered_map<fd64_t,fd_info_t> fd_info_mp;
-	int fd_exist(int fd);
-	//void remove_fd(int fd);
-	//fd64_t fd_to_fd64(int fd);
+    fd_info_t& get_info(fd64_t fd64);
+    int exist_info(fd64_t);
+    int exist(fd64_t fd64);
+    int to_fd(fd64_t);
+    void fd64_close(fd64_t fd64);
+    void reserve(int n);
+    u64_t create(int fd);
+    fd_manager_t();
+
+   private:
+    u64_t counter;
+    unordered_map<int, fd64_t> fd_to_fd64_mp;
+    unordered_map<fd64_t, int> fd64_to_fd_mp;
+    unordered_map<fd64_t, fd_info_t> fd_info_mp;
+    int fd_exist(int fd);
+    // void remove_fd(int fd);
+    // fd64_t fd_to_fd64(int fd);
 };
 
 extern fd_manager_t fd_manager;

+ 729 - 859
fec_manager.cpp

@@ -11,917 +11,787 @@
 #include "lib/rs.h"
 #include "fd_manager.h"
 
-//int g_fec_data_num=20;
-//int g_fec_redundant_num=10;
-//int g_fec_mtu=1250;
-//int g_fec_queue_len=200;
-//int g_fec_timeout=8*1000; //8ms
-//int g_fec_mode=0;
+// int g_fec_data_num=20;
+// int g_fec_redundant_num=10;
+// int g_fec_mtu=1250;
+// int g_fec_queue_len=200;
+// int g_fec_timeout=8*1000; //8ms
+// int g_fec_mode=0;
 
 fec_parameter_t g_fec_par;
 
-int debug_fec_enc=0;
-int debug_fec_dec=0;
-//int dynamic_update_fec=1;
+int debug_fec_enc = 0;
+int debug_fec_dec = 0;
+// int dynamic_update_fec=1;
 
-const int encode_fast_send=1;
-const int decode_fast_send=1;
+const int encode_fast_send = 1;
+const int decode_fast_send = 1;
 
-int short_packet_optimize=1;
-int header_overhead=40;
+int short_packet_optimize = 1;
+int header_overhead = 40;
 
-u32_t fec_buff_num=2000;// how many packet can fec_decode_manager hold. shouldnt be very large,or it will cost huge memory
+u32_t fec_buff_num = 2000;  // how many packet can fec_decode_manager hold. shouldnt be very large,or it will cost huge memory
 
-
-blob_encode_t::blob_encode_t()
-{
-	clear();
+blob_encode_t::blob_encode_t() {
+    clear();
 }
-int blob_encode_t::clear()
-{
-	counter=0;
-	current_len=(int)sizeof(u32_t);
-	return 0;
+int blob_encode_t::clear() {
+    counter = 0;
+    current_len = (int)sizeof(u32_t);
+    return 0;
 }
 
-int blob_encode_t::get_num()
-{
-	return counter;
+int blob_encode_t::get_num() {
+    return counter;
 }
-int blob_encode_t::get_shard_len(int n)
-{
-	return round_up_div(current_len,n);
+int blob_encode_t::get_shard_len(int n) {
+    return round_up_div(current_len, n);
 }
 
-int blob_encode_t::get_shard_len(int n,int next_packet_len)
-{
-	return round_up_div(current_len+(int)sizeof(u16_t)+next_packet_len,n);
+int blob_encode_t::get_shard_len(int n, int next_packet_len) {
+    return round_up_div(current_len + (int)sizeof(u16_t) + next_packet_len, n);
 }
 
-int blob_encode_t::input(char *s,int len)
-{
-	assert(current_len+len+sizeof(u16_t) +100<sizeof(input_buf));
-	assert(len<=65535&&len>=0);
-	counter++;
-	assert(counter<=max_blob_packet_num);
-	write_u16(input_buf+current_len,len);
-	current_len+=sizeof(u16_t);
-	memcpy(input_buf+current_len,s,len);
-	current_len+=len;
-	return 0;
+int blob_encode_t::input(char *s, int len) {
+    assert(current_len + len + sizeof(u16_t) + 100 < sizeof(input_buf));
+    assert(len <= 65535 && len >= 0);
+    counter++;
+    assert(counter <= max_blob_packet_num);
+    write_u16(input_buf + current_len, len);
+    current_len += sizeof(u16_t);
+    memcpy(input_buf + current_len, s, len);
+    current_len += len;
+    return 0;
 }
 
-int blob_encode_t::output(int n,char ** &s_arr,int & len)
-{
-	len=round_up_div(current_len,n);
-	write_u32(input_buf,counter);
-	for(int i=0;i<n;i++)
-	{
-		output_buf[i]=input_buf+len*i;
-	}
-	s_arr=output_buf;
-	return 0;
+int blob_encode_t::output(int n, char **&s_arr, int &len) {
+    len = round_up_div(current_len, n);
+    write_u32(input_buf, counter);
+    for (int i = 0; i < n; i++) {
+        output_buf[i] = input_buf + len * i;
+    }
+    s_arr = output_buf;
+    return 0;
 }
-blob_decode_t::blob_decode_t()
-{
-	clear();
+blob_decode_t::blob_decode_t() {
+    clear();
 }
-int blob_decode_t::clear()
-{
-	current_len=0;
-	last_len=-1;
-	counter=0;
-	return 0;
+int blob_decode_t::clear() {
+    current_len = 0;
+    last_len = -1;
+    counter = 0;
+    return 0;
 }
-int blob_decode_t::input(char *s,int len)
-{
-	if(last_len!=-1)
-	{
-		assert(last_len==len);
-	}
-	counter++;
-	assert(counter<=max_fec_packet_num);
-	last_len=len;
-	assert(current_len+len+100<(int)sizeof(input_buf));//avoid overflow
-	memcpy(input_buf+current_len,s,len);
-	current_len+=len;
-	return 0;
+int blob_decode_t::input(char *s, int len) {
+    if (last_len != -1) {
+        assert(last_len == len);
+    }
+    counter++;
+    assert(counter <= max_fec_packet_num);
+    last_len = len;
+    assert(current_len + len + 100 < (int)sizeof(input_buf));  // avoid overflow
+    memcpy(input_buf + current_len, s, len);
+    current_len += len;
+    return 0;
 }
-int blob_decode_t::output(int &n,char ** &s_arr,int *&len_arr)
-{
+int blob_decode_t::output(int &n, char **&s_arr, int *&len_arr) {
+    int parser_pos = 0;
 
-	int parser_pos=0;
-
-	if(parser_pos+(int)sizeof(u32_t)>current_len) {mylog(log_info,"failed 0\n");return -1;}
-
-	n=(int)read_u32(input_buf+parser_pos);
-	if(n>max_blob_packet_num) {mylog(log_info,"failed 1\n");return -1;}
-	s_arr=output_buf;
-	len_arr=output_len;
-
-	parser_pos+=sizeof(u32_t);
-	for(int i=0;i<n;i++)
-	{
-		if(parser_pos+(int)sizeof(u16_t)>current_len) {mylog(log_info,"failed2 \n");return -1;}
-		len_arr[i]=(int)read_u16(input_buf+parser_pos);
-		parser_pos+=(int)sizeof(u16_t);
-		if(parser_pos+len_arr[i]>current_len) {mylog(log_info,"failed 3 %d  %d %d\n",parser_pos,len_arr[i],current_len);return -1;}
-		s_arr[i]=input_buf+parser_pos;
-		parser_pos+=len_arr[i];
-	}
-	return 0;
-}
+    if (parser_pos + (int)sizeof(u32_t) > current_len) {
+        mylog(log_info, "failed 0\n");
+        return -1;
+    }
 
+    n = (int)read_u32(input_buf + parser_pos);
+    if (n > max_blob_packet_num) {
+        mylog(log_info, "failed 1\n");
+        return -1;
+    }
+    s_arr = output_buf;
+    len_arr = output_len;
+
+    parser_pos += sizeof(u32_t);
+    for (int i = 0; i < n; i++) {
+        if (parser_pos + (int)sizeof(u16_t) > current_len) {
+            mylog(log_info, "failed2 \n");
+            return -1;
+        }
+        len_arr[i] = (int)read_u16(input_buf + parser_pos);
+        parser_pos += (int)sizeof(u16_t);
+        if (parser_pos + len_arr[i] > current_len) {
+            mylog(log_info, "failed 3 %d  %d %d\n", parser_pos, len_arr[i], current_len);
+            return -1;
+        }
+        s_arr[i] = input_buf + parser_pos;
+        parser_pos += len_arr[i];
+    }
+    return 0;
+}
 
-fec_encode_manager_t::~fec_encode_manager_t()
-{
-	clear_all();
-	//fd_manager.fd64_close(timer_fd64);
+fec_encode_manager_t::~fec_encode_manager_t() {
+    clear_all();
+    // fd_manager.fd64_close(timer_fd64);
 }
 /*
 u64_t fec_encode_manager_t::get_timer_fd64()
 {
-	return timer_fd64;
+        return timer_fd64;
 }*/
 
-fec_encode_manager_t::fec_encode_manager_t()
-{
-	//int timer_fd;
-
-	/*
-	if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
-	{
-		mylog(log_fatal,"timer_fd create error");
-		myexit(1);
-	}
-	timer_fd64=fd_manager.create(timer_fd);*/
+fec_encode_manager_t::fec_encode_manager_t() {
+    // int timer_fd;
 
+    /*
+    if ((timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) < 0)
+    {
+            mylog(log_fatal,"timer_fd create error");
+            myexit(1);
+    }
+    timer_fd64=fd_manager.create(timer_fd);*/
 
-	/////reset_fec_parameter(g_fec_data_num,g_fec_redundant_num,g_fec_mtu,g_fec_queue_len,g_fec_timeout,g_fec_mode);
-
-	fec_par.clone(g_fec_par);
-	clear_data();
+    /////reset_fec_parameter(g_fec_data_num,g_fec_redundant_num,g_fec_mtu,g_fec_queue_len,g_fec_timeout,g_fec_mode);
 
+    fec_par.clone(g_fec_par);
+    clear_data();
 }
 /*
 int fec_encode_manager_t::reset_fec_parameter(int data_num,int redundant_num,int mtu,int queue_len,int timeout,int mode)
 {
-	fec_data_num=data_num;
-	fec_redundant_num=redundant_num;
-	fec_mtu=mtu;
-	fec_queue_len=queue_len;
-	fec_timeout=timeout;
-	fec_mode=mode;
+        fec_data_num=data_num;
+        fec_redundant_num=redundant_num;
+        fec_mtu=mtu;
+        fec_queue_len=queue_len;
+        fec_timeout=timeout;
+        fec_mode=mode;
 
-	assert(data_num+redundant_num<max_fec_packet_num);
+        assert(data_num+redundant_num<max_fec_packet_num);
 
-	//clear();
+        //clear();
 
-	clear_data();
-	return 0;
+        clear_data();
+        return 0;
 }*/
-int fec_encode_manager_t::append(char *s,int len/*,int &is_first_packet*/)
-{
-	if(counter==0)
-	{
-		first_packet_time=get_current_time_us();
-
-		const double m=1000*1000;
-
-		ev_timer_stop(loop, &timer);
-		ev_timer_set(&timer, fec_par.timeout/m,0 );
-		ev_timer_start(loop, &timer);
-	}
-	if(fec_par.mode==0)//for type 0 use blob
-	{
-		assert(blob_encode.input(s,len)==0);
-	}
-	else if(fec_par.mode==1)//for tpe 1 use  input_buf and counter
-	{
-		mylog(log_trace,"counter=%d\n",counter);
-		assert(len<=65535&&len>=0);
-		//assert(len<=fec_mtu);//relax this limitation
-		char * p=input_buf[counter]+sizeof(u32_t)+4*sizeof(char);//copy directly to final position,avoid unnecessary copy.
-		//remember to change this,if protocol is modified
-
-		write_u16(p,(u16_t)((u32_t)len));  //TODO  omit this u16 for data packet while sending
-		p+=sizeof(u16_t);
-		memcpy(p,s,len);
-		input_len[counter]=len+sizeof(u16_t);
-	}
-	else
-	{
-		assert(0==1);
-	}
-	counter++;
-	return 0;
-}
-int fec_encode_manager_t::input(char *s,int len/*,int &is_first_packet*/)
-{
-	if(counter==0&&fec_par.version!=g_fec_par.version)
-	{
-		fec_par.clone(g_fec_par);
-	}
-
-	int about_to_fec=0;
-	int delayed_append=0;
-	//int counter_back=counter;
-	assert(fec_par.mode==0||fec_par.mode==1);
-
-	if(fec_par.mode==0&& s!=0 &&counter==0)
-	{
-		int out_len=blob_encode.get_shard_len(fec_par.get_tail().x,len);
-		if(out_len>fec_par.mtu)
-		{
-			mylog(log_warn,"message too long ori_len=%d out_len=%d fec_mtu=%d,ignored\n",len,out_len,fec_par.mtu);
-			return -1;
-		}
-	}
-	if(fec_par.mode==1&&s!=0&&len>fec_par.mtu)
-	{
-		mylog(log_warn,"mode==1,message len=%d,len>fec_mtu,fec_mtu=%d,packet may not be delivered\n",len,fec_par.mtu);
-		//return -1;
-	}
-	if(s==0&&counter==0)
-	{
-		mylog(log_warn,"unexpected s==0&&counter==0\n");
-		return -1;
-	}
-	if(s==0) about_to_fec=1;//now
-
-	if(fec_par.mode==0&& blob_encode.get_shard_len(fec_par.get_tail().x,len)>fec_par.mtu) {about_to_fec=1; delayed_append=1;}//fec then add packet
-
-	if(fec_par.mode==0) assert(counter<fec_par.queue_len);//counter will never equal fec_pending_num,if that happens fec should already been done.
-	if(fec_par.mode==1) assert(counter<fec_par.get_tail().x);
-
-
-	if(s!=0&&!delayed_append)
-	{
-		append(s,len);
-	}
-
-	if(fec_par.mode==0&& counter==fec_par.queue_len) about_to_fec=1;
-
-	if(fec_par.mode==1&& counter==fec_par.get_tail().x) about_to_fec=1;
-
-
-    if(about_to_fec)
-	{
-    	char ** blob_output=0;
-    	int fec_len=-1;
-    	mylog(log_trace,"counter=%d\n",counter);
-
-    	if(counter==0)
-    	{
-    		mylog(log_warn,"unexpected counter==0 here\n");
-    		return -1;
-    	}
-
-    	int actual_data_num;
-    	int actual_redundant_num;
-
-    	if(fec_par.mode==0)
-    	{
-
-
-    		int tail_x=fec_par.get_tail().x;
-    		int tail_y=fec_par.get_tail().y;
-    		actual_data_num=tail_x;
-    		actual_redundant_num=tail_y;
-
-    		if(short_packet_optimize)
-    		{
-    			u32_t best_len=(blob_encode.get_shard_len(tail_x,0)+header_overhead)*(tail_x+tail_y);
-    			int best_data_num=tail_x;
-    			assert(tail_x<=fec_par.rs_cnt);
-    			for(int i=1;i<tail_x;i++)
-    			{
-    				assert(fec_par.rs_par[i-1].x==i);
-    				int tmp_x=fec_par.rs_par[i-1].x;
-    				int tmp_y=fec_par.rs_par[i-1].y;
-    				assert(tmp_x==i);
-    				u32_t shard_len=blob_encode.get_shard_len(tmp_x,0);
-    				if(shard_len>(u32_t)fec_par.mtu) continue;
-
-    				u32_t new_len=(shard_len+header_overhead)*(tmp_x+tmp_y);
-    				if(new_len<best_len)
-    				{
-    					best_len=new_len;
-    					best_data_num=tmp_x;
-    				}
-    			}
-    			actual_data_num=best_data_num;
-    			assert(best_data_num>=1&&best_data_num<=fec_par.rs_cnt);
-    			actual_redundant_num=fec_par.rs_par[best_data_num-1].y;
-    		}
-
-        	assert(blob_encode.output(actual_data_num,blob_output,fec_len)==0);
-
-    		if(debug_fec_enc)
-    			mylog(log_debug,"[enc]seq=%08x x=%d y=%d len=%d cnt=%d\n",seq,actual_data_num,actual_redundant_num,fec_len,counter);
-    		else
-    			mylog(log_trace,"[enc]seq=%08x x=%d y=%d len=%d cnt=%d\n",seq,actual_data_num,actual_redundant_num,fec_len,counter);
-    	}
-    	else
-    	{
-    		assert(counter<=fec_par.rs_cnt);
-    		actual_data_num=counter;
-    		actual_redundant_num=fec_par.rs_par[counter-1].y;
-
-    		int sum_ori=0;
-    		for(int i=0;i<counter;i++)
-    		{
-    			sum_ori+=input_len[i];
-    			assert(input_len[i]>=0);
-    			if(input_len[i]>fec_len) fec_len=input_len[i];
-    		}
-
-    		int sum=fec_len*counter;
-
-    		if(debug_fec_enc)
-    			mylog(log_debug,"[enc]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d\n",seq,actual_data_num,actual_redundant_num,fec_len,sum_ori,sum);
-    		else
-    			mylog(log_trace,"[enc]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d\n",seq,actual_data_num,actual_redundant_num,fec_len,sum_ori,sum);
-    	}
-
-    	//mylog(log_trace,"%d %d %d\n",actual_data_num,actual_redundant_num,fec_len);
-
-    	char *tmp_output_buf[max_fec_packet_num+5]={0};
-    	for(int i=0;i<actual_data_num+actual_redundant_num;i++)
-    	{
-    		int tmp_idx=0;
-
-        	write_u32(input_buf[i] + tmp_idx, seq);
-			tmp_idx += sizeof(u32_t);
-			input_buf[i][tmp_idx++] = (unsigned char) fec_par.mode;
-			if (fec_par.mode == 1 && i < actual_data_num)
-			{
-				input_buf[i][tmp_idx++] = (unsigned char) 0;
-				input_buf[i][tmp_idx++] = (unsigned char) 0;
-			} else
-			{
-				input_buf[i][tmp_idx++] = (unsigned char) actual_data_num;
-				input_buf[i][tmp_idx++] = (unsigned char) actual_redundant_num;
-			}
-			input_buf[i][tmp_idx++] = (unsigned char) i;
-
-    		tmp_output_buf[i]=input_buf[i]+tmp_idx; //////caution ,trick here.
-
-    		if(fec_par.mode==0)
-    		{
-        		output_len[i]=tmp_idx+fec_len;
-        		if(i<actual_data_num)
-        		{
-        			memcpy(input_buf[i]+tmp_idx,blob_output[i],fec_len);
-        		}
-    		}
-    		else
-    		{
-    			if(i<actual_data_num)
-    			{
-    				output_len[i]=tmp_idx+input_len[i];
-    				memset(tmp_output_buf[i]+input_len[i],0,fec_len-input_len[i]);
-    			}
-    			else
-    				output_len[i]=tmp_idx+fec_len;
-
-    		}
-    		output_buf[i]=input_buf[i];//output_buf points to same block of memory with different offset
-
-    	}
-
-    	if(0)
-    	{
-			printf("seq=%u,fec_len=%d,%d %d,before fec\n",seq,fec_len,actual_data_num,actual_redundant_num);
-
-			for(int i=0;i<actual_data_num;i++)
-			{
-				printf("{");
-				for(int j=0;j<8+fec_len;j++)
-				{
-					log_bare(log_warn,"0x%02x,",(u32_t)(unsigned char)input_buf[i][j]);
-				}
-				printf("},\n");
-				//log_bare(log_warn,"")
-			}
-    	}
-    	//output_len=blob_len+sizeof(u32_t)+4*sizeof(char);/////remember to change this 4,if modified the protocol
-		rs_encode2(actual_data_num,actual_data_num+actual_redundant_num,tmp_output_buf,fec_len);
-
-		if(0)
-		{
-			printf("seq=%u,fec_len=%d,%d %d,after fec\n",seq,fec_len,actual_data_num,actual_redundant_num);
-			for(int i=0;i<actual_data_num+actual_redundant_num;i++)
-			{
-				printf("{");
-				for(int j=0;j<8+fec_len;j++)
-				{
-					log_bare(log_warn,"0x%02x,",(u32_t)(unsigned char)output_buf[i][j]);
-				}
-				printf("},\n");
-				//log_bare(log_warn,"")
-			}
-		}
-
-		//mylog(log_trace,"!!! s= %d\n");
-		assert(ready_for_output==0);
-    	ready_for_output=1;
-    	first_packet_time_for_output=first_packet_time;
-    	first_packet_time=0;
-    	seq++;
-    	counter=0;
-    	output_n=actual_data_num+actual_redundant_num;
-    	blob_encode.clear();
-
-		my_itimerspec its;
-		memset(&its,0,sizeof(its));
-		ev_timer_stop(loop, &timer);
-		//timerfd_settime(timer_fd,TFD_TIMER_ABSTIME,&its,0);
-
-    	if(encode_fast_send&&fec_par.mode==1)
-    	{
-			int packet_to_send[max_fec_packet_num+5]={0};
-			int packet_to_send_counter=0;
-
-			//assert(counter!=0);
-			if(s!=0)
-				packet_to_send[packet_to_send_counter++]=actual_data_num-1;
-			for(int i=actual_data_num;i<actual_data_num+actual_redundant_num;i++)
-			{
-
-					packet_to_send[packet_to_send_counter++]=i;
-			}
-			output_n=packet_to_send_counter;//re write
-			for(int i=0;i<packet_to_send_counter;i++)
-			{
-				output_buf[i]=output_buf[packet_to_send[i]];
-				output_len[i]=output_len[packet_to_send[i]];
-			}
-
-    	}
-	}
-    else
+int fec_encode_manager_t::append(char *s, int len /*,int &is_first_packet*/) {
+    if (counter == 0) {
+        first_packet_time = get_current_time_us();
+
+        const double m = 1000 * 1000;
+
+        ev_timer_stop(loop, &timer);
+        ev_timer_set(&timer, fec_par.timeout / m, 0);
+        ev_timer_start(loop, &timer);
+    }
+    if (fec_par.mode == 0)  // for type 0 use blob
+    {
+        assert(blob_encode.input(s, len) == 0);
+    } else if (fec_par.mode == 1)  // for tpe 1 use  input_buf and counter
     {
-    	if(encode_fast_send&&s!=0&&fec_par.mode==1)
-    	{
-    		assert(counter>=1);
-    		assert(counter<=255);
-    		int input_buf_idx=counter-1;
-    		assert(ready_for_output==0);
-    		ready_for_output=1;
-    		first_packet_time_for_output=0;
-    		output_n=1;
-
-
-    		int tmp_idx=0;
-    		write_u32(input_buf[input_buf_idx]+tmp_idx,seq);
-    		tmp_idx+=sizeof(u32_t);
-
-    		input_buf[input_buf_idx][tmp_idx++]=(unsigned char)fec_par.mode;
-    		input_buf[input_buf_idx][tmp_idx++]=(unsigned char)0;
-    		input_buf[input_buf_idx][tmp_idx++]=(unsigned char)0;
-    		input_buf[input_buf_idx][tmp_idx++]=(unsigned char)((u32_t)input_buf_idx);
-
-    		output_len[0]=input_len[input_buf_idx]+tmp_idx;
-    		output_buf[0]=input_buf[input_buf_idx];
-
-    		if(0)
-    		{
-				printf("seq=%u,buf_idx=%d\n",seq,input_buf_idx);
-				for(int j=0;j<output_len[0];j++)
-				{
-					log_bare(log_warn,"0x%02x,",(u32_t)(unsigned char)output_buf[0][j]);
-				}
-				printf("\n");
-    		}
-    	}
+        mylog(log_trace, "counter=%d\n", counter);
+        assert(len <= 65535 && len >= 0);
+        // assert(len<=fec_mtu);//relax this limitation
+        char *p = input_buf[counter] + sizeof(u32_t) + 4 * sizeof(char);  // copy directly to final position,avoid unnecessary copy.
+        // remember to change this,if protocol is modified
+
+        write_u16(p, (u16_t)((u32_t)len));  // TODO  omit this u16 for data packet while sending
+        p += sizeof(u16_t);
+        memcpy(p, s, len);
+        input_len[counter] = len + sizeof(u16_t);
+    } else {
+        assert(0 == 1);
+    }
+    counter++;
+    return 0;
+}
+int fec_encode_manager_t::input(char *s, int len /*,int &is_first_packet*/) {
+    if (counter == 0 && fec_par.version != g_fec_par.version) {
+        fec_par.clone(g_fec_par);
+    }
+
+    int about_to_fec = 0;
+    int delayed_append = 0;
+    // int counter_back=counter;
+    assert(fec_par.mode == 0 || fec_par.mode == 1);
+
+    if (fec_par.mode == 0 && s != 0 && counter == 0) {
+        int out_len = blob_encode.get_shard_len(fec_par.get_tail().x, len);
+        if (out_len > fec_par.mtu) {
+            mylog(log_warn, "message too long ori_len=%d out_len=%d fec_mtu=%d,ignored\n", len, out_len, fec_par.mtu);
+            return -1;
+        }
+    }
+    if (fec_par.mode == 1 && s != 0 && len > fec_par.mtu) {
+        mylog(log_warn, "mode==1,message len=%d,len>fec_mtu,fec_mtu=%d,packet may not be delivered\n", len, fec_par.mtu);
+        // return -1;
+    }
+    if (s == 0 && counter == 0) {
+        mylog(log_warn, "unexpected s==0&&counter==0\n");
+        return -1;
     }
+    if (s == 0) about_to_fec = 1;  // now
 
-	if(s!=0&&delayed_append)
-	{
-		assert(fec_par.mode!=1);
-		append(s,len);
-	}
+    if (fec_par.mode == 0 && blob_encode.get_shard_len(fec_par.get_tail().x, len) > fec_par.mtu) {
+        about_to_fec = 1;
+        delayed_append = 1;
+    }  // fec then add packet
 
-	return 0;
+    if (fec_par.mode == 0) assert(counter < fec_par.queue_len);  // counter will never equal fec_pending_num,if that happens fec should already been done.
+    if (fec_par.mode == 1) assert(counter < fec_par.get_tail().x);
+
+    if (s != 0 && !delayed_append) {
+        append(s, len);
+    }
+
+    if (fec_par.mode == 0 && counter == fec_par.queue_len) about_to_fec = 1;
+
+    if (fec_par.mode == 1 && counter == fec_par.get_tail().x) about_to_fec = 1;
+
+    if (about_to_fec) {
+        char **blob_output = 0;
+        int fec_len = -1;
+        mylog(log_trace, "counter=%d\n", counter);
+
+        if (counter == 0) {
+            mylog(log_warn, "unexpected counter==0 here\n");
+            return -1;
+        }
+
+        int actual_data_num;
+        int actual_redundant_num;
+
+        if (fec_par.mode == 0) {
+            int tail_x = fec_par.get_tail().x;
+            int tail_y = fec_par.get_tail().y;
+            actual_data_num = tail_x;
+            actual_redundant_num = tail_y;
+
+            if (short_packet_optimize) {
+                u32_t best_len = (blob_encode.get_shard_len(tail_x, 0) + header_overhead) * (tail_x + tail_y);
+                int best_data_num = tail_x;
+                assert(tail_x <= fec_par.rs_cnt);
+                for (int i = 1; i < tail_x; i++) {
+                    assert(fec_par.rs_par[i - 1].x == i);
+                    int tmp_x = fec_par.rs_par[i - 1].x;
+                    int tmp_y = fec_par.rs_par[i - 1].y;
+                    assert(tmp_x == i);
+                    u32_t shard_len = blob_encode.get_shard_len(tmp_x, 0);
+                    if (shard_len > (u32_t)fec_par.mtu) continue;
+
+                    u32_t new_len = (shard_len + header_overhead) * (tmp_x + tmp_y);
+                    if (new_len < best_len) {
+                        best_len = new_len;
+                        best_data_num = tmp_x;
+                    }
+                }
+                actual_data_num = best_data_num;
+                assert(best_data_num >= 1 && best_data_num <= fec_par.rs_cnt);
+                actual_redundant_num = fec_par.rs_par[best_data_num - 1].y;
+            }
+
+            assert(blob_encode.output(actual_data_num, blob_output, fec_len) == 0);
+
+            if (debug_fec_enc)
+                mylog(log_debug, "[enc]seq=%08x x=%d y=%d len=%d cnt=%d\n", seq, actual_data_num, actual_redundant_num, fec_len, counter);
+            else
+                mylog(log_trace, "[enc]seq=%08x x=%d y=%d len=%d cnt=%d\n", seq, actual_data_num, actual_redundant_num, fec_len, counter);
+        } else {
+            assert(counter <= fec_par.rs_cnt);
+            actual_data_num = counter;
+            actual_redundant_num = fec_par.rs_par[counter - 1].y;
+
+            int sum_ori = 0;
+            for (int i = 0; i < counter; i++) {
+                sum_ori += input_len[i];
+                assert(input_len[i] >= 0);
+                if (input_len[i] > fec_len) fec_len = input_len[i];
+            }
+
+            int sum = fec_len * counter;
+
+            if (debug_fec_enc)
+                mylog(log_debug, "[enc]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d\n", seq, actual_data_num, actual_redundant_num, fec_len, sum_ori, sum);
+            else
+                mylog(log_trace, "[enc]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d\n", seq, actual_data_num, actual_redundant_num, fec_len, sum_ori, sum);
+        }
+
+        // mylog(log_trace,"%d %d %d\n",actual_data_num,actual_redundant_num,fec_len);
+
+        char *tmp_output_buf[max_fec_packet_num + 5] = {0};
+        for (int i = 0; i < actual_data_num + actual_redundant_num; i++) {
+            int tmp_idx = 0;
+
+            write_u32(input_buf[i] + tmp_idx, seq);
+            tmp_idx += sizeof(u32_t);
+            input_buf[i][tmp_idx++] = (unsigned char)fec_par.mode;
+            if (fec_par.mode == 1 && i < actual_data_num) {
+                input_buf[i][tmp_idx++] = (unsigned char)0;
+                input_buf[i][tmp_idx++] = (unsigned char)0;
+            } else {
+                input_buf[i][tmp_idx++] = (unsigned char)actual_data_num;
+                input_buf[i][tmp_idx++] = (unsigned char)actual_redundant_num;
+            }
+            input_buf[i][tmp_idx++] = (unsigned char)i;
+
+            tmp_output_buf[i] = input_buf[i] + tmp_idx;  //////caution ,trick here.
+
+            if (fec_par.mode == 0) {
+                output_len[i] = tmp_idx + fec_len;
+                if (i < actual_data_num) {
+                    memcpy(input_buf[i] + tmp_idx, blob_output[i], fec_len);
+                }
+            } else {
+                if (i < actual_data_num) {
+                    output_len[i] = tmp_idx + input_len[i];
+                    memset(tmp_output_buf[i] + input_len[i], 0, fec_len - input_len[i]);
+                } else
+                    output_len[i] = tmp_idx + fec_len;
+            }
+            output_buf[i] = input_buf[i];  // output_buf points to same block of memory with different offset
+        }
+
+        if (0) {
+            printf("seq=%u,fec_len=%d,%d %d,before fec\n", seq, fec_len, actual_data_num, actual_redundant_num);
+
+            for (int i = 0; i < actual_data_num; i++) {
+                printf("{");
+                for (int j = 0; j < 8 + fec_len; j++) {
+                    log_bare(log_warn, "0x%02x,", (u32_t)(unsigned char)input_buf[i][j]);
+                }
+                printf("},\n");
+                // log_bare(log_warn,"")
+            }
+        }
+        // output_len=blob_len+sizeof(u32_t)+4*sizeof(char);/////remember to change this 4,if modified the protocol
+        rs_encode2(actual_data_num, actual_data_num + actual_redundant_num, tmp_output_buf, fec_len);
+
+        if (0) {
+            printf("seq=%u,fec_len=%d,%d %d,after fec\n", seq, fec_len, actual_data_num, actual_redundant_num);
+            for (int i = 0; i < actual_data_num + actual_redundant_num; i++) {
+                printf("{");
+                for (int j = 0; j < 8 + fec_len; j++) {
+                    log_bare(log_warn, "0x%02x,", (u32_t)(unsigned char)output_buf[i][j]);
+                }
+                printf("},\n");
+                // log_bare(log_warn,"")
+            }
+        }
+
+        // mylog(log_trace,"!!! s= %d\n");
+        assert(ready_for_output == 0);
+        ready_for_output = 1;
+        first_packet_time_for_output = first_packet_time;
+        first_packet_time = 0;
+        seq++;
+        counter = 0;
+        output_n = actual_data_num + actual_redundant_num;
+        blob_encode.clear();
+
+        my_itimerspec its;
+        memset(&its, 0, sizeof(its));
+        ev_timer_stop(loop, &timer);
+        // timerfd_settime(timer_fd,TFD_TIMER_ABSTIME,&its,0);
+
+        if (encode_fast_send && fec_par.mode == 1) {
+            int packet_to_send[max_fec_packet_num + 5] = {0};
+            int packet_to_send_counter = 0;
+
+            // assert(counter!=0);
+            if (s != 0)
+                packet_to_send[packet_to_send_counter++] = actual_data_num - 1;
+            for (int i = actual_data_num; i < actual_data_num + actual_redundant_num; i++) {
+                packet_to_send[packet_to_send_counter++] = i;
+            }
+            output_n = packet_to_send_counter;  // re write
+            for (int i = 0; i < packet_to_send_counter; i++) {
+                output_buf[i] = output_buf[packet_to_send[i]];
+                output_len[i] = output_len[packet_to_send[i]];
+            }
+        }
+    } else {
+        if (encode_fast_send && s != 0 && fec_par.mode == 1) {
+            assert(counter >= 1);
+            assert(counter <= 255);
+            int input_buf_idx = counter - 1;
+            assert(ready_for_output == 0);
+            ready_for_output = 1;
+            first_packet_time_for_output = 0;
+            output_n = 1;
+
+            int tmp_idx = 0;
+            write_u32(input_buf[input_buf_idx] + tmp_idx, seq);
+            tmp_idx += sizeof(u32_t);
+
+            input_buf[input_buf_idx][tmp_idx++] = (unsigned char)fec_par.mode;
+            input_buf[input_buf_idx][tmp_idx++] = (unsigned char)0;
+            input_buf[input_buf_idx][tmp_idx++] = (unsigned char)0;
+            input_buf[input_buf_idx][tmp_idx++] = (unsigned char)((u32_t)input_buf_idx);
+
+            output_len[0] = input_len[input_buf_idx] + tmp_idx;
+            output_buf[0] = input_buf[input_buf_idx];
+
+            if (0) {
+                printf("seq=%u,buf_idx=%d\n", seq, input_buf_idx);
+                for (int j = 0; j < output_len[0]; j++) {
+                    log_bare(log_warn, "0x%02x,", (u32_t)(unsigned char)output_buf[0][j]);
+                }
+                printf("\n");
+            }
+        }
+    }
+
+    if (s != 0 && delayed_append) {
+        assert(fec_par.mode != 1);
+        append(s, len);
+    }
+
+    return 0;
 }
 
-int fec_encode_manager_t::output(int &n,char ** &s_arr,int *&len)
-{
-	if(!ready_for_output)
-	{
-		n=-1;
-		len=0;
-		s_arr=0;
-	}
-	else
-	{
-		n=output_n;
-		len=output_len;
-		s_arr=output_buf;
-		ready_for_output=0;
-	}
-	return 0;
+int fec_encode_manager_t::output(int &n, char **&s_arr, int *&len) {
+    if (!ready_for_output) {
+        n = -1;
+        len = 0;
+        s_arr = 0;
+    } else {
+        n = output_n;
+        len = output_len;
+        s_arr = output_buf;
+        ready_for_output = 0;
+    }
+    return 0;
 }
 /*
 int fec_decode_manager_t::re_init()
 {
-	clear();
-	return 0;
+        clear();
+        return 0;
 }*/
 
-int fec_decode_manager_t::input(char *s,int len)
-{
-	assert(s!=0);
-	assert(len+100<buf_len);//guarenteed by upper level
-
-	int tmp_idx=0;
-	int tmp_header_len=sizeof(u32_t)+sizeof(char)*4;
-	if(len<tmp_header_len)
-	{
-		mylog(log_warn,"len =%d\n",len);
-		return -1;
-	}
-	u32_t seq=read_u32(s+tmp_idx);
-	tmp_idx+=sizeof(u32_t);
-	int type=(unsigned char)s[tmp_idx++];
-	int data_num=(unsigned char)s[tmp_idx++];
-	int redundant_num=(unsigned char)s[tmp_idx++];
-	int inner_index=(unsigned char)s[tmp_idx++];
-	len=len-tmp_idx;
-
-	//mylog(log_trace,"input\n");
-
-	if(len<0)
-	{
-		mylog(log_warn,"len<0\n");
-		return -1;
-	}
-
-	if(type==1)
-	{
-		if(len<(int)sizeof(u16_t))
-		{
-			mylog(log_warn,"type==1&&len<2\n");
-			return -1;
-		}
-		if(data_num==0&&(int)( read_u16(s+tmp_idx)+sizeof(u16_t))!=len)
-		{
-			mylog(log_warn,"inner_index<data_num&&read_u16(s+tmp_idx)+sizeof(u16_t)!=len    %d %d\n",(int)( read_u16(s+tmp_idx)+sizeof(u16_t)),len);
-			return -1;
-		}
-	}
-
-	if(type==0&&data_num==0)
-	{
-		mylog(log_warn,"unexpected type==0&&data_num==0\n");
-		return -1;
-	}
-	if(data_num+redundant_num>=max_fec_packet_num)
-	{
-		mylog(log_warn,"data_num+redundant_num>=max_fec_packet_num\n");
-		return -1;
-	}
-	if(!anti_replay.is_vaild(seq))
-	{
-		mylog(log_trace,"!anti_replay.is_vaild(seq) ,seq =%u\n",seq);
-		return 0;
-	}
-
-	if(mp[seq].fec_done!=0)
-	{
-		mylog(log_debug,"fec already done, ignore, seq=%u\n",seq);
-		return -1;
-	}
-
-	if(mp[seq].group_mp.find(inner_index)!=mp[seq].group_mp.end() )
-	{
-		mylog(log_debug,"dup fec index\n");//duplicate can happen on  a normal network, so its just log_debug
-		return -1;
-	}
-
-
-	if(mp[seq].type==-1)
-		mp[seq].type=type;
-	else
-	{
-		if(mp[seq].type!=type)
-		{
-			mylog(log_warn,"type mismatch\n");
-			return -1;
-		}
-	}
-
-	if(data_num!=0)
-	{
-		//mp[seq].data_counter++;
-
-		if(mp[seq].data_num==-1)
-		{
-			mp[seq].data_num=data_num;
-			mp[seq].redundant_num=redundant_num;
-			mp[seq].len=len;
-		}
-		else
-		{
-			if(mp[seq].data_num!=data_num||mp[seq].redundant_num!=redundant_num||mp[seq].len!=len)
-			{
-				mylog(log_warn,"unexpected mp[seq].data_num!=data_num||mp[seq].redundant_num!=redundant_num||mp[seq].len!=len\n");
-				return -1;
-			}
-		}
-	}
-
-	//mylog(log_info,"mp.size()=%d index=%d\n",mp.size(),index);
-
-	if(fec_data[index].used!=0)
-	{
-		u32_t tmp_seq=fec_data[index].seq;
-		anti_replay.set_invaild(tmp_seq);
-
-		auto tmp_it=mp.find(tmp_seq);
-		if(tmp_it!=mp.end())
-		{
-			int x=tmp_it->second.data_num;
-			int y=tmp_it->second.redundant_num;
-			int cnt=tmp_it->second.group_mp.size();
-
-			if(cnt<x)
-			{
-				if(debug_fec_dec)
-					mylog(log_debug,"[dec][failed]seq=%08x x=%d y=%d cnt=%d\n",tmp_seq,x,y,cnt);
-				else
-					mylog(log_trace,"[dec][failed]seq=%08x x=%d y=%d cnt=%d\n",tmp_seq,x,y,cnt);
-			}
-			mp.erase(tmp_it);
-		}
-		if(tmp_seq==seq)
-		{
-			mylog(log_warn,"unexpected tmp_seq==seq ,seq=%d\n",seq);
-			return -1;
-		}
-	}
-
-	fec_data[index].used=1;
-	fec_data[index].seq=seq;
-	fec_data[index].type=type;
-	fec_data[index].data_num=data_num;
-	fec_data[index].redundant_num=redundant_num;
-	fec_data[index].idx=inner_index;
-	fec_data[index].len=len;
-	assert(0<=index&&index<(int)fec_buff_num);
-	assert(len+100<buf_len);
-	memcpy(fec_data[index].buf,s+tmp_idx,len);
-	mp[seq].group_mp[inner_index]=index;
-	//index++ at end of function
-
-	map<int,int> &inner_mp=mp[seq].group_mp;
-
-
-	int about_to_fec=0;
-	if(type==0)
-	{
-		//assert((int)inner_mp.size()<=data_num);
-		if((int)inner_mp.size()>data_num)
-		{
-			mylog(log_warn,"inner_mp.size()>data_num\n");
-			anti_replay.set_invaild(seq);
-			goto end;
-		}
-		if((int)inner_mp.size()==data_num)
-			about_to_fec=1;
-	}
-	else
-	{
-		if(mp[seq].data_num!=-1)
-		{
-			if((int)inner_mp.size()>mp[seq].data_num+1)
-			{
-				mylog(log_warn,"inner_mp.size()>data_num+1\n");
-				anti_replay.set_invaild(seq);
-				goto end;
-			}
-			if((int)inner_mp.size()>=mp[seq].data_num)
-			{
-				about_to_fec=1;
-			}
-		}
-	}
-
-
-	if(about_to_fec)
-	{
-		int group_data_num=mp[seq].data_num;
-		int group_redundant_num=mp[seq].redundant_num;
-
-		int x_got=0;
-		int y_got=0;
-		//mylog(log_error,"fec here!\n");
-		if(type==0)
-		{
-			char *fec_tmp_arr[max_fec_packet_num+5]={0};
-			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
-			{
-				if(it->first <group_data_num)
-					x_got++;
-				else
-					y_got++;
-				fec_tmp_arr[it->first]=fec_data[it->second].buf;
-			}
-			assert(rs_decode2(group_data_num,group_data_num+group_redundant_num,fec_tmp_arr,len)==0); //the input data has been modified in-place
-			//this line should always succeed
-    		mp[seq].fec_done=1;
-
-    		if(debug_fec_dec)
-    			mylog(log_debug,"[dec]seq=%08x x=%d y=%d len=%d cnt=%d X=%d Y=%d\n",seq,group_data_num,group_redundant_num,len,int(inner_mp.size()),x_got,y_got);
-    		else
-    			mylog(log_trace,"[dec]seq=%08x x=%d y=%d len=%d cnt=%d X=%d Y=%d\n",seq,group_data_num,group_redundant_num,len,int(inner_mp.size()),x_got,y_got);
-
-			blob_decode.clear();
-			for(int i=0;i<group_data_num;i++)
-			{
-				blob_decode.input(fec_tmp_arr[i],len);
-			}
-			if(blob_decode.output(output_n,output_s_arr,output_len_arr)!=0)
-			{
-				mylog(log_warn,"blob_decode failed\n");
-				//ready_for_output=0;
-				anti_replay.set_invaild(seq);
-				goto end;
-			}
-			assert(ready_for_output==0);
-			ready_for_output=1;
-			anti_replay.set_invaild(seq);
-		}
-		else//type==1
-		{
-
-
-			int max_len=-1;
-			int fec_result_ok=1;
-			int data_check_ok=1;
-			int debug_num=inner_mp.size();
-
-			int missed_packet[max_fec_packet_num+5];
-			int missed_packet_counter=0;
-
-			//outupt_s_arr_buf[max_fec_packet_num+5]={0};
-
-			//memset(output_s_arr_buf,0,sizeof(output_s_arr_buf));//in efficient
-
-			for(int i=0;i<group_data_num+group_redundant_num;i++)
-			{
-				output_s_arr_buf[i]=0;
-			}
-			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
-			{
-				if(it->first <group_data_num)
-					x_got++;
-				else
-					y_got++;
-
-				output_s_arr_buf[it->first]=fec_data[it->second].buf;
-				if(fec_data[it->second].len<(int)sizeof(u16_t))
-				{
-					mylog(log_warn,"fec_data[it->second].len<(int)sizeof(u16_t)");
-					data_check_ok=0;
-				}
-
-				if(fec_data[it->second].len > max_len)
-					max_len=fec_data[it->second].len;
-			}
-			if(max_len!=mp[seq].len)
-			{
-				data_check_ok=0;
-				mylog(log_warn,"max_len!=mp[seq].len");
-			}
-			if(data_check_ok==0)
-			{
-				//ready_for_output=0;
-				mylog(log_warn,"data_check_ok==0\n");
-				anti_replay.set_invaild(seq);
-				goto end;
-			}
-			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
-			{
-				int tmp_idx=it->second;
-				assert(max_len>=fec_data[tmp_idx].len);//guarenteed by data_check_ok
-				memset(fec_data[tmp_idx].buf+fec_data[tmp_idx].len,0,max_len-fec_data[tmp_idx].len);
-			}
-
-			for(int i=0;i<group_data_num;i++)
-			{
-				if(output_s_arr_buf[i]==0 ||i==inner_index) //only missed packet +current packet
-				{
-					missed_packet[missed_packet_counter++]=i;
-				}
-			}
-			mylog(log_trace,"fec done,%d %d,missed_packet_counter=%d\n",group_data_num,group_redundant_num,missed_packet_counter);
-
-			assert(rs_decode2(group_data_num,group_data_num+group_redundant_num,output_s_arr_buf,max_len)==0);//this should always succeed
-			mp[seq].fec_done=1;
-
-			int sum_ori=0;
-
-			for(int i=0;i<group_data_num;i++)
-			{
-				output_len_arr_buf[i]=read_u16(output_s_arr_buf[i]);
-				sum_ori+=output_len_arr_buf[i];
-				output_s_arr_buf[i]+=sizeof(u16_t);
-				if(output_len_arr_buf[i]>max_data_len)
-				{
-					mylog(log_warn,"invaild len %d,seq= %u,data_num= %d r_num= %d,i= %d\n",output_len_arr_buf[i],seq,group_data_num,group_redundant_num,i);
-					fec_result_ok=0;
-					for(int i=0;i<missed_packet_counter;i++)
-					{
-						log_bare(log_warn,"%d ",missed_packet[i]);
-					}
-					log_bare(log_warn,"\n");
-					//break;
-				}
-			}
-
-			int sum=max_len*group_data_num;
-
-    		if(debug_fec_dec)
-    			mylog(log_debug,"[dec]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d X=%d Y=%d\n",seq,group_data_num,group_redundant_num,max_len,sum_ori,sum,x_got,y_got);
-    		else
-    			mylog(log_trace,"[dec]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d X=%d Y=%d\n",seq,group_data_num,group_redundant_num,max_len,sum_ori,sum,x_got,y_got);
-
-			if(fec_result_ok)
-			{
-
-				output_n=group_data_num;
-
-				if(decode_fast_send)
-				{
-					output_n=missed_packet_counter;
-					for(int i=0;i<missed_packet_counter;i++)
-					{
-						output_s_arr_buf[i]=output_s_arr_buf[missed_packet[i]];
-						output_len_arr_buf[i]=output_len_arr_buf[missed_packet[i]];
-					}
-				}
-
-
-				output_s_arr=output_s_arr_buf;
-				output_len_arr=output_len_arr_buf;
-				assert(ready_for_output==0);
-				ready_for_output=1;
-			}
-			else
-			{
-				//fec_not_ok:
-				ready_for_output=0;
-			}
-			anti_replay.set_invaild(seq);
-		}// end of type==1
-	}
-	else //not about_to_fec
-	{
-
-		if(decode_fast_send)
-		{
-			if(type==1&&data_num==0)
-			{
-				assert(ready_for_output==0);
-				output_n=1;
-				int check_len=read_u16(fec_data[index].buf);
-				output_s_arr_buf[0]=fec_data[index].buf+sizeof(u16_t);
-				output_len_arr_buf[0]=fec_data[index].len-sizeof(u16_t);
-
-				if(output_len_arr_buf[0]!=check_len)
-				{
-					mylog(log_warn,"len mismatch %d %d\n",output_len_arr_buf[0],check_len);
-				}
-				output_s_arr=output_s_arr_buf;
-				output_len_arr=output_len_arr_buf;
-
-				ready_for_output=1;
-			}
-		}
-	}
-
-	end:
-	index++;
-	if(index==int(fec_buff_num)) index=0;
-
-	return 0;
+int fec_decode_manager_t::input(char *s, int len) {
+    assert(s != 0);
+    assert(len + 100 < buf_len);  // guarenteed by upper level
+
+    int tmp_idx = 0;
+    int tmp_header_len = sizeof(u32_t) + sizeof(char) * 4;
+    if (len < tmp_header_len) {
+        mylog(log_warn, "len =%d\n", len);
+        return -1;
+    }
+    u32_t seq = read_u32(s + tmp_idx);
+    tmp_idx += sizeof(u32_t);
+    int type = (unsigned char)s[tmp_idx++];
+    int data_num = (unsigned char)s[tmp_idx++];
+    int redundant_num = (unsigned char)s[tmp_idx++];
+    int inner_index = (unsigned char)s[tmp_idx++];
+    len = len - tmp_idx;
+
+    // mylog(log_trace,"input\n");
+
+    if (len < 0) {
+        mylog(log_warn, "len<0\n");
+        return -1;
+    }
+
+    if (type == 1) {
+        if (len < (int)sizeof(u16_t)) {
+            mylog(log_warn, "type==1&&len<2\n");
+            return -1;
+        }
+        if (data_num == 0 && (int)(read_u16(s + tmp_idx) + sizeof(u16_t)) != len) {
+            mylog(log_warn, "inner_index<data_num&&read_u16(s+tmp_idx)+sizeof(u16_t)!=len    %d %d\n", (int)(read_u16(s + tmp_idx) + sizeof(u16_t)), len);
+            return -1;
+        }
+    }
+
+    if (type == 0 && data_num == 0) {
+        mylog(log_warn, "unexpected type==0&&data_num==0\n");
+        return -1;
+    }
+    if (data_num + redundant_num >= max_fec_packet_num) {
+        mylog(log_warn, "data_num+redundant_num>=max_fec_packet_num\n");
+        return -1;
+    }
+    if (!anti_replay.is_vaild(seq)) {
+        mylog(log_trace, "!anti_replay.is_vaild(seq) ,seq =%u\n", seq);
+        return 0;
+    }
+
+    if (mp[seq].fec_done != 0) {
+        mylog(log_debug, "fec already done, ignore, seq=%u\n", seq);
+        return -1;
+    }
+
+    if (mp[seq].group_mp.find(inner_index) != mp[seq].group_mp.end()) {
+        mylog(log_debug, "dup fec index\n");  // duplicate can happen on  a normal network, so its just log_debug
+        return -1;
+    }
+
+    if (mp[seq].type == -1)
+        mp[seq].type = type;
+    else {
+        if (mp[seq].type != type) {
+            mylog(log_warn, "type mismatch\n");
+            return -1;
+        }
+    }
+
+    if (data_num != 0) {
+        // mp[seq].data_counter++;
+
+        if (mp[seq].data_num == -1) {
+            mp[seq].data_num = data_num;
+            mp[seq].redundant_num = redundant_num;
+            mp[seq].len = len;
+        } else {
+            if (mp[seq].data_num != data_num || mp[seq].redundant_num != redundant_num || mp[seq].len != len) {
+                mylog(log_warn, "unexpected mp[seq].data_num!=data_num||mp[seq].redundant_num!=redundant_num||mp[seq].len!=len\n");
+                return -1;
+            }
+        }
+    }
+
+    // mylog(log_info,"mp.size()=%d index=%d\n",mp.size(),index);
+
+    if (fec_data[index].used != 0) {
+        u32_t tmp_seq = fec_data[index].seq;
+        anti_replay.set_invaild(tmp_seq);
+
+        auto tmp_it = mp.find(tmp_seq);
+        if (tmp_it != mp.end()) {
+            int x = tmp_it->second.data_num;
+            int y = tmp_it->second.redundant_num;
+            int cnt = tmp_it->second.group_mp.size();
+
+            if (cnt < x) {
+                if (debug_fec_dec)
+                    mylog(log_debug, "[dec][failed]seq=%08x x=%d y=%d cnt=%d\n", tmp_seq, x, y, cnt);
+                else
+                    mylog(log_trace, "[dec][failed]seq=%08x x=%d y=%d cnt=%d\n", tmp_seq, x, y, cnt);
+            }
+            mp.erase(tmp_it);
+        }
+        if (tmp_seq == seq) {
+            mylog(log_warn, "unexpected tmp_seq==seq ,seq=%d\n", seq);
+            return -1;
+        }
+    }
+
+    fec_data[index].used = 1;
+    fec_data[index].seq = seq;
+    fec_data[index].type = type;
+    fec_data[index].data_num = data_num;
+    fec_data[index].redundant_num = redundant_num;
+    fec_data[index].idx = inner_index;
+    fec_data[index].len = len;
+    assert(0 <= index && index < (int)fec_buff_num);
+    assert(len + 100 < buf_len);
+    memcpy(fec_data[index].buf, s + tmp_idx, len);
+    mp[seq].group_mp[inner_index] = index;
+    // index++ at end of function
+
+    map<int, int> &inner_mp = mp[seq].group_mp;
+
+    int about_to_fec = 0;
+    if (type == 0) {
+        // assert((int)inner_mp.size()<=data_num);
+        if ((int)inner_mp.size() > data_num) {
+            mylog(log_warn, "inner_mp.size()>data_num\n");
+            anti_replay.set_invaild(seq);
+            goto end;
+        }
+        if ((int)inner_mp.size() == data_num)
+            about_to_fec = 1;
+    } else {
+        if (mp[seq].data_num != -1) {
+            if ((int)inner_mp.size() > mp[seq].data_num + 1) {
+                mylog(log_warn, "inner_mp.size()>data_num+1\n");
+                anti_replay.set_invaild(seq);
+                goto end;
+            }
+            if ((int)inner_mp.size() >= mp[seq].data_num) {
+                about_to_fec = 1;
+            }
+        }
+    }
+
+    if (about_to_fec) {
+        int group_data_num = mp[seq].data_num;
+        int group_redundant_num = mp[seq].redundant_num;
+
+        int x_got = 0;
+        int y_got = 0;
+        // mylog(log_error,"fec here!\n");
+        if (type == 0) {
+            char *fec_tmp_arr[max_fec_packet_num + 5] = {0};
+            for (auto it = inner_mp.begin(); it != inner_mp.end(); it++) {
+                if (it->first < group_data_num)
+                    x_got++;
+                else
+                    y_got++;
+                fec_tmp_arr[it->first] = fec_data[it->second].buf;
+            }
+            assert(rs_decode2(group_data_num, group_data_num + group_redundant_num, fec_tmp_arr, len) == 0);  // the input data has been modified in-place
+            // this line should always succeed
+            mp[seq].fec_done = 1;
+
+            if (debug_fec_dec)
+                mylog(log_debug, "[dec]seq=%08x x=%d y=%d len=%d cnt=%d X=%d Y=%d\n", seq, group_data_num, group_redundant_num, len, int(inner_mp.size()), x_got, y_got);
+            else
+                mylog(log_trace, "[dec]seq=%08x x=%d y=%d len=%d cnt=%d X=%d Y=%d\n", seq, group_data_num, group_redundant_num, len, int(inner_mp.size()), x_got, y_got);
+
+            blob_decode.clear();
+            for (int i = 0; i < group_data_num; i++) {
+                blob_decode.input(fec_tmp_arr[i], len);
+            }
+            if (blob_decode.output(output_n, output_s_arr, output_len_arr) != 0) {
+                mylog(log_warn, "blob_decode failed\n");
+                // ready_for_output=0;
+                anti_replay.set_invaild(seq);
+                goto end;
+            }
+            assert(ready_for_output == 0);
+            ready_for_output = 1;
+            anti_replay.set_invaild(seq);
+        } else  // type==1
+        {
+            int max_len = -1;
+            int fec_result_ok = 1;
+            int data_check_ok = 1;
+            int debug_num = inner_mp.size();
+
+            int missed_packet[max_fec_packet_num + 5];
+            int missed_packet_counter = 0;
+
+            // outupt_s_arr_buf[max_fec_packet_num+5]={0};
+
+            // memset(output_s_arr_buf,0,sizeof(output_s_arr_buf));//in efficient
+
+            for (int i = 0; i < group_data_num + group_redundant_num; i++) {
+                output_s_arr_buf[i] = 0;
+            }
+            for (auto it = inner_mp.begin(); it != inner_mp.end(); it++) {
+                if (it->first < group_data_num)
+                    x_got++;
+                else
+                    y_got++;
+
+                output_s_arr_buf[it->first] = fec_data[it->second].buf;
+                if (fec_data[it->second].len < (int)sizeof(u16_t)) {
+                    mylog(log_warn, "fec_data[it->second].len<(int)sizeof(u16_t)");
+                    data_check_ok = 0;
+                }
+
+                if (fec_data[it->second].len > max_len)
+                    max_len = fec_data[it->second].len;
+            }
+            if (max_len != mp[seq].len) {
+                data_check_ok = 0;
+                mylog(log_warn, "max_len!=mp[seq].len");
+            }
+            if (data_check_ok == 0) {
+                // ready_for_output=0;
+                mylog(log_warn, "data_check_ok==0\n");
+                anti_replay.set_invaild(seq);
+                goto end;
+            }
+            for (auto it = inner_mp.begin(); it != inner_mp.end(); it++) {
+                int tmp_idx = it->second;
+                assert(max_len >= fec_data[tmp_idx].len);  // guarenteed by data_check_ok
+                memset(fec_data[tmp_idx].buf + fec_data[tmp_idx].len, 0, max_len - fec_data[tmp_idx].len);
+            }
+
+            for (int i = 0; i < group_data_num; i++) {
+                if (output_s_arr_buf[i] == 0 || i == inner_index)  // only missed packet +current packet
+                {
+                    missed_packet[missed_packet_counter++] = i;
+                }
+            }
+            mylog(log_trace, "fec done,%d %d,missed_packet_counter=%d\n", group_data_num, group_redundant_num, missed_packet_counter);
+
+            assert(rs_decode2(group_data_num, group_data_num + group_redundant_num, output_s_arr_buf, max_len) == 0);  // this should always succeed
+            mp[seq].fec_done = 1;
+
+            int sum_ori = 0;
+
+            for (int i = 0; i < group_data_num; i++) {
+                output_len_arr_buf[i] = read_u16(output_s_arr_buf[i]);
+                sum_ori += output_len_arr_buf[i];
+                output_s_arr_buf[i] += sizeof(u16_t);
+                if (output_len_arr_buf[i] > max_data_len) {
+                    mylog(log_warn, "invaild len %d,seq= %u,data_num= %d r_num= %d,i= %d\n", output_len_arr_buf[i], seq, group_data_num, group_redundant_num, i);
+                    fec_result_ok = 0;
+                    for (int i = 0; i < missed_packet_counter; i++) {
+                        log_bare(log_warn, "%d ", missed_packet[i]);
+                    }
+                    log_bare(log_warn, "\n");
+                    // break;
+                }
+            }
+
+            int sum = max_len * group_data_num;
+
+            if (debug_fec_dec)
+                mylog(log_debug, "[dec]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d X=%d Y=%d\n", seq, group_data_num, group_redundant_num, max_len, sum_ori, sum, x_got, y_got);
+            else
+                mylog(log_trace, "[dec]seq=%08x x=%d y=%d len=%d sum_ori=%d sum=%d X=%d Y=%d\n", seq, group_data_num, group_redundant_num, max_len, sum_ori, sum, x_got, y_got);
+
+            if (fec_result_ok) {
+                output_n = group_data_num;
+
+                if (decode_fast_send) {
+                    output_n = missed_packet_counter;
+                    for (int i = 0; i < missed_packet_counter; i++) {
+                        output_s_arr_buf[i] = output_s_arr_buf[missed_packet[i]];
+                        output_len_arr_buf[i] = output_len_arr_buf[missed_packet[i]];
+                    }
+                }
+
+                output_s_arr = output_s_arr_buf;
+                output_len_arr = output_len_arr_buf;
+                assert(ready_for_output == 0);
+                ready_for_output = 1;
+            } else {
+                // fec_not_ok:
+                ready_for_output = 0;
+            }
+            anti_replay.set_invaild(seq);
+        }   // end of type==1
+    } else  // not about_to_fec
+    {
+        if (decode_fast_send) {
+            if (type == 1 && data_num == 0) {
+                assert(ready_for_output == 0);
+                output_n = 1;
+                int check_len = read_u16(fec_data[index].buf);
+                output_s_arr_buf[0] = fec_data[index].buf + sizeof(u16_t);
+                output_len_arr_buf[0] = fec_data[index].len - sizeof(u16_t);
+
+                if (output_len_arr_buf[0] != check_len) {
+                    mylog(log_warn, "len mismatch %d %d\n", output_len_arr_buf[0], check_len);
+                }
+                output_s_arr = output_s_arr_buf;
+                output_len_arr = output_len_arr_buf;
+
+                ready_for_output = 1;
+            }
+        }
+    }
+
+end:
+    index++;
+    if (index == int(fec_buff_num)) index = 0;
+
+    return 0;
 }
-int fec_decode_manager_t::output(int &n,char ** &s_arr,int* &len_arr)
-{
-	if(!ready_for_output)
-	{
-		n=-1;
-		s_arr=0;
-		len_arr=0;
-	}
-	else
-	{
-		ready_for_output=0;
-		n=output_n;
-		s_arr=output_s_arr;
-		len_arr=output_len_arr;
-	}
-	return 0;
+int fec_decode_manager_t::output(int &n, char **&s_arr, int *&len_arr) {
+    if (!ready_for_output) {
+        n = -1;
+        s_arr = 0;
+        len_arr = 0;
+    } else {
+        ready_for_output = 0;
+        n = output_n;
+        s_arr = output_s_arr;
+        len_arr = output_len_arr;
+    }
+    return 0;
 }

+ 391 - 448
fec_manager.h

@@ -12,483 +12,426 @@
 #include "log.h"
 #include "lib/rs.h"
 
-const int max_blob_packet_num=30000;//how many packet can be contain in a blob_t ,can be set very large
-const u32_t anti_replay_buff_size=30000;//can be set very large
+const int max_blob_packet_num = 30000;      // how many packet can be contain in a blob_t ,can be set very large
+const u32_t anti_replay_buff_size = 30000;  // can be set very large
 
-const int max_fec_packet_num=255;// this is the limitation of the rs lib
+const int max_fec_packet_num = 255;  // this is the limitation of the rs lib
 extern u32_t fec_buff_num;
 
-const int rs_str_len=max_fec_packet_num*10+100;
+const int rs_str_len = max_fec_packet_num * 10 + 100;
 extern int header_overhead;
 extern int debug_fec_enc;
 extern int debug_fec_dec;
 
-struct fec_parameter_t
-{
-	int version=0;
-	int mtu=default_mtu;
-	int queue_len=200;
-	int timeout=8*1000;
-	int mode=0;
-
-	int rs_cnt=0;
-	struct rs_parameter_t //parameters for reed solomon
-	{
-		unsigned char x;//AKA fec_data_num  (x should be same as <index of rs_par>+1 at the moment)
-		unsigned char y;//fec_redundant_num
-	}rs_par[max_fec_packet_num+10];
-
-	int rs_from_str(char * s)//todo inefficient
-	{
-		vector<string> str_vec=string_to_vec(s,",");
-		if(str_vec.size()<1)
-		{
-			mylog(log_warn,"failed to parse [%s]\n",s);
-			return -1;
-		}
-		vector<rs_parameter_t> par_vec;
-		for(int i=0;i<(int)str_vec.size();i++)
-		{
-			rs_parameter_t tmp_par;
-			string &tmp_str=str_vec[i];
-			int x,y;
-			if(sscanf((char *)tmp_str.c_str(),"%d:%d",&x,&y)!=2)
-			{
-				mylog(log_warn,"failed to parse [%s]\n",tmp_str.c_str());
-				return -1;
-			}
-			if(x<1||y<0||x+y>max_fec_packet_num)
-			{
-				mylog(log_warn,"invaild value x=%d y=%d, x should >=1, y should >=0, x +y should <%d\n",x,y,max_fec_packet_num);
-				return -1;
-			}
-			tmp_par.x=x;
-			tmp_par.y=y;
-			par_vec.push_back(tmp_par);
-		}
-		assert(par_vec.size()==str_vec.size());
-
-		int found_problem=0;
-		for(int i=1;i<(int)par_vec.size();i++)
-		{
-			if(par_vec[i].x<=par_vec[i-1].x)
-			{
-				mylog(log_warn,"error in [%s], x in x:y should be in ascend order\n",s);
-				return -1;
-			}
-			int now_x=par_vec[i].x;
-			int now_y=par_vec[i].y;
-			int pre_x=par_vec[i-1].x;
-			int pre_y=par_vec[i-1].y;
-
-			double now_ratio=double(par_vec[i].y)/par_vec[i].x;
-			double pre_ratio=double(par_vec[i-1].y)/par_vec[i-1].x;
-
-			if(pre_ratio+0.0001<now_ratio)
-			{
-				if(found_problem==0)
-				{
-					mylog(log_warn,"possible problems: %d/%d<%d/%d",pre_y,pre_x,now_y,now_x);
-					found_problem=1;
-				}
-				else
-				{
-					log_bare(log_warn,", %d/%d<%d/%d",pre_y,pre_x,now_y,now_x);
-				}
-			}
-		}
-		if(found_problem)
-		{
-			log_bare(log_warn," in %s\n",s);
-		}
-
-		{ //special treatment for first parameter
-			int x=par_vec[0].x;
-			int y=par_vec[0].y;
-			for(int i=1;i<=x;i++)
-			{
-				rs_par[i-1].x=i;
-				rs_par[i-1].y=y;
-			}
-		}
-
-		for(int i=1;i<(int)par_vec.size();i++)
-		{
-			int now_x=par_vec[i].x;
-			int now_y=par_vec[i].y;
-			int pre_x=par_vec[i-1].x;
-			int pre_y=par_vec[i-1].y;
-			rs_par[now_x-1].x=now_x;
-			rs_par[now_x-1].y=now_y;
-
-			double now_ratio=double(par_vec[i].y)/par_vec[i].x;
-			double pre_ratio=double(par_vec[i-1].y)/par_vec[i-1].x;
-
-			//double k= double(now_y-pre_y)/double(now_x-pre_x);
-			for(int j=pre_x+1;j<=now_x-1;j++)
-			{
-				int in_x=j;
-
-			////////	int in_y= double(pre_y) + double(in_x-pre_x)*k+ 0.9999;// round to upper
-
-			double distance=now_x-pre_x;
-			///////	double in_ratio=pre_ratio*(1.0-(in_x-pre_x)/distance)   +   now_ratio *(1.0- (now_x-in_x)/distance);
-			//////	int in_y= in_x*in_ratio + 0.9999;
-				int in_y= pre_y +(now_y-pre_y) *(in_x-pre_x)/distance +0.9999;
-
-				if(in_x+in_y>max_fec_packet_num)
-				{
-					in_y=max_fec_packet_num-in_x;
-					assert(in_y>=0&&in_y<=max_fec_packet_num);
-				}
-
-				rs_par[in_x-1].x=in_x;
-				rs_par[in_x-1].y=in_y;
-			}
-		}
-		rs_cnt=par_vec[par_vec.size()-1].x;
-
-		return 0;
-	}
-
-	char *rs_to_str()//todo inefficient
-	{
-		static char res[rs_str_len];
-		string tmp_string;
-		char tmp_buf[100];
-		assert(rs_cnt>=1);
-		for(int i=0;i<rs_cnt;i++)
-		{
-			sprintf(tmp_buf,"%d:%d",int(rs_par[i].x),int(rs_par[i].y));
-			if(i!=0)
-				tmp_string+=",";
-			tmp_string+=tmp_buf;
-		}
-		strcpy(res,tmp_string.c_str());
-		return res;
-	}
-
-	rs_parameter_t get_tail()
-	{
-		assert(rs_cnt>=1);
-		return rs_par[rs_cnt-1];
-	}
-
-
-	int clone(fec_parameter_t & other)
-	{
-		version=other.version;
-		mtu=other.mtu;
-		queue_len=other.queue_len;
-		timeout=other.timeout;
-		mode=other.mode;
-
-		assert(other.rs_cnt>=1);
-		rs_cnt=other.rs_cnt;
-		memcpy(rs_par,other.rs_par,sizeof(rs_parameter_t)*rs_cnt);
-
-		return 0;
-	}
-
-	int copy_fec(fec_parameter_t & other)
-	{
-		assert(other.rs_cnt>=1);
-		rs_cnt=other.rs_cnt;
-		memcpy(rs_par,other.rs_par,sizeof(rs_parameter_t)*rs_cnt);
-
-		return 0;
-	}
+struct fec_parameter_t {
+    int version = 0;
+    int mtu = default_mtu;
+    int queue_len = 200;
+    int timeout = 8 * 1000;
+    int mode = 0;
+
+    int rs_cnt = 0;
+    struct rs_parameter_t  // parameters for reed solomon
+    {
+        unsigned char x;  // AKA fec_data_num  (x should be same as <index of rs_par>+1 at the moment)
+        unsigned char y;  // fec_redundant_num
+    } rs_par[max_fec_packet_num + 10];
+
+    int rs_from_str(char *s)  // todo inefficient
+    {
+        vector<string> str_vec = string_to_vec(s, ",");
+        if (str_vec.size() < 1) {
+            mylog(log_warn, "failed to parse [%s]\n", s);
+            return -1;
+        }
+        vector<rs_parameter_t> par_vec;
+        for (int i = 0; i < (int)str_vec.size(); i++) {
+            rs_parameter_t tmp_par;
+            string &tmp_str = str_vec[i];
+            int x, y;
+            if (sscanf((char *)tmp_str.c_str(), "%d:%d", &x, &y) != 2) {
+                mylog(log_warn, "failed to parse [%s]\n", tmp_str.c_str());
+                return -1;
+            }
+            if (x < 1 || y < 0 || x + y > max_fec_packet_num) {
+                mylog(log_warn, "invaild value x=%d y=%d, x should >=1, y should >=0, x +y should <%d\n", x, y, max_fec_packet_num);
+                return -1;
+            }
+            tmp_par.x = x;
+            tmp_par.y = y;
+            par_vec.push_back(tmp_par);
+        }
+        assert(par_vec.size() == str_vec.size());
+
+        int found_problem = 0;
+        for (int i = 1; i < (int)par_vec.size(); i++) {
+            if (par_vec[i].x <= par_vec[i - 1].x) {
+                mylog(log_warn, "error in [%s], x in x:y should be in ascend order\n", s);
+                return -1;
+            }
+            int now_x = par_vec[i].x;
+            int now_y = par_vec[i].y;
+            int pre_x = par_vec[i - 1].x;
+            int pre_y = par_vec[i - 1].y;
+
+            double now_ratio = double(par_vec[i].y) / par_vec[i].x;
+            double pre_ratio = double(par_vec[i - 1].y) / par_vec[i - 1].x;
+
+            if (pre_ratio + 0.0001 < now_ratio) {
+                if (found_problem == 0) {
+                    mylog(log_warn, "possible problems: %d/%d<%d/%d", pre_y, pre_x, now_y, now_x);
+                    found_problem = 1;
+                } else {
+                    log_bare(log_warn, ", %d/%d<%d/%d", pre_y, pre_x, now_y, now_x);
+                }
+            }
+        }
+        if (found_problem) {
+            log_bare(log_warn, " in %s\n", s);
+        }
+
+        {  // special treatment for first parameter
+            int x = par_vec[0].x;
+            int y = par_vec[0].y;
+            for (int i = 1; i <= x; i++) {
+                rs_par[i - 1].x = i;
+                rs_par[i - 1].y = y;
+            }
+        }
+
+        for (int i = 1; i < (int)par_vec.size(); i++) {
+            int now_x = par_vec[i].x;
+            int now_y = par_vec[i].y;
+            int pre_x = par_vec[i - 1].x;
+            int pre_y = par_vec[i - 1].y;
+            rs_par[now_x - 1].x = now_x;
+            rs_par[now_x - 1].y = now_y;
+
+            double now_ratio = double(par_vec[i].y) / par_vec[i].x;
+            double pre_ratio = double(par_vec[i - 1].y) / par_vec[i - 1].x;
+
+            // double k= double(now_y-pre_y)/double(now_x-pre_x);
+            for (int j = pre_x + 1; j <= now_x - 1; j++) {
+                int in_x = j;
+
+                ////////	int in_y= double(pre_y) + double(in_x-pre_x)*k+ 0.9999;// round to upper
+
+                double distance = now_x - pre_x;
+                ///////	double in_ratio=pre_ratio*(1.0-(in_x-pre_x)/distance)   +   now_ratio *(1.0- (now_x-in_x)/distance);
+                //////	int in_y= in_x*in_ratio + 0.9999;
+                int in_y = pre_y + (now_y - pre_y) * (in_x - pre_x) / distance + 0.9999;
+
+                if (in_x + in_y > max_fec_packet_num) {
+                    in_y = max_fec_packet_num - in_x;
+                    assert(in_y >= 0 && in_y <= max_fec_packet_num);
+                }
+
+                rs_par[in_x - 1].x = in_x;
+                rs_par[in_x - 1].y = in_y;
+            }
+        }
+        rs_cnt = par_vec[par_vec.size() - 1].x;
+
+        return 0;
+    }
+
+    char *rs_to_str()  // todo inefficient
+    {
+        static char res[rs_str_len];
+        string tmp_string;
+        char tmp_buf[100];
+        assert(rs_cnt >= 1);
+        for (int i = 0; i < rs_cnt; i++) {
+            sprintf(tmp_buf, "%d:%d", int(rs_par[i].x), int(rs_par[i].y));
+            if (i != 0)
+                tmp_string += ",";
+            tmp_string += tmp_buf;
+        }
+        strcpy(res, tmp_string.c_str());
+        return res;
+    }
+
+    rs_parameter_t get_tail() {
+        assert(rs_cnt >= 1);
+        return rs_par[rs_cnt - 1];
+    }
+
+    int clone(fec_parameter_t &other) {
+        version = other.version;
+        mtu = other.mtu;
+        queue_len = other.queue_len;
+        timeout = other.timeout;
+        mode = other.mode;
+
+        assert(other.rs_cnt >= 1);
+        rs_cnt = other.rs_cnt;
+        memcpy(rs_par, other.rs_par, sizeof(rs_parameter_t) * rs_cnt);
+
+        return 0;
+    }
+
+    int copy_fec(fec_parameter_t &other) {
+        assert(other.rs_cnt >= 1);
+        rs_cnt = other.rs_cnt;
+        memcpy(rs_par, other.rs_par, sizeof(rs_parameter_t) * rs_cnt);
+
+        return 0;
+    }
 };
 
 extern fec_parameter_t g_fec_par;
-//extern int dynamic_update_fec;
-
-const int anti_replay_timeout=120*1000;// 120s
-
-struct anti_replay_t
-{
-
-	struct info_t
-	{
-		my_time_t my_time;
-		int index;
-	};
-
-	u64_t replay_buffer[anti_replay_buff_size];
-	unordered_map<u32_t,info_t> mp;
-	int index;
-	anti_replay_t()
-	{
-		clear();
-	}
-	int clear()
-	{
-		memset(replay_buffer,-1,sizeof(replay_buffer));
-		mp.clear();
-		mp.rehash(anti_replay_buff_size*3);
-		index=0;
-		return 0;
-	}
-	void set_invaild(u32_t seq)
-	{
-
-		if(is_vaild(seq)==0)
-		{
-			mylog(log_trace,"seq %u exist\n",seq);
-			//assert(mp.find(seq)!=mp.end());
-			//mp[seq].my_time=get_current_time_rough();
-			return;
-		}
-		if(replay_buffer[index]!=u64_t(i64_t(-1)))
-		{
-			assert(mp.find(replay_buffer[index])!=mp.end());
-			mp.erase(replay_buffer[index]);
-		}
-		replay_buffer[index]=seq;
-		assert(mp.find(seq)==mp.end());
-		mp[seq].my_time=get_current_time();
-		mp[seq].index=index;
-		index++;
-		if(index==int(anti_replay_buff_size)) index=0;
-	}
-	int is_vaild(u32_t seq)
-	{
-		if(mp.find(seq)==mp.end()) return 1;
-		
-		if(get_current_time()-mp[seq].my_time>anti_replay_timeout)
-		{
-			replay_buffer[mp[seq].index]=u64_t(i64_t(-1));
-			mp.erase(seq);
-			return 1;
-		}
-
-		return 0;
-	}
+// extern int dynamic_update_fec;
+
+const int anti_replay_timeout = 120 * 1000;  // 120s
+
+struct anti_replay_t {
+    struct info_t {
+        my_time_t my_time;
+        int index;
+    };
+
+    u64_t replay_buffer[anti_replay_buff_size];
+    unordered_map<u32_t, info_t> mp;
+    int index;
+    anti_replay_t() {
+        clear();
+    }
+    int clear() {
+        memset(replay_buffer, -1, sizeof(replay_buffer));
+        mp.clear();
+        mp.rehash(anti_replay_buff_size * 3);
+        index = 0;
+        return 0;
+    }
+    void set_invaild(u32_t seq) {
+        if (is_vaild(seq) == 0) {
+            mylog(log_trace, "seq %u exist\n", seq);
+            // assert(mp.find(seq)!=mp.end());
+            // mp[seq].my_time=get_current_time_rough();
+            return;
+        }
+        if (replay_buffer[index] != u64_t(i64_t(-1))) {
+            assert(mp.find(replay_buffer[index]) != mp.end());
+            mp.erase(replay_buffer[index]);
+        }
+        replay_buffer[index] = seq;
+        assert(mp.find(seq) == mp.end());
+        mp[seq].my_time = get_current_time();
+        mp[seq].index = index;
+        index++;
+        if (index == int(anti_replay_buff_size)) index = 0;
+    }
+    int is_vaild(u32_t seq) {
+        if (mp.find(seq) == mp.end()) return 1;
+
+        if (get_current_time() - mp[seq].my_time > anti_replay_timeout) {
+            replay_buffer[mp[seq].index] = u64_t(i64_t(-1));
+            mp.erase(seq);
+            return 1;
+        }
+
+        return 0;
+    }
 };
 
-struct blob_encode_t
-{
-	char input_buf[(max_fec_packet_num+5)*buf_len];
-	int current_len;
-	int counter;
+struct blob_encode_t {
+    char input_buf[(max_fec_packet_num + 5) * buf_len];
+    int current_len;
+    int counter;
 
-	char *output_buf[max_fec_packet_num+100];
+    char *output_buf[max_fec_packet_num + 100];
 
-	blob_encode_t();
+    blob_encode_t();
 
     int clear();
 
     int get_num();
     int get_shard_len(int n);
-    int get_shard_len(int n,int next_packet_len);
+    int get_shard_len(int n, int next_packet_len);
 
-	int input(char *s,int len);  //len=use len=0 for second and following packet
-	int output(int n,char ** &s_arr,int & len);
+    int input(char *s, int len);  // len=use len=0 for second and following packet
+    int output(int n, char **&s_arr, int &len);
 };
 
-struct blob_decode_t
-{
-	char input_buf[(max_fec_packet_num+5)*buf_len];
-	int current_len;
-	int last_len;
-	int counter;
+struct blob_decode_t {
+    char input_buf[(max_fec_packet_num + 5) * buf_len];
+    int current_len;
+    int last_len;
+    int counter;
 
-	char *output_buf[max_blob_packet_num+100];
-	int output_len[max_blob_packet_num+100];
+    char *output_buf[max_blob_packet_num + 100];
+    int output_len[max_blob_packet_num + 100];
 
-	blob_decode_t();
-	int clear();
-	int input(char *input,int len);
-	int output(int &n,char ** &output,int *&len_arr);
+    blob_decode_t();
+    int clear();
+    int input(char *input, int len);
+    int output(int &n, char **&output, int *&len_arr);
 };
 
-class fec_encode_manager_t:not_copy_able_t
-{
-
-private:
-	u32_t seq;
-
-	//int fec_mode;
-	//int fec_data_num,fec_redundant_num;
-	//int fec_mtu;
-	//int fec_queue_len;
-	//int fec_timeout;
-	fec_parameter_t fec_par;
-
-
-	my_time_t first_packet_time;
-	my_time_t first_packet_time_for_output;
-
-
-	blob_encode_t blob_encode;
-	char input_buf[max_fec_packet_num+5][buf_len];
-	int input_len[max_fec_packet_num+100];
-
-	char *output_buf[max_fec_packet_num+100];
-	int output_len[max_fec_packet_num+100];
-
-	int counter;
-	//int timer_fd;
-	//u64_t timer_fd64;
-
-	int ready_for_output;
-	u32_t output_n;
-
-	int append(char *s,int len);
-
-	ev_timer timer;
-	struct ev_loop *loop=0;
-	void (*cb) (struct ev_loop *loop, struct ev_timer *watcher, int revents)=0;
-
-public:
-	fec_encode_manager_t();
-	~fec_encode_manager_t();
-
-	fec_parameter_t & get_fec_par()
-	{
-		return fec_par;
-	}
-	void set_data(void * data)
-	{
-		timer.data=data;
-	}
-
-
-	void set_loop_and_cb(struct ev_loop *loop,void (*cb) (struct ev_loop *loop, struct ev_timer *watcher, int revents))
-	{
-		this->loop=loop;
-		this->cb=cb;
-		ev_init(&timer,cb);
-	}
-
-	int clear_data()
-	{
-		counter=0;
-		blob_encode.clear();
-		ready_for_output=0;
-
-		seq=(u32_t)get_fake_random_number(); //TODO temp solution for a bug.
-
-		if(loop)
-		{
-			ev_timer_stop(loop,&timer);
-		}
-		return 0;
-	}
-	int clear_all()
-	{
-
-		//itimerspec zero_its;
-		//memset(&zero_its, 0, sizeof(zero_its));
-		//timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &zero_its, 0);
-
-		if(loop)
-		{
-			ev_timer_stop(loop,&timer);
-			loop=0;
-			cb=0;
-		}
-
-		clear_data();
-
-		return 0;
-	}
-
-	my_time_t get_first_packet_time()
-	{
-		return first_packet_time_for_output;
-	}
-
-	int get_pending_time()
-	{
-		return fec_par.timeout;
-	}
-
-	int get_type()
-	{
-		return fec_par.mode;
-	}
-	//u64_t get_timer_fd64();
-	int reset_fec_parameter(int data_num,int redundant_num,int mtu,int pending_num,int pending_time,int type);
-	int input(char *s,int len/*,int &is_first_packet*/);
-	int output(int &n,char ** &s_arr,int *&len);
+class fec_encode_manager_t : not_copy_able_t {
+   private:
+    u32_t seq;
+
+    // int fec_mode;
+    // int fec_data_num,fec_redundant_num;
+    // int fec_mtu;
+    // int fec_queue_len;
+    // int fec_timeout;
+    fec_parameter_t fec_par;
+
+    my_time_t first_packet_time;
+    my_time_t first_packet_time_for_output;
+
+    blob_encode_t blob_encode;
+    char input_buf[max_fec_packet_num + 5][buf_len];
+    int input_len[max_fec_packet_num + 100];
+
+    char *output_buf[max_fec_packet_num + 100];
+    int output_len[max_fec_packet_num + 100];
+
+    int counter;
+    // int timer_fd;
+    // u64_t timer_fd64;
+
+    int ready_for_output;
+    u32_t output_n;
+
+    int append(char *s, int len);
+
+    ev_timer timer;
+    struct ev_loop *loop = 0;
+    void (*cb)(struct ev_loop *loop, struct ev_timer *watcher, int revents) = 0;
+
+   public:
+    fec_encode_manager_t();
+    ~fec_encode_manager_t();
+
+    fec_parameter_t &get_fec_par() {
+        return fec_par;
+    }
+    void set_data(void *data) {
+        timer.data = data;
+    }
+
+    void set_loop_and_cb(struct ev_loop *loop, void (*cb)(struct ev_loop *loop, struct ev_timer *watcher, int revents)) {
+        this->loop = loop;
+        this->cb = cb;
+        ev_init(&timer, cb);
+    }
+
+    int clear_data() {
+        counter = 0;
+        blob_encode.clear();
+        ready_for_output = 0;
+
+        seq = (u32_t)get_fake_random_number();  // TODO temp solution for a bug.
+
+        if (loop) {
+            ev_timer_stop(loop, &timer);
+        }
+        return 0;
+    }
+    int clear_all() {
+        // itimerspec zero_its;
+        // memset(&zero_its, 0, sizeof(zero_its));
+        // timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &zero_its, 0);
+
+        if (loop) {
+            ev_timer_stop(loop, &timer);
+            loop = 0;
+            cb = 0;
+        }
+
+        clear_data();
+
+        return 0;
+    }
+
+    my_time_t get_first_packet_time() {
+        return first_packet_time_for_output;
+    }
+
+    int get_pending_time() {
+        return fec_par.timeout;
+    }
+
+    int get_type() {
+        return fec_par.mode;
+    }
+    // u64_t get_timer_fd64();
+    int reset_fec_parameter(int data_num, int redundant_num, int mtu, int pending_num, int pending_time, int type);
+    int input(char *s, int len /*,int &is_first_packet*/);
+    int output(int &n, char **&s_arr, int *&len);
 };
-struct fec_data_t
-{
-	int used;
-	u32_t seq;
-	int type;
-	int data_num;
-	int redundant_num;
-	int idx;
-	char buf[buf_len];
-	int len;
+struct fec_data_t {
+    int used;
+    u32_t seq;
+    int type;
+    int data_num;
+    int redundant_num;
+    int idx;
+    char buf[buf_len];
+    int len;
 };
-struct fec_group_t
-{
-	int type=-1;
-	int data_num=-1;
-	int redundant_num=-1;
-	int len=-1;
-	int fec_done=0;
-	//int data_counter=0;
-	map<int,int>  group_mp;
+struct fec_group_t {
+    int type = -1;
+    int data_num = -1;
+    int redundant_num = -1;
+    int len = -1;
+    int fec_done = 0;
+    // int data_counter=0;
+    map<int, int> group_mp;
 };
-class fec_decode_manager_t:not_copy_able_t
-{
-	anti_replay_t anti_replay;
-	fec_data_t *fec_data=0;
-	unordered_map<u32_t, fec_group_t> mp;
-	blob_decode_t blob_decode;
-
-	int index;
-
-	int output_n;
-	char ** output_s_arr;
-	int * output_len_arr;
-	int ready_for_output;
-
-	char *output_s_arr_buf[max_fec_packet_num+100];//only for type=1,for type=0 the buf inside blot_t is used
-	int output_len_arr_buf[max_fec_packet_num+100];//same
-
-public:
-	fec_decode_manager_t()
-	{
-		fec_data=new fec_data_t[fec_buff_num+5];
-		assert(fec_data!=0);
-		clear();
-	}
-	/*
-	fec_decode_manager_t(const fec_decode_manager_t &b)
-	{
-		assert(0==1);//not allowed to copy
-	}*/
-	~fec_decode_manager_t()
-	{
-		mylog(log_debug,"fec_decode_manager destroyed\n");
-		if(fec_data!=0)
-		{
-			mylog(log_debug,"fec_data freed\n");
-			delete fec_data;
-		}
-	}
-	int clear()
-	{
-		anti_replay.clear();
-		mp.clear();
-		mp.rehash(fec_buff_num*3);
-
-		for(int i=0;i<(int)fec_buff_num;i++)
-			fec_data[i].used=0;
-		ready_for_output=0;
-		index=0;
-
-		return 0;
-	}
-
-	//int re_init();
-	int input(char *s,int len);
-	int output(int &n,char ** &s_arr,int* &len_arr);
+class fec_decode_manager_t : not_copy_able_t {
+    anti_replay_t anti_replay;
+    fec_data_t *fec_data = 0;
+    unordered_map<u32_t, fec_group_t> mp;
+    blob_decode_t blob_decode;
+
+    int index;
+
+    int output_n;
+    char **output_s_arr;
+    int *output_len_arr;
+    int ready_for_output;
+
+    char *output_s_arr_buf[max_fec_packet_num + 100];  // only for type=1,for type=0 the buf inside blot_t is used
+    int output_len_arr_buf[max_fec_packet_num + 100];  // same
+
+   public:
+    fec_decode_manager_t() {
+        fec_data = new fec_data_t[fec_buff_num + 5];
+        assert(fec_data != 0);
+        clear();
+    }
+    /*
+    fec_decode_manager_t(const fec_decode_manager_t &b)
+    {
+            assert(0==1);//not allowed to copy
+    }*/
+    ~fec_decode_manager_t() {
+        mylog(log_debug, "fec_decode_manager destroyed\n");
+        if (fec_data != 0) {
+            mylog(log_debug, "fec_data freed\n");
+            delete fec_data;
+        }
+    }
+    int clear() {
+        anti_replay.clear();
+        mp.clear();
+        mp.rehash(fec_buff_num * 3);
+
+        for (int i = 0; i < (int)fec_buff_num; i++)
+            fec_data[i].used = 0;
+        ready_for_output = 0;
+        index = 0;
+
+        return 0;
+    }
+
+    // int re_init();
+    int input(char *s, int len);
+    int output(int &n, char **&s_arr, int *&len_arr);
 };
 
 #endif /* FEC_MANAGER_H_ */

+ 45 - 57
lib/rs.cpp

@@ -8,69 +8,57 @@
 #include "stdlib.h"
 #include "string.h"
 
-void rs_encode(void *code,char *data[],int size)
-{
-	int k=get_k(code);
-	int n=get_n(code);
-	for(int i=k;i<n;i++)
-	{
-		fec_encode(code, (void **)data, data[i],i, size);
-	}
+void rs_encode(void *code, char *data[], int size) {
+    int k = get_k(code);
+    int n = get_n(code);
+    for (int i = k; i < n; i++) {
+        fec_encode(code, (void **)data, data[i], i, size);
+    }
 
-	return ;
+    return;
 }
 
-int rs_decode(void *code,char *data[],int size)
-{
-	int k=get_k(code);
-	int n=get_n(code);
-	int index[n];
-	int count=0;
-	for(int i=0;i<n;i++)
-	{
-		if(data[i]!=0)
-		{
-			index[count++]=i;
-		}
-	}
-	if(count<k)
-		return -1;
-	for(int i=0;i<n;i++)
-	{
-		if(i<count)
-			data[i]=data[index[i]];
-		else
-			data[i]=0;
-	}
-	return fec_decode(code,(void**)data,index,size);
+int rs_decode(void *code, char *data[], int size) {
+    int k = get_k(code);
+    int n = get_n(code);
+    int index[n];
+    int count = 0;
+    for (int i = 0; i < n; i++) {
+        if (data[i] != 0) {
+            index[count++] = i;
+        }
+    }
+    if (count < k)
+        return -1;
+    for (int i = 0; i < n; i++) {
+        if (i < count)
+            data[i] = data[index[i]];
+        else
+            data[i] = 0;
+    }
+    return fec_decode(code, (void **)data, index, size);
 }
 
-static void * (*table)[256]=0;
-void* get_code(int k,int n)
-{
-	if (table==0)
-	{
-		table=(void* (*)[256]) malloc(sizeof(void*)*256*256);
-		if(!table)
-		{
-		    return table;
-		}
-		memset(table,0,sizeof(void*)*256*256);
-	}
-	if(table[k][n]==0)
-	{
-		table[k][n]=fec_new(k,n);
-	}
-	return table[k][n];
+static void *(*table)[256] = 0;
+void *get_code(int k, int n) {
+    if (table == 0) {
+        table = (void *(*)[256])malloc(sizeof(void *) * 256 * 256);
+        if (!table) {
+            return table;
+        }
+        memset(table, 0, sizeof(void *) * 256 * 256);
+    }
+    if (table[k][n] == 0) {
+        table[k][n] = fec_new(k, n);
+    }
+    return table[k][n];
 }
-void rs_encode2(int k,int n,char *data[],int size)
-{
-	void* code=get_code(k,n);
-	rs_encode(code,data,size);
+void rs_encode2(int k, int n, char *data[], int size) {
+    void *code = get_code(k, n);
+    rs_encode(code, data, size);
 }
 
-int rs_decode2(int k,int n,char *data[],int size)
-{
-	void* code=get_code(k,n);
-	return rs_decode(code,data,size);
+int rs_decode2(int k, int n, char *data[], int size) {
+    void *code = get_code(k, n);
+    return rs_decode(code, data, size);
 }

+ 4 - 10
lib/rs.h

@@ -20,8 +20,7 @@
 //
 // info:
 // the function will always succeed,except malloc fail.if malloc fail,it will call exit()
-void rs_encode(void *code,char *data[],int size); 
-
+void rs_encode(void *code, char *data[], int size);
 
 // input:
 // data[0.....n-1] points to original data and redundate data,in right order
@@ -37,15 +36,10 @@ void rs_encode(void *code,char *data[],int size);
 // advanced info:
 // 1. rs_decode wont malloc memory for those zero pointers in data[0.....k-1]. instead it will re-use the memory of other non-zero pointers (and let data[0.....k-1] point to those memory).
 // 2. if the input data[0.....n-1] contains x non-zero pointers,after called rs_decode,there will still be exactly x non-zero poninters in data[0.....n-1],just the order may change.
-int rs_decode(void *code,char *data[],int size);
-
-
-void rs_encode2(int k,int n,char *data[],int size);
-
-int rs_decode2(int k,int n,char *data[],int size);
-
-
+int rs_decode(void *code, char *data[], int size);
 
+void rs_encode2(int k, int n, char *data[], int size);
 
+int rs_decode2(int k, int n, char *data[], int size);
 
 #endif /* LIB_RS_H_ */

+ 41 - 47
log.cpp

@@ -1,63 +1,57 @@
 #include <common.h>
 #include <log.h>
 
-int log_level=log_info;
+int log_level = log_info;
 
-int enable_log_position=0;
-int enable_log_color=1;
+int enable_log_position = 0;
+int enable_log_color = 1;
 
+void log0(const char* file, const char* function, int line, int level, const char* str, ...) {
+    if (level > log_level) return;
+    if (level > log_trace || level < 0) return;
 
-void log0(const char * file,const char * function,int line,int level,const char* str, ...) {
+    time_t timer;
+    char buffer[100];
+    struct tm* tm_info;
 
-	if(level>log_level) return ;
-	if(level>log_trace||level<0) return ;
+    time(&timer);
+    tm_info = localtime(&timer);
 
+    if (enable_log_color)
+        printf("%s", log_color[level]);
 
-	time_t timer;
-	char buffer[100];
-	struct tm* tm_info;
+    strftime(buffer, 100, "%Y-%m-%d %H:%M:%S", tm_info);
+    printf("[%s][%s]", buffer, log_text[level]);
 
-	time(&timer);
-	tm_info = localtime(&timer);
+    if (enable_log_position) printf("[%s,func:%s,line:%d]", file, function, line);
 
-	if(enable_log_color)
-		printf("%s",log_color[level]);
+    va_list vlist;
+    va_start(vlist, str);
+    vfprintf(stdout, str, vlist);
+    va_end(vlist);
+    if (enable_log_color)
+        printf("%s", RESET);
 
-	strftime(buffer, 100, "%Y-%m-%d %H:%M:%S", tm_info);
-	printf("[%s][%s]",buffer,log_text[level]);
+    // printf("\n");
+    // if(enable_log_color)
+    // printf(log_color[level]);
+    fflush(stdout);
 
-	if(enable_log_position)printf("[%s,func:%s,line:%d]",file,function,line);
-
-	va_list vlist;
-	va_start(vlist, str);
-	vfprintf(stdout, str, vlist);
-	va_end(vlist);
-	if(enable_log_color)
-		printf("%s",RESET);
-
-	//printf("\n");
-	//if(enable_log_color)
-		//printf(log_color[level]);
-	fflush(stdout);
-
-	if(log_level==log_fatal)
-	{
-		about_to_exit=1;
-	}
+    if (log_level == log_fatal) {
+        about_to_exit = 1;
+    }
 }
 
-void log_bare(int level,const char* str, ...)
-{
-	if(level>log_level) return ;
-	if(level>log_trace||level<0) return ;
-	if(enable_log_color)
-		printf("%s",log_color[level]);
-	va_list vlist;
-	va_start(vlist, str);
-	vfprintf(stdout, str, vlist);
-	va_end(vlist);
-	if(enable_log_color)
-		printf("%s",RESET);
-	fflush(stdout);
-
+void log_bare(int level, const char* str, ...) {
+    if (level > log_level) return;
+    if (level > log_trace || level < 0) return;
+    if (enable_log_color)
+        printf("%s", log_color[level]);
+    va_list vlist;
+    va_start(vlist, str);
+    vfprintf(stdout, str, vlist);
+    va_end(vlist);
+    if (enable_log_color)
+        printf("%s", RESET);
+    fflush(stdout);
 }

+ 26 - 32
log.h

@@ -2,60 +2,54 @@
 #ifndef _LOG_MYLOG_H_
 #define _LOG_MYLOG_H_
 
-
-#include<stdio.h>
-#include<string.h>
-#include<stdlib.h>
-#include<getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
 #include <unistd.h>
-#include<errno.h>
+#include <errno.h>
 #include <time.h>
 
 #include <set>
 
 using namespace std;
 
-
-#define RED   "\x1B[31m"
-#define GRN   "\x1B[32m"
-#define YEL   "\x1B[33m"
-#define BLU   "\x1B[34m"
-#define MAG   "\x1B[35m"
-#define CYN   "\x1B[36m"
-#define WHT   "\x1B[37m"
+#define RED "\x1B[31m"
+#define GRN "\x1B[32m"
+#define YEL "\x1B[33m"
+#define BLU "\x1B[34m"
+#define MAG "\x1B[35m"
+#define CYN "\x1B[36m"
+#define WHT "\x1B[37m"
 #define RESET "\x1B[0m"
 
+const int log_never = 0;
+const int log_fatal = 1;
+const int log_error = 2;
+const int log_warn = 3;
+const int log_info = 4;
+const int log_debug = 5;
+const int log_trace = 6;
+const int log_end = 7;
 
-const int log_never=0;
-const int log_fatal=1;
-const int log_error=2;
-const int log_warn=3;
-const int log_info=4;
-const int log_debug=5;
-const int log_trace=6;
-const int log_end=7;
-
-const char log_text[][20]={"NEVER","FATAL","ERROR","WARN","INFO","DEBUG","TRACE",""};
-const char log_color[][20]={RED,RED,RED,YEL,GRN,MAG,""};
+const char log_text[][20] = {"NEVER", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", ""};
+const char log_color[][20] = {RED, RED, RED, YEL, GRN, MAG, ""};
 
 extern int log_level;
 extern int enable_log_position;
 extern int enable_log_color;
 
-
 #ifdef MY_DEBUG
-#define mylog(__first_argu__dummy_abcde__,...) printf(__VA_ARGS__)
+#define mylog(__first_argu__dummy_abcde__, ...) printf(__VA_ARGS__)
 
 #else
-#define mylog(...) log0(__FILE__,__FUNCTION__,__LINE__,__VA_ARGS__)
+#define mylog(...) log0(__FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
 #endif
 
-
 //#define mylog(__first_argu__dummy_abcde__,...) {;}
 
-void log0(const char * file,const char * function,int line,int level,const char* str, ...);
-
-void log_bare(int level,const char* str, ...);
+void log0(const char* file, const char* function, int line, int level, const char* str, ...);
 
+void log_bare(int level, const char* str, ...);
 
 #endif

+ 107 - 124
main.cpp

@@ -13,106 +13,97 @@
 #include "git_version.h"
 using namespace std;
 
-
-static void print_help()
-{
-	char git_version_buf[100]={0};
-	strncpy(git_version_buf,gitversion,10);
-
-	printf("UDPspeeder V2\n");
-	printf("git version: %s    ",git_version_buf);
-	printf("build date: %s %s\n",__DATE__,__TIME__);
-	printf("repository: https://github.com/wangyu-/UDPspeeder\n");
-	printf("\n");
-	printf("usage:\n");
-	printf("    run as client: ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port  [options]\n");
-	printf("    run as server: ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port  [options]\n");
-	printf("\n");
-	printf("common options, must be same on both sides:\n");
-	printf("    -k,--key              <string>        key for simple xor encryption. if not set, xor is disabled\n");
-
-	printf("main options:\n");
-	printf("    -f,--fec              x:y             forward error correction, send y redundant packets for every x packets\n");
-	printf("    --timeout             <number>        how long could a packet be held in queue before doing fec, unit: ms, default: 8ms\n");
-	printf("    --report              <number>        turn on send/recv report, and set a period for reporting, unit: s\n");
-
-	printf("advanced options:\n");
-	printf("    --mode                <number>        fec-mode,available values: 0,1; mode 0(default) costs less bandwidth,no mtu problem.\n");
-	printf("                                          mode 1 usually introduces less latency, but you have to care about mtu.\n");
-	printf("    --mtu                 <number>        mtu. for mode 0, the program will split packet to segment smaller than mtu value.\n");
-	printf("                                          for mode 1, no packet will be split, the program just check if the mtu is exceed.\n");
-	printf("                                          default value: 1250. you typically shouldnt change this value.\n");
-	printf("    -j,--jitter           <number>        simulated jitter. randomly delay first packet for 0~<number> ms, default value: 0.\n");
-	printf("                                          do not use if you dont know what it means.\n");
-	printf("    -i,--interval         <number>        scatter each fec group to a interval of <number> ms, to defend burst packet loss.\n");
-	printf("                                          default value: 0. do not use if you dont know what it means.\n");
-	printf("    -f,--fec              x1:y1,x2:y2,..  similiar to -f/--fec above,fine-grained fec parameters,may help save bandwidth.\n");
-	printf("                                          example: \"-f 1:3,2:4,10:6,20:10\". check repo for details\n");
-	printf("    --random-drop         <number>        simulate packet loss, unit: 0.01%%. default value: 0.\n");
-	printf("    --disable-obscure     <number>        disable obscure, to save a bit bandwidth and cpu\n");
-	printf("    --disable-checksum    <number>        disable checksum to save a bit bandwdith and cpu\n");
-	//printf("    --disable-xor         <number>        disable xor\n");
-
-	printf("developer options:\n");
-	printf("    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program, so that you\n");
-	printf("                                          can change fec encode parameters dynamically, check readme.md in repository for\n");
-	printf("                                          supported commands.\n");
-	printf("    -j ,--jitter          jmin:jmax       similiar to -j above, but create jitter randomly between jmin and jmax\n");
-	printf("    -i,--interval         imin:imax       similiar to -i above, but scatter randomly between imin and imax\n");
+static void print_help() {
+    char git_version_buf[100] = {0};
+    strncpy(git_version_buf, gitversion, 10);
+
+    printf("UDPspeeder V2\n");
+    printf("git version: %s    ", git_version_buf);
+    printf("build date: %s %s\n", __DATE__, __TIME__);
+    printf("repository: https://github.com/wangyu-/UDPspeeder\n");
+    printf("\n");
+    printf("usage:\n");
+    printf("    run as client: ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port  [options]\n");
+    printf("    run as server: ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port  [options]\n");
+    printf("\n");
+    printf("common options, must be same on both sides:\n");
+    printf("    -k,--key              <string>        key for simple xor encryption. if not set, xor is disabled\n");
+
+    printf("main options:\n");
+    printf("    -f,--fec              x:y             forward error correction, send y redundant packets for every x packets\n");
+    printf("    --timeout             <number>        how long could a packet be held in queue before doing fec, unit: ms, default: 8ms\n");
+    printf("    --report              <number>        turn on send/recv report, and set a period for reporting, unit: s\n");
+
+    printf("advanced options:\n");
+    printf("    --mode                <number>        fec-mode,available values: 0,1; mode 0(default) costs less bandwidth,no mtu problem.\n");
+    printf("                                          mode 1 usually introduces less latency, but you have to care about mtu.\n");
+    printf("    --mtu                 <number>        mtu. for mode 0, the program will split packet to segment smaller than mtu value.\n");
+    printf("                                          for mode 1, no packet will be split, the program just check if the mtu is exceed.\n");
+    printf("                                          default value: 1250. you typically shouldnt change this value.\n");
+    printf("    -j,--jitter           <number>        simulated jitter. randomly delay first packet for 0~<number> ms, default value: 0.\n");
+    printf("                                          do not use if you dont know what it means.\n");
+    printf("    -i,--interval         <number>        scatter each fec group to a interval of <number> ms, to defend burst packet loss.\n");
+    printf("                                          default value: 0. do not use if you dont know what it means.\n");
+    printf("    -f,--fec              x1:y1,x2:y2,..  similiar to -f/--fec above,fine-grained fec parameters,may help save bandwidth.\n");
+    printf("                                          example: \"-f 1:3,2:4,10:6,20:10\". check repo for details\n");
+    printf("    --random-drop         <number>        simulate packet loss, unit: 0.01%%. default value: 0.\n");
+    printf("    --disable-obscure     <number>        disable obscure, to save a bit bandwidth and cpu\n");
+    printf("    --disable-checksum    <number>        disable checksum to save a bit bandwdith and cpu\n");
+    // printf("    --disable-xor         <number>        disable xor\n");
+
+    printf("developer options:\n");
+    printf("    --fifo                <string>        use a fifo(named pipe) for sending commands to the running program, so that you\n");
+    printf("                                          can change fec encode parameters dynamically, check readme.md in repository for\n");
+    printf("                                          supported commands.\n");
+    printf("    -j ,--jitter          jmin:jmax       similiar to -j above, but create jitter randomly between jmin and jmax\n");
+    printf("    -i,--interval         imin:imax       similiar to -i above, but scatter randomly between imin and imax\n");
     printf("    -q,--queue-len        <number>        fec queue len, only for mode 0, fec will be performed immediately after queue is full.\n");
-	printf("                                          default value: 200. \n");
+    printf("                                          default value: 200. \n");
     printf("    --decode-buf          <number>        size of buffer of fec decoder,unit: packet, default: 2000\n");
-//    printf("    --fix-latency         <number>        try to stabilize latency, only for mode 0\n");
+    //    printf("    --fix-latency         <number>        try to stabilize latency, only for mode 0\n");
     printf("    --delay-capacity      <number>        max number of delayed packets, 0 means unlimited, default: 0\n");
-	printf("    --disable-fec         <number>        completely disable fec, turn the program into a normal udp tunnel\n");
-	printf("    --sock-buf            <number>        buf size for socket, >=10 and <=10240, unit: kbyte, default: 1024\n");
-	printf("    --out-addr            ip:port         force all output packets of '-r' end to go through this address, port 0 for random port.\n");
+    printf("    --disable-fec         <number>        completely disable fec, turn the program into a normal udp tunnel\n");
+    printf("    --sock-buf            <number>        buf size for socket, >=10 and <=10240, unit: kbyte, default: 1024\n");
+    printf("    --out-addr            ip:port         force all output packets of '-r' end to go through this address, port 0 for random port.\n");
 #ifdef __linux__
-	printf("    --out-interface       <string>        force all output packets of '-r' end to go through this interface.\n");
+    printf("    --out-interface       <string>        force all output packets of '-r' end to go through this interface.\n");
 #endif
-	printf("log and help options:\n");
-	printf("    --log-level           <number>        0: never    1: fatal   2: error   3: warn \n");
-	printf("                                          4: info (default)      5: debug   6: trace\n");
-	printf("    --log-position                        enable file name, function name, line number in log\n");
-	printf("    --disable-color                       disable log color\n");
-	printf("    -h,--help                             print this help message\n");
-
-	//printf("common options,these options must be same on both side\n");
+    printf("log and help options:\n");
+    printf("    --log-level           <number>        0: never    1: fatal   2: error   3: warn \n");
+    printf("                                          4: info (default)      5: debug   6: trace\n");
+    printf("    --log-position                        enable file name, function name, line number in log\n");
+    printf("    --disable-color                       disable log color\n");
+    printf("    -h,--help                             print this help message\n");
+
+    // printf("common options,these options must be same on both side\n");
 }
 
-
-void sigpipe_cb(struct ev_loop *l, ev_signal *w, int revents)
-{
-	mylog(log_info, "got sigpipe, ignored");
+void sigpipe_cb(struct ev_loop *l, ev_signal *w, int revents) {
+    mylog(log_info, "got sigpipe, ignored");
 }
 
-void sigterm_cb(struct ev_loop *l, ev_signal *w, int revents)
-{
-	mylog(log_info, "got sigterm, exit");
-	myexit(0);
+void sigterm_cb(struct ev_loop *l, ev_signal *w, int revents) {
+    mylog(log_info, "got sigterm, exit");
+    myexit(0);
 }
 
-void sigint_cb(struct ev_loop *l, ev_signal *w, int revents)
-{
-	mylog(log_info, "got sigint, exit");
-	myexit(0);
+void sigint_cb(struct ev_loop *l, ev_signal *w, int revents) {
+    mylog(log_info, "got sigint, exit");
+    myexit(0);
 }
 
+int main(int argc, char *argv[]) {
+    working_mode = tunnel_mode;
+    init_ws();
+    // unit_test();
 
-
-int main(int argc, char *argv[])
-{
-	working_mode=tunnel_mode;
-	init_ws();
-	//unit_test();
-
-	struct ev_loop* loop=ev_default_loop(0);
+    struct ev_loop *loop = ev_default_loop(0);
 #if !defined(__MINGW32__)
     ev_signal signal_watcher_sigpipe;
     ev_signal_init(&signal_watcher_sigpipe, sigpipe_cb, SIGPIPE);
     ev_signal_start(loop, &signal_watcher_sigpipe);
 #else
-    enable_log_color=0;
+    enable_log_color = 0;
 #endif
 
     ev_signal signal_watcher_sigterm;
@@ -123,47 +114,39 @@ int main(int argc, char *argv[])
     ev_signal_init(&signal_watcher_sigint, sigint_cb, SIGINT);
     ev_signal_start(loop, &signal_watcher_sigint);
 
-	assert(sizeof(u64_t)==8);
-	assert(sizeof(i64_t)==8);
-	assert(sizeof(u32_t)==4);
-	assert(sizeof(i32_t)==4);
-	assert(sizeof(u16_t)==2);
-	assert(sizeof(i16_t)==2);
-	dup2(1, 2);		//redirect stderr to stdout
-	int i, j, k;
-
-	if (argc == 1)
-	{
-		print_help();
-		myexit( -1);
-	}
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
-		{
-			print_help();
-			myexit(0);
-		}
-	}
-
-	process_arg(argc,argv);
-
-	delay_manager.set_capacity(delay_capacity);
-
-	if(strlen(tun_dev)==0)
-	{
-		sprintf(tun_dev,"tun%u",get_fake_random_number()%1000);
-	}
-
-	if(program_mode==client_mode)
-	{
-		tunnel_client_event_loop();
-	}
-	else
-	{
-		tunnel_server_event_loop();
-	}
-
-	return 0;
+    assert(sizeof(u64_t) == 8);
+    assert(sizeof(i64_t) == 8);
+    assert(sizeof(u32_t) == 4);
+    assert(sizeof(i32_t) == 4);
+    assert(sizeof(u16_t) == 2);
+    assert(sizeof(i16_t) == 2);
+    dup2(1, 2);  // redirect stderr to stdout
+    int i, j, k;
+
+    if (argc == 1) {
+        print_help();
+        myexit(-1);
+    }
+    for (i = 0; i < argc; i++) {
+        if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+            print_help();
+            myexit(0);
+        }
+    }
+
+    process_arg(argc, argv);
+
+    delay_manager.set_capacity(delay_capacity);
+
+    if (strlen(tun_dev) == 0) {
+        sprintf(tun_dev, "tun%u", get_fake_random_number() % 1000);
+    }
+
+    if (program_mode == client_mode) {
+        tunnel_client_event_loop();
+    } else {
+        tunnel_server_event_loop();
+    }
+
+    return 0;
 }
-

+ 859 - 1069
misc.cpp

@@ -5,1100 +5,890 @@
  *      Author: root
  */
 
-
 #include "misc.h"
 
+char fifo_file[1000] = "";
 
-char fifo_file[1000]="";
-
-int mtu_warn=1350;
-
-int disable_mtu_warn=1;
-int disable_fec=0;
-int disable_checksum=0;
-
-int debug_force_flush_fec=0;
+int mtu_warn = 1350;
 
+int disable_mtu_warn = 1;
+int disable_fec = 0;
+int disable_checksum = 0;
 
-int jitter_min=0*1000;
-int jitter_max=0*1000;
+int debug_force_flush_fec = 0;
 
-int output_interval_min=0*1000;
-int output_interval_max=0*1000;
+int jitter_min = 0 * 1000;
+int jitter_max = 0 * 1000;
 
-int fix_latency=0;
+int output_interval_min = 0 * 1000;
+int output_interval_max = 0 * 1000;
 
+int fix_latency = 0;
 
-address_t local_addr,remote_addr;
-address_t *out_addr=0;
-char *out_interface=0;
-//u32_t local_ip_uint32,remote_ip_uint32=0;
-//char local_ip[100], remote_ip[100];
-//int local_port = -1, remote_port = -1;
+address_t local_addr, remote_addr;
+address_t *out_addr = 0;
+char *out_interface = 0;
+// u32_t local_ip_uint32,remote_ip_uint32=0;
+// char local_ip[100], remote_ip[100];
+// int local_port = -1, remote_port = -1;
 
 conn_manager_t conn_manager;
 delay_manager_t delay_manager;
 fd_manager_t fd_manager;
 
-int time_mono_test=0;
-
-int delay_capacity=0;
-
-
-char sub_net[100]="10.22.22.0";
-u32_t sub_net_uint32=0;
-
-char tun_dev[100]="";
-
-
-int keep_reconnect=0;
-
-int tun_mtu=1500;
-
-int mssfix=default_mtu;
-
-int manual_set_tun=0;
-int persist_tun=0;
-
-char rs_par_str[rs_str_len]="20:10";
-
-
-int from_normal_to_fec(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay)
-{
-
-	static my_time_t out_delay_buf[max_fec_packet_num+100]={0};
-	//static int out_len_buf[max_fec_packet_num+100]={0};
-	//static int counter=0;
-	out_delay=out_delay_buf;
-	//out_len=out_len_buf;
-	inner_stat_t &inner_stat=conn_info.stat.normal_to_fec;
-	if(disable_fec)
-	{
-		if(data==0)
-		{
-			out_n=0;
-			return 0;
-		}
-		//assert(data!=0);
-		inner_stat.input_packet_num++;
-		inner_stat.input_packet_size+=len;
-		inner_stat.output_packet_num++;
-		inner_stat.output_packet_size+=len;
-
-		out_n=1;
-		static char *data_static;
-		data_static=data;
-		static int len_static;
-		len_static=len;
-		out_arr=&data_static;
-		out_len=&len_static;
-		out_delay[0]=0;
-
-	}
-	else
-	{
-		if(data!=0)
-		{
-			inner_stat.input_packet_num++;
-			inner_stat.input_packet_size+=len;
-		}
-		//counter++;
-
-		conn_info.fec_encode_manager.input(data,len);
-
-		//if(counter%5==0)
-			//conn_info.fec_encode_manager.input(0,0);
-
-		//int n;
-		//char **s_arr;
-		//int s_len;
-
-
-		conn_info.fec_encode_manager.output(out_n,out_arr,out_len);
-
-		if(out_n>0)
-		{
-			my_time_t common_latency=0;
-			my_time_t first_packet_time=conn_info.fec_encode_manager.get_first_packet_time();
-
-			if(fix_latency==1&&conn_info.fec_encode_manager.get_type()==0)
-			{
-				my_time_t current_time=get_current_time_us();
-				my_time_t tmp;
-				assert(first_packet_time!=0);
-				//mylog(log_info,"current_time=%llu first_packlet_time=%llu   fec_pending_time=%llu\n",current_time,first_packet_time,(my_time_t)fec_pending_time);
-				if((my_time_t)conn_info.fec_encode_manager.get_pending_time() >=(current_time - first_packet_time))
-				{
-					tmp=(my_time_t)conn_info.fec_encode_manager.get_pending_time()-(current_time - first_packet_time);
-					//mylog(log_info,"tmp=%llu\n",tmp);
-				}
-				else
-				{
-					tmp=0;
-					//mylog(log_info,"0\n");
-				}
-				common_latency+=tmp;
-			}
-
-			common_latency+=random_between(jitter_min,jitter_max);
-
-			out_delay_buf[0]=common_latency;
-
-			for(int i=1;i<out_n;i++)
-			{
-				out_delay_buf[i]=out_delay_buf[i-1]+ (my_time_t)( random_between(output_interval_min,output_interval_max)/(out_n-1)  );
-			}
-		}
-
-
-		if(out_n>0)
-		{
-			log_bare(log_trace,"seq= %u ",read_u32(out_arr[0]));
-		}
-		for(int i=0;i<out_n;i++)
-		{
-			inner_stat.output_packet_num++;
-			inner_stat.output_packet_size+=out_len[i];
-
-			log_bare(log_trace,"%d ",out_len[i]);
-
-		}
-
-		log_bare(log_trace,"\n");
-
-	}
-
-	mylog(log_trace,"from_normal_to_fec input_len=%d,output_n=%d\n",len,out_n);
-
-
-	//for(int i=0;i<n;i++)
-	//{
-		//delay_send(0,dest,s_arr[i],s_len);
-	//}
-	//delay_send(0,dest,data,len);
-	//delay_send(1000*1000,dest,data,len);
-	return 0;
+int time_mono_test = 0;
+
+int delay_capacity = 0;
+
+char sub_net[100] = "10.22.22.0";
+u32_t sub_net_uint32 = 0;
+
+char tun_dev[100] = "";
+
+int keep_reconnect = 0;
+
+int tun_mtu = 1500;
+
+int mssfix = default_mtu;
+
+int manual_set_tun = 0;
+int persist_tun = 0;
+
+char rs_par_str[rs_str_len] = "20:10";
+
+int from_normal_to_fec(conn_info_t &conn_info, char *data, int len, int &out_n, char **&out_arr, int *&out_len, my_time_t *&out_delay) {
+    static my_time_t out_delay_buf[max_fec_packet_num + 100] = {0};
+    // static int out_len_buf[max_fec_packet_num+100]={0};
+    // static int counter=0;
+    out_delay = out_delay_buf;
+    // out_len=out_len_buf;
+    inner_stat_t &inner_stat = conn_info.stat.normal_to_fec;
+    if (disable_fec) {
+        if (data == 0) {
+            out_n = 0;
+            return 0;
+        }
+        // assert(data!=0);
+        inner_stat.input_packet_num++;
+        inner_stat.input_packet_size += len;
+        inner_stat.output_packet_num++;
+        inner_stat.output_packet_size += len;
+
+        out_n = 1;
+        static char *data_static;
+        data_static = data;
+        static int len_static;
+        len_static = len;
+        out_arr = &data_static;
+        out_len = &len_static;
+        out_delay[0] = 0;
+
+    } else {
+        if (data != 0) {
+            inner_stat.input_packet_num++;
+            inner_stat.input_packet_size += len;
+        }
+        // counter++;
+
+        conn_info.fec_encode_manager.input(data, len);
+
+        // if(counter%5==0)
+        // conn_info.fec_encode_manager.input(0,0);
+
+        // int n;
+        // char **s_arr;
+        // int s_len;
+
+        conn_info.fec_encode_manager.output(out_n, out_arr, out_len);
+
+        if (out_n > 0) {
+            my_time_t common_latency = 0;
+            my_time_t first_packet_time = conn_info.fec_encode_manager.get_first_packet_time();
+
+            if (fix_latency == 1 && conn_info.fec_encode_manager.get_type() == 0) {
+                my_time_t current_time = get_current_time_us();
+                my_time_t tmp;
+                assert(first_packet_time != 0);
+                // mylog(log_info,"current_time=%llu first_packlet_time=%llu   fec_pending_time=%llu\n",current_time,first_packet_time,(my_time_t)fec_pending_time);
+                if ((my_time_t)conn_info.fec_encode_manager.get_pending_time() >= (current_time - first_packet_time)) {
+                    tmp = (my_time_t)conn_info.fec_encode_manager.get_pending_time() - (current_time - first_packet_time);
+                    // mylog(log_info,"tmp=%llu\n",tmp);
+                } else {
+                    tmp = 0;
+                    // mylog(log_info,"0\n");
+                }
+                common_latency += tmp;
+            }
+
+            common_latency += random_between(jitter_min, jitter_max);
+
+            out_delay_buf[0] = common_latency;
+
+            for (int i = 1; i < out_n; i++) {
+                out_delay_buf[i] = out_delay_buf[i - 1] + (my_time_t)(random_between(output_interval_min, output_interval_max) / (out_n - 1));
+            }
+        }
+
+        if (out_n > 0) {
+            log_bare(log_trace, "seq= %u ", read_u32(out_arr[0]));
+        }
+        for (int i = 0; i < out_n; i++) {
+            inner_stat.output_packet_num++;
+            inner_stat.output_packet_size += out_len[i];
+
+            log_bare(log_trace, "%d ", out_len[i]);
+        }
+
+        log_bare(log_trace, "\n");
+    }
+
+    mylog(log_trace, "from_normal_to_fec input_len=%d,output_n=%d\n", len, out_n);
+
+    // for(int i=0;i<n;i++)
+    //{
+    // delay_send(0,dest,s_arr[i],s_len);
+    //}
+    // delay_send(0,dest,data,len);
+    // delay_send(1000*1000,dest,data,len);
+    return 0;
 }
-int from_fec_to_normal(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay)
-{
-	static my_time_t out_delay_buf[max_blob_packet_num+100]={0};
-	out_delay=out_delay_buf;
-	inner_stat_t &inner_stat=conn_info.stat.fec_to_normal;
-	if(disable_fec)
-	{
-		assert(data!=0);
-		inner_stat.input_packet_num++;
-		inner_stat.input_packet_size+=len;
-		inner_stat.output_packet_num++;
-		inner_stat.output_packet_size+=len;
-
-		if(data==0)
-		{
-			out_n=0;
-			return 0;
-		}
-		out_n=1;
-		static char *data_static;
-		data_static=data;
-		static int len_static;
-		len_static=len;
-		out_arr=&data_static;
-		out_len=&len_static;
-		out_delay[0]=0;
-	}
-	else
-	{
-
-		if(data!=0)
-		{
-			inner_stat.input_packet_num++;
-			inner_stat.input_packet_size+=len;
-		}
-
-		conn_info.fec_decode_manager.input(data,len);
-
-		//int n;char ** s_arr;int* len_arr;
-		conn_info.fec_decode_manager.output(out_n,out_arr,out_len);
-		for(int i=0;i<out_n;i++)
-		{
-			out_delay_buf[i]=0;
-
-			inner_stat.output_packet_num++;
-			inner_stat.output_packet_size+=out_len[i];
-		}
-
-
-	}
-
-	mylog(log_trace,"from_fec_to_normal input_len=%d,output_n=%d,input_seq=%u\n",len,out_n,read_u32(data));
-
-
-//	printf("<n:%d>",n);
-	/*
-	for(int i=0;i<n;i++)
-	{
-		delay_send(0,dest,s_arr[i],len_arr[i]);
-		//s_arr[i][len_arr[i]]=0;
-		//printf("<%s>\n",s_arr[i]);
-	}*/
-	//my_send(dest,data,len);
-	return 0;
+int from_fec_to_normal(conn_info_t &conn_info, char *data, int len, int &out_n, char **&out_arr, int *&out_len, my_time_t *&out_delay) {
+    static my_time_t out_delay_buf[max_blob_packet_num + 100] = {0};
+    out_delay = out_delay_buf;
+    inner_stat_t &inner_stat = conn_info.stat.fec_to_normal;
+    if (disable_fec) {
+        assert(data != 0);
+        inner_stat.input_packet_num++;
+        inner_stat.input_packet_size += len;
+        inner_stat.output_packet_num++;
+        inner_stat.output_packet_size += len;
+
+        if (data == 0) {
+            out_n = 0;
+            return 0;
+        }
+        out_n = 1;
+        static char *data_static;
+        data_static = data;
+        static int len_static;
+        len_static = len;
+        out_arr = &data_static;
+        out_len = &len_static;
+        out_delay[0] = 0;
+    } else {
+        if (data != 0) {
+            inner_stat.input_packet_num++;
+            inner_stat.input_packet_size += len;
+        }
+
+        conn_info.fec_decode_manager.input(data, len);
+
+        // int n;char ** s_arr;int* len_arr;
+        conn_info.fec_decode_manager.output(out_n, out_arr, out_len);
+        for (int i = 0; i < out_n; i++) {
+            out_delay_buf[i] = 0;
+
+            inner_stat.output_packet_num++;
+            inner_stat.output_packet_size += out_len[i];
+        }
+    }
+
+    mylog(log_trace, "from_fec_to_normal input_len=%d,output_n=%d,input_seq=%u\n", len, out_n, read_u32(data));
+
+    //	printf("<n:%d>",n);
+    /*
+    for(int i=0;i<n;i++)
+    {
+            delay_send(0,dest,s_arr[i],len_arr[i]);
+            //s_arr[i][len_arr[i]]=0;
+            //printf("<%s>\n",s_arr[i]);
+    }*/
+    // my_send(dest,data,len);
+    return 0;
 }
 
-
-int delay_send(my_time_t delay,const dest_t &dest,char *data,int len)
-{
-	//int rand=random()%100;
-	//mylog(log_info,"rand = %d\n",rand);
-
-	if (dest.cook&&random_drop != 0) {
-		if (get_fake_random_number() % 10000 < (u32_t) random_drop) {
-			return 0;
-		}
-	}
-	return delay_manager.add(delay,dest,data,len);;
+int delay_send(my_time_t delay, const dest_t &dest, char *data, int len) {
+    // int rand=random()%100;
+    // mylog(log_info,"rand = %d\n",rand);
+
+    if (dest.cook && random_drop != 0) {
+        if (get_fake_random_number() % 10000 < (u32_t)random_drop) {
+            return 0;
+        }
+    }
+    return delay_manager.add(delay, dest, data, len);
+    ;
 }
 
-int print_parameter()
-{
-	mylog(log_info,"jitter_min=%d jitter_max=%d output_interval_min=%d output_interval_max=%d fec_timeout=%d fec_mtu=%d fec_queue_len=%d fec_mode=%d\n",
-			jitter_min/1000,jitter_max/1000,output_interval_min/1000,output_interval_max/1000,g_fec_par.timeout/1000,g_fec_par.mtu,g_fec_par.queue_len,g_fec_par.mode);
-	mylog(log_info,"fec_str=%s\n",rs_par_str);
-	mylog(log_info,"fec_inner_parameter=%s\n",g_fec_par.rs_to_str());
-	return 0;
+int print_parameter() {
+    mylog(log_info, "jitter_min=%d jitter_max=%d output_interval_min=%d output_interval_max=%d fec_timeout=%d fec_mtu=%d fec_queue_len=%d fec_mode=%d\n",
+          jitter_min / 1000, jitter_max / 1000, output_interval_min / 1000, output_interval_max / 1000, g_fec_par.timeout / 1000, g_fec_par.mtu, g_fec_par.queue_len, g_fec_par.mode);
+    mylog(log_info, "fec_str=%s\n", rs_par_str);
+    mylog(log_info, "fec_inner_parameter=%s\n", g_fec_par.rs_to_str());
+    return 0;
 }
-int handle_command(char *s)
-{
-	int len=strlen(s);
-	while(len>=1&&s[len-1]=='\n')
-		s[len-1]=0;
-	mylog(log_info,"got data from fifo,len=%d,s=[%s]\n",len,s);
-	int a=-1,b=-1;
-	if(strncmp(s,"fec",strlen("fec"))==0)
-	{
-		mylog(log_info,"got command [fec]\n");
-		char tmp_str[max_fec_packet_num*10+100];
-		fec_parameter_t tmp_par;
-		sscanf(s,"fec %s",tmp_str);
-		/*
-		if(a<1||b<0||a+b>254)
-		{
-			mylog(log_warn,"invaild value\n");
-			return -1;
-		}*/
-		int ret=tmp_par.rs_from_str(tmp_str);
-		if(ret!=0)
-		{
-			mylog(log_warn,"failed to parse [%s]\n",tmp_str);
-			return -1;
-		}
-		int version=g_fec_par.version;
-		g_fec_par.copy_fec(tmp_par);
-		g_fec_par.version=version+1;
-		strcpy(rs_par_str,tmp_str);
-		//g_fec_data_num=a;
-		//g_fec_redundant_num=b;
-	}
-	else if(strncmp(s,"mtu",strlen("mtu"))==0)
-	{
-		mylog(log_info,"got command [mtu]\n");
-		sscanf(s,"mtu %d",&a);
-		if(a<100||a>2000)
-		{
-			mylog(log_warn,"invaild value\n");
-			return -1;
-		}
-		g_fec_par.mtu=a;
-	}
-	else if(strncmp(s,"queue-len",strlen("queue-len"))==0)
-	{
-		mylog(log_info,"got command [queue-len]\n");
-		sscanf(s,"queue-len %d",&a);
-		if(a<1||a>10000)
-		{
-			mylog(log_warn,"invaild value\n");
-			return -1;
-		}
-		g_fec_par.queue_len=a;
-	}
-	else if(strncmp(s,"mode",strlen("mode"))==0)
-	{
-		mylog(log_info,"got command [mode]\n");
-		sscanf(s,"mode %d",&a);
-		if(a!=0&&a!=1)
-		{
-			mylog(log_warn,"invaild value\n");
-			return -1;
-		}
-		if(g_fec_par.mode!=a)
-		{
-			g_fec_par.mode=a;
-
-			assert(g_fec_par.rs_from_str(rs_par_str)==0); //re parse rs_par_str,not necessary at the moment, for futher use
-			g_fec_par.version++;
-		}
-	}
-	else if(strncmp(s,"timeout",strlen("timeout"))==0)
-	{
-		mylog(log_info,"got command [timeout]\n");
-		sscanf(s,"timeout %d",&a);
-		if(a<0||a>1000)
-		{
-			mylog(log_warn,"invaild value\n");
-			return -1;
-		}
-		g_fec_par.timeout=a*1000;
-	}
-	else
-	{
-		mylog(log_info,"unknown command\n");
-	}
-	print_parameter();
-
-	return 0;
+int handle_command(char *s) {
+    int len = strlen(s);
+    while (len >= 1 && s[len - 1] == '\n')
+        s[len - 1] = 0;
+    mylog(log_info, "got data from fifo,len=%d,s=[%s]\n", len, s);
+    int a = -1, b = -1;
+    if (strncmp(s, "fec", strlen("fec")) == 0) {
+        mylog(log_info, "got command [fec]\n");
+        char tmp_str[max_fec_packet_num * 10 + 100];
+        fec_parameter_t tmp_par;
+        sscanf(s, "fec %s", tmp_str);
+        /*
+        if(a<1||b<0||a+b>254)
+        {
+                mylog(log_warn,"invaild value\n");
+                return -1;
+        }*/
+        int ret = tmp_par.rs_from_str(tmp_str);
+        if (ret != 0) {
+            mylog(log_warn, "failed to parse [%s]\n", tmp_str);
+            return -1;
+        }
+        int version = g_fec_par.version;
+        g_fec_par.copy_fec(tmp_par);
+        g_fec_par.version = version + 1;
+        strcpy(rs_par_str, tmp_str);
+        // g_fec_data_num=a;
+        // g_fec_redundant_num=b;
+    } else if (strncmp(s, "mtu", strlen("mtu")) == 0) {
+        mylog(log_info, "got command [mtu]\n");
+        sscanf(s, "mtu %d", &a);
+        if (a < 100 || a > 2000) {
+            mylog(log_warn, "invaild value\n");
+            return -1;
+        }
+        g_fec_par.mtu = a;
+    } else if (strncmp(s, "queue-len", strlen("queue-len")) == 0) {
+        mylog(log_info, "got command [queue-len]\n");
+        sscanf(s, "queue-len %d", &a);
+        if (a < 1 || a > 10000) {
+            mylog(log_warn, "invaild value\n");
+            return -1;
+        }
+        g_fec_par.queue_len = a;
+    } else if (strncmp(s, "mode", strlen("mode")) == 0) {
+        mylog(log_info, "got command [mode]\n");
+        sscanf(s, "mode %d", &a);
+        if (a != 0 && a != 1) {
+            mylog(log_warn, "invaild value\n");
+            return -1;
+        }
+        if (g_fec_par.mode != a) {
+            g_fec_par.mode = a;
+
+            assert(g_fec_par.rs_from_str(rs_par_str) == 0);  // re parse rs_par_str,not necessary at the moment, for futher use
+            g_fec_par.version++;
+        }
+    } else if (strncmp(s, "timeout", strlen("timeout")) == 0) {
+        mylog(log_info, "got command [timeout]\n");
+        sscanf(s, "timeout %d", &a);
+        if (a < 0 || a > 1000) {
+            mylog(log_warn, "invaild value\n");
+            return -1;
+        }
+        g_fec_par.timeout = a * 1000;
+    } else {
+        mylog(log_info, "unknown command\n");
+    }
+    print_parameter();
+
+    return 0;
 }
 
-static void empty_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-
+static void empty_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
 }
-int unit_test()
-{
-
-	{
-		union test_t
-		{
-			u64_t u64;
-			char arry[8];
-		}test111;
-
-		assert((void*)&test111.u64==(void*)&test111.arry[0]);
-		//printf("%llx,%llx\n",&ttt.u64,&ttt.arry[0]);
-
-//		printf("%lld\n",get_fake_random_number_64());
-//		printf("%lld\n",get_fake_random_number_64());
-//		printf("%lld\n",get_fake_random_number_64());
-
-//		printf("%x\n",get_fake_random_number());
-//		printf("%x\n",get_fake_random_number());
-//		printf("%x\n",get_fake_random_number());
-
-		char buf[10];
-		get_fake_random_chars(buf,10);
-		for(int i=0;i<10;i++)
-			printf("<%d>",(int)buf[i]);
-		printf("\n");
-
-		get_fake_random_chars(buf,10);
-		for(int i=0;i<10;i++)
-			printf("<%d>",(int)buf[i]);
-		printf("\n");
-	}
-
-
-	int i,j,k;
-	void *code=fec_new(3,6);
-	char arr[6][100]=
-	{
-		"aaa","bbb","ccc"
-		,"ddd","eee","fff"
-	};
-	char *data[6];
-	for(i=0;i<6;i++)
-	{
-		data[i]=arr[i];
-	}
-	rs_encode2(3,6,data,3);
-	//printf("%d %d",(int)(unsigned char)arr[5][0],(int)('a'^'b'^'c'^'d'^'e'));
-
-	for(i=0;i<6;i++)
-	{
-		printf("<%s>",data[i]);
-	}
-
-	data[0]=0;
-	//data[1]=0;
-	//data[5]=0;
-
-	int ret=rs_decode2(3,6,data,3);
-	printf("ret:%d\n",ret);
-
-	for(i=0;i<6;i++)
-	{
-		printf("<%s>",data[i]);
-	}
-	fec_free(code);
-
-
-	char arr2[6][100]=
-	{
-		"aaa11111","","ccc333333333"
-		,"ddd444","eee5555","ff6666"
-	};
-	blob_encode_t blob_encode;
-	for(int i=0;i<6;i++)
-		blob_encode.input(arr2[i],strlen(arr2[i]));
-
-	char **output;
-	int shard_len;
-	blob_encode.output(7,output,shard_len);
-
-
-	printf("<shard_len:%d>",shard_len);
-	blob_decode_t blob_decode;
-	for(int i=0;i<7;i++)
-	{
-		blob_decode.input(output[i],shard_len);
-	}
-
-	char **decode_output;
-	int * len_arr;
-	int num;
-
-
-	ret=blob_decode.output(num,decode_output,len_arr);
-
-	printf("<num:%d,ret:%d>\n",num,ret);
-	for(int i=0;i<num;i++)
-	{
-		char buf[1000]={0};
-		memcpy(buf,decode_output[i],len_arr[i]);
-		printf("<%d:%s>",len_arr[i],buf);
-	}
-	printf("\n");
-	static fec_encode_manager_t fec_encode_manager;
-	static fec_decode_manager_t fec_decode_manager;
-
-	//dynamic_update_fec=0;
-
-	fec_encode_manager.set_loop_and_cb(ev_default_loop(0),empty_cb);
-
-	{
-
-		string a = "11111";
-		string b = "22";
-		string c = "33333333";
-
-		fec_encode_manager.input((char *) a.c_str(), a.length());
-		fec_encode_manager.input((char *) b.c_str(), b.length());
-		fec_encode_manager.input((char *) c.c_str(), c.length());
-		fec_encode_manager.input(0, 0);
-
-		int n;
-		char **s_arr;
-		int *len;
-
-
-		fec_encode_manager.output(n,s_arr,len);
-		printf("<n:%d,len:%d>",n,len[0]);
-
-		for(int i=0;i<n;i++)
-		{
-			fec_decode_manager.input(s_arr[i],len[i]);
-		}
-
-		{
-			int n;char ** s_arr;int* len_arr;
-			fec_decode_manager.output(n,s_arr,len_arr);
-			printf("<n:%d>",n);
-			for(int i=0;i<n;i++)
-			{
-				s_arr[i][len_arr[i]]=0;
-				printf("<%s>\n",s_arr[i]);
-			}
-		}
-
-
-	}
-
-	{
-		string a = "aaaaaaa";
-		string b = "bbbbbbbbbbbbb";
-		string c = "ccc";
-
-
-		fec_encode_manager.input((char *) a.c_str(), a.length());
-		fec_encode_manager.input((char *) b.c_str(), b.length());
-		fec_encode_manager.input((char *) c.c_str(), c.length());
-		fec_encode_manager.input(0, 0);
-
-		int n;
-		char **s_arr;
-		int * len;
-
-
-		fec_encode_manager.output(n,s_arr,len);
-		printf("<n:%d,len:%d>",n,len[0]);
-
-		for(int i=0;i<n;i++)
-		{
-			if(i==1||i==3||i==5||i==0)
-			fec_decode_manager.input(s_arr[i],len[i]);
-		}
-
-		{
-			int n;char ** s_arr;int* len_arr;
-			fec_decode_manager.output(n,s_arr,len_arr);
-			printf("<n:%d>",n);
-			for(int i=0;i<n;i++)
-			{
-				s_arr[i][len_arr[i]]=0;
-				printf("<%s>\n",s_arr[i]);
-			}
-		}
-	}
-
-	printf("ok here.\n");
-	for(int i=0;i<10;i++)
-	{
-		string a = "aaaaaaaaaaaaaaaaaaaaaaa";
-		string b = "bbbbbbbbbbbbb";
-		string c = "cccccccccccccccccc";
-
-
-
-		printf("======\n");
-		int n;
-		char **s_arr;
-		int * len;
-		fec_decode_manager.output(n,s_arr,len);
-
-		//fec_encode_manager.reset_fec_parameter(3,2,g_fec_mtu,g_fec_queue_len,g_fec_timeout,1);
-
-		fec_parameter_t &fec_par=fec_encode_manager.get_fec_par();
-		fec_par.mtu=g_fec_par.mtu;
-		fec_par.queue_len=g_fec_par.queue_len;
-		fec_par.timeout=g_fec_par.timeout;
-		fec_par.mode=1;
-		fec_par.rs_from_str((char *)"3:2");
-
-		fec_encode_manager.input((char *) a.c_str(), a.length());
-		fec_encode_manager.output(n,s_arr,len);
-
-		printf("n=<%d>\n",n);
-		assert(n==1);
-
-		fec_decode_manager.input(s_arr[0],len[0]);
-
-		fec_decode_manager.output(n,s_arr,len);
-		assert(n==1);
-		printf("%s\n",s_arr[0]);
-
-		fec_encode_manager.input((char *) b.c_str(), b.length());
-		fec_encode_manager.output(n,s_arr,len);
-		assert(n==1);
-		//fec_decode_manager.input(s_arr[0],len[0]);
-
-
-		fec_encode_manager.input((char *) c.c_str(), c.length());
-		fec_encode_manager.output(n,s_arr,len);
-
-		assert(n==3);
-
-		fec_decode_manager.input(s_arr[0],len[0]);
-		//printf("n=%d\n",n);
-
-
-		{
-			int n;
-			char **s_arr;
-			int * len;
-			fec_decode_manager.output(n,s_arr,len);
-			assert(n==1);
-			printf("%s\n",s_arr[0]);
-		}
-
-		fec_decode_manager.input(s_arr[1],len[1]);
-
-		{
-			int n;
-			char **s_arr;
-			int * len;
-			fec_decode_manager.output(n,s_arr,len);
-			assert(n==1);
-			printf("n=%d\n",n);
-			s_arr[0][len[0]]=0;
-			printf("%s\n",s_arr[0]);
-		}
-
-	}
-
-	myexit(0);
-	return 0;
+int unit_test() {
+    {
+        union test_t {
+            u64_t u64;
+            char arry[8];
+        } test111;
+
+        assert((void *)&test111.u64 == (void *)&test111.arry[0]);
+        // printf("%llx,%llx\n",&ttt.u64,&ttt.arry[0]);
+
+        //		printf("%lld\n",get_fake_random_number_64());
+        //		printf("%lld\n",get_fake_random_number_64());
+        //		printf("%lld\n",get_fake_random_number_64());
+
+        //		printf("%x\n",get_fake_random_number());
+        //		printf("%x\n",get_fake_random_number());
+        //		printf("%x\n",get_fake_random_number());
+
+        char buf[10];
+        get_fake_random_chars(buf, 10);
+        for (int i = 0; i < 10; i++)
+            printf("<%d>", (int)buf[i]);
+        printf("\n");
+
+        get_fake_random_chars(buf, 10);
+        for (int i = 0; i < 10; i++)
+            printf("<%d>", (int)buf[i]);
+        printf("\n");
+    }
+
+    int i, j, k;
+    void *code = fec_new(3, 6);
+    char arr[6][100] =
+        {
+            "aaa", "bbb", "ccc", "ddd", "eee", "fff"};
+    char *data[6];
+    for (i = 0; i < 6; i++) {
+        data[i] = arr[i];
+    }
+    rs_encode2(3, 6, data, 3);
+    // printf("%d %d",(int)(unsigned char)arr[5][0],(int)('a'^'b'^'c'^'d'^'e'));
+
+    for (i = 0; i < 6; i++) {
+        printf("<%s>", data[i]);
+    }
+
+    data[0] = 0;
+    // data[1]=0;
+    // data[5]=0;
+
+    int ret = rs_decode2(3, 6, data, 3);
+    printf("ret:%d\n", ret);
+
+    for (i = 0; i < 6; i++) {
+        printf("<%s>", data[i]);
+    }
+    fec_free(code);
+
+    char arr2[6][100] =
+        {
+            "aaa11111", "", "ccc333333333", "ddd444", "eee5555", "ff6666"};
+    blob_encode_t blob_encode;
+    for (int i = 0; i < 6; i++)
+        blob_encode.input(arr2[i], strlen(arr2[i]));
+
+    char **output;
+    int shard_len;
+    blob_encode.output(7, output, shard_len);
+
+    printf("<shard_len:%d>", shard_len);
+    blob_decode_t blob_decode;
+    for (int i = 0; i < 7; i++) {
+        blob_decode.input(output[i], shard_len);
+    }
+
+    char **decode_output;
+    int *len_arr;
+    int num;
+
+    ret = blob_decode.output(num, decode_output, len_arr);
+
+    printf("<num:%d,ret:%d>\n", num, ret);
+    for (int i = 0; i < num; i++) {
+        char buf[1000] = {0};
+        memcpy(buf, decode_output[i], len_arr[i]);
+        printf("<%d:%s>", len_arr[i], buf);
+    }
+    printf("\n");
+    static fec_encode_manager_t fec_encode_manager;
+    static fec_decode_manager_t fec_decode_manager;
+
+    // dynamic_update_fec=0;
+
+    fec_encode_manager.set_loop_and_cb(ev_default_loop(0), empty_cb);
+
+    {
+        string a = "11111";
+        string b = "22";
+        string c = "33333333";
+
+        fec_encode_manager.input((char *)a.c_str(), a.length());
+        fec_encode_manager.input((char *)b.c_str(), b.length());
+        fec_encode_manager.input((char *)c.c_str(), c.length());
+        fec_encode_manager.input(0, 0);
+
+        int n;
+        char **s_arr;
+        int *len;
+
+        fec_encode_manager.output(n, s_arr, len);
+        printf("<n:%d,len:%d>", n, len[0]);
+
+        for (int i = 0; i < n; i++) {
+            fec_decode_manager.input(s_arr[i], len[i]);
+        }
+
+        {
+            int n;
+            char **s_arr;
+            int *len_arr;
+            fec_decode_manager.output(n, s_arr, len_arr);
+            printf("<n:%d>", n);
+            for (int i = 0; i < n; i++) {
+                s_arr[i][len_arr[i]] = 0;
+                printf("<%s>\n", s_arr[i]);
+            }
+        }
+    }
+
+    {
+        string a = "aaaaaaa";
+        string b = "bbbbbbbbbbbbb";
+        string c = "ccc";
+
+        fec_encode_manager.input((char *)a.c_str(), a.length());
+        fec_encode_manager.input((char *)b.c_str(), b.length());
+        fec_encode_manager.input((char *)c.c_str(), c.length());
+        fec_encode_manager.input(0, 0);
+
+        int n;
+        char **s_arr;
+        int *len;
+
+        fec_encode_manager.output(n, s_arr, len);
+        printf("<n:%d,len:%d>", n, len[0]);
+
+        for (int i = 0; i < n; i++) {
+            if (i == 1 || i == 3 || i == 5 || i == 0)
+                fec_decode_manager.input(s_arr[i], len[i]);
+        }
+
+        {
+            int n;
+            char **s_arr;
+            int *len_arr;
+            fec_decode_manager.output(n, s_arr, len_arr);
+            printf("<n:%d>", n);
+            for (int i = 0; i < n; i++) {
+                s_arr[i][len_arr[i]] = 0;
+                printf("<%s>\n", s_arr[i]);
+            }
+        }
+    }
+
+    printf("ok here.\n");
+    for (int i = 0; i < 10; i++) {
+        string a = "aaaaaaaaaaaaaaaaaaaaaaa";
+        string b = "bbbbbbbbbbbbb";
+        string c = "cccccccccccccccccc";
+
+        printf("======\n");
+        int n;
+        char **s_arr;
+        int *len;
+        fec_decode_manager.output(n, s_arr, len);
+
+        // fec_encode_manager.reset_fec_parameter(3,2,g_fec_mtu,g_fec_queue_len,g_fec_timeout,1);
+
+        fec_parameter_t &fec_par = fec_encode_manager.get_fec_par();
+        fec_par.mtu = g_fec_par.mtu;
+        fec_par.queue_len = g_fec_par.queue_len;
+        fec_par.timeout = g_fec_par.timeout;
+        fec_par.mode = 1;
+        fec_par.rs_from_str((char *)"3:2");
+
+        fec_encode_manager.input((char *)a.c_str(), a.length());
+        fec_encode_manager.output(n, s_arr, len);
+
+        printf("n=<%d>\n", n);
+        assert(n == 1);
+
+        fec_decode_manager.input(s_arr[0], len[0]);
+
+        fec_decode_manager.output(n, s_arr, len);
+        assert(n == 1);
+        printf("%s\n", s_arr[0]);
+
+        fec_encode_manager.input((char *)b.c_str(), b.length());
+        fec_encode_manager.output(n, s_arr, len);
+        assert(n == 1);
+        // fec_decode_manager.input(s_arr[0],len[0]);
+
+        fec_encode_manager.input((char *)c.c_str(), c.length());
+        fec_encode_manager.output(n, s_arr, len);
+
+        assert(n == 3);
+
+        fec_decode_manager.input(s_arr[0], len[0]);
+        // printf("n=%d\n",n);
+
+        {
+            int n;
+            char **s_arr;
+            int *len;
+            fec_decode_manager.output(n, s_arr, len);
+            assert(n == 1);
+            printf("%s\n", s_arr[0]);
+        }
+
+        fec_decode_manager.input(s_arr[1], len[1]);
+
+        {
+            int n;
+            char **s_arr;
+            int *len;
+            fec_decode_manager.output(n, s_arr, len);
+            assert(n == 1);
+            printf("n=%d\n", n);
+            s_arr[0][len[0]] = 0;
+            printf("%s\n", s_arr[0]);
+        }
+    }
+
+    myexit(0);
+    return 0;
 }
 
-
-void process_arg(int argc, char *argv[])
-{
-	int is_client=0,is_server=0;
-	int i, j, k;
-	int opt;
+void process_arg(int argc, char *argv[]) {
+    int is_client = 0, is_server = 0;
+    int i, j, k;
+    int opt;
     static struct option long_options[] =
-      {
-		{"log-level", required_argument,    0, 1},
-		{"log-position", no_argument,    0, 1},
-		{"disable-color", no_argument,    0, 1},
-		{"enable-color", no_argument,    0, 1},
-		{"disable-filter", no_argument,    0, 1},
-		{"disable-fec", no_argument,    0, 1},
-		{"disable-obscure", no_argument,    0, 1},
-		{"disable-xor", no_argument,    0, 1},
-		{"disable-checksum", no_argument,    0, 1},
-		{"fix-latency", no_argument,    0, 1},
-		{"sock-buf", required_argument,    0, 1},
-		{"random-drop", required_argument,    0, 1},
-		{"report", required_argument,    0, 1},
-		{"delay-capacity", required_argument,    0, 1},
-		{"mtu", required_argument,    0, 1},
-		{"mode", required_argument,   0,1},
-		{"timeout", required_argument,   0,1},
-		{"decode-buf", required_argument,   0,1},
-		{"queue-len", required_argument,   0,'q'},
-		{"fec", required_argument,   0,'f'},
-		{"jitter", required_argument,   0,'j'},
-		{"out-addr", required_argument,   0,1},
-		{"out-interface", required_argument,    0, 1},
-		{"key", required_argument,   0,'k'},
-		{"header-overhead", required_argument,    0, 1},
-		//{"debug-fec", no_argument,    0, 1},
-		{"debug-fec-enc", no_argument,    0, 1},
-		{"debug-fec-dec", no_argument,    0, 1},
-		{"fifo", required_argument,    0, 1},
-		{"sub-net", required_argument,    0, 1},
-		{"tun-dev", required_argument,    0, 1},
-		{"tun-mtu", required_argument,    0, 1},
-		{"mssfix", required_argument,    0, 1},
-		{"keep-reconnect", no_argument,    0, 1},
-		{"persist-tun", no_argument,    0, 1},
-		{"manual-set-tun", no_argument,    0, 1},
-		{"interval", required_argument,   0,'i'},
-		{NULL, 0, 0, 0}
-      };
+        {
+            {"log-level", required_argument, 0, 1},
+            {"log-position", no_argument, 0, 1},
+            {"disable-color", no_argument, 0, 1},
+            {"enable-color", no_argument, 0, 1},
+            {"disable-filter", no_argument, 0, 1},
+            {"disable-fec", no_argument, 0, 1},
+            {"disable-obscure", no_argument, 0, 1},
+            {"disable-xor", no_argument, 0, 1},
+            {"disable-checksum", no_argument, 0, 1},
+            {"fix-latency", no_argument, 0, 1},
+            {"sock-buf", required_argument, 0, 1},
+            {"random-drop", required_argument, 0, 1},
+            {"report", required_argument, 0, 1},
+            {"delay-capacity", required_argument, 0, 1},
+            {"mtu", required_argument, 0, 1},
+            {"mode", required_argument, 0, 1},
+            {"timeout", required_argument, 0, 1},
+            {"decode-buf", required_argument, 0, 1},
+            {"queue-len", required_argument, 0, 'q'},
+            {"fec", required_argument, 0, 'f'},
+            {"jitter", required_argument, 0, 'j'},
+            {"out-addr", required_argument, 0, 1},
+            {"out-interface", required_argument, 0, 1},
+            {"key", required_argument, 0, 'k'},
+            {"header-overhead", required_argument, 0, 1},
+            //{"debug-fec", no_argument,    0, 1},
+            {"debug-fec-enc", no_argument, 0, 1},
+            {"debug-fec-dec", no_argument, 0, 1},
+            {"fifo", required_argument, 0, 1},
+            {"sub-net", required_argument, 0, 1},
+            {"tun-dev", required_argument, 0, 1},
+            {"tun-mtu", required_argument, 0, 1},
+            {"mssfix", required_argument, 0, 1},
+            {"keep-reconnect", no_argument, 0, 1},
+            {"persist-tun", no_argument, 0, 1},
+            {"manual-set-tun", no_argument, 0, 1},
+            {"interval", required_argument, 0, 'i'},
+            {NULL, 0, 0, 0}};
     int option_index = 0;
-    assert(g_fec_par.rs_from_str(rs_par_str)==0);
-
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"--unit-test")==0)
-		{
-			unit_test();
-			myexit(0);
-		}
-	}
-
-	for (i = 0; i < argc; i++)
-	{
-		if(strcmp(argv[i],"--log-level")==0)
-		{
-			if(i<argc -1)
-			{
-				sscanf(argv[i+1],"%d",&log_level);
-				if(0<=log_level&&log_level<log_end)
-				{
-				}
-				else
-				{
-					log_bare(log_fatal,"invalid log_level\n");
-					myexit(-1);
-				}
-			}
-		}
-		if(strcmp(argv[i],"--enable-color")==0)
-		{
-			enable_log_color=1;
-		}
-		if(strcmp(argv[i],"--disable-color")==0)
-		{
-			enable_log_color=0;
-		}
-	}
-
-    mylog(log_info,"argc=%d ", argc);
-
-	for (i = 0; i < argc; i++) {
-		log_bare(log_info, "%s ", argv[i]);
-	}
-	log_bare(log_info, "\n");
-
-
-	int no_l = 1, no_r = 1;
-	while ((opt = getopt_long(argc, argv, "l:r:hcsk:j:f:p:n:i:q:",long_options,&option_index)) != -1)
-	{
-		//string opt_key;
-		//opt_key+=opt;
-		switch (opt)
-		{
-		case 'k':
-			sscanf(optarg,"%s\n",key_string);
-			mylog(log_debug,"key=%s\n",key_string);
-			if(strlen(key_string)==0)
-			{
-				mylog(log_fatal,"key len=0??\n");
-				myexit(-1);
-			}
-			break;
-		case 'j':
-			if (strchr(optarg, ':') == 0)
-			{
-				int jitter;
-				sscanf(optarg,"%d\n",&jitter);
-				if(jitter<0 ||jitter>1000*10)
-				{
-					mylog(log_fatal,"jitter must be between 0 and 10,000(10 second)\n");
-					myexit(-1);
-				}
-				jitter_min=0;
-				jitter_max=jitter;
-
-
-			}
-			else
-			{
-				sscanf(optarg,"%d:%d\n",&jitter_min,&jitter_max);
-				if(jitter_min<0 ||jitter_max<0||jitter_min>jitter_max)
-				{
-					mylog(log_fatal," must satisfy  0<=jmin<=jmax\n");
-					myexit(-1);
-				}
-			}
-			jitter_min*=1000;
-			jitter_max*=1000;
-			break;
-		case 'i':
-			if (strchr(optarg, ':') == 0)
-			{
-				int output_interval=-1;
-				sscanf(optarg,"%d\n",&output_interval);
-				if(output_interval<0||output_interval>1000*10)
-				{
-					mylog(log_fatal,"output_interval must be between 0 and 10,000(10 second)\n");
-					myexit(-1);
-				}
-				output_interval_min=output_interval_max=output_interval;
-			}
-			else
-			{
-				sscanf(optarg,"%d:%d\n",&output_interval_min,&output_interval_max);
-				if(output_interval_min<0 ||output_interval_max<0||output_interval_min>output_interval_max)
-				{
-					mylog(log_fatal," must satisfy  0<=output_interval_min<=output_interval_max\n");
-					myexit(-1);
-				}
-			}
-			output_interval_min*=1000;
-			output_interval_max*=1000;
-			break;
-		case 'f':
-			if (strchr(optarg, ':') == 0)
-			{
-				mylog(log_fatal,"invalid format for f");
-				myexit(-1);
-			}
-			else
-			{
-				strcpy(rs_par_str,optarg);
-				//sscanf(optarg,"%d:%d\n",&g_fec_data_num,&g_fec_redundant_num);
-				/*
-				if(g_fec_data_num<1 ||g_fec_redundant_num<0||g_fec_data_num+g_fec_redundant_num>254)
-				{
-					mylog(log_fatal,"fec_data_num<1 ||fec_redundant_num<0||fec_data_num+fec_redundant_num>254\n");
-					myexit(-1);
-				}*/
-			}
-			break;
-		case 'q':
-			sscanf(optarg,"%d",&g_fec_par.queue_len);
-			if(g_fec_par.queue_len<1||g_fec_par.queue_len>10000)
-			{
-
-					mylog(log_fatal,"fec_pending_num should be between 1 and 10000\n");
-					myexit(-1);
-			}
-			break;
-		case 'c':
-			is_client = 1;
-			break;
-		case 's':
-			is_server = 1;
-			break;
-		case 'l':
-			no_l = 0;
-			local_addr.from_str(optarg);
-			break;
-		case 'r':
-			no_r = 0;
-			remote_addr.from_str(optarg);
-			break;
-		case 'h':
-			break;
-		case 1:
-			if(strcmp(long_options[option_index].name,"log-level")==0)
-			{
-			}
-			else if(strcmp(long_options[option_index].name,"disable-filter")==0)
-			{
-				disable_replay_filter=1;
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-color")==0)
-			{
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"enable-color")==0)
-			{
-				//enable_log_color=0;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-fec")==0)
-			{
-				disable_fec=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-obscure")==0)
-			{
-				mylog(log_info,"obscure disabled\n");
-				disable_obscure=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-xor")==0)
-			{
-				mylog(log_info,"xor disabled\n");
-				disable_xor=1;
-			}
-			else if(strcmp(long_options[option_index].name,"disable-checksum")==0)
-			{
-				disable_checksum=1;
-				mylog(log_warn,"checksum disabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"fix-latency")==0)
-			{
-				mylog(log_info,"fix-latency enabled\n");
-				fix_latency=1;
-			}
-
-			else if(strcmp(long_options[option_index].name,"log-position")==0)
-			{
-				enable_log_position=1;
-			}
-			else if(strcmp(long_options[option_index].name,"random-drop")==0)
-			{
-				sscanf(optarg,"%d",&random_drop);
-				if(random_drop<0||random_drop>10000)
-				{
-					mylog(log_fatal,"random_drop must be between 0 10000 \n");
-					myexit(-1);
-				}
-				mylog(log_info,"random_drop=%d\n",random_drop);
-			}
-			else if(strcmp(long_options[option_index].name,"delay-capacity")==0)
-			{
-				sscanf(optarg,"%d",&delay_capacity);
-
-				if(delay_capacity<0)
-				{
-					mylog(log_fatal,"delay_capacity must be >=0 \n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"report")==0)
-			{
-				sscanf(optarg,"%d",&report_interval);
-
-				if(report_interval<=0)
-				{
-					mylog(log_fatal,"report_interval must be >0 \n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"sock-buf")==0)
-			{
-				int tmp=-1;
-				sscanf(optarg,"%d",&tmp);
-				if(10<=tmp&&tmp<=10*1024)
-				{
-					socket_buf_size=tmp*1024;
-				}
-				else
-				{
-					mylog(log_fatal,"sock-buf value must be between 1 and 10240 (kbyte) \n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"decode-buf")==0)
-			{
-				sscanf(optarg,"%d",&fec_buff_num);
-				if(fec_buff_num<300 || fec_buff_num>20000)
-				{
-					mylog(log_fatal,"decode-buf value must be between 300 and 20000 (kbyte) \n");
-					myexit(-1);
-				}
-				mylog(log_info,"decode-buf=%d\n",fec_buff_num);
-			}
-			else if(strcmp(long_options[option_index].name,"mode")==0)
-			{
-				sscanf(optarg,"%d",&g_fec_par.mode);
-				if(g_fec_par.mode!=0&&g_fec_par.mode!=1)
-				{
-					mylog(log_fatal,"mode should be 0 or 1\n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"mtu")==0)
-			{
-				sscanf(optarg,"%d",&g_fec_par.mtu);
-				if(g_fec_par.mtu<100||g_fec_par.mtu>2000)
-				{
-					mylog(log_fatal,"fec_mtu should be between 100 and 2000\n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"out-addr")==0)
-			{
-			    //has_b = true;
-			    mylog(log_debug,"out-addr=%s\n",optarg);
-			    out_addr=new address_t();
-			    out_addr->from_str(optarg);
-			}
-			else if(strcmp(long_options[option_index].name,"out-interface")==0)
-			{
-			    out_interface=new char[strlen(optarg)+10];
-				sscanf(optarg,"%s\n",out_interface);
-				mylog(log_debug,"out-interface=%s\n",out_interface);
-				if(strlen(out_interface)==0)
-				{
-					mylog(log_fatal,"out_interface string len=0??\n");
-					myexit(-1);
-				}
-			}
-			else if(strcmp(long_options[option_index].name,"timeout")==0)
-			{
-				sscanf(optarg,"%d",&g_fec_par.timeout);
-				if(g_fec_par.timeout<0||g_fec_par.timeout>1000)
-				{
-
-						mylog(log_fatal,"fec_pending_time should be between 0 and 1000(1s)\n");
-						myexit(-1);
-				}
-				g_fec_par.timeout*=1000;
-			}
-			else if(strcmp(long_options[option_index].name,"debug-fec-enc")==0)
-			{
-				debug_fec_enc=1;
-				mylog(log_info,"debug_fec_enc enabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"debug-fec-dec")==0)
-			{
-				debug_fec_dec=1;
-				mylog(log_info,"debug_fec_dec enabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"fifo")==0)
-			{
-				sscanf(optarg,"%s",fifo_file);
-
-				mylog(log_info,"fifo_file =%s \n",fifo_file);
-			}
-			else if(strcmp(long_options[option_index].name,"keep-reconnect")==0)
-			{
-				keep_reconnect=1;
-				mylog(log_info,"keep_reconnect enabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"manual-set-tun")==0)
-			{
-				manual_set_tun=1;
-				mylog(log_info,"manual_set_tun enabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"persist-tun")==0)
-			{
-				persist_tun=1;
-				mylog(log_info,"persist_tun enabled\n");
-			}
-			else if(strcmp(long_options[option_index].name,"sub-net")==0)
-			{
-				sscanf(optarg,"%s",sub_net);
-				mylog(log_info,"sub_net %s\n",sub_net);
-
-			}
-			else if(strcmp(long_options[option_index].name,"tun-dev")==0)
-			{
-				sscanf(optarg,"%s",tun_dev);
-				mylog(log_info,"tun_dev=%s\n",tun_dev);
-
-			}
-			else if(strcmp(long_options[option_index].name,"tun-mtu")==0)
-			{
-				sscanf(optarg,"%d",&tun_mtu);
-				mylog(log_warn,"changed tun_mtu,tun_mtu=%d\n",tun_mtu);
-			}
-			else if(strcmp(long_options[option_index].name,"header-overhead")==0)
-			{
-				sscanf(optarg,"%d",&header_overhead);
-				mylog(log_warn,"changed header_overhead,header_overhead=%d\n",header_overhead);
-			}
-			else if(strcmp(long_options[option_index].name,"mssfix")==0)
-			{
-				sscanf(optarg,"%d",&mssfix);
-				mylog(log_warn,"mssfix=%d\n",mssfix);
-			}
-			else
-			{
-				mylog(log_fatal,"unknown option\n");
-				myexit(-1);
-			}
-			break;
-		default:
-			mylog(log_fatal,"unknown option <%x>", opt);
-			myexit(-1);
-		}
-	}
-
-	if (is_client == 0 && is_server == 0)
-	{
-		mylog(log_fatal,"-s -c hasnt been set\n");
-		myexit(-1);
-	}
-	if (is_client == 1 && is_server == 1)
-	{
-		mylog(log_fatal,"-s -c cant be both set\n");
-		myexit(-1);
-	}
-	if(is_client==1)
-	{
-		program_mode=client_mode;
-	}
-	else
-	{
-		program_mode=server_mode;
-	}
-
-
-	if(working_mode==tunnel_mode)
-	{
-		if (no_l)
-			mylog(log_fatal,"error: -l not found\n");
-		if (no_r)
-			mylog(log_fatal,"error: -r not found\n");
-		if (no_l || no_r)
-			myexit(-1);
-	}
-	else if(working_mode==tun_dev_mode)
-	{
-		if(program_mode==client_mode&&no_r)
-		{
-			mylog(log_fatal,"error: -r not found\n");
-			myexit(-1);
-		}
-		else if(program_mode==server_mode&&no_l)
-		{
-			mylog(log_fatal,"error: -l not found\n");
-			myexit(-1);
-		}
-	}
-
-	int ret=g_fec_par.rs_from_str(rs_par_str);
-	if(ret!=0)
-	{
-		mylog(log_fatal,"failed to parse [%s]\n",rs_par_str);
-		myexit(-1);
-	}
-
-	print_parameter();
-
+    assert(g_fec_par.rs_from_str(rs_par_str) == 0);
+
+    for (i = 0; i < argc; i++) {
+        if (strcmp(argv[i], "--unit-test") == 0) {
+            unit_test();
+            myexit(0);
+        }
+    }
+
+    for (i = 0; i < argc; i++) {
+        if (strcmp(argv[i], "--log-level") == 0) {
+            if (i < argc - 1) {
+                sscanf(argv[i + 1], "%d", &log_level);
+                if (0 <= log_level && log_level < log_end) {
+                } else {
+                    log_bare(log_fatal, "invalid log_level\n");
+                    myexit(-1);
+                }
+            }
+        }
+        if (strcmp(argv[i], "--enable-color") == 0) {
+            enable_log_color = 1;
+        }
+        if (strcmp(argv[i], "--disable-color") == 0) {
+            enable_log_color = 0;
+        }
+    }
+
+    mylog(log_info, "argc=%d ", argc);
+
+    for (i = 0; i < argc; i++) {
+        log_bare(log_info, "%s ", argv[i]);
+    }
+    log_bare(log_info, "\n");
+
+    int no_l = 1, no_r = 1;
+    while ((opt = getopt_long(argc, argv, "l:r:hcsk:j:f:p:n:i:q:", long_options, &option_index)) != -1) {
+        // string opt_key;
+        // opt_key+=opt;
+        switch (opt) {
+            case 'k':
+                sscanf(optarg, "%s\n", key_string);
+                mylog(log_debug, "key=%s\n", key_string);
+                if (strlen(key_string) == 0) {
+                    mylog(log_fatal, "key len=0??\n");
+                    myexit(-1);
+                }
+                break;
+            case 'j':
+                if (strchr(optarg, ':') == 0) {
+                    int jitter;
+                    sscanf(optarg, "%d\n", &jitter);
+                    if (jitter < 0 || jitter > 1000 * 10) {
+                        mylog(log_fatal, "jitter must be between 0 and 10,000(10 second)\n");
+                        myexit(-1);
+                    }
+                    jitter_min = 0;
+                    jitter_max = jitter;
+
+                } else {
+                    sscanf(optarg, "%d:%d\n", &jitter_min, &jitter_max);
+                    if (jitter_min < 0 || jitter_max < 0 || jitter_min > jitter_max) {
+                        mylog(log_fatal, " must satisfy  0<=jmin<=jmax\n");
+                        myexit(-1);
+                    }
+                }
+                jitter_min *= 1000;
+                jitter_max *= 1000;
+                break;
+            case 'i':
+                if (strchr(optarg, ':') == 0) {
+                    int output_interval = -1;
+                    sscanf(optarg, "%d\n", &output_interval);
+                    if (output_interval < 0 || output_interval > 1000 * 10) {
+                        mylog(log_fatal, "output_interval must be between 0 and 10,000(10 second)\n");
+                        myexit(-1);
+                    }
+                    output_interval_min = output_interval_max = output_interval;
+                } else {
+                    sscanf(optarg, "%d:%d\n", &output_interval_min, &output_interval_max);
+                    if (output_interval_min < 0 || output_interval_max < 0 || output_interval_min > output_interval_max) {
+                        mylog(log_fatal, " must satisfy  0<=output_interval_min<=output_interval_max\n");
+                        myexit(-1);
+                    }
+                }
+                output_interval_min *= 1000;
+                output_interval_max *= 1000;
+                break;
+            case 'f':
+                if (strchr(optarg, ':') == 0) {
+                    mylog(log_fatal, "invalid format for f");
+                    myexit(-1);
+                } else {
+                    strcpy(rs_par_str, optarg);
+                    // sscanf(optarg,"%d:%d\n",&g_fec_data_num,&g_fec_redundant_num);
+                    /*
+                    if(g_fec_data_num<1 ||g_fec_redundant_num<0||g_fec_data_num+g_fec_redundant_num>254)
+                    {
+                            mylog(log_fatal,"fec_data_num<1 ||fec_redundant_num<0||fec_data_num+fec_redundant_num>254\n");
+                            myexit(-1);
+                    }*/
+                }
+                break;
+            case 'q':
+                sscanf(optarg, "%d", &g_fec_par.queue_len);
+                if (g_fec_par.queue_len < 1 || g_fec_par.queue_len > 10000) {
+                    mylog(log_fatal, "fec_pending_num should be between 1 and 10000\n");
+                    myexit(-1);
+                }
+                break;
+            case 'c':
+                is_client = 1;
+                break;
+            case 's':
+                is_server = 1;
+                break;
+            case 'l':
+                no_l = 0;
+                local_addr.from_str(optarg);
+                break;
+            case 'r':
+                no_r = 0;
+                remote_addr.from_str(optarg);
+                break;
+            case 'h':
+                break;
+            case 1:
+                if (strcmp(long_options[option_index].name, "log-level") == 0) {
+                } else if (strcmp(long_options[option_index].name, "disable-filter") == 0) {
+                    disable_replay_filter = 1;
+                    // enable_log_color=0;
+                } else if (strcmp(long_options[option_index].name, "disable-color") == 0) {
+                    // enable_log_color=0;
+                } else if (strcmp(long_options[option_index].name, "enable-color") == 0) {
+                    // enable_log_color=0;
+                } else if (strcmp(long_options[option_index].name, "disable-fec") == 0) {
+                    disable_fec = 1;
+                } else if (strcmp(long_options[option_index].name, "disable-obscure") == 0) {
+                    mylog(log_info, "obscure disabled\n");
+                    disable_obscure = 1;
+                } else if (strcmp(long_options[option_index].name, "disable-xor") == 0) {
+                    mylog(log_info, "xor disabled\n");
+                    disable_xor = 1;
+                } else if (strcmp(long_options[option_index].name, "disable-checksum") == 0) {
+                    disable_checksum = 1;
+                    mylog(log_warn, "checksum disabled\n");
+                } else if (strcmp(long_options[option_index].name, "fix-latency") == 0) {
+                    mylog(log_info, "fix-latency enabled\n");
+                    fix_latency = 1;
+                }
+
+                else if (strcmp(long_options[option_index].name, "log-position") == 0) {
+                    enable_log_position = 1;
+                } else if (strcmp(long_options[option_index].name, "random-drop") == 0) {
+                    sscanf(optarg, "%d", &random_drop);
+                    if (random_drop < 0 || random_drop > 10000) {
+                        mylog(log_fatal, "random_drop must be between 0 10000 \n");
+                        myexit(-1);
+                    }
+                    mylog(log_info, "random_drop=%d\n", random_drop);
+                } else if (strcmp(long_options[option_index].name, "delay-capacity") == 0) {
+                    sscanf(optarg, "%d", &delay_capacity);
+
+                    if (delay_capacity < 0) {
+                        mylog(log_fatal, "delay_capacity must be >=0 \n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "report") == 0) {
+                    sscanf(optarg, "%d", &report_interval);
+
+                    if (report_interval <= 0) {
+                        mylog(log_fatal, "report_interval must be >0 \n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "sock-buf") == 0) {
+                    int tmp = -1;
+                    sscanf(optarg, "%d", &tmp);
+                    if (10 <= tmp && tmp <= 10 * 1024) {
+                        socket_buf_size = tmp * 1024;
+                    } else {
+                        mylog(log_fatal, "sock-buf value must be between 1 and 10240 (kbyte) \n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "decode-buf") == 0) {
+                    sscanf(optarg, "%d", &fec_buff_num);
+                    if (fec_buff_num < 300 || fec_buff_num > 20000) {
+                        mylog(log_fatal, "decode-buf value must be between 300 and 20000 (kbyte) \n");
+                        myexit(-1);
+                    }
+                    mylog(log_info, "decode-buf=%d\n", fec_buff_num);
+                } else if (strcmp(long_options[option_index].name, "mode") == 0) {
+                    sscanf(optarg, "%d", &g_fec_par.mode);
+                    if (g_fec_par.mode != 0 && g_fec_par.mode != 1) {
+                        mylog(log_fatal, "mode should be 0 or 1\n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "mtu") == 0) {
+                    sscanf(optarg, "%d", &g_fec_par.mtu);
+                    if (g_fec_par.mtu < 100 || g_fec_par.mtu > 2000) {
+                        mylog(log_fatal, "fec_mtu should be between 100 and 2000\n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "out-addr") == 0) {
+                    // has_b = true;
+                    mylog(log_debug, "out-addr=%s\n", optarg);
+                    out_addr = new address_t();
+                    out_addr->from_str(optarg);
+                } else if (strcmp(long_options[option_index].name, "out-interface") == 0) {
+                    out_interface = new char[strlen(optarg) + 10];
+                    sscanf(optarg, "%s\n", out_interface);
+                    mylog(log_debug, "out-interface=%s\n", out_interface);
+                    if (strlen(out_interface) == 0) {
+                        mylog(log_fatal, "out_interface string len=0??\n");
+                        myexit(-1);
+                    }
+                } else if (strcmp(long_options[option_index].name, "timeout") == 0) {
+                    sscanf(optarg, "%d", &g_fec_par.timeout);
+                    if (g_fec_par.timeout < 0 || g_fec_par.timeout > 1000) {
+                        mylog(log_fatal, "fec_pending_time should be between 0 and 1000(1s)\n");
+                        myexit(-1);
+                    }
+                    g_fec_par.timeout *= 1000;
+                } else if (strcmp(long_options[option_index].name, "debug-fec-enc") == 0) {
+                    debug_fec_enc = 1;
+                    mylog(log_info, "debug_fec_enc enabled\n");
+                } else if (strcmp(long_options[option_index].name, "debug-fec-dec") == 0) {
+                    debug_fec_dec = 1;
+                    mylog(log_info, "debug_fec_dec enabled\n");
+                } else if (strcmp(long_options[option_index].name, "fifo") == 0) {
+                    sscanf(optarg, "%s", fifo_file);
+
+                    mylog(log_info, "fifo_file =%s \n", fifo_file);
+                } else if (strcmp(long_options[option_index].name, "keep-reconnect") == 0) {
+                    keep_reconnect = 1;
+                    mylog(log_info, "keep_reconnect enabled\n");
+                } else if (strcmp(long_options[option_index].name, "manual-set-tun") == 0) {
+                    manual_set_tun = 1;
+                    mylog(log_info, "manual_set_tun enabled\n");
+                } else if (strcmp(long_options[option_index].name, "persist-tun") == 0) {
+                    persist_tun = 1;
+                    mylog(log_info, "persist_tun enabled\n");
+                } else if (strcmp(long_options[option_index].name, "sub-net") == 0) {
+                    sscanf(optarg, "%s", sub_net);
+                    mylog(log_info, "sub_net %s\n", sub_net);
+
+                } else if (strcmp(long_options[option_index].name, "tun-dev") == 0) {
+                    sscanf(optarg, "%s", tun_dev);
+                    mylog(log_info, "tun_dev=%s\n", tun_dev);
+
+                } else if (strcmp(long_options[option_index].name, "tun-mtu") == 0) {
+                    sscanf(optarg, "%d", &tun_mtu);
+                    mylog(log_warn, "changed tun_mtu,tun_mtu=%d\n", tun_mtu);
+                } else if (strcmp(long_options[option_index].name, "header-overhead") == 0) {
+                    sscanf(optarg, "%d", &header_overhead);
+                    mylog(log_warn, "changed header_overhead,header_overhead=%d\n", header_overhead);
+                } else if (strcmp(long_options[option_index].name, "mssfix") == 0) {
+                    sscanf(optarg, "%d", &mssfix);
+                    mylog(log_warn, "mssfix=%d\n", mssfix);
+                } else {
+                    mylog(log_fatal, "unknown option\n");
+                    myexit(-1);
+                }
+                break;
+            default:
+                mylog(log_fatal, "unknown option <%x>", opt);
+                myexit(-1);
+        }
+    }
+
+    if (is_client == 0 && is_server == 0) {
+        mylog(log_fatal, "-s -c hasnt been set\n");
+        myexit(-1);
+    }
+    if (is_client == 1 && is_server == 1) {
+        mylog(log_fatal, "-s -c cant be both set\n");
+        myexit(-1);
+    }
+    if (is_client == 1) {
+        program_mode = client_mode;
+    } else {
+        program_mode = server_mode;
+    }
+
+    if (working_mode == tunnel_mode) {
+        if (no_l)
+            mylog(log_fatal, "error: -l not found\n");
+        if (no_r)
+            mylog(log_fatal, "error: -r not found\n");
+        if (no_l || no_r)
+            myexit(-1);
+    } else if (working_mode == tun_dev_mode) {
+        if (program_mode == client_mode && no_r) {
+            mylog(log_fatal, "error: -r not found\n");
+            myexit(-1);
+        } else if (program_mode == server_mode && no_l) {
+            mylog(log_fatal, "error: -l not found\n");
+            myexit(-1);
+        }
+    }
+
+    int ret = g_fec_par.rs_from_str(rs_par_str);
+    if (ret != 0) {
+        mylog(log_fatal, "failed to parse [%s]\n", rs_par_str);
+        myexit(-1);
+    }
+
+    print_parameter();
 }
-

+ 8 - 13
misc.h

@@ -14,8 +14,6 @@
 #include "delay_manager.h"
 #include "fec_manager.h"
 
-
-
 extern char fifo_file[1000];
 
 extern int mtu_warn;
@@ -26,7 +24,6 @@ extern int disable_checksum;
 
 extern int debug_force_flush_fec;
 
-
 extern int jitter_min;
 extern int jitter_max;
 
@@ -35,12 +32,11 @@ extern int output_interval_max;
 
 extern int fix_latency;
 
-//extern u32_t local_ip_uint32,remote_ip_uint32;
-//extern char local_ip[100], remote_ip[100];
-//extern int local_port, remote_port;
+// extern u32_t local_ip_uint32,remote_ip_uint32;
+// extern char local_ip[100], remote_ip[100];
+// extern int local_port, remote_port;
 
-
-extern address_t local_addr,remote_addr;
+extern address_t local_addr, remote_addr;
 
 extern address_t *out_addr;
 extern char *out_interface;
@@ -62,17 +58,16 @@ extern int mssfix;
 extern int manual_set_tun;
 extern int persist_tun;
 
+int from_normal_to_fec(conn_info_t &conn_info, char *data, int len, int &out_n, char **&out_arr, int *&out_len, my_time_t *&out_delay);
+int from_fec_to_normal(conn_info_t &conn_info, char *data, int len, int &out_n, char **&out_arr, int *&out_len, my_time_t *&out_delay);
 
-int from_normal_to_fec(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay);
-int from_fec_to_normal(conn_info_t & conn_info,char *data,int len,int & out_n,char **&out_arr,int *&out_len,my_time_t *&out_delay);
-
-int delay_send(my_time_t delay,const dest_t &dest,char *data,int len);
+int delay_send(my_time_t delay, const dest_t &dest, char *data, int len);
 int print_parameter();
 int handle_command(char *s);
 
 int unit_test();
 
-//void print_help();
+// void print_help();
 
 void process_arg(int argc, char *argv[]);
 

+ 0 - 1
my_ev.h

@@ -2,4 +2,3 @@
 
 #include "my_ev_common.h"
 #include "ev.h"
-

+ 7 - 5
my_ev_common.h

@@ -1,13 +1,15 @@
 
 #define EV_STANDALONE 1
-#define EV_COMMON  void *data; unsigned long long u64;
+#define EV_COMMON \
+    void *data;   \
+    unsigned long long u64;
 #define EV_COMPAT3 0
 //#define EV_VERIFY 2
 
 #if defined(__MINGW32__)
-# define EV_FD_TO_WIN32_HANDLE(fd) (fd)
-# define EV_WIN32_HANDLE_TO_FD(handle) (handle)
-# define EV_WIN32_CLOSE_FD(fd) closesocket (fd)
-# define FD_SETSIZE 4096
+#define EV_FD_TO_WIN32_HANDLE(fd) (fd)
+#define EV_WIN32_HANDLE_TO_FD(handle) (handle)
+#define EV_WIN32_CLOSE_FD(fd) closesocket(fd)
+#define FD_SETSIZE 4096
 
 #endif

+ 291 - 339
packet.cpp

@@ -5,375 +5,333 @@
  *      Author: root
  */
 
-
 #include "common.h"
 #include "log.h"
 #include "packet.h"
 #include "misc.h"
 
-int iv_min=4;
-int iv_max=32;//< 256;
-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 iv_min = 4;
+int iv_max = 32;  //< 256;
+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;
 
 typedef u64_t anti_replay_seq_t;
-int disable_replay_filter=0;
-
-int disable_obscure=0;
-int disable_xor=0;
+int disable_replay_filter = 0;
 
-int random_drop=0;
+int disable_obscure = 0;
+int disable_xor = 0;
 
-char key_string[1000]= "";
+int random_drop = 0;
 
-//int local_listen_fd=-1;
+char key_string[1000] = "";
 
+// int local_listen_fd=-1;
 
-void encrypt_0(char * input,int &len,char *key)
-{
-	int i,j;
-	if(key[0]==0) return;
-	for(i=0,j=0;i<len;i++,j++)
-	{
-		if(key[j]==0)j=0;
-		input[i]^=key[j];
-	}
+void encrypt_0(char *input, int &len, char *key) {
+    int i, j;
+    if (key[0] == 0) return;
+    for (i = 0, j = 0; i < len; i++, j++) {
+        if (key[j] == 0) j = 0;
+        input[i] ^= key[j];
+    }
 }
 
-void decrypt_0(char * input,int &len,char *key)
-{
-	int i,j;
-	if(key[0]==0) return;
-	for(i=0,j=0;i<len;i++,j++)
-	{
-		if(key[j]==0)j=0;
-		input[i]^=key[j];
-	}
+void decrypt_0(char *input, int &len, char *key) {
+    int i, j;
+    if (key[0] == 0) return;
+    for (i = 0, j = 0; i < len; i++, j++) {
+        if (key[j] == 0) j = 0;
+        input[i] ^= key[j];
+    }
+}
+int do_obscure_old(const char *input, int in_len, char *output, int &out_len) {
+    // memcpy(output,input,in_len);
+    //	out_len=in_len;
+    // return 0;
+
+    int i, j, k;
+    if (in_len > 65535 || in_len < 0)
+        return -1;
+    int iv_len = iv_min + rand() % (iv_max - iv_min);
+    get_fake_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 < in_len; i++, j++, k++) {
+        if (j == iv_len) j = 0;
+        if (key_string[k] == 0) k = 0;
+        output[iv_len + i] ^= output[j];
+        output[iv_len + i] ^= key_string[k];
+    }
+
+    out_len = iv_len + in_len + 1;
+    return 0;
 }
-int do_obscure_old(const char * input, int in_len,char *output,int &out_len)
-{
-	//memcpy(output,input,in_len);
-//	out_len=in_len;
-	//return 0;
-
-	int i, j, k;
-	if (in_len > 65535||in_len<0)
-		return -1;
-	int iv_len=iv_min+rand()%(iv_max-iv_min);
-	get_fake_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<in_len;i++,j++,k++)
-	{
-		if(j==iv_len) j=0;
-		if(key_string[k]==0)k=0;
-		output[iv_len+i]^=output[j];
-		output[iv_len+i]^=key_string[k];
-	}
 
+int do_obscure(char *data, int &len) {
+    assert(len >= 0);
+    assert(len < buf_len);
 
-	out_len=iv_len+in_len+1;
-	return 0;
-}
+    int iv_len = random_between(iv_min, iv_max);
+    get_fake_random_chars(data + len, iv_len);
+    data[iv_len + len] = (uint8_t)iv_len;
+    for (int i = 0, j = 0; i < len; i++, j++) {
+        if (j == iv_len) j = 0;
+        data[i] ^= data[len + j];
+    }
 
-int do_obscure(char * data,int &len)
-{
-	assert(len>=0);
-	assert(len<buf_len);
-
-	int iv_len=random_between(iv_min,iv_max);
-	get_fake_random_chars(data+len,iv_len);
-	data[iv_len+len]=(uint8_t)iv_len;
-	for(int i=0,j=0;i<len;i++,j++)
-	{
-		if(j==iv_len)j=0;
-		data[i]^=data[len+j];
-	}
-
-	len=len+iv_len+1;
-	return 0;
+    len = len + iv_len + 1;
+    return 0;
 }
 
-int de_obscure(char * data,int &len)
-{
-	if(len<1) return -1;
-	int iv_len=int ((uint8_t) data[len-1]);
+int de_obscure(char *data, int &len) {
+    if (len < 1) return -1;
+    int iv_len = int((uint8_t)data[len - 1]);
 
-	if(len<1+iv_len) return -1;
+    if (len < 1 + iv_len) return -1;
 
-	len=len-1-iv_len;
-	for(int i=0,j=0;i<len;i++,j++)
-	{
-		if(j==iv_len)j=0;
-		data[i]^=data[len+j];
-	}
+    len = len - 1 - iv_len;
+    for (int i = 0, j = 0; i < len; i++, j++) {
+        if (j == iv_len) j = 0;
+        data[i] ^= data[len + j];
+    }
 
-	return 0;
+    return 0;
 }
-int de_obscure_old(const char * input, int in_len,char *output,int &out_len)
-{
-	//memcpy(output,input,in_len);
-	//out_len=in_len;
-	//return 0;
-
-	int i, j, k;
-	if (in_len > 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<in_len;i++,j++,k++)
-	{
-		if(j==iv_len) j=0;
-		if(key_string[k]==0)k=0;
-		output[i]=input[iv_len+i]^input[j]^key_string[k];
-
-	}
-	dup_packet_recv_count++;
-	return 0;
+int de_obscure_old(const char *input, int in_len, char *output, int &out_len) {
+    // memcpy(output,input,in_len);
+    // out_len=in_len;
+    // return 0;
+
+    int i, j, k;
+    if (in_len > 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 < in_len; i++, j++, k++) {
+        if (j == iv_len) j = 0;
+        if (key_string[k] == 0) k = 0;
+        output[i] = input[iv_len + i] ^ input[j] ^ key_string[k];
+    }
+    dup_packet_recv_count++;
+    return 0;
 }
 
 /*
 int sendto_fd_ip_port (int fd,u32_t ip,int port,char * buf, int len,int flags)
 {
 
-	sockaddr_in tmp_sockaddr;
+        sockaddr_in tmp_sockaddr;
 
-	memset(&tmp_sockaddr,0,sizeof(tmp_sockaddr));
-	tmp_sockaddr.sin_family = AF_INET;
-	tmp_sockaddr.sin_addr.s_addr = ip;
-	tmp_sockaddr.sin_port = htons(uint16_t(port));
+        memset(&tmp_sockaddr,0,sizeof(tmp_sockaddr));
+        tmp_sockaddr.sin_family = AF_INET;
+        tmp_sockaddr.sin_addr.s_addr = ip;
+        tmp_sockaddr.sin_port = htons(uint16_t(port));
 
-	return sendto(fd, buf,
-			len , 0,
-			(struct sockaddr *) &tmp_sockaddr,
-			sizeof(tmp_sockaddr));
+        return sendto(fd, buf,
+                        len , 0,
+                        (struct sockaddr *) &tmp_sockaddr,
+                        sizeof(tmp_sockaddr));
 }*/
 
-int sendto_fd_addr (int fd,address_t addr,char * buf, int len,int flags)
-{
-
-	return sendto(fd, buf,
-			len , 0,
-			(struct sockaddr *) &addr.inner,
-			addr.get_len());
+int sendto_fd_addr(int fd, address_t addr, char *buf, int len, int flags) {
+    return sendto(fd, buf,
+                  len, 0,
+                  (struct sockaddr *)&addr.inner,
+                  addr.get_len());
 }
 /*
 int sendto_ip_port (u32_t ip,int port,char * buf, int len,int flags)
 {
-	return sendto_fd_ip_port(local_listen_fd,ip,port,buf,len,flags);
+        return sendto_fd_ip_port(local_listen_fd,ip,port,buf,len,flags);
 }*/
 
-int send_fd (int fd,char * buf, int len,int flags)
-{
-	return send(fd,buf,len,flags);
+int send_fd(int fd, char *buf, int len, int flags) {
+    return send(fd, buf, len, flags);
 }
 
-int my_send(const dest_t &dest,char *data,int len)
-{
-	if(dest.cook)
-	{
-		do_cook(data,len);
-	}
-	switch(dest.type)
-	{
-		case type_fd_addr:
-		{
-			return sendto_fd_addr(dest.inner.fd,dest.inner.fd_addr.addr,data,len,0);
-			break;
-		}
-		case type_fd64_addr:
-		{
-			if(!fd_manager.exist(dest.inner.fd64)) return -1;
-			int fd=fd_manager.to_fd(dest.inner.fd64);
-
-			return sendto_fd_addr(fd,dest.inner.fd64_addr.addr,data,len,0);
-			break;
-		}
-		case type_fd:
-		{
-			return send_fd(dest.inner.fd,data,len,0);
-			break;
-		}
-		case type_write_fd:
-		{
-			return write(dest.inner.fd,data,len);
-			break;
-		}
-		case type_fd64:
-		{
-
-			if(!fd_manager.exist(dest.inner.fd64)) return -1;
-			int fd=fd_manager.to_fd(dest.inner.fd64);
-
-			return send_fd(fd,data,len,0);
-			break;
-		}
-		/*
-		case type_fd64_ip_port_conv:
-		{
-			if(!fd_manager.exist(dest.inner.fd64)) return -1;
-			int fd=fd_manager.to_fd(dest.inner.fd64);
-
-			char *new_data;
-			int new_len;
-
-			put_conv(dest.conv,data,len,new_data,new_len);
-			return sendto_fd_ip_port(fd,dest.inner.fd64_ip_port.ip_port.ip,dest.inner.fd64_ip_port.ip_port.port,new_data,new_len,0);
-			break;
-		}*/
-
-		/*
-		case type_fd64_conv:
-		{
-			char *new_data;
-			int new_len;
-			put_conv(dest.conv,data,len,new_data,new_len);
-
-			if(!fd_manager.exist(dest.inner.fd64)) return -1;
-			int fd=fd_manager.to_fd(dest.inner.fd64);
-			return send_fd(fd,new_data,new_len,0);
-		}*/
-		/*
-		case type_fd:
-		{
-			send_fd(dest.inner.fd,data,len,0);
-			break;
-		}*/
-		default:
-			assert(0==1);
-	}
-	return 0;
+int my_send(const dest_t &dest, char *data, int len) {
+    if (dest.cook) {
+        do_cook(data, len);
+    }
+    switch (dest.type) {
+        case type_fd_addr: {
+            return sendto_fd_addr(dest.inner.fd, dest.inner.fd_addr.addr, data, len, 0);
+            break;
+        }
+        case type_fd64_addr: {
+            if (!fd_manager.exist(dest.inner.fd64)) return -1;
+            int fd = fd_manager.to_fd(dest.inner.fd64);
+
+            return sendto_fd_addr(fd, dest.inner.fd64_addr.addr, data, len, 0);
+            break;
+        }
+        case type_fd: {
+            return send_fd(dest.inner.fd, data, len, 0);
+            break;
+        }
+        case type_write_fd: {
+            return write(dest.inner.fd, data, len);
+            break;
+        }
+        case type_fd64: {
+            if (!fd_manager.exist(dest.inner.fd64)) return -1;
+            int fd = fd_manager.to_fd(dest.inner.fd64);
+
+            return send_fd(fd, data, len, 0);
+            break;
+        }
+        /*
+        case type_fd64_ip_port_conv:
+        {
+                if(!fd_manager.exist(dest.inner.fd64)) return -1;
+                int fd=fd_manager.to_fd(dest.inner.fd64);
+
+                char *new_data;
+                int new_len;
+
+                put_conv(dest.conv,data,len,new_data,new_len);
+                return sendto_fd_ip_port(fd,dest.inner.fd64_ip_port.ip_port.ip,dest.inner.fd64_ip_port.ip_port.port,new_data,new_len,0);
+                break;
+        }*/
+
+        /*
+        case type_fd64_conv:
+        {
+                char *new_data;
+                int new_len;
+                put_conv(dest.conv,data,len,new_data,new_len);
+
+                if(!fd_manager.exist(dest.inner.fd64)) return -1;
+                int fd=fd_manager.to_fd(dest.inner.fd64);
+                return send_fd(fd,new_data,new_len,0);
+        }*/
+        /*
+        case type_fd:
+        {
+                send_fd(dest.inner.fd,data,len,0);
+                break;
+        }*/
+        default:
+            assert(0 == 1);
+    }
+    return 0;
 }
 
 /*
  *  this function comes from  http://www.hackersdelight.org/hdcodetxt/crc.c.txt
  */
-unsigned int crc32h(unsigned char *message,int len) {
-	assert(len>=0);
-   int i, crc;
-   unsigned int byte, c;
-   const unsigned int g0 = 0xEDB88320,    g1 = g0>>1,
-      g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
-      g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
-
-   i = 0;
-   crc = 0xFFFFFFFF;
-   while (i!=len) {    // Get next byte.
-	   byte = message[i];
-      crc = crc ^ byte;
-      c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
-          ((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
-          ((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
-          ((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
-      crc = ((unsigned)crc >> 8) ^ c;
-      i = i + 1;
-   }
-   return ~crc;
+unsigned int crc32h(unsigned char *message, int len) {
+    assert(len >= 0);
+    int i, crc;
+    unsigned int byte, c;
+    const unsigned int g0 = 0xEDB88320, g1 = g0 >> 1,
+                       g2 = g0 >> 2, g3 = g0 >> 3, g4 = g0 >> 4, g5 = g0 >> 5,
+                       g6 = (g0 >> 6) ^ g0, g7 = ((g0 >> 6) ^ g0) >> 1;
+
+    i = 0;
+    crc = 0xFFFFFFFF;
+    while (i != len) {  // Get next byte.
+        byte = message[i];
+        crc = crc ^ byte;
+        c = ((crc << 31 >> 31) & g7) ^ ((crc << 30 >> 31) & g6) ^
+            ((crc << 29 >> 31) & g5) ^ ((crc << 28 >> 31) & g4) ^
+            ((crc << 27 >> 31) & g3) ^ ((crc << 26 >> 31) & g2) ^
+            ((crc << 25 >> 31) & g1) ^ ((crc << 24 >> 31) & g0);
+        crc = ((unsigned)crc >> 8) ^ c;
+        i = i + 1;
+    }
+    return ~crc;
 }
 
-int put_conv0(u32_t conv,const char * input,int len_in,char *&output,int &len_out)
-{
-	assert(len_in>=0);
-	static char buf[buf_len];
-	output=buf;
-	u32_t n_conv=htonl(conv);
-	memcpy(output,&n_conv,sizeof(n_conv));
-	memcpy(output+sizeof(n_conv),input,len_in);
-	u32_t crc32=crc32h((unsigned char *)output,len_in+sizeof(crc32));
-	u32_t crc32_n=htonl(crc32);
-	len_out=len_in+(int)(sizeof(n_conv))+(int)sizeof(crc32_n);
-	memcpy(output+len_in+(int)(sizeof(n_conv)),&crc32_n,sizeof(crc32_n));
-	return 0;
+int put_conv0(u32_t conv, const char *input, int len_in, char *&output, int &len_out) {
+    assert(len_in >= 0);
+    static char buf[buf_len];
+    output = buf;
+    u32_t n_conv = htonl(conv);
+    memcpy(output, &n_conv, sizeof(n_conv));
+    memcpy(output + sizeof(n_conv), input, len_in);
+    u32_t crc32 = crc32h((unsigned char *)output, len_in + sizeof(crc32));
+    u32_t crc32_n = htonl(crc32);
+    len_out = len_in + (int)(sizeof(n_conv)) + (int)sizeof(crc32_n);
+    memcpy(output + len_in + (int)(sizeof(n_conv)), &crc32_n, sizeof(crc32_n));
+    return 0;
 }
-int get_conv0(u32_t &conv,const char *input,int len_in,char *&output,int &len_out )
-{
-	assert(len_in>=0);
-	u32_t n_conv;
-	memcpy(&n_conv,input,sizeof(n_conv));
-	conv=ntohl(n_conv);
-	output=(char *)input+sizeof(n_conv);
-	u32_t crc32_n;
-	len_out=len_in-(int)sizeof(n_conv)-(int)sizeof(crc32_n);
-	if(len_out<0)
-	{
-		mylog(log_debug,"len_out<0\n");
-		return -1;
-	}
-	memcpy(&crc32_n,input+len_in-(int)sizeof(crc32_n),sizeof(crc32_n));
-	u32_t crc32=ntohl(crc32_n);
-	if(crc32!=crc32h((unsigned char *)input,len_in-(int)sizeof(crc32_n)))
-	{
-		mylog(log_debug,"crc32 check failed\n");
-		return -1;
-	}
-	return 0;
+int get_conv0(u32_t &conv, const char *input, int len_in, char *&output, int &len_out) {
+    assert(len_in >= 0);
+    u32_t n_conv;
+    memcpy(&n_conv, input, sizeof(n_conv));
+    conv = ntohl(n_conv);
+    output = (char *)input + sizeof(n_conv);
+    u32_t crc32_n;
+    len_out = len_in - (int)sizeof(n_conv) - (int)sizeof(crc32_n);
+    if (len_out < 0) {
+        mylog(log_debug, "len_out<0\n");
+        return -1;
+    }
+    memcpy(&crc32_n, input + len_in - (int)sizeof(crc32_n), sizeof(crc32_n));
+    u32_t crc32 = ntohl(crc32_n);
+    if (crc32 != crc32h((unsigned char *)input, len_in - (int)sizeof(crc32_n))) {
+        mylog(log_debug, "crc32 check failed\n");
+        return -1;
+    }
+    return 0;
 }
-int put_crc32(char * s,int &len)
-{
-	if(disable_checksum)return 0;
-	assert(len>=0);
-	//if(len<0) return -1;
-	u32_t crc32=crc32h((unsigned char *)s,len);
-	write_u32(s+len,crc32);
-	len+=sizeof(u32_t);
-
-
-	return 0;
+int put_crc32(char *s, int &len) {
+    if (disable_checksum) return 0;
+    assert(len >= 0);
+    // if(len<0) return -1;
+    u32_t crc32 = crc32h((unsigned char *)s, len);
+    write_u32(s + len, crc32);
+    len += sizeof(u32_t);
+
+    return 0;
 }
 
-int do_cook(char * data,int &len)
-{
-	put_crc32(data,len);
-	if(!disable_obscure)do_obscure(data,len);
-	if(!disable_xor)encrypt_0(data,len,key_string);
-	return 0;
+int do_cook(char *data, int &len) {
+    put_crc32(data, len);
+    if (!disable_obscure) do_obscure(data, len);
+    if (!disable_xor) encrypt_0(data, len, key_string);
+    return 0;
 }
 
-int de_cook(char * s,int &len)
-{
-	if(!disable_xor)decrypt_0(s,len,key_string);
-	if(!disable_obscure)
-	{
-		int ret=de_obscure(s,len);
-		if(ret!=0)
-		{
-			mylog(log_debug,"de_obscure fail\n");
-			return ret;
-		}
-	}
-	int ret=rm_crc32(s,len);
-	if(ret!=0)
-	{
-		mylog(log_debug,"rm_crc32 fail\n");
-		return ret;
-	}
-	return 0;
+int de_cook(char *s, int &len) {
+    if (!disable_xor) decrypt_0(s, len, key_string);
+    if (!disable_obscure) {
+        int ret = de_obscure(s, len);
+        if (ret != 0) {
+            mylog(log_debug, "de_obscure fail\n");
+            return ret;
+        }
+    }
+    int ret = rm_crc32(s, len);
+    if (ret != 0) {
+        mylog(log_debug, "rm_crc32 fail\n");
+        return ret;
+    }
+    return 0;
 }
-int rm_crc32(char * s,int &len)
-{
-	if(disable_checksum)return 0;
-	assert(len>=0);
-	len-=sizeof(u32_t);
-	if(len<0) return -1;
-	u32_t crc32_in=read_u32(s+len);
-	u32_t crc32=crc32h((unsigned char *)s,len);
-	if(crc32!=crc32_in) return -1;
-	return 0;
+int rm_crc32(char *s, int &len) {
+    if (disable_checksum) return 0;
+    assert(len >= 0);
+    len -= sizeof(u32_t);
+    if (len < 0) return -1;
+    u32_t crc32_in = read_u32(s + len);
+    u32_t crc32 = crc32h((unsigned char *)s, len);
+    if (crc32 != crc32_in) return -1;
+    return 0;
 }
 /*
 int do_obs()
@@ -381,31 +339,25 @@ int do_obs()
 
 }
 int de_obs()*/
-int put_conv(u32_t conv,const char * input,int len_in,char *&output,int &len_out)
-{
-	static char buf[buf_len];
-	output=buf;
-	u32_t n_conv=htonl(conv);
-	memcpy(output,&n_conv,sizeof(n_conv));
-	memcpy(output+sizeof(n_conv),input,len_in);
-	len_out=len_in+(int)(sizeof(n_conv));
-
-	return 0;
+int put_conv(u32_t conv, const char *input, int len_in, char *&output, int &len_out) {
+    static char buf[buf_len];
+    output = buf;
+    u32_t n_conv = htonl(conv);
+    memcpy(output, &n_conv, sizeof(n_conv));
+    memcpy(output + sizeof(n_conv), input, len_in);
+    len_out = len_in + (int)(sizeof(n_conv));
+
+    return 0;
 }
-int get_conv(u32_t &conv,const char *input,int len_in,char *&output,int &len_out )
-{
-	u32_t n_conv;
-	memcpy(&n_conv,input,sizeof(n_conv));
-	conv=ntohl(n_conv);
-	output=(char *)input+sizeof(n_conv);
-	len_out=len_in-(int)sizeof(n_conv);
-	if(len_out<0)
-	{
-		mylog(log_debug,"len_out<0\n");
-		return -1;
-	}
-	return 0;
+int get_conv(u32_t &conv, const char *input, int len_in, char *&output, int &len_out) {
+    u32_t n_conv;
+    memcpy(&n_conv, input, sizeof(n_conv));
+    conv = ntohl(n_conv);
+    output = (char *)input + sizeof(n_conv);
+    len_out = len_in - (int)sizeof(n_conv);
+    if (len_out < 0) {
+        mylog(log_debug, "len_out<0\n");
+        return -1;
+    }
+    return 0;
 }
-
-
-

+ 20 - 21
packet.h

@@ -12,7 +12,7 @@
 #include "fd_manager.h"
 
 extern int iv_min;
-extern int iv_max;//< 256;
+extern int iv_max;  //< 256;
 
 extern u64_t packet_send_count;
 extern u64_t dup_packet_send_count;
@@ -24,24 +24,23 @@ extern int random_drop;
 extern int disable_obscure;
 extern int disable_xor;
 
-
-int my_send(const dest_t &dest,char *data,int len);
-
-void encrypt_0(char * input,int &len,char *key);
-void decrypt_0(char * input,int &len,char *key);
-int add_seq(char * data,int &data_len );
-int remove_seq(char * data,int &data_len);
-int do_obscure(const char * input, int in_len,char *output,int &out_len);
-int de_obscure(const char * input, int in_len,char *output,int &out_len);
-
-//int sendto_fd_u64 (int fd,u64_t u64,char * buf, int len,int flags);
-int sendto_ip_port (u32_t ip,int port,char * buf, int len,int flags);
-int send_fd (int fd,char * buf, int len,int flags);
-
-int put_conv(u32_t conv,const char * input,int len_in,char *&output,int &len_out);
-int get_conv(u32_t &conv,const char *input,int len_in,char *&output,int &len_out );
-int put_crc32(char * s,int &len);
-int rm_crc32(char * s,int &len);
-int do_cook(char * data,int &len);
-int de_cook(char * s,int &len);
+int my_send(const dest_t &dest, char *data, int len);
+
+void encrypt_0(char *input, int &len, char *key);
+void decrypt_0(char *input, int &len, char *key);
+int add_seq(char *data, int &data_len);
+int remove_seq(char *data, int &data_len);
+int do_obscure(const char *input, int in_len, char *output, int &out_len);
+int de_obscure(const char *input, int in_len, char *output, int &out_len);
+
+// int sendto_fd_u64 (int fd,u64_t u64,char * buf, int len,int flags);
+int sendto_ip_port(u32_t ip, int port, char *buf, int len, int flags);
+int send_fd(int fd, char *buf, int len, int flags);
+
+int put_conv(u32_t conv, const char *input, int len_in, char *&output, int &len_out);
+int get_conv(u32_t &conv, const char *input, int len_in, char *&output, int &len_out);
+int put_crc32(char *s, int &len);
+int rm_crc32(char *s, int &len);
+int do_cook(char *data, int &len);
+int de_cook(char *s, int &len);
 #endif /* PACKET_H_ */

+ 0 - 1
tunnel.h

@@ -8,7 +8,6 @@
 #ifndef TUNNEL_H_
 #define TUNNEL_H_
 
-
 #include "misc.h"
 
 int tunnel_client_event_loop();

+ 357 - 388
tunnel_client.cpp

@@ -1,453 +1,422 @@
 #include "tunnel.h"
 
-void data_from_local_or_fec_timeout(conn_info_t & conn_info,int is_time_out)
-{
-	fd64_t &remote_fd64=conn_info.remote_fd64;
-	int & local_listen_fd=conn_info.local_listen_fd;
-
-	char data[buf_len];
-	int data_len;
-	address_t addr;
-	u32_t conv;
-	int  out_n;char **out_arr;int *out_len;my_time_t *out_delay;
-	dest_t dest;
-	dest.type=type_fd64;
-	dest.inner.fd64=remote_fd64;
-	dest.cook=1;
-
-	if(is_time_out)
-	{
-		//fd64_t fd64=events[idx].data.u64;
-		mylog(log_trace,"events[idx].data.u64 == conn_info.fec_encode_manager.get_timer_fd64()\n");
-
-		//uint64_t value;
-		//if(!fd_manager.exist(fd64))   //fd64 has been closed
-		//{
-		//	mylog(log_trace,"!fd_manager.exist(fd64)");
-		//	continue;
-		//}
-		//if((ret=read(fd_manager.to_fd(fd64), &value, 8))!=8)
-		//{
-		//	mylog(log_trace,"(ret=read(fd_manager.to_fd(fd64), &value, 8))!=8,ret=%d\n",ret);
-		//	continue;
-		//}
-		//if(value==0)
-		//{
-		//	mylog(log_debug,"value==0\n");
-		//	continue;
-		//}
-		//assert(value==1);
-		from_normal_to_fec(conn_info,0,0,out_n,out_arr,out_len,out_delay);
-	}
-	else//events[idx].data.u64 == (u64_t)local_listen_fd
-	{
-		mylog(log_trace,"events[idx].data.u64 == (u64_t)local_listen_fd\n");
-		address_t::storage_t udp_new_addr_in={0};
-		socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
-		if ((data_len = recvfrom(local_listen_fd, data, max_data_len+1, 0,
-				(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
-			mylog(log_debug,"recv_from error,this shouldnt happen,err=%s,but we can try to continue\n",get_sock_error());
-			return;
-		};
-
-		if(data_len==max_data_len+1)
-		{
-			mylog(log_warn,"huge packet from upper level, data_len > %d, packet truncated, dropped\n",max_data_len);
-			return ;
-		}
-
-		if(!disable_mtu_warn&&data_len>=mtu_warn)
-		{
-			mylog(log_warn,"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ",data_len,mtu_warn);
-		}
-
-
-		addr.from_sockaddr((struct sockaddr *) &udp_new_addr_in,udp_new_addr_len);
-
-		mylog(log_trace,"Received packet from %s, len: %d\n", addr.get_str(),data_len);
-
-		//u64_t u64=ip_port.to_u64();
-
-		if(!conn_info.conv_manager.c.is_data_used(addr))
-		{
-			if(conn_info.conv_manager.c.get_size() >=max_conv_num)
-			{
-				mylog(log_warn,"ignored new udp connect bc max_conv_num exceed\n");
-				return;
-			}
-			conv=conn_info.conv_manager.c.get_new_conv();
-			conn_info.conv_manager.c.insert_conv(conv,addr);
-			mylog(log_info,"new packet from %s,conv_id=%x\n",addr.get_str(),conv);
-		}
-		else
-		{
-			conv=conn_info.conv_manager.c.find_conv_by_data(addr);
-			mylog(log_trace,"conv=%d\n",conv);
-		}
-		conn_info.conv_manager.c.update_active_time(conv);
-		char * new_data;
-		int new_len;
-		put_conv(conv,data,data_len,new_data,new_len);
-
-
-		mylog(log_trace,"data_len=%d new_len=%d\n",data_len,new_len);
-		from_normal_to_fec(conn_info,new_data,new_len,out_n,out_arr,out_len,out_delay);
-
-	}
-	mylog(log_trace,"out_n=%d\n",out_n);
-	for(int i=0;i<out_n;i++)
-	{
-		delay_send(out_delay[i],dest,out_arr[i],out_len[i]);
-	}
+void data_from_local_or_fec_timeout(conn_info_t &conn_info, int is_time_out) {
+    fd64_t &remote_fd64 = conn_info.remote_fd64;
+    int &local_listen_fd = conn_info.local_listen_fd;
+
+    char data[buf_len];
+    int data_len;
+    address_t addr;
+    u32_t conv;
+    int out_n;
+    char **out_arr;
+    int *out_len;
+    my_time_t *out_delay;
+    dest_t dest;
+    dest.type = type_fd64;
+    dest.inner.fd64 = remote_fd64;
+    dest.cook = 1;
+
+    if (is_time_out) {
+        // fd64_t fd64=events[idx].data.u64;
+        mylog(log_trace, "events[idx].data.u64 == conn_info.fec_encode_manager.get_timer_fd64()\n");
+
+        // uint64_t value;
+        // if(!fd_manager.exist(fd64))   //fd64 has been closed
+        //{
+        //	mylog(log_trace,"!fd_manager.exist(fd64)");
+        //	continue;
+        // }
+        // if((ret=read(fd_manager.to_fd(fd64), &value, 8))!=8)
+        //{
+        //	mylog(log_trace,"(ret=read(fd_manager.to_fd(fd64), &value, 8))!=8,ret=%d\n",ret);
+        //	continue;
+        // }
+        // if(value==0)
+        //{
+        //	mylog(log_debug,"value==0\n");
+        //	continue;
+        // }
+        // assert(value==1);
+        from_normal_to_fec(conn_info, 0, 0, out_n, out_arr, out_len, out_delay);
+    } else  // events[idx].data.u64 == (u64_t)local_listen_fd
+    {
+        mylog(log_trace, "events[idx].data.u64 == (u64_t)local_listen_fd\n");
+        address_t::storage_t udp_new_addr_in = {0};
+        socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
+        if ((data_len = recvfrom(local_listen_fd, data, max_data_len + 1, 0,
+                                 (struct sockaddr *)&udp_new_addr_in, &udp_new_addr_len)) == -1) {
+            mylog(log_debug, "recv_from error,this shouldnt happen,err=%s,but we can try to continue\n", get_sock_error());
+            return;
+        };
+
+        if (data_len == max_data_len + 1) {
+            mylog(log_warn, "huge packet from upper level, data_len > %d, packet truncated, dropped\n", max_data_len);
+            return;
+        }
+
+        if (!disable_mtu_warn && data_len >= mtu_warn) {
+            mylog(log_warn, "huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ", data_len, mtu_warn);
+        }
+
+        addr.from_sockaddr((struct sockaddr *)&udp_new_addr_in, udp_new_addr_len);
+
+        mylog(log_trace, "Received packet from %s, len: %d\n", addr.get_str(), data_len);
+
+        // u64_t u64=ip_port.to_u64();
+
+        if (!conn_info.conv_manager.c.is_data_used(addr)) {
+            if (conn_info.conv_manager.c.get_size() >= max_conv_num) {
+                mylog(log_warn, "ignored new udp connect bc max_conv_num exceed\n");
+                return;
+            }
+            conv = conn_info.conv_manager.c.get_new_conv();
+            conn_info.conv_manager.c.insert_conv(conv, addr);
+            mylog(log_info, "new packet from %s,conv_id=%x\n", addr.get_str(), conv);
+        } else {
+            conv = conn_info.conv_manager.c.find_conv_by_data(addr);
+            mylog(log_trace, "conv=%d\n", conv);
+        }
+        conn_info.conv_manager.c.update_active_time(conv);
+        char *new_data;
+        int new_len;
+        put_conv(conv, data, data_len, new_data, new_len);
+
+        mylog(log_trace, "data_len=%d new_len=%d\n", data_len, new_len);
+        from_normal_to_fec(conn_info, new_data, new_len, out_n, out_arr, out_len, out_delay);
+    }
+    mylog(log_trace, "out_n=%d\n", out_n);
+    for (int i = 0; i < out_n; i++) {
+        delay_send(out_delay[i], dest, out_arr[i], out_len[i]);
+    }
 }
-static void local_listen_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void local_listen_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
 
-	data_from_local_or_fec_timeout(conn_info,0);
+    data_from_local_or_fec_timeout(conn_info, 0);
 }
 
-static void remote_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void remote_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
+
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
+
+    char data[buf_len];
+    if (!fd_manager.exist(watcher->u64))  // fd64 has been closed
+    {
+        mylog(log_trace, "!fd_manager.exist(events[idx].data.u64)");
+        return;
+    }
+    fd64_t &remote_fd64 = conn_info.remote_fd64;
+    int &remote_fd = conn_info.remote_fd;
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
+    assert(watcher->u64 == remote_fd64);
 
-	char data[buf_len];
-	if(!fd_manager.exist(watcher->u64))   //fd64 has been closed
-	{
-		mylog(log_trace,"!fd_manager.exist(events[idx].data.u64)");
-		return;
-	}
-	fd64_t &remote_fd64=conn_info.remote_fd64;
-	int &remote_fd=conn_info.remote_fd;
+    int fd = fd_manager.to_fd(remote_fd64);
 
-	assert(watcher->u64==remote_fd64);
+    int data_len = recv(fd, data, max_data_len + 1, 0);
 
-	int fd=fd_manager.to_fd(remote_fd64);
+    if (data_len == max_data_len + 1) {
+        mylog(log_warn, "huge packet, data_len > %d, packet truncated, dropped\n", max_data_len);
+        return;
+    }
 
-	int data_len =recv(fd,data,max_data_len+1,0);
+    mylog(log_trace, "received data from udp fd %d, len=%d\n", remote_fd, data_len);
+    if (data_len < 0) {
+        if (get_sock_errno() == ECONNREFUSED) {
+            mylog(log_debug, "recv failed %d ,udp_fd%d,errno:%s\n", data_len, remote_fd, get_sock_error());
+        }
 
-	if(data_len==max_data_len+1)
-        {
-                mylog(log_warn,"huge packet, data_len > %d, packet truncated, dropped\n",max_data_len);
-                return ;
+        mylog(log_warn, "recv failed %d ,udp_fd%d,errno:%s\n", data_len, remote_fd, get_sock_error());
+        return;
+    }
+    if (!disable_mtu_warn && data_len > mtu_warn) {
+        mylog(log_warn, "huge packet,data len=%d (>%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ", data_len, mtu_warn);
+    }
+
+    if (de_cook(data, data_len) != 0) {
+        mylog(log_debug, "de_cook error");
+        return;
+    }
+
+    int out_n;
+    char **out_arr;
+    int *out_len;
+    my_time_t *out_delay;
+    from_fec_to_normal(conn_info, data, data_len, out_n, out_arr, out_len, out_delay);
+
+    mylog(log_trace, "out_n=%d\n", out_n);
+
+    for (int i = 0; i < out_n; i++) {
+        u32_t conv;
+        char *new_data;
+        int new_len;
+        if (get_conv(conv, out_arr[i], out_len[i], new_data, new_len) != 0) {
+            mylog(log_debug, "get_conv(conv,out_arr[i],out_len[i],new_data,new_len)!=0");
+            continue;
+        }
+        if (!conn_info.conv_manager.c.is_conv_used(conv)) {
+            mylog(log_trace, "!conn_info.conv_manager.is_conv_used(conv)");
+            continue;
         }
 
+        conn_info.conv_manager.c.update_active_time(conv);
+
+        address_t addr = conn_info.conv_manager.c.find_data_by_conv(conv);
+        dest_t dest;
+        dest.inner.fd_addr.fd = conn_info.local_listen_fd;
+        dest.inner.fd_addr.addr = addr;
+        dest.type = type_fd_addr;
 
-	mylog(log_trace, "received data from udp fd %d, len=%d\n", remote_fd,data_len);
-	if(data_len<0)
-	{
-		if(get_sock_errno()==ECONNREFUSED)
-		{
-			mylog(log_debug, "recv failed %d ,udp_fd%d,errno:%s\n", data_len,remote_fd,get_sock_error());
-		}
-
-		mylog(log_warn, "recv failed %d ,udp_fd%d,errno:%s\n", data_len,remote_fd,get_sock_error());
-		return;
-	}
-	if(!disable_mtu_warn&&data_len>mtu_warn)
-	{
-		mylog(log_warn,"huge packet,data len=%d (>%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ",data_len,mtu_warn);
-	}
-
-	if(de_cook(data,data_len)!=0)
-	{
-		mylog(log_debug,"de_cook error");
-		return;
-	}
-
-	int  out_n;char **out_arr;int *out_len;my_time_t *out_delay;
-	from_fec_to_normal(conn_info,data,data_len,out_n,out_arr,out_len,out_delay);
-
-	mylog(log_trace,"out_n=%d\n",out_n);
-
-	for(int i=0;i<out_n;i++)
-	{
-		u32_t conv;
-		char *new_data;
-		int new_len;
-		if(get_conv(conv,out_arr[i],out_len[i],new_data,new_len)!=0)
-		{
-			mylog(log_debug,"get_conv(conv,out_arr[i],out_len[i],new_data,new_len)!=0");
-			continue;
-		}
-		if(!conn_info.conv_manager.c.is_conv_used(conv))
-		{
-			mylog(log_trace,"!conn_info.conv_manager.is_conv_used(conv)");
-			continue;
-		}
-
-		conn_info.conv_manager.c.update_active_time(conv);
-
-		address_t addr=conn_info.conv_manager.c.find_data_by_conv(conv);
-		dest_t dest;
-		dest.inner.fd_addr.fd=conn_info.local_listen_fd;
-		dest.inner.fd_addr.addr=addr;
-		dest.type=type_fd_addr;
-
-		delay_send(out_delay[i],dest,new_data,new_len);
-	}
+        delay_send(out_delay[i], dest, new_data, new_len);
+    }
 }
 
-static void fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
-	int fifo_fd=watcher->fd;
-
-	char buf[buf_len];
-	int len=read (fifo_fd, buf, sizeof (buf));
-	if(len<0)
-	{
-		mylog(log_warn,"fifo read failed len=%d,errno=%s\n",len,get_sock_error());
-		return;
-	}
-	buf[len]=0;
-	handle_command(buf);
+static void fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
+    int fifo_fd = watcher->fd;
+
+    char buf[buf_len];
+    int len = read(fifo_fd, buf, sizeof(buf));
+    if (len < 0) {
+        mylog(log_warn, "fifo read failed len=%d,errno=%s\n", len, get_sock_error());
+        return;
+    }
+    buf[len] = 0;
+    handle_command(buf);
 }
 
-static void delay_manager_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void delay_manager_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	//uint64_t value;
-	//read(delay_manager.get_timer_fd(), &value, 8);
-	//mylog(log_trace,"events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()\n");
+    // uint64_t value;
+    // read(delay_manager.get_timer_fd(), &value, 8);
+    // mylog(log_trace,"events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()\n");
 
-	//do nothing
+    // do nothing
 }
 
-static void fec_encode_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void fec_encode_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
-
-	data_from_local_or_fec_timeout(conn_info,1);
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
 
+    data_from_local_or_fec_timeout(conn_info, 1);
 }
 
-static void conn_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
-
-	uint64_t value;
-
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
-
-	//read(conn_info.timer.get_timer_fd(), &value, 8);
-	conn_info.conv_manager.c.clear_inactive();
-	mylog(log_trace,"events[idx].data.u64==(u64_t)conn_info.timer.get_timer_fd()\n");
-
-	conn_info.stat.report_as_client();
-
-	if(debug_force_flush_fec)
-	{
-		int  out_n;char **out_arr;int *out_len;my_time_t *out_delay;
-		dest_t dest;
-		dest.type=type_fd64;
-		dest.inner.fd64=conn_info.remote_fd64;
-		dest.cook=1;
-		from_normal_to_fec(conn_info,0,0,out_n,out_arr,out_len,out_delay);
-		for(int i=0;i<out_n;i++)
-		{
-			delay_send(out_delay[i],dest,out_arr[i],out_len[i]);
-		}
-	}
-}
+static void conn_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
+
+    uint64_t value;
 
-static void prepare_cb(struct ev_loop *loop, struct ev_prepare *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
 
-	delay_manager.check();
+    // read(conn_info.timer.get_timer_fd(), &value, 8);
+    conn_info.conv_manager.c.clear_inactive();
+    mylog(log_trace, "events[idx].data.u64==(u64_t)conn_info.timer.get_timer_fd()\n");
+
+    conn_info.stat.report_as_client();
+
+    if (debug_force_flush_fec) {
+        int out_n;
+        char **out_arr;
+        int *out_len;
+        my_time_t *out_delay;
+        dest_t dest;
+        dest.type = type_fd64;
+        dest.inner.fd64 = conn_info.remote_fd64;
+        dest.cook = 1;
+        from_normal_to_fec(conn_info, 0, 0, out_n, out_arr, out_len, out_delay);
+        for (int i = 0; i < out_n; i++) {
+            delay_send(out_delay[i], dest, out_arr[i], out_len[i]);
+        }
+    }
 }
 
-int tunnel_client_event_loop()
-{
-	int i, j, k;int ret;
-	int yes = 1;
-	//int epoll_fd;
+static void prepare_cb(struct ev_loop *loop, struct ev_prepare *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
+    delay_manager.check();
+}
+
+int tunnel_client_event_loop() {
+    int i, j, k;
+    int ret;
+    int yes = 1;
+    // int epoll_fd;
 
-    conn_info_t *conn_info_p=new conn_info_t;
-    conn_info_t &conn_info=*conn_info_p;  //huge size of conn_info,do not allocate on stack
+    conn_info_t *conn_info_p = new conn_info_t;
+    conn_info_t &conn_info = *conn_info_p;  // huge size of conn_info,do not allocate on stack
 
-	int &local_listen_fd=conn_info.local_listen_fd;
-    new_listen_socket2(local_listen_fd,local_addr);
+    int &local_listen_fd = conn_info.local_listen_fd;
+    new_listen_socket2(local_listen_fd, local_addr);
 
-	//epoll_fd = epoll_create1(0);
-	//assert(epoll_fd>0);
+    // epoll_fd = epoll_create1(0);
+    // assert(epoll_fd>0);
 
-	//const int max_events = 4096;
-	//struct epoll_event ev, events[max_events];
-	//if (epoll_fd < 0) {
-	//	mylog(log_fatal,"epoll return %d\n", epoll_fd);
-	//	myexit(-1);
-	//}
+    // const int max_events = 4096;
+    // struct epoll_event ev, events[max_events];
+    // if (epoll_fd < 0) {
+    //	mylog(log_fatal,"epoll return %d\n", epoll_fd);
+    //	myexit(-1);
+    // }
 
-	struct ev_loop * loop= ev_default_loop(0);
-	assert(loop != NULL);
+    struct ev_loop *loop = ev_default_loop(0);
+    assert(loop != NULL);
 
-	conn_info.loop=loop;
+    conn_info.loop = loop;
 
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = local_listen_fd;
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, local_listen_fd, &ev);
-	//if (ret!=0) {
-	//	mylog(log_fatal,"add  udp_listen_fd error\n");
-	//	myexit(-1);
-	//}
-	struct ev_io local_listen_watcher;
-	local_listen_watcher.data=&conn_info;
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = local_listen_fd;
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, local_listen_fd, &ev);
+    // if (ret!=0) {
+    //	mylog(log_fatal,"add  udp_listen_fd error\n");
+    //	myexit(-1);
+    // }
+    struct ev_io local_listen_watcher;
+    local_listen_watcher.data = &conn_info;
 
     ev_io_init(&local_listen_watcher, local_listen_cb, local_listen_fd, EV_READ);
     ev_io_start(loop, &local_listen_watcher);
 
-    int & remote_fd=conn_info.remote_fd;
-    fd64_t &remote_fd64=conn_info.remote_fd64;
+    int &remote_fd = conn_info.remote_fd;
+    fd64_t &remote_fd64 = conn_info.remote_fd64;
 
-	assert(new_connected_socket2(remote_fd,remote_addr,out_addr,out_interface)==0);
-	remote_fd64=fd_manager.create(remote_fd);
+    assert(new_connected_socket2(remote_fd, remote_addr, out_addr, out_interface) == 0);
+    remote_fd64 = fd_manager.create(remote_fd);
 
-	mylog(log_debug,"remote_fd64=%llu\n",remote_fd64);
+    mylog(log_debug, "remote_fd64=%llu\n", remote_fd64);
 
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = remote_fd64;
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = remote_fd64;
 
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, remote_fd, &ev);
-	//if (ret!= 0) {
-	//	mylog(log_fatal,"add raw_fd error\n");
-	//	myexit(-1);
-	//}
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, remote_fd, &ev);
+    // if (ret!= 0) {
+    //	mylog(log_fatal,"add raw_fd error\n");
+    //	myexit(-1);
+    // }
 
-	struct ev_io remote_watcher;
-	remote_watcher.data=&conn_info;
-	remote_watcher.u64=remote_fd64;
+    struct ev_io remote_watcher;
+    remote_watcher.data = &conn_info;
+    remote_watcher.u64 = remote_fd64;
 
     ev_io_init(&remote_watcher, remote_cb, remote_fd, EV_READ);
     ev_io_start(loop, &remote_watcher);
 
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = delay_manager.get_timer_fd();
 
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = delay_manager.get_timer_fd();
-
-	//mylog(log_debug,"delay_manager.get_timer_fd()=%d\n",delay_manager.get_timer_fd());
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, delay_manager.get_timer_fd(), &ev);
-	//if (ret!= 0) {
-	//	mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
-	//	myexit(-1);
-	//}
+    // mylog(log_debug,"delay_manager.get_timer_fd()=%d\n",delay_manager.get_timer_fd());
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, delay_manager.get_timer_fd(), &ev);
+    // if (ret!= 0) {
+    //	mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
+    //	myexit(-1);
+    // }
 
-    delay_manager.set_loop_and_cb(loop,delay_manager_cb);
+    delay_manager.set_loop_and_cb(loop, delay_manager_cb);
 
     conn_info.fec_encode_manager.set_data(&conn_info);
-    conn_info.fec_encode_manager.set_loop_and_cb(loop,fec_encode_cb);
-
-	//u64_t tmp_fd64=conn_info.fec_encode_manager.get_timer_fd64();
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = tmp_fd64;
-
-	//mylog(log_debug,"conn_info.fec_encode_manager.get_timer_fd64()=%llu\n",conn_info.fec_encode_manager.get_timer_fd64());
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd_manager.to_fd(tmp_fd64), &ev);
-	//if (ret!= 0) {
-	//	mylog(log_fatal,"add fec_encode_manager.get_timer_fd64() error\n");
-	//	myexit(-1);
-	//}
-
-    conn_info.timer.data=&conn_info;
-    ev_init(&conn_info.timer,conn_timer_cb);
-    ev_timer_set(&conn_info.timer, 0, timer_interval/1000.0 );
-    ev_timer_start(loop,&conn_info.timer);
-	//conn_info.timer.add_fd_to_epoll(epoll_fd);
-	//conn_info.timer.set_timer_repeat_us(timer_interval*1000);
+    conn_info.fec_encode_manager.set_loop_and_cb(loop, fec_encode_cb);
 
-	//mylog(log_debug,"conn_info.timer.get_timer_fd()=%d\n",conn_info.timer.get_timer_fd());
+    // u64_t tmp_fd64=conn_info.fec_encode_manager.get_timer_fd64();
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = tmp_fd64;
 
+    // mylog(log_debug,"conn_info.fec_encode_manager.get_timer_fd64()=%llu\n",conn_info.fec_encode_manager.get_timer_fd64());
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd_manager.to_fd(tmp_fd64), &ev);
+    // if (ret!= 0) {
+    //	mylog(log_fatal,"add fec_encode_manager.get_timer_fd64() error\n");
+    //	myexit(-1);
+    // }
 
+    conn_info.timer.data = &conn_info;
+    ev_init(&conn_info.timer, conn_timer_cb);
+    ev_timer_set(&conn_info.timer, 0, timer_interval / 1000.0);
+    ev_timer_start(loop, &conn_info.timer);
+    // conn_info.timer.add_fd_to_epoll(epoll_fd);
+    // conn_info.timer.set_timer_repeat_us(timer_interval*1000);
 
+    // mylog(log_debug,"conn_info.timer.get_timer_fd()=%d\n",conn_info.timer.get_timer_fd());
 
     struct ev_io fifo_watcher;
 
-	int fifo_fd=-1;
-
-	if(fifo_file[0]!=0)
-	{
-		fifo_fd=create_fifo(fifo_file);
-		//ev.events = EPOLLIN;
-		//ev.data.u64 = fifo_fd;
-
-		//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fifo_fd, &ev);
-		//if (ret!= 0) {
-		//	mylog(log_fatal,"add fifo_fd to epoll error %s\n",strerror(errno));
-		//	myexit(-1);
-		//}
-		mylog(log_info,"fifo_file=%s\n",fifo_file);
-
-	    ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);
-	    ev_io_start(loop, &fifo_watcher);
-
-	}
-
-	ev_prepare prepare_watcher;
-	ev_init(&prepare_watcher,prepare_cb);
-	ev_prepare_start(loop,&prepare_watcher);
-
-	mylog(log_info,"now listening at %s\n",local_addr.get_str());
-
-	ev_run(loop, 0);
-
-	mylog(log_warn,"ev_run returned\n");
-	myexit(0);
-
-	/*
-	while(1)////////////////////////
-	{
-		if(about_to_exit) myexit(0);
-
-		int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000);
-		if (nfds < 0) {  //allow zero
-			if(errno==EINTR  )
-			{
-				mylog(log_info,"epoll interrupted by signal continue\n");
-			}
-			else
-			{
-				mylog(log_fatal,"epoll_wait return %d,%s\n", nfds,strerror(errno));
-				myexit(-1);
-			}
-		}
-		int idx;
-		for (idx = 0; idx < nfds; ++idx) {
-			if(events[idx].data.u64==(u64_t)conn_info.timer.get_timer_fd())
-			{
-
-			}
-
-			else if (events[idx].data.u64 == (u64_t)fifo_fd)
-			{
-
-			}
-			else if (events[idx].data.u64 == (u64_t)local_listen_fd||events[idx].data.u64 == conn_info.fec_encode_manager.get_timer_fd64())
-			{
-
-			}
-		    else if (events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()) {
-
-			}
-			else if(events[idx].data.u64>u32_t(-1) )
-			{
-
-			}
-			else
-			{
-				mylog(log_fatal,"unknown fd,this should never happen\n");
-				myexit(-1);
-			}
-		}
-		//delay_manager.check();
-	}*/
-	return 0;
+    int fifo_fd = -1;
+
+    if (fifo_file[0] != 0) {
+        fifo_fd = create_fifo(fifo_file);
+        // ev.events = EPOLLIN;
+        // ev.data.u64 = fifo_fd;
+
+        // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fifo_fd, &ev);
+        // if (ret!= 0) {
+        //	mylog(log_fatal,"add fifo_fd to epoll error %s\n",strerror(errno));
+        //	myexit(-1);
+        // }
+        mylog(log_info, "fifo_file=%s\n", fifo_file);
+
+        ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);
+        ev_io_start(loop, &fifo_watcher);
+    }
+
+    ev_prepare prepare_watcher;
+    ev_init(&prepare_watcher, prepare_cb);
+    ev_prepare_start(loop, &prepare_watcher);
+
+    mylog(log_info, "now listening at %s\n", local_addr.get_str());
+
+    ev_run(loop, 0);
+
+    mylog(log_warn, "ev_run returned\n");
+    myexit(0);
+
+    /*
+    while(1)////////////////////////
+    {
+            if(about_to_exit) myexit(0);
+
+            int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000);
+            if (nfds < 0) {  //allow zero
+                    if(errno==EINTR  )
+                    {
+                            mylog(log_info,"epoll interrupted by signal continue\n");
+                    }
+                    else
+                    {
+                            mylog(log_fatal,"epoll_wait return %d,%s\n", nfds,strerror(errno));
+                            myexit(-1);
+                    }
+            }
+            int idx;
+            for (idx = 0; idx < nfds; ++idx) {
+                    if(events[idx].data.u64==(u64_t)conn_info.timer.get_timer_fd())
+                    {
+
+                    }
+
+                    else if (events[idx].data.u64 == (u64_t)fifo_fd)
+                    {
+
+                    }
+                    else if (events[idx].data.u64 == (u64_t)local_listen_fd||events[idx].data.u64 == conn_info.fec_encode_manager.get_timer_fd64())
+                    {
+
+                    }
+                else if (events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()) {
+
+                    }
+                    else if(events[idx].data.u64>u32_t(-1) )
+                    {
+
+                    }
+                    else
+                    {
+                            mylog(log_fatal,"unknown fd,this should never happen\n");
+                            myexit(-1);
+                    }
+            }
+            //delay_manager.check();
+    }*/
+    return 0;
 }

+ 367 - 406
tunnel_server.cpp

@@ -11,493 +11,454 @@ static void conn_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int re
 static void fec_encode_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents);
 static void remote_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
 
-enum tmp_mode_t{is_from_remote=0,is_fec_timeout,is_conn_timer};
-
-void data_from_remote_or_fec_timeout_or_conn_timer(conn_info_t & conn_info,fd64_t fd64,tmp_mode_t mode)
-{
-	int ret;
-
-	char data[buf_len];
-	int data_len;
-	u32_t conv;
-	//fd64_t fd64=events[idx].data.u64;
-	//mylog(log_trace,"events[idx].data.u64 >u32_t(-1),%llu\n",(u64_t)events[idx].data.u64);
-
-
-	//assert(fd_manager.exist_info(fd64));
-	//ip_port_t ip_port=fd_manager.get_info(fd64).ip_port;
-
-
-	//conn_info_t &conn_info=conn_manager.find(ip_port);
-	address_t &addr=conn_info.addr;
-	assert(conn_manager.exist(addr));
-
-	int &local_listen_fd=conn_info.local_listen_fd;
-
-	int  out_n=-2;char **out_arr;int *out_len;my_time_t *out_delay;
-
-	dest_t dest;
-	dest.inner.fd_addr.fd=local_listen_fd;
-	dest.inner.fd_addr.addr=addr;
-	dest.type=type_fd_addr;
-	dest.cook=1;
-
-	if(mode==is_fec_timeout)
-	{
-		assert(fd64==0);
-		//uint64_t value;
-		//if((ret=read(fd_manager.to_fd(fd64), &value, 8))!=8)
-		//{
-		//	mylog(log_trace,"fd_manager.to_fd(fd64), &value, 8)!=8 ,%d\n",ret);
-		//	continue;
-		//}
-		//if(value==0)
-		//{
-		//	mylog(log_trace,"value==0\n");
-		//	continue;
-		//}
-		//assert(value==1);
-		from_normal_to_fec(conn_info,0,0,out_n,out_arr,out_len,out_delay);
-	}
-	else if(mode==is_conn_timer)
-	{
-		assert(fd64==0);
-		//uint64_t value;
-		//read(conn_info.timer.get_timer_fd(), &value, 8);
-		conn_info.conv_manager.s.clear_inactive();
-		if(debug_force_flush_fec)
-		{
-		from_normal_to_fec(conn_info,0,0,out_n,out_arr,out_len,out_delay);
-		}
-
-		conn_info.stat.report_as_server(addr);
-		return;
-	}
-	else if(mode==is_from_remote)
-	{
-		if(!fd_manager.exist(fd64))   //fd64 has been closed
-		{
-			mylog(log_warn,"!fd_manager.exist(fd64)\n");
-			return;
-		}
-
-		//fd64_t &fd64 =conn_info.remote_fd64;
-		assert(conn_info.conv_manager.s.is_data_used(fd64));
-
-		conv=conn_info.conv_manager.s.find_conv_by_data(fd64);
-		conn_info.conv_manager.s.update_active_time(conv);
-		conn_info.update_active_time();
-
-		int fd=fd_manager.to_fd(fd64);
-		data_len=recv(fd,data,max_data_len+1,0);
-
-		if(data_len==max_data_len+1)
-		{
-			mylog(log_warn,"huge packet from upper level, data_len > %d, packet truncated, dropped\n",max_data_len);
-			return ;
-		}
-
-		mylog(log_trace,"received a packet from udp_fd,len:%d,conv=%d\n",data_len,conv);
-
-		if(data_len<0)
-		{
-			mylog(log_debug,"udp fd,recv_len<0 continue,%s\n",get_sock_error());
-
-			return;
-		}
-
-		if(!disable_mtu_warn&&data_len>=mtu_warn)
-		{
-			mylog(log_warn,"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ",data_len,mtu_warn);
-		}
-
-		char * new_data;
-		int new_len;
-		put_conv(conv,data,data_len,new_data,new_len);
-
-		from_normal_to_fec(conn_info,new_data,new_len,out_n,out_arr,out_len,out_delay);
-	}
-	else
-	{
-		assert(0==1);
-	}
-
-	mylog(log_trace,"out_n=%d\n",out_n);
-	for(int i=0;i<out_n;i++)
-	{
-		delay_send(out_delay[i],dest,out_arr[i],out_len[i]);
-	}
-}
+enum tmp_mode_t { is_from_remote = 0,
+                  is_fec_timeout,
+                  is_conn_timer };
+
+void data_from_remote_or_fec_timeout_or_conn_timer(conn_info_t &conn_info, fd64_t fd64, tmp_mode_t mode) {
+    int ret;
+
+    char data[buf_len];
+    int data_len;
+    u32_t conv;
+    // fd64_t fd64=events[idx].data.u64;
+    // mylog(log_trace,"events[idx].data.u64 >u32_t(-1),%llu\n",(u64_t)events[idx].data.u64);
+
+    // assert(fd_manager.exist_info(fd64));
+    // ip_port_t ip_port=fd_manager.get_info(fd64).ip_port;
+
+    // conn_info_t &conn_info=conn_manager.find(ip_port);
+    address_t &addr = conn_info.addr;
+    assert(conn_manager.exist(addr));
+
+    int &local_listen_fd = conn_info.local_listen_fd;
+
+    int out_n = -2;
+    char **out_arr;
+    int *out_len;
+    my_time_t *out_delay;
+
+    dest_t dest;
+    dest.inner.fd_addr.fd = local_listen_fd;
+    dest.inner.fd_addr.addr = addr;
+    dest.type = type_fd_addr;
+    dest.cook = 1;
+
+    if (mode == is_fec_timeout) {
+        assert(fd64 == 0);
+        // uint64_t value;
+        // if((ret=read(fd_manager.to_fd(fd64), &value, 8))!=8)
+        //{
+        //	mylog(log_trace,"fd_manager.to_fd(fd64), &value, 8)!=8 ,%d\n",ret);
+        //	continue;
+        // }
+        // if(value==0)
+        //{
+        //	mylog(log_trace,"value==0\n");
+        //	continue;
+        // }
+        // assert(value==1);
+        from_normal_to_fec(conn_info, 0, 0, out_n, out_arr, out_len, out_delay);
+    } else if (mode == is_conn_timer) {
+        assert(fd64 == 0);
+        // uint64_t value;
+        // read(conn_info.timer.get_timer_fd(), &value, 8);
+        conn_info.conv_manager.s.clear_inactive();
+        if (debug_force_flush_fec) {
+            from_normal_to_fec(conn_info, 0, 0, out_n, out_arr, out_len, out_delay);
+        }
 
-static void local_listen_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
-
-	int local_listen_fd=watcher->fd;
-	int ret;
-
-	mylog(log_trace,"events[idx].data.u64 == (u64_t)local_listen_fd\n");
-	char data[buf_len];
-	int data_len;
-	address_t::storage_t udp_new_addr_in={0};
-	socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
-	if ((data_len = recvfrom(local_listen_fd, data, max_data_len+1, 0,
-			(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
-		mylog(log_error,"recv_from error,this shouldnt happen,err=%s,but we can try to continue\n",get_sock_error());
-		return;
-	};
-
-	if(data_len==max_data_len+1)
+        conn_info.stat.report_as_server(addr);
+        return;
+    } else if (mode == is_from_remote) {
+        if (!fd_manager.exist(fd64))  // fd64 has been closed
         {
-                mylog(log_warn,"huge packet, data_len > %d, packet truncated, dropped\n",max_data_len);
-                return ;
+            mylog(log_warn, "!fd_manager.exist(fd64)\n");
+            return;
         }
 
-	address_t addr;
-	addr.from_sockaddr((struct sockaddr *) &udp_new_addr_in,udp_new_addr_len);
-
-	mylog(log_trace,"Received packet from %s,len: %d\n", addr.get_str(),data_len);
-
-	if(!disable_mtu_warn&&data_len>=mtu_warn)///////////////////////delete this for type 0 in furture
-	{
-		mylog(log_warn,"huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ",data_len,mtu_warn);
-	}
-
-
-	if(de_cook(data,data_len)!=0)
-	{
-		mylog(log_debug,"de_cook error");
-		return;
-	}
-
+        // fd64_t &fd64 =conn_info.remote_fd64;
+        assert(conn_info.conv_manager.s.is_data_used(fd64));
 
+        conv = conn_info.conv_manager.s.find_conv_by_data(fd64);
+        conn_info.conv_manager.s.update_active_time(conv);
+        conn_info.update_active_time();
 
-	if(!conn_manager.exist(addr))
-	{
-		if(conn_manager.mp.size() >=max_conn_num)
-		{
-			mylog(log_warn,"new connection %s ignored bc max_conn_num exceed\n",addr.get_str());
-			return;
-		}
+        int fd = fd_manager.to_fd(fd64);
+        data_len = recv(fd, data, max_data_len + 1, 0);
 
-		//conn_manager.insert(addr);
-		conn_info_t &conn_info=conn_manager.find_insert(addr);
-		conn_info.addr=addr;
-		conn_info.loop=ev_default_loop(0);
-		conn_info.local_listen_fd=local_listen_fd;
-
-		//u64_t fec_fd64=conn_info.fec_encode_manager.get_timer_fd64();
-		//mylog(log_debug,"fec_fd64=%llu\n",fec_fd64);
-		//ev.events = EPOLLIN;
-		//ev.data.u64 = fec_fd64;
-		//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd_manager.to_fd(fec_fd64), &ev);
-
-		//fd_manager.get_info(fec_fd64).ip_port=ip_port;
-
-	    conn_info.timer.data=&conn_info;
-	    ev_init(&conn_info.timer,conn_timer_cb);
-	    ev_timer_set(&conn_info.timer, 0, timer_interval/1000.0 );
-	    ev_timer_start(loop,&conn_info.timer);
-
-		//conn_info.timer.add_fd64_to_epoll(epoll_fd);
-		//conn_info.timer.set_timer_repeat_us(timer_interval*1000);
+        if (data_len == max_data_len + 1) {
+            mylog(log_warn, "huge packet from upper level, data_len > %d, packet truncated, dropped\n", max_data_len);
+            return;
+        }
 
-		//mylog(log_debug,"conn_info.timer.get_timer_fd64()=%llu\n",conn_info.timer.get_timer_fd64());
+        mylog(log_trace, "received a packet from udp_fd,len:%d,conv=%d\n", data_len, conv);
 
-		//u64_t timer_fd64=conn_info.timer.get_timer_fd64();
-		//fd_manager.get_info(timer_fd64).ip_port=ip_port;
+        if (data_len < 0) {
+            mylog(log_debug, "udp fd,recv_len<0 continue,%s\n", get_sock_error());
 
+            return;
+        }
 
+        if (!disable_mtu_warn && data_len >= mtu_warn) {
+            mylog(log_warn, "huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ", data_len, mtu_warn);
+        }
 
-	    conn_info.fec_encode_manager.set_data(&conn_info);
-	    conn_info.fec_encode_manager.set_loop_and_cb(loop,fec_encode_cb);
+        char *new_data;
+        int new_len;
+        put_conv(conv, data, data_len, new_data, new_len);
 
+        from_normal_to_fec(conn_info, new_data, new_len, out_n, out_arr, out_len, out_delay);
+    } else {
+        assert(0 == 1);
+    }
 
-		mylog(log_info,"new connection from %s\n",addr.get_str());
+    mylog(log_trace, "out_n=%d\n", out_n);
+    for (int i = 0; i < out_n; i++) {
+        delay_send(out_delay[i], dest, out_arr[i], out_len[i]);
+    }
+}
 
-	}
-	conn_info_t &conn_info=conn_manager.find_insert(addr);
+static void local_listen_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
+
+    int local_listen_fd = watcher->fd;
+    int ret;
+
+    mylog(log_trace, "events[idx].data.u64 == (u64_t)local_listen_fd\n");
+    char data[buf_len];
+    int data_len;
+    address_t::storage_t udp_new_addr_in = {0};
+    socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
+    if ((data_len = recvfrom(local_listen_fd, data, max_data_len + 1, 0,
+                             (struct sockaddr *)&udp_new_addr_in, &udp_new_addr_len)) == -1) {
+        mylog(log_error, "recv_from error,this shouldnt happen,err=%s,but we can try to continue\n", get_sock_error());
+        return;
+    };
+
+    if (data_len == max_data_len + 1) {
+        mylog(log_warn, "huge packet, data_len > %d, packet truncated, dropped\n", max_data_len);
+        return;
+    }
+
+    address_t addr;
+    addr.from_sockaddr((struct sockaddr *)&udp_new_addr_in, udp_new_addr_len);
+
+    mylog(log_trace, "Received packet from %s,len: %d\n", addr.get_str(), data_len);
+
+    if (!disable_mtu_warn && data_len >= mtu_warn)  ///////////////////////delete this for type 0 in furture
+    {
+        mylog(log_warn, "huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ", data_len, mtu_warn);
+    }
+
+    if (de_cook(data, data_len) != 0) {
+        mylog(log_debug, "de_cook error");
+        return;
+    }
+
+    if (!conn_manager.exist(addr)) {
+        if (conn_manager.mp.size() >= max_conn_num) {
+            mylog(log_warn, "new connection %s ignored bc max_conn_num exceed\n", addr.get_str());
+            return;
+        }
 
-	conn_info.update_active_time();
-	int  out_n;char **out_arr;int *out_len;my_time_t *out_delay;
-	from_fec_to_normal(conn_info,data,data_len,out_n,out_arr,out_len,out_delay);
+        // conn_manager.insert(addr);
+        conn_info_t &conn_info = conn_manager.find_insert(addr);
+        conn_info.addr = addr;
+        conn_info.loop = ev_default_loop(0);
+        conn_info.local_listen_fd = local_listen_fd;
+
+        // u64_t fec_fd64=conn_info.fec_encode_manager.get_timer_fd64();
+        // mylog(log_debug,"fec_fd64=%llu\n",fec_fd64);
+        // ev.events = EPOLLIN;
+        // ev.data.u64 = fec_fd64;
+        // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd_manager.to_fd(fec_fd64), &ev);
+
+        // fd_manager.get_info(fec_fd64).ip_port=ip_port;
+
+        conn_info.timer.data = &conn_info;
+        ev_init(&conn_info.timer, conn_timer_cb);
+        ev_timer_set(&conn_info.timer, 0, timer_interval / 1000.0);
+        ev_timer_start(loop, &conn_info.timer);
+
+        // conn_info.timer.add_fd64_to_epoll(epoll_fd);
+        // conn_info.timer.set_timer_repeat_us(timer_interval*1000);
+
+        // mylog(log_debug,"conn_info.timer.get_timer_fd64()=%llu\n",conn_info.timer.get_timer_fd64());
+
+        // u64_t timer_fd64=conn_info.timer.get_timer_fd64();
+        // fd_manager.get_info(timer_fd64).ip_port=ip_port;
+
+        conn_info.fec_encode_manager.set_data(&conn_info);
+        conn_info.fec_encode_manager.set_loop_and_cb(loop, fec_encode_cb);
+
+        mylog(log_info, "new connection from %s\n", addr.get_str());
+    }
+    conn_info_t &conn_info = conn_manager.find_insert(addr);
+
+    conn_info.update_active_time();
+    int out_n;
+    char **out_arr;
+    int *out_len;
+    my_time_t *out_delay;
+    from_fec_to_normal(conn_info, data, data_len, out_n, out_arr, out_len, out_delay);
+
+    mylog(log_trace, "out_n= %d\n", out_n);
+    for (int i = 0; i < out_n; i++) {
+        u32_t conv;
+        char *new_data;
+        int new_len;
+        if (get_conv(conv, out_arr[i], out_len[i], new_data, new_len) != 0) {
+            mylog(log_debug, "get_conv failed");
+            continue;
+        }
 
-	mylog(log_trace,"out_n= %d\n",out_n);
-	for(int i=0;i<out_n;i++)
-	{
-		u32_t conv;
-		char *new_data;
-		int new_len;
-		if(get_conv(conv,out_arr[i],out_len[i],new_data,new_len)!=0)
-		{
-			mylog(log_debug,"get_conv failed");
-			continue;
-		}
+        if (!conn_info.conv_manager.s.is_conv_used(conv)) {
+            if (conn_info.conv_manager.s.get_size() >= max_conv_num) {
+                mylog(log_warn, "ignored new udp connect bc max_conv_num exceed\n");
+                continue;
+            }
 
+            int new_udp_fd;
+            ret = new_connected_socket2(new_udp_fd, remote_addr, out_addr, out_interface);
 
-		if (!conn_info.conv_manager.s.is_conv_used(conv))
-		{
-			if(conn_info.conv_manager.s.get_size() >=max_conv_num)
-			{
-				mylog(log_warn,"ignored new udp connect bc max_conv_num exceed\n");
-				continue;
-			}
+            if (ret != 0) {
+                mylog(log_warn, "[%s]new_connected_socket failed\n", addr.get_str());
+                continue;
+            }
 
-			int new_udp_fd;
-			ret=new_connected_socket2(new_udp_fd,remote_addr,out_addr,out_interface);
+            fd64_t fd64 = fd_manager.create(new_udp_fd);
+            // ev.events = EPOLLIN;
+            // ev.data.u64 = fd64;
+            // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_udp_fd, &ev);
 
-			if (ret != 0) {
-				mylog(log_warn, "[%s]new_connected_socket failed\n",addr.get_str());
-				continue;
-			}
+            conn_info.conv_manager.s.insert_conv(conv, fd64);
+            fd_manager.get_info(fd64).addr = addr;
 
-			fd64_t fd64 = fd_manager.create(new_udp_fd);
-			//ev.events = EPOLLIN;
-			//ev.data.u64 = fd64;
-			//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, new_udp_fd, &ev);
+            ev_io &io_watcher = fd_manager.get_info(fd64).io_watcher;
+            io_watcher.u64 = fd64;
+            io_watcher.data = &conn_info;
 
-			conn_info.conv_manager.s.insert_conv(conv, fd64);
-			fd_manager.get_info(fd64).addr=addr;
+            ev_init(&io_watcher, remote_cb);
+            ev_io_set(&io_watcher, new_udp_fd, EV_READ);
+            ev_io_start(conn_info.loop, &io_watcher);
 
-			ev_io &io_watcher=fd_manager.get_info(fd64).io_watcher;
-			io_watcher.u64=fd64;
-			io_watcher.data=&conn_info;
+            mylog(log_info, "[%s]new conv %x,fd %d created,fd64=%llu\n", addr.get_str(), conv, new_udp_fd, fd64);
+        }
+        conn_info.conv_manager.s.update_active_time(conv);
+        fd64_t fd64 = conn_info.conv_manager.s.find_data_by_conv(conv);
+        dest_t dest;
+        dest.type = type_fd64;
+        dest.inner.fd64 = fd64;
+        delay_send(out_delay[i], dest, new_data, new_len);
+    }
+}
 
-			ev_init(&io_watcher,remote_cb);
-			ev_io_set(&io_watcher,new_udp_fd,EV_READ);
-			ev_io_start(conn_info.loop,&io_watcher);
+static void remote_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
+    fd64_t fd64 = watcher->u64;
 
-			mylog(log_info,"[%s]new conv %x,fd %d created,fd64=%llu\n",addr.get_str(),conv,new_udp_fd,fd64);
-		}
-		conn_info.conv_manager.s.update_active_time(conv);
-		fd64_t fd64= conn_info.conv_manager.s.find_data_by_conv(conv);
-		dest_t dest;
-		dest.type=type_fd64;
-		dest.inner.fd64=fd64;
-		delay_send(out_delay[i],dest,new_data,new_len);
-	}
+    data_from_remote_or_fec_timeout_or_conn_timer(conn_info, fd64, is_from_remote);
 }
 
-static void remote_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
-	fd64_t fd64=watcher->u64;
+    int fifo_fd = watcher->fd;
 
-	data_from_remote_or_fec_timeout_or_conn_timer(conn_info,fd64,is_from_remote);
+    char buf[buf_len];
+    int len = read(fifo_fd, buf, sizeof(buf));
+    if (len < 0) {
+        mylog(log_warn, "fifo read failed len=%d,errno=%s\n", len, get_sock_error());
+        return;
+    }
+    buf[len] = 0;
+    handle_command(buf);
 }
 
-static void fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
-
-	int fifo_fd=watcher->fd;
-
-	char buf[buf_len];
-	int len=read (fifo_fd, buf, sizeof (buf));
-	if(len<0)
-	{
-		mylog(log_warn,"fifo read failed len=%d,errno=%s\n",len,get_sock_error());
-		return;
-	}
-	buf[len]=0;
-	handle_command(buf);
-}
-
-static void delay_manager_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
-
-	//uint64_t value;
-	//read(delay_manager.get_timer_fd(), &value, 8);
-	//mylog(log_trace,"events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()\n");
+static void delay_manager_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	//do nothing
+    // uint64_t value;
+    // read(delay_manager.get_timer_fd(), &value, 8);
+    // mylog(log_trace,"events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()\n");
 
+    // do nothing
 }
 
-static void fec_encode_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void fec_encode_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
 
-	data_from_remote_or_fec_timeout_or_conn_timer(conn_info,0,is_fec_timeout);
+    data_from_remote_or_fec_timeout_or_conn_timer(conn_info, 0, is_fec_timeout);
 }
 
-static void conn_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void conn_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	conn_info_t & conn_info= *((conn_info_t*)watcher->data);
+    conn_info_t &conn_info = *((conn_info_t *)watcher->data);
 
-	data_from_remote_or_fec_timeout_or_conn_timer(conn_info,0,is_conn_timer);
+    data_from_remote_or_fec_timeout_or_conn_timer(conn_info, 0, is_conn_timer);
 }
 
-static void prepare_cb(struct ev_loop *loop, struct ev_prepare *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void prepare_cb(struct ev_loop *loop, struct ev_prepare *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	delay_manager.check();
+    delay_manager.check();
 }
 
-static void global_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)
-{
-	assert(!(revents&EV_ERROR));
+static void global_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
+    assert(!(revents & EV_ERROR));
 
-	//uint64_t value;
-	//read(timer.get_timer_fd(), &value, 8);
-	conn_manager.clear_inactive();
-	mylog(log_trace,"events[idx].data.u64==(u64_t)timer.get_timer_fd()\n");
+    // uint64_t value;
+    // read(timer.get_timer_fd(), &value, 8);
+    conn_manager.clear_inactive();
+    mylog(log_trace, "events[idx].data.u64==(u64_t)timer.get_timer_fd()\n");
 }
 
-int tunnel_server_event_loop()
-{
-
-	int i, j, k;int ret;
-	int yes = 1;
-	//int epoll_fd;
-	//int remote_fd;
-
-	int local_listen_fd;
-    new_listen_socket2(local_listen_fd,local_addr);
-
-	//epoll_fd = epoll_create1(0);
-	//assert(epoll_fd>0);
-
-	//const int max_events = 4096;
-	//struct epoll_event ev, events[max_events];
-	//if (epoll_fd < 0) {
-	//	mylog(log_fatal,"epoll return %d\n", epoll_fd);
-	//	myexit(-1);
-	//}
-
-	struct ev_loop * loop= ev_default_loop(0);
-	assert(loop != NULL);
-
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = local_listen_fd;
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, local_listen_fd, &ev);
-	//if (ret!=0) {
-	//	mylog(log_fatal,"add  udp_listen_fd error\n");
-	//	myexit(-1);
-	//}
-	struct ev_io local_listen_watcher;
+int tunnel_server_event_loop() {
+    int i, j, k;
+    int ret;
+    int yes = 1;
+    // int epoll_fd;
+    // int remote_fd;
+
+    int local_listen_fd;
+    new_listen_socket2(local_listen_fd, local_addr);
+
+    // epoll_fd = epoll_create1(0);
+    // assert(epoll_fd>0);
+
+    // const int max_events = 4096;
+    // struct epoll_event ev, events[max_events];
+    // if (epoll_fd < 0) {
+    //	mylog(log_fatal,"epoll return %d\n", epoll_fd);
+    //	myexit(-1);
+    // }
+
+    struct ev_loop *loop = ev_default_loop(0);
+    assert(loop != NULL);
+
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = local_listen_fd;
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, local_listen_fd, &ev);
+    // if (ret!=0) {
+    //	mylog(log_fatal,"add  udp_listen_fd error\n");
+    //	myexit(-1);
+    // }
+    struct ev_io local_listen_watcher;
     ev_io_init(&local_listen_watcher, local_listen_cb, local_listen_fd, EV_READ);
     ev_io_start(loop, &local_listen_watcher);
 
-	//ev.events = EPOLLIN;
-	//ev.data.u64 = delay_manager.get_timer_fd();
-	//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, delay_manager.get_timer_fd(), &ev);
-	//if (ret!= 0) {
-	//	mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
-	//	myexit(-1);
-	//}
+    // ev.events = EPOLLIN;
+    // ev.data.u64 = delay_manager.get_timer_fd();
+    // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, delay_manager.get_timer_fd(), &ev);
+    // if (ret!= 0) {
+    //	mylog(log_fatal,"add delay_manager.get_timer_fd() error\n");
+    //	myexit(-1);
+    // }
 
-    delay_manager.set_loop_and_cb(loop,delay_manager_cb);
+    delay_manager.set_loop_and_cb(loop, delay_manager_cb);
 
-	//mylog(log_debug," delay_manager.get_timer_fd() =%d\n", delay_manager.get_timer_fd());
+    // mylog(log_debug," delay_manager.get_timer_fd() =%d\n", delay_manager.get_timer_fd());
 
-	mylog(log_info,"now listening at %s\n",local_addr.get_str());
+    mylog(log_info, "now listening at %s\n", local_addr.get_str());
 
-	//my_timer_t timer;
-	//timer.add_fd_to_epoll(epoll_fd);
-	//timer.set_timer_repeat_us(timer_interval*1000);
+    // my_timer_t timer;
+    // timer.add_fd_to_epoll(epoll_fd);
+    // timer.set_timer_repeat_us(timer_interval*1000);
 
-	ev_timer global_timer;
-    ev_init(&global_timer,global_timer_cb);
-    ev_timer_set(&global_timer, 0, timer_interval/1000.0 );
-    ev_timer_start(loop,&global_timer);
+    ev_timer global_timer;
+    ev_init(&global_timer, global_timer_cb);
+    ev_timer_set(&global_timer, 0, timer_interval / 1000.0);
+    ev_timer_start(loop, &global_timer);
 
-	//mylog(log_debug," timer.get_timer_fd() =%d\n",timer.get_timer_fd());
+    // mylog(log_debug," timer.get_timer_fd() =%d\n",timer.get_timer_fd());
 
     struct ev_io fifo_watcher;
 
-	int fifo_fd=-1;
-
-	if(fifo_file[0]!=0)
-	{
-		fifo_fd=create_fifo(fifo_file);
-		//ev.events = EPOLLIN;
-		//ev.data.u64 = fifo_fd;
-
-		//ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fifo_fd, &ev);
-		//if (ret!= 0) {
-			//mylog(log_fatal,"add fifo_fd to epoll error %s\n",strerror(errno));
-			//myexit(-1);
-		//}
-	    ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);
-	    ev_io_start(loop, &fifo_watcher);
-
-		mylog(log_info,"fifo_file=%s\n",fifo_file);
-	}
+    int fifo_fd = -1;
 
-	ev_prepare prepare_watcher;
-	ev_init(&prepare_watcher,prepare_cb);
-	ev_prepare_start(loop,&prepare_watcher);
+    if (fifo_file[0] != 0) {
+        fifo_fd = create_fifo(fifo_file);
+        // ev.events = EPOLLIN;
+        // ev.data.u64 = fifo_fd;
 
+        // ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fifo_fd, &ev);
+        // if (ret!= 0) {
+        // mylog(log_fatal,"add fifo_fd to epoll error %s\n",strerror(errno));
+        // myexit(-1);
+        //}
+        ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);
+        ev_io_start(loop, &fifo_watcher);
 
-	ev_run(loop, 0);
+        mylog(log_info, "fifo_file=%s\n", fifo_file);
+    }
 
-	mylog(log_warn,"ev_run returned\n");
-	myexit(0);
+    ev_prepare prepare_watcher;
+    ev_init(&prepare_watcher, prepare_cb);
+    ev_prepare_start(loop, &prepare_watcher);
 
-	/*
-	while(1)////////////////////////
-	{
+    ev_run(loop, 0);
 
-		if(about_to_exit) myexit(0);
+    mylog(log_warn, "ev_run returned\n");
+    myexit(0);
 
-		int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000);
-		if (nfds < 0) {  //allow zero
-			if(errno==EINTR  )
-			{
-				mylog(log_info,"epoll interrupted by signal,continue\n");
-			}
-			else
-			{
-				mylog(log_fatal,"epoll_wait return %d,%s\n", nfds,strerror(errno));
-				myexit(-1);
-			}
-		}
-		int idx;
-		for (idx = 0; idx < nfds; ++idx)
-		{
-			if(events[idx].data.u64==(u64_t)timer.get_timer_fd())
-			{
+    /*
+    while(1)////////////////////////
+    {
 
-			}
+            if(about_to_exit) myexit(0);
 
-			else if (events[idx].data.u64 == (u64_t)fifo_fd)
-			{
+            int nfds = epoll_wait(epoll_fd, events, max_events, 180 * 1000);
+            if (nfds < 0) {  //allow zero
+                    if(errno==EINTR  )
+                    {
+                            mylog(log_info,"epoll interrupted by signal,continue\n");
+                    }
+                    else
+                    {
+                            mylog(log_fatal,"epoll_wait return %d,%s\n", nfds,strerror(errno));
+                            myexit(-1);
+                    }
+            }
+            int idx;
+            for (idx = 0; idx < nfds; ++idx)
+            {
+                    if(events[idx].data.u64==(u64_t)timer.get_timer_fd())
+                    {
 
-			}
+                    }
 
-			else if (events[idx].data.u64 == (u64_t)local_listen_fd)
-			{
+                    else if (events[idx].data.u64 == (u64_t)fifo_fd)
+                    {
 
+                    }
 
-			}
-		    else if (events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()) {
+                    else if (events[idx].data.u64 == (u64_t)local_listen_fd)
+                    {
 
-			}
-			else if (events[idx].data.u64 >u32_t(-1))
-			{
 
+                    }
+                else if (events[idx].data.u64 == (u64_t)delay_manager.get_timer_fd()) {
 
-			}
-			else
-			{
-				mylog(log_fatal,"unknown fd,this should never happen\n");
-				myexit(-1);
-			}
-		}
+                    }
+                    else if (events[idx].data.u64 >u32_t(-1))
+                    {
 
-	}*/
 
+                    }
+                    else
+                    {
+                            mylog(log_fatal,"unknown fd,this should never happen\n");
+                            myexit(-1);
+                    }
+            }
 
-	return 0;
+    }*/
 
+    return 0;
 }

Някои файлове не бяха показани, защото твърде много файлове са промени