浏览代码

better tuneable --fec works

wangyu- 7 年之前
父节点
当前提交
25da3a2b03
共有 6 个文件被更改,包括 133 次插入8 次删除
  1. 18 0
      common.cpp
  2. 3 1
      common.h
  3. 6 1
      fec_manager.cpp
  4. 95 4
      fec_manager.h
  5. 10 2
      misc.cpp
  6. 1 0
      tunnel_client.cpp

+ 18 - 0
common.cpp

@@ -1006,3 +1006,21 @@ u32_t sdbm(unsigned char *str,int len)
      return hash;
  }
 
+vector<string> string_to_vec(const char * s,const char * sp) {
+	  vector<string> res;
+	  string str=s;
+	  char *p = strtok ((char *)str.c_str(),sp);
+	  while (p != NULL)
+	  {
+		 res.push_back(p);
+	    //printf ("%s\n",p);
+	    p = strtok(NULL, sp);
+	  }
+
+	 /* for(int i=0;i<(int)res.size();i++)
+	  {
+		  printf("<<%s>>\n",res[i].c_str());
+	  }*/
+	  return res;
+}
+

+ 3 - 1
common.h

@@ -52,7 +52,7 @@ typedef int socklen_t;
 #include<map>
 #include<list>
 #include<string>
-
+#include<vector>
 using  namespace std;
 
 
@@ -548,4 +548,6 @@ struct lru_collector_t:not_copy_able_t
 };
 
 
+vector<string> string_to_vec(const char * s,const char * sp) ;
+
 #endif /* COMMON_H_ */

+ 6 - 1
fec_manager.cpp

@@ -20,6 +20,7 @@
 
 fec_parameter_t g_fec_par;
 
+int debug_fec=1;
 //int dynamic_update_fec=1;
 
 const int encode_fast_send=1;
@@ -314,7 +315,11 @@ int fec_encode_manager_t::input(char *s,int len/*,int &is_first_packet*/)
     			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;
-    			mylog(log_trace,"actual_data_num=%d actual_redundant_num=%d\n",actual_data_num,actual_redundant_num);
+
+    			if(debug_fec)
+    				mylog(log_debug,"actual_data_num=%d actual_redundant_num=%d len=%d\n",actual_data_num,actual_redundant_num,blob_encode.get_shard_len(actual_data_num,0));
+    			else
+    				mylog(log_trace,"actual_data_num=%d actual_redundant_num=%d\n",actual_data_num,actual_redundant_num);
     		}
 
         	assert(blob_encode.output(actual_data_num,blob_output,fec_len)==0);

+ 95 - 4
fec_manager.h

@@ -18,6 +18,7 @@ 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
 extern u32_t fec_buff_num;
 
+const int rs_str_len=max_fec_packet_num*10+100;
 
 struct fec_parameter_t
 {
@@ -27,21 +28,111 @@ struct fec_parameter_t
 	int timeout=8*1000;
 	int mode=0;
 
-	int rs_cnt;
+	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[255+10];
 
-	int rs_from_str(char * s)
+	int rs_from_str(char * s)//todo inefficient
 	{
+		vector<string> str_vec=string_to_vec(s,",");
+		if(str_vec.size()<1) 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<1||x+y>max_fec_packet_num)
+			{
+				mylog(log_warn,"invaild value x=%d y=%d\n",x,y);
+				return -1;
+			}
+			tmp_par.x=x;
+			tmp_par.y=y;
+			par_vec.push_back(tmp_par);
+		}
+		assert(par_vec.size()==str_vec.size());
+
+		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<now_ratio)
+			{
+				mylog(log_warn,"%d/%d < %d/%d ,not suggested\n",pre_y,pre_x,now_y,now_x);
+			}
+		}
+
+		{ //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 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
+				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()
+	char *rs_to_str()//todo inefficient
 	{
-		return 0;
+		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));
+			tmp_string+=tmp_buf;
+		}
+		strcpy(res,tmp_string.c_str());
+		return res;
 	}
 
 	rs_parameter_t get_tail()

+ 10 - 2
misc.cpp

@@ -53,7 +53,8 @@ int tun_mtu=1500;
 
 int mssfix=1;
 
-char rs_par_str[max_fec_packet_num*10+100];
+
+char rs_par_str[rs_str_len];
 
 
 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)
@@ -289,6 +290,7 @@ int handle_command(char *s)
 		g_fec_par.clone(tmp_par);
 		g_fec_par.version=version;
 		g_fec_par.version++;
+		strcpy(rs_par_str,tmp_str);
 		//g_fec_data_num=a;
 		//g_fec_redundant_num=b;
 	}
@@ -323,7 +325,13 @@ int handle_command(char *s)
 			mylog(log_warn,"invaild value\n");
 			return -1;
 		}
-		g_fec_par.mode=a;
+		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)
 	{

+ 1 - 0
tunnel_client.cpp

@@ -381,6 +381,7 @@ int tunnel_client_event_loop()
 	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);