diff --git a/src/web_server.cpp b/src/web_server.cpp index cb0dbc8..4cab66f 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -28,7 +28,7 @@ //= History: KJC (12/29/00) - Genesis (from server.c) = //= HF (01/25/01) - Ported to multi-platform environment = //============================================================================= -#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env. +#define WIN // WIN for Windows environment, UNIX for BSD or LINUX env. //----- Include files --------------------------------------------------------- #include // Needed for printf() @@ -36,7 +36,7 @@ #include // Needed for strcpy() and strlen() #include // Needed for file i/o constants #include // Needed for file i/o constants -#include +#include /* FOR BSD UNIX/LINUX ---------------------------------------------------- */ #ifdef UNIX @@ -53,10 +53,14 @@ #include // Needed for _threadid #include // Needed for _beginthread() and _endthread() #include // Needed for open(), close(), and eof() +#include #include // Needed for all Winsock stuff +// Lazy struct fixes +typedef int32_t socklen_t; #endif /* ------------------------------------------------------------------------ */ + //----- HTTP response messages ---------------------------------------------- #define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n" #define OK_TEXT "HTTP/1.0 200 OK\nContent-Type:text/html\n\n" @@ -68,6 +72,7 @@ #define PORT_NUM 7080 // Port number for a Web server //----- Function prototypes ------------------------------------------------- +void ClientRequest(int server_s, int client_s); /* FOR WIN --------------------------------------------------------------- */ #ifdef WIN void handle_get(void *in_arg); // Thread function to handle GET @@ -112,54 +117,70 @@ int main(void) // Create a socket, fill-in address information, and then bind it server_s = socket(AF_INET, SOCK_STREAM, 0); + if (server_s == -1) + { + printf("ERROR - Unable to create socket on server\n"); + exit(1); + } 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)); + int bindRet = bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr)); + if (bindRet == -1) + { + printf("ERROR - Unable to bind socket\n"); + exit(1); + } + // Listen for connections and then accept + listen(server_s, 100); // Main loop to listen, accept, and then spin-off a thread to handle the GET while (1) { - // Listen for connections and then accept - listen(server_s, 100); addr_len = sizeof(client_addr); client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len); - if (client_s == 0) + if (client_s == -1) { - printf("ERROR - Unable to create socket \n"); - exit(1); + perror("ERROR - Unable to create socket to client\n"); + continue; } + std::async(std::launch::async, ClientRequest, server_s, client_s); + /* FOR UNIX/LINUX ---------------------------------------------------- */ #ifdef UNIX + /* // Spin-off a child process by fork nChild_proc_id = fork(); // Separate the parent and child process here ... if (nChild_proc_id == -1) // if I am a new child, go to the child module. { - child_proc(server_s, client_s); + child_proc(server_s, client_s); } + */ #endif /* ------------------------------------------------------------------- */ /* FOR WIN ----------------------------------------------------------- */ #ifdef WIN + /* // Spin-off a thread to handle this request (pass only client_s) if (_beginthread(handle_get, 4096, (void *)client_s) < 0) { printf("ERROR - Unable to create thread \n"); exit(1); } + */ #endif /* ------------------------------------------------------------------- */ } - + close(server_s); /* FOR UNIX/LINUX ------------------------------------------------------ */ #ifdef UNIX // Close the server socket - close(server_s); + //close(server_s); #endif /* --------------------------------------------------------------------- */ @@ -177,6 +198,61 @@ int main(void) return (1); } +void ClientRequest(int server_s, int client_s) { + char in_buf[BUF_SIZE]; // Input buffer for GET resquest + char out_buf[BUF_SIZE]; // Output buffer for HTML response + char *file_name; // File name + unsigned int fh; // File handle + unsigned int buf_len; // Buffer length for file reads + unsigned int retcode; // Return code + + // Receive the GET request from the Web browser + retcode = recv(client_s, in_buf, BUF_SIZE, 0); + + // Handle the GET if there is one (see note #3 in the header) + if (retcode != -1) + { + // Parse out the filename from the GET request + strtok(in_buf, " "); + file_name = strtok(NULL, " "); + + // Open the requested file + // - Start at 2nd char to get rid of leading "\" +#ifdef WIN + fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); +#endif +#ifdef UNIX + fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE); +#endif + + // Generate and send the response (404 if could not open the file) + if (fh == -1) + { + printf("File %s not found - sending an HTTP 404 \n", &file_name[1]); + strcpy(out_buf, NOTOK_404); + send(client_s, out_buf, strlen(out_buf), 0); + strcpy(out_buf, MESS_404); + send(client_s, out_buf, strlen(out_buf), 0); + } + else + { + printf("File %s is being sent \n", &file_name[1]); + if (strstr(file_name, ".gif") != NULL) + strcpy(out_buf, OK_IMAGE); + else + strcpy(out_buf, OK_TEXT); + send(client_s, out_buf, strlen(out_buf), 0); + do { + buf_len = read(fh, out_buf, BUF_SIZE); + send(client_s, out_buf, buf_len, 0); + } while (buf_len != 0); + close(fh); + } + } + // Close the client socket and end the thread + close(client_s); +} + /* FOR WIN --------------------------------------------------------------- */ #ifdef WIN //=========================================================================== @@ -194,7 +270,7 @@ void handle_get(void *in_arg) unsigned int retcode; // Return code // Set client_s to in_arg - client_s = (unsigned int)in_arg; + client_s = (unsigned int&)in_arg; // Receive the GET request from the Web browser retcode = recv(client_s, in_buf, BUF_SIZE, 0); @@ -290,11 +366,10 @@ void child_proc(int server_s, int client_s) strcpy(out_buf, OK_TEXT); send(client_s, out_buf, strlen(out_buf), 0); - while (fh != EOF) - { + do { buf_len = read(fh, out_buf, BUF_SIZE); send(client_s, out_buf, buf_len, 0); - } + } while (buf_len != 0); close(fh); } }