#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <signal.h>
#define MAX_PACKET 80000
#define MINLEN 100
struct statistics{
	float average;
	float sq_average;
	int min;
	int max;
};

int count=1;
pcap_dumper_t *fdesc=NULL; //file dscriptor
int exit_now=1;
pcap_t* my_descr;

struct statistics current_stats;

void exit_cleanly(int the_signal){
	exit_now=-1;
	printf("proceeding to exit\n");
}

void init_stats(){
	current_stats.average=0;
	current_stats.sq_average=0;
	current_stats.min=0;
	current_stats.max=0;
}

int cleanup_pcap(pcap_t *thePcap,pcap_dumper_t *filedesc)
{
  pcap_close(thePcap);
  pcap_dump_close(filedesc);
  return 0;
}

//calculate statistics: average=average*(i-1)/i+new/i
void stats(float number, bpf_u_int32 lenght){	
	
		if (lenght<current_stats.min||current_stats.min==0){
	       		current_stats.min=lenght;
       			}
       
       		if (lenght>current_stats.max||current_stats.max==0){
	       		current_stats.max=lenght;
       			}
       		printf("\n %f \n",number);
       		current_stats.average=(current_stats.average)*(number-1)/number+(float)lenght/number;
       
      		 current_stats.sq_average=(current_stats.sq_average)*(number-1)/number+(float)lenght*(float)lenght/number;
}

void print_stats(){
	fprintf(stdout,"average=%f\n",current_stats.average);
	fprintf(stdout,"sq_average=%f\n",current_stats.sq_average);
	fprintf(stdout,"max=%d\n",current_stats.max);
	fprintf(stdout,"min=%d\n",current_stats.min);
	
}	
	
	     
	       
    	  

void my_callback(u_char *args,const struct pcap_pkthdr* pkthdr,
		const u_char* packet){
//	static int count=1;
	if (exit_now==-1){
		cleanup_pcap(my_descr,fdesc);
		fprintf(stdout,"everything is closed....exiting\n");
		exit(0);
	}
	fprintf(stdout,"%d:%d,",count,pkthdr->len);
	fflush(stdout);
	stats((float)count,pkthdr->len);
	count++;
	print_stats();
	pcap_dump((u_char*)fdesc,pkthdr,(u_char*)packet);
	
	}
	
int main (int argc,char **argv){

	char *dev;
	char errbuf[PCAP_ERRBUF_SIZE];
	int defdev;
	struct bpf_program fp; //holder of compiled filter
	char pcap_filter[100]; //holder of the filtering string
	bpf_u_int32 maskp;
	bpf_u_int32 netp;
	u_char* args = NULL;
	
	//Handle parameters
	if (argc==1){
		defdev=1;
	}
	else if (argc==2)
	{
		defdev=0;
	}
	else {
		printf("Wrong number of parameter in %s\n",argv[0]);
		exit(-1);
	}
	
	//open device
	if (defdev==1){

		dev= pcap_lookupdev(errbuf);
	}
	else {
		dev=argv[1]; //user defined
	}

	if (dev==NULL){
		printf("no device to open...weird\n");
	}
	fprintf(stdout,"reading from %s\n",dev);
	
	
	//netwok address and mask of the device (for compiling filter)
	
	pcap_lookupnet(dev,&netp,&maskp,errbuf);
	
	//and know we open our little descriptor
	
	my_descr= pcap_open_live (dev,MAX_PACKET,1,-1,errbuf);
	if (my_descr==NULL){

		printf ("pcap _open_live failed!!:%s\n",errbuf);
		exit(-1);
	}

	//here is where we compile the filter etc
	
	sprintf(pcap_filter,"link[0] == 0x08");      
	
	//sprintf(pcap_filter,"host 128");      
	//declaration of the filter
	//in this case, only get data packets
							
	
	//compile the filter

	if(pcap_compile(my_descr,&fp,pcap_filter,0,netp)==-1){
		fprintf(stdout,"error in pcap_compile\n");
		return(-1);
	}

	//set the filter
	
	if(pcap_setfilter(my_descr,&fp)==-1){
		fprintf(stdout,"error while setting filter\n");
		return(-1);
	}
	
	

	//init the statistics
	
	init_stats();
	
	//open file to dump the crap
	
	fdesc=pcap_dump_open(my_descr,"filedumper");
	if(fdesc==NULL){
		fprintf(stdout,"problems opening file\n");
		return(-1);
		}
  	/* set the signals so Ctl-C gives us some stats */
  	signal(SIGTERM, exit_cleanly);
  	signal(SIGINT,  exit_cleanly);
  	signal(SIGQUIT, exit_cleanly);
	//and loop foreveeeeeeeeer
	
	pcap_loop(my_descr,-1,my_callback,args);
	
	fprintf(stdout, "we should never reach here...\n");
	
	exit(-1);
}
			

	
		
		
       	
