diff --git a/src/common.hpp b/src/common.hpp index 6dfd51e9a1..f77eae95f0 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -31,8 +31,7 @@ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif -//#include -#include +#include // SIZE_MAX appears to be a compiler thing not an OS header thing. // make sure it is defined. diff --git a/src/processors/hybi_header.hpp b/src/processors/hybi_header.hpp index 02cb4448c8..72dddf2e0a 100644 --- a/src/processors/hybi_header.hpp +++ b/src/processors/hybi_header.hpp @@ -136,7 +136,7 @@ private: static const uint8_t STATE_WRITE = 4; uint8_t m_state; - uint64_t m_bytes_needed; + std::streamsize m_bytes_needed; uint64_t m_payload_size; char m_header[MAX_HEADER_LENGTH]; }; diff --git a/src/processors/hybi_legacy.hpp b/src/processors/hybi_legacy.hpp index 836d0ee727..c08c615f05 100644 --- a/src/processors/hybi_legacy.hpp +++ b/src/processors/hybi_legacy.hpp @@ -79,9 +79,7 @@ public: // TODO: decide if it is best to silently fail here or produce some sort // of warning or exception. const std::string& key3 = request.header("Sec-WebSocket-Key3"); - std::copy(key3.c_str(), - key3.c_str()+std::min(static_cast(8), key3.size()), - &key_final[8]); + memcpy(&key_final[8],key3.c_str(),std::min(static_cast(8), key3.size())); m_key3 = md5_hash_string(std::string(key_final,16)); @@ -331,11 +329,9 @@ private: num = atoi(digits.c_str()); if (spaces > 0 && num > 0) { num = htonl(num/spaces); - std::copy(reinterpret_cast(&num), - reinterpret_cast(&num)+4, - result); + memcpy(result,&num,4); } else { - std::fill(result,result+4,0); + memset(result,0,4); } } diff --git a/src/roles/server.hpp b/src/roles/server.hpp index 48c445378c..1e1f13a393 100644 --- a/src/roles/server.hpp +++ b/src/roles/server.hpp @@ -201,18 +201,40 @@ public: m_state(IDLE), m_timer(m,boost::posix_time::seconds(0)) {} - void listen(uint16_t port, size_t n = 1); - void listen(const boost::asio::ip::tcp::endpoint& e, size_t num_threads = 1); + void start_listen(uint16_t port, size_t num_threads = 1); + void start_listen(const boost::asio::ip::tcp::endpoint& e, size_t num_threads = 1); // uses internal resolver - void listen(const std::string &host, const std::string &service, size_t n = 1); + void start_listen(const std::string &host, const std::string &service, size_t num_threads = 1); template - void listen(const InternetProtocol &internet_protocol, uint16_t port, size_t n = 1) { + void start_listen(const InternetProtocol &internet_protocol, uint16_t port, size_t num_threads = 1) { m_endpoint.m_alog->at(log::alevel::DEVEL) << "role::server listening on port " << port << log::endl; boost::asio::ip::tcp::endpoint e(internet_protocol, port); - listen(e,n); + start_listen(e,num_threads); } + + void stop_listen(bool join); + + // legacy interface + void listen(uint16_t port, size_t num_threads = 1) { + start_listen(port,num_threads>1 ? num_threads : 0); + if(num_threads > 1) stop_listen(true); + } + void listen(const boost::asio::ip::tcp::endpoint& e, size_t num_threads = 1) { + start_listen(e,num_threads>1 ? num_threads : 0); + if(num_threads > 1) stop_listen(true); + } + void listen(const std::string &host, const std::string &service, size_t num_threads = 1) { + start_listen(host,service,num_threads>1 ? num_threads : 0); + if(num_threads > 1) stop_listen(true); + } + template + void listen(const InternetProtocol &internet_protocol, uint16_t port, size_t num_threads = 1) { + start_listen(internet_protocol,port,num_threads>1 ? num_threads : 0); + if(num_threads > 1) stop_listen(true); + } + protected: bool is_server() { return true; @@ -240,10 +262,12 @@ private: state m_state; boost::asio::deadline_timer m_timer; + + std::vector< boost::shared_ptr > m_listening_threads; }; template -void server::listen(const boost::asio::ip::tcp::endpoint& e,size_t num_threads) { +void server::start_listen(const boost::asio::ip::tcp::endpoint& e,size_t num_threads) { { boost::unique_lock lock(m_endpoint.m_lock); @@ -259,38 +283,55 @@ void server::listen(const boost::asio::ip::tcp::endpoint& e,size_t num this->start_accept(); } - if (num_threads == 1) { - m_endpoint.run_internal(); - } else if (num_threads > 1 && num_threads <= MAX_THREAD_POOL_SIZE) { - std::vector< boost::shared_ptr > threads; - - for (std::size_t i = 0; i < num_threads; ++i) { - boost::shared_ptr thread( - new boost::thread(boost::bind( - &endpoint_type::run_internal, - &m_endpoint - )) - ); - threads.push_back(thread); - } - - for (std::size_t i = 0; i < threads.size(); ++i) { - threads[i]->join(); - } - } else { + if (num_threads < 0 || num_threads > MAX_THREAD_POOL_SIZE) { throw exception("listen called with invalid num_threads value"); } + + m_state = LISTENING; + + for (std::size_t i = 0; i < num_threads; ++i) { + boost::shared_ptr thread( + new boost::thread(boost::bind( + &endpoint_type::run_internal, + &m_endpoint + )) + ); + m_listening_threads.push_back(thread); + } + + if(num_threads == 0) + { + m_endpoint.run_internal(); + m_state = IDLE; + } } -// server Implimentation -// TODO: provide a way to stop/reset the server endpoint template -void server::listen(uint16_t port, size_t n) { - listen(boost::asio::ip::tcp::v6(), port, n); +void server::stop_listen(bool join) { + if (m_state != LISTENING) { + throw exception("stop_listen called from invalid state"); + } + + m_state = STOPPING; + + if(join) { + for (std::size_t i = 0; i < m_listening_threads.size(); ++i) { + m_listening_threads[i]->join(); + } + } + + m_listening_threads.clear(); + + m_state = IDLE; } template -void server::listen(const std::string &host, const std::string &service, size_t n) { +void server::start_listen(uint16_t port, size_t num_threads) { + start_listen(boost::asio::ip::tcp::v6(), port, num_threads); +} + +template +void server::start_listen(const std::string &host, const std::string &service, size_t num_threads) { boost::asio::ip::tcp::resolver resolver(m_io_service); boost::asio::ip::tcp::resolver::query query(host, service); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); @@ -299,7 +340,7 @@ void server::listen(const std::string &host, const std::string &servic throw std::invalid_argument("Can't resolve host/service to listen"); } const boost::asio::ip::tcp::endpoint &ep = *endpoint_iterator; - listen(ep,n); + start_listen(ep,num_threads); } template diff --git a/src/sockets/plain.hpp b/src/sockets/plain.hpp index 201d86c249..48aa910799 100644 --- a/src/sockets/plain.hpp +++ b/src/sockets/plain.hpp @@ -35,6 +35,12 @@ #include +#ifdef _MSC_VER +// Disable "warning C4355: 'this' : used in base member initializer list". +# pragma warning(push) +# pragma warning(disable:4355) +#endif + namespace websocketpp { namespace socket { @@ -116,4 +122,8 @@ private: } // namespace socket } // namespace websocketpp +#ifdef _MSC_VER +# pragma warning(pop) +#endif + #endif // WEBSOCKETPP_SOCKET_PLAIN_HPP diff --git a/windows/vcpp2008/common.vsprops b/windows/vcpp2008/common.vsprops new file mode 100644 index 0000000000..405a9f9042 --- /dev/null +++ b/windows/vcpp2008/common.vsprops @@ -0,0 +1,15 @@ + + + + + diff --git a/windows/vcpp2008/examples/chatclient.vcproj b/windows/vcpp2008/examples/chatclient.vcproj index 929efff01e..a5b570c5e2 100644 --- a/windows/vcpp2008/examples/chatclient.vcproj +++ b/windows/vcpp2008/examples/chatclient.vcproj @@ -21,6 +21,7 @@ OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="1" + InheritedPropertySheets="..\common.vsprops" CharacterSet="1" > @@ -138,7 +139,6 @@ @@ -116,7 +117,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\..\..\..\boost_1_47_0;.." + AdditionalIncludeDirectories=".." PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;NOCOMM;_WIN32_WINNT=0x0600" RuntimeLibrary="0" BufferSecurityCheck="false" @@ -138,7 +139,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/vcpp2008/examples/echoserver.vcproj b/windows/vcpp2008/examples/echoserver.vcproj index f2fc495064..f5d28de880 100644 --- a/windows/vcpp2008/examples/echoserver.vcproj +++ b/windows/vcpp2008/examples/echoserver.vcproj @@ -21,6 +21,7 @@ OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="1" + InheritedPropertySheets="..\common.vsprops" CharacterSet="1" > @@ -117,7 +118,7 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\..\..\..\boost_1_47_0;.." + AdditionalIncludeDirectories=".." PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;WIN32_LEAN_AND_MEAN;NOCOMM;_WIN32_WINNT=0x0600" RuntimeLibrary="0" BufferSecurityCheck="false" @@ -139,7 +140,6 @@ - - - - - - diff --git a/windows/vcpp2008/websocketpp.sln b/windows/vcpp2008/websocketpp.sln index 2c657c2785..26e10dd30b 100644 --- a/windows/vcpp2008/websocketpp.sln +++ b/windows/vcpp2008/websocketpp.sln @@ -20,6 +20,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chatclient", "examples\chat {1C0FD04E-5ACA-4031-B3D1-320A5360C9D0} = {1C0FD04E-5ACA-4031-B3D1-320A5360C9D0} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "concurrent_server", "examples\concurrent_server.vcproj", "{F633A1F7-8FE5-408B-924F-4A3CAEF172C1}" + ProjectSection(ProjectDependencies) = postProject + {1C0FD04E-5ACA-4031-B3D1-320A5360C9D0} = {1C0FD04E-5ACA-4031-B3D1-320A5360C9D0} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -42,6 +47,10 @@ Global {116BFEDA-AF8E-4B3F-8508-ACC5EE89F905}.Debug|Win32.Build.0 = Debug|Win32 {116BFEDA-AF8E-4B3F-8508-ACC5EE89F905}.Release|Win32.ActiveCfg = Release|Win32 {116BFEDA-AF8E-4B3F-8508-ACC5EE89F905}.Release|Win32.Build.0 = Release|Win32 + {F633A1F7-8FE5-408B-924F-4A3CAEF172C1}.Debug|Win32.ActiveCfg = Debug|Win32 + {F633A1F7-8FE5-408B-924F-4A3CAEF172C1}.Debug|Win32.Build.0 = Debug|Win32 + {F633A1F7-8FE5-408B-924F-4A3CAEF172C1}.Release|Win32.ActiveCfg = Release|Win32 + {F633A1F7-8FE5-408B-924F-4A3CAEF172C1}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -50,5 +59,6 @@ Global {B569A272-D7D3-404B-B5FB-9187C0EB9F48} = {14E490FC-930E-40EE-B14A-84E2D98DEC9F} {2AFECE48-86DE-47D0-9263-DC0D203AA62D} = {14E490FC-930E-40EE-B14A-84E2D98DEC9F} {116BFEDA-AF8E-4B3F-8508-ACC5EE89F905} = {14E490FC-930E-40EE-B14A-84E2D98DEC9F} + {F633A1F7-8FE5-408B-924F-4A3CAEF172C1} = {14E490FC-930E-40EE-B14A-84E2D98DEC9F} EndGlobalSection EndGlobal diff --git a/windows/vcpp2008/websocketpp.vcproj b/windows/vcpp2008/websocketpp.vcproj index eb63530692..b992f2287c 100644 --- a/windows/vcpp2008/websocketpp.vcproj +++ b/windows/vcpp2008/websocketpp.vcproj @@ -21,6 +21,7 @@ OutputDirectory="$(SolutionDir)$(ConfigurationName)" IntermediateDirectory="$(ConfigurationName)" ConfigurationType="4" + InheritedPropertySheets=".\common.vsprops" CharacterSet="1" > @@ -107,7 +109,7 @@ Optimization="2" EnableIntrinsicFunctions="true" FavorSizeOrSpeed="1" - AdditionalIncludeDirectories="..\..\..\boost_1_47_0;." + AdditionalIncludeDirectories="." PreprocessorDefinitions="WIN32;NDEBUG;_LIB;WIN32_LEAN_AND_MEAN;NOCOMM;_WIN32_WINNT=0x0600" RuntimeLibrary="0" BufferSecurityCheck="false" @@ -159,27 +161,7 @@ > - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - @@ -249,7 +267,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +