Browse Source

Win32 support.

Merged windows branch.

Revert "Merged windows branch."

This reverts commit ceb070d993f49543aa26a0ce9bd7e1f9ffabe5f5.
yhirose 13 years ago
parent
commit
c5c1c4d412
4 changed files with 188 additions and 72 deletions
  1. 7 0
      .gitignore
  2. 20 0
      example/sample.sln
  3. 86 0
      example/sample.vcxproj
  4. 75 72
      httpsvrkit.h

+ 7 - 0
.gitignore

@@ -2,3 +2,10 @@ tags
 sample
 sample
 
 
 *.swp
 *.swp
+
+Debug
+Release
+*.vcxproj.user
+*.sdf
+*.opensdf
+ipch

+ 20 - 0
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

+ 86 - 0
example/sample.vcxproj

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{864CD288-050A-4C8B-9BEF-3048BD876C5B}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>sample</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>..</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="sample.cc" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 75 - 72
httpsvrkit.h

@@ -5,16 +5,16 @@
 //  The Boost Software License 1.0
 //  The Boost Software License 1.0
 //
 //
 
 
-#include <functional>
-#include <map>
-#include <regex>
-#include <string>
-#include <assert.h>
-
 #ifdef _WIN32
 #ifdef _WIN32
+//#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_NONSTDC_NO_DEPRECATE
+
+#include <fcntl.h>
+#include <io.h>
 #include <winsock2.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <ws2tcpip.h>
 
 
+typedef unsigned __int16 uint16_t;
 typedef SOCKET socket_t;
 typedef SOCKET socket_t;
 
 
 int inet_aton(const char* strptr, struct in_addr* addrptr)
 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;
 typedef int socket_t;
 #endif
 #endif
 
 
+#include <functional>
+#include <map>
+#include <regex>
+#include <string>
+#include <assert.h>
+
 namespace httpsvrkit
 namespace httpsvrkit
 {
 {
 
 
@@ -74,7 +80,7 @@ public:
     void stop();
     void stop();
 
 
 private:
 private:
-    void process_request(int fd);
+    void process_request(FILE* fp_read, FILE* fp_write);
 
 
     socket_t sock_;
     socket_t sock_;
     std::multimap<std::string, Handler> handlers_;
     std::multimap<std::string, Handler> handlers_;
@@ -82,26 +88,6 @@ private:
 
 
 // Implementation
 // Implementation
 
 
-template <typename Fn>
-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)
 inline socket_t create_socket(const std::string& ipaddr, int port)
 {
 {
     // Create a server socket
     // Create a server socket
@@ -111,8 +97,8 @@ inline socket_t create_socket(const std::string& ipaddr, int port)
     }
     }
 
 
     // Make 'reuse address' option available
     // 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
     // Bind the socket to the given address
     struct sockaddr_in addr;
     struct sockaddr_in addr;
@@ -151,6 +137,15 @@ inline Server::Server()
 #ifdef _WIN32
 #ifdef _WIN32
     WSADATA wsaData;
     WSADATA wsaData;
     WSAStartup(0x0002, &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
 #endif
 }
 }
 
 
@@ -190,8 +185,19 @@ inline bool Server::run(const std::string& ipaddr, int port)
             return false;
             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
     // 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;
     const char* msg = NULL;
 
 
@@ -268,43 +272,42 @@ inline void write_error(int fd, int code)
 
 
     assert(msg);
     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 headers
-        Map headers;
-        read_headers(fp, 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());
-    });
+      // 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_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) {
+      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
 } // namespace httpsvrkit
 
 
 // vim: et ts=4 sw=4 cin cino={1s ff=unix
 // vim: et ts=4 sw=4 cin cino={1s ff=unix
-