//====================================================== file = http302.c =====
//=  A server program to respond to an HTTP GET with an HTTP 302 redirect     =
//=============================================================================
//=  Notes:                                                                   =
//=    1) This program conditionally compiles for Winsock and BSD sockets.    =
//=       Set the initial #define to WIN or BSD as appropriate.               =
//=    2) This program hardwires an HTTP 302 response to return to the        =
//=       the browser.  The HTTP 302 is hardwire to redirect to               =
//=       http://www.csee.usf.edu/~christen.                                   =
//=---------------------------------------------------------------------------=
//=  Example execution:                                                       =
//=                                                                           =
//=   1) Determine the IP address on which htt302 will run                    =
//=      (e.g., 131.247.167.109).  On Windows ipconfig to determine the IP    =
//=      address of the local machine.                                        =
//=   2) Execute http302 on the local machine                                 =
//=   3) Open a Web browser and surf to http://xxx.xxx.xxx.xxx where          =
//=      xxx.xxx.xxx.xxx is the IP address determined in step (1)             =
//=   4) Will see http://www.csee.usf.edu/~christen on Web browser            =
//=---------------------------------------------------------------------------=
//=  Build: bcc32 http302.c, cl http302.c wsock32.lib,                        =
//=         gcc http302.c -lsocket -lnsl                                      =
//=---------------------------------------------------------------------------=
//=  Execute: http302                                                         =
//=---------------------------------------------------------------------------=
//=  History:  KJC (12/20/00) - Genesis (from server.c)                       =
//=            KJC (01/06/09) - Updated the comments                          =
//=            KJC (03/04/09) - Fixed \n to \r\n for firefox                  =
//=============================================================================
#define  WIN                // WIN for Winsock and BSD for BSD sockets

//----- Include files ---------------------------------------------------------
#include <stdio.h>          // Needed for printf()
#include <stdlib.h>         // Needed for exit()
#include <string.h>         // Needed for strcpy() and strlen()
#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>
  #include <netdb.h>
#endif

//----- Defines ---------------------------------------------------------------
#define  BUF_SIZE           10000     // Buffer size
#define  PORT_NUM              80     // This is the port number for a Web 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         server_s;             // Server socket descriptor
  struct sockaddr_in   server_addr;          // Server Internet address
  unsigned int         client_s;             // Client 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[BUF_SIZE];    // Output buffer for HTML response
  char                 in_buf[BUF_SIZE];     // Input buffer for GET resquest
  unsigned int         retcode;              // Return code
  unsigned int         i;                    // Loop counter

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

  // Create a socket
  server_s = socket(AF_INET, SOCK_STREAM, 0);

  // Fill-in my socket's address information and bind the socket
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(PORT_NUM);
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

  // Listen for connections and then accept
  listen(server_s, 1);
  addr_len = sizeof(client_addr);
  client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);

  // Receive from the Web browser and output what was received
  //  - The return code from recv() is the number of bytes received
  retcode = recv(client_s, in_buf, BUF_SIZE, 0);
  for (i=0; i<retcode; i++)
    printf ("%c", in_buf[i]);

  // Copy the HTTP 302 response into the out buffer
  strcpy(out_buf, "HTTP/1.1 302 Moved Temporarily\r\n\
                   Date:\r\n\
                   Server:\r\n\
                   Location: http://www.csee.usf.edu/~christen\r\n\
                   Connection: close\r\n\
                   Content-Type: text/html\r\n\n");

  // Send HTTP 302 response to the client
  send(client_s, out_buf, strlen(out_buf), 0);

  // Close all open sockets
#ifdef WIN
  closesocket(server_s);
  closesocket(client_s);
#endif
#ifdef BSD
  close(server_s);
  close(client_s);
#endif

#ifdef WIN
  // This stuff cleans-up winsock
  WSACleanup();
#endif
}

