Bläddra i källkod

fix indent problem with clang-format

yancey 2 år sedan
förälder
incheckning
41cac842a8
24 ändrade filer med 4662 tillägg och 5469 borttagningar
  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

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 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;
 }

Vissa filer visades inte eftersom för många filer har ändrats