/* udp/srv/main.c

Serveur UDP basique

*/

#if defined (WIN32)
#include <winsock2.h>
#elif defined (linux)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket(s) close (s)
typedef int SOCKET;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr SOCKADDR;
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define PORT 23

int server (void)
{
   /* Creation de la socket sur le domaine internet */
   SOCKET sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
   if (sock != INVALID_SOCKET)
   {
      struct sockaddr_in si_server = { 0 };

      /* Initialisation de la structure contenant l'adresse de
         l'hote et le port utilise */
      si_server.sin_family = AF_INET;

      /* conversion du numero de port */
      si_server.sin_port = htons (PORT);

      /* conversion de l'adresse ip (serveur : ANY ) */
      si_server.sin_addr.s_addr = htonl(INADDR_ANY);

      /* Liaison entre la socket et la structure */
      if (bind (sock, (struct sockaddr *) &si_server, sizeof si_server)
          != SOCKET_ERROR)
      {
         int fin = 0;

         while (!fin)
         {
            printf ("waiting for a client datagram\n");

            {
               struct sockaddr_in si_client = { 0 };
               /* reception  */
               char data[128];
               int size_si_client = sizeof (si_client);
               int nb_octet = recvfrom (sock, data, sizeof data - 1, 0,
                                        (struct sockaddr *) &si_client,
                                        &size_si_client);
               if (nb_octet > 0)
               {
                  if (!fin)
                  {
                     printf ("%d octets received\n", nb_octet);
                     /* echo */
                     nb_octet =
                        sendto (sock, data, nb_octet, 0,
                                (struct sockaddr *) &si_client,
                                sizeof (si_client));

                     if (nb_octet > 0)
                     {
                        printf ("%d octets sent\n", nb_octet);
                     }
                     else if (nb_octet < 0)
                     {
                        printf ("sendto() : local error\n");
                        fin = 1;
                     }
                     else
                     {
                        printf ("sendto() : remote error\n");
                        fin = 1;
                     }
                  }
               }
               else if (nb_octet < 0)
               {
                  printf ("recvfrom() : local error\n");
                  fin = 1;
               }
               else
               {
                  printf ("recvfrom() : remote error\n");
                  fin = 1;
               }
            }
         }
      }
      else
      {
         printf ("bind() error\n");
      }
      /* Fermeture de la socket */
      (void) closesocket (sock);
   }
   else
   {
      printf ("socket() error\n");
   }

   return 0;
}

int main (void)
{
#if defined (WIN32)
   WSADATA WSAData;
   int erreur = WSAStartup (MAKEWORD (2, 0), &WSAData);
#else
   int erreur = 0;
#endif
   server ();
#if defined (WIN32)
   WSACleanup ();
#endif

#ifdef DEVCPP
   system ("pause");
#endif

   return 0;
}
