text: /*
   * packet.cpp
   *
   *  Created on: Sep 15, 2017
   *      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;
  
  typedef u64_t anti_replay_seq_t;
  int disable_replay_filter=0;
  
  int disable_obscure=0;
  int disable_xor=0;
  
  int random_drop=0;
  
  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 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(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;
  }
  
  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;
  
  	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;
  }
  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;
  
  	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));
  }*/
  
  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);
  }*/
  
  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;
  }
  
  /*
   *  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;
  }
  
  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 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 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 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 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;
  }
  
  
  
  