/* Revision: 2.7.5 */

/******************************************************************************
* Copyright 1998-2016 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 its derivatives in part or in
*    whole are granted.
*
*    It may be possible to license this or other NetBurner software for use on
*    non-NetBurner Hardware. Contact sales@Netburner.com for more information.
*
*    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
* 5405 Morehouse Dr.
* San Diego, CA 92121
* www.netburner.com
******************************************************************************/


/******************************************************************************
 UDP Sockets Example
 This application will send/receive UDP packets with another host on a network,
 such as a PC. Use the MTTTY serial port program to access the menu and
 prompts to specify the destination IP address and port number.

 NetBurner supplies an API for handling UDP as a C++ Class using UDPPacket, or
 you can use a UDP socets API (see UDP socet example).

 For an external UDP host you can use the NetBurner java example, or the
 NetBurner UDP terminal program.
*****************************************************************************/
#include "predef.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <startnet.h>
#include <ucos.h>
#include <udp.h>
#include <autoupdate.h>
#include <string.h>
#include <taskmon.h>
#include <dhcpclient.h>
#include <networkdebug.h>

const char *AppName = "UDP Sockets Example";

extern "C"
{
   void UserMain( void *pd );
}


// Declare a task stack for the UDP Reader task
DWORD UdpReaderStack[USER_TASK_STK_SIZE];


/*-------------------------------------------------------------------
 * This task will wait for incoming UDP packets and process them.
 ------------------------------------------------------------------*/
void UdpReaderTask( void *pd )
{
   int port = ( int ) pd;
   iprintf( "UdpReaderTask monitoring port %d\r\n", port );

   // Create a UDP socket for receiving
   int UdpFd = CreateRxUdpSocket( port );
   if ( UdpFd <= 0 )
   {
      iprintf("Error Creating UDP Listen Socket: %d\r\n", UdpFd);
      while (1)
         OSTimeDly(TICKS_PER_SECOND);
   }
   else
   {
      iprintf( "Listening for UDP packets on port %d\r\n", port );
   }

   while (1)
   {
      IPADDR SrcIpAddr;  // UDP packet source IP address
      WORD   LocalPort;  // Port number UDP packet was sent to
      WORD   SrcPort;    // UDP packet source port number
      char   buffer[80];

      int len = recvfrom( UdpFd, (BYTE *)buffer, 80, &SrcIpAddr, &LocalPort, &SrcPort );
      buffer[len] = '\0';

      iprintf( "\r\nReceived a UDP packet with %d bytes from :", len );
      ShowIP( SrcIpAddr );
      iprintf( "\r\n%s\r\n", buffer );
   }
}





/*-------------------------------------------------------------------
 * UserMain Task
 * This is the first task to be executed and will create the UDP
 * Reader Task.
 -------------------------------------------------------------------*/
void UserMain( void *pd )
{
   int 		portnum;
   IPADDR 	ipaddr;
   char 	buffer[80];

   InitializeStack();
   EnableAutoUpdate();
   EnableTaskMonitor();

   if ( EthernetIP == 0 )
   {
      iprintf( "Trying DHCP\r\n" );
      GetDHCPAddress();
      iprintf( "DHCP assigned the IP address of :" );
      ShowIP( EthernetIP );
      iprintf( "\r\n" );
   }

   OSChangePrio( MAIN_PRIO );

   #ifdef _DEBUG
   InitializeNetworkGDB();
   #endif

   iprintf( "Starting UDP Sockets Example\r\n" );

   // Get desination IP address
   iprintf( "Enter the UDP Server destination IP address: " );
   buffer[0] = '\0';
   while ( buffer[0] == '\0' )  // Keep looping until something is entered
   {
      gets( buffer );
   }
   ipaddr = AsciiToIp( buffer );
   iprintf("\r\n");

   // Get the port number. This application uses the same
   // port number for send and receive.
   iprintf( "Enter the source/destination port number: " );
   gets( buffer );
   portnum = atoi( buffer );
   iprintf("\r\n");

   // Create a UDP socket for sending/receiving
   int UdpFd = CreateTxUdpSocket( ipaddr, portnum, portnum );
   if ( UdpFd <= 0 )
   {
      iprintf("Error Creating UDP Socket: %d\r\n", UdpFd);
      while (1)
         OSTimeDly(TICKS_PER_SECOND);
   }
   else
   {
      iprintf( "Sending/Recieving with host ");
      ShowIP( ipaddr );
      iprintf( ": %d\r\n", portnum );
   }

   // Create task to recieve UDP packets. We will pass the destination
   // port number in the optional second parameter field, and set the
   // priority to 1 less than the UserMain priority so packets get
   // processed as they are received.
   OSTaskCreate( UdpReaderTask,
                 ( void * ) portnum,
                 &UdpReaderStack[USER_TASK_STK_SIZE],
                 UdpReaderStack,
                 MAIN_PRIO - 1 );

   // Loop forever displaying UDP data
   while ( 1 )
   {
      iprintf( "Enter a string to send: " );
      gets(buffer);
      iprintf("\r\n");
      iprintf( "Sending \"%s\" using UDP to ", buffer );
      ShowIP( ipaddr );
      iprintf(" : %d\r\n", portnum );

      sendto( UdpFd, (BYTE *)buffer, strlen(buffer), ipaddr, portnum );
      iprintf( "\r\n" );
   };
}




