/* aagengob.c */

/* This version sends a specified amount of data */
/* to a socket and consumes it.                  */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/times.h>

#ifdef GLIBC_PATCH
#include <stdint.h>
#undef __GLIBC__
#include <linux/socket.h>
#include <linux/atm.h>
#else
#include <sys/socket.h>
#include <linux/types.h>
#endif

#include <signal.h>

struct timezone dummy = {0,0};

struct timeval time1;
struct timeval time2;
struct tms timeb;
double tu1;
double tu2;

#define MAX_BLK 1008

char buf[MAX_BLK] = "This is a test";
char bufi[MAX_BLK] = "This is a test";

int  drops = 0;
int  dropcount = 0;
int  frames = 0;

void sigintx(
int  dummy)
{
   printf("Frames sent = %d \n", frames);
   exit(1);
}

void sigintr(
int  dummy)
{
   printf("Frames recvd = %10d \n", frames);
   printf("Drops        = %10d \n", drops);
   printf("Drop count   = %10d \n", dropcount);
   printf("Total        = %10d \n", frames + dropcount);
   exit(1);
}

void aa_send(
int s,                  /* socket handle */
int blk,                /* Block size    */
int count)              /* Total count.  */
{
   int rc;
   int fc = 0;
   int sent = count;

   signal(SIGINT, sigintx);
   rc = 0;
   memset(buf, 'a', sizeof(buf));
   gettimeofday(&time1,&dummy);

   while ((sent < count) || (count <= 0))
   {
      long *loc;

      loc = (long *)buf;
     *loc = fc;
      rc = write(s, buf, blk);

      if (rc < 0)
         break;

   /* printf("Wrote %d bytes \n", rc); */
      sent -= rc;
      fc += 1;
      frames += 1;
   }

   printf("Sender complete: count = %d rc = %d \n", count, rc);
   memset(buf, 'z', sizeof(buf));
   rc = write(s, buf, blk);

   times(&timeb);
   printf("User time   = %6d.%02d \n",
               timeb.tms_utime / 100, timeb.tms_utime % 100);
   printf("System time = %6d.%02d \n",
               timeb.tms_stime / 100, timeb.tms_stime % 100);

   gettimeofday(&time2,&dummy);

#if 0
   printf("time 1: %d %d\n",time1.tv_sec, time1.tv_usec);
   printf("time 2: %d %d\n",time2.tv_sec, time2.tv_usec);
#endif

   tu1 = 1000000 * time1.tv_sec;
   tu1 += time1.tv_usec;

   tu2 = 1000000 * time2.tv_sec;
   tu2 += time2.tv_usec;

   printf("Elapsed time= %8.2lf \n", (tu2 - tu1)/ 1000000);
   printf("MBits / sec = %8.3lf \n", 8 * count / (tu2 - tu1));
   printf("Frames sent = %8d    \n", fc);
   printf("Frames/usec = %8.3lf \n", fc / (tu2 - tu1));

   fprintf(stderr,
      "%6d \t %6d.%02d \t %6d.%02d \t %8.2lf \t %8.3lf \t %8d \t %8.3lf \n",
       blk,
       timeb.tms_utime / 100, timeb.tms_utime % 100,
       timeb.tms_stime / 100, timeb.tms_stime % 100,
       (tu2 - tu1)/ 1000000,
       8 * count / (tu2 - tu1),
       fc,
       fc / (tu2 - tu1));
   sleep(3);
   rc = write(s, buf, blk);
   exit(1);
}

void aa_recv(
int s)                  /* socket handle */
{
   int rc;
   int amt = 0;
   int fc  = 0;
   int fctrue;

   signal(SIGINT, sigintr);

   rc = read(s, bufi, sizeof(bufi));
   printf("Read %d bytes \n", rc);
   while (rc >= 0)
   {
      amt += rc;
      rc = read(s, bufi, sizeof(bufi));

      fctrue = *(long *)bufi;
#if 1
      if (fctrue != fc)
      {
         drops += 1;
         dropcount += fctrue - fc;

      }
#endif
      frames += 1;
      fc = fctrue + 1;
   /* printf("Read %d bytes first was %c \n", rc, bufi[0]);  */
   }
   printf("Receiver complete.. received  %d \n", amt);
}



int main(
int argc,
char **argv)
{
   struct sockaddr_atmpvc addr;
   struct atm_qos         qos;
   int    s,size,offset;
   int    rc;
   int    pid;
   int    blk = MAX_BLK;
   int    count = 5 * 1024 * 1024;
   int    vci = 33;
   int    fd;
   int    psr = 2;


   s = socket(PF_ATMPVC,SOCK_DGRAM,ATM_AAL5);
   printf("Socket call returned %d \n", s);

   if (argc < 2)
   {
      printf("This sends stdin to the vci specified.              \n");
      printf("You must give vci number in decimal as parm 1.      \n");
      printf("You may  give blk size   in decimal as parm 2.      \n");
      printf("You may  give byte count in decimal as parm 3.      \n");
      printf("You may  give psr        in decimal as parm 4.      \n");
      exit(1);
   }

   sscanf(argv[1], "%d", &vci);

   if (argc > 2)
      sscanf(argv[2], "%d", &blk);

   if (argc > 3)
      sscanf(argv[3], "%d", &count);

   if (argc > 4)
      sscanf(argv[4], "%d", &psr);

   printf("Sending to vci %d \n", vci);
   printf("Frame size %d bytes \n", blk);

   qos.aal = 5;
   qos.txtp.traffic_class = ATM_UBR;
   qos.txtp.max_sdu = blk;
   qos.txtp.max_pcr = 5 * 1024 * 1024;
   qos.txtp.min_pcr = 1 * 1024 * 1024;
   qos.txtp.max_cdv = 1 * 1024 * 1024;

   qos.rxtp.traffic_class = ATM_UBR;
   qos.rxtp.max_sdu = 768;
   qos.rxtp.max_pcr = 5 * 1024 * 1024;
   qos.rxtp.min_pcr = 1 * 1024 * 1024;
   qos.rxtp.max_cdv = 1 * 1024 * 1024;

   rc = setsockopt(s, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos));
   printf("Return from setsock is %d \n", rc);

   addr.sap_family   = AF_ATMPVC;
   addr.sap_addr.itf = 0;
   addr.sap_addr.vpi = 0;
   addr.sap_addr.vci = vci;

   while (rc = connect(s,(struct sockaddr *) &addr,sizeof(addr)))
   {
      sleep(1);
   }
   printf("Return from connect is %d \n", rc);

   pid = fork();

   if (pid == 0)
   {
     aa_recv(s);
     exit(1);
   }
   else
   {
     aa_send(s, blk, count);
   }
}
