pserver.c File Reference

Concurrent Server Example. More...

#include <BoardSupport/inc/stdtypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
#include <Libs/Netlib/net.h>
#include <Libs/Netlib/pserver.h>
#include <BoardSupport/inc/BoardSpecific.h>
#include <Common/Common.h>
#include <Common/uartio.h>
#include <Common/timer.h>
#include <Common/CPrintf.h>
#include <BoardSupport/config/netconfig.c>

Data Structures

struct  echoserv_type
 

Macros

#define _ECHO_RECEIVE_BUFFER   1460L
 
#define _ECHO_LISTENING   0
 
#define _ECHO_ESTABLISHED   1
 

Functions

int32_t tcp_echo (SOCKET *so, void *data, uint32_t len, uint32_t ec)
 
int close_parallel_echo_server (SOCKET *so)
 
int init_parallel_echo_server (SOCKET *so)
 
int main (void)
 

Variables

char * program_name = "pserver"
 
_PARALLEL_SERVER * _ECHO_SERVER_HEAD = NULL
 
_PARALLEL_SERVER * echo_pserver = NULL
 
unsigned int echo_socket_counter = 0
 

Detailed Description

                          _         _             _
                       __| |    ___(_) ____ _ __ | |_
                      / _` |   / __| |/ _` | '_ \| __|
                     | (_| | _ \__ \ | (_| | | | | |_
                      \__,_|(_) ___/_|\__, |_| |_|\__|
                     Signalprocessing |___/ Technology
Author
D.SignT GmbH & Co. KG, Claus Hermbusche
Date
2019-06-03

This program installs a concurrent TCP echo server on port 5031.

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

>ping 192.168.168.200

or

>ping mydemo

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

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

>nc 192.168.168.200 5031
           |        |
           |        +-- port 5031 = User Echo Port
           +----------- the DSP's IP address

or

>nc mydemo 5031
      |     |
      |     +----- port 5031 = User Echo Port
      +----------- the DSP hostname

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 TCP echo (MAX_DATA = 1024).

Using parallel servers:

The user defined function 'init_parallel_echo_server()' must be called once to have at least one listening socket. After connecting this socket, the callback function tcp_echo() is called from TCP stack with error code SO_CONNECTION_ESTABLISHED. The next 'init_parallel_echo_server()' function call increases the server list. The new opened server socket is auto- matically in listening state and can be connected from the next client. After disconnecting one client, the TCP stack calls the user callback function again. This time with error code SO_CONNECTION_CLOSED (or SO_CONNECTION_RESET ). Call 'close_parallel_echo_server()' to decrease the server list and free all associated memory.

Macro Definition Documentation

#define _ECHO_RECEIVE_BUFFER   1460L
Examples:
PServer.c.
#define _ECHO_LISTENING   0
Examples:
PServer.c.
#define _ECHO_ESTABLISHED   1
Examples:
PServer.c.

Function Documentation

int32_t tcp_echo ( SOCKET *  so,
void *  data,
uint32_t  len,
uint32_t  ec 
)
236 {
237  /***************************************************************************
238  it's safe to use ec unmasked, because the event flag (MSB) is reset before
239  this callback function is called
240  ***************************************************************************/
241  switch (ec)
242  {
243  case SO_NO_ERROR:
244  /*******************************************************************
245  send echo
246  *******************************************************************/
247  net_send (so, data, (uint16_t)len);
248  break;
249 
251  /*******************************************************************
252  get a new listening server
253  *******************************************************************/
254  if (init_parallel_echo_server (so))
255  {
256  /***************************************************************
257  print error code
258  ***************************************************************/
259  CPuts ("\r ");
260  net_print_error (ec, CPrintf);
261  CPrintf (" %d concurrent sockets\r\n", echo_socket_counter);
262  }
263  else
264  {
265  /***************************************************************
266  print error code
267  ***************************************************************/
268  CPuts ("\r Out of memory\r\n");
269  shutdown (so, 100L);
270  }
271  break;
272 
274  case SO_CONNECTION_RESET :
275  /*******************************************************************
276  close the server
277  *******************************************************************/
279 
280  /*******************************************************************
281  print error code
282  *******************************************************************/
283  CPuts ("\r ");
284  net_print_error (ec, CPrintf);
285  CPrintf (" %d concurrent sockets\r\n", echo_socket_counter);
286 
287  /*******************************************************************
288  return -1 signals socket is invalid
289  *******************************************************************/
290  return (SOCKET_CB_CLOSED);
291 
292  default:
293  /*******************************************************************
294  else print error code
295  *******************************************************************/
296  CPuts ("\r ");
297  net_print_error (ec, CPrintf);
298  break;
299  }
300 
301  /***************************************************************************
302  return true, if message processed
303  ***************************************************************************/
304  return (SOCKET_CB_OK);
305 }
int close_parallel_echo_server(SOCKET *so)
Definition: pserver.c:315
int32_t shutdown(SOCKET *so, int32_t timeout)
Active shut-down of a TCP connection.
#define SO_CONNECTION_CLOSED
Definition: net.h:472
#define SOCKET_CB_CLOSED
Definition: net.h:577
unsigned short uint16_t
Definition: stdint.h:45
int CPrintf(const char *_format,...)
Custom printf function.
Definition: cprintf.c:708
unsigned int echo_socket_counter
Definition: pserver.c:212
#define SO_CONNECTION_ESTABLISHED
Definition: net.h:474
int32_t net_send(SOCKET *so, void *data, uint16_t len)
Send a message via the specified socket.
int init_parallel_echo_server(SOCKET *so)
Definition: pserver.c:373
#define SO_CONNECTION_RESET
Definition: net.h:467
#define SOCKET_CB_OK
Definition: net.h:576
int CPuts(const char *_ptr)
Definition: cprintf.c:399
#define SO_NO_ERROR
Definition: net.h:461
int close_parallel_echo_server ( SOCKET *  so)
Examples:
PServer.c.
316 {
317  /***************************************************************************
318  Locals
319  ***************************************************************************/
320  _PARALLEL_SERVER *echo_pserver = NULL;
321  echoserv_type *echo_info; // used for protocol information for
322  // each connection
323 
324  /***************************************************************************
325  get control information for current server
326  ***************************************************************************/
327  echo_pserver = get_current_pserver (so, &_ECHO_SERVER_HEAD);
328  echo_info = (echoserv_type *)(echo_pserver-> info);
329 
330  echo_pserver-> close = TRUE;
331 
332  if ( echo_pserver-> state > _ECHO_LISTENING )
333  {
334  /***********************************************************************
335  connection closed or terminated:
336  free all protocol specific buffers
337  ***********************************************************************/
338  if ( echo_info-> control_buffer != NULL )
339  {
340  free (echo_info-> control_buffer);
341  echo_info-> control_buffer = NULL;
342 
343  free (echo_info);
344  echo_pserver-> info = NULL;
345  }
346 
347  /***********************************************************************
348  use close() method to delete the terminated or closed server
349  ***********************************************************************/
350  echo_pserver = close_pserver (echo_pserver, &_ECHO_SERVER_HEAD);
351 
352  /***********************************************************************
353  correct current connection counter
354  ***********************************************************************/
356  }
357 
358  /***************************************************************************
359  return true, if message processed
360  ***************************************************************************/
361  return (1);
362 }
#define _ECHO_LISTENING
Definition: pserver.c:172
_PARALLEL_SERVER * echo_pserver
Definition: pserver.c:207
#define NULL
Definition: net.h:126
_PARALLEL_SERVER * close_pserver(_PARALLEL_SERVER *pserver, _PARALLEL_SERVER **pserver_head)
Erase a node from a concurrent server list.
_PARALLEL_SERVER * get_current_pserver(SOCKET *so, _PARALLEL_SERVER **pserver_head)
Search pserver list for current socket.
unsigned int echo_socket_counter
Definition: pserver.c:212
Definition: pserver.c:179
_PARALLEL_SERVER * _ECHO_SERVER_HEAD
Definition: pserver.c:202
int init_parallel_echo_server ( SOCKET *  so)
Examples:
PServer.c.
374 {
375  /***************************************************************************
376  Locals
377  ***************************************************************************/
378  _PARALLEL_SERVER *pserver = NULL;
379  echoserv_type *echo_info; // used for protocol information for
380  // each connection
381 
382  /***************************************************************************
383  add a new pserver to server list
384  first parameter: Port to listen on
385  second parameter: user defined head of server list
386  ***************************************************************************/
387  pserver = add_pserver (5031, &_ECHO_SERVER_HEAD);
388 
389  if ( pserver == NULL )
390  {
391  /***********************************************************************
392  out of memory
393  ***********************************************************************/
394  return (FALSE);
395  }
396 
397  /***************************************************************************
398  create a protocol info and link it to the parallel server
399  echoserv_type is a user defined structure type containing all
400  information needed for protocol handling
401  ***************************************************************************/
402  pserver-> info = (echoserv_type *) malloc ( sizeof( echoserv_type));
403 
404  if ( pserver-> info == NULL )
405  {
406  /***********************************************************************
407  out of memory, use close() method to delete the listening server
408  ***********************************************************************/
409  close_pserver (pserver, &_ECHO_SERVER_HEAD);
410 
411  return (FALSE);
412  }
413 
414  /***************************************************************************
415  initialize protocol specific information
416  ***************************************************************************/
417  echo_info = (echoserv_type *)(pserver-> info);
418  echo_info-> control = INVALID_SOCKET;
419 
420  /***************************************************************************
421  get buffer space for control data
422  ***************************************************************************/
423  echo_info-> control_buffer = (char *) malloc (_ECHO_RECEIVE_BUFFER * sizeof (char));
424 
425  if ( echo_info-> control_buffer == NULL )
426  {
427  /***********************************************************************
428  out of memory, use close() method to delete the listening server
429  ***********************************************************************/
430  free (echo_info);
431 
432  pserver = close_pserver (pserver, &_ECHO_SERVER_HEAD);
433 
434  return (FALSE); // out of memory
435  } // if
436 
437  /***************************************************************************
438  define callback function for received TCP packets
439  ***************************************************************************/
440  socket_define_callback (pserver-> server, /* socket */
441  tcp_echo, /* call back function */
442  echo_info-> control_buffer, /* data buffer */
443  _ECHO_RECEIVE_BUFFER); /* data buffer size */
444 
445  /***************************************************************************
446  count the current sockets
447  ***************************************************************************/
449 
450  if (so != INVALID_SOCKET)
451  {
452  pserver = get_current_pserver (so, &_ECHO_SERVER_HEAD);
453 
454  /***********************************************************************
455  switch to established state
456  ***********************************************************************/
457  pserver-> state = _ECHO_ESTABLISHED;
458  pserver-> close = FALSE;
459  }
460 
461  return (TRUE);
462 }
void socket_define_callback(SOCKET *so, int32_t(*call_back_function)(SOCKET *, void *, uint32_t, uint32_t), void *data, uint16_t maxdata)
Install a user callback function for a specific socket.
#define NULL
Definition: net.h:126
_PARALLEL_SERVER * add_pserver(uint16_t proto, _PARALLEL_SERVER **pserver_head)
Add a new concurrent server to the double linked list.
_PARALLEL_SERVER * close_pserver(_PARALLEL_SERVER *pserver, _PARALLEL_SERVER **pserver_head)
Erase a node from a concurrent server list.
#define _ECHO_RECEIVE_BUFFER
Definition: pserver.c:167
_PARALLEL_SERVER * get_current_pserver(SOCKET *so, _PARALLEL_SERVER **pserver_head)
Search pserver list for current socket.
unsigned int echo_socket_counter
Definition: pserver.c:212
Definition: pserver.c:179
#define _ECHO_ESTABLISHED
Definition: pserver.c:173
int32_t tcp_echo(SOCKET *so, void *data, uint32_t len, uint32_t ec)
Definition: pserver.c:235
#define INVALID_SOCKET
Definition: net.h:540
_PARALLEL_SERVER * _ECHO_SERVER_HEAD
Definition: pserver.c:202
int main ( void  )
473 {
474  /***************************************************************************
475  locals
476  ***************************************************************************/
477  int main_loop = 1; /* main loop switch, set to 0 to exit */
478  timeval stamp1, stamp2, delta; /* used to determine startup time */
479 
480  /***************************************************************************
481  initialize application (e.g. timer clocks, PLL settings, EMIF etc.)
482  (ref. \Common\Common.c)
483  ***************************************************************************/
484  AppInit (GET_CLOCK);
485 
486  /***************************************************************************
487  select output device for CPrintf (ref. \Common\cprintf.c)
488  possible settings:
489  CPRINTF_UART_OUTPUT -> output to UART
490  CPRINTF_CCS_OUTPUT -> output to CCS
491  CPRINTF_UART_OUTPUT | CPRINTF_CCS_OUTPUT -> output to UART and CCS
492  ***************************************************************************/
493  CPrintf_select_output (CPRINTF_DEFAULT_OUTPUT); /* default outputs */
494 
495  /***************************************************************************
496  print a start up message
497  ***************************************************************************/
498  START_UP_MESSAGE (BLANK_REV NETLIB_REV);
499 
500  /**************************************************************************/
501  // CPrintfProgress (" Heap check ");
502  // at least 0x2000 bytes required for this app
503  /**************************************************************************/
504  ASSERT_HEAP (initial_heap_size, 0x2000);
505  // CPrintfProgressSuccess();
506 
507  /**************************************************************************/
508  CPrintfProgress (" Setup system time ");
509  // 1 milli seconds resolution
510  /**************************************************************************/
513  CPrintf (" *** timer %d mapped to CPU int %d ***\r\n",
515 
516  /**************************************************************************/
517  CPrintfProgress (" Enable interrupts ");
518  /**************************************************************************/
521 
522  /**************************************************************************/
523  CPrintfProgress (" Start system timer ");
524  /**************************************************************************/
525  StartSystemTimer ();
527  CPrintf (" *** timer %d running at %"PRId32" Hz ***\r\n", SystemTimerDev, RES_SECONDS/GetSystemTimerRes());
528 
529  /***************************************************************************
530  measure network initialization time
531  ***************************************************************************/
532  stamp1 = GetTimeStamp();
533 
534  /**************************************************************************/
535  CPrintfProgress (" Initialize network ");
536  /**************************************************************************/
537  InitializeNetwork ( 64); // 64 bytes for ping
538 
539  /***************************************************************************
540  the first call to init_parallel_echo_server() creates a listening socket
541  ***************************************************************************/
544 
545  stamp2 = GetTimeStamp();
546 
547  tv_interval (&delta, &stamp1, &stamp2);
548  CPuts (" network startup time [sec]: ");
550  "%"PRId32".%03"PRId32"\r\n"
552  delta.tv_sec,
553  delta.tv_usec/1000);
554 
555 
556  /***************************************************************************
557  loop forever
558  ***************************************************************************/
559  CPrintf (" %s running on address %s\r\n", program_name, eth.ip);
560  CPuts ("\r\n Entering main loop ...\r\n");
561 
562  /***************************************************************************
563  main program loop: set main_loop to 0 to exit loop
564  ***************************************************************************/
565  while ( main_loop )
566  {
567  /***********************************************************************
568  process net_isq()
569  ***********************************************************************/
570  net_isq (); // process ISQ
571 
572  /***********************************************************************
573  monitor link status
574  ***********************************************************************/
576 
577  /***********************************************************************
578  try to detect IP assignment
579  if DHCP is used, the assigned IP address may change
580  ***********************************************************************/
582 
583  /***********************************************************************
584  show that the program is running, perform symbol animation
585  ***********************************************************************/
587  }
588 
589  /***************************************************************************
590  exit program, shut down peripherals
591  ***************************************************************************/
592  return (0);
593 }
void BoardEnableInterrupts(void)
global enable interrupts
Definition: BoardSpecific.c:365
#define ANIMATE_SYMBOLS_COUNT
Definition: BoardSpecific.h:268
void StartSystemTimer(void)
start system timer
Definition: timer.c:447
#define RES_MSECONDS
Definition: timer.h:67
uint16_t CPrintf_select_output(uint16_t device)
Definition: cprintf.c:206
#define ASSERT_HEAP(i, h)
Definition: Common.h:262
#define NULL
Definition: net.h:126
time_t GetSystemTimerRes(void)
Definition: timer.c:160
#define GET_CLOCK
Definition: BoardSpecific.h:258
int CPrintf(const char *_format,...)
Custom printf function.
Definition: cprintf.c:708
#define VT100_DEFAULT
Definition: cprintf.h:150
void SetupSystemTime(int32_t cpuint, int port, time_t resolution)
Setup System Time.
Definition: timer.c:392
void AppInit(uint32_t dsp_clock)
Initialize application.
Definition: Common.c:230
uint32_t initial_heap_size
Definition: Common.c:140
#define CPRINTF_DEFAULT_OUTPUT
Definition: BoardSpecific.h:129
#define VT100_RED
Definition: cprintf.h:143
uint16_t CPrintAnimatedSymbol(char *c, time_t period, size_t size)
Definition: cprintf.c:816
int InitializeNetwork(uint16_t icmp_size)
Initialize MAC, sockets and protocols.
Definition: BoardSpecific.c:597
char sym_animate[]
Definition: BoardSpecific.c:129
Definition: timer.h:75
#define GetTimeStamp()
Definition: timer.h:81
void tv_interval(timeval *e, timeval *t1, timeval *t2)
compute elapsed time
Definition: timer.c:336
#define SYSTEM_TIMER_INT
Definition: BoardSpecific.h:174
#define SYSTEM_TIMER
Definition: BoardSpecific.h:167
int init_parallel_echo_server(SOCKET *so)
Definition: pserver.c:373
void net_isq(void)
The main polling function for processing sockets, must be periodically called in the main application...
char ip[31]
Definition: net.h:170
#define BLANK_REV
Definition: BoardSpecific.h:191
Uint16 SystemTimerDev
adapter_t eth
Definition: netconfig.c:62
uint16_t monitor_ip_address(tpOutputFunc pLog)
monitor IP assignment
Definition: BoardSpecific.c:545
#define START_UP_MESSAGE(rev)
Definition: BoardSpecific.h:192
char * program_name
Definition: pserver.c:196
#define RES_SECONDS
Definition: timer.h:70
uint16_t monitor_link_status(tpOutputFunc pLog)
monitor link status change
Definition: BoardSpecific.c:497
int CPuts(const char *_ptr)
Definition: cprintf.c:399
time_t tv_sec
Definition: timer.h:77
#define CPrintfProgress(s)
Definition: cprintf.h:230
time_t tv_usec
Definition: timer.h:78
#define CPrintfProgressSuccess()
Definition: cprintf.h:263

Variable Documentation

char* program_name = "pserver"
_PARALLEL_SERVER* _ECHO_SERVER_HEAD = NULL
Examples:
PServer.c.
_PARALLEL_SERVER* echo_pserver = NULL
Examples:
PServer.c.
unsigned int echo_socket_counter = 0
Examples:
PServer.c.