#include "pktTrace.h"
#include <stdio.h>

PktType		PktArray[2][1000];
PktType		*PktArrayEnd[2]={NULL,NULL};
int		PktArrayIndx=0;
PktType		*CurPkt;
PktType		*MaxCntPkt;
PktType		*MaxLenPkt;
int		MaxCntIndx;
int		MaxLenIndx;
int		PktIndx[2]={0,0};
PktType		*PktSavedArray[1000];
int		PktSavedArrayIndx=0;
int		PktLenArray[PKT_LEN_ARRAY];
int		PktLenArrayBeg=0;
int		PktLenArrayEnd=0;
int		PktLenArraySize=0;
int		PktQueueCnt=0;
int		PktQueueLen=0;
int		PktQueueDropCntArg=60;	/* arg */
int		PktTimeBegArg=0;	/* arg */
int		PktTimeEndArg=0;	/* arg */
int		PktTimeNext=0;
int		PktTimeIncArg=10000;	/* arg */
int		PktMaxQueueCntArg=1000000;
int		PktMaxQueueLenArg=100000000;

PktType		PktMark={99, 99, 99, 0, 99, {99, 99, 99, 99}, 99, 99, 99, 99};

void pktInit(int argc, char *argv[])
{
  char *cp;
  int  i, j, k;

  CurPkt = &PktArray[0][0];
  MaxCntPkt = MaxLenPkt = CurPkt;
  MaxCntIndx = MaxLenIndx = 0;
  for (k=0; k<argc; k++) 
    if (!strncmp(argv[k], "-pktQueueDropCnt=", 17))
      sscanf(argv[k]+17, "%d", &PktQueueDropCntArg);
    else if (!strncmp(argv[k], "-pktTimeBeg=", 12)) {
      sscanf(argv[k]+12, "%d", &PktTimeBegArg);
      PktTimeBegArg *= 1000;
    }
    else if (!strncmp(argv[k], "-pktTimeEnd=", 12)) {
      sscanf(argv[k]+12, "%d", &PktTimeEndArg);
      PktTimeEndArg *= 1000;
    }
    else if (!strncmp(argv[k], "-pktTimeInc=", 12)) {
      sscanf(argv[k]+12, "%d", &PktTimeIncArg);
      PktTimeIncArg *= 1000;
    }
    else if (!strncmp(argv[k], "-pktMaxQueueCnt=", 16))
      sscanf(argv[k]+16, "%d", &PktMaxQueueCntArg);
    else if (!strncmp(argv[k], "-pktMaxQueueLen=", 16)) {
      sscanf(argv[k]+16, "%d", &PktMaxQueueLenArg);
      PktMaxQueueLenArg *= 1024;
    }

  PktTimeNext = PktTimeBegArg + PktTimeIncArg;
}
  

void pktTrace(int lastTime) 
{
  int     i, j, k, n, ke, ka;
  PktType *p, *p1, *p2;

  if (PktTimeBegArg < lastTime  &&  lastTime <= PktTimeEndArg) {
    if (PktTimeNext <= lastTime) {
      if (MaxCntPkt->queueCnt >= PktMaxQueueCntArg) {
	/* save pkt traces */
	PktSavedArray[PktSavedArrayIndx++] = p = p1 = 
	  (PktType *)malloc(sizeof(PktType)*(MaxCntPkt->queueCnt+44));
	bzero((char *)p, sizeof(PktType)*(MaxCntPkt->queueCnt+44));
	if (MaxCntIndx+10 < PktIndx[PktArrayIndx])
	  ke = MaxCntIndx + 10, ka = 40;
	else
	  ke = PktIndx[PktArrayIndx] - 1, 
	  ka = PktIndx[PktArrayIndx] - 1 - MaxCntIndx + 30;
	p2 = &PktArray[PktArrayIndx][ke];
	/* p2 = MaxCntPkt; */
	n = 100000;
	for (k=0; k<ke  &&  k <= MaxCntPkt->queueCnt+ka; k++) {
	  if (p2 == MaxCntPkt)
	    *p1++ = PktMark, n=MaxCntPkt->queueCnt;
	  if (n == 0)
	    *p1++ = PktMark;
	  *p1++ = *p2--;
	  n--;
	}
	if (k <= MaxCntPkt->queueCnt + ka) {
	  if ((p2 = PktArrayEnd[PktArrayIndx^0x1]) != NULL) 
	    for (j=0; j<PktIndx[PktArrayIndx^0x1] && 
		 k<=MaxCntPkt->queueCnt+ka; j++,k++) {
	      if (n == 0)
		*p1++ = PktMark;
	      *p1++ = *p2--;
	      n--;
	    }
	}
	*p1 = PktMark;
      }
      if (MaxLenPkt->queueLen >= PktMaxQueueLenArg) {
	/* save pkt traces */
      }
      PktArrayEnd[PktArrayIndx] = --CurPkt;
      PktArrayIndx =  (PktArrayIndx + 1) & 0x1;
      PktArray[PktArrayIndx][0] = *CurPkt;
      CurPkt = &PktArray[PktArrayIndx][0];
      PktIndx[PktArrayIndx] = 0;
      MaxCntPkt = CurPkt;
      MaxLenPkt = CurPkt;
      MaxCntIndx = MaxLenIndx = 0;
      while (PktTimeNext < lastTime)
	PktTimeNext +=  PktTimeIncArg;
    }
    
    if (MaxCntPkt->queueCnt < CurPkt->queueCnt)
      MaxCntPkt = CurPkt, MaxCntIndx = PktIndx[PktArrayIndx];
    if (MaxLenPkt->queueLen < CurPkt->queueLen)
      MaxLenPkt = CurPkt, MaxLenIndx = PktIndx[PktArrayIndx];
    CurPkt++;
    PktIndx[PktArrayIndx]++;
  }
}    

static char   *StrTypes1[10]={"F","T","S", "N", "?", "f", "t", "s", "n", "?"};
static IdType idNull={0,0,0,0};
static int    x0[4]={10000, 1000, 100, 10};
static int    x1[4]={1000, 100, 10, 1};

void pktPrint ()
{
  char *cp, types[200], ss[200], sa[200], flags[200][10];
  int  i, j, k, typeCnts[5], typeLens[5], ssCnt, ssLen, saCnt, saLen;
  int  pktLens[200], dtime[200], t, qLens[200], qCnt[200];
  int  intIds[200], idCnt, begLen, endLen, topCnts[5], topLens[5];
  int  topIds[5], markCnt, idCnts[200], idLens[200], maxLen, maxCnt;
  PktType *p, *p1, *p2, *pkts[200], *pMax;

  if (PktTimeBegArg >= PktTimeEndArg)
    return;
  printf("Pkt Queue Drop Cnt: %d\n", PktQueueDropCntArg);
  printf("Pkt Time Beg:       %dms\n", PktTimeBegArg/1000);
  printf("Pkt Time End:       %dms\n", PktTimeEndArg/1000);
  printf("Pkt Time Inc:       %dms\n", PktTimeIncArg/1000);
  printf("Pkt Max Queue Cnt:  %d\n", PktMaxQueueCntArg);
  printf("Pkt Max Queue Len:  %dKB\n\n", PktMaxQueueLenArg/1024);

  for (i=0; i<PktSavedArrayIndx; i++) {
    p = p1 = PktSavedArray[i];
    for (k=0; k<5; k++)
      typeCnts[k] = typeLens[k] = topCnts[k] = topLens[k] = topIds[k] = 0;
    ssCnt = ssLen = saCnt = saLen = 0;
    idCnt = 1;
    for (k=0; k<200; k++) {
      intIds[k] = dtime[k] = 0;
      pktLens[k] = qLens[k] = qCnt[k] = 0;
      types[k] = ss[k] = sa[k] = ' ';
      strcpy(flags[k], "         ");
      idCnts[k] = idLens[k] = 0;
      pkts[k] = &PktMark;
    }
    for (k=p->queueCnt+42; k>=0 && p1!=NULL; k--, p1++)
      if (p1->inPort == 99) {
	pMax = p1 + 1;
	break;
      }
    t = pMax->time;
    p1 = p;
    markCnt = 0;
    for (k=p->queueCnt+42; k>=0 && p1!=NULL; k--) {
      if (p1->inPort == 99) {
	if (markCnt == 0)
	  endLen = (p1+1)->queueLen;
	else if (markCnt == 1)
	  begLen = (p1-1)->queueLen;
	else if (markCnt == 2)
	  break;
	markCnt++;
	p1++;
	continue;
      }
      types[k] = StrTypes1[p1->type][0];
      if (p1->flags & 0x40)
	flags[k][7] = 's', ssCnt++, ssLen += p1->len;
      if (p1->flags & 0x80)
	flags[k][8] = 'r', saCnt++, saLen += p1->len;
      if (p1->flags & 0x01)
	flags[k][0] = 'F';
      if (p1->flags & 0x02)
	flags[k][1] = 'S';
      if (p1->flags & 0x04)
	flags[k][2] = 'R';
      if (p1->flags & 0x08)
	flags[k][3] = 'P';
      /* if (p1->flags & 0x10)
	flags[k][4] = 'A'; */
      if (p1->flags & 0x20)
	flags[k][5] = 'U';

      pktLens[k] = p1->len;
      typeCnts[p1->type%5]++;
      typeLens[p1->type%5] += p1->len;
      qLens[k] = p1->queueLen;
      qCnt[k] = p1->queueCnt;
      pkts[k] = p1;
      for (j=p->queueCnt+42; j>k; j--)
	if (pkts[j]->inPort == 99)
	  continue;
	else if (p1->id.ipSrc == pkts[j]->id.ipSrc  &&
		 p1->id.ipDst == pkts[j]->id.ipDst  &&
		 p1->id.sport == pkts[j]->id.sport  &&
		 p1->id.dport == pkts[j]->id.dport) {
	  intIds[k] = intIds[j];
	  idCnts[j]++;
	  idLens[j] += pkts[j]->len;
	  break;
	}
      if (j == k)
	intIds[k] = idCnt++;
      dtime[k] = t - p1->time;
      p1++;
    }

    printf("Queue: %3d at time %2d:%02d.%03d %03d  begLen:%d endLen:%d\n\n", 
	   pMax->queueCnt,
	   pMax->time/60000000, (pMax->time%60000000)/1000000,
	   (pMax->time%1000000)/1000, (pMax->time%1000),
	   begLen, endLen);

    markCnt = 0;
    p1 = p;
    printf("     flags     len   time  id    qLen  qCnt     ipSrc    ipDst\n");
    printf("   ---------  ----  -----  --  ------  ----    -------  -------\n");
    for (k=p->queueCnt+42; k>=0 && p1!=NULL; k--) {
      if (p1->inPort == 99) {
	if (markCnt == 0  ||  markCnt == 1)
	  printf("\n");
	else
	  break;
	markCnt++;
      }
      else
	printf("%c  %s  %4d  %5d  %2d  %6d  %4d    %3d.%03d  %3d.%03d\n", 
	       types[k], flags[k], 
	       pktLens[k], dtime[k], intIds[k], qLens[k], qCnt[k],
	       p1->id.ipSrc>>8, p1->id.ipSrc&0xff, p1->id.ipDst>>8,
	       p1->id.ipDst&0xff);
      p1++;
    }
/*
    printf("%s\n%s\n%s\n", types, ss, sa);
    for (j=0; j<4; j++) {
      for (k=0; k<71; k++) {
	if (pktLens[k] == 0 || pktLens[k] < x1[j])
	  printf(" ");
	else
	  printf("%c", '0'+(pktLens[k]%x0[j])/x1[j]);
      }
      printf("\n");
    }
    printf("\n");

    for (j=0; j<4; j++) {
      for (k=0; k<71; k++) {
	if (dtime[k] == 0 || dtime[k] < x1[j])
	  printf(" ");
	else if (dtime[k] > 9999)
	  printf(".");
	else
	  printf("%c", '0'+(dtime[k]%x0[j])/x1[j]);
      }
      printf("\n");
    }
    printf("\n");

    for (j=2; j<4; j++) {
      for (k=0; k<71; k++) {
	if (intIds[k] == 0 || intIds[k] < x1[j])
	  printf(" ");
	else
	  printf("%c", '0'+(intIds[k]%x0[j])/x1[j]);
      }
      printf("\n");
    }
*/
    printf("\n");

    printf("       FTP    TELNET    SMTP    NNTP        SS      SA\n");
    printf("cnt  %6d   %6d  %6d  %6d    %6d  %6d\n", typeCnts[0],
	   typeCnts[1], typeCnts[2], typeCnts[3], ssCnt, saCnt);
    printf("len  %6d   %6d  %6d  %6d    %6d  %6d\n", typeLens[0],
	   typeLens[1], typeLens[2], typeLens[3], ssLen, saLen);
    printf("\n............................................\n\n");
  }
}
