/* Rev:$Revision: 1.0 $ */
/******************************************************************************
 * Copyright 1998-2009 NetBurner, Inc.  ALL RIGHTS RESERVED
 * Permission is hereby granted to purchasers of NetBurner Hardware
 * to use or modify this computer program for any use as long as the
 * resultant program is only executed on NetBurner provided hardware.
 *
 * No other rights to use this program or it's derivitives in part or
 * in whole are granted. It may be possible to license this or other NetBurner
 * software for use on non-NetBurner hardware. Please contact sales@netburner.com
 * for more infomation.
 *
 * NetBurner makes no representation or warranties with respect to the
 * performance of this computer program, and specifically disclaims
 * any responsibility for any damages, special or consequential,
 * connected with the use of this program.
 *
 * NetBurner, Inc.
 * 5405 Morehouse Dr
 * San Diego Ca, 92131
 *
 *****************************************************************************/
/*-------------------------------------------------------------------
 * This program will test the receive speed of the NetBurner
 * device. To run the program:
 *
 * - Run MTTTY and connect to the debug serial port.
 * - Build and download this example application
 * - Run the speed.exe PC application located in the "pc" directory
 *   of this example folder
 * - The test results will be displayed in MTTTY and in the command
 *   prompt window
 *
 * ------------------------------------------------------------------*/
#include "predef.h"
#include 
#include 
#include 
#include 
#include 
#include 

#define BUFFER_SIZE 1500

char DataBuffer[BUFFER_SIZE]FAST_USER_VAR;

extern WORD tx_buf_frame_cnt;

// Application name to display in IPFind utility
const char *AppName = "TCP Speed Test TX/RX";

extern "C" {
    void UserMain( void *pd );
}

/*-------------------------------------------------------------------
 * UserMain
 * ----------------------------------------------------------------*/
void UserMain( void *pd )
{
   InitializeStack();

   if( EthernetIP == 0 )
   {
      iprintf( "Trying DHCP\r\n" );
      GetDHCPAddress();
      iprintf( "DHCP assigned the IP address of :" );
      ShowIP( EthernetIP );
      iprintf( "\r\n" );
   }

   OSChangePrio( MAIN_PRIO );
   EnableAutoUpdate();

   // Init data buffer array
   for ( int i = 0; i < BUFFER_SIZE; i++ )
       DataBuffer[i] = ('A' + (i % 64));

   iprintf( "Opening TCP listen socket on port 1234 ... " );
   int fdListen = listen( INADDR_ANY, 1234, 5 );

   if( fdListen > 0 )
      iprintf( "complete, fd = %d\r\n", fdListen );
   else
      iprintf( "FAILED\r\n" );

   if( fdListen > 0 )
   {
      while( 1 )
      {
         iprintf( "Waiting for incoming connection ... " );
         IPADDR ClientIp;
         WORD ClientPort;

         int fda = accept( fdListen, &ClientIp, &ClientPort, 0 );

         if( fda > 0 )
         {
            iprintf( "Connected to: " );
            ShowIP( ClientIp );
            iprintf( ":%d\n", ClientPort );

            iprintf( "TCP BUFFER SEGMENTS: %d\r\n", TCP_BUFFER_SEGMENTS );
            iprintf( "Setting TCP socket options to NOPUSH and ack buffers to 40\r\n" );
            setsockoption( fda, SO_NOPUSH );

            // Block to read first byte from client, indicates start of test
            iprintf( "Waiting for Client to signal start of test\r\n" );
            int n = read( fda, DataBuffer, 1 );
            DataBuffer[n] = '\0';
            iprintf( "DataBuffer: %s\r\n", DataBuffer );

            DWORD dw1, dw2;

            if( DataBuffer[0] == 'T' ) // Transmit test
            {
               iprintf( "Starting Transmit Test\r\n" );
               DWORD BytesSent = 0;
               dw1 = TimeTick;

               while( 1 )
               {
                  int rv = write( fda, DataBuffer, TCP_BUFFER_SEGMENTS * 1460 );

                  if( rv < 0 )
                  {
                     dw2 = TimeTick;
                     close( fda );
                     iprintf( "Bytes Sent = %ld, TimeTick count: %ld\r\n", BytesSent, dw2 - dw1 );
                     break;
                  }
                  else
                     BytesSent += rv;
               }
            }

            // Receive Test
            if( DataBuffer[0] == 'R' )
            {
               DWORD BytesReceived = 0;
               unsigned long PrintableChars = 0;
               dw1 = TimeTick;

               while( BytesReceived < 10000000 )
               {
                  int rv = ReadWithTimeout( fda, DataBuffer, BUFFER_SIZE, TICKS_PER_SECOND );

                  if( rv < 0 )
                  {
                     break;
                  }
                  else
                  {
                     // Look at each byte and count printable characters
                     for ( int i = 0; i < rv; i++ )
                     {
                        if( (DataBuffer[i] >= ' ') && (DataBuffer[i] < 127) )
                           PrintableChars++;
                     }

                     BytesReceived += rv;
                  }
               }
               dw2 = TimeTick;
               close( fda );
               float DataRate = (float)BytesReceived / (float)( dw2 - dw1 ) * TICKS_PER_SECOND * 8.0 / 1000000.0;
               printf( "Bytes Received: %ld, TimeTick Count: %ld, Data Rate: %g, Printable Chars: %ld\r\n",
                   BytesReceived, dw2 - dw1, DataRate, PrintableChars );
            }
         }
         else
            iprintf( "accept() failed\r\n" );
      }
   }

   iprintf( "Program terminated. Reset device to repeat\r\n" );

   while( 1 );
}