From c5c1c4d4129a04ce52ae391fd3ed5281e1f3e644 Mon Sep 17 00:00:00 2001 From: yhirose Date: Mon, 24 Sep 2012 09:39:13 -0400 Subject: [PATCH] Win32 support. Merged windows branch. Revert "Merged windows branch." This reverts commit ceb070d993f49543aa26a0ce9bd7e1f9ffabe5f5. --- .gitignore | 7 ++ example/sample.sln | 20 ++++++ example/sample.vcxproj | 86 +++++++++++++++++++++++++ httpsvrkit.h | 143 +++++++++++++++++++++-------------------- 4 files changed, 186 insertions(+), 70 deletions(-) create mode 100644 example/sample.sln create mode 100644 example/sample.vcxproj diff --git a/.gitignore b/.gitignore index c28abb0..c0511b7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,10 @@ tags sample *.swp + +Debug +Release +*.vcxproj.user +*.sdf +*.opensdf +ipch diff --git a/example/sample.sln b/example/sample.sln new file mode 100644 index 0000000..58d135a --- /dev/null +++ b/example/sample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample", "sample.vcxproj", "{864CD288-050A-4C8B-9BEF-3048BD876C5B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {864CD288-050A-4C8B-9BEF-3048BD876C5B}.Debug|Win32.ActiveCfg = Debug|Win32 + {864CD288-050A-4C8B-9BEF-3048BD876C5B}.Debug|Win32.Build.0 = Debug|Win32 + {864CD288-050A-4C8B-9BEF-3048BD876C5B}.Release|Win32.ActiveCfg = Release|Win32 + {864CD288-050A-4C8B-9BEF-3048BD876C5B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/example/sample.vcxproj b/example/sample.vcxproj new file mode 100644 index 0000000..eaa186c --- /dev/null +++ b/example/sample.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {864CD288-050A-4C8B-9BEF-3048BD876C5B} + Win32Proj + sample + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + .. + + + Console + true + Ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + .. + + + Console + true + true + true + Ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file diff --git a/httpsvrkit.h b/httpsvrkit.h index 5a9893c..5d490f8 100644 --- a/httpsvrkit.h +++ b/httpsvrkit.h @@ -5,16 +5,16 @@ // The Boost Software License 1.0 // -#include -#include -#include -#include -#include - #ifdef _WIN32 +//#define _CRT_SECURE_NO_WARNINGS +#define _CRT_NONSTDC_NO_DEPRECATE + +#include +#include #include #include +typedef unsigned __int16 uint16_t; typedef SOCKET socket_t; int inet_aton(const char* strptr, struct in_addr* addrptr) @@ -34,6 +34,12 @@ int inet_aton(const char* strptr, struct in_addr* addrptr) typedef int socket_t; #endif +#include +#include +#include +#include +#include + namespace httpsvrkit { @@ -74,7 +80,7 @@ public: void stop(); private: - void process_request(int fd); + void process_request(FILE* fp_read, FILE* fp_write); socket_t sock_; std::multimap handlers_; @@ -82,26 +88,6 @@ private: // Implementation -template -void fdopen_b(int fd, const char* md, Fn fn) -{ -#ifdef _WIN32 - int osfhandle = _open_osfhandle(fd, _O_RDONLY); - FILE* fp = fdopen(osfhandle, md); -#else - FILE* fp = fdopen(fd, md); -#endif - - if (fp) { - fn(fp); - fclose(fp); - -#ifdef _WIN32 - close(osfhandle); -#endif - } -} - inline socket_t create_socket(const std::string& ipaddr, int port) { // Create a server socket @@ -111,8 +97,8 @@ inline socket_t create_socket(const std::string& ipaddr, int port) } // Make 'reuse address' option available - int yes = 1; - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); + int opt = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)); // Bind the socket to the given address struct sockaddr_in addr; @@ -151,6 +137,15 @@ inline Server::Server() #ifdef _WIN32 WSADATA wsaData; WSAStartup(0x0002, &wsaData); + +#ifndef SO_SYNCHRONOUS_NONALERT +#define SO_SYNCHRONOUS_NONALERT 0x20; +#endif +#ifndef SO_OPENTYPE +#define SO_OPENTYPE 0x7008 +#endif + int opt = SO_SYNCHRONOUS_NONALERT; + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char*)&opt, sizeof(opt)); #endif } @@ -190,8 +185,19 @@ inline bool Server::run(const std::string& ipaddr, int port) return false; } - process_request(fd); - close(fd); +#ifdef _WIN32 + int osfhandle = _open_osfhandle(fd, _O_RDONLY); + FILE* fp_read = fdopen(osfhandle, "r"); + FILE* fp_write = fdopen(osfhandle, "w"); +#else + FILE* fp_read = fdopen(fd, "r"); + FILE* fp_write = fdopen(fd, "w"); +#endif + + process_request(fp_read, fp_write); + + fflush(fp_write); + close_socket(fd); } // NOTREACHED @@ -238,18 +244,16 @@ inline void read_headers(FILE* fp, Map& headers) } } -inline void write_plain_text(int fd, const char* s) +inline void write_plain_text(FILE* fp, const char* s) { - fdopen_b(fd, "w", [=](FILE* fp) { - fprintf(fp, "HTTP/1.0 200 OK\r\n"); - fprintf(fp, "Content-type: text/plain\r\n"); - fprintf(fp, "Connection: close\r\n"); - fprintf(fp, "\r\n"); - fprintf(fp, "%s", s); - }); + fprintf(fp, "HTTP/1.0 200 OK\r\n"); + fprintf(fp, "Content-type: text/plain\r\n"); + fprintf(fp, "Connection: close\r\n"); + fprintf(fp, "\r\n"); + fprintf(fp, "%s", s); } -inline void write_error(int fd, int code) +inline void write_error(FILE* fp, int code) { const char* msg = NULL; @@ -268,43 +272,42 @@ inline void write_error(int fd, int code) assert(msg); - fdopen_b(fd, "w", [=](FILE* fp) { - fprintf(fp, "HTTP/1.0 %d %s\r\n", code, msg); - fprintf(fp, "Content-type: text/plain\r\n"); - fprintf(fp, "Connection: close\r\n"); - fprintf(fp, "\r\n"); - fprintf(fp, "Status: %d\r\n", code); - }); + fprintf(fp, "HTTP/1.0 %d %s\r\n", code, msg); + fprintf(fp, "Content-type: text/plain\r\n"); + fprintf(fp, "Connection: close\r\n"); + fprintf(fp, "\r\n"); + fprintf(fp, "Status: %d\r\n", code); } -inline void Server::process_request(int fd) +inline void Server::process_request(FILE* fp_read, FILE* fp_write) { - fdopen_b(fd, "r", [=](FILE* fp) { - // Read and parse request line - std::string method, url; - if (!read_request_line(fp, method, url)) { - write_error(fd, 400); - return; - } + // Read and parse request line + std::string method, url; + if (!read_request_line(fp_read, method, url)) { + write_error(fp_write, 400); + return; + } - // Read headers - Map headers; - read_headers(fp, headers); + // Read headers + Map headers; + read_headers(fp_read, headers); - // Write content - char buf[BUFSIZ]; - std::string content; - sprintf(buf, "Method: %s, URL: %s\n", method.c_str(), url.c_str()); - content += buf; - for (const auto& x : headers) { - sprintf(buf, "%s: %s\n", x.first.c_str(), x.second.c_str()); - content += buf; - } - write_plain_text(fd, content.c_str()); - }); + // Write content + char buf[BUFSIZ]; + std::string content; + sprintf(buf, "Method: %s, URL: %s\n", method.c_str(), url.c_str()); + content += buf; + + //for (const auto& x : headers) { + for (auto it = headers.begin(); it != headers.end(); ++it) { + const auto& x = *it; + sprintf(buf, "%s: %s\n", x.first.c_str(), x.second.c_str()); + content += buf; + } + + write_plain_text(fp_write, content.c_str()); } } // namespace httpsvrkit // vim: et ts=4 sw=4 cin cino={1s ff=unix -