Blocksend.c

Blocksend.c example details

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.

Use Netcat to establish a TCP connection on port 5031:

>nc 192.168.168.200 5031 > test.dat

A continuous data stream will be written into test.dat until the connection is closed.

See also
TCP Transmission Control Protocol
/***************************************************************************//**
@file Blocksend.c
@brief Sending a continuous data stream over TCP
@verbatim
_ _ _
__| | ___(_) ____ _ __ | |_
/ _` | / __| |/ _` | '_ \| __|
| (_| | _ \__ \ | (_| | | | | |_
\__,_|(_) ___/_|\__, |_| |_|\__|
Signalprocessing |___/ Technology
@endverbatim
@author D.SignT GmbH & Co. KG, Claus Hermbusche
@date 2019-06-03
@anchor BLOCKSENDEX
@details
To verify this program, first 'ping' the DSP:
>ping 192.168.168.200
or, if configured for DHCP
>ping mydemo
If the settings and network connections are correct, the pings will be
replied.
Establish a TCP connection on port 5031:
>nc 192.168.168.200 5031 > test.dat
or
>nc mydemo 5031 > test.dat
A continuous data stream will be written into test.dat until the connection
is closed.
@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 */
#ifdef __cplusplus
extern "C" {
#endif /* !__cplusplus */
/*******************************************************************************
local prototypes
*******************************************************************************/
#ifdef __cplusplus
} // extern "C"
#endif
/*******************************************************************************
* *
* DEFINES *
* *
*******************************************************************************/
#define LOCAL_TCP_PORT 5031
/*******************************************************************************
* *
* GLOBALS *
* *
*******************************************************************************/
/*******************************************************************************
program name
*******************************************************************************/
char *program_name = "blocksend";
extern far char *domain_name;
/*******************************************************************************
data buffer
*******************************************************************************/
// #pragma DATA_SECTION(data_buffer,".data");
static unsigned char data_buffer[TCP_SEND_BUFFER_SIZE];
uint32_t transmitting = FALSE; /* TRUE if transmission activated */
uint32_t dhcp_active = FALSE; /* TRUE if configured for dhcp */
static char buffer[100]; /* buffer for incoming TCP data */
timeval connect_stamp1; /* used to determine connection time */
/*******************************************************************************
* *
* FUNCTIONS *
* *
*******************************************************************************/
/*******************************************************************************
@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_echo_cb 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.
*******************************************************************************/
int32_t tcp_echo_cb (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); // 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);
}
/***************************************************************************
use this callback to detect a timeout
***************************************************************************/
switch ( ec & SO_ERROR_MASK )
{
case SO_TIMED_OUT: // timeout detected, shutdown connection
break;
default:
break;
}
/***************************************************************************
Return true, if socket was not closed before
***************************************************************************/
return (SOCKET_CB_OK);
}
/*******************************************************************************
@brief open a new TCP server socket
@param -
@return opened TCP server socket
*******************************************************************************/
SOCKET *open_tcp_server (void)
{
/***************************************************************************
locals
***************************************************************************/
SOCKET *so = INVALID_SOCKET;
if ( so == INVALID_SOCKET )
{
prg_exit ("socket_open() error"); /* possibly insufficient heap */
}
/***************************************************************************
set keep alive time 5 seconds (three unanswered packets within 5 seconds)
***************************************************************************/
/***************************************************************************
install callback function
***************************************************************************/
/***************************************************************************
increase unacknowledged segment size
***************************************************************************/
/***************************************************************************
set lower re-transmit delay
***************************************************************************/
// tcp_set_option( so, TCP_RETRANS_DELAY, 0x20); //default 0x40
return (so);
}
/*******************************************************************************
@brief monitor link status change
@param pLog - printf function or NULL
@return TRUE (1) - link status changed
@return FALSE (0) - link status not changed
@details Use this function in your main loop to detect a link status change.
Global flag _link_mode is monitored and in case of change a LED
can be toggled or a message can be printed on the default output
terminal.
Parameter pLog can be a standard formatted print function like
printf or CPrintf. If this parameter is NULL, no output is printed.
The return value can be used for event processing in case of a
status change.
@note _link_mode is only valid, if a link_status callback function is
used and the _link_mode is set.
@example DHCPTest.c
*******************************************************************************/
{
/***************************************************************************
locals
***************************************************************************/
static uint8_t _link_mode_old = 0xff;
if (_link_mode_old != _link_mode)
{
_link_mode_old = _link_mode;
if (pLog) pLog ("\n\r Link status changed: ");
switch (_link_mode)
{
case 0xff:
LED_off (2);
/***************************************************************
shutdown connection and close socket
***************************************************************/
if (pLog) pLog ("No Link\r\n");
break;
default:
LED_on (2);
/***************************************************************
if not configured for DHCP, open a new TCP server socket
***************************************************************/
{
}
if (pLog) pLog ("Linked at %d Mbit %s duplex\r\n",
(_link_mode & SPEED_100) ? 100:10,
(_link_mode & FULL_DUPLEX) ? "full":"half");
break;
}
return (1);
}
return (0);
}
/*******************************************************************************
@brief Main application
@param -
@return never
*******************************************************************************/
int main ( void )
{
/***************************************************************************
locals
***************************************************************************/
int main_loop = 1; /* main loop switch, set to 0 to exit */
char conversion_buffer[16];
struct tm *local_time; /* structure to hold time and date */
timeval stamp2, delta; /* used to determine session time */
static timeval CurrentTimeStamp;
/***************************************************************************
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 ");
/**************************************************************************/
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());
/**************************************************************************/
CPrintfProgress (" Initialize network ");
/**************************************************************************/
InitializeNetwork ( 64); // 64 bytes for ping
/***************************************************************************
detect if program was configured for DHCP
***************************************************************************/
if (!((eth.ip[0]-'0')<=9))
{
dhcp_active = TRUE;
}
else
{
}
/***************************************************************************
main program loop: set main_loop to 0 to exit loop
***************************************************************************/
CPuts ("\r\n Entering main loop ...");
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
***********************************************************************/
{
/*******************************************************************
in case of DHCP open a new TCP server after IP assignment
*******************************************************************/
{
}
/*******************************************************************
print what to do next
*******************************************************************/
CPrintf (" Establish a TCP connection on port %d:\r\n", tcp_server-> src_port);
if (domain_name) CPrintf (">nc %s.%s %d > test.dat\r\n or\r\n",
tcp_server-> src_port);
CPrintf (">nc %s %d > test.dat\r\n",
inet_ntoa(get_ip_address(0), conversion_buffer),
tcp_server-> src_port);
CPuts (" A continuous data stream will be written into test.dat\r\n until the connection is closed.\r\n");
}
/***********************************************************************
TCP output
***********************************************************************/
if ( accept (tcp_server) && (_link_mode != 0xff)) /* if connection established */
{
/*******************************************************************
if TCP connection established but transmitting flag not set, a new
connection has started.
*******************************************************************/
if (transmitting == FALSE)
{
transmitting = TRUE; /* set flag for transmission */
/***************************************************************
take time stamp when the connection started
***************************************************************/
connect_stamp1 = GetTimeStamp();
}
else
{
/***************************************************************
show that the program is running, print connection time
***************************************************************/
if ( tv_elapsed (&CurrentTimeStamp, UINT32_C(1), UINT32_C(0), TRUE) )
{
/***********************************************************
get current time
***********************************************************/
stamp2 = GetTimeStamp();
/***********************************************************
calculate elapsed time
***********************************************************/
tv_interval (&delta, &connect_stamp1, &stamp2);
local_time = localtime ((const time_t *)&delta);
CPrintf (CLRLINE" %02d:%02d:%02d",
local_time->tm_hour, local_time->tm_min, local_time->tm_sec );
}
}
/*******************************************************************
check data currently in transmission (wait for completion was not
used in net_send_safe() below)
two approaches:
1. use tcp_tx_complete()
2. determine pending data with tcp_pending_window() and decide
if sending new data is safe
*******************************************************************/
// if ( tcp_pending_window (tcp_server) < TCP_MAX_PACKET_SIZE )
{
/***************************************************************
process buffer, generate new data
***************************************************************/
/* ... */
/***************************************************************
send data block
no need to wait for completion here because tcp_pending_window()
is used above to prevent net_send_safe() being called while
data is pending.
***************************************************************/
if (net_send_safe (tcp_server,
TCP_NOWAIT) == 0)
{
/***********************************************************
fatal error occurred, stop transmission
***********************************************************/
}
}
else
{
/***************************************************************
more than one packet is pending, don't touch the buffer!
***************************************************************/
} // if
}
else
{
{
/***************************************************************
connection stopped
***************************************************************/
transmitting = FALSE; /* clear transmission flag */
/***************************************************************
get current time
***************************************************************/
stamp2 = GetTimeStamp();
/***************************************************************
calculate elapsed time
***************************************************************/
tv_interval (&delta, &connect_stamp1, &stamp2);
local_time = localtime ((const time_t *)&delta);
CPrintf (" connection duration [hh:mm:ss]: ");
" %02d:%02d:%02d\r\n"
local_time->tm_hour, local_time->tm_min, local_time->tm_sec );
}
/*******************************************************************
show that the program is running
*******************************************************************/
if ((get_ip_address (0)) != UINT32_C(0))
{
CPrintProgressBarText ('<', 500000, 1, " waiting for connection ");
}
}
}
/***************************************************************************
exit program, shut down peripherals
***************************************************************************/
return (0);
}