/*******************************************************************************
        udp_echo_dh.c
        Z-World, 2002

        A UDP example, that receives packets from any host on UDP port 7, then
        echoes the received packet back to the sender.

        This demonstrates use of a UDP data handler, which is the fastest
        "official" way to implement UDP-based request/response servers.

        This sample will work for Dynamic C 7.30 and later.
*******************************************************************************/
#class auto 			// Change default storage class for local variables: on the stack

/***********************************
 * Configuration                   *
 * -------------                   *
 * All fields in this section must *
 * be altered to match your local  *
 * network settings.               *
 ***********************************/

/*
 * Pick the predefined TCP/IP configuration for this sample.  See
 * LIB\TCPIP\TCP_CONFIG.LIB for instructions on how to set the
 * configuration.  If value >= 100, then use "custom_config.h"
 */
#define TCPCONFIG		1

//#define DCRTCP_VERBOSE
//#define DCRTCP_DEBUG

/*
 * Define the number of socket buffers that will be allocated for
 * UDP sockets.  We only need one UDP socket, so one socket buffer
 * will be enough.
 */
#define MAX_UDP_SOCKET_BUFFERS 1

/*
 * Bump Ethernet MTU up to the max (1500), but only need a few buffers
 */
#define ETH_MTU 1500
#define ETH_MAXBUFS 3

/*
 * UDP demo configuration
 */
#define DISABLE_TCP		// Not using TCP

/*
 *  what local UDP port to use - we receive packets only sent to this port.
 *  Port 7 is the standard echo port.
 */
#define LOCAL_PORT	7


/********************************
 * End of configuration section *
 ********************************/

#memmap xmem
#use "dcrtcp.lib"

udp_Socket sock;


/**
 * 	Handler called frmo the UDP stack.  If message is relevant, then send
 * 	back a reply.  Return 1 tells UDP stack not to copy this into a
 * 	client buffer; it has already been taken care of-thank you.
 *
 * 	RETURN: 	1 = handler has done all relevant processing for datagram.
 */
int echo_handler(int event, udp_Socket * s, ll_Gather * g,
						_udp_datagram_info * udi)
{
	// Datagram has come in.  It is in the Ethernet receive buffer.  No need to
	// copy it anywhere - we just transmit it straight back to the sender.
	// The relevant information comes in the following fields (not all of which
	// we use here) (see LIB\tcpip\net.lib for structure):
	//  g->data1  ->  IP and UDP headers (root)
	//  g->data2  ->  UDP datagram data (xmem)
	//  g->len2   ->  UDP datagram data length
	//  udi->remip  -> sender's IP address
	//  udi->remport  ->  sender's UDP port number
	//  udi->flags  -> flags.

	// The 'event' parameter determines the type of event.  As of DC 7.30, this is either
	//  UDP_DH_INDATA : incoming datagram
	//  UDP_DH_ICMPMSG : incoming ICMP message.

	if (event == UDP_DH_ICMPMSG) {
		return 1;	// Just ignore incoming ICMP errors.
	}

	// Otherwise, bounce the packet back!  We ignore errors because this
	// is UDP, and the sender will try again.  Not a good idea in general, though.
	// The udp_xsendto() function is new in DC 7.30.  It is the same as udp_sendto()
	// except that the data buffer is in extended memory.  It is slightly more
	// efficient than udp_sendto().
	udp_xsendto(s, g->data2, g->len2, udi->remip, udi->remport);

	// Return 1 to indicate that all processing has been done.  No copy to
	// normal udp socket receive buffer.
	return 1;
}



void main()
{
	sock_init();

	if(!udp_extopen(&sock, IF_ANY, LOCAL_PORT, -1L, 0, echo_handler, 0, 0)) {
		printf("udp_extopen failed!\n");
		exit(0);
	}

	/* Let the stack do everything... */
	for(;;)
		tcp_tick(NULL);
}

