// gcc bwcnt6.c > bwcnt6;  mv a.out bwcnt6 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAXCONNS 200
#define TFRM 1
#define TCP 2
// This plots the throughput of individual flows.
// This has been verified for TCP and TFRM flows.

main(int argc, char **argv)
{
  int conns=0, i, j, cnum;
  int src, dst, size, dummy1, dummy4, pid;
  float ts, tsmax=0.0, psrc, pdst, tdiff;
  char type[10], flags[10];
  char line[80];
  char event;
  int *tn, connspace;
  float *srcs;
  float *dsts;
  double *time;
  int *counts;
  int *types;
  int tcpconns=0;
  int tfrmconns=0;
  int lsrc, ldst, bw;
  double bwf=2.0;
  int starttime=15;
  double interval=0.2;
  FILE *file;

  if (argc<5) {
    fprintf(stderr, "Usage: bwvt <avlen> <src> <dst> <filename>\n");
    exit(0);
  }
  file = fopen(argv[4], "r");
  if (file==NULL) {
    fprintf(stderr, "bwvt: failed to open file %s\n", argv[4]);
    exit(0);
  }
  lsrc=atoi(argv[2]);
  ldst=atoi(argv[3]);
  bwf=atof(argv[1])*1000000.0/8.0;
  srcs=(float*)malloc(sizeof(float)*MAXCONNS);
  dsts=(float*)malloc(sizeof(float)*MAXCONNS);
  counts=(int*)malloc(sizeof(int)*MAXCONNS);
  types=(int*)malloc(sizeof(int)*MAXCONNS);
  time=(double*)malloc(sizeof(double)*MAXCONNS);
  connspace=MAXCONNS;
  //pass 1
  while(feof(file)==0) {
    fgets(line, 80, file);
    sscanf(line, "%c %f %d %d %s %d %s %d %f %f %d %d",
	   &event, &ts, &src, &dst, type, &size, flags, &dummy1, &psrc, 
	   &pdst, &dummy4, &pid);
    //only trace the packets on link lsrc -> ldst when they enter the queue
    //and only trace data packets in that direction
    if ((src!=lsrc)||(dst!=ldst)||(dummy1==1)) continue;

    //find the connection number
    // this would be faster if we just set up an array to map from
    // psrc (packet source) to cnum (connection number).
    cnum=-1;
    for(i=0;i<conns;i++) {
//      printf("%d srcs: %f,%f  %f,%f\n", i, srcs[i], dsts[i], pdst, psrc);
      if ((srcs[i]==psrc)&&(dsts[i]==pdst)) {
	cnum=i;
	break;
      }
    }
    //new connection
    if ((event=='+')&&(cnum==-1)) {
      fprintf(stderr, "new connection %d from %f to %f\n", conns, psrc, pdst);
      srcs[conns]=psrc;
      dsts[conns]=pdst;
      counts[conns]=0;
      if (strcmp(type, "tcp")==0) {
	tcpconns++;
	types[conns]=TCP;
      } else if (strcmp(type, "tcpFriend")==0 || strcmp(type, "message")==0) {
	tfrmconns++;
	types[conns]=TFRM;
      }
      cnum=conns;
      conns++;
      if(conns==connspace) {
	srcs=(float *)realloc(srcs, sizeof(float)*(conns+MAXCONNS));
	dsts=(float *)realloc(dsts, sizeof(float)*(conns+MAXCONNS));
	counts=(int *)realloc(counts, sizeof(int)*(conns+MAXCONNS));
	types=(int *)realloc(types, sizeof(int)*(conns+MAXCONNS));
	connspace=conns+MAXCONNS;
      }
    }
    //new packet
    //only keep stats after the first starttime seconds
    if (event=='r') {
      if (strchr(flags, 'E')) {
        if (ts>15)
          printf("ecn %f %d\n", ts, cnum);
      }
      if (ts>starttime) {
	while (ts>time[cnum]+2*interval){
	   printf("conn: %d time: %4.1f bytes: %d\n", cnum, time[cnum]+interval, counts[cnum]);
	   time[cnum]+=interval;
	   counts[cnum]=0;
	} 
        if (ts>time[cnum]+interval){
	   printf("conn: %d time: %4.1f bytes: %d\n", cnum, time[cnum]+interval, counts[cnum]);
	   time[cnum]+=interval;
	   counts[cnum]=0;
	} 
	counts[cnum]+=size;
      }
      else 
	time[cnum]=starttime;
      tsmax=ts;
    }
    if (event=='d') {
      if (ts>15)
        printf("drop %f %d\n", ts, cnum);
    }
  }
}
