NetTest.c

NetTest.c example details

This program installs a UDP echo server (port 7), and a TCP server listening on port 1061.

To verify this program, first 'Ping' the DSP:

>ping 192.168.168.200

If the settings and network connections are correct, the pings will be replied.

The UDP Echo server will re-send (echo) anything it receives. To verify this, start Netcat (nc) with the following command

>nc -u 192.168.168.200 7
     |       |         |
     |       |         +-- port 7 = Echo Port
     |       +------------ the DSP's IP address
     +-------------------- use UDP transfers

Any characters you type in the console window will be returned. NetCat doesn't send the characters immediately, it will send the entire string following a terminating CR. Please note that the maximum length of the character string is limited by the size of the buffer used for UDP echo (1472). You may also transmit a file by re-directing it to stdin:

>nc -u 192.168.168.200 7 < hello.txt

The TCP server will respond to any incoming request on port 1061 and return a short message. To verify this, start Netcat with the following command

>nc 192.168.168.200 1061
          |         |
          |         +-- port 1061 = the port the DSP listens to
          +------------ the DSP's IP address

Type a CR, the DSP will respond with its message

See also
TCP Transmission Control Protocol , UDP User Datagram Protocol
/***************************************************************************//**
@file NetTest.c
@brief Network test program
@verbatim
_ _ _
__| | ___(_) ____ _ __ | |_
/ _` | / __| |/ _` | '_ \| __|
| (_| | _ \__ \ | (_| | | | | |_
\__,_|(_) ___/_|\__, |_| |_|\__|
Signalprocessing |___/ Technology
@endverbatim
@author D.SignT GmbH & Co. KG, Claus Hermbusche
@date 2019-06-03
@anchor NETTESTEX
@details
This program installs a UDP echo server (port 7) with quad buffering,
and a TCP message server listening on port 1061.
When the program has started successfully, the terminal printout should
look like:
---------------------------------------------------------
| D.SignT GmbH & Co. KG Nettest |
| |
| (c) 2019 D.SignT www.dsignt.de |
| |
| netlib revision: 2.92.02 |
---------------------------------------------------------
Setup system time ................................. success
*** timer 1 mapped to CPU int 14 ***
Enable interrupts ................................. success
Start system timer ................................ success
*** timer 1 running at 1000 Hz ***
Initialize network ................................ success
network startup time [sec]: 0.036
Entering main loop ...
/
Link status changed: Linked at 100 Mbit full duplex
-
network configuration:
MAC address: 02.00.D2.02.00.01
IP address: 192.168.168.126
Host name: DM2C6747-0001
Domain name: fritz.box
DNS Server: 192.168.168.100
Gateway: 192.168.168.100
Subnetmask: 255.255.255.0
To verify this program, first 'ping' the DSP:
>ping DM2C6747-0001.fritz.box
>ping 192.168.168.126
UDP test:
>nc -u DM2C6747-0001.fritz.box 7
>nc -u 192.168.168.126 7
TCP test
>nc DM2C6747-0001.fritz.box 1061
>nc 192.168.168.126 1061
The real network settings depend on your configuration.
The UDP Echo server will re-send (echo) anything it receives.
To verify this, start NetCat (nc) with the following command
>nc -u 192.168.168.126 7
| | |
| | +-- port 7 = Echo Port
| +------------ the DSP's IP address
+-------------------- use UDP transfers
or, if configured for DHCP
>nc -u DM2C6747-0001.fritz.box 7
| | |
| | +--- port 7 = Echo Port
| +------------------------- the DSP Fully-Qualified Host Name
+----------------------------- use UDP transfers
Any characters you type in the console window will be returned.
NetCat doesn't send the characters immediately, it will send
the entire string following a terminating CR. Please note that
the maximum length of the character string is limited by the
size of the buffer used for UDP echo (1472). You may also
transmit a file by re-directing it to stdin:
>nc -u 192.168.168.126 7 < hello.txt
The TCP server will respond to any incoming request on port 1061
and return a short message. To verify this, start NetCat with
the following command
>nc 192.168.168.126 1061
| |
| +-- port 1061 = the port the DSP listens to
+------------ the DSP's IP address
Type a CR, the DSP will respond with its message.
@cond Software License Agreement
Copyright (C) 2001-2019 D.SignT GmbH & Co. KG - http://www.dsignt.de
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
Neither the name of D.SignT GmbH & Co. KG nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
Disclaimer
THIS SOFTWARE IS PROVIDED BY D.SIGNT GMBH & CO. KG "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL D.SIGNT GMBH & CO. KG BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@endcond
*******************************************************************************/
/*******************************************************************************
include stdtypes.h to avoid data type mismatch
*******************************************************************************/
/*******************************************************************************
include Runtime Source
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
/*******************************************************************************
network support functions
*******************************************************************************/
#include <Libs/NETlib/net.h> /* D.Module network support */
/*******************************************************************************
board specific functions
*******************************************************************************/
#include <BoardSupport/inc/BoardSpecific.h> /* board support functions */
/*******************************************************************************
common support functions
*******************************************************************************/
#include <Common/Common.h> /* on exit function */
#include <Common/uartio.h> /* UART support */
#include <Common/timer.h> /* timer setting */
#include <Common/CPrintf.h> /* CPrintf defines */
/*******************************************************************************
network configuration
*******************************************************************************/
#include <BoardSupport/config/netconfig.c> /* network configuration */
/*******************************************************************************
Uncomment USE_STATIC_MEMORY to use static memory instead of dynamic.
This definition is required before "nbuffer.h" include.
Don't forget to change heap size and linker command file to fit these buffers
into memory.
*******************************************************************************/
//~ #define USE_STATIC_MEMORY TRUE
#define MAX_NBUFFER_SIZE (1500) /* must be defined before #include nbuffer.h */
#include "..\..\..\Common\nbuffer.h" /* network buffer support */
#ifdef __cplusplus
extern "C" {
#endif /* !__cplusplus */
/*******************************************************************************
local prototypes
*******************************************************************************/
#pragma CODE_SECTION(udp_call_back , ".commontext")
int32_t udp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec);
#pragma CODE_SECTION(tcp_call_back , ".commontext")
int32_t tcp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec);
#pragma CODE_SECTION(process_data , ".commontext")
void process_data (SOCKET *so);
#ifdef __cplusplus
} // extern "C"
#endif
/*******************************************************************************
* *
* DEFINES *
* *
*******************************************************************************/
/*******************************************************************************
activate USE_TCP_CALLBACK to use a callback function instead of net_recv()
*******************************************************************************/
#define USE_TCP_CALLBACK 1
/*******************************************************************************
define the number of nbuffers. At least two buffers are necessary to perform
ping-pong buffering (one buffer - ping - is used to receive data while the
other one - pong - is used to process data).
*******************************************************************************/
#define MAX_UDP_BUFFERS 4
/*******************************************************************************
* *
* GLOBALS *
* *
*******************************************************************************/
/*******************************************************************************
program name
*******************************************************************************/
char *program_name = "Nettest";
extern far char *domain_name;
/*******************************************************************************
create UDP data buffer
NBuffer_t is defined in nbuffer.h
*******************************************************************************/
#ifdef USE_STATIC_MEMORY
#pragma DATA_SECTION(udp_buffer , ".data_slow");
#endif
NBuffer_t udp_buffer[MAX_UDP_BUFFERS]; /* 4 buffers for UDP echo */
/*******************************************************************************
UDP socket
*******************************************************************************/
SOCKET *udp_echo_so = INVALID_SOCKET; /* UDP socket */
/*******************************************************************************
create and pre-initialize control structure for UDP echo buffers
NBCtl_t is defined in nbuffer.h
*******************************************************************************/
{
udp_buffer, /* buffers */
sizeof(NBuffer_t), /* size of NBuffer_t */
0, /* used */
0, /* out of buffer memory */
BUFFER_EMPTY, /* receive index */
BUFFER_EMPTY, /* process index */
MAX_UDP_BUFFERS, /* max buffers */
0, /* use static memory */
#else
1, /* use dynamic memory */
#endif
MAX_NBUFFER_SIZE /* NBuffer size limit */
};
/*******************************************************************************
TCP socket
*******************************************************************************/
SOCKET *tcp_server = INVALID_SOCKET; /* TCP socket */
static char tcp_rx[16]; /* buffer for TCP requests */
static char tcp_tx[27] = "this is the DSP response\r\n";
#define TX_SIZE (uint32_t)sizeof(tcp_tx)
/*******************************************************************************
* *
* FUNCTIONS *
* *
*******************************************************************************/
/*******************************************************************************
@brief This function is called each time new UDP data is received or the
UDP event status has changed (MSB set in error code)
@param so - socket
@param data - pointer to received data
@param len - received data length
@param ec - error code
@return SOCKET_CB_OK - if message processed
@return SOCKET_CB_CLOSED - if socket was closed
@details Function udp_call_back is immediately called from net_isq() in case
of new data waiting in receive buffer or in case of socket events
which require user intervention. Since all necessary buffer
pointers, length information and socket flags are saved in the
nbuffer control structure, parameter data, len and ec are not used
in this example and declared as UNREFERENCED_PARAMETER.
As a precondition for this example a valid nbuffer control
structure must be assigned to the socket user_pointer during
initialization.
Function net_recv_event_handler() is used to detect new data or
to handle socket events.
In case of new data (data_len > 0) the current data size is saved
to bctl-> Buf[bctl-> ri].Size for later processing, the process
index is set to this buffer if not already busy and a new buffer is
allocated by function NBufferAcquireBuffer().
@note Precondition for proper function is a valid nbuffer control
structure assigned to the socket user_pointer
*******************************************************************************/
int32_t udp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec)
{
/***************************************************************************
locals
***************************************************************************/
NBCtl_t *bctl = (NBCtl_t *)so-> user_pointer; /* get buffer control */
int32_t data_length; // net_recv_event_handler() return parameter
/***************************************************************************
suppress unused parameter warnings
***************************************************************************/
UNREFERENCED_PARAMETER(data); // replaced by bctl-> Buf[].Data
UNREFERENCED_PARAMETER(ec); // handled in net_recv_event_handler()
UNREFERENCED_PARAMETER(len); // len is ignored, data_len is used instead
/***************************************************************************
Check events
If NULL is passed as pLog parameter, no message is printed to output.
Use net_recv_event_handler() to determine the data length waiting in the
receive buffer
***************************************************************************/
data_length = net_recv_event_handler (so, CPrintf); /* with messages */
// data_length = net_recv_event_handler (so, NULL); /* without messages */
/***************************************************************************
net_recv_event_handler() returns the amount of data waiting in the buffer
***************************************************************************/
if (data_length)
{
// CPrintf ("received %"PRId32" bytes\r\n", data_length);
if ( bctl == NULL )
{
/*******************************************************************
no control structure available, buffer processing not possible
*******************************************************************/
return (SOCKET_CB_OK);
} // if
/***********************************************************************
if "OutOfBuffer" error occurred before, this is an overrun condition
and the previous packet is lost
***********************************************************************/
if ( bctl-> OutOfBuffer )
{
/***************************************************************
reset flag and try to allocate new buffer later
***************************************************************/
bctl-> OutOfBuffer = FALSE;
/***************************************************************
signal this error to user or switch a LED on
***************************************************************/
LED_on(1);
}
/***********************************************************************
new data is available in buffer that has been previously assigned by
socket_define_callback() or set_recv_buffer() function.
The receive index bctl-> ri should always point to the active buffer
and is maintained in NBufferAcquireBuffer()
***********************************************************************/
/***********************************************************************
save packet size, useful for later processing
***********************************************************************/
bctl-> Buf[bctl-> ri].Size = data_length;
/***********************************************************************
set process index to this buffer, if not already set.
this starts the processing task in main.
if bctl-> pi is not BUFFER_EMPTY, processing is already in progress
***********************************************************************/
if ( bctl-> pi == BUFFER_EMPTY )
{
bctl-> pi = bctl-> ri;
} // if
/***********************************************************************
malloc space for new data
***********************************************************************/
if ( NBufferAcquireBuffer (so) == NULL)
{
/*******************************************************************
allocation failed due to all buffers in use.
this may happen when the receive task works faster than the signal
processing task. due to the lack of flow control (like TCP), this
is a possible overrun condition when the next packet has to be
received. set OutOfBuffer flag to handle this condition later
*******************************************************************/
bctl-> OutOfBuffer = TRUE;
} // if
}
/***************************************************************************
return true, if message processed
***************************************************************************/
return (SOCKET_CB_OK);
}
#ifdef USE_TCP_CALLBACK
/*******************************************************************************
@brief This function is called each time new TCP data is received or the
TCP event status has changed (MSB set in error code)
@param so - socket
@param data - pointer to received data
@param len - received data length
@param ec - error code
@return SOCKET_CB_OK - if message processed
@return SOCKET_CB_CLOSED - if socket was closed
@details Function tcp_call_back is immediately called from net_isq() in case
of new data waiting in receive buffer or in case of socket events
which require user intervention. Since parameter data, len and ec
are not used in this example, UNREFERENCED_PARAMETER is used to
suppress compiler unused warnings.
Function net_recv_event_handler() is used to detect new data or
to handle socket events.
In case of new data (data_len > 0) this packet is counted to send
a message in main.
*******************************************************************************/
int32_t tcp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec)
{
/***************************************************************************
locals
***************************************************************************/
int32_t data_length; // net_recv_event_handler() return parameter
/***************************************************************************
suppress unused parameter warning
***************************************************************************/
UNREFERENCED_PARAMETER(data); // not used here, data is discarded
UNREFERENCED_PARAMETER(ec); // handled in net_recv_event_handler()
UNREFERENCED_PARAMETER(len); // len is ignored, data_len is used instead
/***************************************************************************
Check events
If NULL is passed as pLog parameter, no message is printed to output.
Use net_recv_event_handler() to determine the data length waiting in the
receive buffer
***************************************************************************/
data_length = net_recv_event_handler (so, CPrintf); /* with messages */
// data_length = net_recv_event_handler (so, NULL); /* without messages */
/***************************************************************************
net_recv_event_handler()returns the amount of data waiting in the buffer
***************************************************************************/
if (data_length)
{
// CPrintf ("received %"PRId32" bytes\r\n", data_length);
/***********************************************************************
TCP packet received
process data
here:discard data, count packets to send answer in main
***********************************************************************/
}
/***************************************************************************
return true, if message processed
***************************************************************************/
return (SOCKET_CB_OK);
}
#endif
/*******************************************************************************
@brief Process UDP data, send back echo
@param so - socket
@return -
@details This function monitors buffer allocation problems and tries to
allocate a new buffer if OutOfBuffer was signalled.
Furthermore the UDP input queue is checked, the buffer is processed
and the echo is sent back. After sending back the data, the buffer
is freed.
*******************************************************************************/
void process_data (SOCKET *so)
{
/***************************************************************************
locals
***************************************************************************/
NBCtl_t *bctl = (NBCtl_t *)so-> user_pointer; /* get buffer control */
char *buffer;
uint32_t size;
if ( bctl == NULL )
{
/***********************************************************************
no control structure available
***********************************************************************/
return;
} // if
/***************************************************************************
if allocation failed due to all buffers in use, OutOfBuffer flag was
set in udp_call_back(); try to allocate a new buffer
***************************************************************************/
if ( bctl-> OutOfBuffer )
{
if ( NBufferAcquireBuffer (so) != NULL )
{
/*******************************************************************
allocation successful,
reset OutOfBuffer flag,
*******************************************************************/
bctl-> OutOfBuffer = FALSE;
} // if
} // if
/***************************************************************************
check received UDP messages
process index bctl-> pi is set by the first received packet in udp_call_back()
and signals data waiting for processing
***************************************************************************/
if ( bctl-> pi != BUFFER_EMPTY )
{
/***********************************************************************
check "out of buffer" condition, set BUFFER_EMPTY flag when this buffer
was overwritten
***********************************************************************/
if ( bctl-> OutOfBuffer )
{
if ( bctl-> pi == bctl-> ri )
{
bctl-> pi = BUFFER_EMPTY;
return;
} // if
}
/***********************************************************************
process buffer if required
the next data to process is bctl-> Buf[bctl-> pi].Data
***********************************************************************/
buffer = (char*)bctl-> Buf[bctl-> pi].Data;
size = (uint32_t)bctl-> Buf[bctl-> pi].Size;
/***********************************************************************
send data back (UDP echo)
***********************************************************************/
net_send_safe (so, buffer , size, 0);
/***********************************************************************
it's safe to free this buffer here, UDP packets are not queued for
retransmission
***********************************************************************/
if ( NBufferFreeBuffer (so) )
{
/*******************************************************************
error occurred, no buffer control structure available
assign buffer control structure to socket-> user_pointer
during initialization
*******************************************************************/
prg_exit ("out of memory error");
} // if
}
}
/*******************************************************************************
@brief Main application
@param -
@return never
*******************************************************************************/
#pragma CODE_SECTION(main , ".commontext");
int main ( void )
{
/***************************************************************************
locals
***************************************************************************/
int main_loop = 1; /* main loop switch, set to 0 to exit */
timeval stamp1, stamp2, delta; /* used to determine startup time */
char conversion_buffer[16];
#ifndef USE_TCP_CALLBACK
int32_t data_length=0;
#endif
/***************************************************************************
initialize application (e.g. timer clocks, PLL settings, EMIF etc.)
(ref. \Common\Common.c)
***************************************************************************/
/***************************************************************************
select output device for CPrintf (ref. \Common\cprintf.c)
possible settings:
CPRINTF_UART_OUTPUT -> output to UART
CPRINTF_CCS_OUTPUT -> output to CCS
CPRINTF_UART_OUTPUT | CPRINTF_CCS_OUTPUT -> output to UART and CCS
***************************************************************************/
/***************************************************************************
print a start up message
***************************************************************************/
/**************************************************************************/
// CPrintfProgress (" Heap check ");
// at least 0x2000 bytes required for this app
/**************************************************************************/
// CPrintfProgressSuccess();
/**************************************************************************/
CPrintfProgress (" Setup system time ");
// 1 milli seconds resolution
/**************************************************************************/
CPrintf (" *** timer %d mapped to CPU int %d ***\r\n",
/**************************************************************************/
CPrintfProgress (" Enable interrupts ");
/**************************************************************************/
/**************************************************************************/
CPrintfProgress (" Start system timer ");
/**************************************************************************/
CPrintf (" *** timer %d running at %"PRId32" Hz ***\r\n", SystemTimerDev, RES_SECONDS/GetSystemTimerRes());
/***************************************************************************
measure network initialization time
***************************************************************************/
stamp1 = GetTimeStamp();
/**************************************************************************/
CPrintfProgress (" Initialize network ");
/**************************************************************************/
InitializeNetwork ( 64); // 64 bytes for ping
/***************************************************************************
create UDP echo socket
***************************************************************************/
{
prg_exit ("socket_open() error"); /* possibly insufficient heap */
}
/***************************************************************************
attach buffer control structure to socket
(required for NBufferAcquireBuffer() later)
***************************************************************************/
udp_echo_so-> user_pointer = (void *)&bcontrol;
/***************************************************************************
initially malloc space for data
NBufferAcquireBuffer() allocates new buffer space and modifies the
bcontrol structure data buffer pointer and receive index
***************************************************************************/
{
prg_exit ("out of memory error");
} // if
/***************************************************************************
install callback function
NBufferAcquireBuffer() has modified receive index ri to point to the next
buffer
***************************************************************************/
bcontrol.Buf[bcontrol.ri].Data ,
/***************************************************************************
create TCP data server socket on port 1061
***************************************************************************/
1061,
{
prg_exit ("socket_open() error"); /* possibly insufficient heap */
}
#ifdef USE_TCP_CALLBACK
/***************************************************************************
define callback function for received TCP packets
***************************************************************************/
sizeof(tcp_rx));
#endif
stamp2 = GetTimeStamp();
tv_interval (&delta, &stamp1, &stamp2);
CPuts (" network startup time [sec]: ");
"%"PRId32".%03"PRId32"\r\n"
delta.tv_sec,
delta.tv_usec/1000);
/***************************************************************************
main program loop: set main_loop to 0 to exit loop
***************************************************************************/
CPuts ("\r\n Entering main loop ...\r\n");
while ( main_loop )
{
/***********************************************************************
process net_isq()
***********************************************************************/
net_isq (); // process ISQ
/***********************************************************************
monitor link status
***********************************************************************/
/***********************************************************************
try to detect IP assignment
if DHCP is used, the assigned IP address may change
***********************************************************************/
{
CPuts ("\r\n To verify this program, first 'ping' the DSP:\r\n");
if (domain_name) CPrintf (">ping %s.%s\r\n", eth.ip, domain_name);
CPrintf (">ping %s\r\n\n", inet_ntoa(get_ip_address(0), conversion_buffer));
CPuts (" UDP test:\r\n");
if (domain_name) CPrintf (">nc -u %s.%s %d\r\n", eth.ip, domain_name, udp_echo_so-> src_port);
CPrintf (">nc -u %s %d\r\n\n", inet_ntoa(get_ip_address(0), conversion_buffer), udp_echo_so-> src_port);
CPuts (" TCP test\r\n");
if (domain_name) CPrintf (">nc %s.%s %d\r\n", eth.ip, domain_name, tcp_server-> src_port);
CPrintf (">nc %s %d\r\n", inet_ntoa(get_ip_address(0), conversion_buffer), tcp_server-> src_port);
}
/***********************************************************************
process UDP data
***********************************************************************/
#ifndef USE_TCP_CALLBACK
/***********************************************************************
two methods for buffer handling
1. always pass the buffer pointer to net_recv()
-> the buffer is reset with each call
2. passing a NULL pointer
-> the buffer is not changed; this requires a later call to
set_recv_buffer()(s.below) e.g. for ping-pong buffering
***********************************************************************/
if (net_recv (tcp_server, tcp_rx, sizeof(tcp_rx))) // method 1
// if (net_recv (tcp_server, NULL, 0)) // method 2
{
/*******************************************************************
check events
if NULL is passed as pLog parameter, no message is printed to output
use net_recv_event_handler() to determine the data length waiting
in the receive buffer
*******************************************************************/
data_length = net_recv_event_handler (tcp_server, CPrintf); /* with messages */
// data_length = net_recv_event_handler (tcp_server, NULL); /* without messages */
}
if (data_length)
{
// CPrintf ("received %"PRId32" data elements\r\n", data_length);
/*******************************************************************
new data available, process TCP buffer
*******************************************************************/
// ...
/*******************************************************************
reset receive buffer or choose different buffer for ping-pong
buffering (only for method 2, see above)
*******************************************************************/
// set_recv_buffer (tcp_server, tcp_rx, sizeof(tcp_rx));
/*******************************************************************
TCP packet received
process data, here:count packets to send answer in main
*******************************************************************/
data_length = 0;
}
#endif
/***********************************************************************
check received TCP messages
***********************************************************************/
if ( tcp_received )
{
/*******************************************************************
send TCP message
*******************************************************************/
if (net_send_safe (tcp_server, tcp_tx, TX_SIZE, TCP_WAIT) == 0)
{
/***************************************************************
fatal error occurred, reset received counter, do other things
to stop transmission etc.
***************************************************************/
}
} // if
/***********************************************************************
show that the program is running, perform symbol animation
***********************************************************************/
}
/***************************************************************************
exit program, shut down peripherals
***************************************************************************/
return (0);
}