//======================================================= file = server.c =====
//=  A message "server" program to demonstrate sockets programming            =
//=   - TCP/IP client/server model is implemented                             =
//=============================================================================
//=  Notes:                                                                   =
//=    1) This program conditionally compiles for Winsock and BSD sockets.    =
//=       Set the initial #define to WIN or BSD as appropriate.               =
//=    2) There is *no* error checking in this program.  Error checking was   =
//=       omitted to simplify the program.                                    =
//=    3) This program serves a message to program client running on another  =
//=       host.                                                               =
//=    4) The steps #'s correspond to lecture topics.                         =
//=---------------------------------------------------------------------------=
//=  Build: bcc32 server.c or cl server.c wsock32.lib for Winsock             =
//=         gcc server.c -lsocket -lnsl for BSD                               =
//=---------------------------------------------------------------------------=
//=  History:  KJC (11/02/98) - Genesis                                       =
//=            KJC (02/08/00) - Added client-to-server recv                   =
//=            KJC (05/20/03) - Updated socket naming to match Kurose et al.  =
//=            KJC (12/14/05) - Minor clean-up                                =
//=============================================================================
#define  WIN                // WIN for Winsock and BSD for BSD sockets

//----- Include files ---------------------------------------------------------
#include <stdio.h>          // Needed for printf()
#include <string.h>         // Needed for memcpy() and strcpy()
#ifdef WIN
  #include <windows.h>      // Needed for all Winsock stuff
#endif
#ifdef BSD
  #include <sys/types.h>    // Needed for system defined identifiers.
  #include <netinet/in.h>   // Needed for internet address structure.
  #include <sys/socket.h>   // Needed for socket(), bind(), etc...
  #include <arpa/inet.h>    // Needed for inet_ntoa()
  #include <fcntl.h>        // Needed for sockets stuff
  #include <netdb.h>        // Needed for sockets stuff
#endif

//----- Defines ---------------------------------------------------------------
#define  PORT_NUM   1050    // Arbitrary port number for the server

//===== Main program ==========================================================
void main(void)
{
#ifdef WIN
  WORD wVersionRequested = MAKEWORD(1,1);       // Stuff for WSA functions
  WSADATA wsaData;                              // Stuff for WSA functions
#endif
  unsigned int         welcome_s;       // Welcome socket descriptor
  struct sockaddr_in   server_addr;     // Server Internet address
  unsigned int         connect_s;       // Connection socket descriptor
  struct sockaddr_in   client_addr;     // Client Internet address
  struct in_addr       client_ip_addr;  // Client IP address
  int                  addr_len;        // Internet address length
  char                 out_buf[100];    // Output buffer for data
  char                 in_buf[100];     // Input buffer for data

#ifdef WIN
  // This stuff initializes winsock
  WSAStartup(wVersionRequested, &wsaData);
#endif

  // >>> Step #1 <<<
  // Create a welcome socket
  //   - AF_INET is Address Family Internet and SOCK_STREAM is streams
  welcome_s = socket(AF_INET, SOCK_STREAM, 0);

  // >>> Step #2 <<<
  // Fill-in server (my) address information and bind the welcome socket
  //   - See winsock.h for a description of struct sockaddr_in
  server_addr.sin_family = AF_INET;                 // Address family to use
  server_addr.sin_port = htons(PORT_NUM);           // Port number to use
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);  // Listen on any IP address
  bind(welcome_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

  // >>> Step #3 <<<
  // Listen on welcome socket for a connection
  listen(welcome_s, 1);

  // >>> Step #4 <<<
  // Accept a connection.  The accept() will block and then return with
  // connect_s assigned and client_addr filled-in.
  addr_len = sizeof(client_addr);
  connect_s = accept(welcome_s, (struct sockaddr *)&client_addr, &addr_len);

  // Copy the four-byte client IP address into an IP address structure
  //   - See winsock.h for a description of struct in_addr
  memcpy(&client_ip_addr, &client_addr.sin_addr.s_addr, 4);

  // Print an informational message that accept completed
  printf("Accept completed (IP address of client = %s  port = %d) \n",
    inet_ntoa(client_ip_addr), ntohs(client_addr.sin_port));

  // >>> Step #5 <<<
  // Send to the client using the connect socket
  strcpy(out_buf, "Test message from server to client");
  send(connect_s, out_buf, (strlen(out_buf) + 1), 0);

  // >>> Step #6 <<<
  // Receive from the client using the connect socket
  recv(connect_s, in_buf, sizeof(in_buf), 0);
  printf("Received from client... data = '%s' \n", in_buf);

  // >>> Step #7 <<<
  // Close the welcome and connect sockets
#ifdef WIN
  closesocket(welcome_s);
  closesocket(connect_s);
#endif
#ifdef BSD
  close(welcome_s);
  close(connect_s);
#endif

#ifdef WIN
  // Clean-up winsock
  WSACleanup();
#endif
}

