/*
** UDP server example program.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <proto/socket.h>

#define DEFAULT_PORT 54321
#define TERMINATOR "quit\n"

main ( argc, argv )
     int argc;
     char *argv[];
{
int s, retcode,  done;
long fromlen;
char  buf[256];
struct sockaddr_in addr, from;
struct servent *sp;

/*
** Create a socket.
*/
s = socket ( AF_INET, SOCK_DGRAM,0 );
if ( s == -1 ) {
    fprintf ( stderr, "Server can't create socket.\n");
    exit(1);
}

/*
** Applications should get the service number from the services file.
** Try the services file first, and upon failure, use a default port
** number.  This allows the example to run without modifying the
** system environment.
*/
memset(&addr, 0, sizeof(addr));
sp = getservbyname( "example", "udp" );
if( sp != NULL ) {
    addr.sin_port = sp->s_port;
} else {
    addr.sin_port = DEFAULT_PORT;
}

/*
** Binding assigns the local port number to the socket.
** Clients will send datagrams to this port.
** The address INADDR_ANY means the server is willing to accept
** datagrams arriving on any local interface.
*/
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
if ( bind ( s, (struct sockaddr *)&addr, sizeof (addr)) == -1 ) {
    perror("bind");
    exit (1);
}

fromlen = sizeof(from);

/*
** Server Main Loop - read datagram and echo back to client.
** If the datagram starts with the word "quit" terminate service.
** Unlike TCP sockets, UDP will transmit all or none of the
** requested data so there is no need to worry about partial
** writes.  However, UDP is an unreliable protocol; datagrams
** may get lost, duplicated, or delivered in a out of order.
*/

done = 0;
while (!done) {
    memset(&from, 0, sizeof(from));
    retcode = recvfrom ( s, buf, sizeof(buf), 0,
			    (struct sockaddr *)&from, &fromlen );
    if ( retcode < 0 ) {
	perror("recvfrom");
	exit (1);
    }
    buf[retcode] = 0;

    fprintf(stdout, "Packet from %s, port %d, length %3d, data %s",
		    inet_ntoa(from.sin_addr),from.sin_port, retcode, buf);

    if (!strncmp(buf, TERMINATOR, strlen(TERMINATOR))){
	done = 1;
    }
    retcode = sendto ( s, buf, retcode, 0,
			    (struct sockaddr *)&from, fromlen );

    if ( retcode < 0 ) {
	perror("sendto");
	exit (1);
    }
}
exit(0);
}
