diff --git a/.gitignore b/.gitignore index f8f6375ac..84b0b8781 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -*.cmake *.swp *.pyc CMakeCache.txt @@ -8,4 +7,10 @@ Testing *.gch libs/mime/test/mime-roundtrip *.a +bin/ +tests/ _build +CPP-NETLIB.* +CMakeScripts/ +*.cmake +*~ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..90e6826ad --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "deps/gtest"] + path = deps/gtest + url = git://github.com/cpp-netlib/gtest +[submodule "uri"] + path = uri + url = git://github.com/cpp-netlib/uri +[submodule "deps/gmock"] + path = deps/gmock + url = git://github.com/cpp-netlib/gmock diff --git a/CMakeLists.txt b/CMakeLists.txt index 4667f235f..2dc02acde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,40 +1,131 @@ -# Copyright (c) Dean Michael Berris 2010. +# Copyright (c) Dean Michael Berris 2010. +# Copyright (c) Google, Inc. 2012. # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) cmake_minimum_required(VERSION 2.8) project(CPP-NETLIB) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTI_THREADED ON) -find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options ) + +option( CPP-NETLIB_BUILD_SHARED_LIBS "Build cpp-netlib as shared libraries." OFF ) +option( CPP-NETLIB_BUILD_TESTS "Build the unit tests." ON ) +option( CPP-NETLIB_BUILD_EXAMPLES "Build the examples using cpp-netlib." ON ) +option( CPP-NETLIB_ALWAYS_LOGGING "Allow cpp-netlib to log debug messages even in non-debug mode." OFF ) +option( CPP-NETLIB_DISABLE_LOGGING "Disable logging definitely, no logging code will be generated or compiled." OFF ) + + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +find_package( ICU ) + +if(CPP-NETLIB_BUILD_SHARED_LIBS) + set(Boost_USE_STATIC_LIBS OFF) +else() + set(Boost_USE_STATIC_LIBS ON) +endif() +set(Boost_USE_MULTITHREADED ON) +if(CPP-NETLIB_BUILD_TESTS) + set(Boost_COMPONENTS unit_test_framework system regex date_time filesystem program_options ) +else() + set(Boost_COMPONENTS system regex date_time filesystem program_options ) +endif() +find_package( Boost 1.51 REQUIRED ${Boost_COMPONENTS} ) find_package( OpenSSL ) find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) -if (CMAKE_BUILD_TYPE MATCHES Debug) - add_definitions(-DBOOST_NETWORK_DEBUG) +if(CMAKE_BUILD_TYPE MATCHES Debug) + add_definitions(-DNETWORK_DEBUG) endif() + + if (OPENSSL_FOUND) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) + add_definitions(-DNETWORK_ENABLE_HTTPS) +endif() + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + if (HAVE_STD11) + set(CMAKE_CXX_FLAGS -std=c++11) + else() + message(FATAL_ERROR "No advanced standard C++ support (-std=c++11 not defined).") + endif() +elseif(${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + INCLUDE(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + if (HAVE_STD11) + set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++") + set(CMAKE_CXX_LINK_FLAGS "-std=c++11 -stdlib=libc++") + else() + message(FATAL_ERROR "No C++11 support for Clang version. Please upgrade Clang to a version supporting C++11.") + endif() + add_definitions( + -DASIO_HAS_MOVE -DASIO_HAS_VARIADIC_TEMPLATES -DASIO_HAS_STD_SYSTEM_ERROR + -DASIO_ERROR_CATEGORY_NOEXCEPT=noexcept -DASIO_HAS_STD_ARRAY + -DASIO_HAS_STD_SHARED_PTR -DASIO_HAS_STD_ATOMIC -DASIO_HAS_STD_CHRONO + -DASIO_HAS_STD_ADDRESSOFF -DASIO_HAS_STD_FUNCTION -DASIO_HAS_STD_TYPE_TRAITS) endif() +message("C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}") +message("C++ Flags: ${CMAKE_CXX_FLAGS} link flags: ${CMAKE_CXX_LINK_FLAGS}") if (Boost_FOUND) - if (MSVC) - add_definitions(-D_SCL_SECURE_NO_WARNINGS) - endif(MSVC) - if (WIN32) - add_definitions(-D_WIN32_WINNT=0x0501) - endif(WIN32) - include_directories(${Boost_INCLUDE_DIRS}) - enable_testing() - add_subdirectory(libs/network/src) - add_subdirectory(libs/network/test) - if (NOT MSVC) - add_subdirectory(libs/mime/test) - endif(NOT MSVC) - add_subdirectory(libs/network/example) + if (MSVC) + add_definitions(-D_SCL_SECURE_NO_WARNINGS) + endif(MSVC) + if (WIN32) + add_definitions(-D_WIN32_WINNT=0x0501) + endif(WIN32) + include_directories(${Boost_INCLUDE_DIRS}) endif(Boost_FOUND) -enable_testing() +message(STATUS "CPP-NETLIB options selected:") +message(STATUS " CPP-NETLIB_BUILD_SHARED_LIBS: ${CPP-NETLIB_BUILD_SHARED_LIBS}\t(Build cpp-netlib as shared libraries: OFF, ON)") +message(STATUS " CPP-NETLIB_BUILD_TESTS: ${CPP-NETLIB_BUILD_TESTS}\t(Build the unit tests: ON, OFF)") +message(STATUS " CPP-NETLIB_BUILD_EXAMPLES: ${CPP-NETLIB_BUILD_EXAMPLES}\t(Build the examples using cpp-netlib: ON, OFF)") +message(STATUS " CPP-NETLIB_ALWAYS_LOGGING: ${CPP-NETLIB_ALWAYS_LOGGING}\t(Allow cpp-netlib to log debug messages even in non-debug mode: ON, OFF)") +message(STATUS " CPP-NETLIB_DISABLE_LOGGING: ${CPP-NETLIB_DISABLE_LOGGING}\t(Disable logging definitely, no logging code will be generated or compiled: ON, OFF)") +message(STATUS "CMake build options selected:") + +############################################################################ +# +# The code following this point is for the new directory structure +# + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + if(MSVC11) + add_definitions(-D_VARIADIC_MAX=10) + endif(MSVC11) + + if(MSVC) + set(gtest_force_shared_crt ON CACHE BOOL "Override gtest option.") + endif(MSVC) + + # gmock automatically searches for gtest + add_subdirectory(deps/gmock) + + set(GTEST_ROOT ${CPP-NETLIB_SOURCE_DIR}/deps/gtest) + set(GTEST_FOUND ON) + set(GTEST_INCLUDE_DIRS ${GTEST_ROOT}/include) + set(GTEST_LIBRARIES gtest) + set(GTEST_MAIN_LIBRARIES gtest_main) + set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) + + set(GMOCK_ROOT ${CPP-NETLIB_SOURCE_DIR}/deps/gmock) + set(GMOCK_FOUND ON) + set(GMOCK_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} {${GMOCK_DIR}/include) + set(GMOCK_LIBRARIES {$GTEST_LIBRARIES} gmock) + set(GMOCK_MAIN_LIBRARIES gmock_main) + set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARIES} ${GMOCK_MAIN_LIBRARIES}) +endif() + +add_subdirectory(uri) +add_subdirectory(message) +add_subdirectory(logging) +add_subdirectory(concurrency) +add_subdirectory(http) +#add_subdirectory(mime) +if(CPP-NETLIB_BUILD_EXAMPLES) + add_subdirectory(contrib/http_examples) +endif() diff --git a/FindICU.cmake b/FindICU.cmake new file mode 100644 index 000000000..6cb91a073 --- /dev/null +++ b/FindICU.cmake @@ -0,0 +1,97 @@ +# Finds the International Components for Unicode (ICU) Library +# +# ICU_FOUND - True if ICU found. +# ICU_I18N_FOUND - True if ICU's internationalization library found. +# ICU_INCLUDE_DIRS - Directory to include to get ICU headers +# Note: always include ICU headers as, e.g., +# unicode/utypes.h +# ICU_LIBRARIES - Libraries to link against for the common ICU +# ICU_I18N_LIBRARIES - Libraries to link against for ICU internationaliation +# (note: in addition to ICU_LIBRARIES) + +# Look for the header file. +find_path( + ICU_INCLUDE_DIR + NAMES unicode/utypes.h + DOC "Include directory for the ICU library") +mark_as_advanced(ICU_INCLUDE_DIR) + +# Look for the library. +find_library( + ICU_LIBRARY + NAMES icuuc cygicuuc cygicuuc32 + DOC "Libraries to link against for the common parts of ICU") +mark_as_advanced(ICU_LIBRARY) + +# Copy the results to the output variables. +if(ICU_INCLUDE_DIR AND ICU_LIBRARY) + set(ICU_FOUND 1) + set(ICU_LIBRARIES ${ICU_LIBRARY}) + set(ICU_INCLUDE_DIRS ${ICU_INCLUDE_DIR}) + + set(ICU_VERSION 0) + set(ICU_MAJOR_VERSION 0) + set(ICU_MINOR_VERSION 0) + if (EXISTS "${ICU_INCLUDE_DIR}/unicode/uvernum.h") + FILE(READ "${ICU_INCLUDE_DIR}/unicode/uvernum.h" _ICU_VERSION_CONENTS) + else() + FILE(READ "${ICU_INCLUDE_DIR}/unicode/uversion.h" _ICU_VERSION_CONENTS) + endif() + + STRING(REGEX REPLACE ".*#define U_ICU_VERSION_MAJOR_NUM ([0-9]+).*" "\\1" ICU_MAJOR_VERSION "${_ICU_VERSION_CONENTS}") + STRING(REGEX REPLACE ".*#define U_ICU_VERSION_MINOR_NUM ([0-9]+).*" "\\1" ICU_MINOR_VERSION "${_ICU_VERSION_CONENTS}") + + set(ICU_VERSION "${ICU_MAJOR_VERSION}.${ICU_MINOR_VERSION}") + + # Look for the ICU internationalization libraries + find_library( + ICU_I18N_LIBRARY + NAMES icuin icui18n cygicuin cygicuin32 + DOC "Libraries to link against for ICU internationalization") + mark_as_advanced(ICU_I18N_LIBRARY) + if (ICU_I18N_LIBRARY) + set(ICU_I18N_FOUND 1) + set(ICU_I18N_LIBRARIES ${ICU_I18N_LIBRARY}) + else (ICU_I18N_LIBRARY) + set(ICU_I18N_FOUND 0) + set(ICU_I18N_LIBRARIES) + endif (ICU_I18N_LIBRARY) + + # Look for the ICU data libraries + find_library( + ICU_DATA_LIBRARY + NAMES icudata cygicudata cygicudata32 + DOC "Libraries to link against for ICU data") + mark_as_advanced(ICU_DATA_LIBRARY) + if (ICU_DATA_LIBRARY) + set(ICU_DATA_FOUND 1) + set(ICU_DATA_LIBRARIES ${ICU_DATA_LIBRARY}) + else (ICU_DATA_LIBRARY) + set(ICU_DATA_FOUND 0) + set(ICU_DATA_LIBRARIES) + endif (ICU_DATA_LIBRARY) +else(ICU_INCLUDE_DIR AND ICU_LIBRARY) + set(ICU_FOUND 0) + set(ICU_I18N_FOUND 0) + set(ICU_DATA_FOUND 0) + set(ICU_LIBRARIES) + set(ICU_I18N_LIBRARIES) + set(ICU_DATA_LIBRARIES) + set(ICU_INCLUDE_DIRS) + set(ICU_VERSION) + set(ICU_MAJOR_VERSION) + set(ICU_MINOR_VERSION) +endif(ICU_INCLUDE_DIR AND ICU_LIBRARY) + +IF(ICU_FOUND) + IF( NOT ICU_FIND_QUIETLY ) + MESSAGE( STATUS "Found ICU header files in ${ICU_INCLUDE_DIRS}") + MESSAGE( STATUS "Found ICU libraries: ${ICU_LIBRARIES}") + ENDIF( NOT ICU_FIND_QUIETLY ) +ELSE(ICU_FOUND) + IF(ICU_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Could not find ICU" ) + ELSE(ICU_FIND_REQUIRED) + MESSAGE( STATUS "Optional package ICU was not found" ) + ENDIF(ICU_FIND_REQUIRED) +ENDIF(ICU_FOUND) diff --git a/Jamroot b/Jamroot index 965e8d30e..ce0ebf032 100644 --- a/Jamroot +++ b/Jamroot @@ -6,7 +6,7 @@ import os ; -local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; +path-constant BOOST_ROOT : [ os.environ BOOST_ROOT ] ; use-project /boost : $(BOOST_ROOT) ; use-project /cpp-netlib : libs/network/build ; diff --git a/README.rst b/README.rst index b0f219767..84eed3723 100644 --- a/README.rst +++ b/README.rst @@ -33,23 +33,36 @@ You can find official release packages of the library at:: Building and Installing ----------------------- +Configuring the submodules +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The project contains submodules for some dependencies and some +libraries. Once you have cloned cpp-netlib, you must update the +submodules: + +:: + + $ cd ~/cpp-netlib + $ git submodule update + Building with CMake ~~~~~~~~~~~~~~~~~~~ To build the libraries and run the tests with CMake, you will need to -have CMake version 2.8 or higher installed appropriately in your +have CMake version 2.8.10 or higher installed appropriately in your system. :: $ cmake --version - cmake version 2.8.1 + cmake version 2.8.10 Inside the cpp-netlib directory, you can issue the following statements to configure and generate the Makefiles, and build the tests:: $ cd ~/cpp-netlib # we're assuming it's where cpp-netlib is - $ cmake -DCMAKE_BUILD_TYPE=Debug \ + $ cmake ~/cpp-netlib-build \ # cmake is built out of source + > -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=clang \ > -DCMAKE_CXX_COMPILER=clang++ \ > . @@ -57,7 +70,7 @@ configure and generate the Makefiles, and build the tests:: Once CMake is done with generating the Makefiles and configuring the project, you can now build the tests and run them:: - $ cd ~/cpp-netlib + $ cd ~/cpp-netlib-build $ make $ make test @@ -67,42 +80,14 @@ list`_. .. _`developers mailing list`: cpp-netlib@googlegroups.com -Building with Boost.Build -~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you don't already have Boost.Build set up on your system, follow the steps -indicated in the Boost Getting Started Guide [#]_ -- you will particularly want -to copy the ``bjam`` executable to a directory that is already in your ``PATH`` -so that you don't have to go hunting for it all the time. A good place to put it -is in ``/usr/local/bin``. - -.. [#] http://www.boost.org/doc/libs/release/more/getting_started/ - -Building and running the tests can be as simple as doing the following:: - - $ cd ~/cpp-netlib - $ bjam - -Doing this will already build all the tests and run them as they are built. In -case you encounter any problems and would like to report it to the developers, -please do the following:: - - $ cd ~/cpp-netlib - $ bjam 2>&1 >build-test.log - -And then attach the ``build-test.log`` file to the email you will send to the -cpp-netlib `developers mailing list`_. - -.. _`developers mailing list`: cpp-netlib@googlegroups.com - Running Tests ------------- If you want to run the tests that come with cpp-netlib, there are a few things you will need. These are: - * A compiler (GCC 4.x, Clang 2.8, MSVC 2008) - * A build tool (CMake [#]_ recommended, Boost.Build also an option) + * A compiler (GCC 4.7.x, Clang 2.8, MSVC 2012) + * CMake [#]_ * OpenSSL headers (optional) .. note:: This assumes that you have cpp-netlib at the top-level of @@ -136,13 +121,11 @@ would be greatly appreciated. Copious amounts of comments will be called out, but code that is not self-explanatory typically at least requires a rationale documentation in comments explaining "why" the code is written that way. -The main "upstream" repository is the one hosted by the original maintainer of -the project (Dean Michael Berris) at http://github.com/mikhailberis/cpp-netlib. -The "official" release repository is maintained at -http://github.com/cpp-netlib/cpp-netlib -- which is a fork of the upstream -repository. It is recommended that forks be made against the upstream repostory -and pull requests be submitted against the upstream repository so that patches -and other implementations can be curated by the original maintainer. +The main "upstream" repository and official release repository is +maintained at http://github.com/cpp-netlib/cpp-netlib. It is +recommended that forks and pull requests be submitted to the upstream +repository so that patches and other implementations can be curated by +the project administrators. Contact and Support ------------------- diff --git a/boost/network.hpp b/boost/network.hpp deleted file mode 100644 index 6ef92832e..000000000 --- a/boost/network.hpp +++ /dev/null @@ -1,18 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_HPP__ -#define __NETWORK_HPP__ - -// Include all headers in network/ -// Author: Dean Michael Berris -// Date: May 20, 2007 - -#include // message type implementation -#include // protocols implementation - -#endif // __NETWORK_HPP__ - diff --git a/boost/network/constants.hpp b/boost/network/constants.hpp deleted file mode 100644 index f2b100760..000000000 --- a/boost/network/constants.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef BOOST_NETWORK_CONSTANTS_HPP_20100808 -#define BOOST_NETWORK_CONSTANTS_HPP_20100808 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - template - struct constants_narrow { - - static char const * crlf() { - static char crlf_[] = { '\r', '\n', 0 }; - return crlf_; - } - - static char const * dot() { - static char dot_[] = { '.', 0 }; - return dot_; - } - - static char dot_char() { return '.'; } - - static char const * http_slash() { - static char http_slash_[] = { 'H', 'T', 'T', 'P', '/', 0 }; - return http_slash_; - } - - static char const * space() { - static char space_[] = {' ', 0}; - return space_; - } - - static char space_char() { return ' '; } - - static char const * slash() { - static char slash_[] = {'/', 0}; - return slash_; - } - - static char slash_char() { return '/'; } - - static char const * host() { - static char host_[] = {'H', 'o', 's', 't', 0}; - return host_; - } - - static char const * colon() { - static char colon_[] = {':', 0}; - return colon_; - } - - static char colon_char() { return ':'; } - - static char const * accept() { - static char accept_[] = {'A', 'c', 'c', 'e', 'p', 't', 0}; - return accept_; - } - - static char const * default_accept_mime() { - static char mime_[] = { - '*', '/', '*', 0 - }; - return mime_; - } - - static char const * accept_encoding() { - static char accept_encoding_[] = { - 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0 - }; - return accept_encoding_; - } - - static char const * default_accept_encoding() { - static char default_accept_encoding_[] = { - 'i','d','e','n','t','i','t','y',';','q','=','1','.','0',',',' ','*',';','q','=','0',0 - }; - return default_accept_encoding_; - } - - static char const * user_agent() { - static char user_agent_[] = { - 'U','s','e','r','-','A','g','e','n','t',0 - }; - return user_agent_; - } - - static char const * cpp_netlib_slash() { - static char cpp_netlib_slash_[] = { - 'c','p','p','-','n','e','t','l','i','b','/',0 - }; - return cpp_netlib_slash_; - } - - static char question_mark_char() { - return '?'; - } - - static char hash_char() { - return '#'; - } - - static char const * connection() { - static char connection_[] = { - 'C','o','n','n','e','c','t','i','o','n',0 - }; - return connection_; - } - - static char const * close() { - static char close_[] = { - 'C','l','o','s','e', 0 - }; - return close_; - } - - static char const * https() { - static char https_[] = "https"; - return https_; - } - - }; - - template - struct constants_wide { - - static wchar_t const * https() { - static wchar_t https_[] = L"https"; - return https_; - } - - }; - } - - template - struct constants : - mpl::if_< - is_default_string, - impl::constants_narrow, - typename mpl::if_< - is_default_wstring, - impl::constants_wide, - unsupported_tag - >::type - >::type - {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_CONSTANTS_HPP_20100808 diff --git a/boost/network/detail/debug.hpp b/boost/network/detail/debug.hpp deleted file mode 100644 index 8b331cdaa..000000000 --- a/boost/network/detail/debug.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BOOST_NETWORK_DEBUG_HPP_20110410 -#define BOOST_NETWORK_DEBUG_HPP_20110410 - -// (c) Copyright 2011 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -/** BOOST_NETWORK_MESSAGE is a debugging macro used by cpp-netlib to - print out network-related errors through standard error. This is - only useful when BOOST_NETWORK_DEBUG is turned on. Otherwise - the macro amounts to a no-op. -*/ -#ifdef BOOST_NETWORK_DEBUG -# include -# ifndef BOOST_NETWORK_MESSAGE -# define BOOST_NETWORK_MESSAGE(msg) std::cerr << "[DEBUG " << __FILE__ << ':' << __LINE__ << "]: " << msg << std::endl; -# endif -#else -# ifndef BOOST_NETWORK_MESSAGE -# define BOOST_NETWORK_MESSAGE(msg) -# endif -#endif - -#endif /* end of include guard: BOOST_NETWORK_DEBUG_HPP_20110410 */ diff --git a/boost/network/detail/directive_base.hpp b/boost/network/detail/directive_base.hpp deleted file mode 100644 index 0667d1345..000000000 --- a/boost/network/detail/directive_base.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ -#define __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ - -/** Defines the base type from which all directives inherit - * to allow friend access to message and other types' internals. - */ -namespace boost { namespace network { namespace detail { - - template - struct directive_base { - typedef Tag tag ; - //explicit directive_base(basic_message & message_) - // : _message(message_) - protected: - ~directive_base() - { }; // can only be extended - - // mutable basic_message & _message; - }; - -} // namespace detail - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ - diff --git a/boost/network/detail/wrapper_base.hpp b/boost/network/detail/wrapper_base.hpp deleted file mode 100644 index 9c1a8fca4..000000000 --- a/boost/network/detail/wrapper_base.hpp +++ /dev/null @@ -1,45 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_DETAIL_WRAPPER_BASE_HPP__ -#define __NETWORK_DETAIL_WRAPPER_BASE_HPP__ - -namespace boost { namespace network { - - namespace detail { - - template - struct wrapper_base { - explicit wrapper_base(Message & message_) - : _message(message_) - {}; - - protected: - ~wrapper_base() {}; // for extending only - - Message & _message; - }; - - template - struct wrapper_base_const { - explicit wrapper_base_const(Message const & message_) - : _message(message_) - {} - - protected: - ~wrapper_base_const() {}; // for extending only - - Message const & _message; - }; - - } // namespace detail - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_DETAIL_WRAPPER_BASE_HPP__ - diff --git a/boost/network/include/http/client.hpp b/boost/network/include/http/client.hpp deleted file mode 100644 index f9b27d188..000000000 --- a/boost/network/include/http/client.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ -#define BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ - -// Copyright 2009 Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// This is the modular include file for using the HTTP Client - -#include - -#endif // BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_ - diff --git a/boost/network/include/http/server.hpp b/boost/network/include/http/server.hpp deleted file mode 100644 index 021eefe0b..000000000 --- a/boost/network/include/http/server.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef BOOST_NETWORK_INCLUDE_HTTP_SERVER_HPP_ -#define BOOST_NETWORK_INCLUDE_HTTP_SERVER_HPP_ - -// Copyright 2010 Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// This is the modular include file for using the HTTP Client - -#include - -#endif diff --git a/boost/network/message.hpp b/boost/network/message.hpp deleted file mode 100644 index 190018b67..000000000 --- a/boost/network/message.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_HPP__ -#define __NETWORK_MESSAGE_HPP__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -/** message.hpp - * - * This header file implements the common message type which - * all networking implementations under the boost::network - * namespace. The common message type allows for easy message - * construction and manipulation suited for networked - * application development. - */ -namespace boost { namespace network { - - /** The common message type. - */ - template - struct basic_message { - public: - - typedef Tag tag; - - typedef typename headers_container::type headers_container_type; - typedef typename headers_container_type::value_type header_type; - typedef typename string::type string_type; - - basic_message() - : _headers(), _body(), _source(), _destination() - { } - - basic_message(const basic_message & other) - : _headers(other._headers), _body(other._body), _source(other._source), _destination(other._destination) - { } - - basic_message & operator=(basic_message rhs) { - rhs.swap(*this); - return *this; - } - - void swap(basic_message & other) { - std::swap(other._headers, _headers); - std::swap(other._body, _body); - std::swap(other._source, _source); - std::swap(other._destination, _destination); - } - - headers_container_type & headers() { - return _headers; - } - - void headers(headers_container_type const & headers_) const { - _headers = headers_; - } - - void add_header(typename headers_container_type::value_type const & pair_) const { - _headers.insert(pair_); - } - - void remove_header(typename headers_container_type::key_type const & key) const { - _headers.erase(key); - } - - headers_container_type const & headers() const { - return _headers; - } - - string_type & body() { - return _body; - } - - void body(string_type const & body_) const { - _body = body_; - } - - string_type const & body() const { - return _body; - } - - string_type & source() { - return _source; - } - - void source(string_type const & source_) const { - _source = source_; - } - - string_type const & source() const { - return _source; - } - - string_type & destination() { - return _destination; - } - - void destination(string_type const & destination_) const { - _destination = destination_; - } - - string_type const & destination() const { - return _destination; - } - - private: - - friend struct detail::directive_base ; - friend struct detail::wrapper_base > ; - - mutable headers_container_type _headers; - mutable string_type _body; - mutable string_type _source; - mutable string_type _destination; - }; - - template - inline void swap(basic_message & left, basic_message & right) { - // swap for ADL - left.swap(right); - } - - // Commenting this out as we don't need to do this anymore. - // BOOST_CONCEPT_ASSERT((Message >)); - // BOOST_CONCEPT_ASSERT((Message >)); - typedef basic_message message; - typedef basic_message wmessage; - -} // namespace network -} // namespace boost - -#endif // __NETWORK_MESSAGE_HPP__ - diff --git a/boost/network/message/directives.hpp b/boost/network/message/directives.hpp deleted file mode 100644 index 005a91e14..000000000 --- a/boost/network/message/directives.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_DIRECTIVES_HPP__ -#define __NETWORK_MESSAGE_DIRECTIVES_HPP__ - -#include -#include -#include - -namespace boost { namespace network { - - template - inline basic_message & - operator<< (basic_message & message_, Directive const & directive) { - directive(message_); - return message_; - } - - BOOST_NETWORK_STRING_DIRECTIVE(source, source_, message.source(source_), message.source=source_); - BOOST_NETWORK_STRING_DIRECTIVE(destination, destination_, message.destination(destination_), message.destination=destination_); - BOOST_NETWORK_STRING_DIRECTIVE(body, body_, message.body(body_), message.body=body_); - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_DIRECTIVES_HPP__ - diff --git a/boost/network/message/directives/detail/string_directive.hpp b/boost/network/message/directives/detail/string_directive.hpp deleted file mode 100644 index 6f2da4430..000000000 --- a/boost/network/message/directives/detail/string_directive.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 -#define BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * - * To create your own string directive, you can use the preprocessor macro - * BOOST_NETWORK_STRING_DIRECTIVE which takes three parameters: the name of - * the directive, a name for the variable to use in the directive visitor, - * and the body to be implemented in the visitor. An example directive for - * setting the source of a message would look something like this given the - * BOOST_NETWORK_STRING_DIRECTIVE macro: - * - * BOOST_NETWORK_STRING_DIRECTIVE(source, source_, - * message.source(source_) - * , message.source=source_); - * - */ - -#ifndef BOOST_NETWORK_STRING_DIRECTIVE -#define BOOST_NETWORK_STRING_DIRECTIVE(name, value, body, pod_body) \ - template \ - struct name##_directive { \ - ValueType const & value; \ - explicit name##_directive(ValueType const & value_) \ - : value(value_) {} \ - name##_directive(name##_directive const & other) \ - : value(other.value) {} \ - template class Message> \ - typename enable_if, void>::type \ - operator()(Message & message) const { \ - pod_body; \ - } \ - template class Message> \ - typename enable_if >, void>::type \ - operator()(Message & message) const { \ - body; \ - } \ - }; \ - \ - template inline name##_directive \ - name (T const & input) { \ - return name##_directive(input); \ - } -#endif /* BOOST_NETWORK_STRING_DIRECTIVE */ - -#endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 */ diff --git a/boost/network/message/directives/detail/string_value.hpp b/boost/network/message/directives/detail/string_value.hpp deleted file mode 100644 index 4d62d9747..000000000 --- a/boost/network/message/directives/detail/string_value.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 -#define BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace detail { - - template - struct string_value : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - -} /* detail */ -} /* network */ -} /* boost */ - -#endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 */ diff --git a/boost/network/message/directives/header.hpp b/boost/network/message/directives/header.hpp deleted file mode 100644 index e20c95cd9..000000000 --- a/boost/network/message/directives/header.hpp +++ /dev/null @@ -1,87 +0,0 @@ - -// Copyright Dean Michael Berris 2007-2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ -#define __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - - template - struct header_directive { - - explicit header_directive(KeyType const & header_name, - ValueType const & header_value) : - _header_name(header_name), - _header_value(header_value) - { }; - - template - struct pod_directive { - template - static void eval(Message const & message, T1 const & key, T2 const & value) { - typedef typename Message::headers_container_type::value_type value_type; - value_type value_ = { key, value }; - message.headers.insert(message.headers.end(), value_); - } - }; - - template - struct normal_directive { - template - static void eval(Message const & message, T1 const & key, T2 const & value) { - typedef typename Message::headers_container_type::value_type value_type; - message.add_header(value_type(key, value)); - } - }; - - template - struct directive_impl : - mpl::if_< - is_base_of< - tags::pod, - typename Message::tag - >, - pod_directive, - normal_directive - >::type - {}; - - template - void operator() (Message const & msg) const { - typedef typename Message::headers_container_type::value_type value_type; - directive_impl::eval(msg, _header_name, _header_value); - } - - private: - - KeyType const & _header_name; - ValueType const & _header_value; - }; - - } // namespace impl - - template - inline impl::header_directive - header(T1 const & header_name, T2 const & header_value) { - return impl::header_directive(header_name, header_value); - } -} // namespace network -} // namespace boost - -#endif // __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ - diff --git a/boost/network/message/directives/remove_header.hpp b/boost/network/message/directives/remove_header.hpp deleted file mode 100644 index 051d35f78..000000000 --- a/boost/network/message/directives/remove_header.hpp +++ /dev/null @@ -1,56 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP -#define NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP - - -#include - - -namespace boost { namespace network { - - template - struct basic_message; - -namespace impl { -template < - class T - > -struct remove_header_directive { - - explicit remove_header_directive(T header_name) : - header_name_(header_name) - { }; - - template - void operator() (basic_message & msg) const { - msg.headers().erase(header_name_); - } - -private: - mutable T header_name_; -}; - -} // namespace impl - -inline -impl::remove_header_directive -remove_header(std::string header_name) { - return impl::remove_header_directive(header_name); -} - -inline -impl::remove_header_directive -remove_header(std::wstring header_name) { - return impl::remove_header_directive(header_name); -} -} // namespace network -} // namespace boost - - -#endif // NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP - diff --git a/boost/network/message/message_concept.hpp b/boost/network/message/message_concept.hpp deleted file mode 100644 index 91ac07960..000000000 --- a/boost/network/message/message_concept.hpp +++ /dev/null @@ -1,73 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 -#define BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 - -// Copyright (c) Glyn Matthews 2010. -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct Message - : DefaultConstructible, CopyConstructible, Assignable { - typedef typename M::string_type string_type; - typedef typename M::headers_container_type headers_container_type; - - BOOST_CONCEPT_USAGE(Message) { - M message_; - swap(message, message_); - - typedef typename traits::body::type body_type; - typedef typename traits::source::type source_type; - typedef typename traits::destination::type destination_type; - - typedef typename traits::header_key::type header_key_type; - typedef typename traits::header_value::type header_value_type; - - headers_container_type headers_ = headers(message); - string_type body_ = body(message); - string_type source_ = source(message); - string_type destination_ = destination(message); - - message << source(source_type()) - << destination(destination_type()) - << header(string_type(), string_type()) - << body(body_type()); - - add_header(message, string_type(), string_type()); - remove_header(message, string_type()); - clear_headers(message); - source(message, source_type()); - destination(message, destination_type()); - body(message, body_type()); - - (void)headers_; - (void)body_; - (void)source_; - (void)destination_; - } - - private: - - M message; - }; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 - diff --git a/boost/network/message/modifiers/add_header.hpp b/boost/network/message/modifiers/add_header.hpp deleted file mode 100644 index f92e9c21f..000000000 --- a/boost/network/message/modifiers/add_header.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 -#define BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , mpl::not_ > - > - , void - >::type - add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { - message.headers().insert(std::make_pair(key, value)); - } - - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , is_async - > - , void - >::type - add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { - typedef typename Message::header_type header_type; - message.add_header(header_type(key,value)); - } - - template - inline typename enable_if< - is_pod - , void - >::type - add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { - typename Message::header_type header = { key, value }; - message.headers.insert(message.headers.end(), header); - } - - } - - template class Message, class KeyType, class ValueType> - inline void add_header(Message & message, KeyType const & key, ValueType const & value) { - impl::add_header(message, key, value, Tag()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 diff --git a/boost/network/message/modifiers/body.hpp b/boost/network/message/modifiers/body.hpp deleted file mode 100644 index 317264c68..000000000 --- a/boost/network/message/modifiers/body.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 -#define BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template class Message, class ValueType> - inline void body_impl(Message & message, ValueType const & body, tags::pod) { - message.body = body; - } - - template class Message, class ValueType> - inline void body_impl(Message & message, ValueType const & body, tags::normal) { - message.body(body); - } - - template class Message, class ValueType> - inline void body(Message & message, ValueType const & body_) { - body_impl(message, body_, typename pod_or_normal::type()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824 diff --git a/boost/network/message/modifiers/clear_headers.hpp b/boost/network/message/modifiers/clear_headers.hpp deleted file mode 100644 index b44ff1207..000000000 --- a/boost/network/message/modifiers/clear_headers.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 -#define BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , mpl::not_ > - > - , void - >::type - clear_headers(Message const & message, Tag const &) { - (typename Message::headers_container_type()).swap(message.headers()); - } - - template - inline typename enable_if, void>::type - clear_headers(Message const & message, Tag const &) { - (typename Message::headers_container_type()).swap(message.headers); - } - - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , is_async - > - , void - >::type - clear_headers(Message const & message, Tag const &) { - boost::promise header_promise; - boost::shared_future headers_future(header_promise.get_future()); - message.headers(headers_future); - header_promise.set_value(typename Message::headers_container_type()); - } - - } // namespace impl - - template class Message> - inline void clear_headers(Message const & message) { - impl::clear_headers(message, Tag()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 diff --git a/boost/network/message/modifiers/destination.hpp b/boost/network/message/modifiers/destination.hpp deleted file mode 100644 index b04b07129..000000000 --- a/boost/network/message/modifiers/destination.hpp +++ /dev/null @@ -1,38 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 -#define BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - namespace impl { - - template - inline void destination(Message const & message, ValueType const & destination_, Tag const &, mpl::false_ const &){ - message.destination(destination_); - } - - template - inline void destination(Message const & message, ValueType const & destination_, Tag const &, mpl::true_ const &) { - message.destination(destination_); - } - - } - - template class Message, class ValueType> - inline void destination(Message const & message, ValueType const & destination_) { - impl::destination(message, destination_, Tag(), is_async()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 diff --git a/boost/network/message/modifiers/remove_header.hpp b/boost/network/message/modifiers/remove_header.hpp deleted file mode 100644 index c2ab29bf1..000000000 --- a/boost/network/message/modifiers/remove_header.hpp +++ /dev/null @@ -1,85 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 -#define BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , mpl::not_ > - > - , void - >::type - remove_header(Message & message, KeyType const & key, Tag) { - message.headers().erase(key); - } - - template - inline typename enable_if< - mpl::and_< - mpl::not_ > - , is_async - > - , void - >::type - remove_header(Message & message, KeyType const & key, Tag) { - message.remove_header(key); - } - - template - struct iequals_pred { - KeyType const & key; - iequals_pred(KeyType const & key) - : key(key) {} - template - bool operator()(Header & other) const { - return boost::iequals(key, name(other)); - } - }; - - template - inline typename enable_if< - is_pod - , void - >::type - remove_header(Message & message, KeyType const & key, Tag) { - typedef typename Message::headers_container_type headers; - message.headers.erase( - boost::remove_if( - message.headers, - iequals_pred(key) - ) - , message.headers.end() - ); - } - - - } // namespace impl - - template class Message, class KeyType> - inline void remove_header(Message & message, KeyType const & key) { - impl::remove_header(message, key, Tag()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 - diff --git a/boost/network/message/modifiers/source.hpp b/boost/network/message/modifiers/source.hpp deleted file mode 100644 index fad8c00f3..000000000 --- a/boost/network/message/modifiers/source.hpp +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 -#define BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { - - namespace impl { - - template - inline void source(Message const & message, ValueType const & source_, Tag const &, mpl::false_ const &) { - message.source(source_); - } - - template - inline void source(Message const & message, ValueType const & source_, Tag const &, mpl::true_ const &) { - message.source(source_); - } - - } // namespace impl - - template class Message, class ValueType> - inline void source(Message const & message, ValueType const & source_) { - impl::source(message, source_, Tag(), is_async()); - } - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 diff --git a/boost/network/message/traits/body.hpp b/boost/network/message/traits/body.hpp deleted file mode 100644 index 25cb14961..000000000 --- a/boost/network/message/traits/body.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 -#define BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace traits { - - template - struct unsupported_tag; - - template - struct body : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - } // namespace traits - -} /* network */ - -} /* boost */ - -#endif // BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903 - diff --git a/boost/network/message/traits/destination.hpp b/boost/network/message/traits/destination.hpp deleted file mode 100644 index 92c5435ad..000000000 --- a/boost/network/message/traits/destination.hpp +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 -#define BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace traits { - - template - struct unsupported_tag; - - template - struct destination : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - } // namespace traits - -} /* network */ - -} /* boost */ - -#endif // BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903 - diff --git a/boost/network/message/traits/headers.hpp b/boost/network/message/traits/headers.hpp deleted file mode 100644 index e1d34abe8..000000000 --- a/boost/network/message/traits/headers.hpp +++ /dev/null @@ -1,66 +0,0 @@ - -#ifndef BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 -#define BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace traits { - - template - struct unsupported_tag; - - template - struct header_key : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - template - struct header_value : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - } // namespace traits - -} /* network */ - -} /* boost */ - -#endif // BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903 - diff --git a/boost/network/message/traits/source.hpp b/boost/network/message/traits/source.hpp deleted file mode 100644 index 231a5e0d3..000000000 --- a/boost/network/message/traits/source.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 -#define BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - namespace traits { - - template - struct unsupported_tag; - - template - struct source : - mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - } // namespace traits - -} /* network */ - -} /* boost */ - -#endif // BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903 - - diff --git a/boost/network/message/transformers.hpp b/boost/network/message/transformers.hpp deleted file mode 100644 index baea48f4b..000000000 --- a/boost/network/message/transformers.hpp +++ /dev/null @@ -1,62 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_TRANSFORMERS_HPP__ -#define __NETWORK_MESSAGE_TRANSFORMERS_HPP__ - -/** transformers.hpp - * - * Pulls in all the transformers files. - */ -#include -#include -#include - -#include - -namespace boost { namespace network { - namespace impl { - template - struct get_real_algorithm { - typedef typename boost::function_traits< - typename boost::remove_pointer< - Algorithm - >::type - > - ::result_type:: - template type< - typename boost::function_traits< - typename boost::remove_pointer< - Selector - >::type - >::result_type - > type; - }; - - template - struct transform_impl : public get_real_algorithm::type { }; - } // namspace impl - - template - inline impl::transform_impl - transform(Algorithm, Selector) { - return impl::transform_impl(); - } - - template - inline basic_message & - operator<< (basic_message & msg_, - impl::transform_impl - const & transformer) { - transformer(msg_); - return msg_; - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_TRANSFORMERS_HPP__ diff --git a/boost/network/message/transformers/selectors.hpp b/boost/network/message/transformers/selectors.hpp deleted file mode 100644 index 004c7f141..000000000 --- a/boost/network/message/transformers/selectors.hpp +++ /dev/null @@ -1,51 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ -#define __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ - -namespace boost { namespace network { - namespace selectors { - struct source_selector; - struct destination_selector; - } // namespace selectors - - selectors::source_selector source_(selectors::source_selector); - selectors::destination_selector destination_(selectors::destination_selector); - - namespace selectors { - struct source_selector { - private: - source_selector() {}; - source_selector(source_selector const &) {}; - friend source_selector boost::network::source_(source_selector); - }; - - struct destination_selector { - private: - destination_selector() {}; - destination_selector(destination_selector const &) {}; - friend destination_selector boost::network::destination_(destination_selector); - }; - } // namespace selectors - - typedef selectors::source_selector (*source_selector_t)(selectors::source_selector); - typedef selectors::destination_selector (*destination_selector_t)(selectors::destination_selector); - - inline selectors::source_selector source_(selectors::source_selector) { - return selectors::source_selector(); - } - - inline selectors::destination_selector destination_(selectors::destination_selector) { - return selectors::destination_selector(); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP__ - diff --git a/boost/network/message/transformers/to_lower.hpp b/boost/network/message/transformers/to_lower.hpp deleted file mode 100644 index 75ed3a67b..000000000 --- a/boost/network/message/transformers/to_lower.hpp +++ /dev/null @@ -1,82 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ -#define __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ - -#include - -/** to_lower.hpp - * - * Implements the to_lower transformer. This applies - * the to_lower string algorithm to a string, which - * is selected by the appropriate selector. - * - * This defines a type, to be applied using template - * metaprogramming on the selected string target. - */ -namespace boost { namespace network { - - namespace impl { - - template - struct to_lower_transformer { }; - - template <> - struct to_lower_transformer { - template - void operator() (basic_message & message_) const { - boost::to_lower(message_.source()); - } - - protected: - ~to_lower_transformer() { } - }; - - template <> - struct to_lower_transformer { - template - void operator() (basic_message & message_) const { - boost::to_lower(message_.destination()); - } - - protected: - ~to_lower_transformer() { }; - }; - - } // namespace impl - - namespace detail { - struct to_lower_placeholder_helper; - } - - detail::to_lower_placeholder_helper to_lower_(detail::to_lower_placeholder_helper); - - namespace detail { - - struct to_lower_placeholder_helper { - template - struct type : public impl::to_lower_transformer { }; - private: - to_lower_placeholder_helper() {} - to_lower_placeholder_helper(to_lower_placeholder_helper const &) {} - friend to_lower_placeholder_helper boost::network::to_lower_(to_lower_placeholder_helper); - }; - - } - - typedef detail::to_lower_placeholder_helper (*to_lower_placeholder)(detail::to_lower_placeholder_helper); - - inline detail::to_lower_placeholder_helper to_lower_(detail::to_lower_placeholder_helper) { - return detail::to_lower_placeholder_helper(); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP__ - diff --git a/boost/network/message/transformers/to_upper.hpp b/boost/network/message/transformers/to_upper.hpp deleted file mode 100644 index 8ad11c09e..000000000 --- a/boost/network/message/transformers/to_upper.hpp +++ /dev/null @@ -1,82 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ -#define __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ - -#include - -/** to_upper.hpp - * - * Implements the to_upper transformer. This applies - * the to_upper string algorithm to a string, which - * is selected by the appropriate selector. - * - * This defines a type, to be applied using template - * metaprogramming on the selected string target. - */ -namespace boost { namespace network { - - namespace impl { - - template - struct to_upper_transformer { }; - - template <> - struct to_upper_transformer { - template - void operator() (basic_message & message_) const { - boost::to_upper(message_.source()); - } - - protected: - ~to_upper_transformer() { }; - }; - - template <> - struct to_upper_transformer { - template - void operator() (basic_message & message_) const { - boost::to_upper(message_.destination()); - } - - protected: - ~to_upper_transformer() { }; - }; - - } // namespace impl - - namespace detail { - struct to_upper_placeholder_helper; - } - - detail::to_upper_placeholder_helper to_upper_(detail::to_upper_placeholder_helper); - - namespace detail { - - struct to_upper_placeholder_helper { - template - struct type : public impl::to_upper_transformer { }; - private: - to_upper_placeholder_helper() {} - to_upper_placeholder_helper(to_upper_placeholder_helper const &) {} - friend to_upper_placeholder_helper boost::network::to_upper_(to_upper_placeholder_helper); - }; - - } - - typedef detail::to_upper_placeholder_helper (*to_upper_placeholder)(detail::to_upper_placeholder_helper); - - inline detail::to_upper_placeholder_helper to_upper_(detail::to_upper_placeholder_helper) { - return detail::to_upper_placeholder_helper(); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP__ - diff --git a/boost/network/message/wrappers.hpp b/boost/network/message/wrappers.hpp deleted file mode 100644 index 60fbe06ae..000000000 --- a/boost/network/message/wrappers.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_WRAPPERS_HPP__ -#define __NETWORK_MESSAGE_WRAPPERS_HPP__ - -/** wrappers.hpp - * - * Pulls in all the wrapper header files. - */ -#include -#include -#include -#include - -#endif // __NETWORK_MESSAGE_WRAPPERS_HPP__ diff --git a/boost/network/message/wrappers/body.hpp b/boost/network/message/wrappers/body.hpp deleted file mode 100644 index 507d87e07..000000000 --- a/boost/network/message/wrappers/body.hpp +++ /dev/null @@ -1,112 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ -#define __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ - -#include -#include -#include - -namespace boost { namespace network { - - template - struct body_range { - typedef typename boost::iterator_range type; - }; - - namespace impl { - template - struct body_wrapper : public detail::wrapper_base > { - typedef basic_message message_type; - typedef typename string::type string_type; - typedef detail::wrapper_base > wrapper_base; - - explicit body_wrapper(basic_message & message_) - : wrapper_base(message_) - { }; - - operator string_type () const { - return string_type(wrapper_base::_message.body()); - }; - - std::size_t size() const { - return wrapper_base::_message.body().size(); - } - - operator boost::iterator_range< - typename boost::range_iterator::type - > () const { - return boost::make_iterator_range(wrapper_base::_message.body()); - } - - typename string_type::const_iterator - begin() const { - return wrapper_base::_message.body().begin(); - } - - typename string_type::const_iterator - end() const { - return wrapper_base::_message.body().end(); - } - - }; - - template - struct body_wrapper_const : public detail::wrapper_base_const > { - typedef basic_message message_type; - typedef typename string::type string_type; - typedef detail::wrapper_base_const > wrapper_base; - - explicit body_wrapper_const(basic_message const & message_) - : wrapper_base(message_) - {}; - - operator string_type () const { - return string_type(wrapper_base::_message.body()); - } - - std::size_t size() const { - return wrapper_base::_message.body().size(); - } - - operator boost::range_iterator () const { - return boost::make_iterator_range(wrapper_base::_message.body()); - } - }; - - template - inline std::ostream & operator<<(std::ostream & os, body_wrapper const & body) { - os << static_cast::string_type>(body); - return os; - } - - template - inline std::ostream & operator<<(std::ostream & os, body_wrapper_const const & body) { - os << static_cast::string_type>(body); - return os; - } - - } // namespace impl - - template - inline impl::body_wrapper const - body(basic_message & message_) { - return impl::body_wrapper(message_); - } - - template - inline impl::body_wrapper_const const - body(basic_message const & message_) { - return impl::body_wrapper_const(message_); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__ - diff --git a/boost/network/message/wrappers/destination.hpp b/boost/network/message/wrappers/destination.hpp deleted file mode 100644 index 935e9c101..000000000 --- a/boost/network/message/wrappers/destination.hpp +++ /dev/null @@ -1,45 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ -#define __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ - - -#include - - -namespace boost { namespace network { - - namespace impl { - template - struct destination_wrapper : public detail::wrapper_base > { - typedef Tag tag; - typedef basic_message message_type; - typedef typename string::type string_type; - typedef detail::wrapper_base > wrapper_base; - - explicit destination_wrapper(message_type & message_) - : wrapper_base(message_) - { }; - - operator string_type () const { - return string_type(wrapper_base::_message.destination()); - }; - }; - } // namespace impl - - template - inline typename string::type - destination(basic_message & message_) { - return impl::destination_wrapper(message_); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__ - diff --git a/boost/network/message/wrappers/headers.hpp b/boost/network/message/wrappers/headers.hpp deleted file mode 100644 index 37a2e611c..000000000 --- a/boost/network/message/wrappers/headers.hpp +++ /dev/null @@ -1,101 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ -#define __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - /// Template metaprogram to get the range type for a message - template - struct headers_range { - typedef typename headers_container::type headers_container_type; - typedef typename - boost::iterator_range - type; - }; - - template - struct basic_message; - - /** headers wrapper for messages. - * - * This exposes an interface similar to a map, indexable - * using operator[] taking a string as the index and returns - * a range of iterators (std::pair) - * whose keys are all equal to the index string. - * - * This type is also convertible to a - * headers_range >::type - * Which allows for full range support. - * - * The type is also convertible to a - * headers_container::type - * Which copies the headers from the wrapped message. - * - */ - namespace impl { - template - struct headers_wrapper : public detail::wrapper_base_const > { - typedef Tag tag; - typedef basic_message message_type; - typedef typename string::type string_type; - typedef typename headers_range::type range_type; - typedef typename headers_container::type headers_container_type; - typedef typename headers_container_type::const_iterator const_iterator; - typedef typename headers_container_type::iterator iterator; - typedef detail::wrapper_base_const > wrapper_base; - - explicit headers_wrapper(basic_message const & message_) - : wrapper_base(message_) - { }; - - range_type operator[] (string_type const & key) const { - return headers_wrapper::_message.headers().equal_range(key); - }; - - typename message_type::headers_container_type::size_type count(string_type const & key) const { - return headers_wrapper::_message.headers().count(key); - }; - - const_iterator begin() const { - return headers_wrapper::_message.headers().begin(); - }; - - const_iterator end() const { - return headers_wrapper::_message.headers().end(); - }; - - operator range_type () { - return make_iterator_range(headers_wrapper::_message.headers().begin(), headers_wrapper::_message.headers().end()); - }; - - operator headers_container_type () { - return headers_wrapper::_message.headers(); - } - - }; - } // namespace impl - - /// Factory method to create the right wrapper object - template - inline impl::headers_wrapper - headers(basic_message const & message_) { - return impl::headers_wrapper(message_); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ - diff --git a/boost/network/message/wrappers/source.hpp b/boost/network/message/wrappers/source.hpp deleted file mode 100644 index 42579895c..000000000 --- a/boost/network/message/wrappers/source.hpp +++ /dev/null @@ -1,46 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ -#define __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ - - -#include - - -namespace boost { namespace network { - - namespace impl { - template - struct source_wrapper : public detail::wrapper_base > { - typedef Tag tag; - typedef basic_message message_type; - typedef typename string::type string_type; - typedef detail::wrapper_base > wrapper_base; - - explicit source_wrapper(basic_message & message_) - : wrapper_base(message_) - { }; - - operator string_type () const { - return string_type(wrapper_base::_message.source()); - }; - }; - } // namespace impl - - template - inline typename string::type - source(basic_message & message_) { - return impl::source_wrapper(message_); - } - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__ - - diff --git a/boost/network/message_fwd.hpp b/boost/network/message_fwd.hpp deleted file mode 100644 index ca8714e70..000000000 --- a/boost/network/message_fwd.hpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Glyn Matthews 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __2008817MESSAGE_FWD_INC__ -# define __2008817MESSAGE_FWD_INC__ - -namespace boost { -namespace network { - -template -struct basic_message; - -} // namespace boost -} // namespace network - - -#endif // __2008817MESSAGE_FWD_INC__ diff --git a/boost/network/protocol.hpp b/boost/network/protocol.hpp deleted file mode 100644 index 9810697b7..000000000 --- a/boost/network/protocol.hpp +++ /dev/null @@ -1,16 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOLS_20070908_1_HPP__ -#define __NETWORK_PROTOCOLS_20070908_1_HPP__ - -// Include all protocol implementation headers in protocol/* -// Author: Dean Michael Berris -// Date Created: Oct. 08, 2007 - -#include // include HTTP implementation - -#endif // __NETWORK_PROTOCOLS_20070908-1_HPP__ diff --git a/boost/network/protocol/http.hpp b/boost/network/protocol/http.hpp deleted file mode 100644 index 2304f6f8b..000000000 --- a/boost/network/protocol/http.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -// Copyright Dean Michael Berris 2007, 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOL_HTTP_20070908_1_HPP__ -#define __NETWORK_PROTOCOL_HTTP_20070908_1_HPP__ - -// Include HTTP implementation headers -// Author: Dean Michael Berris -// Date Created: Oct. 08, 2007 - -#include -#include -#include -#include - -#endif // __NETWORK_PROTOCOL_HTTP_20070908-1_HPP__ diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp deleted file mode 100644 index 703a7cf7f..000000000 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct linearize_header { - typedef typename string::type string_type; - - template - struct result; - - template - struct result { - typedef string_type type; - }; - - template - BOOST_CONCEPT_REQUIRES( - ((Header)), - (string_type) - ) operator()(ValueType & header) { - typedef typename ostringstream::type output_stream; - typedef constants consts; - output_stream header_line; - header_line << name(header) - << consts::colon() << consts::space() - << value(header) << consts::crlf(); - return header_line.str(); - } - }; - - template - BOOST_CONCEPT_REQUIRES( - ((ClientRequest)), - (OutputIterator) - ) linearize( - Request const & request, - typename Request::string_type const & method, - unsigned version_major, - unsigned version_minor, - OutputIterator oi - ) - { - typedef typename Request::tag Tag; - typedef constants consts; - typedef typename string::type string_type; - static string_type - http_slash = consts::http_slash() - , accept = consts::accept() - , accept_mime = consts::default_accept_mime() - , accept_encoding = consts::accept_encoding() - , default_accept_encoding = consts::default_accept_encoding() - , crlf = consts::crlf() - , host = consts::host() - , connection = consts::connection() - , close = consts::close() - ; - boost::copy(method, oi); - *oi = consts::space_char(); - if (request.path().empty() || request.path()[0] != consts::slash_char()) - *oi = consts::slash_char(); - boost::copy(request.path(), oi); - if (!request.query().empty()) { - *oi = consts::question_mark_char(); - boost::copy(request.query(), oi); - } - if (!request.anchor().empty()) { - *oi = consts::hash_char(); - boost::copy(request.anchor(), oi); - } - *oi = consts::space_char(); - boost::copy(http_slash, oi); - string_type version_major_str = boost::lexical_cast(version_major), - version_minor_str = boost::lexical_cast(version_minor); - boost::copy(version_major_str, oi); - *oi = consts::dot_char(); - boost::copy(version_minor_str, oi); - boost::copy(crlf, oi); - boost::copy(host, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(request.host(), oi); - boost::optional port_ = port(request); - if (port_) { - string_type port_str = boost::lexical_cast(*port_); - *oi = consts::colon_char(); - boost::copy(port_str, oi); - } - boost::copy(crlf, oi); - boost::copy(accept, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(accept_mime, oi); - boost::copy(crlf, oi); - if (version_major == 1u && version_minor == 1u) { - boost::copy(accept_encoding, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(default_accept_encoding, oi); - boost::copy(crlf, oi); - } - typedef typename headers_range::type headers_range; - typedef typename range_value::type headers_value; - BOOST_FOREACH(const headers_value &header, headers(request)) - { - string_type header_name = name(header), - header_value = value(header); - boost::copy(header_name, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(header_value, oi); - boost::copy(crlf, oi); - } - if (!connection_keepalive::value) { - boost::copy(connection, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(close, oi); - boost::copy(crlf, oi); - } - boost::copy(crlf, oi); - typename body_range::type body_data = body(request).range(); - return boost::copy(body_data, oi); - } - -} /* http */ - -} /* net */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ - diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp deleted file mode 100644 index 78a0619bf..000000000 --- a/boost/network/protocol/http/client.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 - -// Copyright Dean Michael Berris 2007-2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_client - : basic_client_facade - { - private: - typedef basic_client_facade - base_facade_type; - public: - typedef basic_request request; - typedef basic_response response; - typedef typename string::type string_type; - typedef Tag tag_type; - - // Constructor - // ================================================================= - // This is a Boost.Parameter-based constructor forwarder, whose - // implementation is actually forwarded to the base type. - // - // The supported parameters are: - // _follow_redirects : bool -- whether to follow HTTP redirect - // responses (default: false) - // _cache_resolved : bool -- whether to cache the resolved - // endpoints (default: false) - // _io_service : boost::asio::io_service & - // -- supply an io_service to the - // client - // _openssl_certificate : string - // -- the name of the certificate file - // to use - // _openssl_verify_path : string - // -- the name of the directory from - // which the certificate authority - // files can be found - - BOOST_PARAMETER_CONSTRUCTOR( - basic_client, (base_facade_type), tag, - (optional - (in_out(io_service), (boost::asio::io_service&)) - (follow_redirects, (bool)) - (cache_resolved, (bool)) - (openssl_certificate, (string_type)) - (openssl_verify_path, (string_type)) - )) - - // - // ================================================================= - - }; - -#ifndef BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG -#define BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG tags::http_async_8bit_udp_resolve -#endif - - typedef basic_client client; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215 diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp deleted file mode 100644 index a7e178d16..000000000 --- a/boost/network/protocol/http/client/async_impl.hpp +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 - -// Copyright Dean Michael Berris 2010. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_client_impl; - - namespace impl { - template - struct async_client : - connection_policy::type - { - typedef - typename connection_policy::type - connection_base; - typedef - typename resolver::type - resolver_type; - typedef - typename string::type - string_type; - - typedef - function const &, system::error_code const &)> - body_callback_function_type; - - async_client(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) - : connection_base(cache_resolved, follow_redirect), - service_ptr(new boost::asio::io_service), - service_(*service_ptr), - resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)), - certificate_filename_(certificate_filename), - verify_path_(verify_path) - { - connection_base::resolver_strand_.reset(new - boost::asio::io_service::strand(service_)); - lifetime_thread_.reset(new boost::thread( - boost::bind( - &boost::asio::io_service::run, - &service_ - ))); - } - - async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) - : connection_base(cache_resolved, follow_redirect), - service_ptr(0), - service_(service), - resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)), - certificate_filename_(certificate_filename), - verify_path_(verify_path) - { - } - - ~async_client() throw () - { - sentinel_.reset(); - if (lifetime_thread_.get()) { - lifetime_thread_->join(); - lifetime_thread_.reset(); - } - delete service_ptr; - } - - basic_response const request_skeleton( - basic_request const & request_, - string_type const & method, - bool get_body, - body_callback_function_type callback - ) - { - typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); - return connection_->send_request(method, request_, get_body, callback); - } - - boost::asio::io_service * service_ptr; - boost::asio::io_service & service_; - resolver_type resolver_; - boost::shared_ptr sentinel_; - boost::shared_ptr lifetime_thread_; - optional certificate_filename_, verify_path_; - }; - } // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp deleted file mode 100644 index 943ca2106..000000000 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct async_connection_base { - typedef async_connection_base this_type; - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename resolver_base::resolve_function resolve_function; - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef iterator_range char_const_range; - typedef function - body_callback_function_type; - typedef shared_ptr connection_ptr; - - // This is the factory function which constructs the appropriate async - // connection implementation with the correct delegate chosen based on the - // tag. - static connection_ptr new_connection( - resolve_function resolve, - resolver_type & resolver, - bool follow_redirect, - bool https, - optional certificate_filename=optional(), - optional const & verify_path=optional()) { - typedef http_async_connection - async_connection; - typedef typename delegate_factory::type delegate_factory_type; - connection_ptr temp; - temp.reset( - new async_connection( - resolver, - resolve, - follow_redirect, - delegate_factory_type::new_connection_delegate( - resolver.get_io_service(), - https, - certificate_filename, - verify_path))); - BOOST_ASSERT(temp.get() != 0); - return temp; - } - - // This is the pure virtual entry-point for all asynchronous connections. - virtual response start( - request const & request, - string_type const & method, - bool get_body, - body_callback_function_type callback) = 0; - - virtual ~async_connection_base() {} - - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529 diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp deleted file mode 100644 index 4f95fdcf0..000000000 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ /dev/null @@ -1,447 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google,Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct async_connection_base; - - namespace placeholders = boost::asio::placeholders; - - template - struct http_async_connection - : async_connection_base, - protected http_async_protocol_handler, - boost::enable_shared_from_this > - { - typedef async_connection_base base; - typedef http_async_protocol_handler protocol_base; - typedef typename base::resolver_type resolver_type; - typedef typename base::resolver_base::resolver_iterator resolver_iterator; - typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; - typedef typename base::response response; - typedef typename base::string_type string_type; - typedef typename base::request request; - typedef typename base::resolver_base::resolve_function resolve_function; - typedef typename base::body_callback_function_type body_callback_function_type; - typedef http_async_connection this_type; - typedef typename delegate_factory::type delegate_factory_type; - typedef typename delegate_factory_type::connection_delegate_ptr - connection_delegate_ptr; - - http_async_connection(resolver_type & resolver, - resolve_function resolve, - bool follow_redirect, - connection_delegate_ptr delegate) - : - follow_redirect_(follow_redirect), - resolver_(resolver), - resolve_(resolve), - request_strand_(resolver.get_io_service()), - delegate_(delegate) {} - - // This is the main entry point for the connection/request pipeline. We're - // overriding async_connection_base<...>::start(...) here which is called - // by the client. - virtual response start(request const & request, - string_type const & method, - bool get_body, - body_callback_function_type callback) { - response response_; - this->init_response(response_, get_body); - linearize(request, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&command_streambuf)); - this->method = method; - boost::uint16_t port_ = port(request); - resolve_(resolver_, - host(request), - port_, - request_strand_.wrap( - boost::bind(&this_type::handle_resolved, - this_type::shared_from_this(), - port_, - get_body, - callback, - _1, - _2))); - return response_; - } - - private: - - http_async_connection(http_async_connection const &); // = delete - - void set_errors(boost::system::error_code const & ec) { - boost::system::system_error error(ec); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - - void handle_resolved(boost::uint16_t port, - bool get_body, - body_callback_function_type callback, - boost::system::error_code const & ec, - resolver_iterator_pair endpoint_range) { - if (!ec && !boost::empty(endpoint_range)) { - // Here we deal with the case that there was an error encountered and - // that there's still more endpoints to try connecting to. - resolver_iterator iter = boost::begin(endpoint_range); - asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); - delegate_->connect(endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, - get_body, - callback, - std::make_pair(++iter, - resolver_iterator()), - placeholders::error))); - } else { - set_errors(ec ? ec : boost::asio::error::host_not_found); - } - } - - void handle_connected(boost::uint16_t port, - bool get_body, - body_callback_function_type callback, - resolver_iterator_pair endpoint_range, - boost::system::error_code const & ec) { - if (!ec) { - BOOST_ASSERT(delegate_.get() != 0); - delegate_->write(command_streambuf, - request_strand_.wrap( - boost::bind( - &this_type::handle_sent_request, - this_type::shared_from_this(), - get_body, - callback, - placeholders::error, - placeholders::bytes_transferred))); - } else { - if (!boost::empty(endpoint_range)) { - resolver_iterator iter = boost::begin(endpoint_range); - asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); - delegate_->connect(endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, - get_body, - callback, - std::make_pair(++iter, - resolver_iterator()), - placeholders::error))); - } else { - set_errors(ec ? ec : boost::asio::error::host_not_found); - } - } - } - - enum state_t { - version, status, status_message, headers, body - }; - - void handle_sent_request(bool get_body, - body_callback_function_type callback, - boost::system::error_code const & ec, - std::size_t bytes_transferred) { - if (!ec) { - delegate_->read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), - this->part.size()), - request_strand_.wrap( - boost::bind(&this_type::handle_received_data, - this_type::shared_from_this(), - version, get_body, callback, - placeholders::error, - placeholders::bytes_transferred))); - } else { - set_errors(ec); - } - } - - void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - static long short_read_error = 335544539; - bool is_ssl_short_read_error = -#ifdef BOOST_NETWORK_ENABLE_HTTPS - ec.category() == asio::error::ssl_category && - ec.value() == short_read_error -#else - false -#endif - ; - if (!ec || ec == boost::asio::error::eof || is_ssl_short_read_error) { - logic::tribool parsed_ok; - size_t remainder; - switch(state) { - case version: - parsed_ok = - this->parse_version(delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - version, get_body, callback, - placeholders::error, - placeholders::bytes_transferred)), - bytes_transferred); - if (!parsed_ok || indeterminate(parsed_ok)) return; - case status: - parsed_ok = - this->parse_status(delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - status, get_body, callback, - placeholders::error, - placeholders::bytes_transferred)), - bytes_transferred); - if (!parsed_ok || indeterminate(parsed_ok)) return; - case status_message: - parsed_ok = - this->parse_status_message(delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - status_message, get_body, callback, - placeholders::error, placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (!parsed_ok || indeterminate(parsed_ok)) return; - case headers: - // In the following, remainder is the number of bytes that remain - // in the buffer. We need this in the body processing to make sure - // that the data remaining in the buffer is dealt with before - // another call to get more data for the body is scheduled. - fusion::tie(parsed_ok, remainder) = - this->parse_headers(delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - headers, get_body, callback, - placeholders::error, placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - - if (!parsed_ok || indeterminate(parsed_ok)) return; - - if (!get_body) { - // We short-circuit here because the user does not - // want to get the body (in the case of a HEAD - // request). - this->body_promise.set_value(""); - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); - return; - } - - if (callback) { - // Here we deal with the spill-over data from the - // headers processing. This means the headers data - // has already been parsed appropriately and we're - // looking to treat everything that remains in the - // buffer. - typename protocol_base::buffer_type::const_iterator begin = this->part_begin; - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, remainder); - - // We're setting the body promise here to an empty string because - // this can be used as a signaling mechanism for the user to - // determine that the body is now ready for processing, even - // though the callback is already provided. - this->body_promise.set_value(""); - - // The invocation of the callback is synchronous to allow us to - // wait before scheduling another read. - callback(make_iterator_range(begin, end), ec); - - delegate_->read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), - this->part.size()), - request_strand_.wrap( - boost::bind(&this_type::handle_received_data, - this_type::shared_from_this(), - body, - get_body, - callback, - placeholders::error, - placeholders::bytes_transferred))); - } else { - // Here we handle the body data ourself and append to an - // ever-growing string buffer. - this->parse_body( - delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, get_body, callback, - placeholders::error, placeholders::bytes_transferred - ) - ), - remainder); - } - return; - case body: - if (ec == boost::asio::error::eof || is_ssl_short_read_error) { - // Here we're handling the case when the connection has been - // closed from the server side, or at least that the end of file - // has been reached while reading the socket. This signals the end - // of the body processing chain. - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = - this->part.begin(), - end = begin; - std::advance(end, bytes_transferred); - - // We call the callback function synchronously passing the error - // condition (in this case, end of file) so that it can handle - // it appropriately. - callback(make_iterator_range(begin, end), ec); - } else { - string_type body_string; - std::swap(body_string, this->partial_parsed); - body_string.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body_string); - } - // TODO set the destination value somewhere! - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); - } else { - // This means the connection has not been closed yet and we want to get more - // data. - if (callback) { - // Here we have a body_handler callback. Let's invoke the - // callback from here and make sure we're getting more data - // right after. - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - delegate_->read_some( - boost::asio::mutable_buffers_1( - this->part.c_array(), - this->part.size()), - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, - get_body, - callback, - placeholders::error, - placeholders::bytes_transferred))); - } else { - // Here we don't have a body callback. Let's - // make sure that we deal with the remainder - // from the headers part in case we do have data - // that's still in the buffer. - this->parse_body(delegate_, - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, - get_body, - callback, - placeholders::error, - placeholders::bytes_transferred)), - bytes_transferred); - } - } - return; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } else { - boost::system::system_error error(ec); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - switch (state) { - case version: - this->version_promise.set_exception(boost::copy_exception(error)); - case status: - this->status_promise.set_exception(boost::copy_exception(error)); - case status_message: - this->status_message_promise.set_exception(boost::copy_exception(error)); - case headers: - this->headers_promise.set_exception(boost::copy_exception(error)); - case body: - this->body_promise.set_exception(boost::copy_exception(error)); - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } - } - - bool follow_redirect_; - resolver_type & resolver_; - resolve_function resolve_; - boost::asio::io_service::strand request_strand_; - connection_delegate_ptr delegate_; - boost::asio::streambuf command_streambuf; - string_type method; - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp deleted file mode 100644 index 0e18b231c..000000000 --- a/boost/network/protocol/http/client/connection/connection_delegate.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { namespace impl { - -struct connection_delegate { - virtual void connect(asio::ip::tcp::endpoint & endpoint, - function handler) = 0; - virtual void write(asio::streambuf & command_streambuf, - function handler) = 0; - virtual void read_some(asio::mutable_buffers_1 const & read_buffer, - function handler) = 0; - virtual ~connection_delegate() {} -}; - -} /* impl */ - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ */ diff --git a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp deleted file mode 100644 index eca673666..000000000 --- a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include -#endif /* BOOST_NETWORK_ENABLE_HTTPS */ - -namespace boost { namespace network { namespace http { namespace impl { - -struct ssl_delegate; - -struct normal_delegate; - -template -struct connection_delegate_factory { - typedef shared_ptr connection_delegate_ptr; - typedef typename string::type string_type; - - // This is the factory method that actually returns the delegate instance. - // TODO Support passing in proxy settings when crafting connections. - static connection_delegate_ptr new_connection_delegate( - asio::io_service & service, - bool https, - optional certificate_filename, - optional verify_path) { - connection_delegate_ptr delegate; - if (https) { -#ifdef BOOST_NETWORK_ENABLE_HTTPS - delegate.reset(new ssl_delegate(service, - certificate_filename, - verify_path)); -#else - BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported.")); -#endif /* BOOST_NETWORK_ENABLE_HTTPS */ - } else { - delegate.reset(new normal_delegate(service)); - } - return delegate; - } -}; - -} /* impl */ -} /* http */ -} /* network */ -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp deleted file mode 100644 index d18f1461a..000000000 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - -struct normal_delegate : connection_delegate { - normal_delegate(asio::io_service & service); - - virtual void connect(asio::ip::tcp::endpoint & endpoint, - function handler); - virtual void write(asio::streambuf & command_streambuf, - function handler); - virtual void read_some(asio::mutable_buffers_1 const & read_buffer, - function handler); - ~normal_delegate(); - - private: - asio::io_service & service_; - scoped_ptr socket_; - - normal_delegate(normal_delegate const &); // = delete - normal_delegate& operator=(normal_delegate); // = delete -}; - -} /* impl */ - -} /* http */ - -} /* network */ - -} /* boost */ - -#ifdef BOOST_NETWORK_NO_LIB -#include -#endif /* BOOST_NETWORK_NO_LIB */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp deleted file mode 100644 index f084dc163..000000000 --- a/boost/network/protocol/http/client/connection/normal_delegate.ipp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -boost::network::http::impl::normal_delegate::normal_delegate(asio::io_service & service) - : service_(service) -{} - -void boost::network::http::impl::normal_delegate::connect( - asio::ip::tcp::endpoint & endpoint, - function handler) { - socket_.reset(new asio::ip::tcp::socket(service_)); - socket_->async_connect(endpoint, handler); -} - -void boost::network::http::impl::normal_delegate::write( - asio::streambuf & command_streambuf, - function handler) { - asio::async_write(*socket_, command_streambuf, handler); -} - -void boost::network::http::impl::normal_delegate::read_some( - asio::mutable_buffers_1 const & read_buffer, - function handler) { - socket_->async_read_some(read_buffer, handler); -} - -boost::network::http::impl::normal_delegate::~normal_delegate() {} - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp deleted file mode 100644 index a1cb9a0c6..000000000 --- a/boost/network/protocol/http/client/connection/ssl_delegate.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - -struct ssl_delegate : connection_delegate, enable_shared_from_this { - ssl_delegate(asio::io_service & service, - optional certificate_filename, - optional verify_path); - - virtual void connect(asio::ip::tcp::endpoint & endpoint, - function handler); - virtual void write(asio::streambuf & command_streambuf, - function handler); - virtual void read_some(asio::mutable_buffers_1 const & read_buffer, - function handler); - ~ssl_delegate(); - - private: - asio::io_service & service_; - optional certificate_filename_, verify_path_; - scoped_ptr context_; - scoped_ptr > socket_; - - ssl_delegate(ssl_delegate const &); // = delete - ssl_delegate& operator=(ssl_delegate); // = delete - - void handle_connected(system::error_code const & ec, - function handler); -}; - -} /* impl */ - -} /* http */ - -} /* network */ - -} /* boost */ - -#ifdef BOOST_NETWORK_NO_LIB -#include -#endif /* BOOST_NETWORK_NO_LIB */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp deleted file mode 100755 index 3acd5addb..000000000 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -boost::network::http::impl::ssl_delegate::ssl_delegate(asio::io_service & service, - optional certificate_filename, - optional verify_path) : - service_(service), - certificate_filename_(certificate_filename), - verify_path_(verify_path) {} - -void boost::network::http::impl::ssl_delegate::connect( - asio::ip::tcp::endpoint & endpoint, - function handler) { - context_.reset(new asio::ssl::context( - service_, - asio::ssl::context::sslv23_client)); - if (certificate_filename_ || verify_path_) { - context_->set_verify_mode(asio::ssl::context::verify_peer); - if (certificate_filename_) context_->load_verify_file(*certificate_filename_); - if (verify_path_) context_->add_verify_path(*verify_path_); - } else { - context_->set_verify_mode(asio::ssl::context::verify_none); - } - socket_.reset(new asio::ssl::stream(service_, *context_)); - socket_->lowest_layer().async_connect( - endpoint, - ::boost::bind(&boost::network::http::impl::ssl_delegate::handle_connected, - boost::network::http::impl::ssl_delegate::shared_from_this(), - asio::placeholders::error, - handler)); -} - -void boost::network::http::impl::ssl_delegate::handle_connected(system::error_code const & ec, - function handler) { - if (!ec) { - socket_->async_handshake(asio::ssl::stream_base::client, handler); - } else { - handler(ec); - } -} - -void boost::network::http::impl::ssl_delegate::write( - asio::streambuf & command_streambuf, - function handler) { - asio::async_write(*socket_, command_streambuf, handler); -} - -void boost::network::http::impl::ssl_delegate::read_some( - asio::mutable_buffers_1 const & read_buffer, - function handler) { - socket_->async_read_some(read_buffer, handler); -} - -boost::network::http::impl::ssl_delegate::~ssl_delegate() {} - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/sync_normal.hpp b/boost/network/protocol/http/client/connection/sync_normal.hpp deleted file mode 100644 index 18add4b4d..000000000 --- a/boost/network/protocol/http/client/connection/sync_normal.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct sync_connection_base_impl; - - template - struct sync_connection_base; - - template - struct http_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename string::type string_type; - typedef function resolver_function_type; - typedef sync_connection_base_impl connection_base; - - http_sync_connection(resolver_type & resolver, resolver_function_type resolve) - : connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.get_io_service()) { } - - void init_socket(string_type const & hostname, string_type const & port) { - connection_base::init_socket(socket_, resolver_, hostname, port, resolve_); - } - - void send_request_impl(string_type const & method, basic_request const & request_) { - boost::asio::streambuf request_buffer; - linearize(request_, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&request_buffer)); - connection_base::send_request_impl(socket_, method, request_buffer); - } - - void read_status(basic_response & response_, boost::asio::streambuf & response_buffer) { - connection_base::read_status(socket_, response_, response_buffer); - } - - void read_headers(basic_response & response, boost::asio::streambuf & response_buffer) { - connection_base::read_headers(socket_, response, response_buffer); - } - - void read_body(basic_response & response_, boost::asio::streambuf & response_buffer) { - connection_base::read_body(socket_, response_, response_buffer); - typename headers_range >::type connection_range = - headers(response_)["Connection"]; - if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { - close_socket(); - } else if (version_major == 1 && version_minor == 0) { - close_socket(); - } - } - - bool is_open() { return socket_.is_open(); } - - void close_socket() { - if (!is_open()) return; - boost::system::error_code ignored; - socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); - if (ignored) return; - socket_.close(ignored); - } - - private: - - resolver_type & resolver_; - resolver_function_type resolve_; - boost::asio::ip::tcp::socket socket_; - - }; - -} // namespace impl - -} // nmaespace http - -} // namespace network - -} // nmaespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100 diff --git a/boost/network/protocol/http/client/connection/sync_ssl.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp deleted file mode 100644 index ce13a78c3..000000000 --- a/boost/network/protocol/http/client/connection/sync_ssl.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct sync_connection_base_impl; - - template - struct sync_connection_base; - - template - struct https_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename string::type string_type; - typedef function resolver_function_type; - typedef sync_connection_base_impl connection_base; - - // FIXME make the certificate filename and verify path parameters be optional ranges - https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional const & certificate_filename = optional(), optional const & verify_path = optional()) - : connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.get_io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.get_io_service(), context_) { - if (certificate_filename || verify_path) { - context_.set_verify_mode(boost::asio::ssl::context::verify_peer); - // FIXME make the certificate filename and verify path parameters be optional ranges - if (certificate_filename) context_.load_verify_file(*certificate_filename); - if (verify_path) context_.add_verify_path(*verify_path); - } else { - context_.set_verify_mode(boost::asio::ssl::context::verify_none); - } - } - - void init_socket(string_type const & hostname, string_type const & port) { - connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_); - socket_.handshake(boost::asio::ssl::stream_base::client); - } - - void send_request_impl(string_type const & method, basic_request const & request_) { - boost::asio::streambuf request_buffer; - linearize(request_, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&request_buffer)); - connection_base::send_request_impl(socket_, method, request_buffer); - } - - void read_status(basic_response & response_, boost::asio::streambuf & response_buffer) { - connection_base::read_status(socket_, response_, response_buffer); - } - - void read_headers(basic_response & response_, boost::asio::streambuf & response_buffer) { - connection_base::read_headers(socket_, response_, response_buffer); - } - - void read_body(basic_response & response_, boost::asio::streambuf & response_buffer) { - connection_base::read_body(socket_, response_, response_buffer); - typename headers_range >::type connection_range = - headers(response_)["Connection"]; - if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { - close_socket(); - } else if (version_major == 1 && version_minor == 0) { - close_socket(); - } - } - - bool is_open() { - return socket_.lowest_layer().is_open(); - } - - void close_socket() { - boost::system::error_code ignored; - socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); - if (ignored) return; - socket_.lowest_layer().close(ignored); - } - - ~https_sync_connection() { - close_socket(); - } - - private: - resolver_type & resolver_; - resolver_function_type resolve_; - boost::asio::ssl::context context_; - boost::asio::ssl::stream socket_; - - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp deleted file mode 100644 index 639fb7277..000000000 --- a/boost/network/protocol/http/client/facade.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - struct basic_response; - - template - struct basic_client_facade { - - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef basic_client_impl pimpl_type; - typedef function const &,system::error_code const &)> body_callback_function_type; - - template - basic_client_facade(ArgPack const & args) - { - init_pimpl(args, - typename mpl::if_< - is_same< - typename parameter::value_type::type, - void - >, - no_io_service, - has_io_service - >::type()); - } - - BOOST_PARAMETER_MEMBER_FUNCTION((response const), head, tag, (required (request,(request const &)))) { - return pimpl->request_skeleton(request, "HEAD", false, body_callback_function_type()); - } - - BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, - (required - (request,(request const &)) - ) - (optional - (body_handler,(body_callback_function_type),body_callback_function_type()) - ) - ) { - return pimpl->request_skeleton(request, "GET", true, body_handler); - } - - BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag, - (required - (request,(request)) // yes sir, we make a copy of the original request. - ) - (optional - (body,(string_type const &),string_type()) - (content_type,(string_type const &),string_type()) - (body_handler,(body_callback_function_type),body_callback_function_type()) - ) - ) { - if (body != string_type()) { - request << remove_header("Content-Length") - << header("Content-Length", boost::lexical_cast(body.size())) - << boost::network::body(body); - } - typename headers_range >::type content_type_headers = - headers(request)["Content-Type"]; - if (content_type != string_type()) { - if (!boost::empty(content_type_headers)) - request << remove_header("Content-Type"); - request << header("Content-Type", content_type); - } else { - if (boost::empty(content_type_headers)) { - typedef typename char_::type char_type; - static char_type content_type[] = "x-application/octet-stream"; - request << header("Content-Type", content_type); - } - } - return pimpl->request_skeleton(request, "POST", true, body_handler); - } - - BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag, - (required - (request,(request)) // yes sir, we make a copy of the original request. - ) - (optional - (body,(string_type const &),string_type()) - (content_type,(string_type const &),string_type()) - (body_handler,(body_callback_function_type),body_callback_function_type()) - ) - ) { - if (body != string_type()) { - request << remove_header("Content-Length") - << header("Content-Length", boost::lexical_cast(body.size())) - << boost::network::body(body); - } - typename headers_range >::type content_type_headers = - headers(request)["Content-Type"]; - if (content_type != string_type()) { - if (!boost::empty(content_type_headers)) - request << remove_header("Content-Type"); - request << header("Content-Type", content_type); - } else { - if (boost::empty(content_type_headers)) { - typedef typename char_::type char_type; - static char_type content_type[] = "x-application/octet-stream"; - request << header("Content-Type", content_type); - } - } - return pimpl->request_skeleton(request, "PUT", true, body_handler); - } - - BOOST_PARAMETER_MEMBER_FUNCTION((response const), delete_, tag, - (required - (request,(request const &)) - ) - (optional - (body_handler,(body_callback_function_type),body_callback_function_type()) - ) - ) { - return pimpl->request_skeleton(request, "DELETE", true, body_handler); - } - - void clear_resolved_cache() { - pimpl->clear_resolved_cache(); - } - - protected: - - struct no_io_service {}; - struct has_io_service {}; - - boost::shared_ptr pimpl; - - template - void init_pimpl(ArgPack const & args, no_io_service) { - pimpl.reset( - new pimpl_type( - args[_cache_resolved|false] - , args[_follow_redirects|false] - , optional(args[_openssl_certificate|optional()]) - , optional(args[_openssl_verify_path|optional()]) - ) - ); - } - - template - void init_pimpl(ArgPack const & args, has_io_service) { - pimpl.reset( - new pimpl_type( - args[_cache_resolved|false] - , args[_follow_redirects|false] - , args[_io_service] - , optional(args[_openssl_certificate|optional()]) - , optional(args[_openssl_verify_path|optional()]) - ) - ); - } - - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 diff --git a/boost/network/protocol/http/client/macros.hpp b/boost/network/protocol/http/client/macros.hpp deleted file mode 100644 index f4fad800c..000000000 --- a/boost/network/protocol/http/client/macros.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 - -// Copyright 2011 Dean Michael Berris . -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -#ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK -#define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, error_name) \ - void function_name (boost::iterator_range const & range_name, boost::system::error_code const & error_name) -#endif - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ - diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp deleted file mode 100644 index dade4e756..000000000 --- a/boost/network/protocol/http/client/parameters.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - BOOST_PARAMETER_NAME(follow_redirects) - BOOST_PARAMETER_NAME(cache_resolved) - BOOST_PARAMETER_NAME(openssl_certificate) - BOOST_PARAMETER_NAME(openssl_verify_path) - - BOOST_PARAMETER_NAME(request) - BOOST_PARAMETER_NAME(body) - BOOST_PARAMETER_NAME(content_type) - BOOST_PARAMETER_NAME(body_handler) - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 */ diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp deleted file mode 100644 index 55df10f57..000000000 --- a/boost/network/protocol/http/client/pimpl.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_client_impl; - - namespace impl { - - template - struct async_client; - - template - struct sync_client; - - - template - struct client_base { - typedef unsupported_tag type; - }; - - template - struct client_base >::type> { - typedef async_client type; - }; - - template - struct client_base >::type> { - typedef sync_client type; - }; - - } // namespace impl - - template - struct basic_client; - - template - struct basic_client_impl - : impl::client_base::type - { - BOOST_STATIC_ASSERT(( - mpl::not_< - mpl::and_< - is_async, - is_sync - > - >::value - )); - - typedef typename impl::client_base::type base_type; - typedef typename base_type::string_type string_type; - - basic_client_impl(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) - : base_type(cache_resolved, follow_redirect, certificate_filename, verify_path) - {} - - basic_client_impl(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) - : base_type(cache_resolved, follow_redirect, service, certificate_filename, verify_path) - {} - - ~basic_client_impl() - {} - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 diff --git a/boost/network/protocol/http/client/sync_impl.hpp b/boost/network/protocol/http/client/sync_impl.hpp deleted file mode 100644 index b81c2198a..000000000 --- a/boost/network/protocol/http/client/sync_impl.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 -#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_client_impl; - - namespace impl { - template - struct sync_client : - connection_policy::type - { - typedef typename string::type string_type; - typedef typename connection_policy::type connection_base; - typedef typename resolver::type resolver_type; - typedef function const &, system::error_code const &)> body_callback_function_type; - friend struct basic_client_impl; - - boost::asio::io_service * service_ptr; - boost::asio::io_service & service_; - resolver_type resolver_; - optional certificate_file, verify_path; - - sync_client(bool cache_resolved, bool follow_redirect - , optional const & certificate_file = optional() - , optional const & verify_path = optional() - ) - : connection_base(cache_resolved, follow_redirect), - service_ptr(new boost::asio::io_service), - service_(*service_ptr), - resolver_(service_) - , certificate_file(certificate_file) - , verify_path(verify_path) - {} - - sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service - , optional const & certificate_file = optional() - , optional const & verify_path = optional() - ) - : connection_base(cache_resolved, follow_redirect), - service_ptr(0), - service_(service), - resolver_(service_) - , certificate_file(certificate_file) - , verify_path(verify_path) - {} - - ~sync_client() { - connection_base::cleanup(); - delete service_ptr; - } - - basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body, body_callback_function_type callback) { - typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); - return connection_->send_request(method, request_, get_body, callback); - } - - }; - - } // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 diff --git a/boost/network/protocol/http/client_fwd.hpp b/boost/network/protocol/http/client_fwd.hpp deleted file mode 100644 index c57ad70cc..000000000 --- a/boost/network/protocol/http/client_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ - -// Copyright Dean Michael Berris 2007-2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP__ -#define __NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP__ - -#include -#include - -namespace boost { namespace network { namespace http { - - //! Forward declaration of basic_client template. - template - class basic_client; - - typedef basic_client client; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP__ - diff --git a/boost/network/protocol/http/errors.hpp b/boost/network/protocol/http/errors.hpp deleted file mode 100644 index 70952e3ec..000000000 --- a/boost/network/protocol/http/errors.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -// Copyright Dean Michael Berris 2007, 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP__ -#define __NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP__ - -#include -#include - -namespace boost { namespace network { namespace http { namespace errors { - - template - struct connection_timeout_exception : - std::runtime_error - { - }; - - typedef connection_timeout_exception<> connection_timeout; - -} // namespace errors - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_PROTOCOL_HTTP_20080516_HPP__ - diff --git a/boost/network/protocol/http/impl/message.ipp b/boost/network/protocol/http/impl/message.ipp deleted file mode 100644 index b2875092d..000000000 --- a/boost/network/protocol/http/impl/message.ipp +++ /dev/null @@ -1,269 +0,0 @@ -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_IPP - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - // static member functions of boost::network::http::message - - template - typename message_impl::string_type const message_impl::url_decode(typename message_impl::string_type const & str) - { - char decode_buf[3]; - typename message_impl::string_type result; - result.reserve(str.size()); - - for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { - switch(str[pos]) { - case '+': - // convert to space character - result += ' '; - break; - case '%': - // decode hexidecimal value - if (pos + 2 < str.size()) { - decode_buf[0] = str[++pos]; - decode_buf[1] = str[++pos]; - decode_buf[2] = '\0'; - result += static_cast( strtol(decode_buf, 0, 16) ); - } else { - // recover from error by not decoding character - result += '%'; - } - break; - default: - // character does not need to be escaped - result += str[pos]; - } - }; - - return result; - } - - template - typename message_impl::string_type const message_impl::url_encode(typename message_impl::string_type const & str) - { - char encode_buf[4]; - typename message_impl::string_type result; - encode_buf[0] = '%'; - result.reserve(str.size()); - - // character selection for this algorithm is based on the following url: - // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm - - for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { - switch(str[pos]) { - default: - if (str[pos] >= 32 && str[pos] < 127) { - // character does not need to be escaped - result += str[pos]; - break; - } - // else pass through to next case - - case '$': case '&': case '+': case ',': case '/': case ':': - case ';': case '=': case '?': case '@': case '"': case '<': - case '>': case '#': case '%': case '{': case '}': case '|': - case '\\': case '^': case '~': case '[': case ']': case '`': - // the character needs to be encoded - sprintf(encode_buf+1, "%02X", str[pos]); - result += encode_buf; - break; - } - }; - - return result; - } - - template - typename message_impl::string_type const message_impl::make_query_string(typename query_container::type const & query_params) - { - typename message_impl::string_type query_string; - for (typename query_container::type::const_iterator i = query_params.begin(); - i != query_params.end(); ++i) - { - if (i != query_params.begin()) - query_string += '&'; - query_string += url_encode(i->first); - query_string += '='; - query_string += url_encode(i->second); - } - return query_string; - } - - template - typename message_impl::string_type const message_impl::make_set_cookie_header(typename message_impl::string_type const & name, - typename message_impl::string_type const & value, - typename message_impl::string_type const & path, - bool const has_max_age, - unsigned long const max_age) - { - typename message_impl::string_type set_cookie_header(name); - set_cookie_header += "=\""; - set_cookie_header += value; - set_cookie_header += "\"; Version=\"1\""; - if (! path.empty()) { - set_cookie_header += "; Path=\""; - set_cookie_header += path; - set_cookie_header += '\"'; - } - if (has_max_age) { - set_cookie_header += "; Max-Age=\""; - set_cookie_header += boost::lexical_cast::string_type>(max_age); - set_cookie_header += '\"'; - } - return set_cookie_header; - } - - template - bool message_impl::base64_decode(const typename message_impl::string_type &input, typename message_impl::string_type &output) - { - static const char nop = -1; - static const char decoding_data[] = { - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop, 62, nop,nop,nop, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,nop,nop, nop,nop,nop,nop, - nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,nop, nop,nop,nop,nop, - nop,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, - nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop - }; - - unsigned int input_length=input.size(); - const char * input_ptr = input.data(); - - // allocate space for output string - output.clear(); - output.reserve(((input_length+2)/3)*4); - - // for each 4-bytes sequence from the input, extract 4 6-bits sequences by droping first two bits - // and regenerate into 3 8-bits sequence - - for (unsigned int i=0; i(input_ptr[i])]; - if(base64code0==nop) // non base64 character - return false; - if(!(++i(input_ptr[i])]; - if(base64code1==nop) // non base64 character - return false; - - output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); - - if(++i(input_ptr[i])]; - if(base64code2==nop) // non base64 character - return false; - - output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f); - } - - if(++i(input_ptr[i])]; - if(base64code3==nop) // non base64 character - return false; - - output += (((base64code2 << 6) & 0xc0) | base64code3 ); - } - - } - - return true; - } - - template - bool message_impl::base64_encode(typename message_impl::string_type const & input, typename message_impl::string_type & output) - { - static const char encoding_data[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - unsigned int input_length=input.size(); - const char * input_ptr = input.data(); - - // allocate space for output string - output.clear(); - output.reserve(((input_length+2)/3)*4); - - // for each 3-bytes sequence from the input, extract 4 6-bits sequences and encode using - // encoding_data lookup table. - // if input do not contains enough chars to complete 3-byte sequence,use pad char '=' - for (unsigned int i=0; i> 2) & 0x3f; // 1-byte 6 bits - output += encoding_data[base64code0]; - base64code1 = (input_ptr[i] << 4 ) & 0x3f; // 1-byte 2 bits + - - if (++i < input_length) { - base64code1 |= (input_ptr[i] >> 4) & 0x0f; // 2-byte 4 bits - output += encoding_data[base64code1]; - base64code2 = (input_ptr[i] << 2) & 0x3f; // 2-byte 4 bits + - - if (++i < input_length) { - base64code2 |= (input_ptr[i] >> 6) & 0x03; // 3-byte 2 bits - base64code3 = input_ptr[i] & 0x3f; // 3-byte 6 bits - output += encoding_data[base64code2]; - output += encoding_data[base64code3]; - } else { - output += encoding_data[base64code2]; - output += '='; - } - } else { - output += encoding_data[base64code1]; - output += '='; - output += '='; - } - } - - return true; - } - - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP diff --git a/boost/network/protocol/http/impl/parser.ipp b/boost/network/protocol/http/impl/parser.ipp deleted file mode 100644 index 893319bb8..000000000 --- a/boost/network/protocol/http/impl/parser.ipp +++ /dev/null @@ -1,782 +0,0 @@ -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP - -#include - -namespace boost { namespace network { namespace http { - - // member functions for class basic_parser - - template - boost::tribool basic_parser::parse_http_headers(basic_message& http_msg) - { - // - // note that boost::tribool may have one of THREE states: - // - // false: encountered an error while parsing HTTP headers - // true: finished successfully parsing the HTTP headers - // indeterminate: parsed bytes, but the HTTP headers are not yet finished - // - const char *read_start_ptr = m_read_ptr; - m_bytes_last_read = 0; - while (m_read_ptr < m_read_end_ptr) { - - switch (m_headers_parse_state) { - case PARSE_METHOD_START: - // we have not yet started parsing the HTTP method string - if (*m_read_ptr != ' ' && *m_read_ptr!='\r' && *m_read_ptr!='\n') { // ignore leading whitespace - if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) - return false; - m_headers_parse_state = PARSE_METHOD; - m_method.erase(); - m_method.push_back(*m_read_ptr); - } - break; - - case PARSE_METHOD: - // we have started parsing the HTTP method string - if (*m_read_ptr == ' ') { - m_resource.erase(); - m_headers_parse_state = PARSE_URI_STEM; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else if (m_method.size() >= ParserTraits::METHOD_MAX) { - return false; - } else { - m_method.push_back(*m_read_ptr); - } - break; - - case PARSE_URI_STEM: - // we have started parsing the URI stem (or resource name) - if (*m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HTTP_VERSION_H; - } else if (*m_read_ptr == '?') { - m_query_string.erase(); - m_headers_parse_state = PARSE_URI_QUERY; - } else if (is_control(*m_read_ptr)) { - return false; - } else if (m_resource.size() >= ParserTraits::RESOURCE_MAX) { - return false; - } else { - m_resource.push_back(*m_read_ptr); - } - break; - - case PARSE_URI_QUERY: - // we have started parsing the URI query string - if (*m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HTTP_VERSION_H; - } else if (is_control(*m_read_ptr)) { - return false; - } else if (m_query_string.size() >= ParserTraits::QUERY_STRING_MAX) { - return false; - } else { - m_query_string.push_back(*m_read_ptr); - } - break; - - case PARSE_HTTP_VERSION_H: - // parsing "HTTP" - if (*m_read_ptr != 'H') return false; - m_headers_parse_state = PARSE_HTTP_VERSION_T_1; - break; - - case PARSE_HTTP_VERSION_T_1: - // parsing "HTTP" - if (*m_read_ptr != 'T') return false; - m_headers_parse_state = PARSE_HTTP_VERSION_T_2; - break; - - case PARSE_HTTP_VERSION_T_2: - // parsing "HTTP" - if (*m_read_ptr != 'T') return false; - m_headers_parse_state = PARSE_HTTP_VERSION_P; - break; - - case PARSE_HTTP_VERSION_P: - // parsing "HTTP" - if (*m_read_ptr != 'P') return false; - m_headers_parse_state = PARSE_HTTP_VERSION_SLASH; - break; - - case PARSE_HTTP_VERSION_SLASH: - // parsing slash after "HTTP" - if (*m_read_ptr != '/') return false; - m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR_START; - break; - - case PARSE_HTTP_VERSION_MAJOR_START: - // parsing the first digit of the major version number - if (!is_digit(*m_read_ptr)) return false; - http_msg.setVersionMajor(*m_read_ptr - '0'); - m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR; - break; - - case PARSE_HTTP_VERSION_MAJOR: - // parsing the major version number (not first digit) - if (*m_read_ptr == '.') { - m_headers_parse_state = PARSE_HTTP_VERSION_MINOR_START; - } else if (is_digit(*m_read_ptr)) { - http_msg.setVersionMajor( (http_msg.getVersionMajor() * 10) - + (*m_read_ptr - '0') ); - } else { - return false; - } - break; - - case PARSE_HTTP_VERSION_MINOR_START: - // parsing the first digit of the minor version number - if (!is_digit(*m_read_ptr)) return false; - http_msg.setVersionMinor(*m_read_ptr - '0'); - m_headers_parse_state = PARSE_HTTP_VERSION_MINOR; - break; - - case PARSE_HTTP_VERSION_MINOR: - // parsing the major version number (not first digit) - if (*m_read_ptr == ' ') { - // should only happen for responses - if (m_is_request) return false; - m_headers_parse_state = PARSE_STATUS_CODE_START; - } else if (*m_read_ptr == '\r') { - // should only happen for requests - if (! m_is_request) return false; - m_headers_parse_state = PARSE_EXPECTING_NEWLINE; - } else if (*m_read_ptr == '\n') { - // should only happen for requests - if (! m_is_request) return false; - m_headers_parse_state = PARSE_EXPECTING_CR; - } else if (is_digit(*m_read_ptr)) { - http_msg.setVersionMinor( (http_msg.getVersionMinor() * 10) - + (*m_read_ptr - '0') ); - } else { - return false; - } - break; - - case PARSE_STATUS_CODE_START: - // parsing the first digit of the response status code - if (!is_digit(*m_read_ptr)) return false; - m_status_code = (*m_read_ptr - '0'); - m_headers_parse_state = PARSE_STATUS_CODE; - break; - - case PARSE_STATUS_CODE: - // parsing the response status code (not first digit) - if (*m_read_ptr == ' ') { - m_status_message.erase(); - m_headers_parse_state = PARSE_STATUS_MESSAGE; - } else if (is_digit(*m_read_ptr)) { - m_status_code = ( (m_status_code * 10) + (*m_read_ptr - '0') ); - } else { - return false; - } - break; - - case PARSE_STATUS_MESSAGE: - // parsing the response status message - if (*m_read_ptr == '\r') { - m_headers_parse_state = PARSE_EXPECTING_NEWLINE; - } else if (*m_read_ptr == '\n') { - m_headers_parse_state = PARSE_EXPECTING_CR; - } else if (is_control(*m_read_ptr)) { - return false; - } else if (m_status_message.size() >= ParserTraits::STATUS_MESSAGE_MAX) { - return false; - } else { - m_status_message.push_back(*m_read_ptr); - } - break; - - case PARSE_EXPECTING_NEWLINE: - // we received a CR; expecting a newline to follow - if (*m_read_ptr == '\n') { - m_headers_parse_state = PARSE_HEADER_START; - } else if (*m_read_ptr == '\r') { - // we received two CR's in a row - // assume CR only is (incorrectly) being used for line termination - // therefore, the message is finished - ++m_read_ptr; - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return true; - } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HEADER_WHITESPACE; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else { - // assume it is the first character for the name of a header - m_header_name.erase(); - m_header_name.push_back(*m_read_ptr); - m_headers_parse_state = PARSE_HEADER_NAME; - } - break; - - case PARSE_EXPECTING_CR: - // we received a newline without a CR - if (*m_read_ptr == '\r') { - m_headers_parse_state = PARSE_HEADER_START; - } else if (*m_read_ptr == '\n') { - // we received two newlines in a row - // assume newline only is (incorrectly) being used for line termination - // therefore, the message is finished - ++m_read_ptr; - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return true; - } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HEADER_WHITESPACE; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else { - // assume it is the first character for the name of a header - m_header_name.erase(); - m_header_name.push_back(*m_read_ptr); - m_headers_parse_state = PARSE_HEADER_NAME; - } - break; - - case PARSE_HEADER_WHITESPACE: - // parsing whitespace before a header name - if (*m_read_ptr == '\r') { - m_headers_parse_state = PARSE_EXPECTING_NEWLINE; - } else if (*m_read_ptr == '\n') { - m_headers_parse_state = PARSE_EXPECTING_CR; - } else if (*m_read_ptr != '\t' && *m_read_ptr != ' ') { - if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) - return false; - // assume it is the first character for the name of a header - m_header_name.erase(); - m_header_name.push_back(*m_read_ptr); - m_headers_parse_state = PARSE_HEADER_NAME; - } - break; - - case PARSE_HEADER_START: - // parsing the start of a new header - if (*m_read_ptr == '\r') { - m_headers_parse_state = PARSE_EXPECTING_FINAL_NEWLINE; - } else if (*m_read_ptr == '\n') { - m_headers_parse_state = PARSE_EXPECTING_FINAL_CR; - } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HEADER_WHITESPACE; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else { - // first character for the name of a header - m_header_name.erase(); - m_header_name.push_back(*m_read_ptr); - m_headers_parse_state = PARSE_HEADER_NAME; - } - break; - - case PARSE_HEADER_NAME: - // parsing the name of a header - if (*m_read_ptr == ':') { - m_header_value.erase(); - m_headers_parse_state = PARSE_SPACE_BEFORE_HEADER_VALUE; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else if (m_header_name.size() >= ParserTraits::HEADER_NAME_MAX) { - return false; - } else { - // character (not first) for the name of a header - m_header_name.push_back(*m_read_ptr); - } - break; - - case PARSE_SPACE_BEFORE_HEADER_VALUE: - // parsing space character before a header's value - if (*m_read_ptr == ' ') { - m_headers_parse_state = PARSE_HEADER_VALUE; - } else if (*m_read_ptr == '\r') { - http_msg.addHeader(m_header_name, m_header_value); - m_headers_parse_state = PARSE_EXPECTING_NEWLINE; - } else if (*m_read_ptr == '\n') { - http_msg.addHeader(m_header_name, m_header_value); - m_headers_parse_state = PARSE_EXPECTING_CR; - } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { - return false; - } else { - // assume it is the first character for the value of a header - m_header_value.push_back(*m_read_ptr); - m_headers_parse_state = PARSE_HEADER_VALUE; - } - break; - - case PARSE_HEADER_VALUE: - // parsing the value of a header - if (*m_read_ptr == '\r') { - http_msg.addHeader(m_header_name, m_header_value); - m_headers_parse_state = PARSE_EXPECTING_NEWLINE; - } else if (*m_read_ptr == '\n') { - http_msg.addHeader(m_header_name, m_header_value); - m_headers_parse_state = PARSE_EXPECTING_CR; - } else if (is_control(*m_read_ptr)) { - return false; - } else if (m_header_value.size() >= ParserTraits::HEADER_VALUE_MAX) { - return false; - } else { - // character (not first) for the value of a header - m_header_value.push_back(*m_read_ptr); - } - break; - - case PARSE_EXPECTING_FINAL_NEWLINE: - if (*m_read_ptr == '\n') ++m_read_ptr; - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return true; - - case PARSE_EXPECTING_FINAL_CR: - if (*m_read_ptr == '\r') ++m_read_ptr; - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return true; - } - - ++m_read_ptr; - } - - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return boost::indeterminate; - } - - template - boost::tribool basic_parser::parse_chunks(types::chunk_cache_t& chunk_buffers) - { - // - // note that boost::tribool may have one of THREE states: - // - // false: encountered an error while parsing message - // true: finished successfully parsing the message - // indeterminate: parsed bytes, but the message is not yet finished - // - const char *read_start_ptr = m_read_ptr; - m_bytes_last_read = 0; - while (m_read_ptr < m_read_end_ptr) { - - switch (m_chunked_content_parse_state) { - case PARSE_CHUNK_SIZE_START: - // we have not yet started parsing the next chunk size - if (is_hex_digit(*m_read_ptr)) { - m_chunk_size_str.erase(); - m_chunk_size_str.push_back(*m_read_ptr); - m_chunked_content_parse_state = PARSE_CHUNK_SIZE; - } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09' || *m_read_ptr == '\x0D' || *m_read_ptr == '\x0A') { - // Ignore leading whitespace. Technically, the standard probably doesn't allow white space here, - // but we'll be flexible, since there's no ambiguity. - break; - } else { - return false; - } - break; - - case PARSE_CHUNK_SIZE: - if (is_hex_digit(*m_read_ptr)) { - m_chunk_size_str.push_back(*m_read_ptr); - } else if (*m_read_ptr == '\x0D') { - m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; - } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { - // Ignore trailing tabs or spaces. Technically, the standard probably doesn't allow this, - // but we'll be flexible, since there's no ambiguity. - m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE; - } else { - return false; - } - break; - - case PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE: - if (*m_read_ptr == '\x0D') { - m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; - } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { - // Ignore trailing tabs or spaces. Technically, the standard probably doesn't allow this, - // but we'll be flexible, since there's no ambiguity. - break; - } else { - return false; - } - break; - - case PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE: - // We received a CR; expecting LF to follow. We can't be flexible here because - // if we see anything other than LF, we can't be certain where the chunk starts. - if (*m_read_ptr == '\x0A') { - m_bytes_read_in_current_chunk = 0; - m_size_of_current_chunk = strtol(m_chunk_size_str.c_str(), 0, 16); - if (m_size_of_current_chunk == 0) { - m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK; - } else { - m_current_chunk.clear(); - m_chunked_content_parse_state = PARSE_CHUNK; - } - } else { - return false; - } - break; - - case PARSE_CHUNK: - if (m_bytes_read_in_current_chunk < m_size_of_current_chunk) { - m_current_chunk.push_back(*m_read_ptr); - m_bytes_read_in_current_chunk++; - } - if (m_bytes_read_in_current_chunk == m_size_of_current_chunk) { - chunk_buffers.push_back(m_current_chunk); - m_current_chunk.clear(); - m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK; - } - break; - - case PARSE_EXPECTING_CR_AFTER_CHUNK: - // we've read exactly m_size_of_current_chunk bytes since starting the current chunk - if (*m_read_ptr == '\x0D') { - m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK; - } else { - return false; - } - break; - - case PARSE_EXPECTING_LF_AFTER_CHUNK: - // we received a CR; expecting LF to follow - if (*m_read_ptr == '\x0A') { - m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; - } else { - return false; - } - break; - - case PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK: - // we've read the final chunk; expecting final CRLF - if (*m_read_ptr == '\x0D') { - m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK; - } else { - return false; - } - break; - - case PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK: - // we received the final CR; expecting LF to follow - if (*m_read_ptr == '\x0A') { - ++m_read_ptr; - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return true; - } else { - return false; - } - } - - ++m_read_ptr; - } - - m_bytes_last_read = (m_read_ptr - read_start_ptr); - m_bytes_total_read += m_bytes_last_read; - return boost::indeterminate; - } - - template - std::size_t basic_parser::consume_content(basic_message& http_msg) - { - // get the payload content length from the HTTP headers - http_msg.updateContentLengthUsingHeader(); - - // read the post content - std::size_t content_bytes_to_read = http_msg.getContentLength(); - char *post_buffer = http_msg.createContentBuffer(); - - if (m_read_ptr < m_read_end_ptr) { - // there are extra bytes left from the last read operation - // copy them into the beginning of the content buffer - const std::size_t bytes_left_in_read_buffer = bytes_available(); - - if (bytes_left_in_read_buffer >= http_msg.getContentLength()) { - // the last read operation included all of the payload content - memcpy(post_buffer, m_read_ptr, http_msg.getContentLength()); - content_bytes_to_read = 0; - m_read_ptr += http_msg.getContentLength(); - } else { - // only some of the post content has been read so far - memcpy(post_buffer, m_read_ptr, bytes_left_in_read_buffer); - content_bytes_to_read -= bytes_left_in_read_buffer; - m_read_ptr = m_read_end_ptr; - } - } - - m_bytes_last_read = (http_msg.getContentLength() - content_bytes_to_read); - m_bytes_total_read += m_bytes_last_read; - return m_bytes_last_read; - } - - template - std::size_t basic_parser::consume_content_as_next_chunk(types::chunk_cache_t& chunk_buffers) - { - if (bytes_available() == 0) { - m_bytes_last_read = 0; - } else { - std::vector next_chunk; - while (m_read_ptr < m_read_end_ptr) { - next_chunk.push_back(*m_read_ptr); - ++m_read_ptr; - } - chunk_buffers.push_back(next_chunk); - m_bytes_last_read = next_chunk.size(); - m_bytes_total_read += m_bytes_last_read; - } - return m_bytes_last_read; - } - - template - void basic_parser::finish(basic_request& http_request) - { - http_request.setIsValid(true); - http_request.setMethod(m_method); - http_request.setResource(m_resource); - http_request.setQueryString(m_query_string); - - // parse query pairs from the URI query string - if (! m_query_string.empty()) { - if (! parseURLEncoded(http_request.getQueryParams(), - m_query_string.c_str(), - m_query_string.size())) - } - - // parse query pairs from post content (x-www-form-urlencoded) - if (http_request.getHeader(types::HEADER_CONTENT_TYPE) == - types::CONTENT_TYPE_URLENCODED) - { - if (! parseURLEncoded(http_request.getQueryParams(), - http_request.getContent(), - http_request.getContentLength())) - } - - // parse "Cookie" headers - std::pair - cookie_pair = http_request.getHeaders().equal_range(types::HEADER_COOKIE); - for (types::headers::const_iterator cookie_iterator = cookie_pair.first; - cookie_iterator != http_request.getHeaders().end() - && cookie_iterator != cookie_pair.second; ++cookie_iterator) - { - if (! parseCookieHeader(http_request.getCookieParams(), - cookie_iterator->second) ) - } - } - - template - void basic_parser::finish(basic_response& http_response) - { - http_response.setIsValid(true); - http_response.setStatusCode(m_status_code); - http_response.setStatusMessage(m_status_message); - } - - template - inline void basic_parser::reset(void) - { - m_headers_parse_state = (m_is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H); - m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; - m_status_code = 0; - m_status_message.erase(); - m_method.erase(); - m_resource.erase(); - m_query_string.erase(); - m_current_chunk.clear(); - m_bytes_last_read = m_bytes_total_read = 0; - } - - template - static bool basic_parser::parse_url_encoded(types::query_params& params, - const char *ptr, const std::size_t len) - { - // used to track whether we are parsing the name or value - enum query_parse_state_t { - QUERY_PARSE_NAME, QUERY_PARSE_VALUE - } parse_state = QUERY_PARSE_NAME; - - // misc other variables used for parsing - const char * const end = ptr + len; - string_type query_name; - string_type query_value; - - // iterate through each encoded character - while (ptr < end) { - switch (parse_state) { - - case QUERY_PARSE_NAME: - // parsing query name - if (*ptr == '=') { - // end of name found - if (query_name.empty()) return false; - parse_state = QUERY_PARSE_VALUE; - } else if (*ptr == '&') { - // value is empty (OK) - if (query_name.empty()) return false; - params.insert( std::make_pair(query_name, query_value) ); - query_name.erase(); - } else if (is_control(*ptr) || query_name.size() >= ParserTraits::QUERY_NAME_MAX) { - // control character detected, or max sized exceeded - return false; - } else { - // character is part of the name - query_name.push_back(*ptr); - } - break; - - case QUERY_PARSE_VALUE: - // parsing query value - if (*ptr == '&') { - // end of value found (OK if empty) - params.insert( std::make_pair(query_name, query_value) ); - query_name.erase(); - query_value.erase(); - parse_state = QUERY_PARSE_NAME; - } else if (is_control(*ptr) || query_value.size() >= ParserTraits::QUERY_VALUE_MAX) { - // control character detected, or max sized exceeded - return false; - } else { - // character is part of the value - query_value.push_back(*ptr); - } - break; - } - - ++ptr; - } - - // handle last pair in string - if (! query_name.empty()) - params.insert( std::make_pair(query_name, query_value) ); - - return true; - } - - template - static bool basic_parser::parse_cookie_header(types::cookie_params& params, - const string_type& cookie_header) - { - // BASED ON RFC 2109 - // - // The current implementation ignores cookie attributes which begin with '$' - // (i.e. $Path=/, $Domain=, etc.) - - // used to track what we are parsing - enum cookie_parse_state_t { - COOKIE_PARSE_NAME, COOKIE_PARSE_VALUE, COOKIE_PARSE_IGNORE - } parse_state = COOKIE_PARSE_NAME; - - // misc other variables used for parsing - string_type cookie_name; - string_type cookie_value; - char value_quote_character = '\0'; - - // iterate through each character - for (string_type::const_iterator string_iterator = cookie_header.begin(); - string_iterator != cookie_header.end(); ++string_iterator) - { - switch (parse_state) { - - case COOKIE_PARSE_NAME: - // parsing cookie name - if (*string_iterator == '=') { - // end of name found - if (cookie_name.empty()) return false; - value_quote_character = '\0'; - parse_state = COOKIE_PARSE_VALUE; - } else if (*string_iterator == ';' || *string_iterator == ',') { - // ignore empty cookie names since this may occur naturally - // when quoted values are encountered - if (! cookie_name.empty()) { - // value is empty (OK) - if (cookie_name[0] != '$') - params.insert( std::make_pair(cookie_name, cookie_value) ); - cookie_name.erase(); - } - } else if (*string_iterator != ' ') { // ignore whitespace - // check if control character detected, or max sized exceeded - if (is_control(*string_iterator) || cookie_name.size() >= ParserTraits::COOKIE_NAME_MAX) - return false; - // character is part of the name - // cookie names are case insensitive -> convert to lowercase - cookie_name.push_back( tolower(*string_iterator) ); - } - break; - - case COOKIE_PARSE_VALUE: - // parsing cookie value - if (value_quote_character == '\0') { - // value is not (yet) quoted - if (*string_iterator == ';' || *string_iterator == ',') { - // end of value found (OK if empty) - if (cookie_name[0] != '$') - params.insert( std::make_pair(cookie_name, cookie_value) ); - cookie_name.erase(); - cookie_value.erase(); - parse_state = COOKIE_PARSE_NAME; - } else if (*string_iterator == '\'' || *string_iterator == '"') { - if (cookie_value.empty()) { - // begin quoted value - value_quote_character = *string_iterator; - } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { - // max size exceeded - return false; - } else { - // assume character is part of the (unquoted) value - cookie_value.push_back(*string_iterator); - } - } else if (*string_iterator != ' ') { // ignore unquoted whitespace - // check if control character detected, or max sized exceeded - if (is_control(*string_iterator) || cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) - return false; - // character is part of the (unquoted) value - cookie_value.push_back(*string_iterator); - } - } else { - // value is quoted - if (*string_iterator == value_quote_character) { - // end of value found (OK if empty) - if (cookie_name[0] != '$') - params.insert( std::make_pair(cookie_name, cookie_value) ); - cookie_name.erase(); - cookie_value.erase(); - parse_state = COOKIE_PARSE_IGNORE; - } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { - // max size exceeded - return false; - } else { - // character is part of the (quoted) value - cookie_value.push_back(*string_iterator); - } - } - break; - - case COOKIE_PARSE_IGNORE: - // ignore everything until we reach a comma "," or semicolon ";" - if (*string_iterator == ';' || *string_iterator == ',') - parse_state = COOKIE_PARSE_NAME; - break; - } - } - - // handle last cookie in string - if (! cookie_name.empty() && cookie_name[0] != '$') - params.insert( std::make_pair(cookie_name, cookie_value) ); - - return true; - } - -}; // namespace http - -}; // namespace network - -}; // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_IPP diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp deleted file mode 100644 index 5ba92d6c1..000000000 --- a/boost/network/protocol/http/impl/request.hpp +++ /dev/null @@ -1,257 +0,0 @@ - -// Copyright Dean Michael Berris 2007,2009,2010. -// Copyright Michael Dickey 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ -#define __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include - -namespace boost { namespace network { - - /** Specialize the traits for the http_server tag. */ - template <> - struct headers_container : - vector::apply::type> - {}; - - template <> - struct headers_container : - vector::apply::type> - {}; - -namespace http { - - /** request.hpp - * - * This file implements the basic request object required - * by the HTTP client implementation. The basic_request - * object encapsulates a URI which is parsed at runtime. - */ - - template - struct basic_request : public basic_message - { - - mutable boost::network::uri::uri uri_; - typedef basic_message base_type; - - public: - typedef typename sync_only::type tag; - typedef typename string::type string_type; - typedef boost::uint16_t port_type; - - explicit basic_request(string_type const & uri_) - : uri_(uri_) - { } - - explicit basic_request(boost::network::uri::uri const & uri_) - : uri_(uri_) - { } - - void uri(string_type const & new_uri) { - uri_ = new_uri; - } - - void uri(boost::network::uri::uri const & new_uri) { - uri_ = new_uri; - } - - basic_request() - : base_type() - { } - - basic_request(basic_request const & other) - : base_type(other), uri_(other.uri_) - { } - - basic_request & operator=(basic_request rhs) { - rhs.swap(*this); - return *this; - } - - void swap(basic_request & other) { - base_type & base_ref(other); - basic_request & this_ref(*this); - base_ref.swap(this_ref); - boost::swap(other.uri_, this->uri_); - } - - string_type const host() const { - return uri_.host(); - } - - port_type port() const { - boost::optional port = uri::port_us(uri_); - if (!port) - { - typedef constants consts; - return boost::iequals(uri_.scheme(), - string_type(consts::https()))? 443 : 80; - } - return *port; - } - - string_type const path() const { - return uri_.path(); - } - - string_type const query() const { - return uri_.query(); - } - - string_type const anchor() const { - return uri_.fragment(); - } - - string_type const protocol() const { - return uri_.scheme(); - } - - void uri(string_type const & new_uri) const { - uri_ = new_uri; - } - - boost::network::uri::uri const & uri() const { - return uri_; - } - - }; - - /** This is the implementation of a POD request type - * that is specificially used by the HTTP server - * implementation. This fully specializes the - * basic_request template above to be - * primarily and be solely a POD for performance - * reasons. - * - * Reality check: This is not a POD because it contains a non-POD - * member, the headers vector. :( - */ - template - struct not_quite_pod_request_base { - typedef Tag tag; - typedef typename string::type string_type; - typedef typename request_header::type header_type; - typedef typename vector:: - template apply::type - vector_type; - typedef vector_type headers_container_type; - typedef boost::uint16_t port_type; - mutable string_type source; - mutable string_type method; - mutable string_type destination; - mutable boost::uint8_t http_version_major; - mutable boost::uint8_t http_version_minor; - mutable vector_type headers; - mutable string_type body; - - void swap(not_quite_pod_request_base & r) const { - using std::swap; - swap(method, r.method); - swap(source, r.source); - swap(destination, r.destination); - swap(http_version_major, r.http_version_major); - swap(http_version_minor, r.http_version_minor); - swap(headers, r.headers); - swap(body, r.body); - } - }; - - template <> - struct basic_request - : not_quite_pod_request_base - {}; - - template <> - struct basic_request - : not_quite_pod_request_base - {}; - - template - struct ServerRequest; - - BOOST_CONCEPT_ASSERT((ServerRequest >)); - BOOST_CONCEPT_ASSERT((ServerRequest >)); - - template - inline void swap(basic_request & lhs, basic_request & rhs) { - lhs.swap(rhs); - } - -} // namespace http - - namespace http { namespace impl { - - template <> - struct request_headers_wrapper { - basic_request const & request_; - request_headers_wrapper(basic_request const & request_) - : request_(request_) {} - typedef headers_container::type headers_container_type; - operator headers_container_type () { - return request_.headers; - } - }; - - template <> - struct body_wrapper > { - typedef string::type string_type; - basic_request const & request_; - body_wrapper(basic_request const & request_) - : request_(request_) {} - operator string_type () { - return request_.body; - } - }; - - template <> - struct request_headers_wrapper { - basic_request const & request_; - request_headers_wrapper(basic_request const & request_) - : request_(request_) {} - typedef headers_container::type headers_container_type; - operator headers_container_type () { - return request_.headers; - } - }; - - template <> - struct body_wrapper > { - typedef string::type string_type; - basic_request const & request_; - body_wrapper(basic_request const & request_) - : request_(request_) {} - operator string_type () { - return request_.body; - } - }; - - } // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ - diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp deleted file mode 100644 index 2eb669dba..000000000 --- a/boost/network/protocol/http/impl/response.ipp +++ /dev/null @@ -1,334 +0,0 @@ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) -// Copyright (c) 2009 Tarroo, Inc. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Note: This implementation has significantly changed from the original example -// from a plain header file into a header-only implementation using C++ templates -// to reduce the dependence on building an external library. -// - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - /// A reply to be sent to a client. - template <> - struct basic_response { - typedef tags::http_server tag; - typedef response_header::type header_type; - - /// The status of the reply. - enum status_type { - ok = 200, - created = 201, - accepted = 202, - no_content = 204, - multiple_choices = 300, - moved_permanently = 301, - moved_temporarily = 302, - not_modified = 304, - bad_request = 400, - unauthorized = 401, - forbidden = 403, - not_found = 404, - not_supported = 405, - not_acceptable = 406, - internal_server_error = 500, - not_implemented = 501, - bad_gateway = 502, - service_unavailable = 503 - } status; - - /// The headers to be included in the reply. - typedef vector::apply::type headers_vector; - headers_vector headers; - - /// The content to be sent in the reply. - typedef string::type string_type; - string_type content; - - /// Convert the reply into a vector of buffers. The buffers do not own the - /// underlying memory blocks, therefore the reply object must remain valid and - /// not be changed until the write operation has completed. - std::vector to_buffers() { - using boost::asio::const_buffer; - using boost::asio::buffer; - static const char name_value_separator[] = { ':', ' ' }; - static const char crlf[] = { '\r', '\n' }; - std::vector buffers; - buffers.push_back(to_buffer(status)); - for (std::size_t i = 0; i < headers.size(); ++i) { - header_type & h = headers[i]; - buffers.push_back(buffer(h.name)); - buffers.push_back(buffer(name_value_separator)); - buffers.push_back(buffer(h.value)); - buffers.push_back(buffer(crlf)); - } - buffers.push_back(buffer(crlf)); - buffers.push_back(buffer(content)); - return buffers; - } - - /// Get a stock reply. - static basic_response stock_reply(status_type status) { - return stock_reply(status, to_string(status)); - } - - /// Get a stock reply with custom plain text data. - static basic_response stock_reply(status_type status, string_type content) { - using boost::lexical_cast; - basic_response rep; - rep.status = status; - rep.content = content; - rep.headers.resize(2); - rep.headers[0].name = "Content-Length"; - rep.headers[0].value = lexical_cast(rep.content.size()); - rep.headers[1].name = "Content-Type"; - rep.headers[1].value = "text/html"; - return rep; - } - - /// Swap response objects - void swap(basic_response &r) { - using std::swap; - swap(headers, r.headers); - swap(content, r.content); - } - - private: - - static string_type to_string(status_type status) { - static const char ok[] = ""; - static const char created[] = - "" - "Created" - "

201 Created

" - ""; - static const char accepted[] = - "" - "Accepted" - "

202 Accepted

" - ""; - static const char no_content[] = - "" - "No Content" - "

204 Content

" - ""; - static const char multiple_choices[] = - "" - "Multiple Choices" - "

300 Multiple Choices

" - ""; - static const char moved_permanently[] = - "" - "Moved Permanently" - "

301 Moved Permanently

" - ""; - static const char moved_temporarily[] = - "" - "Moved Temporarily" - "

302 Moved Temporarily

" - ""; - static const char not_modified[] = - "" - "Not Modified" - "

304 Not Modified

" - ""; - static const char bad_request[] = - "" - "Bad Request" - "

400 Bad Request

" - ""; - static const char unauthorized[] = - "" - "Unauthorized" - "

401 Unauthorized

" - ""; - static const char forbidden[] = - "" - "Forbidden" - "

403 Forbidden

" - ""; - static const char not_found[] = - "" - "Not Found" - "

404 Not Found

" - ""; - static const char not_supported[] = - "" - "Method Not Supported" - "

Method Not Supported

" - ""; - static const char not_acceptable[] = - "" - "Request Not Acceptable" - "

Request Not Acceptable

" - ""; - static const char internal_server_error[] = - "" - "Internal Server Error" - "

500 Internal Server Error

" - ""; - static const char not_implemented[] = - "" - "Not Implemented" - "

501 Not Implemented

" - ""; - static const char bad_gateway[] = - "" - "Bad Gateway" - "

502 Bad Gateway

" - ""; - static const char service_unavailable[] = - "" - "Service Unavailable" - "

503 Service Unavailable

" - ""; - - switch (status) - { - case basic_response::ok: - return ok; - case basic_response::created: - return created; - case basic_response::accepted: - return accepted; - case basic_response::no_content: - return no_content; - case basic_response::multiple_choices: - return multiple_choices; - case basic_response::moved_permanently: - return moved_permanently; - case basic_response::moved_temporarily: - return moved_temporarily; - case basic_response::not_modified: - return not_modified; - case basic_response::bad_request: - return bad_request; - case basic_response::unauthorized: - return unauthorized; - case basic_response::forbidden: - return forbidden; - case basic_response::not_found: - return not_found; - case basic_response::not_supported: - return not_supported; - case basic_response::not_acceptable: - return not_acceptable; - case basic_response::internal_server_error: - return internal_server_error; - case basic_response::not_implemented: - return not_implemented; - case basic_response::bad_gateway: - return bad_gateway; - case basic_response::service_unavailable: - return service_unavailable; - default: - return internal_server_error; - } - } - - boost::asio::const_buffer to_buffer(status_type status) { - using boost::asio::buffer; - static const string_type ok = - "HTTP/1.0 200 OK\r\n"; - static const string_type created = - "HTTP/1.0 201 Created\r\n"; - static const string_type accepted = - "HTTP/1.0 202 Accepted\r\n"; - static const string_type no_content = - "HTTP/1.0 204 No Content\r\n"; - static const string_type multiple_choices = - "HTTP/1.0 300 Multiple Choices\r\n"; - static const string_type moved_permanently = - "HTTP/1.0 301 Moved Permanently\r\n"; - static const string_type moved_temporarily = - "HTTP/1.0 302 Moved Temporarily\r\n"; - static const string_type not_modified = - "HTTP/1.0 304 Not Modified\r\n"; - static const string_type bad_request = - "HTTP/1.0 400 Bad Request\r\n"; - static const string_type unauthorized = - "HTTP/1.0 401 Unauthorized\r\n"; - static const string_type forbidden = - "HTTP/1.0 403 Forbidden\r\n"; - static const string_type not_found = - "HTTP/1.0 404 Not Found\r\n"; - static const string_type not_supported = - "HTTP/1.0 405 Method Not Supported\r\n"; - static const string_type not_acceptable = - "HTTP/1.0 406 Method Not Acceptable\r\n"; - static const string_type internal_server_error = - "HTTP/1.0 500 Internal Server Error\r\n"; - static const string_type not_implemented = - "HTTP/1.0 501 Not Implemented\r\n"; - static const string_type bad_gateway = - "HTTP/1.0 502 Bad Gateway\r\n"; - static const string_type service_unavailable = - "HTTP/1.0 503 Service Unavailable\r\n"; - - switch (status) { - case basic_response::ok: - return buffer(ok); - case basic_response::created: - return buffer(created); - case basic_response::accepted: - return buffer(accepted); - case basic_response::no_content: - return buffer(no_content); - case basic_response::multiple_choices: - return buffer(multiple_choices); - case basic_response::moved_permanently: - return buffer(moved_permanently); - case basic_response::moved_temporarily: - return buffer(moved_temporarily); - case basic_response::not_modified: - return buffer(not_modified); - case basic_response::bad_request: - return buffer(bad_request); - case basic_response::unauthorized: - return buffer(unauthorized); - case basic_response::forbidden: - return buffer(forbidden); - case basic_response::not_found: - return buffer(not_found); - case basic_response::not_supported: - return buffer(not_supported); - case basic_response::not_acceptable: - return buffer(not_acceptable); - case basic_response::internal_server_error: - return buffer(internal_server_error); - case basic_response::not_implemented: - return buffer(not_implemented); - case basic_response::bad_gateway: - return buffer(bad_gateway); - case basic_response::service_unavailable: - return buffer(service_unavailable); - default: - return buffer(internal_server_error); - } - } - - }; - - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP - diff --git a/boost/network/protocol/http/message.hpp b/boost/network/protocol/http/message.hpp deleted file mode 100644 index 7e674143d..000000000 --- a/boost/network/protocol/http/message.hpp +++ /dev/null @@ -1,147 +0,0 @@ -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Some changes Copyright (c) Dean Michael Berris 2008 - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - /// base class for HTTP messages (requests and responses) - template - struct message_impl : public basic_message { - - typedef typename string::type string_type; - - /// escapes URL-encoded strings (a%20value+with%20spaces) - static string_type const url_decode(string_type const & str); - - /// encodes strings so that they are safe for URLs (with%20spaces) - static string_type const url_encode(string_type const & str); - - /// builds an HTTP query string from a collection of query parameters - static string_type const make_query_string(typename query_container::type const & query_params); - - /** - * creates a "Set-Cookie" header - * - * @param name the name of the cookie - * @param value the value of the cookie - * @param path the path of the cookie - * @param has_max_age true if the max_age value should be set - * @param max_age the life of the cookie, in seconds (0 = discard) - * - * @return the new "Set-Cookie" header - */ - static string_type const make_set_cookie_header(string_type const & name, - string_type const & value, - string_type const & path, - bool const has_max_age = false, - unsigned long const max_age = 0); - - /** decodes base64-encoded strings - * - * @param input base64 encoded string - * @param output decoded string ( may include non-text chars) - * @return true if successful, false if input string contains non-base64 symbols - */ - static bool base64_decode(string_type const &input, string_type & output); - - /** encodes strings using base64 - * - * @param input arbitrary string ( may include non-text chars) - * @param output base64 encoded string - * @return true if successful - */ - static bool base64_encode(string_type const &input, string_type & output); - - protected: - mutable string_type version_; - mutable boost::uint16_t status_; - mutable string_type status_message_; - - private: - typedef basic_message base_type; - - public: - - message_impl() - : base_type(), version_(), status_(0u), status_message_() - {} - - message_impl(message_impl const & other) - : base_type(other), version_(other.version_), status_(other.status_), status_message_(other.status_message_) - {} - - void version(string_type const & version) const { - version_ = version; - } - - string_type const version() const { - return version_; - } - - void status(boost::uint16_t status) const { - status_ = status; - } - - boost::uint16_t status() const { - return status_; - } - - void status_message(string_type const & status_message) const { - status_message_ = status_message; - } - - string_type const status_message() const { - return status_message_; - } - - message_impl & operator=(message_impl rhs) { - rhs.swap(*this); - return *this; - } - - void swap(message_impl & other) { - base_type & base_ref(other), - & this_ref(*this); - std::swap(this_ref, base_ref); - std::swap(status_, other.status_); - std::swap(status_message_, other.status_message_); - std::swap(version_, other.version_); - } - - }; - - template - inline void swap(message_impl & lhs, message_impl & rhs) { - lhs.swap(rhs); - } - - typedef message_impl message; - -} // namespace http - -} // namespace network - -} // namespace boost - -// import implementation file -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp deleted file mode 100644 index 39b16fd27..000000000 --- a/boost/network/protocol/http/message/async_message.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -//FIXME move this out to a trait -#include -#include -#include - -namespace boost { namespace network { namespace http { - - namespace impl { - - template - struct ready_wrapper; - - } /* impl */ - - template - struct async_message { - - typedef typename string::type string_type; - typedef typename headers_container::type headers_container_type; - typedef typename headers_container_type::value_type header_type; - - async_message() - : status_message_(), - version_(), - source_(), - destination_(), - status_(), - headers_(), - body_() - {} - - async_message(async_message const & other) - : status_message_(other.status_message_), - version_(other.version_), - source_(other.source_), - destination_(other.destination_), - status_(other.status_), - headers_(other.headers_), - body_(other.body_) - {} - - string_type const status_message() const { - return status_message_.get(); - } - - void status_message(boost::shared_future const & future) const { - status_message_ = future; - } - - string_type const version() const { - return version_.get(); - } - - void version(boost::shared_future const & future) const { - version_ = future; - } - - boost::uint16_t status() const { - return status_.get(); - } - - void status(boost::shared_future const & future) const { - status_ = future; - } - - string_type const source() const { - return source_.get(); - } - - void source(boost::shared_future const & future) const { - source_ = future; - } - - string_type const destination() const { - return destination_.get(); - } - - void destination(boost::shared_future const & future) const { - destination_ = future; - } - - headers_container_type const & headers() const { - if (retrieved_headers_) return *retrieved_headers_; - headers_container_type raw_headers = headers_.get(); - raw_headers.insert(added_headers.begin(), added_headers.end()); - BOOST_FOREACH(string_type const & key, removed_headers) { - raw_headers.erase(key); - } - retrieved_headers_ = raw_headers; - return *retrieved_headers_; - } - - void headers(boost::shared_future const & future) const { - headers_ = future; - } - - void add_header(typename headers_container_type::value_type const & pair_) const { - added_headers.insert(added_headers.end(), pair_); - } - - void remove_header(typename headers_container_type::key_type const & key_) const { - removed_headers.insert(key_); - } - - string_type const body() const { - return body_.get(); - } - - void body(boost::shared_future const & future) const { - body_ = future; - } - - void swap(async_message & other) { - std::swap(status_message_, other.status_message_); - std::swap(status_, other.status_); - std::swap(version_, other.version_); - std::swap(source_, other.source_); - std::swap(destination_, other.destination_); - std::swap(headers_, other.headers_); - std::swap(body_, other.body_); - } - - async_message & operator=(async_message other) { - other.swap(*this); - return *this; - } - - private: - - mutable boost::shared_future status_message_, - version_, source_, destination_; - mutable boost::shared_future status_; - mutable boost::shared_future headers_; - mutable headers_container_type added_headers; - mutable std::set removed_headers; - mutable boost::shared_future body_; - mutable boost::optional retrieved_headers_; - - friend struct boost::network::http::impl::ready_wrapper; - }; - - template - inline void swap(async_message & lhs, async_message & rhs) { - lhs.swap(rhs); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 diff --git a/boost/network/protocol/http/message/directives/major_version.hpp b/boost/network/protocol/http/message/directives/major_version.hpp deleted file mode 100644 index dc83f46ba..000000000 --- a/boost/network/protocol/http/message/directives/major_version.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - struct major_version_directive { - boost::uint8_t major_version; - explicit major_version_directive(boost::uint8_t major_version) - : major_version(major_version) {} - template - void operator()(basic_request & request) const { - request.http_version_major = major_version; - } - }; - - inline major_version_directive - major_version(boost::uint8_t major_version_) { - return major_version_directive(major_version_); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/directives/method.hpp b/boost/network/protocol/http/message/directives/method.hpp deleted file mode 100644 index 2f9aac3a4..000000000 --- a/boost/network/protocol/http/message/directives/method.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - BOOST_NETWORK_STRING_DIRECTIVE(method, method_, - message.method(method_), - message.method=method_); - -} /* http */ - -} /* network */ - -} /* booet */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/directives/minor_version.hpp b/boost/network/protocol/http/message/directives/minor_version.hpp deleted file mode 100644 index 2dbfe0a55..000000000 --- a/boost/network/protocol/http/message/directives/minor_version.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - struct minor_version_directive { - boost::uint8_t minor_version; - explicit minor_version_directive(boost::uint8_t minor_version) - : minor_version(minor_version) {} - template - void operator()(basic_request & request) const { - request.http_version_minor = minor_version; - } - }; - - inline minor_version_directive - minor_version(boost::uint8_t minor_version_) { - return minor_version_directive(minor_version_); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 */ - diff --git a/boost/network/protocol/http/message/directives/status.hpp b/boost/network/protocol/http/message/directives/status.hpp deleted file mode 100644 index 2f3b3916c..000000000 --- a/boost/network/protocol/http/message/directives/status.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - struct status_directive { - - boost::variant< - boost::uint16_t, - boost::shared_future - > status_; - - explicit status_directive(boost::uint16_t status) - : status_(status) {} - - explicit status_directive(boost::shared_future const & status) - : status_(status) {} - - status_directive(status_directive const & other) - : status_(other.status_) {} - - template - struct value - : mpl::if_< - is_async, - boost::shared_future, - boost::uint16_t - > - {}; - - template - struct status_visitor : boost::static_visitor<> { - basic_response const & response; - status_visitor(basic_response const & response) - : response(response) {} - - void operator()(typename value::type const & status_) const { - response.status(status_); - } - - template - void operator()(T const &) const { - // FIXME fail here! - } - }; - - template basic_response const & operator() (basic_response const & response) const { - apply_visitor(status_visitor(response), status_); - return response; - } - - }; - - template - inline status_directive const status(T const & status_) { - return status_directive(status_); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 diff --git a/boost/network/protocol/http/message/directives/status_message.hpp b/boost/network/protocol/http/message/directives/status_message.hpp deleted file mode 100644 index 93463990b..000000000 --- a/boost/network/protocol/http/message/directives/status_message.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - BOOST_NETWORK_STRING_DIRECTIVE(status_message, status_message_, - message.status_message(status_message_), - message.status_message=status_message_); - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 diff --git a/boost/network/protocol/http/message/directives/uri.hpp b/boost/network/protocol/http/message/directives/uri.hpp deleted file mode 100644 index f5fe4a7d1..000000000 --- a/boost/network/protocol/http/message/directives/uri.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - BOOST_NETWORK_STRING_DIRECTIVE(uri, uri_, message.uri(uri_), message.uri=uri_); - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 diff --git a/boost/network/protocol/http/message/directives/version.hpp b/boost/network/protocol/http/message/directives/version.hpp deleted file mode 100644 index f3eedf0ef..000000000 --- a/boost/network/protocol/http/message/directives/version.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - BOOST_NETWORK_STRING_DIRECTIVE(version, version_, message.version(version_), message.version=version_); - -} // namespace http - -} // namespace network - -} // namespace boost - - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 diff --git a/boost/network/protocol/http/message/header.hpp b/boost/network/protocol/http/message/header.hpp deleted file mode 100644 index 22de2a728..000000000 --- a/boost/network/protocol/http/message/header.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// header.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009,2010 Dean Michael Berris (mikhailberis@gmail.com) -// Copyright (c) 2009 Tarroo, Inc. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 - -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct unsupported_tag; - - struct request_header_narrow { - typedef std::string string_type; - std::string name, value; - }; - - struct request_header_wide { - typedef std::wstring string_type; - std::wstring name, value; - }; - - template - struct request_header - : mpl::if_< - is_default_string, - request_header_narrow, - typename mpl::if_< - is_default_wstring, - request_header_wide, - unsupported_tag - >::type - > - {}; - - inline void swap(request_header_narrow & l, request_header_narrow & r) { - swap(l.name, r.name); - swap(l.value, r.value); - } - - inline void swap(request_header_wide & l, request_header_wide & r) { - swap(l.name, r.name); - swap(l.value, r.value); - } - - struct response_header_narrow { - typedef std::string string_type; - std::string name, value; - }; - - struct response_header_wide { - typedef std::wstring string_type; - std::wstring name, value; - }; - - template - struct response_header - : mpl::if_< - is_default_string, - response_header_narrow, - typename mpl::if_< - is_default_wstring, - response_header_wide, - unsupported_tag - >::type - > - {}; - - inline void swap(response_header_narrow & l, response_header_narrow & r) { - std::swap(l.name, r.name); - std::swap(l.value, r.value); - } - - inline void swap(response_header_wide & l, response_header_wide & r) { - std::swap(l.name, r.name); - std::swap(l.value, r.value); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -BOOST_FUSION_ADAPT_STRUCT( - boost::network::http::request_header_narrow, - (std::string, name) - (std::string, value) - ) - -BOOST_FUSION_ADAPT_STRUCT( - boost::network::http::request_header_wide, - (std::wstring, name) - (std::wstring, value) - ) - -BOOST_FUSION_ADAPT_STRUCT( - boost::network::http::response_header_narrow, - (std::string, name) - (std::string, value) - ) - -BOOST_FUSION_ADAPT_STRUCT( - boost::network::http::response_header_wide, - (std::wstring, name) - (std::wstring, value) - ) - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 diff --git a/boost/network/protocol/http/message/header/name.hpp b/boost/network/protocol/http/message/header/name.hpp deleted file mode 100644 index e7c26d17c..000000000 --- a/boost/network/protocol/http/message/header/name.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - T1 & - name(std::pair const & p) { - return p.first; - } - - inline std::string const & - name(request_header_narrow const & h) { - return h.name; - } - - inline std::wstring const & - name(request_header_wide const &h) { - return h.name; - } - - - inline std::string const & - name(response_header_narrow const & h) { - return h.name; - } - - inline std::wstring const & - name(response_header_wide const &h) { - return h.name; - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 */ diff --git a/boost/network/protocol/http/message/header/value.hpp b/boost/network/protocol/http/message/header/value.hpp deleted file mode 100644 index 3769ec2ab..000000000 --- a/boost/network/protocol/http/message/header/value.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - struct request_header_narrow; - struct request_header_wide; - struct response_header_narrow; - struct response_header_wide; - - template - T1 & value(std::pair const & p) { - return p.second; - } - - inline request_header_narrow::string_type const & - value(request_header_narrow const & h) { - return h.value; - } - - inline request_header_wide::string_type const & - value(request_header_wide const & h) { - return h.value; - } - - inline response_header_narrow::string_type const & - value(response_header_narrow const & h) { - return h.value; - } - - inline response_header_wide::string_type const & - value(response_header_wide const & h) { - return h.value; - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 */ - diff --git a/boost/network/protocol/http/message/header_concept.hpp b/boost/network/protocol/http/message/header_concept.hpp deleted file mode 100644 index 9a14d47fd..000000000 --- a/boost/network/protocol/http/message/header_concept.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct Header - : DefaultConstructible - , Assignable - , CopyConstructible - { - - BOOST_CONCEPT_USAGE(Header) { - typedef typename H::string_type string_type; - string_type name_ = name(header); - string_type value_ = value(header); - H h1, h2; - swap(h1,h2); // ADL Swap! - (void)name_; - (void)value_; - } - - private: - H header; - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 */ diff --git a/boost/network/protocol/http/message/message_base.hpp b/boost/network/protocol/http/message/message_base.hpp deleted file mode 100644 index 885d74dbb..000000000 --- a/boost/network/protocol/http/message/message_base.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct async_message; - - template - struct message_impl; - - template - struct message_base - : mpl::if_< - is_async, - async_message, - message_impl - > - {}; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603 diff --git a/boost/network/protocol/http/message/modifiers/body.hpp b/boost/network/protocol/http/message/modifiers/body.hpp deleted file mode 100644 index d88961dd3..000000000 --- a/boost/network/protocol/http/message/modifiers/body.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - namespace impl { - - template - void body(basic_response & response, T const & value, mpl::false_ const &) { - response << ::boost::network::body(value); - } - - template - void body(basic_response & response, T const & future, mpl::true_ const &) { - response.body(future); - } - - } - - template - inline void - body(basic_response & response, T const & value) { - impl::body(response, value, is_async()); - } - - template - inline void - body_impl(basic_request & request, T const & value, tags::server) { - request.body = value; - } - - template - inline void - body_impl(basic_request & request, T const & value, tags::client) { - request << ::boost::network::body(value); - } - - template - inline void - body(basic_request & request, T const & value) { - body_impl(request, value, typename client_or_server::type()); - } - -} // namespace http - - namespace impl { - - template - inline void body(Message const & message, ValueType const & body_, http::tags::http_server, Async) { - message.body = body_; - } - - } /* impl */ - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_BODY_HPP_20100624 diff --git a/boost/network/protocol/http/message/modifiers/clear_headers.hpp b/boost/network/protocol/http/message/modifiers/clear_headers.hpp deleted file mode 100644 index 33e9f5854..000000000 --- a/boost/network/protocol/http/message/modifiers/clear_headers.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - inline void clear_headers_impl(basic_request & request, tags::pod) { - typedef typename basic_request::headers_container_type headers_container; - headers_container().swap(request.headers); - } - - template - inline void clear_headers_impl(basic_request & request, tags::normal) { - request.headers(typename basic_request::headers_container_type()); - } - - template - inline void clear_headers_impl(basic_request & request, tags::client) { - clear_headers_impl(request, typename pod_or_normal::type()); - } - - template - inline void clear_headers_impl(basic_request & request, tags::server) { - typedef typename basic_request::headers_container_type headers_container; - headers_container().swap(request.headers); - } - - template - inline void clear_headers(basic_request & request) { - clear_headers_impl(request, typename client_or_server::type()); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 */ diff --git a/boost/network/protocol/http/message/modifiers/destination.hpp b/boost/network/protocol/http/message/modifiers/destination.hpp deleted file mode 100644 index f0532abba..000000000 --- a/boost/network/protocol/http/message/modifiers/destination.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - namespace impl { - - template - void destination(basic_response & response, T const & value, mpl::false_ const &) { - response << ::boost::network::destination(value); - } - - template - void destination(basic_response & response, T const & future, mpl::true_ const &) { - response.destination(future); - } - - } - - template - inline void - destination(basic_response & response, T const & value) { - impl::destination(response, value, is_async()); - } - - template - struct ServerRequest; - - template - inline void - destination_impl(basic_request & request, T const & value, tags::server) { - request.destination = value; - } - - template - inline void - destination_impl(basic_request & request, T const & value, tags::pod) { - request.destination = value; - } - - template - inline void - destination_impl(basic_request & request, T const & value, tags::normal) { - request.destination(value); - } - - template - inline void - destination_impl(basic_request & request, T const & value, tags::client) { - destination_impl(request, value, typename pod_or_normal::type()); - } - - template - inline void - destination(basic_request & request, T const & value) { - destination_impl(request, value, typename client_or_server::type()); - } - -} // namespace http - - namespace impl { - - template - inline void destination(Message const & message, ValueType const & destination_, http::tags::http_server, Async) { - message.destination = destination_; - } - - } /* impl */ - -} // namespace network - -} // namespace boost - -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624 diff --git a/boost/network/protocol/http/message/modifiers/headers.hpp b/boost/network/protocol/http/message/modifiers/headers.hpp deleted file mode 100644 index d789a7452..000000000 --- a/boost/network/protocol/http/message/modifiers/headers.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - namespace impl { - - template - void headers(basic_response & response, T const & value, mpl::false_ const &) { - response << headers(value); - } - - template - void headers(basic_response & response, T const & future, mpl::true_ const &) { - response.headers(future); - } - - template - void headers(basic_request & request, T const & value, tags::server const &) { - request.headers = value; - } - - } - - template - inline void - headers(basic_response & response, T const & value) { - impl::headers(response, value, is_async()); - } - - template - inline void - headers(basic_request & request, T const & value) { - impl::headers(request, value, Tag()); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_HEADERS_HPP_20100624 diff --git a/boost/network/protocol/http/message/modifiers/major_version.hpp b/boost/network/protocol/http/message/modifiers/major_version.hpp deleted file mode 100644 index e1510c678..000000000 --- a/boost/network/protocol/http/message/modifiers/major_version.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - inline typename enable_if, void>::type - major_version(basic_request & request, boost::uint8_t major_version_) { - request.http_version_major = major_version_; - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/modifiers/method.hpp b/boost/network/protocol/http/message/modifiers/method.hpp deleted file mode 100644 index 52afe2696..000000000 --- a/boost/network/protocol/http/message/modifiers/method.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - inline typename enable_if, void>::type - method(basic_request & request, typename string::type const & method_) { - request.method = method_; - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 */ diff --git a/boost/network/protocol/http/message/modifiers/minor_version.hpp b/boost/network/protocol/http/message/modifiers/minor_version.hpp deleted file mode 100644 index e70c32a6d..000000000 --- a/boost/network/protocol/http/message/modifiers/minor_version.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - inline typename enable_if, void>::type - minor_version(basic_request & request, boost::uint8_t minor_version_) { - request.http_version_minor = minor_version_; - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 */ - diff --git a/boost/network/protocol/http/message/modifiers/source.hpp b/boost/network/protocol/http/message/modifiers/source.hpp deleted file mode 100644 index 0f4df485d..000000000 --- a/boost/network/protocol/http/message/modifiers/source.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - void source(basic_response & response, T const & value, mpl::false_ const &) { - response << ::boost::network::source(value); - } - - template - void source(basic_response & response, T const & future, mpl::true_ const &) { - response.source(future); - } - - template - void source(basic_request & request, T const & value, tags::server const &) { - request.source = value; - } - - template - void source(basic_request & request, T const & value, tags::client const &) { - request << ::boost::network::source(value); - } - - } - - template - inline void - source(basic_response & response, T const & value) { - impl::source(response, value, is_async()); - } - - template - inline void - source_impl(basic_request & request, T const & value, tags::server) { - impl::source(request, value, Tag()); - } - - template - inline void - source_impl(basic_request & request, T const & value, tags::client) { - impl::source(request, value, Tag()); - } - - template - inline void - source(basic_request & request, T const & value) { - source_impl(request, value, typename client_or_server::type()); - } - -} // namespace http - - namespace impl { - - template - inline void source(Message const & message, ValueType const & source_, http::tags::http_server const &, Async const &) { - message.source = source_; - } - - } /* impl */ - -} // namespace network - -} // namespace boost - -#include -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624 diff --git a/boost/network/protocol/http/message/modifiers/status.hpp b/boost/network/protocol/http/message/modifiers/status.hpp deleted file mode 100644 index 5e541f95f..000000000 --- a/boost/network/protocol/http/message/modifiers/status.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - void status(basic_response & response, T const & value, mpl::false_ const &) { - response << boost::network::http::status(value); - } - - template - void status(basic_response & response, T const & future, mpl::true_ const &) { - response.status(future); - } - - } // namespace impl - - template - void status(basic_response & response, T const & value) { - impl::status(response, value, is_async()); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 diff --git a/boost/network/protocol/http/message/modifiers/status_message.hpp b/boost/network/protocol/http/message/modifiers/status_message.hpp deleted file mode 100644 index 8149e6575..000000000 --- a/boost/network/protocol/http/message/modifiers/status_message.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - void status_message(basic_response & response, T const & value, mpl::false_ const &) { - response << boost::network::http::status_message(value); - } - - template - void status_message(basic_response & response, T const & future, mpl::true_ const &) { - response.status_message(future); - } - - } // namespace impl - - template - void status_message(basic_response & response, T const & value) { - impl::status_message(response, value, is_async()); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 diff --git a/boost/network/protocol/http/message/modifiers/uri.hpp b/boost/network/protocol/http/message/modifiers/uri.hpp deleted file mode 100644 index aaa198ea3..000000000 --- a/boost/network/protocol/http/message/modifiers/uri.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - void uri(basic_request & request, T const & value) { - request.uri(value); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 diff --git a/boost/network/protocol/http/message/modifiers/version.hpp b/boost/network/protocol/http/message/modifiers/version.hpp deleted file mode 100644 index e0b267c71..000000000 --- a/boost/network/protocol/http/message/modifiers/version.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - void version(basic_response & response, T const & value, mpl::false_ const &) { - response << boost::network::http::version(value); - } - - template - void version(basic_response & response, T const & future, mpl::true_ const &) { - response.version(future); - } - - } // namespace impl - - template - void version(basic_response & response, T const & value) { - impl::version(response, value, is_async()); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 diff --git a/boost/network/protocol/http/message/traits/status.hpp b/boost/network/protocol/http/message/traits/status.hpp deleted file mode 100644 index 2eabedea8..000000000 --- a/boost/network/protocol/http/message/traits/status.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_HPP_20100903 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - namespace traits { - - template - struct unsupported_tag; - - template - struct status - : mpl::if_< - is_async, - boost::shared_future, - typename mpl::if_< - is_sync, - boost::uint16_t, - unsupported_tag - >::type - > - {}; - - } /* traits */ - -} /* http */ -} /* network */ -} /* boost */ - -#endif - diff --git a/boost/network/protocol/http/message/traits/status_message.hpp b/boost/network/protocol/http/message/traits/status_message.hpp deleted file mode 100644 index 8469c01ff..000000000 --- a/boost/network/protocol/http/message/traits/status_message.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_MESSAGE_HPP_20100903 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_STATUS_MESSAGE_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - namespace traits { - - template - struct unsupported_tag; - - template - struct status_message - : mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< - mpl::or_< - is_sync, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - - } /* traits */ - -} /* http */ -} /* network */ -} /* boost */ - -#endif - diff --git a/boost/network/protocol/http/message/traits/version.hpp b/boost/network/protocol/http/message/traits/version.hpp deleted file mode 100644 index 15ac4e848..000000000 --- a/boost/network/protocol/http/message/traits/version.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_VERSION_HPP_20100903 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_VERSION_HPP_20100903 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - namespace traits { - - template - struct unsupported_tag; - - template - struct version - { - typedef unsupported_tag type; - }; - - template - struct version >::type> - { - typedef boost::shared_future::type> type; - }; - - template - struct version, - is_default_string, - is_default_wstring - > - >::type - > - { - typedef typename string::type type; - }; - - } /* traits */ - -} /* http */ -} /* network */ -} /* boost */ - -#endif diff --git a/boost/network/protocol/http/message/wrappers/anchor.hpp b/boost/network/protocol/http/message/wrappers/anchor.hpp deleted file mode 100644 index 4a6e85f15..000000000 --- a/boost/network/protocol/http/message/wrappers/anchor.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - template - struct anchor_wrapper { - basic_request const & message_; - anchor_wrapper(basic_request const & message) - : message_(message) {} - typedef typename basic_request::string_type string_type; - operator string_type() { - return message_.anchor(); - } - }; - } - - template inline - impl::anchor_wrapper - anchor(basic_request const & request) { - return impl::anchor_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // nmaespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 diff --git a/boost/network/protocol/http/message/wrappers/body.hpp b/boost/network/protocol/http/message/wrappers/body.hpp deleted file mode 100644 index 068ab38a9..000000000 --- a/boost/network/protocol/http/message/wrappers/body.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - namespace impl { - - template - struct body_wrapper { - typedef typename string::type string_type; - Message const & message_; - explicit body_wrapper(Message const & message) - : message_(message) {} - body_wrapper(body_wrapper const & other) - : message_(other.message_) {} - - operator string_type () const { - return message_.body(); - } - - size_t size() const { - return message_.body().size(); - } - - boost::iterator_range - range() const - { - return boost::make_iterator_range(message_.body()); - } - }; - - template - inline std::ostream & operator<<(std::ostream & os, body_wrapper const & body) { - os << static_cast::string_type>(body); - return os; - } - - } // namespace impl - - template - inline - typename impl::body_wrapper > - body(basic_response const & message) { - return impl::body_wrapper >(message); - } - - template - inline - typename impl::body_wrapper > - body(basic_request const & message) { - return impl::body_wrapper >(message); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_BODY_HPP_20100622 diff --git a/boost/network/protocol/http/message/wrappers/destination.hpp b/boost/network/protocol/http/message/wrappers/destination.hpp deleted file mode 100644 index bf851aac7..000000000 --- a/boost/network/protocol/http/message/wrappers/destination.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 - -// Copyright 2010 (c) Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - template - struct Request; - - template - struct Response; - - BOOST_NETWORK_DEFINE_HTTP_WRAPPER(destination, destination, destination); - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DESTINATION_HPP_20100624 diff --git a/boost/network/protocol/http/message/wrappers/headers.hpp b/boost/network/protocol/http/message/wrappers/headers.hpp deleted file mode 100644 index 69447d30b..000000000 --- a/boost/network/protocol/http/message/wrappers/headers.hpp +++ /dev/null @@ -1,129 +0,0 @@ - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct headers_range { - typedef typename headers_container::type headers_container_type; - typedef typename boost::iterator_range type; - }; - - template - struct basic_request; - - template - struct basic_response; - - namespace impl { - - template - struct request_headers_wrapper { - typedef typename string::type string_type; - typedef typename headers_range >::type range_type; - typedef typename headers_container::type headers_container_type; - typedef typename headers_container_type::const_iterator const_iterator; - typedef typename headers_container_type::iterator iterator; - - explicit request_headers_wrapper(basic_request const & message) - : message_(message) - {} - - range_type operator[] (string_type const & key) const { - return message_.headers().equal_range(key); - } - - typename headers_container_type::size_type count(string_type const & key) const { - return message_.headers().count(key); - } - - const_iterator begin() const { - return message_.headers().begin(); - } - - const_iterator end() const { - return message_.headers().end(); - } - - operator range_type () { - return make_iterator_range(message_.headers().begin(), message_.headers().end()); - } - - operator headers_container_type () { - return message_.headers(); - } - - private: - basic_request const & message_; - }; - - template - struct response_headers_wrapper { - typedef typename string::type string_type; - typedef typename headers_range >::type range_type; - typedef typename headers_container::type headers_container_type; - typedef typename headers_container_type::const_iterator const_iterator; - typedef typename headers_container_type::iterator iterator; - - explicit response_headers_wrapper(basic_response const & message) - : message_(message) - {} - - range_type operator[] (string_type const & key) const { - return message_.headers().equal_range(key); - } - - typename headers_container_type::size_type count(string_type const & key) const { - return message_.headers().count(key); - } - - const_iterator begin() const { - return message_.headers().begin(); - } - - const_iterator end() const { - return message_.headers().end(); - } - - operator range_type () { - return make_iterator_range(message_.headers().begin(), message_.headers().end()); - } - - operator headers_container_type () { - return message_.headers(); - } - - private: - basic_response const & message_; - }; - - } // namespace impl - - template - inline impl::request_headers_wrapper - headers(basic_request const & request_) { - return impl::request_headers_wrapper(request_); - } - - template - inline impl::response_headers_wrapper - headers(basic_response const & response_) { - return impl::response_headers_wrapper(response_); - } - -} // namepace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811 diff --git a/boost/network/protocol/http/message/wrappers/host.hpp b/boost/network/protocol/http/message/wrappers/host.hpp deleted file mode 100644 index 876beb352..000000000 --- a/boost/network/protocol/http/message/wrappers/host.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - - template - struct host_wrapper { - basic_request const & message_; - - host_wrapper(basic_request const & message) - : message_(message) {} - - typedef typename basic_request::string_type string_type; - - operator string_type() { - return message_.host(); - } - }; - - } - - template - inline - impl::host_wrapper - host(basic_request const & request) { - return impl::host_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 diff --git a/boost/network/protocol/http/message/wrappers/major_version.hpp b/boost/network/protocol/http/message/wrappers/major_version.hpp deleted file mode 100644 index 7b71736a3..000000000 --- a/boost/network/protocol/http/message/wrappers/major_version.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - struct major_version_wrapper { - basic_request const & request; - explicit major_version_wrapper(basic_request const & request) - : request(request) {} - operator boost::uint8_t () { - return request.http_version_major; - } - }; - - template - inline typename enable_if, major_version_wrapper >::type - major_version(basic_request const & request) { - return major_version_wrapper(request); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/wrappers/method.hpp b/boost/network/protocol/http/message/wrappers/method.hpp deleted file mode 100644 index 8edb98692..000000000 --- a/boost/network/protocol/http/message/wrappers/method.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - template - struct method_wrapper { - explicit method_wrapper(basic_request const & message) - : message_(message) {} - - basic_request const & message_; - - typedef typename basic_request::string_type string_type; - - operator string_type() { - return message_.method; - } - }; - - template - inline typename enable_if, typename string::type >::type - method(basic_request const & message) { - return method_wrapper(message); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 */ diff --git a/boost/network/protocol/http/message/wrappers/path.hpp b/boost/network/protocol/http/message/wrappers/path.hpp deleted file mode 100644 index 818b55c2f..000000000 --- a/boost/network/protocol/http/message/wrappers/path.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - - template - struct path_wrapper { - basic_request const & message_; - - path_wrapper(basic_request const & message) - : message_(message) {} - - typedef typename basic_request::string_type string_type; - - operator string_type() { - return message_.path(); - } - }; - - } - - template - inline - impl::path_wrapper - path(basic_request const & request) { - return impl::path_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp deleted file mode 100644 index 786ce1e98..000000000 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - - template - struct port_wrapper { - basic_request const & message_; - - port_wrapper(basic_request const & message) - : message_(message) {} - - typedef typename basic_request::port_type port_type; - - operator port_type() { - return message_.port(); - } - - operator boost::optional () { - return uri::port_us(message_.uri()); - } - }; - - } // namespace impl - - template - inline - impl::port_wrapper - port(basic_request const & request) { - return impl::port_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 diff --git a/boost/network/protocol/http/message/wrappers/protocol.hpp b/boost/network/protocol/http/message/wrappers/protocol.hpp deleted file mode 100644 index bca206c68..000000000 --- a/boost/network/protocol/http/message/wrappers/protocol.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - template - struct protocol_wrapper { - basic_request const & message_; - protocol_wrapper(basic_request const & message) - : message_(message) {} - typedef typename basic_request::string_type string_type; - operator string_type() { - return message_.protocol(); - } - }; - } - - template inline - impl::protocol_wrapper - protocol(basic_request const & request) { - return impl::protocol_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 diff --git a/boost/network/protocol/http/message/wrappers/query.hpp b/boost/network/protocol/http/message/wrappers/query.hpp deleted file mode 100644 index 594e6720f..000000000 --- a/boost/network/protocol/http/message/wrappers/query.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - - template - struct query_wrapper { - basic_request const & message_; - - query_wrapper(basic_request const & message) - : message_(message) {} - - typedef typename basic_request::string_type string_type; - - operator string_type () { - return message_.query(); - } - - }; - - } // namespace impl - - template - inline - impl::query_wrapper - query(basic_request const & request) { - return impl::query_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 diff --git a/boost/network/protocol/http/message/wrappers/source.hpp b/boost/network/protocol/http/message/wrappers/source.hpp deleted file mode 100644 index be5f67ea9..000000000 --- a/boost/network/protocol/http/message/wrappers/source.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - template - struct basic_request; - - BOOST_NETWORK_DEFINE_HTTP_WRAPPER(source, source, source); - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_SOURCE_HPP_20100622 diff --git a/boost/network/protocol/http/message/wrappers/status.hpp b/boost/network/protocol/http/message/wrappers/status.hpp deleted file mode 100644 index 2fc860a94..000000000 --- a/boost/network/protocol/http/message/wrappers/status.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - struct status_wrapper { - - basic_response const & response_; - - explicit status_wrapper(basic_response const & response) - : response_(response) {} - - status_wrapper(status_wrapper const & other) - : response_(other.response_) {} - - operator boost::uint16_t () { - return response_.status(); - } - - }; - - } // namespace impl - - template - struct Response; - - template - inline - impl::status_wrapper - status(basic_response const & response) { - return impl::status_wrapper(response); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 diff --git a/boost/network/protocol/http/message/wrappers/status_message.hpp b/boost/network/protocol/http/message/wrappers/status_message.hpp deleted file mode 100644 index 99f29658d..000000000 --- a/boost/network/protocol/http/message/wrappers/status_message.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - struct status_message_wrapper { - - typedef typename string::type string_type; - - basic_response const & response_; - - explicit status_message_wrapper(basic_response const & response) - : response_(response) {} - - status_message_wrapper(status_message_wrapper const & other) - : response_(other.response_) {} - - operator string_type () { - return response_.status_message(); - } - - }; - - } // namespace impl - - template - inline - impl::status_message_wrapper - status_message(basic_response const & response) { - return impl::status_message_wrapper(response); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_STATUS_MESSAGE_HPP_20100603 diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp deleted file mode 100644 index 7ff9d9b02..000000000 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 - -// Copyright 2010 (c) Dean Michael Berris. -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_request; - - namespace impl { - template - struct uri_wrapper { - basic_request const & message_; - uri_wrapper(basic_request const & message) - : message_(message) {} - typedef typename basic_request::string_type string_type; - operator string_type() { - return message_.uri().raw(); - } - operator boost::network::uri::uri () { - return message_.uri(); - } - }; - } - - template inline - impl::uri_wrapper - uri(basic_request const & request) { - return impl::uri_wrapper(request); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 diff --git a/boost/network/protocol/http/message/wrappers/version.hpp b/boost/network/protocol/http/message/wrappers/version.hpp deleted file mode 100644 index b3e16d2fc..000000000 --- a/boost/network/protocol/http/message/wrappers/version.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace http { - - template - struct basic_response; - - namespace impl { - - template - struct version_wrapper { - - typedef typename string::type string_type; - - basic_response const & response_; - - explicit version_wrapper(basic_response const & response) - : response_(response) {} - - version_wrapper(version_wrapper const & other) - : response_(other.response_) {} - - operator string_type () { - return response_.version(); - } - - }; - - } // namespace impl - - template - inline - impl::version_wrapper - version(basic_response const & response) { - return impl::version_wrapper(response); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 diff --git a/boost/network/protocol/http/parameters.hpp b/boost/network/protocol/http/parameters.hpp deleted file mode 100644 index 9bf0ae97e..000000000 --- a/boost/network/protocol/http/parameters.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 -#define BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if !defined(BOOST_PARAMETER_MAX_ARITY) - #define BOOST_PARAMETER_MAX_ARITY 16 -#endif -#include - -namespace boost { namespace network { namespace http { - - BOOST_PARAMETER_NAME(io_service) - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 */ diff --git a/boost/network/protocol/http/parser/incremental.hpp b/boost/network/protocol/http/parser/incremental.hpp deleted file mode 100644 index 44c4c2a2e..000000000 --- a/boost/network/protocol/http/parser/incremental.hpp +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 - -// Copyright Dean Michael Berris 2010. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct response_parser { - - enum state_t { - http_response_begin, - http_version_h, - http_version_t1, - http_version_t2, - http_version_p, - http_version_slash, - http_version_major, - http_version_dot, - http_version_minor, - http_version_done, - http_status_digit, - http_status_done, - http_status_message_char, - http_status_message_cr, - http_status_message_done, - http_header_name_char, - http_header_colon, - http_header_value_char, - http_header_line_cr, - http_header_line_done, - http_headers_end_cr, - http_headers_done - }; - - explicit response_parser (state_t state=http_response_begin) - : state_(state) {} - - response_parser (response_parser const & other) - : state_(other.state_) {} - - ~response_parser () {} - - void swap(response_parser & other) { - std::swap(other.state_, this->state_); - } - - response_parser & operator=(response_parser rhs) { - rhs.swap(*this); - return *this; - } - - template - fusion::tuple > parse_until(state_t stop_state, Range & range_) { - logic::tribool parsed_ok(logic::indeterminate); - typename Range::const_iterator start = boost::begin(range_), - current = start, - end = boost::end(range_); - boost::iterator_range - local_range = boost::make_iterator_range(start, end); - while (!boost::empty(local_range) && indeterminate(parsed_ok)) { - current = boost::begin(local_range); - if (state_ == stop_state) { - parsed_ok = true; - } else { - switch(state_) { - case http_response_begin: - if (*current == ' ' || *current == '\r' || *current == '\n') { - // skip valid leading whitespace - ++start; - ++current; - } else if (*current == 'H') { - state_ = http_version_h; - start = current; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_h: - if (*current == 'T') { - state_ = http_version_t1; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_t1: - if (*current == 'T') { - state_ = http_version_t2; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_t2: - if (*current == 'P') { - state_ = http_version_p; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_p: - if (*current == '/') { - state_ = http_version_slash; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_slash: - if (algorithm::is_digit()(*current)) { - state_ = http_version_major; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_major: - if (*current == '.') { - state_ = http_version_dot; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_dot: - if (algorithm::is_digit()(*current)) { - state_ = http_version_minor; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_minor: - if (*current == ' ') { - state_ = http_version_done; - ++current; - } else { - parsed_ok = false; - } - break; - case http_version_done: - if (algorithm::is_digit()(*current)) { - state_ = http_status_digit; - ++current; - } else { - parsed_ok = false; - } - break; - case http_status_digit: - if (algorithm::is_digit()(*current)) { - ++current; - } else if (*current == ' ') { - state_ = http_status_done; - ++current; - } else { - parsed_ok = false; - } - break; - case http_status_done: - if (algorithm::is_alnum()(*current)) { - state_ = http_status_message_char; - ++current; - } else { - parsed_ok = false; - } - break; - case http_status_message_char: - if (algorithm::is_alnum()(*current) || algorithm::is_punct()(*current) || (*current == ' ')) { - ++current; - } else if (*current == '\r') { - state_ = http_status_message_cr; - ++current; - } else { - parsed_ok = false; - } - break; - case http_status_message_cr: - if (*current == '\n') { - state_ = http_status_message_done; - ++current; - } else { - parsed_ok = false; - } - break; - case http_status_message_done: - case http_header_line_done: - if (algorithm::is_alnum()(*current)) { - state_ = http_header_name_char; - ++current; - } else if (*current == '\r') { - state_ = http_headers_end_cr; - ++current; - } else { - parsed_ok = false; - } - break; - case http_header_name_char: - if (*current == ':') { - state_ = http_header_colon; - ++current; - } else if (algorithm::is_alnum()(*current) || algorithm::is_space()(*current) || algorithm::is_punct()(*current)) { - ++current; - } else { - parsed_ok = false; - } - break; - case http_header_colon: - if (algorithm::is_space()(*current)) { - ++current; - } else if (algorithm::is_alnum()(*current) || algorithm::is_punct()(*current)) { - state_ = http_header_value_char; - ++current; - } else { - parsed_ok = false; - } - break; - case http_header_value_char: - if (*current == '\r') { - state_ = http_header_line_cr; - ++current; - } else if (algorithm::is_cntrl()(*current)) { - parsed_ok = false; - } else { - ++current; - } - break; - case http_header_line_cr: - if (*current == '\n') { - state_ = http_header_line_done; - ++current; - } else { - parsed_ok = false; - } - break; - case http_headers_end_cr: - if (*current == '\n') { - state_ = http_headers_done; - ++current; - } else { - parsed_ok = false; - } - break; - default: - parsed_ok = false; - } - } - - local_range = boost::make_iterator_range(current, end); - } - if (state_ == stop_state) parsed_ok = true; - return fusion::make_tuple(parsed_ok,boost::make_iterator_range(start, current)); - } - - state_t state() { - return state_; - } - - void reset(state_t new_state = http_response_begin) { - state_ = new_state; - } - - private: - state_t state_; - - }; - - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp deleted file mode 100644 index ea8638d6b..000000000 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 -#define BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct async_connection_policy : resolver_policy::type { - protected: - - typedef typename string::type string_type; - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename resolver_base::resolve_function resolve_function; - typedef function const &, system::error_code const &)> body_callback_function_type; - - struct connection_impl { - connection_impl( - bool follow_redirect, - resolve_function resolve, - resolver_type & resolver, - bool https, - optional const & certificate_filename, - optional const & verify_path - ) - { - pimpl = impl::async_connection_base::new_connection(resolve, resolver, follow_redirect, https, certificate_filename, verify_path); - } - - basic_response send_request(string_type const & method, basic_request const & request_, bool get_body, body_callback_function_type callback) { - return pimpl->start(request_, method, get_body, callback); - } - - private: - - shared_ptr > pimpl; - - }; - - typedef boost::shared_ptr connection_ptr; - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_, optional const & certificate_filename = optional(), optional const & verify_path = optional()) { - string_type protocol_ = protocol(request_); - connection_ptr connection_( - new connection_impl( - follow_redirect_ - , boost::bind( - &async_connection_policy::resolve, - this, - _1, _2, _3, _4 - ) - , resolver - , boost::iequals(protocol_, string_type("https")) - , certificate_filename - , verify_path)); - return connection_; - } - - void cleanup() { } - - async_connection_policy(bool cache_resolved, bool follow_redirect) - : resolver_base(cache_resolved), follow_redirect_(follow_redirect) {} - - bool follow_redirect_; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_POLICY_ASYNC_CONNECTION_HPP_ diff --git a/boost/network/protocol/http/policies/async_resolver.hpp b/boost/network/protocol/http/policies/async_resolver.hpp deleted file mode 100644 index cb49a09cc..000000000 --- a/boost/network/protocol/http/policies/async_resolver.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 -#define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace policies { - - template - struct async_resolver - : boost::enable_shared_from_this > - { - typedef typename resolver::type resolver_type; - typedef typename resolver_type::iterator resolver_iterator; - typedef typename resolver_type::query resolver_query; - typedef std::pair resolver_iterator_pair; - typedef typename string::type string_type; - typedef boost::unordered_map endpoint_cache; - typedef boost::function resolve_completion_function; - typedef boost::function resolve_function; - protected: - bool cache_resolved_; - endpoint_cache endpoint_cache_; - boost::shared_ptr service_; - boost::shared_ptr resolver_strand_; - - explicit async_resolver(bool cache_resolved) - : cache_resolved_(cache_resolved), endpoint_cache_() - { - - } - - void resolve( - resolver_type & resolver_, - string_type const & host, - boost::uint16_t port, - resolve_completion_function once_resolved - ) - { - if (cache_resolved_) { - typename endpoint_cache::iterator iter = - endpoint_cache_.find(boost::to_lower_copy(host)); - if (iter != endpoint_cache_.end()) { - boost::system::error_code ignored; - once_resolved(ignored, iter->second); - return; - } - } - - typename resolver_type::query q( - resolver_type::protocol_type::v4() - , host - , lexical_cast(port)); - resolver_.async_resolve( - q, - resolver_strand_->wrap( - boost::bind( - &async_resolver::handle_resolve, - async_resolver::shared_from_this(), - boost::to_lower_copy(host), - once_resolved, - boost::asio::placeholders::error, - boost::asio::placeholders::iterator - ) - ) - ); - } - - void handle_resolve( - string_type const & host, - resolve_completion_function once_resolved, - boost::system::error_code const & ec, - resolver_iterator endpoint_iterator - ) - { - typename endpoint_cache::iterator iter; - bool inserted = false; - if (!ec && cache_resolved_) { - boost::fusion::tie(iter, inserted) = - endpoint_cache_.insert( - std::make_pair( - host, - std::make_pair( - endpoint_iterator, - resolver_iterator() - ) - ) - ); - once_resolved(ec, iter->second); - } else { - once_resolved(ec, std::make_pair(endpoint_iterator,resolver_iterator())); - } - } - - }; - -} // namespace policies - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_RESOLVER_20100622 diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp deleted file mode 100644 index 31be06f8e..000000000 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -#include -#include -#include -#include -#include -#include - -#ifndef BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT -#define BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT 5 -#endif // BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT - -namespace boost { namespace network { namespace http { - - template - struct pooled_connection_policy : resolver_policy::type { - protected: - - typedef typename string::type string_type; - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef function resolver_function_type; - typedef function const &, system::error_code const &)> body_callback_function_type; - - void cleanup() { - host_connection_map().swap(host_connections); - } - - struct connection_impl { - typedef function(resolver_type &,basic_request const &,optional const &, optional const &)> get_connection_function; - - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https, optional const & certificate_file=optional(), optional const & verify_path=optional()) - : pimpl(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_file, verify_path)) - , resolver_(resolver) - , connection_follow_redirect_(follow_redirect) - , get_connection_(get_connection) - , certificate_filename_(certificate_file) - , verify_path_(verify_path) - {} - - basic_response send_request(string_type const & method, basic_request request_, bool get_body, body_callback_function_type callback) { - return send_request_impl(method, request_, get_body); - } - - private: - - basic_response send_request_impl(string_type const & method, basic_request request_, bool get_body) { - boost::uint8_t count = 0; - bool retry = false; - do { - if (count >= BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT) - boost::throw_exception(std::runtime_error("Redirection exceeds maximum redirect count.")); - - basic_response response_; - // check if the socket is open first - if (!pimpl->is_open()) { - pimpl->init_socket(request_.host(), lexical_cast(request_.port())); - } - response_ = basic_response(); - response_ << ::boost::network::source(request_.host()); - - pimpl->send_request_impl(method, request_); - boost::asio::streambuf response_buffer; - - try { - pimpl->read_status(response_, response_buffer); - } catch (boost::system::system_error & e) { - if (!retry && e.code() == boost::asio::error::eof) { - retry = true; - pimpl->init_socket(request_.host(), lexical_cast(request_.port())); - continue; - } - throw; // it's a retry, and there's something wrong. - } - - pimpl->read_headers(response_, response_buffer); - - if ( - get_body && response_.status() != 304 - && (response_.status() != 204) - && !(response_.status() >= 100 && response_.status() <= 199) - ) { - pimpl->read_body(response_, response_buffer); - } - - typename headers_range >::type connection_range = headers(response_)["Connection"]; - if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::begin(connection_range)->second == string_type("close")) { - pimpl->close_socket(); - } else if (version_major == 1 && version_minor == 0) { - pimpl->close_socket(); - } - - if (connection_follow_redirect_) { - boost::uint16_t status = response_.status(); - if (status >= 300 && status <= 307) { - typename headers_range >::type location_range = headers(response_)["Location"]; - typename range_iterator >::type>::type location_header = boost::begin(location_range); - if (location_header != boost::end(location_range)) { - request_.uri(location_header->second); - connection_ptr connection_; - connection_ = get_connection_(resolver_, request_, certificate_filename_, verify_path_); - ++count; - continue; - } else boost::throw_exception(std::runtime_error("Location header not defined in redirect response.")); - } - } - return response_; - } while(true); - } - - shared_ptr > pimpl; - resolver_type & resolver_; - bool connection_follow_redirect_; - get_connection_function get_connection_; - optional certificate_filename_, verify_path_; - }; - - typedef shared_ptr connection_ptr; - - typedef unordered_map host_connection_map; - host_connection_map host_connections; - bool follow_redirect_; - - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_, optional const & certificate_filename = optional(), optional const & verify_path = optional()) { - string_type index = (request_.host() + ':') + lexical_cast(request_.port()); - connection_ptr connection_; - typename host_connection_map::iterator it = - host_connections.find(index); - if (it == host_connections.end()) { - connection_.reset(new connection_impl( - resolver - , follow_redirect_ - , request_.host() - , lexical_cast(request_.port()) - , boost::bind( - &pooled_connection_policy::resolve, - this, - _1, _2, _3 - ) - , boost::bind( - &pooled_connection_policy::get_connection, - this, - _1, _2, _3, _4 - ) - , boost::iequals(request_.protocol(), string_type("https")) - , certificate_filename - , verify_path - ) - ); - host_connections.insert(std::make_pair(index, connection_)); - return connection_; - } - return it->second; - } - - pooled_connection_policy(bool cache_resolved, bool follow_redirect) - : resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {} - - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_POOLED_CONNECTION_POLICY_20091214 - diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp deleted file mode 100644 index 16d9fd1a8..000000000 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct simple_connection_policy : resolver_policy::type { - protected: - - typedef typename string::type string_type; - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef function resolver_function_type; - typedef function const &, system::error_code const &)> body_callback_function_type; - - struct connection_impl { - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) - : pimpl() - , follow_redirect_(follow_redirect) - { - pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_filename, verify_path)); - } - - basic_response send_request(string_type const & method, basic_request request_, bool get_body, body_callback_function_type callback) { - basic_response response_; - do { - pimpl->init_socket(request_.host(), lexical_cast(request_.port())); - pimpl->send_request_impl(method, request_); - - response_ = basic_response(); - response_ << network::source(request_.host()); - - boost::asio::streambuf response_buffer; - pimpl->read_status(response_, response_buffer); - pimpl->read_headers(response_, response_buffer); - if (get_body) pimpl->read_body(response_, response_buffer); - - if (follow_redirect_) { - boost::uint16_t status = response_.status(); - if (status >= 300 && status <= 307) { - typename headers_range >::type location_range = headers(response_)["Location"]; - typename range_iterator >::type>::type location_header = boost::begin(location_range); - if (location_header != boost::end(location_range)) { - request_.uri(location_header->second); - } else throw std::runtime_error("Location header not defined in redirect response."); - } else break; - } else break; - } while(true); - return response_; - } - - private: - - shared_ptr > pimpl; - bool follow_redirect_; - - }; - - typedef boost::shared_ptr connection_ptr; - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_ - , optional const & certificate_file = optional() - , optional const & verify_file = optional() - ) { - connection_ptr connection_( - new connection_impl( - resolver - , follow_redirect_ - , request_.host() - , lexical_cast(request_.port()) - , boost::bind( - &simple_connection_policy::resolve, - this, - _1, _2, _3 - ) - , boost::iequals(request_.protocol(), string_type("https")) - , certificate_file - , verify_file - ) - ); - return connection_; - } - - void cleanup() { } - - simple_connection_policy(bool cache_resolved, bool follow_redirect) - : resolver_base(cache_resolved), follow_redirect_(follow_redirect) {} - - // member variables - bool follow_redirect_; - - }; - -} // namespace http - -} // namespace network - -} // namespace boost - - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SIMPLE_CONNECTION_20091214 - diff --git a/boost/network/protocol/http/policies/sync_resolver.hpp b/boost/network/protocol/http/policies/sync_resolver.hpp deleted file mode 100644 index 9702425e9..000000000 --- a/boost/network/protocol/http/policies/sync_resolver.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace policies { - - template - struct sync_resolver { - - typedef typename resolver::type resolver_type; - typedef typename resolver_type::iterator resolver_iterator; - typedef typename resolver_type::query resolver_query; - typedef std::pair resolver_iterator_pair; - - protected: - - typedef typename string::type string_type; - typedef boost::unordered_map resolved_cache; - resolved_cache endpoint_cache_; - bool cache_resolved_; - - sync_resolver(bool cache_resolved) : cache_resolved_(cache_resolved) {} - - resolver_iterator_pair resolve(resolver_type & resolver_, string_type const & hostname, string_type const & port) { - if (cache_resolved_) { - typename resolved_cache::iterator cached_iterator = - endpoint_cache_.find(hostname); - if (cached_iterator == endpoint_cache_.end()) { - bool inserted = false; - boost::fusion::tie(cached_iterator, inserted) = - endpoint_cache_.insert( - std::make_pair( - boost::to_lower_copy(hostname), - std::make_pair( - resolver_.resolve( - resolver_query( - hostname, - port, - resolver_query::numeric_service - ) - ) - , resolver_iterator() - ) - ) - ); - }; - return cached_iterator->second; - }; - - return std::make_pair( - resolver_.resolve( - resolver_query( - hostname, - port, - resolver_query::numeric_service - ) - ) - , - resolver_iterator() - ); - }; - - }; - -} // namespace policies - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214 - diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp deleted file mode 100644 index 7ac1fa412..000000000 --- a/boost/network/protocol/http/request.hpp +++ /dev/null @@ -1,84 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef __NETWORK_PROTOCOL_HTTP_REQUEST_20070908_1_HPP__ -#define __NETWORK_PROTOCOL_HTTP_REQUEST_20070908_1_HPP__ - -// Implement the HTTP Request Object - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// forward declarations -namespace boost { namespace network { namespace http { - - template - struct basic_request; - -} // namespace http - -} // namespace network - -} // namespace boost - -#include - -namespace boost { namespace network { namespace http { - - template - basic_request & operator<<( - basic_request & message, - Directive const & directive - ) - { - directive(message); - return message; - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#include - -#endif // __NETWORK_PROTOCOL_HTTP_REQUEST_20070908-1_HPP__ - diff --git a/boost/network/protocol/http/response.hpp b/boost/network/protocol/http/response.hpp deleted file mode 100644 index cf36cceb0..000000000 --- a/boost/network/protocol/http/response.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright Dean Michael Berris 2007. -// Copyright Michael Dickey 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct basic_response : public message_base::type { - - typedef typename string::type string_type; - - private: - typedef typename message_base::type base_type; - - public: - - typedef Tag tag; - - basic_response() - : base_type() - {} - - basic_response(basic_response const & other) - : base_type(other) - {} - - basic_response & operator=(basic_response rhs) { - rhs.swap(*this); - return *this; - }; - - void swap(basic_response & other) { - base_type & base_ref(other), - & this_ref(*this); - std::swap(this_ref, base_ref); - }; - }; - - template - inline void swap(basic_response & lhs, basic_response & rhs) { - lhs.swap(rhs); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#include - -namespace boost { namespace network { namespace http { - - template - basic_response & operator<<( - basic_response & message, - Directive const & directive - ) - { - directive(message); - return message; - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_HPP diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp deleted file mode 100644 index a15613573..000000000 --- a/boost/network/protocol/http/server.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2009 (c) Tarro, Inc. -// Copyright 2009 (c) Dean Michael Berris -// Copyright 2010 (c) Glyn Matthews -// Copyright 2003-2008 (c) Chris Kholhoff -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_HTTP_SERVER_HPP_ -#define BOOST_NETWORK_HTTP_SERVER_HPP_ - -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct server_base { - typedef unsupported_tag type; - }; - - template - struct server_base >::type> { - typedef async_server_base type; - }; - - template - struct server_base >::type> { - typedef sync_server_base type; - }; - - template - struct basic_server : server_base::type - {}; - - template - struct server : server_base::type { - typedef typename server_base::type - server_base; - - BOOST_PARAMETER_CONSTRUCTOR( - server, (server_base), tag, - (required - (address, (typename server_base::string_type const &)) - (port, (typename server_base::string_type const &)) - (in_out(handler), (Handler &))) - (optional - (in_out(io_service), (boost::asio::io_service &)) - (reuse_address, (bool)) - (report_aborted, (bool)) - (receive_buffer_size, (int)) - (send_buffer_size, (int)) - (receive_low_watermark, (int)) - (send_low_watermark, (int)) - (non_blocking_io, (int)) - (linger, (bool)) - (linger_timeout, (int))) - ) - }; - - template - struct async_server : server_base::type - { - typedef typename server_base::type - server_base; - - BOOST_PARAMETER_CONSTRUCTOR( - async_server, (server_base), tag, - (required - (address, (typename server_base::string_type const &)) - (port, (typename server_base::string_type const &)) - (in_out(handler), (Handler&)) - (in_out(thread_pool), (utils::thread_pool&))) - (optional - (in_out(io_service), (boost::asio::io_service&)) - (reuse_address, (bool)) - (report_aborted, (bool)) - (receive_buffer_size, (int)) - (send_buffer_size, (int)) - (receive_low_watermark, (int)) - (send_low_watermark, (int)) - (non_blocking_io, (bool)) - (linger, (bool)) - (linger_timeout, (int))) - ) - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_HTTP_SERVER_HPP_ - diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp deleted file mode 100644 index d1002cf01..000000000 --- a/boost/network/protocol/http/server/async_connection.hpp +++ /dev/null @@ -1,642 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_NETWORK_NO_LIB -#include -#endif - -#ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE -/** Here we define a page's worth of header connection buffer data. - * This can be tuned to reduce the memory cost of connections, but this - * default size is set to be friendly to typical service applications. - * This is the maximum size though and Boost.Asio's internal representation - * of a streambuf would make appropriate decisions on how big a buffer - * is to begin with. - * - * This kinda assumes that a page is by default 4096. Since we're using - * the default allocator with the static buffers, it's not guaranteed that - * the static buffers will be page-aligned when they are allocated. - */ -#define BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE 4096 -#endif /* BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE */ - -namespace boost { namespace network { namespace http { - -#ifndef BOOST_NETWORK_NO_LIB - extern void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair); - extern void parse_headers(std::string const & input, std::vector & container); -#endif - - template - struct async_connection : boost::enable_shared_from_this > { - - enum status_t { - ok = 200 - , created = 201 - , accepted = 202 - , no_content = 204 - , multiple_choices = 300 - , moved_permanently = 301 - , moved_temporarily = 302 - , not_modified = 304 - , bad_request = 400 - , unauthorized = 401 - , forbidden = 403 - , not_found = 404 - , not_supported = 405 - , not_acceptable = 406 - , internal_server_error = 500 - , not_implemented = 501 - , bad_gateway = 502 - , service_unavailable = 503 - }; - - typedef typename string::type string_type; - typedef basic_request request; - typedef shared_ptr connection_ptr; - - private: - static char const * status_message(status_t status) { - static char const - ok_[] = "OK" - , created_[] = "Created" - , accepted_[] = "Accepted" - , no_content_[] = "No Content" - , multiple_choices_[] = "Multiple Choices" - , moved_permanently_[] = "Moved Permanently" - , moved_temporarily_[] = "Moved Temporarily" - , not_modified_[] = "Not Modified" - , bad_request_[] = "Bad Request" - , unauthorized_[] = "Unauthorized" - , forbidden_[] = "Fobidden" - , not_found_[] = "Not Found" - , not_supported_[] = "Not Supported" - , not_acceptable_[] = "Not Acceptable" - , internal_server_error_[] = "Internal Server Error" - , not_implemented_[] = "Not Implemented" - , bad_gateway_[] = "Bad Gateway" - , service_unavailable_[] = "Service Unavailable" - , unknown_[] = "Unknown" - ; - switch(status) { - case ok: return ok_; - case created: return created_; - case accepted: return accepted_; - case no_content: return no_content_; - case multiple_choices: return multiple_choices_; - case moved_permanently: return moved_permanently_; - case moved_temporarily: return moved_temporarily_; - case not_modified: return not_modified_; - case bad_request: return bad_request_; - case unauthorized: return unauthorized_; - case forbidden: return forbidden_; - case not_found: return not_found_; - case not_supported: return not_supported_; - case not_acceptable: return not_acceptable_; - case internal_server_error: return internal_server_error_; - case not_implemented: return not_implemented_; - case bad_gateway: return bad_gateway_; - case service_unavailable: return service_unavailable_; - default: return unknown_; - } - } - - public: - - async_connection( - asio::io_service & io_service - , Handler & handler - , utils::thread_pool & thread_pool - ) - : socket_(io_service) - , strand(io_service) - , handler(handler) - , thread_pool_(thread_pool) - , headers_already_sent(false) - , headers_in_progress(false) - , headers_buffer(BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE) - { - new_start = read_buffer_.begin(); - } - - ~async_connection() throw () { - boost::system::error_code ignored; - socket_.shutdown(asio::ip::tcp::socket::shutdown_receive, ignored); - } - - /** Function: template set_headers(Range headers) - * Precondition: headers have not been sent yet - * Postcondition: headers have been linearized to a buffer, - * and assumed to have been sent already when the function exits - * Throws: std::logic_error in case the headers have already been sent. - * - * A call to set_headers takes a Range where each element models the - * Header concept. This Range will be linearized onto a buffer, which is - * then sent as soon as the first call to `write` or `flush` commences. - */ - template - void set_headers(Range headers) { - lock_guard lock(headers_mutex); - if (headers_in_progress || headers_already_sent) - boost::throw_exception(std::logic_error("Headers have already been sent.")); - - if (error_encountered) - boost::throw_exception(boost::system::system_error(*error_encountered)); - - typedef constants consts; - { - std::ostream stream(&headers_buffer); - stream - << consts::http_slash() << 1<< consts::dot() << 1 << consts::space() - << status << consts::space() << status_message(status) - << consts::crlf(); - if (!boost::empty(headers)) { - typedef typename Range::const_iterator iterator; - typedef typename string::type string_type; - boost::transform(headers, - std::ostream_iterator(stream), - linearize_header()); - } else { - stream << consts::crlf(); - } - stream << consts::crlf(); - } - - write_headers_only( - boost::bind( - &async_connection::do_nothing - , async_connection::shared_from_this() - )); - } - - void set_status(status_t new_status) { - lock_guard lock(headers_mutex); - if (headers_already_sent) boost::throw_exception(std::logic_error("Headers have already been sent, cannot reset status.")); - if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); - - status = new_status; - } - - template - void write(Range const & range) { - lock_guard lock(headers_mutex); - if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); - - boost::function f = - boost::bind( - &async_connection::default_error - , async_connection::shared_from_this() - , _1); - - write_impl( - boost::make_iterator_range(range) - , f - ); - } - - template - typename disable_if, void>::type - write(Range const & range, Callback const & callback) { - lock_guard lock(headers_mutex); - if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); - write_impl(boost::make_iterator_range(range), callback); - } - - template - typename enable_if, void>::type - write(ConstBufferSeq const & seq, Callback const & callback) - { - write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); - } - - private: - typedef boost::array buffer_type; - - public: - typedef iterator_range input_range; - typedef boost::function read_callback_function; - - void read(read_callback_function callback) { - if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); - if (new_start != read_buffer_.begin()) - { - input_range input = boost::make_iterator_range(new_start, read_buffer_.end()); - thread_pool().post( - boost::bind( - callback - , input - , boost::system::error_code() - , std::distance(new_start, data_end) - , async_connection::shared_from_this()) - ); - new_start = read_buffer_.begin(); - return; - } - - socket().async_read_some( - asio::buffer(read_buffer_) - , strand.wrap( - boost::bind( - &async_connection::wrap_read_handler - , async_connection::shared_from_this() - , callback - , asio::placeholders::error, asio::placeholders::bytes_transferred))); - } - - asio::ip::tcp::socket & socket() { return socket_; } - utils::thread_pool & thread_pool() { return thread_pool_; } - bool has_error() { return (!!error_encountered); } - optional error() - { return error_encountered; } - - private: - - void wrap_read_handler(read_callback_function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (ec) error_encountered = in_place(ec); - buffer_type::const_iterator data_start = read_buffer_.begin() - ,data_end = read_buffer_.begin(); - std::advance(data_end, bytes_transferred); - thread_pool().post( - boost::bind( - callback - , boost::make_iterator_range(data_start, data_end) - , ec - , bytes_transferred - , async_connection::shared_from_this())); - } - - void default_error(boost::system::error_code const & ec) { - error_encountered = in_place(ec); - } - - typedef boost::array array; - typedef std::list > array_list; - typedef boost::shared_ptr shared_array_list; - typedef boost::shared_ptr > shared_buffers; - typedef request_parser request_parser_type; - typedef boost::lock_guard lock_guard; - typedef std::list > pending_actions_list; - - asio::ip::tcp::socket socket_; - asio::io_service::strand strand; - Handler & handler; - utils::thread_pool & thread_pool_; - volatile bool headers_already_sent, headers_in_progress; - asio::streambuf headers_buffer; - - boost::recursive_mutex headers_mutex; - buffer_type read_buffer_; - status_t status; - request_parser_type parser; - request request_; - buffer_type::iterator new_start, data_end; - string_type partial_parsed; - optional error_encountered; - pending_actions_list pending_actions; - - template friend struct async_server_base; - - enum state_t { - method, uri, version, headers - }; - - void start() { - typename ostringstream::type ip_stream; - ip_stream << socket_.remote_endpoint().address().to_v4().to_string() << ':' - << socket_.remote_endpoint().port(); - request_.source = ip_stream.str(); - read_more(method); - } - - void read_more(state_t state) { - socket_.async_read_some( - asio::buffer(read_buffer_) - , strand.wrap( - boost::bind( - &async_connection::handle_read_data, - async_connection::shared_from_this(), - state, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ) - ) - ); - } - - void handle_read_data(state_t state, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec) { - logic::tribool parsed_ok; - iterator_range result_range, input_range; - data_end = read_buffer_.begin(); - std::advance(data_end, bytes_transferred); - switch (state) { - case method: - input_range = boost::make_iterator_range( - new_start, data_end); - fusion::tie(parsed_ok, result_range) = parser.parse_until( - request_parser_type::method_done, input_range); - if (!parsed_ok) { - client_error(); - break; - } else if (parsed_ok == true) { - swap(partial_parsed, request_.method); - request_.method.append( - boost::begin(result_range), - boost::end(result_range)); - trim(request_.method); - new_start = boost::end(result_range); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - new_start = read_buffer_.begin(); - read_more(method); - break; - } - case uri: - input_range = boost::make_iterator_range( - new_start, data_end); - fusion::tie(parsed_ok, result_range) = parser.parse_until( - request_parser_type::uri_done, - input_range); - if (!parsed_ok) { - client_error(); - break; - } else if (parsed_ok == true) { - swap(partial_parsed, request_.destination); - request_.destination.append( - boost::begin(result_range), - boost::end(result_range)); - trim(request_.destination); - new_start = boost::end(result_range); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - new_start = read_buffer_.begin(); - read_more(uri); - break; - } - case version: - input_range = boost::make_iterator_range( - new_start, data_end); - fusion::tie(parsed_ok, result_range) = parser.parse_until( - request_parser_type::version_done, - input_range); - if (!parsed_ok) { - client_error(); - break; - } else if (parsed_ok == true) { - fusion::tuple version_pair; - partial_parsed.append(boost::begin(result_range), boost::end(result_range)); - parse_version(partial_parsed, version_pair); - request_.http_version_major = fusion::get<0>(version_pair); - request_.http_version_minor = fusion::get<1>(version_pair); - new_start = boost::end(result_range); - partial_parsed.clear(); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - new_start = read_buffer_.begin(); - read_more(version); - break; - } - case headers: - input_range = boost::make_iterator_range( - new_start, data_end); - fusion::tie(parsed_ok, result_range) = parser.parse_until( - request_parser_type::headers_done, - input_range); - if (!parsed_ok) { - client_error(); - break; - } else if (parsed_ok == true) { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - parse_headers(partial_parsed, request_.headers); - new_start = boost::end(result_range); - thread_pool().post( - boost::bind( - &Handler::operator(), - &handler, - cref(request_), - async_connection::shared_from_this())); - return; - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - new_start = read_buffer_.begin(); - read_more(headers); - break; - } - default: - BOOST_ASSERT(false && "This is a bug, report to the cpp-netlib devel mailing list!"); - std::abort(); - } - } else { - error_encountered = in_place(ec); - } - } - - void client_error() { - static char const * bad_request = - "HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; - - asio::async_write( - socket() - , asio::buffer(bad_request, strlen(bad_request)) - , strand.wrap( - boost::bind( - &async_connection::client_error_sent - , async_connection::shared_from_this() - , asio::placeholders::error - , asio::placeholders::bytes_transferred))); - } - - void client_error_sent(boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec) { - boost::system::error_code ignored; - socket().shutdown(asio::ip::tcp::socket::shutdown_both, ignored); - socket().close(ignored); - } else { - error_encountered = in_place(ec); - } - } - - void do_nothing() {} - - void write_headers_only(boost::function callback) { - if (headers_in_progress) return; - headers_in_progress = true; - asio::async_write( - socket() - , headers_buffer - , strand.wrap( - boost::bind( - &async_connection::handle_write_headers - , async_connection::shared_from_this() - , callback - , asio::placeholders::error - , asio::placeholders::bytes_transferred))); - } - - void handle_write_headers(boost::function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - lock_guard lock(headers_mutex); - if (!ec) { - headers_buffer.consume(headers_buffer.size()); - headers_already_sent = true; - thread_pool().post(callback); - pending_actions_list::iterator start = pending_actions.begin() - , end = pending_actions.end(); - while (start != end) { - thread_pool().post(*start++); - } - pending_actions_list().swap(pending_actions); - } else { - error_encountered = in_place(ec); - } - } - - void handle_write( - boost::function callback - , shared_array_list temporaries - , shared_buffers buffers - , boost::system::error_code const & ec - , std::size_t bytes_transferred - ) { - // we want to forget the temporaries and buffers - thread_pool().post(boost::bind(callback, ec)); - } - - template - void write_impl(Range range, boost::function callback) { - // linearize the whole range into a vector - // of fixed-sized buffers, then schedule an asynchronous - // write of these buffers -- make sure they are live - // by making these linearized buffers shared and made - // part of the completion handler. - // - // once the range has been linearized and sent, schedule - // a wrapper to be called in the io_service's thread, that - // will re-schedule the given callback into the thread pool - // referred to here so that the io_service's thread can concentrate - // on doing I/O. - // - - static std::size_t const connection_buffer_size = - BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE; - shared_array_list temporaries = - boost::make_shared(); - shared_buffers buffers = - boost::make_shared >(0); - - std::size_t range_size = boost::distance(range); - buffers->reserve( - (range_size / connection_buffer_size) - + ((range_size % connection_buffer_size)?1:0) - ); - std::size_t slice_size = - std::min(range_size,connection_buffer_size); - typename boost::range_iterator::type - start = boost::begin(range) - , end = boost::end(range); - while (slice_size != 0) { - using boost::adaptors::sliced; - shared_ptr new_array = make_shared(); - boost::copy( - range | sliced(0,slice_size) - , new_array->begin() - ); - temporaries->push_back(new_array); - buffers->push_back(asio::buffer(new_array->data(), slice_size)); - std::advance(start, slice_size); - range = boost::make_iterator_range(start, end); - range_size = boost::distance(range); - slice_size = std::min(range_size, connection_buffer_size); - } - - if (!buffers->empty()) { - write_vec_impl(*buffers, callback, temporaries, buffers); - } - } - - template - void write_vec_impl(ConstBufferSeq const & seq - ,Callback const & callback - ,shared_array_list temporaries - ,shared_buffers buffers) - { - lock_guard lock(headers_mutex); - if (error_encountered) - boost::throw_exception(boost::system::system_error(*error_encountered)); - - boost::function callback_function = - callback; - - boost::function continuation = boost::bind( - &async_connection::template write_vec_impl > - ,async_connection::shared_from_this() - ,seq, callback_function, temporaries, buffers - ); - - if (!headers_already_sent && !headers_in_progress) { - write_headers_only(continuation); - return; - } else if (headers_in_progress && !headers_already_sent) { - pending_actions.push_back(continuation); - return; - } - - asio::async_write( - socket_ - ,seq - ,boost::bind( - &async_connection::handle_write - ,async_connection::shared_from_this() - ,callback_function - ,temporaries - ,buffers - ,asio::placeholders::error - ,asio::placeholders::bytes_transferred) - ); - } - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 */ - diff --git a/boost/network/protocol/http/server/sync_connection.hpp b/boost/network/protocol/http/server/sync_connection.hpp deleted file mode 100644 index 32d562b93..000000000 --- a/boost/network/protocol/http/server/sync_connection.hpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2009 (c) Dean Michael Berris -// Copyright 2009 (c) Tarroo, Inc. -// Adapted from Christopher Kholhoff's Boost.Asio Example, released under -// the Boost Software License, Version 1.0. (See acccompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ -#define BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ - -#ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE -#define BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 1024uL -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct sync_connection : boost::enable_shared_from_this > { - - sync_connection(boost::asio::io_service & service, Handler & handler) - : service_(service) - , handler_(handler) - , socket_(service_) - , wrapper_(service_) - { - } - - boost::asio::ip::tcp::socket & socket() { - return socket_; - } - - void start() { - // This is HTTP so we really want to just - // read and parse a request that's incoming - // and then pass that request object to the - // handler_ instance. - // - using boost::asio::ip::tcp; - boost::system::error_code option_error; - socket_.set_option(tcp::no_delay(true), option_error); - if (option_error) handler_.log(boost::system::system_error(option_error).what()); - socket_.async_read_some( - boost::asio::buffer(buffer_), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_read_headers, - sync_connection::shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ) - ) - ); - } - - private: - - struct is_content_length { - template - bool operator()(Header const & header) { - return boost::to_lower_copy(header.name) == "content-length"; - } - }; - - void handle_read_headers(boost::system::error_code const &ec, size_t bytes_transferred) { - if (!ec) { - request_.source = socket_.remote_endpoint().address().to_string(); - boost::tribool done; - buffer_type::iterator new_start; - tie(done,new_start) = parser_.parse_headers(request_, buffer_.data(), buffer_.data() + bytes_transferred); - if (done) { - if (request_.method[0] == 'P') { - // look for the content-length header - typename std::vector::type >::iterator it = - std::find_if( - request_.headers.begin(), - request_.headers.end(), - is_content_length() - ); - if (it == request_.headers.end()) { - response_= basic_response::stock_reply(basic_response::bad_request); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - return; - } - - size_t content_length = 0; - - try { - content_length = boost::lexical_cast(it->value); - } catch (...) { - response_= basic_response::stock_reply(basic_response::bad_request); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - return; - } - - if (content_length != 0) { - if (new_start != (buffer_.begin() + bytes_transferred)) { - request_.body.append(new_start, buffer_.begin() + bytes_transferred); - content_length -= std::distance(new_start, buffer_.begin() + bytes_transferred); - } - if (content_length > 0) { - socket_.async_read_some( - boost::asio::buffer(buffer_), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_read_body_contents, - sync_connection::shared_from_this(), - boost::asio::placeholders::error, - content_length, - boost::asio::placeholders::bytes_transferred - ) - ) - ); - return; - } - } - - handler_(request_, response_); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - } else { - handler_(request_, response_); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - } - } else if (!done) { - response_= basic_response::stock_reply(basic_response::bad_request); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - } else { - socket_.async_read_some( - boost::asio::buffer(buffer_), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_read_headers, - sync_connection::shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ) - ) - ); - } - } - // TODO Log the error? - } - - void handle_read_body_contents(boost::system::error_code const & ec, size_t bytes_to_read, size_t bytes_transferred) { - if (!ec) { - size_t difference = bytes_to_read - bytes_transferred; - buffer_type::iterator start = buffer_.begin(), - past_end = start; - std::advance(past_end, (std::min)(bytes_to_read,bytes_transferred)); - request_.body.append(buffer_.begin(), past_end); - if (difference == 0) { - handler_(request_, response_); - boost::asio::async_write( - socket_, - response_.to_buffers(), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_write, - sync_connection::shared_from_this(), - boost::asio::placeholders::error - ) - ) - ); - } else { - socket_.async_read_some( - boost::asio::buffer(buffer_), - wrapper_.wrap( - boost::bind( - &sync_connection::handle_read_body_contents, - sync_connection::shared_from_this(), - boost::asio::placeholders::error, - difference, - boost::asio::placeholders::bytes_transferred - ) - ) - ); - } - } - // TODO Log the error? - } - - void handle_write(boost::system::error_code const & ec) { - if (!ec) { - using boost::asio::ip::tcp; - boost::system::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_receive, ignored_ec); - } - } - - boost::asio::io_service & service_; - Handler & handler_; - boost::asio::ip::tcp::socket socket_; - boost::asio::io_service::strand wrapper_; - - typedef boost::array buffer_type; - buffer_type buffer_; - typedef basic_request_parser request_parser; - request_parser parser_; - basic_request request_; - basic_response response_; - }; - - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ - diff --git a/boost/network/protocol/http/support/is_http.hpp b/boost/network/protocol/http/support/is_http.hpp deleted file mode 100644 index 163c3f5f2..000000000 --- a/boost/network/protocol/http/support/is_http.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 -#define BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct is_http : mpl::false_ {}; - - template - struct is_http::type> : mpl::true_ {}; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 diff --git a/boost/network/protocol/http/support/is_server.hpp b/boost/network/protocol/http/support/is_server.hpp deleted file mode 100644 index 067e16c08..000000000 --- a/boost/network/protocol/http/support/is_server.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 -#define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct is_server : mpl::false_ {}; - - template - struct is_server::type> : mpl::true_ {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 */ diff --git a/boost/network/protocol/http/support/is_simple.hpp b/boost/network/protocol/http/support/is_simple.hpp deleted file mode 100644 index 730648f54..000000000 --- a/boost/network/protocol/http/support/is_simple.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 -#define BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct is_simple : mpl::false_ {}; - - template - struct is_simple::type> : mpl::true_ {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ diff --git a/boost/network/protocol/http/support/sync_only.hpp b/boost/network/protocol/http/support/sync_only.hpp deleted file mode 100644 index c9238c254..000000000 --- a/boost/network/protocol/http/support/sync_only.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 -#define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct sync_only : - mpl::inherit_linearly< - typename mpl::replace_if< - typename tags::components::type, - is_same, - tags::sync - >::type - , mpl::inherit - > - {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 */ diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp deleted file mode 100644 index 93db37a69..000000000 --- a/boost/network/protocol/http/tags.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 -#define BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { namespace tags { - - struct http { typedef mpl::true_::type is_http; }; - struct keepalive { typedef mpl::true_::type is_keepalive; }; - struct simple { typedef mpl::true_::type is_simple; }; - struct server { typedef mpl::true_::type is_server; }; - struct client { typedef mpl::true_::type is_client; }; - - using namespace boost::network::tags; - - template - struct components; - - typedef mpl::vector http_default_8bit_tcp_resolve_tags; - typedef mpl::vector http_default_8bit_udp_resolve_tags; - typedef mpl::vector http_keepalive_8bit_tcp_resolve_tags; - typedef mpl::vector http_keepalive_8bit_udp_resolve_tags; - typedef mpl::vector http_async_8bit_udp_resolve_tags; - typedef mpl::vector http_async_8bit_tcp_resolve_tags; - typedef mpl::vector http_server_tags; - typedef mpl::vector http_async_server_tags; - - BOOST_NETWORK_DEFINE_TAG(http_default_8bit_tcp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_keepalive_8bit_tcp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_keepalive_8bit_udp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_async_8bit_udp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_async_8bit_tcp_resolve); - BOOST_NETWORK_DEFINE_TAG(http_server); - BOOST_NETWORK_DEFINE_TAG(http_async_server); - -} /* tags */ - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_TAGS_HPP_20101019 */ diff --git a/boost/network/protocol/http/traits.hpp b/boost/network/protocol/http/traits.hpp deleted file mode 100644 index b527a31cf..000000000 --- a/boost/network/protocol/http/traits.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP - -// Convenience header for including different traits implementations. -#include -//#include -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP diff --git a/boost/network/protocol/http/traits/connection_keepalive.hpp b/boost/network/protocol/http/traits/connection_keepalive.hpp deleted file mode 100644 index 55d929020..000000000 --- a/boost/network/protocol/http/traits/connection_keepalive.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct connection_keepalive : is_keepalive {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 - diff --git a/boost/network/protocol/http/traits/connection_policy.hpp b/boost/network/protocol/http/traits/connection_policy.hpp deleted file mode 100644 index 6e35570cd..000000000 --- a/boost/network/protocol/http/traits/connection_policy.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct unsupported_tag; - - template - struct connection_policy - { - typedef unsupported_tag type; - }; - - template - struct connection_policy >::type> - { - typedef async_connection_policy type; - }; - - template - struct connection_policy, mpl::not_ > > >::type> - { - typedef simple_connection_policy type; - }; - - template - struct connection_policy, mpl::not_ > > >::type> - { - typedef pooled_connection_policy type; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_CONNECTION_POLICY_20091214 - diff --git a/boost/network/protocol/http/traits/delegate_factory.hpp b/boost/network/protocol/http/traits/delegate_factory.hpp deleted file mode 100644 index 714fc590e..000000000 --- a/boost/network/protocol/http/traits/delegate_factory.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace http { - -namespace impl { - -template -struct connection_delegate_factory; - -} /* impl */ - -template struct unsupported_tag; - -template -struct delegate_factory { - typedef unsupported_tag type; -}; - -template -struct delegate_factory >::type> { - typedef impl::connection_delegate_factory type; -}; - -} /* http */ -} /* network */ -} /* boost */ - - - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/protocol/http/traits/impl/chunk_cache.ipp b/boost/network/protocol/http/traits/impl/chunk_cache.ipp deleted file mode 100644 index 724b13011..000000000 --- a/boost/network/protocol/http/traits/impl/chunk_cache.ipp +++ /dev/null @@ -1,36 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP - -#include -#include - -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct chunk_cache { - // TODO define the allocator using an allocator_traits? - typedef std::list< - std::vector< - typename char_::type - > - > type; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CHUNK_CACHE_CONTAINER_IPP - - diff --git a/boost/network/protocol/http/traits/impl/content.ipp b/boost/network/protocol/http/traits/impl/content.ipp deleted file mode 100644 index a48ff77e3..000000000 --- a/boost/network/protocol/http/traits/impl/content.ipp +++ /dev/null @@ -1,44 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct content { - static char const * type_html() { - static char const * const TYPE_HTML = "text/html"; - return TYPE_HTML; - }; - - static char const * type_text() { - static char const * const TYPE_TEXT = "text/plain"; - return TYPE_TEXT; - }; - - static char const * type_xml() { - static char const * const TYPE_XML = "text/xml"; - return TYPE_XML; - }; - - static char const * type_urlencoded() { - static char const * const TYPE_URLENCODED = "application/x-www-form-urlencoded"; - return TYPE_URLENCODED; - }; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_CONTENT_IPP - diff --git a/boost/network/protocol/http/traits/impl/cookie_name.ipp b/boost/network/protocol/http/traits/impl/cookie_name.ipp deleted file mode 100644 index 5389b5a67..000000000 --- a/boost/network/protocol/http/traits/impl/cookie_name.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct cookie_name { - static boost::uint32_t const MAX = 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_NAME_IPP - diff --git a/boost/network/protocol/http/traits/impl/cookie_value.ipp b/boost/network/protocol/http/traits/impl/cookie_value.ipp deleted file mode 100644 index 9905b67b4..000000000 --- a/boost/network/protocol/http/traits/impl/cookie_value.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct cookie_value { - static boost::uint32_t const MAX = 1024u * 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_COOKIE_VALUE_IPP - diff --git a/boost/network/protocol/http/traits/impl/cookies_container.ipp b/boost/network/protocol/http/traits/impl/cookies_container.ipp deleted file mode 100644 index d6dbe74f1..000000000 --- a/boost/network/protocol/http/traits/impl/cookies_container.ipp +++ /dev/null @@ -1,32 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP - -#include - -#include - -namespace boost { namespace network { namespace http { - - template - struct cookies_container { - typedef std::multimap< - typename string::type, - typename string::type - > type; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_COOKIES_CONTAINER_IPP - - diff --git a/boost/network/protocol/http/traits/impl/delimiters.ipp b/boost/network/protocol/http/traits/impl/delimiters.ipp deleted file mode 100644 index a66a2415e..000000000 --- a/boost/network/protocol/http/traits/impl/delimiters.ipp +++ /dev/null @@ -1,40 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP - -#include - -namespace boost { namespace network { namespace http { - - // specialize on the tags::http_default_8bit_tcp_resolve type - template <> - struct delimiters { - static char const * string_crlf() { - static char const * const CRLF = "\x0D\x0A"; - return CRLF; - }; - - static char const * string_http_version() { - static char const * const HTTP_VERSION = "HTTP/1.1"; - return HTTP_VERSION; - }; - - static char const * header_name_value_delimiter() { - static char const * const HEADER_NAME_VALUE_DELIMITER = ": "; - return HEADER_NAME_VALUE_DELIMITER; - }; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_DELIMITERS_IPP - diff --git a/boost/network/protocol/http/traits/impl/header_name.ipp b/boost/network/protocol/http/traits/impl/header_name.ipp deleted file mode 100644 index 66b502753..000000000 --- a/boost/network/protocol/http/traits/impl/header_name.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct header_name { - static boost::uint32_t const MAX = 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_NAME_IPP - diff --git a/boost/network/protocol/http/traits/impl/header_value.ipp b/boost/network/protocol/http/traits/impl/header_value.ipp deleted file mode 100644 index 2dfce49b6..000000000 --- a/boost/network/protocol/http/traits/impl/header_value.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct header_value { - static boost::uint32_t const MAX = 1024u * 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HEADER_VALUE_IPP - diff --git a/boost/network/protocol/http/traits/impl/headers.ipp b/boost/network/protocol/http/traits/impl/headers.ipp deleted file mode 100644 index 1ef11abf6..000000000 --- a/boost/network/protocol/http/traits/impl/headers.ipp +++ /dev/null @@ -1,85 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct headers_ { - static char const * host() { - static char const * const HOST = "Host"; - return HOST; - }; - - static char const * cookie() { - static char const * const COOKIE = "Cookie"; - return COOKIE; - }; - - static char const * set_cookie() { - static char const * const SET_COOKIE = "Set-Cookie"; - return SET_COOKIE; - }; - - static char const * connection() { - static char const * const CONNECTION = "Connection"; - return CONNECTION; - }; - - static char const * content_type() { - static char const * const CONTENT_TYPE = "Content-Type"; - return CONTENT_TYPE; - }; - - static char const * content_length() { - static char const * const CONTENT_LENGTH = "Content-Length"; - return CONTENT_LENGTH; - }; - - static char const * content_location() { - static char const * const CONTENT_LOCATION = "Content-Location"; - return CONTENT_LOCATION; - }; - - static char const * last_modified() { - static char const * const LAST_MODIFIED = "Last-Modified"; - return LAST_MODIFIED; - }; - - static char const * if_modified_since() { - static char const * const IF_MODIFIED_SINCE = "If-Modified-Since"; - return IF_MODIFIED_SINCE; - }; - - static char const * transfer_encoding() { - static char const * const TRANSFER_ENCODING = "Transfer-Encoding"; - return TRANSFER_ENCODING; - }; - - static char const * location() { - static char const * const LOCATION = "Location"; - return LOCATION; - }; - - static char const * authorization() { - static char const * const AUTHORIZATION = "Authorization"; - return AUTHORIZATION; - }; - - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_HPP - diff --git a/boost/network/protocol/http/traits/impl/headers_container.ipp b/boost/network/protocol/http/traits/impl/headers_container.ipp deleted file mode 100644 index 42f455da7..000000000 --- a/boost/network/protocol/http/traits/impl/headers_container.ipp +++ /dev/null @@ -1,45 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - template <> - struct headers_container { - - // Moving implementation from original - // message_traits implementation by - // Atomic Labs, Inc. - // -- - // returns true if str1 < str2 (ignoring case) - struct is_less_ignore_case { - inline bool operator() ( - string::type const & str1, - string::type const & str2) const { - return to_lower_copy(str1) < to_lower_copy(str2); - }; - }; - - typedef std::multimap< - string::type, - string::type, - is_less_ignore_case> type; - }; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HEADERS_CONTAINER_IPP - diff --git a/boost/network/protocol/http/traits/impl/method.ipp b/boost/network/protocol/http/traits/impl/method.ipp deleted file mode 100644 index 52af0d19d..000000000 --- a/boost/network/protocol/http/traits/impl/method.ipp +++ /dev/null @@ -1,28 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct method { - static boost::uint32_t const MAX = 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_METHOD_IPP - - - diff --git a/boost/network/protocol/http/traits/impl/post_content.ipp b/boost/network/protocol/http/traits/impl/post_content.ipp deleted file mode 100644 index 1a02c38c7..000000000 --- a/boost/network/protocol/http/traits/impl/post_content.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct post_content { - static boost::uint32_t const MAX = 1024u * 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_POST_CONTENT_IPP - diff --git a/boost/network/protocol/http/traits/impl/query_container.ipp b/boost/network/protocol/http/traits/impl/query_container.ipp deleted file mode 100644 index deefc7e7c..000000000 --- a/boost/network/protocol/http/traits/impl/query_container.ipp +++ /dev/null @@ -1,31 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP - -#include - -#include - -namespace boost { namespace network { namespace http { - - template - struct query_container { - typedef std::multimap< - typename string::type, - typename string::type - > type; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_QUERY_CONTAINER_IPP - diff --git a/boost/network/protocol/http/traits/impl/query_name.ipp b/boost/network/protocol/http/traits/impl/query_name.ipp deleted file mode 100644 index 35a12ac4f..000000000 --- a/boost/network/protocol/http/traits/impl/query_name.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct query_name { - static boost::uint32_t const MAX = 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_NAME_IPP - diff --git a/boost/network/protocol/http/traits/impl/query_string.ipp b/boost/network/protocol/http/traits/impl/query_string.ipp deleted file mode 100644 index 98e1b3cee..000000000 --- a/boost/network/protocol/http/traits/impl/query_string.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct query_string { - static boost::uint32_t const MAX = 1024u * 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_STRING_IPP - diff --git a/boost/network/protocol/http/traits/impl/query_value.ipp b/boost/network/protocol/http/traits/impl/query_value.ipp deleted file mode 100644 index 64343be0c..000000000 --- a/boost/network/protocol/http/traits/impl/query_value.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct query_value { - static boost::uint32_t const MAX = 1024u * 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_QUERY_VALUE_IPP - diff --git a/boost/network/protocol/http/traits/impl/request_methods.ipp b/boost/network/protocol/http/traits/impl/request_methods.ipp deleted file mode 100644 index b698dbe7c..000000000 --- a/boost/network/protocol/http/traits/impl/request_methods.ipp +++ /dev/null @@ -1,49 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct request_methods { - static char const * head() { - static char const * const HEAD = "HEAD"; - return HEAD; - }; - - static char const * get() { - static char const * const GET = "GET"; - return GET; - }; - - static char const * put() { - static char const * const PUT = "PUT"; - return PUT; - }; - - static char const * post() { - static char const * const POST = "POST"; - return POST; - }; - - static char const * delete_() { - static char const * const DELETE_ = "DELETE"; - return DELETE_; - }; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_REQUEST_METHODS_IPP - diff --git a/boost/network/protocol/http/traits/impl/resource.ipp b/boost/network/protocol/http/traits/impl/resource.ipp deleted file mode 100644 index 897cbf3b3..000000000 --- a/boost/network/protocol/http/traits/impl/resource.ipp +++ /dev/null @@ -1,26 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct resource { - static boost::uint32_t const MAX = 1024u * 256u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_RESOURCE_IPP - diff --git a/boost/network/protocol/http/traits/impl/response_code.ipp b/boost/network/protocol/http/traits/impl/response_code.ipp deleted file mode 100644 index 42f7815ae..000000000 --- a/boost/network/protocol/http/traits/impl/response_code.ipp +++ /dev/null @@ -1,42 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP - -#include -#include - -namespace boost { namespace network { namespace http { - - /* This glob doesn't have a specialization on the tags::http_default_8bit_tcp_resolve - * yet because it doesn't need to define different behaviour/types - * on different message tags -- for example, it doesn't need to - * determine the type or change the values of the data no matter - * what the tag type is provided. - */ - template - struct response_code { - static boost::uint16_t const OK = 200u; - static boost::uint16_t const CREATED = 201u; - static boost::uint16_t const NO_CONTENT = 204u; - static boost::uint16_t const UNAUTHORIZED = 401u; - static boost::uint16_t const FORBIDDEN = 403u; - static boost::uint16_t const NOT_FOUND = 404u; - static boost::uint16_t const METHOD_NOT_ALLOWED = 405u; - static boost::uint16_t const NOT_MODIFIED = 304u; - static boost::uint16_t const BAD_REQUEST = 400u; - static boost::uint16_t const SERVER_ERROR = 500u; - static boost::uint16_t const NOT_IMPLEMENTED = 501u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_CODE_IPP diff --git a/boost/network/protocol/http/traits/impl/response_message.ipp b/boost/network/protocol/http/traits/impl/response_message.ipp deleted file mode 100644 index 7493b19f8..000000000 --- a/boost/network/protocol/http/traits/impl/response_message.ipp +++ /dev/null @@ -1,80 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct response_message { - static char const * ok() { - static char const * const OK = "OK"; - return OK; - }; - - static char const * created() { - static char const * const CREATED = "Created"; - return CREATED; - }; - - static char const * no_content() { - static char const * const NO_CONTENT = "NO Content"; - return NO_CONTENT; - }; - - static char const * unauthorized() { - static char const * const UNAUTHORIZED = "Unauthorized"; - return UNAUTHORIZED; - }; - - static char const * forbidden() { - static char const * const FORBIDDEN = "Fobidden"; - return FORBIDDEN; - }; - - static char const * not_found() { - static char const * const NOT_FOUND = "Not Found"; - return NOT_FOUND; - }; - - static char const * method_not_allowed() { - static char const * const METHOD_NOT_ALLOWED = "Method Not Allowed"; - return METHOD_NOT_ALLOWED; - }; - - static char const * not_modified() { - static char const * const NOT_MODIFIED = "Not Modified"; - return NOT_MODIFIED; - }; - - static char const * bad_request() { - static char const * const BAD_REQUEST = "Bad Request"; - return BAD_REQUEST; - }; - - static char const * server_error() { - static char const * const SERVER_ERROR = "Server Error"; - return SERVER_ERROR; - }; - - static char const * not_implemented() { - static char const * const NOT_IMPLEMENTED = "Not Implemented"; - return NOT_IMPLEMENTED; - }; - - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_RESPONSE_MESSAGE_IPP - diff --git a/boost/network/protocol/http/traits/impl/status_message.ipp b/boost/network/protocol/http/traits/impl/status_message.ipp deleted file mode 100644 index 71c77d462..000000000 --- a/boost/network/protocol/http/traits/impl/status_message.ipp +++ /dev/null @@ -1,27 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP - -#include - -namespace boost { namespace network { namespace http { - - template <> - struct status_message_text { - static boost::uint32_t const MAX = 1024u; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_STATUS_MESSAGE_IPP - - diff --git a/boost/network/protocol/http/traits/message_traits.hpp b/boost/network/protocol/http/traits/message_traits.hpp deleted file mode 100644 index deb41df42..000000000 --- a/boost/network/protocol/http/traits/message_traits.hpp +++ /dev/null @@ -1,63 +0,0 @@ - -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Some changes Copyright (c) Dean Michael Berris 2008 - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_TRAITS_HPP - -namespace boost { namespace network { namespace http { - - template - struct delimiters; - - template - struct headers_; - - template - struct content; - - template - struct request_methods; - - template - struct response_message; - - template - struct response_code; - - template - struct query_container; - - template - struct cookies_container; - - template - struct chunk_cache; - -} // namespace http - -} // namespace network - -} // namespace boost - -// Defer definition in implementation files -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP diff --git a/boost/network/protocol/http/traits/parser_traits.hpp b/boost/network/protocol/http/traits/parser_traits.hpp deleted file mode 100644 index c5465e544..000000000 --- a/boost/network/protocol/http/traits/parser_traits.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// This file is part of the Boost Network library -// Based on the Pion Network Library (r421) -// Copyright Atomic Labs, Inc. 2007-2008 -// See http://cpp-netlib.sourceforge.net for library home page. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Some changes Copyright 2008 (c) Dean Michael Berris - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP - -namespace boost { namespace network { namespace http { - - template - struct status_message_text; - - template - struct method; - - template - struct resource; - - template - struct query_string; - - template - struct header_name; - - template - struct header_value; - - template - struct query_name; - - template - struct query_value; - - template - struct cookie_name; - - template - struct cookie_value; - - template - struct post_content; - -} // namespace http - -} // namespace network - -} // namespace boost - -// Include implementation files -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_TRAITS_HPP - diff --git a/boost/network/protocol/http/traits/resolver.hpp b/boost/network/protocol/http/traits/resolver.hpp deleted file mode 100644 index c2a31fe68..000000000 --- a/boost/network/protocol/http/traits/resolver.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct unsupported_tag; - - template - struct resolver : - mpl::if_< - mpl::and_< - is_tcp, - is_http - >, - boost::asio::ip::tcp::resolver, - typename mpl::if_< - mpl::and_< - is_udp, - is_http - >, - boost::asio::ip::udp::resolver, - unsupported_tag - >::type - > - { - BOOST_STATIC_ASSERT(( - mpl::not_< - mpl::and_< - is_udp, - is_tcp - > - >::value - )); - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_RESOLVER_20091214 - diff --git a/boost/network/protocol/http/traits/resolver_policy.hpp b/boost/network/protocol/http/traits/resolver_policy.hpp deleted file mode 100644 index 50359a90a..000000000 --- a/boost/network/protocol/http/traits/resolver_policy.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 -#define BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct unsupported_tag; - - template - struct resolver_policy : - mpl::if_< - mpl::and_< is_async,is_http >, - policies::async_resolver, - typename mpl::if_, - policies::sync_resolver, - unsupported_tag - >::type - > - {}; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_RESOLVER_POLICY_20091214 - diff --git a/boost/network/protocol/http/traits/vector.hpp b/boost/network/protocol/http/traits/vector.hpp deleted file mode 100644 index 61b2f5b2f..000000000 --- a/boost/network/protocol/http/traits/vector.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 -#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 - -// Copyright (c) Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template <> - struct vector { - - template - struct apply { - typedef std::vector type; - }; - - }; - - template <> - struct vector { - - template - struct apply { - typedef std::vector type; - }; - - }; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_VECTOR_HPP_20101019 */ diff --git a/boost/network/support/is_async.hpp b/boost/network/support/is_async.hpp deleted file mode 100644 index d6e1f99f5..000000000 --- a/boost/network/support/is_async.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_20100608 -#define BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_20100608 - -// Copyright 2010 (c) Dean Michael Berris -// Copyright 2010 (c) Sinefunc, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template - struct is_async : mpl::false_ {}; - - template - struct is_async::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif //BOOST_NETWORK_SUPPORT_IS_ASYNC_HPP_2010608 diff --git a/boost/network/support/is_default_string.hpp b/boost/network/support/is_default_string.hpp deleted file mode 100644 index 2a0fd824e..000000000 --- a/boost/network/support/is_default_string.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Dean Michael Berris 2010 -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 -#define BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 - -#include -#include - -namespace boost { namespace network { - - template - struct is_default_string : mpl::false_ {}; - - template - struct is_default_string::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 diff --git a/boost/network/support/is_default_wstring.hpp b/boost/network/support/is_default_wstring.hpp deleted file mode 100644 index c414353e1..000000000 --- a/boost/network/support/is_default_wstring.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Dean Michael Berris 2010 -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_SUPPORT_WSTRING_CHECK_20100808 -#define BOOST_NETWORK_SUPPORT_WSTRING_CHECK_20100808 - -#include -#include - -namespace boost { namespace network { - - template - struct is_default_wstring : mpl::false_ {}; - - template - struct is_default_wstring::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 diff --git a/boost/network/support/is_keepalive.hpp b/boost/network/support/is_keepalive.hpp deleted file mode 100644 index 6607cd10f..000000000 --- a/boost/network/support/is_keepalive.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 -#define BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template - struct is_keepalive : mpl::false_ {}; - - template - struct is_keepalive::type> : mpl::true_ {}; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ diff --git a/boost/network/support/is_pod.hpp b/boost/network/support/is_pod.hpp deleted file mode 100644 index 5c1e1065c..000000000 --- a/boost/network/support/is_pod.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 -#define BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template - struct is_pod : mpl::false_ {}; - - template - struct is_pod::type> : mpl::true_ {}; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 */ diff --git a/boost/network/support/is_sync.hpp b/boost/network/support/is_sync.hpp deleted file mode 100644 index 0ff0f7130..000000000 --- a/boost/network/support/is_sync.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 -#define BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace boost { namespace network { - - template - struct is_sync : mpl::false_ {}; - - template - struct is_sync::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_IS_SYNC_HPP_20100623 - diff --git a/boost/network/support/is_tcp.hpp b/boost/network/support/is_tcp.hpp deleted file mode 100644 index c041f125f..000000000 --- a/boost/network/support/is_tcp.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 -#define BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct is_tcp : mpl::false_ {}; - - template - struct is_tcp::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 \ No newline at end of file diff --git a/boost/network/support/is_udp.hpp b/boost/network/support/is_udp.hpp deleted file mode 100644 index cacbc5e0e..000000000 --- a/boost/network/support/is_udp.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 -#define BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct is_udp : mpl::false_ {}; - - template - struct is_udp::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 \ No newline at end of file diff --git a/boost/network/support/pod_or_normal.hpp b/boost/network/support/pod_or_normal.hpp deleted file mode 100644 index fdfcf4c12..000000000 --- a/boost/network/support/pod_or_normal.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 -#define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { - - template - struct pod_or_normal { typedef tags::normal type; }; - - template - struct pod_or_normal::type> : tags::pod {}; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 */ diff --git a/boost/network/support/sync_only.hpp b/boost/network/support/sync_only.hpp deleted file mode 100644 index 4fbdde818..000000000 --- a/boost/network/support/sync_only.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 -#define BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 - -// Copyright Dean Michael Berris 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct sync_only : - mpl::inherit_linearly< - typename mpl::replace_if< - typename tags::components::type, - is_same, - tags::sync - >::type - , mpl::inherit - > - {}; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_SYNC_ONLY_HPP_20100927 */ diff --git a/boost/network/tags.hpp b/boost/network/tags.hpp deleted file mode 100644 index df74703a3..000000000 --- a/boost/network/tags.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright Dean Michael Berris 2008, 2009. -// Glyn Matthews 2009 -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_NETWORK_TAG_INCLUDED_20100808 -#define BOOST_NETWORK_TAG_INCLUDED_20100808 - -#include -#include -#include -#include - -namespace boost { namespace network { namespace tags { - - struct pod { typedef mpl::true_::type is_pod; }; - struct normal { typedef mpl::true_::type is_normal; }; - struct async { typedef mpl::true_::type is_async; }; - struct tcp { typedef mpl::true_::type is_tcp; }; - struct udp { typedef mpl::true_::type is_udp; }; - struct sync { typedef mpl::true_::type is_sync; }; - struct default_string - { typedef mpl::true_::type is_default_string; }; - struct default_wstring - { typedef mpl::true_::type is_default_wstring; }; - - template - struct components; - - // Tag Definition Macro Helper -#ifndef BOOST_NETWORK_DEFINE_TAG -#define BOOST_NETWORK_DEFINE_TAG(name) \ - struct name : mpl::inherit_linearly< \ - name##_tags, \ - mpl::inherit \ - >::type {}; \ - template <> struct components { \ - typedef name##_tags type; \ - }; -#endif // BOOST_NETWORK_DEFINE_TAG - - typedef default_string default_; - -} // namespace tags - -} // namespace network - -} // namespace boost - -#endif // __BOOST_NETWORK_TAGS_INC__ diff --git a/boost/network/traits/char.hpp b/boost/network/traits/char.hpp deleted file mode 100644 index 79e73441d..000000000 --- a/boost/network/traits/char.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Dean Michael Berris 2008, 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_TRAITS_CHAR_HPP -#define BOOST_NETWORK_TRAITS_CHAR_HPP - -#include -#include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct char_ - { - typedef unsupported_tag type; - }; - - template - struct char_ >::type> - { - typedef char type; - }; - - template - struct char_ >::type> - { - typedef wchar_t type; - }; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_TRAITS_CHAR_HPP diff --git a/boost/network/traits/headers_container.hpp b/boost/network/traits/headers_container.hpp deleted file mode 100644 index f852312d2..000000000 --- a/boost/network/traits/headers_container.hpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Glyn Matthews 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC__ -# define __BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC__ - -# include -# include -# include - -namespace boost { namespace network { - - template - struct headers_container { - typedef std::multimap< - typename string::type, - typename string::type - > type; - }; - -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_TRAITS_HEADERS_CONTAINER_INC__ diff --git a/boost/network/traits/istream.hpp b/boost/network/traits/istream.hpp deleted file mode 100644 index 7f50bb291..000000000 --- a/boost/network/traits/istream.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 -#define BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct istream - { - typedef unsupported_tag type; - }; - - template - struct istream >::type> - { - typedef std::istream type; - }; - - template - struct istream >::type> - { - typedef std::wistream type; - }; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_TRAITS_ISTREAM_HPP_20100924 */ diff --git a/boost/network/traits/istringstream.hpp b/boost/network/traits/istringstream.hpp deleted file mode 100644 index 776385b2a..000000000 --- a/boost/network/traits/istringstream.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Glyn Matthews 2009. -// Copyright (c) Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC -# define BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC - -# include -# include -#include -#include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct istringstream - { - typedef unsupported_tag type; - }; - - template - struct istringstream >::type> - { - typedef std::istringstream type; - }; - - template - struct istringstream >::type> - { - typedef std::basic_istringstream type; - }; - -} // namespace network - -} // namespace boost - - -#endif // BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC - diff --git a/boost/network/traits/ostream_iterator.hpp b/boost/network/traits/ostream_iterator.hpp deleted file mode 100644 index 1f40a7129..000000000 --- a/boost/network/traits/ostream_iterator.hpp +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 -#define BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 - -// Copyright 2010 (C) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct ostream_iterator; - - template - struct ostream_iterator : mpl::if_< - is_default_string, - std::ostream_iterator, - typename mpl::if_< - is_default_wstring, - std::ostream_iterator, - unsupported_tag - >::type - > {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_TRAITS_OSTREAM_ITERATOR_HPP_20100815 diff --git a/boost/network/traits/ostringstream.hpp b/boost/network/traits/ostringstream.hpp deleted file mode 100644 index 58e09a638..000000000 --- a/boost/network/traits/ostringstream.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Glyn Matthews 2009. -// Copyright (c) Dean Michael Berris 2009, 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC -# define BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC - -# include -# include -# include -# include -# include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct ostringstream - { - typedef unsupported_tag type; - }; - - template - struct ostringstream >::type> - { - typedef std::ostringstream type; - }; - - template - struct ostringstream >::type> - { - typedef std::wostringstream type; - }; - -} // namespace network - -} // namespace boost - - -#endif // BOOST_NETWORK_TRAITS_OSTRINGSTREAM_INC diff --git a/boost/network/traits/string.hpp b/boost/network/traits/string.hpp deleted file mode 100644 index 92cd88e6d..000000000 --- a/boost/network/traits/string.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Dean Michael Berris 2008, 2009. -// Glyn Matthews 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_NETWORK_TRAITS_STRING_INC -#define BOOST_NETWORK_TRAITS_STRING_INC - -# include -# include -# include -# include - -#ifndef BOOST_NETWORK_DEFAULT_STRING -#define BOOST_NETWORK_DEFAULT_STRING std::string -#endif - -#ifndef BOOST_NETWORK_DEFAULT_WSTRING -#define BOOST_NETWORK_DEFAULT_WSTRING std::wstring -#endif - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct string - { - typedef unsupported_tag type; - }; - - template - struct string >::type> - { - typedef BOOST_NETWORK_DEFAULT_STRING type; - }; - - template - struct string >::type> - { - typedef BOOST_NETWORK_DEFAULT_WSTRING type; - }; - -} // namespace network - -} // namespace boost - - -#endif // BOOST_NETWORK_TRAITS_STRING_INC diff --git a/boost/network/traits/vector.hpp b/boost/network/traits/vector.hpp deleted file mode 100644 index 210a13c68..000000000 --- a/boost/network/traits/vector.hpp +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Dean Michael Berris 2008, 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_TRAITS_VECTOR_HPP -#define BOOST_NETWORK_TRAITS_VECTOR_HPP - -#include -#include - -namespace boost { namespace network { - - template - struct unsupported_tag; - - template - struct vector { - - template - struct apply : - mpl::if_< - is_default_string - , std::vector - , unsupported_tag - > - {}; - - }; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_TRAITS_VECTOR_HPP - diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp deleted file mode 100644 index 0462150f5..000000000 --- a/boost/network/uri/accessors.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ -# define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ - - -# include -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace details { -template < - typename Map - > -struct key_value_sequence - : spirit::qi::grammar -{ - typedef typename Map::key_type key_type; - typedef typename Map::mapped_type mapped_type; - typedef std::pair pair_type; - - key_value_sequence() - : key_value_sequence::base_type(query) - { - query = pair >> *((spirit::qi::lit(';') | '&') >> pair); - pair = key >> -('=' >> value); - key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("a-zA-Z_0-9/%"); - value = +spirit::qi::char_("a-zA-Z_0-9/%"); - } - - spirit::qi::rule query; - spirit::qi::rule pair; - spirit::qi::rule key; - spirit::qi::rule value; -}; -} // namespace details - -template < - class Map - > -inline -Map &query_map(const uri &uri_, Map &map) { - const uri::string_type range = uri_.query(); - details::key_value_sequence parser; - spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); - return map; -} - -inline -uri::string_type username(const uri &uri_) { - const uri::string_type user_info = uri_.user_info(); - uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); - for (; it != end; ++it) { - if (*it == ':') { - break; - } - } - return uri::string_type(boost::begin(user_info), it); -} - -inline -uri::string_type password(const uri &uri_) { - const uri::string_type user_info = uri_.user_info(); - uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); - for (; it != end; ++it) { - if (*it == ':') { - ++it; - break; - } - } - return uri::string_type(it, boost::end(user_info)); -} - -inline -uri::string_type decoded_path(const uri &uri_) { - const uri::string_type path = uri_.path(); - uri::string_type decoded_path; - decode(path, std::back_inserter(decoded_path)); - return decoded_path; -} - -inline -uri::string_type decoded_query(const uri &uri_) { - const uri::string_type query = uri_.query(); - uri::string_type decoded_query; - decode(query, std::back_inserter(decoded_query)); - return decoded_query; -} - -inline -uri::string_type decoded_fragment(const uri &uri_) { - const uri::string_type fragment = uri_.fragment(); - uri::string_type decoded_fragment; - decode(fragment, std::back_inserter(decoded_fragment)); - return decoded_fragment; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ diff --git a/boost/network/uri/builder.hpp b/boost/network/uri/builder.hpp deleted file mode 100644 index 7f0103e36..000000000 --- a/boost/network/uri/builder.hpp +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) Glyn Matthews 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_BUILDER_INC__ -# define __BOOST_NETWORK_URI_BUILDER_INC__ - - -# include -# include - - -namespace boost { -namespace network { -namespace uri { -class builder { - - typedef uri::string_type string_type; - -public: - - builder(uri &uri_) - : uri_(uri_) { - - } - - builder &set_scheme(const string_type &scheme) { - uri_.uri_.append(scheme); - if (opaque_schemes::exists(scheme)) { - uri_.uri_.append(":"); - } - else { - uri_.uri_.append("://"); - } - uri_.parse(); - return *this; - } - - builder &scheme(const string_type &scheme) { - return set_scheme(scheme); - } - - builder &set_user_info(const string_type &user_info) { - uri_.uri_.append(user_info); - uri_.uri_.append("@"); - uri_.parse(); - return *this; - } - - builder &user_info(const string_type &user_info) { - return set_user_info(user_info); - } - - builder &set_host(const string_type &host) { - uri_.uri_.append(host); - uri_.parse(); - return *this; - } - - builder &host(const string_type &host) { - return set_host(host); - } - - builder &set_host(const asio::ip::address &address) { - uri_.uri_.append(address.to_string()); - uri_.parse(); - return *this; - } - - builder &host(const asio::ip::address &host) { - return set_host(host); - } - - builder &set_host(const asio::ip::address_v4 &address) { - uri_.uri_.append(address.to_string()); - uri_.parse(); - return *this; - } - - builder &host(const asio::ip::address_v4 &host) { - return set_host(host); - } - - builder &set_host(const asio::ip::address_v6 &address) { - uri_.uri_.append("["); - uri_.uri_.append(address.to_string()); - uri_.uri_.append("]"); - uri_.parse(); - return *this; - } - - builder &host(const asio::ip::address_v6 &host) { - return set_host(host); - } - - builder &set_port(const string_type &port) { - uri_.uri_.append(":"); - uri_.uri_.append(port); - uri_.parse(); - return *this; - } - - builder &port(const string_type &port) { - return set_port(port); - } - - builder &port(uint16_t port) { - return set_port(boost::lexical_cast(port)); - } - - builder &set_path(const string_type &path) { - uri_.uri_.append(path); - uri_.parse(); - return *this; - } - - builder &path(const string_type &path) { - return set_path(path); - } - - builder &encoded_path(const string_type &path) { - string_type encoded_path; - encode(path, std::back_inserter(encoded_path)); - return set_path(encoded_path); - } - - builder &set_query(const string_type &query) { - uri_.uri_.append("?"); - uri_.uri_.append(query); - uri_.parse(); - return *this; - } - - builder &set_query(const string_type &key, const string_type &value) { - if (!uri_.query_range()) - { - uri_.uri_.append("?"); - } - else - { - uri_.uri_.append("&"); - } - uri_.uri_.append(key); - uri_.uri_.append("="); - uri_.uri_.append(value); - uri_.parse(); - return *this; - } - - builder &query(const string_type &query) { - return set_query(query); - } - - builder &query(const string_type &key, const string_type &value) { - return set_query(key, value); - } - - builder &set_fragment(const string_type &fragment) { - uri_.uri_.append("#"); - uri_.uri_.append(fragment); - uri_.parse(); - return *this; - } - - builder &fragment(const string_type &fragment) { - return set_fragment(fragment); - } - -private: - - uri &uri_; - -}; -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_BUILDER_INC__ diff --git a/boost/network/uri/config.hpp b/boost/network/uri/config.hpp deleted file mode 100644 index 0cb9e17a9..000000000 --- a/boost/network/uri/config.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Glyn Matthews 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_CONFIG_INC__ -# define __BOOST_NETWORK_URI_CONFIG_INC__ - - -# include -# include - -# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URI_DYN_LINK) -# define BOOST_URI_DECL -# else -# define BOOST_URI_DECL -# endif // defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URI_DYN_LINK) - - -#endif // __BOOST_NETWORK_URI_CONFIG_INC__ diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp deleted file mode 100644 index 2f950dfad..000000000 --- a/boost/network/uri/decode.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DECODE_INC__ -# define __BOOST_NETWORK_URI_DECODE_INC__ - - -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -template < - typename CharT - > -CharT letter_to_hex(CharT in) -{ - switch (in) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return in - '0'; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - return in + 10 - 'a'; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - return in + 10 - 'A'; - } - return CharT(); -} -} // namespace detail - -template < - class InputIterator, - class OutputIterator - > -OutputIterator decode(const InputIterator &in_begin, - const InputIterator &in_end, - const OutputIterator &out_begin) { - typedef typename boost::iterator_value::type value_type; - - InputIterator it = in_begin; - OutputIterator out = out_begin; - while (it != in_end) { - if (*it == '%') - { - ++it; - value_type v0 = detail::letter_to_hex(*it); - ++it; - value_type v1 = detail::letter_to_hex(*it); - ++it; - *out++ = 0x10 * v0 + v1; - } - else - { - *out++ = *it++; - } - } - return out; -} - -template < - class SinglePassRange, - class OutputIterator - > -inline -OutputIterator decode(const SinglePassRange &range, - const OutputIterator &out) { - return decode(boost::begin(range), boost::end(range), out); -} - -inline -std::string decoded(const std::string &input) { - std::string decoded; - decode(input, std::back_inserter(decoded)); - return decoded; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DECODE_INC__ diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp deleted file mode 100644 index f9c89f8a1..000000000 --- a/boost/network/uri/detail/uri_parts.hpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -# define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ - - -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -template < - class FwdIter - > -struct hierarchical_part { - optional > user_info; - optional > host; - optional > port; - optional > path; - - FwdIter begin() const { - return boost::begin(user_info); - } - - FwdIter end() const { - return boost::end(path); - } - - void update() { - if (!user_info) { - if (host) { - user_info = iterator_range(boost::begin(host.get()), - boost::begin(host.get())); - } - else if (path) { - user_info = iterator_range(boost::begin(path.get()), - boost::begin(path.get())); - } - } - - if (!host) { - host = iterator_range(boost::begin(path.get()), - boost::begin(path.get())); - } - - if (!port) { - port = iterator_range(boost::end(host.get()), - boost::end(host.get())); - } - - if (!path) { - path = iterator_range(boost::end(port.get()), - boost::end(port.get())); - } - } - -}; - -template < - class FwdIter - > -struct uri_parts { - iterator_range scheme; - hierarchical_part hier_part; - optional > query; - optional > fragment; - - FwdIter begin() const { - return boost::begin(scheme); - } - - FwdIter end() const { - return boost::end(fragment); - } - - void update() { - - hier_part.update(); - - if (!query) { - query = iterator_range(boost::end(hier_part.path.get()), - boost::end(hier_part.path.get())); - } - - if (!fragment) { - fragment = iterator_range(boost::end(query.get()), - boost::end(query.get())); - } - } -}; -} // namespace detail -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp deleted file mode 100644 index eb5beaa12..000000000 --- a/boost/network/uri/directives.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -inline -uri &operator << (uri &uri_, const uri &root_uri) { - if (empty(uri_) && valid(root_uri)) { - uri_.append(boost::begin(root_uri), boost::end(root_uri)); - } - return uri_; -} - -template < - class Directive - > -inline -uri &operator << (uri &uri_, const Directive &directive) { - directive(uri_); - return uri_; -} -} // namespace uri -} // namespace network -} // namespace boost - - -# include -# include -# include -# include -# include -# include -# include -# include - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_INC__ diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp deleted file mode 100644 index 189d4649c..000000000 --- a/boost/network/uri/directives/authority.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ - - -namespace boost { -namespace network { -namespace uri { -struct authority_directive { - - explicit authority_directive(const std::string &authority) - : authority(authority) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(authority); - } - - std::string authority; - -}; - -inline -authority_directive authority(const std::string &authority) { - return authority_directive(authority); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp deleted file mode 100644 index 2342f7079..000000000 --- a/boost/network/uri/directives/fragment.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ - - -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct fragment_directive { - - explicit fragment_directive(const std::string &fragment) - : fragment(fragment) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append("#"); - uri.append(fragment); - } - - std::string fragment; - -}; - -inline -fragment_directive fragment(const std::string &fragment) { - return fragment_directive(fragment); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp deleted file mode 100644 index 6aded4e47..000000000 --- a/boost/network/uri/directives/host.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ - - -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct host_directive { - - explicit host_directive(const std::string &host) - : host(host) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(host); - } - - std::string host; - -}; - -inline -host_directive host(const std::string &host) { - return host_directive(host); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp deleted file mode 100644 index 89ec5f6f9..000000000 --- a/boost/network/uri/directives/path.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ - - -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct path_directive { - - explicit path_directive(const std::string &path) - : path(path) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(path); - } - - std::string path; - -}; - -struct encoded_path_directive { - - explicit encoded_path_directive(const std::string &path) - : path(path) - {} - - void operator () (uri &uri_) const { - std::string encoded_path; - encode(path, std::back_inserter(encoded_path)); - uri_.append(encoded_path); - } - - std::string path; - -}; - -inline -path_directive path(const std::string &path) { - return path_directive(path); -} - -inline -encoded_path_directive encoded_path(const std::string &path) { - return encoded_path_directive(path); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp deleted file mode 100644 index c9e6818a6..000000000 --- a/boost/network/uri/directives/port.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ - - -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct port_directive { - - explicit port_directive(const std::string &port) - : port(port) - {} - - explicit port_directive(boost::uint16_t port) - : port(boost::lexical_cast(port)) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(":"); - uri.append(port); - } - - std::string port; - -}; - -inline -port_directive port(const std::string &port) { - return port_directive(port); -} - -inline -port_directive port(boost::uint16_t port) { - return port_directive(port); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp deleted file mode 100644 index 8b795bd38..000000000 --- a/boost/network/uri/directives/query.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ - - -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct query_directive { - - explicit query_directive(const std::string &query) - : query(query) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append("?"); - uri.append(query); - } - - std::string query; - -}; - -inline -query_directive query(const std::string &query) { - return query_directive(query); -} - -struct query_key_query_directive { - - query_key_query_directive(const std::string &key, const std::string &query) - : key(key), query(query) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - std::string encoded_key, encoded_query; - if (boost::empty(uri.query())) - { - uri.append("?"); - } - else - { - uri.append("&"); - } - uri.append(key); - uri.append("="); - uri.append(query); - } - - std::string key; - std::string query; - -}; - -inline -query_key_query_directive query(const std::string &key, const std::string &query) { - return query_key_query_directive(key, query); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp deleted file mode 100644 index 65c6cc9ce..000000000 --- a/boost/network/uri/directives/scheme.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ - - -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct scheme_directive { - - explicit scheme_directive(const std::string &scheme) - : scheme(scheme) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(scheme); - if (opaque_schemes::exists(scheme)) { - uri.append(":"); - } - else { - uri.append("://"); - } - } - - std::string scheme; - -}; - -inline -scheme_directive scheme(const std::string &scheme) { - return scheme_directive(scheme); -} - -namespace schemes { -inline -uri &http(uri &uri_) { - return uri_ << scheme("http"); -} - -inline -uri &https(uri &uri_) { - return uri_ << scheme("https"); -} - -inline -uri &file(uri &uri_) { - return uri_ << scheme("file"); -} -} // namespace schemes -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp deleted file mode 100644 index 177c0b7a6..000000000 --- a/boost/network/uri/directives/user_info.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ -# define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ - - -# include -# include - - -namespace boost { -namespace network { -namespace uri { -struct user_info_directive { - - explicit user_info_directive(const std::string &user_info) - : user_info(user_info) - {} - - template < - class Uri - > - void operator () (Uri &uri) const { - uri.append(user_info); - uri.append("@"); - } - - std::string user_info; - -}; - -inline -user_info_directive user_info(const std::string &user_info) { - return user_info_directive(user_info); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp deleted file mode 100644 index a68f62658..000000000 --- a/boost/network/uri/encode.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_ENCODE_INC__ -# define __BOOST_NETWORK_URI_ENCODE_INC__ - - -# include -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -template < - typename CharT - > -inline -CharT hex_to_letter(CharT in) { - switch (in) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - return in + '0'; - case 10: - case 11: - case 12: - case 13: - case 14: - default: - return in - 10 + 'A'; - } - return CharT(); -} - - -template < - typename CharT, - class OutputIterator - > -void encode_char(CharT in, OutputIterator &out) { - switch (in) - { - case 'a': - case 'A': - case 'b': - case 'B': - case 'c': - case 'C': - case 'd': - case 'D': - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - case 'h': - case 'H': - case 'i': - case 'I': - case 'j': - case 'J': - case 'k': - case 'K': - case 'l': - case 'L': - case 'm': - case 'M': - case 'n': - case 'N': - case 'o': - case 'O': - case 'p': - case 'P': - case 'q': - case 'Q': - case 'r': - case 'R': - case 's': - case 'S': - case 't': - case 'T': - case 'u': - case 'U': - case 'v': - case 'V': - case 'w': - case 'W': - case 'x': - case 'X': - case 'y': - case 'Y': - case 'z': - case 'Z': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - case '.': - case '_': - case '~': - case '/': - out++ = in; - break; - default: - out++ = '%'; - out++ = hex_to_letter(in >> 4); - out++ = hex_to_letter(in & 0x0f); - ; - } -} -} // namespace detail - -template < - class InputIterator, - class OutputIterator - > -OutputIterator encode(const InputIterator &in_begin, - const InputIterator &in_end, - const OutputIterator &out_begin) { - typedef typename boost::iterator_value::type value_type; - - InputIterator it = in_begin; - OutputIterator out = out_begin; - while (it != in_end) { - detail::encode_char(*it, out); - ++it; - } - return out; -} - -template < - class SinglePassRange, - class OutputIterator - > -inline -OutputIterator encode(const SinglePassRange &range, - const OutputIterator &out) { - return encode(boost::begin(range), boost::end(range), out); -} - -inline -std::string encoded(const std::string &input) { - std::string encoded; - encode(input, std::back_inserter(encoded)); - return encoded; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_ENCODE_INC__ diff --git a/boost/network/uri/schemes.hpp b/boost/network/uri/schemes.hpp deleted file mode 100644 index b8c7d94a2..000000000 --- a/boost/network/uri/schemes.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2012 Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_SCHEMES_INC__ -# define __BOOST_NETWORK_URI_SCHEMES_INC__ - - -#include - - -namespace boost { -namespace network { -namespace uri { -class hierarchical_schemes { - -public: - - static bool exists(const std::string &scheme); - -}; - -class opaque_schemes { - -public: - - static bool exists(const std::string &scheme); - -}; -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_SCHEMES_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp deleted file mode 100644 index f798633b4..000000000 --- a/boost/network/uri/uri.hpp +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_INC__ -# define __BOOST_NETWORK_URI_INC__ - -# pragma once - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -bool parse(std::string::const_iterator first, - std::string::const_iterator last, - uri_parts &parts); -} // namespace detail - - -class BOOST_URI_DECL uri { - - friend class builder; - -public: - - typedef std::string string_type; - typedef string_type::value_type value_type; - typedef string_type::const_iterator const_iterator; - typedef boost::iterator_range const_range_type; - - uri() - : is_valid_(false) { - - } - - //uri(const value_type *uri) - // : uri_(uri), is_valid_(false) { - // parse(); - //} - - uri(const string_type &uri) - : uri_(uri), is_valid_(false) { - parse(); - } - - template < - class FwdIter - > - uri(const FwdIter &first, const FwdIter &last) - : uri_(first, last), is_valid_(false) { - parse(); - } - - uri(const uri &other) - : uri_(other.uri_) { - parse(); - } - - uri &operator = (const uri &other) { - uri(other).swap(*this); - return *this; - } - - uri &operator = (const string_type &uri_string) { - uri(uri_string).swap(*this); - return *this; - } - - ~uri() { - - } - - void swap(uri &other) { - boost::swap(uri_, other.uri_); - boost::swap(uri_parts_, other.uri_parts_); - boost::swap(is_valid_, other.is_valid_); - } - - const_iterator begin() const { - return uri_.begin(); - } - - const_iterator end() const { - return uri_.end(); - } - - const_range_type scheme_range() const { - return uri_parts_.scheme; - } - - const_range_type user_info_range() const { - return uri_parts_.hier_part.user_info? - uri_parts_.hier_part.user_info.get() : - const_range_type(); - } - - const_range_type host_range() const { - return uri_parts_.hier_part.host? - uri_parts_.hier_part.host.get() : - const_range_type(); - } - - const_range_type port_range() const { - return uri_parts_.hier_part.port? - uri_parts_.hier_part.port.get() : - const_range_type(); - } - - const_range_type path_range() const { - return uri_parts_.hier_part.path? - uri_parts_.hier_part.path.get() : - const_range_type(); - } - - const_range_type query_range() const { - return uri_parts_.query ? - uri_parts_.query.get() : - const_range_type(); - } - - const_range_type fragment_range() const { - return uri_parts_.fragment? - uri_parts_.fragment.get() : - const_range_type(); - } - - string_type scheme() const { - const_range_type range = scheme_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type user_info() const { - const_range_type range = user_info_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type host() const { - const_range_type range = host_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type port() const { - const_range_type range = port_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type path() const { - const_range_type range = path_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type query() const { - const_range_type range = query_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type fragment() const { - const_range_type range = fragment_range(); - return range? string_type(boost::begin(range), boost::end(range)) : string_type(); - } - - string_type string() const { - return uri_; - } - - bool is_valid() const { - return is_valid_; - } - - void append(const string_type &data) { - uri_.append(data); - parse(); - } - - template < - class FwdIter - > - void append(const FwdIter &first, const FwdIter &last) { - uri_.append(first, last); - parse(); - } - -private: - - void parse(); - - string_type uri_; - detail::uri_parts uri_parts_; - bool is_valid_; - -}; - -inline -void uri::parse() { - const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); - is_valid_ = detail::parse(first, last, uri_parts_); - if (is_valid_) { - if (!uri_parts_.scheme) { - uri_parts_.scheme = const_range_type(boost::begin(uri_), - boost::begin(uri_)); - } - uri_parts_.update(); - } -} - -inline -uri::string_type scheme(const uri &uri_) { - return uri_.scheme(); -} - -inline -uri::string_type user_info(const uri &uri_) { - return uri_.user_info(); -} - -inline -uri::string_type host(const uri &uri_) { - return uri_.host(); -} - -inline -uri::string_type port(const uri &uri_) { - return uri_.port(); -} - -inline -boost::optional port_us(const uri &uri_) { - uri::string_type port = uri_.port(); - return (port.empty())? - boost::optional() : - boost::optional(boost::lexical_cast(port)); -} - -inline -uri::string_type path(const uri &uri_) { - return uri_.path(); -} - -inline -uri::string_type query(const uri &uri_) { - return uri_.query(); -} - -inline -uri::string_type fragment(const uri &uri_) { - return uri_.fragment(); -} - -inline -uri::string_type hierarchical_part(const uri &uri_) { - return uri::string_type(boost::begin(uri_.user_info_range()), - boost::end(uri_.path_range())); -} - -inline -uri::string_type authority(const uri &uri_) { - return uri::string_type(boost::begin(uri_.user_info_range()), - boost::end(uri_.port_range())); -} - -inline -bool valid(const uri &uri_) { - return uri_.is_valid(); -} - -inline -bool is_absolute(const uri &uri_) { - return uri_.is_valid() && !boost::empty(uri_.scheme_range()); -} - -inline -bool is_relative(const uri &uri_) { - return uri_.is_valid() && boost::empty(uri_.scheme_range()); -} - -inline -bool is_hierarchical(const uri &uri_) { - return is_absolute(uri_) && hierarchical_schemes::exists(scheme(uri_)); -} - -inline -bool is_opaque(const uri &uri_) { - return is_absolute(uri_) && opaque_schemes::exists(scheme(uri_)); -} - -inline -bool is_valid(const uri &uri_) { - return valid(uri_); -} - -inline -void swap(uri &lhs, uri &rhs) { - lhs.swap(rhs); -} - -inline -std::size_t hash_value(const uri &uri_) -{ - std::size_t seed = 0; - for (uri::const_iterator it = begin(uri_); it != end(uri_); ++it) { - hash_combine(seed, *it); - } - return seed; -} - -inline -bool operator == (const uri &lhs, const uri &rhs) { - return boost::equal(lhs, rhs); -} - -inline -bool operator == (const uri &lhs, const uri::string_type &rhs) { - return boost::equal(lhs, rhs); -} - -inline -bool operator == (const uri::string_type &lhs, const uri &rhs) { - return boost::equal(lhs, rhs); -} - -inline -bool operator == (const uri &lhs, const uri::value_type *rhs) { - return boost::equal(lhs, boost::as_literal(rhs)); -} - -inline -bool operator == (const uri::value_type *lhs, const uri &rhs) { - return boost::equal(boost::as_literal(lhs), rhs); -} - -inline -bool operator != (const uri &lhs, const uri &rhs) { - return !(lhs == rhs); -} - -inline -bool operator < (const uri &lhs, const uri &rhs) { - return lhs.string() < rhs.string(); -} -} // namespace uri -} // namespace network -} // namespace boost - -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -inline -uri from_parts(const uri &base_uri, - const uri::string_type &path_, - const uri::string_type &query_, - const uri::string_type &fragment_) { - uri uri_(base_uri); - builder(uri_).path(path_).query(query_).fragment(fragment_); - return uri_; -} - -inline -uri from_parts(const uri &base_uri, - const uri::string_type &path_, - const uri::string_type &query_) { - uri uri_(base_uri); - builder(uri_).path(path_).query(query_); - return uri_; -} - -inline -uri from_parts(const uri &base_uri, - const uri::string_type &path_) { - uri uri_(base_uri); - builder(uri_).path(path_); - return uri_; -} - -inline -uri from_parts(const uri::string_type &base_uri, - const uri::string_type &path, - const uri::string_type &query, - const uri::string_type &fragment) { - return from_parts(uri(base_uri), path, query, fragment); -} - -inline -uri from_parts(const uri::string_type &base_uri, - const uri::string_type &path, - const uri::string_type &query) { - return from_parts(uri(base_uri), path, query); -} - -inline -uri from_parts(const uri::string_type &base_uri, - const uri::string_type &path) { - return from_parts(uri(base_uri), path); -} -} // namespace uri -} // namespace network -} // namespace boost - -# include - -namespace boost { -namespace network { -namespace uri { -inline -uri from_file(const filesystem::path &path_) { - uri uri_; - builder(uri_).scheme("file").path(path_.string()); - return uri_; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_INC__ diff --git a/boost/network/uri/uri.ipp b/boost/network/uri/uri.ipp deleted file mode 100644 index 7af1f48ab..000000000 --- a/boost/network/uri/uri.ipp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2009, 2010, 2011, 2012 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include -#include -#include -#include - -BOOST_FUSION_ADAPT_TPL_STRUCT -( - (FwdIter), - (boost::network::uri::detail::hierarchical_part)(FwdIter), - (boost::optional >, user_info) - (boost::optional >, host) - (boost::optional >, port) - (boost::optional >, path) - ); - -BOOST_FUSION_ADAPT_TPL_STRUCT -( - (FwdIter), - (boost::network::uri::detail::uri_parts)(FwdIter), - (boost::iterator_range, scheme) - (boost::network::uri::detail::hierarchical_part, hier_part) - (boost::optional >, query) - (boost::optional >, fragment) - ); - -namespace boost { -namespace network { -namespace uri { -namespace detail { -namespace qi = boost::spirit::qi; - -template < - class String - > -struct uri_grammar : qi::grammar< - typename String::const_iterator - , detail::uri_parts()> { - - typedef String string_type; - typedef typename String::const_iterator const_iterator; - - uri_grammar() : uri_grammar::base_type(start, "uri") { - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= - qi::raw[*(qi::char_("/") >> segment)] - ; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= - qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ] - ; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= - qi::raw[segment_nz >> *(qi::char_("/") >> segment)] - ; - // path-empty = 0 - path_empty %= - qi::raw[qi::eps] - ; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= - qi::raw[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - ; - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= - qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))] - ; - - ip_literal %= - qi::lit('[') >> (ipv6address | ipvfuture) >> ']' - ; - - ipvfuture %= - qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') - ; - - ipv6address %= qi::raw[ - qi::repeat(6)[h16 >> ':'] >> ls32 - | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 - | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 - | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 - | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 - | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" - ]; - - // ls32 = ( h16 ":" h16 ) / IPv4address - ls32 %= (h16 >> ':' >> h16) | ipv4address - ; - - // h16 = 1*4HEXDIG - h16 %= qi::repeat(1, 4)[qi::xdigit] - ; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - - // TODO, host = IP-literal / IPv4address / reg-name - host %= - qi::raw[ip_literal | ipv4address | reg_name] - ; - - // port %= qi::ushort_; - port %= - qi::raw[*qi::digit] - ; - - // query = *( pchar / "/" / "?" ) - query %= - qi::raw[*(pchar | qi::char_("/?"))] - ; - - // fragment = *( pchar / "/" / "?" ) - fragment %= - qi::raw[*(pchar | qi::char_("/?"))] - ; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - (("//" >> user_info >> '@') | "//") - >> host - >> -(':' >> port) - >> path_abempty - ) - | - ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ) - ; - - start %= - (scheme >> ':') - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment) - ; - } - - qi::rule::value_type()> - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule()> - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; - - qi::rule - h16, ls32; - - qi::rule()> - host, port; - - qi::rule()> - scheme, user_info, query, fragment; - - qi::rule()> - hier_part; - - // actual uri parser - qi::rule()> start; - -}; - -bool parse(std::string::const_iterator first, - std::string::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static detail::uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} -} // namespace detail -} // namespace uri -} // namespace network -} // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp deleted file mode 100644 index 68da1b014..000000000 --- a/boost/network/uri/uri_io.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Glyn Matthews 2011, 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_URI_IO_INC__ -# define __BOOST_NETWORK_URI_URI_IO_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { - -inline -std::ostream &operator << (std::ostream &os, const uri &uri_) { - return os << uri_.string(); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_URI_IO_INC__ diff --git a/boost/network/utils/thread_pool.hpp b/boost/network/utils/thread_pool.hpp deleted file mode 100644 index 2b0fa7a0e..000000000 --- a/boost/network/utils/thread_pool.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 -#define BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace utils { - - typedef boost::shared_ptr io_service_ptr; - typedef boost::shared_ptr worker_threads_ptr; - typedef boost::shared_ptr sentinel_ptr; - - template - struct basic_thread_pool { - basic_thread_pool( - std::size_t threads = 1, - io_service_ptr io_service = io_service_ptr(), - worker_threads_ptr worker_threads = worker_threads_ptr() - ) - : threads_(threads) - , io_service_(io_service) - , worker_threads_(worker_threads) - , sentinel_() - { - bool commit = false; - BOOST_SCOPE_EXIT_TPL((&commit)(&io_service_)(&worker_threads_)(&sentinel_)) { - if (!commit) { - sentinel_.reset(); - io_service_.reset(); - if (worker_threads_.get()) { - worker_threads_->interrupt_all(); - worker_threads_->join_all(); - } - worker_threads_.reset(); - } - } BOOST_SCOPE_EXIT_END - - if (!io_service_.get()) { - io_service_.reset(new boost::asio::io_service); - } - - if (!worker_threads_.get()) { - worker_threads_.reset(new boost::thread_group); - } - - if (!sentinel_.get()) { - sentinel_.reset(new boost::asio::io_service::work(*io_service_)); - } - - for (std::size_t counter = 0; counter < threads_; ++counter) - worker_threads_->create_thread( - boost::bind( - &boost::asio::io_service::run, - io_service_ - ) - ); - - commit = true; - } - - std::size_t thread_count() const { - return threads_; - } - - void post(boost::function f) { - io_service_->post(f); - } - - ~basic_thread_pool() throw () { - sentinel_.reset(); - try { - worker_threads_->join_all(); - } catch (...) { - BOOST_ASSERT(false && "A handler was not supposed to throw, but one did."); - } - } - - void swap(basic_thread_pool & other) { - std::swap(other.threads_, threads_); - std::swap(other.io_service_, io_service_); - std::swap(other.worker_threads_, worker_threads_); - std::swap(other.sentinel_, sentinel_); - } - protected: - std::size_t threads_; - io_service_ptr io_service_; - worker_threads_ptr worker_threads_; - sentinel_ptr sentinel_; - - private: - basic_thread_pool(basic_thread_pool const &); // no copies please - basic_thread_pool & operator=(basic_thread_pool); // no assignment please - }; - - typedef basic_thread_pool thread_pool; - -} /* utils */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_UTILS_THREAD_POOL_HPP_20101020 */ diff --git a/boost/network/version.hpp b/boost/network/version.hpp deleted file mode 100644 index f22fb8628..000000000 --- a/boost/network/version.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef BOOST_NETWORK_VERSION_HPP_20091214 -#define BOOST_NETWORK_VERSION_HPP_20091214 - -// Copyright Dean Michael Berris 2009. -// Copyright Glyn Matthews 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -#define BOOST_NETLIB_VERSION_MAJOR 0 -#define BOOST_NETLIB_VERSION_MINOR 9 -#define BOOST_NETLIB_VERSION_INCREMENT 0 - -#ifndef BOOST_NETLIB_VERSION -# define BOOST_NETLIB_VERSION \ - BOOST_STRINGIZE(BOOST_NETLIB_VERSION_MAJOR) "." \ - BOOST_STRINGIZE(BOOST_NETLIB_VERSION_MINOR) "." \ - BOOST_STRINGIZE(BOOST_NETLIB_VERSION_INCREMENT) -#endif // BOOST_NETLIB_VERSION - -#endif // BOOST_NETWORK_VERSION_HPP_20091214 diff --git a/concurrency/CMakeLists.txt b/concurrency/CMakeLists.txt new file mode 100644 index 000000000..cad1c7ea6 --- /dev/null +++ b/concurrency/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +add_subdirectory(src) + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif(CPP-NETLIB_BUILD_TESTS) diff --git a/concurrency/src/CMakeLists.txt b/concurrency/src/CMakeLists.txt new file mode 100644 index 000000000..4661a0d89 --- /dev/null +++ b/concurrency/src/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}/concurrency/src) + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +set(CPP-NETLIB_CONCURRENCY_SRCS thread_pool.cpp) +add_library(cppnetlib-concurrency ${CPP-NETLIB_CONCURRENCY_SRCS}) +foreach (src_file ${CPP-NETLIB_CONCURRENCY_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) diff --git a/concurrency/src/network/concurrency/thread_pool.hpp b/concurrency/src/network/concurrency/thread_pool.hpp new file mode 100644 index 000000000..02d8d411c --- /dev/null +++ b/concurrency/src/network/concurrency/thread_pool.hpp @@ -0,0 +1,53 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_CONCURRENCY_THREAD_POOL_HPP_20101020 +#define NETWORK_CONCURRENCY_THREAD_POOL_HPP_20101020 + +#include +#include +#include +#include +#include +#include + +namespace network { namespace concurrency { + + typedef std::shared_ptr io_service_ptr; + typedef std::shared_ptr> worker_threads_ptr; + typedef std::shared_ptr sentinel_ptr; + + struct thread_pool_pimpl; + + struct thread_pool { + thread_pool(std::size_t threads = 1, + io_service_ptr io_service = io_service_ptr(), + std::vector worker_threads = std::vector()); +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + thread_pool(thread_pool const&) = delete; +#endif // !defined(BOOST_NO_CXX11_DELETEED_FUNCTIONS) + thread_pool(thread_pool &&other); +#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + thread_pool& operator=(thread_pool const&) = delete; +#endif // !defined(BOOST_NO_CXX11_DELETEED_FUNCTIONS) + thread_pool& operator=(thread_pool &&other); + std::size_t const thread_count() const; + void post(std::function f); + ~thread_pool(); + void swap(thread_pool & other); + protected: + thread_pool_pimpl * pimpl; + }; + + inline void swap(thread_pool & l, thread_pool & r) { + l.swap(r); + } + +} // namespace concurrency +} // namespace network + +#endif /* NETWORK_CONCURRENCY_THREAD_POOL_HPP_20101020 */ diff --git a/concurrency/src/network/concurrency/thread_pool.ipp b/concurrency/src/network/concurrency/thread_pool.ipp new file mode 100644 index 000000000..4671cbfc5 --- /dev/null +++ b/concurrency/src/network/concurrency/thread_pool.ipp @@ -0,0 +1,116 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_CONCURRENCY_THREAD_POOL_IPP_20111021 +#define NETWORK_CONCURRENCY_THREAD_POOL_IPP_20111021 + +#include +#include +#include +#include + +namespace network { namespace concurrency { + + struct thread_pool_pimpl { + thread_pool_pimpl(std::size_t threads = 1, + io_service_ptr io_service = io_service_ptr(), + std::vector worker_threads = std::vector()) + : threads_(threads) + , io_service_(io_service) + , worker_threads_(std::move(worker_threads)) + , sentinel_() + { + bool commit = false; + BOOST_SCOPE_EXIT((&commit)(&io_service_)(&worker_threads_)(&sentinel_)) { + if (!commit) { + sentinel_.reset(); + io_service_.reset(); + for (auto& thread : worker_threads_) + if (thread.joinable()) thread.join(); + worker_threads_.clear(); + } + } BOOST_SCOPE_EXIT_END + + if (!io_service_.get()) io_service_.reset(new boost::asio::io_service); + if (!sentinel_.get()) + sentinel_.reset(new boost::asio::io_service::work(*io_service_)); + auto local_io_service = io_service_; + for (std::size_t counter = 0; counter < threads_; ++counter) + worker_threads_.emplace_back([local_io_service](){ + local_io_service->run();}); + + commit = true; + } + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + thread_pool_pimpl(thread_pool_pimpl const &) = delete; + thread_pool_pimpl & operator=(thread_pool_pimpl const &) = delete; +#endif // !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + + thread_pool_pimpl(thread_pool_pimpl&& other) { + other.swap(*this); + } + + std::size_t const thread_count() const { + return threads_; + } + + void post(std::function f) { + io_service_->post(f); + } + + ~thread_pool_pimpl() { + sentinel_.reset(); + try { + for (auto& thread : worker_threads_) thread.join(); + } catch (...) { + BOOST_ASSERT(false && "A handler was not supposed to throw, but one did."); + std::abort(); + } + } + + void swap(thread_pool_pimpl & other) { + using std::swap; + swap(other.threads_, threads_); + swap(other.io_service_, io_service_); + swap(other.worker_threads_, worker_threads_); + swap(other.sentinel_, sentinel_); + } + + protected: + std::size_t threads_; + io_service_ptr io_service_; + std::vector worker_threads_; + sentinel_ptr sentinel_; + }; + + thread_pool::thread_pool(std::size_t threads, + io_service_ptr io_service, + std::vector worker_threads) + : pimpl(new (std::nothrow) thread_pool_pimpl(threads, io_service, std::move(worker_threads))) + {} + + std::size_t const thread_pool::thread_count() const { + return pimpl->thread_count(); + } + + void thread_pool::post(std::function f) { + pimpl->post(f); + } + + void thread_pool::swap(thread_pool & other) { + std::swap(other.pimpl, this->pimpl); + } + + thread_pool::~thread_pool() { + delete pimpl; + } + +} // namespace concurrency +} // namespace network + +#endif /* NETWORK_CONCURRENCY_THREAD_POOL_IPP_20111021 */ diff --git a/concurrency/src/network/utils/thread_pool.hpp b/concurrency/src/network/utils/thread_pool.hpp new file mode 100644 index 000000000..cc7d98a27 --- /dev/null +++ b/concurrency/src/network/utils/thread_pool.hpp @@ -0,0 +1,19 @@ +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __NETWORK_UTILS_THREAD_POOL_INC__ +#define __NETWORK_UTILS_THREAD_POOL_INC__ + +#include + +namespace network { +namespace utils { + typedef ::network::concurrency::thread_pool thread_pool; +} // namespace utils +} // namespace network + + +#endif // __NETWORK_UTILS_THREAD_POOL_INC__ diff --git a/concurrency/src/thread_pool.cpp b/concurrency/src/thread_pool.cpp new file mode 100644 index 000000000..101d41a43 --- /dev/null +++ b/concurrency/src/thread_pool.cpp @@ -0,0 +1,8 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include diff --git a/concurrency/test/CMakeLists.txt b/concurrency/test/CMakeLists.txt new file mode 100644 index 000000000..73cf52cad --- /dev/null +++ b/concurrency/test/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}/concurrency/src) + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +set_source_files_properties(thread_pool_test.cpp + PROPERTIES COMPILE_FLAGS "-Wall") +add_executable(cpp-netlib-thread_pool_test thread_pool_test.cpp) +target_link_libraries(cpp-netlib-thread_pool_test + cppnetlib-concurrency + ${Boost_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT}) +set_target_properties(cpp-netlib-thread_pool_test + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) +add_test(cpp-netlib-thread_pool_test ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-thread_pool_test) diff --git a/libs/network/test/utils_thread_pool.cpp b/concurrency/test/thread_pool_test.cpp similarity index 52% rename from libs/network/test/utils_thread_pool.cpp rename to concurrency/test/thread_pool_test.cpp index d075efafa..008370a64 100644 --- a/libs/network/test/utils_thread_pool.cpp +++ b/concurrency/test/thread_pool_test.cpp @@ -1,16 +1,21 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Copyright (c) Glyn Matthews 2012. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_TEST_MODULE utils thread pool test +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE thread pool test #include #include -#include +#include #include -using namespace boost::network; +using network::concurrency::thread_pool; // This test specifies the requirements for a thread pool interface. At the // very least any thread pool implementation should be able to pass the simple @@ -21,29 +26,29 @@ using namespace boost::network; // BOOST_AUTO_TEST_CASE( default_constructor ) { - utils::thread_pool pool; - BOOST_CHECK_EQUAL(pool.thread_count(), std::size_t(1)); + thread_pool pool; + BOOST_CHECK_EQUAL(pool.thread_count(), std::size_t(1)); } struct foo { - foo() : val_(0) {} - void bar(int val) { - val_ += val; - } - int const val() const { - return val_; - } + foo() : val_(0) {} + void bar(int val) { + val_ += val; + } + int const val() const { + return val_; + } protected: - int val_; + int val_; }; BOOST_AUTO_TEST_CASE( post_work ) { - foo instance; - { - utils::thread_pool pool; - BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 1))); - BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 2))); - // require that pool is destroyed here, RAII baby - } - BOOST_CHECK_EQUAL(instance.val(), 3); + foo instance; + { + thread_pool pool; + BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 1))); + BOOST_CHECK_NO_THROW(pool.post(boost::bind(&foo::bar, &instance, 2))); + // require that pool is destroyed here, RAII baby + } + BOOST_CHECK_EQUAL(instance.val(), 3); } diff --git a/contrib/http_examples/CMakeLists.txt b/contrib/http_examples/CMakeLists.txt new file mode 100644 index 000000000..9e117b774 --- /dev/null +++ b/contrib/http_examples/CMakeLists.txt @@ -0,0 +1,144 @@ +# Copyright (c) Dean Michael Berris 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories( + ${CPP-NETLIB_SOURCE_DIR}/uri/src + ${CPP-NETLIB_SOURCE_DIR}/message/src + ${CPP-NETLIB_SOURCE_DIR}/logging/src + ${CPP-NETLIB_SOURCE_DIR}/http/src + ${CPP-NETLIB_SOURCE_DIR}) +if (OPENSSL_FOUND) + include_directories(${OPENSSL_INCLUDE_DIR}) +endif (OPENSSL_FOUND) + +if( NOT CPP-NETLIB_DISABLE_LOGGING ) + set( CPP-NETLIB_LOGGING_LIB cppnetlib-logging ) +endif() + +add_executable(simple_wget simple_wget.cpp) +add_executable(atom_reader atom/atom.cpp atom/main.cpp) +add_executable(rss_reader rss/rss.cpp rss/main.cpp) +#add_executable(twitter_search twitter/search.cpp) +#add_executable(hello_world_server http/hello_world_server.cpp) +add_executable(hello_world_client http/hello_world_client.cpp) +#if (UNIX) +# add_executable(fileserver http/fileserver.cpp) +#endif (UNIX) +set(BOOST_CLIENT_LIBS + ${Boost_DATE_TIME_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_REGEX_LIBRARY} + ) +set(BOOST_SERVER_LIBS + ${Boost_DATE_TIME_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ) + +target_link_libraries(simple_wget + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-message + cppnetlib-message-directives + cppnetlib-message-wrappers + cppnetlib-http-message-wrappers + cppnetlib-http-message + cppnetlib-constants + cppnetlib-http-client + cppnetlib-http-client-connections + ${CPP-NETLIB_LOGGING_LIB}) + +target_link_libraries(atom_reader + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-message + cppnetlib-message-directives + cppnetlib-message-wrappers + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-constants + cppnetlib-http-client + cppnetlib-http-client-connections + ${CPP-NETLIB_LOGGING_LIB}) + +target_link_libraries(rss_reader + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-message + cppnetlib-message-directives + cppnetlib-message-wrappers + cppnetlib-http-message + cppnetlib-constants + cppnetlib-http-client + cppnetlib-http-client-connections + ${CPP-NETLIB_LOGGING_LIB}) + +#target_link_libraries(twitter_search +# ${BOOST_CLIENT_LIBS} +# ${CMAKE_THREAD_LIBS_INIT} +# cppnetlib-uri +# cppnetlib-message +# cppnetlib-message-directives +# cppnetlib-message-wrappers +# cppnetlib-http-message-wrappers +# cppnetlib-http-message +# cppnetlib-constants +# cppnetlib-http-client +# cppnetlib-http-client-connections +# ${CPP-NETLIB_LOGGING_LIB}) + +#target_link_libraries(hello_world_server +# ${BOOST_SERVER_LIBS} +# ${CMAKE_THREAD_LIBS_INIT} +# cppnetlib-http-server-parsers +# cppnetlib-http-server +# ${CPP-NETLIB_LOGGING_LIB}) + +target_link_libraries(hello_world_client + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-message + cppnetlib-message-directives + cppnetlib-message-wrappers + cppnetlib-http-message-wrappers + cppnetlib-http-message + cppnetlib-constants + cppnetlib-http-client + cppnetlib-http-client-connections + ${CPP-NETLIB_LOGGING_LIB}) + +if (OPENSSL_FOUND) + target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) + target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) + target_link_libraries(rss_reader ${OPENSSL_LIBRARIES}) + #target_link_libraries(twitter_search ${OPENSSL_LIBRARIES}) + #target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) + target_link_libraries(hello_world_client ${OPENSSL_LIBRARIES}) +endif (OPENSSL_FOUND) + +#if (UNIX) +# target_link_libraries(fileserver +# ${BOOST_SERVER_LIBS} +# ${Boost_FILESYSTEM_LIBRARY} +# ${CMAKE_THREAD_LIBS_INIT} +# cppnetlib-server-parsers) +#endif (UNIX) + +set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(rss_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +#set_target_properties(twitter_search PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +#set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(hello_world_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +#if (UNIX) +# set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +#endif (UNIX) diff --git a/libs/network/example/Jamfile.v2 b/contrib/http_examples/Jamfile.v2 similarity index 88% rename from libs/network/example/Jamfile.v2 rename to contrib/http_examples/Jamfile.v2 index 5bca45589..da6f71f10 100644 --- a/libs/network/example/Jamfile.v2 +++ b/contrib/http_examples/Jamfile.v2 @@ -23,9 +23,6 @@ project network_test : exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; -exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; - -exe http_client1 : http_client1.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; diff --git a/libs/network/example/atom/atom.cpp b/contrib/http_examples/atom/atom.cpp similarity index 98% rename from libs/network/example/atom/atom.cpp rename to contrib/http_examples/atom/atom.cpp index 7555956b6..c75f63563 100644 --- a/libs/network/example/atom/atom.cpp +++ b/contrib/http_examples/atom/atom.cpp @@ -1,4 +1,5 @@ // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,8 +10,6 @@ #include #include - -namespace boost { namespace network { namespace atom { feed::feed(const http::client::response &response) { @@ -94,4 +93,3 @@ feed::feed(const http::client::response &response) { } } // namespace atom } // namespace network -} // namespace boost diff --git a/libs/network/example/atom/atom.hpp b/contrib/http_examples/atom/atom.hpp similarity index 97% rename from libs/network/example/atom/atom.hpp rename to contrib/http_examples/atom/atom.hpp index b19e4146a..3b83ef2ac 100644 --- a/libs/network/example/atom/atom.hpp +++ b/contrib/http_examples/atom/atom.hpp @@ -1,4 +1,5 @@ // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,10 +10,9 @@ # include # include -# include +# include -namespace boost { namespace network { namespace atom { class entry { @@ -172,6 +172,5 @@ class feed { }; } // namespace atom } // namespace network -} // namespace boost #endif // ___ATOM_INC__ diff --git a/libs/network/example/atom/main.cpp b/contrib/http_examples/atom/main.cpp similarity index 79% rename from libs/network/example/atom/main.cpp rename to contrib/http_examples/atom/main.cpp index b419db720..229caf7d5 100644 --- a/libs/network/example/atom/main.cpp +++ b/contrib/http_examples/atom/main.cpp @@ -1,16 +1,19 @@ +// Copyright (c) Glyn Matthews 2011, 2012. // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "atom.hpp" -#include +#include #include #include int main(int argc, char * argv[]) { - using namespace boost::network; + namespace http = network::http; + namespace atom = network::atom; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; @@ -20,7 +23,7 @@ int main(int argc, char * argv[]) { try { http::client client; http::client::request request(argv[1]); - request << header("Connection", "close"); + request << network::header("Connection", "close"); http::client::response response = client.get(request); atom::feed feed(response); diff --git a/libs/network/example/http/fileserver.cpp b/contrib/http_examples/http/fileserver.cpp similarity index 98% rename from libs/network/example/http/fileserver.cpp rename to contrib/http_examples/http/fileserver.cpp index 076680385..5ae98de8e 100644 --- a/libs/network/example/http/fileserver.cpp +++ b/contrib/http_examples/http/fileserver.cpp @@ -1,9 +1,10 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include #include #include #include diff --git a/libs/network/example/http/hello_world_client.cpp b/contrib/http_examples/http/hello_world_client.cpp similarity index 91% rename from libs/network/example/http/hello_world_client.cpp rename to contrib/http_examples/http/hello_world_client.cpp index 333c389d9..53d9eef55 100644 --- a/libs/network/example/http/hello_world_client.cpp +++ b/contrib/http_examples/http/hello_world_client.cpp @@ -1,4 +1,5 @@ // Copyright (c) Glyn Matthews 2010. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -11,11 +12,11 @@ to the `hello_world_server`, then the output is simply "Hello, World!". */ -#include +#include #include -namespace http = boost::network::http; +namespace http = network::http; int diff --git a/libs/network/example/http/hello_world_server.cpp b/contrib/http_examples/http/hello_world_server.cpp similarity index 71% rename from libs/network/example/http/hello_world_server.cpp rename to contrib/http_examples/http/hello_world_server.cpp index e6ec08bcf..5e950e43f 100644 --- a/libs/network/example/http/hello_world_server.cpp +++ b/contrib/http_examples/http/hello_world_server.cpp @@ -1,5 +1,6 @@ // Copyright 2009 (c) Tarro, Inc. -// Copyright 2009 (c) Dean Michael Berris +// Copyright 2009 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -11,16 +12,16 @@ demonstrate how easy it is to set up an HTTP server. All we do in this example is create a request handler and run the server. */ -#include +#include #include -namespace http = boost::network::http; +namespace http = network::http; /*<< Defines the server. >>*/ struct hello_world; -typedef http::server server; +typedef http::sync_server server; /*<< Defines the request handler. It's a class that defines two functions, `operator()` and `log()` >>*/ @@ -28,11 +29,11 @@ struct hello_world { /*<< This is the function that handles the incoming request. >>*/ void operator() (server::request const &request, server::response &response) { - server::string_type ip = source(request); - std::ostringstream data; - data << "Hello, " << ip << "!"; - response = server::response::stock_reply( - server::response::ok, data.str()); + //server::string_type ip = source(request); + //std::ostringstream data; + //data << "Hello, " << ip << "!"; + //response = server::response::stock_reply( + // server::response::ok, data.str()); } /*<< It's necessary to define a log function, but it's ignored in this example. >>*/ @@ -43,7 +44,7 @@ struct hello_world { int main(int argc, char * argv[]) { - + if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; @@ -53,7 +54,8 @@ int main(int argc, char * argv[]) { /*<< Creates the request handler. >>*/ hello_world handler; /*<< Creates the server. >>*/ - server server_(argv[1], argv[2], handler); + http::server_options options; + server server_(options.address(argv[1]).port(argv[2]), handler); /*<< Runs the server. >>*/ server_.run(); } @@ -61,7 +63,7 @@ int main(int argc, char * argv[]) { std::cerr << e.what() << std::endl; return 1; } - + return 0; } //] diff --git a/libs/network/example/http/one_liner.cpp b/contrib/http_examples/http/one_liner.cpp similarity index 89% rename from libs/network/example/http/one_liner.cpp rename to contrib/http_examples/http/one_liner.cpp index 86a98d763..3122e0f98 100644 --- a/libs/network/example/http/one_liner.cpp +++ b/contrib/http_examples/http/one_liner.cpp @@ -1,5 +1,6 @@ // Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,7 +10,7 @@ /*` */ -#include +#include using namespace std; diff --git a/libs/network/example/rapidxml/license.txt b/contrib/http_examples/rapidxml/license.txt similarity index 100% rename from libs/network/example/rapidxml/license.txt rename to contrib/http_examples/rapidxml/license.txt diff --git a/libs/network/example/rapidxml/manual.html b/contrib/http_examples/rapidxml/manual.html similarity index 100% rename from libs/network/example/rapidxml/manual.html rename to contrib/http_examples/rapidxml/manual.html diff --git a/libs/network/example/rapidxml/rapidxml.hpp b/contrib/http_examples/rapidxml/rapidxml.hpp similarity index 100% rename from libs/network/example/rapidxml/rapidxml.hpp rename to contrib/http_examples/rapidxml/rapidxml.hpp diff --git a/libs/network/example/rapidxml/rapidxml_iterators.hpp b/contrib/http_examples/rapidxml/rapidxml_iterators.hpp similarity index 100% rename from libs/network/example/rapidxml/rapidxml_iterators.hpp rename to contrib/http_examples/rapidxml/rapidxml_iterators.hpp diff --git a/libs/network/example/rapidxml/rapidxml_print.hpp b/contrib/http_examples/rapidxml/rapidxml_print.hpp similarity index 100% rename from libs/network/example/rapidxml/rapidxml_print.hpp rename to contrib/http_examples/rapidxml/rapidxml_print.hpp diff --git a/libs/network/example/rapidxml/rapidxml_utils.hpp b/contrib/http_examples/rapidxml/rapidxml_utils.hpp similarity index 100% rename from libs/network/example/rapidxml/rapidxml_utils.hpp rename to contrib/http_examples/rapidxml/rapidxml_utils.hpp diff --git a/libs/network/example/rss/main.cpp b/contrib/http_examples/rss/main.cpp similarity index 83% rename from libs/network/example/rss/main.cpp rename to contrib/http_examples/rss/main.cpp index 141f7c335..07ecdd7f1 100644 --- a/libs/network/example/rss/main.cpp +++ b/contrib/http_examples/rss/main.cpp @@ -1,16 +1,18 @@ // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include "rss.hpp" -#include +#include #include #include int main(int argc, char * argv[]) { - using namespace boost::network; + namespace http = network::http; + namespace rss = network::rss; if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; @@ -20,7 +22,7 @@ int main(int argc, char * argv[]) { try { http::client client; http::client::request request(argv[1]); - request << header("Connection", "close"); + request << network::header("Connection", "close"); http::client::response response = client.get(request); rss::channel channel(response); diff --git a/libs/network/example/rss/rss.cpp b/contrib/http_examples/rss/rss.cpp similarity index 98% rename from libs/network/example/rss/rss.cpp rename to contrib/http_examples/rss/rss.cpp index f4864c1ef..069b1e880 100644 --- a/libs/network/example/rss/rss.cpp +++ b/contrib/http_examples/rss/rss.cpp @@ -1,4 +1,5 @@ // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,8 +10,6 @@ #include #include - -namespace boost { namespace network { namespace rss { channel::channel(const http::client::response &response) { @@ -72,4 +71,3 @@ channel::channel(const http::client::response &response) { } } // namespace rss } // namespace network -} // namespace boost diff --git a/libs/network/example/rss/rss.hpp b/contrib/http_examples/rss/rss.hpp similarity index 95% rename from libs/network/example/rss/rss.hpp rename to contrib/http_examples/rss/rss.hpp index 12acd4ad0..0d3c3f758 100644 --- a/libs/network/example/rss/rss.hpp +++ b/contrib/http_examples/rss/rss.hpp @@ -1,4 +1,5 @@ // Copyright (c) Glyn Matthews 2011. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,10 +10,9 @@ # include # include -# include +# include -namespace boost { namespace network { namespace rss { class item { @@ -107,6 +107,5 @@ class channel { }; } // namespace rss } // namespace network -} // namespace boost #endif // ___RSS_INC__ diff --git a/contrib/http_examples/simple_wget.cpp b/contrib/http_examples/simple_wget.cpp new file mode 100644 index 000000000..4efce05b3 --- /dev/null +++ b/contrib/http_examples/simple_wget.cpp @@ -0,0 +1,69 @@ +// Copyright (c) Glyn Matthews 2009-2012. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +//[ simple_wget_main +/*` + This is a very basic clone of wget. It's missing a lot of + features, such as content-type detection, but it does the + fundamental things the same. + + It demonstrates the use the `uri` and the `http::client`. +*/ + + +#include +#include +#include +#include +#include + + +namespace http = network::http; + + +namespace { +std::string get_filename(const network::uri &url) { + auto path = url.path(); + if (path) { + auto path_str = std::string(*path); + auto index = path_str.find_last_of('/'); + auto filename = path_str.substr(index + 1); + return filename.empty()? "index.html" : filename; + } + return "index.html"; +} +} // namespace + + +int +main(int argc, char *argv[]) { + + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " url" << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + http::client::response response = client.get(request); + + network::uri uri; + request.get_uri(uri); + std::string filename = get_filename(uri); + std::cout << "Saving to: " << filename << std::endl; + std::ofstream ofs(filename.c_str()); + ofs << static_cast(body(response)) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; +} +//] diff --git a/libs/network/example/twitter/rapidjson/document.h b/contrib/http_examples/twitter/rapidjson/document.h similarity index 97% rename from libs/network/example/twitter/rapidjson/document.h rename to contrib/http_examples/twitter/rapidjson/document.h index f956ea97d..d3fb7a63f 100644 --- a/libs/network/example/twitter/rapidjson/document.h +++ b/contrib/http_examples/twitter/rapidjson/document.h @@ -1,806 +1,806 @@ -#ifndef RAPIDJSON_DOCUMENT_H_ -#define RAPIDJSON_DOCUMENT_H_ - -#include "reader.h" -#include "internal/strfunc.h" - -namespace rapidjson { - -/////////////////////////////////////////////////////////////////////////////// -// GenericValue - -//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. -/*! - A JSON value can be one of 7 types. This class is a variant type supporting - these types. - - Use the Value if UTF8 and default allocator - - \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) - \tparam Allocator Allocator type for allocating memory of object, array and string. -*/ -#pragma pack (push, 4) -template > -class GenericValue { -public: - //! Name-value pair in an object. - struct Member { - GenericValue name; //!< name of member (must be a string) - GenericValue value; //!< value of member. - }; - - typedef Encoding EncodingType; //!< Encoding type from template parameter. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef Member* MemberIterator; //!< Member iterator for iterating in object. - typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. - typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. - typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. - - //!@name Constructors and destructor. - //@{ - - //! Default constructor creates a null value. - GenericValue() : flags_(kNullFlag) {} - - //! Copy constructor is not permitted. -private: - GenericValue(const GenericValue& rhs); - -public: - - //! Constructor with JSON value type. - /*! This creates a Value of specified type with default content. - \param type Type of the value. - \note Default content for number is zero. - */ - GenericValue(Type type) { - static const unsigned defaultFlags[7] = { - kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, - kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag - }; - RAPIDJSON_ASSERT(type <= kNumberType); - flags_ = defaultFlags[type]; - memset(&data_, 0, sizeof(data_)); - } - - //! Constructor for boolean value. - GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} - - //! Constructor for int value. - GenericValue(int i) : flags_(kNumberIntFlag) { - data_.n.i64 = i; - if (i >= 0) - flags_ |= kUintFlag | kUint64Flag; - } - - //! Constructor for unsigned value. - GenericValue(unsigned u) : flags_(kNumberUintFlag) { - data_.n.u64 = u; - if (!(u & 0x80000000)) - flags_ |= kIntFlag | kInt64Flag; - } - - //! Constructor for int64_t value. - GenericValue(int64_t i64) : flags_(kNumberInt64Flag) { - data_.n.i64 = i64; - if (i64 >= 0) { - flags_ |= kNumberUint64Flag; - if (!(i64 & 0xFFFFFFFF00000000LL)) - flags_ |= kUintFlag; - if (!(i64 & 0xFFFFFFFF80000000LL)) - flags_ |= kIntFlag; - } - else if (i64 >= -2147483648LL) - flags_ |= kIntFlag; - } - - //! Constructor for uint64_t value. - GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) { - data_.n.u64 = u64; - if (!(u64 & 0x8000000000000000L)) - flags_ |= kInt64Flag; - if (!(u64 & 0xFFFFFFFF00000000L)) - flags_ |= kUintFlag; - if (!(u64 & 0xFFFFFFFF80000000L)) - flags_ |= kIntFlag; - } - - //! Constructor for double value. - GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; } - - //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s, SizeType length) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kConstStringFlag; - data_.s.str = s; - data_.s.length = length; - } - - //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); } - - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); } - - //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); } - - //! Destructor. - /*! Need to destruct elements of array, members of object, or copy-string. - */ - ~GenericValue() { - if (Allocator::kNeedFree) { // Shortcut by Allocator's trait - switch(flags_) { - case kArrayFlag: - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - v->~GenericValue(); - Allocator::Free(data_.a.elements); - break; - - case kObjectFlag: - for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { - m->name.~GenericValue(); - m->value.~GenericValue(); - } - Allocator::Free(data_.o.members); - break; - - case kCopyStringFlag: - Allocator::Free((void*)data_.s.str); - break; - } - } - } - - //@} - - //!@name Assignment operators - //@{ - - //! Assignment with move semantics. - /*! \param rhs Source of the assignment. It will become a null value after assignment. - */ - GenericValue& operator=(GenericValue& rhs) { - RAPIDJSON_ASSERT(this != &rhs); - this->~GenericValue(); - memcpy(this, &rhs, sizeof(GenericValue)); - rhs.flags_ = kNullFlag; - return *this; - } - - //! Assignment with primitive types. - /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch* - \param value The value to be assigned. - */ - template - GenericValue& operator=(T value) { - this->~GenericValue(); - new (this) GenericValue(value); - return *this; - } - //@} - - //!@name Type - //@{ - - Type GetType() const { return static_cast(flags_ & kTypeMask); } - bool IsNull() const { return flags_ == kNullFlag; } - bool IsFalse() const { return flags_ == kFalseFlag; } - bool IsTrue() const { return flags_ == kTrueFlag; } - bool IsBool() const { return (flags_ & kBoolFlag) != 0; } - bool IsObject() const { return flags_ == kObjectFlag; } - bool IsArray() const { return flags_ == kArrayFlag; } - bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } - bool IsInt() const { return (flags_ & kIntFlag) != 0; } - bool IsUint() const { return (flags_ & kUintFlag) != 0; } - bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } - bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } - bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } - bool IsString() const { return (flags_ & kStringFlag) != 0; } - - //@} - - //!@name Null - //@{ - - GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } - - //@} - - //!@name Bool - //@{ - - bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } - GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } - - //@} - - //!@name Object - //@{ - - //! Set this value as an empty object. - GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } - - //! Get the value associated with the object's name. - GenericValue& operator[](const Ch* name) { - if (Member* member = FindMember(name)) - return member->value; - else { - static GenericValue NullValue; - return NullValue; - } - } - const GenericValue& operator[](const Ch* name) const { return const_cast(*this)[name]; } - - //! Member iterators. - ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } - ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } - MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } - MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } - - //! Check whether a member exists in the object. - bool HasMember(const Ch* name) const { return FindMember(name) != 0; } - - //! Add a member (name-value pair) to the object. - /*! \param name A string value as name of member. - \param value Value of any type. - \param allocator Allocator for reallocating memory. - \return The value itself for fluent API. - \note The ownership of name and value will be transfered to this object if success. - */ - GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(name.IsString()); - Object& o = data_.o; - if (o.size >= o.capacity) { - if (o.capacity == 0) { - o.capacity = kDefaultObjectCapacity; - o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member)); - } - else { - SizeType oldCapacity = o.capacity; - o.capacity *= 2; - o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)); - } - } - o.members[o.size].name = name; - o.members[o.size].value = value; - o.size++; - return *this; - } - - GenericValue& AddMember(const char* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name), nameAllocator); - return AddMember(n, value, allocator); - } - - GenericValue& AddMember(const char* name, GenericValue& value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name)); - return AddMember(n, value, allocator); - } - - template - GenericValue& AddMember(const char* name, T value, Allocator& allocator) { - GenericValue n(name, internal::StrLen(name)); - GenericValue v(value); - return AddMember(n, v, allocator); - } - - //! Remove a member in object by its name. - /*! \param name Name of member to be removed. - \return Whether the member existed. - \note Removing member is implemented by moving the last member. So the ordering of members is changed. - */ - bool RemoveMember(const Ch* name) { - RAPIDJSON_ASSERT(IsObject()); - if (Member* m = FindMember(name)) { - RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(data_.o.members != 0); - - if (data_.o.size > 1) { - // Move the last one to this place - Member* last = data_.o.members + (data_.o.size - 1); - m->name = last->name; - m->value = last->value; - } - else { - // Only one left, just destroy - m->name.~GenericValue(); - m->value.~GenericValue(); - } - --data_.o.size; - return true; - } - return false; - } - - //@} - - //!@name Array - //@{ - - //! Set this value as an empty array. - GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } - - //! Get the number of elements in array. - SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } - - //! Get the capacity of array. - SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } - - //! Check whether the array is empty. - bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } - - //! Remove all elements in the array. - /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. - */ - void Clear() { - RAPIDJSON_ASSERT(IsArray()); - for (SizeType i = 0; i < data_.a.size; ++i) - data_.a.elements[i].~GenericValue(); - data_.a.size = 0; - } - - //! Get an element from array by index. - /*! \param index Zero-based index of element. - \note -\code -Value a(kArrayType); -a.PushBack(123); -int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. -int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. -int z = a[0u].GetInt(); // This works too. -\endcode - */ - GenericValue& operator[](SizeType index) { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(index < data_.a.size); - return data_.a.elements[index]; - } - const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } - - //! Element iterator - ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } - ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } - ConstValueIterator Begin() const { return const_cast(*this).Begin(); } - ConstValueIterator End() const { return const_cast(*this).End(); } - - //! Request the array to have enough capacity to store elements. - /*! \param newCapacity The capacity that the array at least need to have. - \param allocator The allocator for allocating memory. It must be the same one use previously. - \return The value itself for fluent API. - */ - GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (newCapacity > data_.a.capacity) { - data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); - data_.a.capacity = newCapacity; - } - return *this; - } - - //! Append a value at the end of the array. - /*! \param value The value to be appended. - \param allocator The allocator for allocating memory. It must be the same one use previously. - \return The value itself for fluent API. - \note The ownership of the value will be transfered to this object if success. - \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. - */ - GenericValue& PushBack(GenericValue& value, Allocator& allocator) { - RAPIDJSON_ASSERT(IsArray()); - if (data_.a.size >= data_.a.capacity) - Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator); - data_.a.elements[data_.a.size++] = value; - return *this; - } - - template - GenericValue& PushBack(T value, Allocator& allocator) { - GenericValue v(value); - return PushBack(v, allocator); - } - - //! Remove the last element in the array. - GenericValue& PopBack() { - RAPIDJSON_ASSERT(IsArray()); - RAPIDJSON_ASSERT(!Empty()); - data_.a.elements[--data_.a.size].~GenericValue(); - return *this; - } - //@} - - //!@name Number - //@{ - - int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i; } - unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u; } - int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } - int64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.u64; } - - double GetDouble() const { - RAPIDJSON_ASSERT(IsNumber()); - if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. - if ((flags_ & kIntFlag) != 0) return data_.n.i; // int -> double - if ((flags_ & kUintFlag) != 0) return data_.n.u; // unsigned -> double - if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) - RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) - } - - GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } - GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } - GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } - GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } - GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } - - //@} - - //!@name String - //@{ - - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; } - - //! Get the length of string. - /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). - */ - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; } - - //! Set this value as a string without copying source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string pointer. - \param length The length of source string, excluding the trailing null terminator. - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; } - - //! Set this value as a string without copying source string. - /*! \param s source string pointer. - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); } - - //! Set this value as a string by copying from source string. - /*! This version has better performance with supplied length, and also support string containing null character. - \param s source string. - \param length The length of source string, excluding the trailing null terminator. - \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; } - - //! Set this value as a string by copying from source string. - /*! \param s source string. - \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). - \return The value itself for fluent API. - */ - GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; } - - //@} - - //! Generate events of this value to a Handler. - /*! This function adopts the GoF visitor pattern. - Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. - It can also be used to deep clone this value via GenericDocument, which is also a Handler. - \tparam Handler type of handler. - \param handler An object implementing concept Handler. - */ - template - GenericValue& Accept(Handler& handler) { - switch(GetType()) { - case kNullType: handler.Null(); break; - case kFalseType: handler.Bool(false); break; - case kTrueType: handler.Bool(true); break; - - case kObjectType: - handler.StartObject(); - for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { - handler.String(m->name.data_.s.str, m->name.data_.s.length, false); - m->value.Accept(handler); - } - handler.EndObject(data_.o.size); - break; - - case kArrayType: - handler.StartArray(); - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - v->Accept(handler); - handler.EndArray(data_.a.size); - break; - - case kStringType: - handler.String(data_.s.str, data_.s.length, false); - break; - - case kNumberType: - if (IsInt()) handler.Int(data_.n.i); - else if (IsUint()) handler.Uint(data_.n.u); - else if (IsInt64()) handler.Int64(data_.n.i64); - else if (IsUint64()) handler.Uint64(data_.n.i64); - else handler.Double(data_.n.d); - break; - } - return *this; - } - -private: - template - friend class GenericDocument; - - enum { - kBoolFlag = 0x100, - kNumberFlag = 0x200, - kIntFlag = 0x400, - kUintFlag = 0x800, - kInt64Flag = 0x1000, - kUint64Flag = 0x2000, - kDoubleFlag = 0x4000, - kStringFlag = 0x100000, - kCopyFlag = 0x200000, - - // Initial flags of different types. - kNullFlag = kNullType, - kTrueFlag = kTrueType | kBoolFlag, - kFalseFlag = kFalseType | kBoolFlag, - kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, - kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag, - kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, - kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, - kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, - kConstStringFlag = kStringType | kStringFlag, - kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, - kObjectFlag = kObjectType, - kArrayFlag = kArrayType, - - kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler - }; - - static const SizeType kDefaultArrayCapacity = 16; - static const SizeType kDefaultObjectCapacity = 16; - - struct String { - const Ch* str; - SizeType length; - unsigned hashcode; //!< reserved - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - // By using proper binary layout, retrieval of different integer types do not need conversions. - union Number { -#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN - struct { - int i; - char padding[4]; - }; - struct { - unsigned u; - char padding2[4]; - }; -#else - struct { - char padding[4]; - int i; - }; - struct { - char padding2[4]; - unsigned u; - }; -#endif - int64_t i64; - uint64_t u64; - double d; - }; // 8 bytes - - struct Object { - Member* members; - SizeType size; - SizeType capacity; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - struct Array { - GenericValue* elements; - SizeType size; - SizeType capacity; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - union Data { - String s; - Number n; - Object o; - Array a; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - - //! Find member by name. - Member* FindMember(const Ch* name) { - RAPIDJSON_ASSERT(name); - RAPIDJSON_ASSERT(IsObject()); - - Object& o = data_.o; - for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) - if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) - return member; - - return 0; - } - const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } - - // Initialize this value as array with initial data, without calling destructor. - void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { - flags_ = kArrayFlag; - data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue)); - memcpy(data_.a.elements, values, count * sizeof(GenericValue)); - data_.a.size = data_.a.capacity = count; - } - - //! Initialize this value as object with initial data, without calling destructor. - void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) { - flags_ = kObjectFlag; - data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member)); - memcpy(data_.o.members, members, count * sizeof(Member)); - data_.o.size = data_.o.capacity = count; - } - - //! Initialize this value as constant string, without calling destructor. - void SetStringRaw(const Ch* s, SizeType length) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kConstStringFlag; - data_.s.str = s; - data_.s.length = length; - } - - //! Initialize this value as copy string with initial data, without calling destructor. - void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) { - RAPIDJSON_ASSERT(s != NULL); - flags_ = kCopyStringFlag; - data_.s.str = (char *)allocator.Malloc(length + 1); - data_.s.length = length; - memcpy((void*)data_.s.str, s, length); - ((char*)data_.s.str)[length] = '\0'; - } - - //! Assignment without calling destructor - void RawAssign(GenericValue& rhs) { - memcpy(this, &rhs, sizeof(GenericValue)); - rhs.flags_ = kNullFlag; - } - - Data data_; - unsigned flags_; -}; -#pragma pack (pop) - -//! Value with UTF8 encoding. -typedef GenericValue > Value; - -/////////////////////////////////////////////////////////////////////////////// -// GenericDocument - -//! A document for parsing JSON text as DOM. -/*! - \implements Handler - \tparam Encoding encoding for both parsing and string storage. - \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing. -*/ -template > -class GenericDocument : public GenericValue { -public: - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue ValueType; //!< Value type of the document. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - - //! Constructor - /*! \param allocator Optional allocator for allocating stack memory. - \param stackCapacity Initial capacity of stack in bytes. - */ - GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} - - //! Parse JSON text from an input stream. - /*! \tparam parseFlags Combination of ParseFlag. - \param stream Input stream to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseStream(Stream& stream) { - ValueType::SetNull(); // Remove existing root if exist - GenericReader reader; - if (reader.Parse(stream, *this)) { - RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - this->RawAssign(*stack_.template Pop(1)); - parseError_ = 0; - errorOffset_ = 0; - } - else { - parseError_ = reader.GetParseError(); - errorOffset_ = reader.GetErrorOffset(); - ClearStack(); - } - return *this; - } - - //! Parse JSON text from a mutable string. - /*! \tparam parseFlags Combination of ParseFlag. - \param str Mutable zero-terminated string to be parsed. - \return The document itself for fluent API. - */ - template - GenericDocument& ParseInsitu(Ch* str) { - GenericInsituStringStream s(str); - return ParseStream(s); - } - - //! Parse JSON text from a read-only string. - /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). - \param str Read-only zero-terminated string to be parsed. - */ - template - GenericDocument& Parse(const Ch* str) { - RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); - GenericStringStream s(str); - return ParseStream(s); - } - - //! Whether a parse error was occured in the last parsing. - bool HasParseError() const { return parseError_ != 0; } - - //! Get the message of parsing error. - const char* GetParseError() const { return parseError_; } - - //! Get the offset in character of the parsing error. - size_t GetErrorOffset() const { return errorOffset_; } - - //! Get the allocator of this document. - Allocator& GetAllocator() { return stack_.GetAllocator(); } - - //! Get the capacity of stack in bytes. - size_t GetStackCapacity() const { return stack_.GetCapacity(); } - -private: - friend class GenericReader; // for Reader to call the following private handler functions - - // Implementation of Handler - void Null() { new (stack_.template Push()) ValueType(); } - void Bool(bool b) { new (stack_.template Push()) ValueType(b); } - void Int(int i) { new (stack_.template Push()) ValueType(i); } - void Uint(unsigned i) { new (stack_.template Push()) ValueType(i); } - void Int64(int64_t i) { new (stack_.template Push()) ValueType(i); } - void Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); } - void Double(double d) { new (stack_.template Push()) ValueType(d); } - - void String(const Ch* str, SizeType length, bool copy) { - if (copy) - new (stack_.template Push()) ValueType(str, length, GetAllocator()); - else - new (stack_.template Push()) ValueType(str, length); - } - - void StartObject() { new (stack_.template Push()) ValueType(kObjectType); } - - void EndObject(SizeType memberCount) { - typename ValueType::Member* members = stack_.template Pop(memberCount); - stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); - } - - void StartArray() { new (stack_.template Push()) ValueType(kArrayType); } - - void EndArray(SizeType elementCount) { - ValueType* elements = stack_.template Pop(elementCount); - stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); - } - - void ClearStack() { - if (Allocator::kNeedFree) - while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) - (stack_.template Pop(1))->~ValueType(); - else - stack_.Clear(); - } - - static const size_t kDefaultStackCapacity = 1024; - internal::Stack stack_; - const char* parseError_; - size_t errorOffset_; -}; - -typedef GenericDocument > Document; - -} // namespace rapidjson - -#endif // RAPIDJSON_DOCUMENT_H_ +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +#include "reader.h" +#include "internal/strfunc.h" + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +#pragma pack (push, 4) +template > +class GenericValue { +public: + //! Name-value pair in an object. + struct Member { + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. + }; + + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef Member* MemberIterator; //!< Member iterator for iterating in object. + typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() : flags_(kNullFlag) {} + + //! Copy constructor is not permitted. +private: + GenericValue(const GenericValue& rhs); + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + GenericValue(Type type) { + static const unsigned defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, + kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + flags_ = defaultFlags[type]; + memset(&data_, 0, sizeof(data_)); + } + + //! Constructor for boolean value. + GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} + + //! Constructor for int value. + GenericValue(int i) : flags_(kNumberIntFlag) { + data_.n.i64 = i; + if (i >= 0) + flags_ |= kUintFlag | kUint64Flag; + } + + //! Constructor for unsigned value. + GenericValue(unsigned u) : flags_(kNumberUintFlag) { + data_.n.u64 = u; + if (!(u & 0x80000000)) + flags_ |= kIntFlag | kInt64Flag; + } + + //! Constructor for int64_t value. + GenericValue(int64_t i64) : flags_(kNumberInt64Flag) { + data_.n.i64 = i64; + if (i64 >= 0) { + flags_ |= kNumberUint64Flag; + if (!(i64 & 0xFFFFFFFF00000000LL)) + flags_ |= kUintFlag; + if (!(i64 & 0xFFFFFFFF80000000LL)) + flags_ |= kIntFlag; + } + else if (i64 >= -2147483648LL) + flags_ |= kIntFlag; + } + + //! Constructor for uint64_t value. + GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) { + data_.n.u64 = u64; + if (!(u64 & 0x8000000000000000L)) + flags_ |= kInt64Flag; + if (!(u64 & 0xFFFFFFFF00000000L)) + flags_ |= kUintFlag; + if (!(u64 & 0xFFFFFFFF80000000L)) + flags_ |= kIntFlag; + } + + //! Constructor for double value. + GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = length; + } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(flags_) { + case kArrayFlag: + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(data_.a.elements); + break; + + case kObjectFlag: + for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { + m->name.~GenericValue(); + m->value.~GenericValue(); + } + Allocator::Free(data_.o.members); + break; + + case kCopyStringFlag: + Allocator::Free((void*)data_.s.str); + break; + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + memcpy(this, &rhs, sizeof(GenericValue)); + rhs.flags_ = kNullFlag; + return *this; + } + + //! Assignment with primitive types. + /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch* + \param value The value to be assigned. + */ + template + GenericValue& operator=(T value) { + this->~GenericValue(); + new (this) GenericValue(value); + return *this; + } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast(flags_ & kTypeMask); } + bool IsNull() const { return flags_ == kNullFlag; } + bool IsFalse() const { return flags_ == kFalseFlag; } + bool IsTrue() const { return flags_ == kTrueFlag; } + bool IsBool() const { return (flags_ & kBoolFlag) != 0; } + bool IsObject() const { return flags_ == kObjectFlag; } + bool IsArray() const { return flags_ == kArrayFlag; } + bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } + bool IsInt() const { return (flags_ & kIntFlag) != 0; } + bool IsUint() const { return (flags_ & kUintFlag) != 0; } + bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } + bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } + bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } + bool IsString() const { return (flags_ & kStringFlag) != 0; } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the value associated with the object's name. + GenericValue& operator[](const Ch* name) { + if (Member* member = FindMember(name)) + return member->value; + else { + static GenericValue NullValue; + return NullValue; + } + } + const GenericValue& operator[](const Ch* name) const { return const_cast(*this)[name]; } + + //! Member iterators. + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } + + //! Check whether a member exists in the object. + bool HasMember(const Ch* name) const { return FindMember(name) != 0; } + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. + \return The value itself for fluent API. + \note The ownership of name and value will be transfered to this object if success. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + Object& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member)); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity *= 2; + o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)); + } + } + o.members[o.size].name = name; + o.members[o.size].value = value; + o.size++; + return *this; + } + + GenericValue& AddMember(const char* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name), nameAllocator); + return AddMember(n, value, allocator); + } + + GenericValue& AddMember(const char* name, GenericValue& value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name)); + return AddMember(n, value, allocator); + } + + template + GenericValue& AddMember(const char* name, T value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name)); + GenericValue v(value); + return AddMember(n, v, allocator); + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Removing member is implemented by moving the last member. So the ordering of members is changed. + */ + bool RemoveMember(const Ch* name) { + RAPIDJSON_ASSERT(IsObject()); + if (Member* m = FindMember(name)) { + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + + if (data_.o.size > 1) { + // Move the last one to this place + Member* last = data_.o.members + (data_.o.size - 1); + m->name = last->name; + m->value = last->value; + } + else { + // Only one left, just destroy + m->name.~GenericValue(); + m->value.~GenericValue(); + } + --data_.o.size; + return true; + } + return false; + } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + for (SizeType i = 0; i < data_.a.size; ++i) + data_.a.elements[i].~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \param index Zero-based index of element. + \note +\code +Value a(kArrayType); +a.PushBack(123); +int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. +int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. +int z = a[0u].GetInt(); // This works too. +\endcode + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator The allocator for allocating memory. It must be the same one use previously. + \return The value itself for fluent API. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a value at the end of the array. + /*! \param value The value to be appended. + \param allocator The allocator for allocating memory. It must be the same one use previously. + \return The value itself for fluent API. + \note The ownership of the value will be transfered to this object if success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator); + data_.a.elements[data_.a.size++] = value; + return *this; + } + + template + GenericValue& PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + data_.a.elements[--data_.a.size].~GenericValue(); + return *this; + } + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } + int64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.u64; } + + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((flags_ & kIntFlag) != 0) return data_.n.i; // int -> double + if ((flags_ & kUintFlag) != 0) return data_.n.u; // unsigned -> double + if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; } + + //! Get the length of string. + /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; } + + //! Set this value as a string without copying source string. + /*! \param s source string pointer. + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + GenericValue& Accept(Handler& handler) { + switch(GetType()) { + case kNullType: handler.Null(); break; + case kFalseType: handler.Bool(false); break; + case kTrueType: handler.Bool(true); break; + + case kObjectType: + handler.StartObject(); + for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { + handler.String(m->name.data_.s.str, m->name.data_.s.length, false); + m->value.Accept(handler); + } + handler.EndObject(data_.o.size); + break; + + case kArrayType: + handler.StartArray(); + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->Accept(handler); + handler.EndArray(data_.a.size); + break; + + case kStringType: + handler.String(data_.s.str, data_.s.length, false); + break; + + case kNumberType: + if (IsInt()) handler.Int(data_.n.i); + else if (IsUint()) handler.Uint(data_.n.u); + else if (IsInt64()) handler.Int64(data_.n.i64); + else if (IsUint64()) handler.Uint64(data_.n.i64); + else handler.Double(data_.n.d); + break; + } + return *this; + } + +private: + template + friend class GenericDocument; + + enum { + kBoolFlag = 0x100, + kNumberFlag = 0x200, + kIntFlag = 0x400, + kUintFlag = 0x800, + kInt64Flag = 0x1000, + kUint64Flag = 0x2000, + kDoubleFlag = 0x4000, + kStringFlag = 0x100000, + kCopyFlag = 0x200000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct String { + const Ch* str; + SizeType length; + unsigned hashcode; //!< reserved + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct { + int i; + char padding[4]; + }; + struct { + unsigned u; + char padding2[4]; + }; +#else + struct { + char padding[4]; + int i; + }; + struct { + char padding2[4]; + unsigned u; + }; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct Object { + Member* members; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct Array { + GenericValue* elements; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + Number n; + Object o; + Array a; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + //! Find member by name. + Member* FindMember(const Ch* name) { + RAPIDJSON_ASSERT(name); + RAPIDJSON_ASSERT(IsObject()); + + Object& o = data_.o; + for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) + if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) + return member; + + return 0; + } + const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { + flags_ = kArrayFlag; + data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue)); + memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) { + flags_ = kObjectFlag; + data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member)); + memcpy(data_.o.members, members, count * sizeof(Member)); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(const Ch* s, SizeType length) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kCopyStringFlag; + data_.s.str = (char *)allocator.Malloc(length + 1); + data_.s.length = length; + memcpy((void*)data_.s.str, s, length); + ((char*)data_.s.str)[length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) { + memcpy(this, &rhs, sizeof(GenericValue)); + rhs.flags_ = kNullFlag; + } + + Data data_; + unsigned flags_; +}; +#pragma pack (pop) + +//! Value with UTF8 encoding. +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \implements Handler + \tparam Encoding encoding for both parsing and string storage. + \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing. +*/ +template > +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! \param allocator Optional allocator for allocating stack memory. + \param stackCapacity Initial capacity of stack in bytes. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} + + //! Parse JSON text from an input stream. + /*! \tparam parseFlags Combination of ParseFlag. + \param stream Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(Stream& stream) { + ValueType::SetNull(); // Remove existing root if exist + GenericReader reader; + if (reader.template Parse(stream, *this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + this->RawAssign(*stack_.template Pop(1)); + parseError_ = 0; + errorOffset_ = 0; + } + else { + parseError_ = reader.GetParseError(); + errorOffset_ = reader.GetErrorOffset(); + ClearStack(); + } + return *this; + } + + //! Parse JSON text from a mutable string. + /*! \tparam parseFlags Combination of ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string. + /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Whether a parse error was occured in the last parsing. + bool HasParseError() const { return parseError_ != 0; } + + //! Get the message of parsing error. + const char* GetParseError() const { return parseError_; } + + //! Get the offset in character of the parsing error. + size_t GetErrorOffset() const { return errorOffset_; } + + //! Get the allocator of this document. + Allocator& GetAllocator() { return stack_.GetAllocator(); } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + friend class GenericReader; // for Reader to call the following private handler functions + + // Implementation of Handler + void Null() { new (stack_.template Push()) ValueType(); } + void Bool(bool b) { new (stack_.template Push()) ValueType(b); } + void Int(int i) { new (stack_.template Push()) ValueType(i); } + void Uint(unsigned i) { new (stack_.template Push()) ValueType(i); } + void Int64(int64_t i) { new (stack_.template Push()) ValueType(i); } + void Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); } + void Double(double d) { new (stack_.template Push()) ValueType(d); } + + void String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + } + + void StartObject() { new (stack_.template Push()) ValueType(kObjectType); } + + void EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + } + + void StartArray() { new (stack_.template Push()) ValueType(kArrayType); } + + void EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + } + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + } + + static const size_t kDefaultStackCapacity = 1024; + internal::Stack stack_; + const char* parseError_; + size_t errorOffset_; +}; + +typedef GenericDocument > Document; + +} // namespace rapidjson + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/libs/network/example/twitter/rapidjson/filestream.h b/contrib/http_examples/twitter/rapidjson/filestream.h similarity index 95% rename from libs/network/example/twitter/rapidjson/filestream.h rename to contrib/http_examples/twitter/rapidjson/filestream.h index 24573aa48..885894963 100644 --- a/libs/network/example/twitter/rapidjson/filestream.h +++ b/contrib/http_examples/twitter/rapidjson/filestream.h @@ -1,46 +1,46 @@ -#ifndef RAPIDJSON_FILESTREAM_H_ -#define RAPIDJSON_FILESTREAM_H_ - -#include - -namespace rapidjson { - -//! Wrapper of C file stream for input or output. -/*! - This simple wrapper does not check the validity of the stream. - \implements Stream -*/ -class FileStream { -public: - typedef char Ch; //!< Character type. Only support char. - - FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } - char Peek() const { return current_; } - char Take() { char c = current_; Read(); return c; } - size_t Tell() const { return count_; } - void Put(char c) { fputc(c, fp_); } - - // Not implemented - char* PutBegin() { return 0; } - size_t PutEnd(char*) { return 0; } - -private: - void Read() { - RAPIDJSON_ASSERT(fp_ != 0); - int c = fgetc(fp_); - if (c != EOF) { - current_ = (char)c; - count_++; - } - else - current_ = '\0'; - } - - FILE* fp_; - char current_; - size_t count_; -}; - -} // namespace rapidjson - -#endif // RAPIDJSON_FILESTREAM_H_ +#ifndef RAPIDJSON_FILESTREAM_H_ +#define RAPIDJSON_FILESTREAM_H_ + +#include + +namespace rapidjson { + +//! Wrapper of C file stream for input or output. +/*! + This simple wrapper does not check the validity of the stream. + \implements Stream +*/ +class FileStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } + char Peek() const { return current_; } + char Take() { char c = current_; Read(); return c; } + size_t Tell() const { return count_; } + void Put(char c) { fputc(c, fp_); } + + // Not implemented + char* PutBegin() { return 0; } + size_t PutEnd(char*) { return 0; } + +private: + void Read() { + RAPIDJSON_ASSERT(fp_ != 0); + int c = fgetc(fp_); + if (c != EOF) { + current_ = (char)c; + count_++; + } + else + current_ = '\0'; + } + + FILE* fp_; + char current_; + size_t count_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/libs/network/example/twitter/rapidjson/internal/pow10.h b/contrib/http_examples/twitter/rapidjson/internal/pow10.h similarity index 98% rename from libs/network/example/twitter/rapidjson/internal/pow10.h rename to contrib/http_examples/twitter/rapidjson/internal/pow10.h index 0852539e7..bf3a9afb0 100644 --- a/libs/network/example/twitter/rapidjson/internal/pow10.h +++ b/contrib/http_examples/twitter/rapidjson/internal/pow10.h @@ -1,54 +1,54 @@ -#ifndef RAPIDJSON_POW10_ -#define RAPIDJSON_POW10_ - -namespace rapidjson { -namespace internal { - -//! Computes integer powers of 10 in double (10.0^n). -/*! This function uses lookup table for fast and accurate results. - \param n positive/negative exponent. Must <= 308. - \return 10.0^n -*/ -inline double Pow10(int n) { - static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes - 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300, - 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280, - 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260, - 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240, - 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220, - 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200, - 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180, - 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160, - 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140, - 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120, - 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100, - 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, - 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, - 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, - 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, - 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, - 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, - 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, - 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, - 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, - 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, - 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, - 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, - 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, - 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, - 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, - 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, - 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, - 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, - 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, - 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, - 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 - }; - RAPIDJSON_ASSERT(n <= 308); - return n < -308 ? 0.0 : e[n + 308]; -} - -} // namespace internal -} // namespace rapidjson - -#endif // RAPIDJSON_POW10_ +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +namespace rapidjson { +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n positive/negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes + 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300, + 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280, + 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260, + 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240, + 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220, + 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200, + 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180, + 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160, + 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140, + 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120, + 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100, + 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, + 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, + 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, + 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, + 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n <= 308); + return n < -308 ? 0.0 : e[n + 308]; +} + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_POW10_ diff --git a/libs/network/example/twitter/rapidjson/internal/stack.h b/contrib/http_examples/twitter/rapidjson/internal/stack.h similarity index 96% rename from libs/network/example/twitter/rapidjson/internal/stack.h rename to contrib/http_examples/twitter/rapidjson/internal/stack.h index 6faefdee7..9f7259ada 100644 --- a/libs/network/example/twitter/rapidjson/internal/stack.h +++ b/contrib/http_examples/twitter/rapidjson/internal/stack.h @@ -1,82 +1,82 @@ -#ifndef RAPIDJSON_INTERNAL_STACK_H_ -#define RAPIDJSON_INTERNAL_STACK_H_ - -namespace rapidjson { -namespace internal { - -/////////////////////////////////////////////////////////////////////////////// -// Stack - -//! A type-unsafe stack for storing different types of data. -/*! \tparam Allocator Allocator for allocating stack memory. -*/ -template -class Stack { -public: - Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { - RAPIDJSON_ASSERT(stack_capacity_ > 0); - if (!allocator_) - own_allocator_ = allocator_ = new Allocator(); - stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); - stack_end_ = stack_ + stack_capacity_; - } - - ~Stack() { - Allocator::Free(stack_); - delete own_allocator_; // Only delete if it is owned by the stack - } - - void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } - - template - T* Push(size_t count = 1) { - // Expand the stack if needed - if (stack_top_ + sizeof(T) * count >= stack_end_) { - size_t new_capacity = stack_capacity_ * 2; - size_t size = GetSize(); - size_t new_size = GetSize() + sizeof(T) * count; - if (new_capacity < new_size) - new_capacity = new_size; - stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); - stack_capacity_ = new_capacity; - stack_top_ = stack_ + size; - stack_end_ = stack_ + stack_capacity_; - } - T* ret = (T*)stack_top_; - stack_top_ += sizeof(T) * count; - return ret; - } - - template - T* Pop(size_t count) { - RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); - stack_top_ -= count * sizeof(T); - return (T*)stack_top_; - } - - template - T* Top() { - RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); - return (T*)(stack_top_ - sizeof(T)); - } - - template - T* Bottom() { return (T*)stack_; } - - Allocator& GetAllocator() { return *allocator_; } - size_t GetSize() const { /*return stack_top_;*/ return stack_top_ - stack_; } - size_t GetCapacity() const { return stack_capacity_; } - -private: - Allocator* allocator_; - Allocator* own_allocator_; - char *stack_; - char *stack_top_; - char *stack_end_; - size_t stack_capacity_; -}; - -} // namespace internal -} // namespace rapidjson - -#endif // RAPIDJSON_STACK_H_ +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +namespace rapidjson { +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { + RAPIDJSON_ASSERT(stack_capacity_ > 0); + if (!allocator_) + own_allocator_ = allocator_ = new Allocator(); + stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); + stack_end_ = stack_ + stack_capacity_; + } + + ~Stack() { + Allocator::Free(stack_); + delete own_allocator_; // Only delete if it is owned by the stack + } + + void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } + + template + T* Push(size_t count = 1) { + // Expand the stack if needed + if (stack_top_ + sizeof(T) * count >= stack_end_) { + size_t new_capacity = stack_capacity_ * 2; + size_t size = GetSize(); + size_t new_size = GetSize() + sizeof(T) * count; + if (new_capacity < new_size) + new_capacity = new_size; + stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); + stack_capacity_ = new_capacity; + stack_top_ = stack_ + size; + stack_end_ = stack_ + stack_capacity_; + } + T* ret = (T*)stack_top_; + stack_top_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stack_top_ -= count * sizeof(T); + return (T*)stack_top_; + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return (T*)(stack_top_ - sizeof(T)); + } + + template + T* Bottom() { return (T*)stack_; } + + Allocator& GetAllocator() { return *allocator_; } + size_t GetSize() const { /*return stack_top_;*/ return stack_top_ - stack_; } + size_t GetCapacity() const { return stack_capacity_; } + +private: + Allocator* allocator_; + Allocator* own_allocator_; + char *stack_; + char *stack_top_; + char *stack_end_; + size_t stack_capacity_; +}; + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_STACK_H_ diff --git a/libs/network/example/twitter/rapidjson/internal/strfunc.h b/contrib/http_examples/twitter/rapidjson/internal/strfunc.h similarity index 96% rename from libs/network/example/twitter/rapidjson/internal/strfunc.h rename to contrib/http_examples/twitter/rapidjson/internal/strfunc.h index 47b8ac075..bbf444fe6 100644 --- a/libs/network/example/twitter/rapidjson/internal/strfunc.h +++ b/contrib/http_examples/twitter/rapidjson/internal/strfunc.h @@ -1,24 +1,24 @@ -#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ -#define RAPIDJSON_INTERNAL_STRFUNC_H_ - -namespace rapidjson { -namespace internal { - -//! Custom strlen() which works on different character types. -/*! \tparam Ch Character type (e.g. char, wchar_t, short) - \param s Null-terminated input string. - \return Number of characters in the string. - \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. -*/ -template -inline SizeType StrLen(const Ch* s) { - const Ch* p = s; - while (*p != '\0') - ++p; - return SizeType(p - s); -} - -} // namespace internal -} // namespace rapidjson - -#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +namespace rapidjson { +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p != '\0') + ++p; + return SizeType(p - s); +} + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/libs/network/example/twitter/rapidjson/prettywriter.h b/contrib/http_examples/twitter/rapidjson/prettywriter.h similarity index 97% rename from libs/network/example/twitter/rapidjson/prettywriter.h rename to contrib/http_examples/twitter/rapidjson/prettywriter.h index 6f282933d..ead8824f8 100644 --- a/libs/network/example/twitter/rapidjson/prettywriter.h +++ b/contrib/http_examples/twitter/rapidjson/prettywriter.h @@ -1,152 +1,152 @@ -#ifndef RAPIDJSON_PRETTYWRITER_H_ -#define RAPIDJSON_PRETTYWRITER_H_ - -#include "writer.h" - -namespace rapidjson { - -//! Writer with indentation and spacing. -/*! - \tparam Stream Type of ouptut stream. - \tparam Encoding Encoding of both source strings and output. - \tparam Allocator Type of allocator for allocating memory of stack. -*/ -template, typename Allocator = MemoryPoolAllocator<> > -class PrettyWriter : public Writer { -public: - typedef Writer Base; - typedef typename Base::Ch Ch; - - //! Constructor - /*! \param stream Output stream. - \param allocator User supplied allocator. If it is null, it will create a private one. - \param levelDepth Initial capacity of - */ - PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : - Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} - - //! Set custom indentation. - /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r'). - \param indentCharCount Number of indent characters for each indentation level. - \note The default indentation is 4 spaces. - */ - PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { - RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); - indentChar_ = indentChar; - indentCharCount_ = indentCharCount; - return *this; - } - - //@name Implementation of Handler. - //@{ - - PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } - PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } - PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } - PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } - PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } - PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } - PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } - - PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { - PrettyPrefix(kStringType); - Base::WriteString(str, length); - return *this; - } - - PrettyWriter& StartObject() { - PrettyPrefix(kObjectType); - new (Base::level_stack_.template Push()) typename Base::Level(false); - Base::WriteStartObject(); - return *this; - } - - PrettyWriter& EndObject(SizeType memberCount = 0) { - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); - bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - - if (!empty) { - Base::stream_.Put('\n'); - WriteIndent(); - } - Base::WriteEndObject(); - return *this; - } - - PrettyWriter& StartArray() { - PrettyPrefix(kArrayType); - new (Base::level_stack_.template Push()) typename Base::Level(true); - Base::WriteStartArray(); - return *this; - } - - PrettyWriter& EndArray(SizeType memberCount = 0) { - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); - bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - - if (!empty) { - Base::stream_.Put('\n'); - WriteIndent(); - } - Base::WriteEndArray(); - return *this; - } - - //@} - - //! Simpler but slower overload. - PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } - -protected: - void PrettyPrefix(Type type) { - if (Base::level_stack_.GetSize() != 0) { // this value is not at root - typename Base::Level* level = Base::level_stack_.template Top(); - - if (level->inArray) { - if (level->valueCount > 0) { - Base::stream_.Put(','); // add comma if it is not the first element in array - Base::stream_.Put('\n'); - } - else - Base::stream_.Put('\n'); - WriteIndent(); - } - else { // in object - if (level->valueCount > 0) { - if (level->valueCount % 2 == 0) { - Base::stream_.Put(','); - Base::stream_.Put('\n'); - } - else { - Base::stream_.Put(':'); - Base::stream_.Put(' '); - } - } - else - Base::stream_.Put('\n'); - - if (level->valueCount % 2 == 0) - WriteIndent(); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else - RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); - } - - void WriteIndent() { - size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; - PutN(Base::stream_, indentChar_, count); - } - - Ch indentChar_; - unsigned indentCharCount_; -}; - -} // namespace rapidjson - -#endif // RAPIDJSON_RAPIDJSON_H_ +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +namespace rapidjson { + +//! Writer with indentation and spacing. +/*! + \tparam Stream Type of ouptut stream. + \tparam Encoding Encoding of both source strings and output. + \tparam Allocator Type of allocator for allocating memory of stack. +*/ +template, typename Allocator = MemoryPoolAllocator<> > +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param stream Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of + */ + PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //@name Implementation of Handler. + //@{ + + PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } + PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } + PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } + PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } + PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } + PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } + PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } + + PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { + PrettyPrefix(kStringType); + Base::WriteString(str, length); + return *this; + } + + PrettyWriter& StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + Base::WriteStartObject(); + return *this; + } + + PrettyWriter& EndObject(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::stream_.Put('\n'); + WriteIndent(); + } + Base::WriteEndObject(); + return *this; + } + + PrettyWriter& StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + Base::WriteStartArray(); + return *this; + } + + PrettyWriter& EndArray(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::stream_.Put('\n'); + WriteIndent(); + } + Base::WriteEndArray(); + return *this; + } + + //@} + + //! Simpler but slower overload. + PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } + +protected: + void PrettyPrefix(Type type) { + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::stream_.Put(','); // add comma if it is not the first element in array + Base::stream_.Put('\n'); + } + else + Base::stream_.Put('\n'); + WriteIndent(); + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::stream_.Put(','); + Base::stream_.Put('\n'); + } + else { + Base::stream_.Put(':'); + Base::stream_.Put(' '); + } + } + else + Base::stream_.Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else + RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(Base::stream_, indentChar_, count); + } + + Ch indentChar_; + unsigned indentCharCount_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/rapidjson/rapidjson.h b/contrib/http_examples/twitter/rapidjson/rapidjson.h similarity index 96% rename from libs/network/example/twitter/rapidjson/rapidjson.h rename to contrib/http_examples/twitter/rapidjson/rapidjson.h index 14b0c3a3c..5a5a90379 100644 --- a/libs/network/example/twitter/rapidjson/rapidjson.h +++ b/contrib/http_examples/twitter/rapidjson/rapidjson.h @@ -1,512 +1,512 @@ -#ifndef RAPIDJSON_RAPIDJSON_H_ -#define RAPIDJSON_RAPIDJSON_H_ - -// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) -// Version 0.1 - -#include // malloc(), realloc(), free() -#include // memcpy() - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_NO_INT64DEFINE - -// Here defines int64_t and uint64_t types in global namespace. -// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. -#ifndef RAPIDJSON_NO_INT64DEFINE -#ifdef _MSC_VER -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif -#endif // RAPIDJSON_NO_INT64TYPEDEF - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_ENDIAN -#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine -#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine - -//! Endianness of the machine. -/*! GCC provided macro for detecting endianness of the target machine. But other - compilers may not have this. User can define RAPIDJSON_ENDIAN to either - RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. -*/ -#ifndef RAPIDJSON_ENDIAN -#ifdef __BYTE_ORDER__ -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN -#else -#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN -#endif // __BYTE_ORDER__ -#else -#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise. -#endif -#endif // RAPIDJSON_ENDIAN - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD - -// Enable SSE2 optimization. -//#define RAPIDJSON_SSE2 - -// Enable SSE4.2 optimization. -//#define RAPIDJSON_SSE42 - -#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) -#define RAPIDJSON_SIMD -#endif - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_NO_SIZETYPEDEFINE - -#ifndef RAPIDJSON_NO_SIZETYPEDEFINE -namespace rapidjson { -//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t. -/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE. -*/ -typedef unsigned SizeType; -} // namespace rapidjson -#endif - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_ASSERT - -//! Assertion. -/*! By default, rapidjson uses C assert() for assertion. - User can override it by defining RAPIDJSON_ASSERT(x) macro. -*/ -#ifndef RAPIDJSON_ASSERT -#include -#define RAPIDJSON_ASSERT(x) assert(x) -#endif // RAPIDJSON_ASSERT - -namespace rapidjson { - -/////////////////////////////////////////////////////////////////////////////// -// Allocator - -/*! \class rapidjson::Allocator - \brief Concept for allocating, resizing and freeing memory block. - - Note that Malloc() and Realloc() are non-static but Free() is static. - - So if an allocator need to support Free(), it needs to put its pointer in - the header of memory block. - -\code -concept Allocator { - static const bool kNeedFree; //!< Whether this allocator needs to call Free(). - - // Allocate a memory block. - // \param size of the memory block in bytes. - // \returns pointer to the memory block. - void* Malloc(size_t size); - - // Resize a memory block. - // \param originalPtr The pointer to current memory block. Null pointer is permitted. - // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) - // \param newSize the new size in bytes. - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); - - // Free a memory block. - // \param pointer to the memory block. Null pointer is permitted. - static void Free(void *ptr); -}; -\endcode -*/ - -/////////////////////////////////////////////////////////////////////////////// -// CrtAllocator - -//! C-runtime library allocator. -/*! This class is just wrapper for standard C library memory routines. - \implements Allocator -*/ -class CrtAllocator { -public: - static const bool kNeedFree = true; - void* Malloc(size_t size) { return malloc(size); } - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { return realloc(originalPtr, newSize); } - static void Free(void *ptr) { free(ptr); } -}; - -/////////////////////////////////////////////////////////////////////////////// -// MemoryPoolAllocator - -//! Default memory allocator used by the parser and DOM. -/*! This allocator allocate memory blocks from pre-allocated memory chunks. - - It does not free memory blocks. And Realloc() only allocate new memory. - - The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. - - User may also supply a buffer as the first chunk. - - If the user-buffer is full then additional chunks are allocated by BaseAllocator. - - The user-buffer is not deallocated by this allocator. - - \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. - \implements Allocator -*/ -template -class MemoryPoolAllocator { -public: - static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) - - //! Constructor with chunkSize. - /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. - \param baseAllocator The allocator for allocating memory chunks. - */ - MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) - { - if (!baseAllocator_) - ownBaseAllocator_ = baseAllocator_ = new BaseAllocator(); - AddChunk(chunk_capacity_); - } - - //! Constructor with user-supplied buffer. - /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. - - The user buffer will not be deallocated when this allocator is destructed. - - \param buffer User supplied buffer. - \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). - \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. - \param baseAllocator The allocator for allocating memory chunks. - */ - MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : - chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) - { - RAPIDJSON_ASSERT(buffer != 0); - RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); - chunkHead_ = (ChunkHeader*)buffer; - chunkHead_->capacity = size - sizeof(ChunkHeader); - chunkHead_->size = 0; - chunkHead_->next = 0; - } - - //! Destructor. - /*! This deallocates all memory chunks, excluding the user-supplied buffer. - */ - ~MemoryPoolAllocator() { - Clear(); - delete ownBaseAllocator_; - } - - //! Deallocates all memory chunks, excluding the user-supplied buffer. - void Clear() { - while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) { - ChunkHeader* next = chunkHead_->next; - baseAllocator_->Free(chunkHead_); - chunkHead_ = next; - } - } - - //! Computes the total capacity of allocated memory chunks. - /*! \return total capacity in bytes. - */ - size_t Capacity() { - size_t capacity = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) - capacity += c->capacity; - return capacity; - } - - //! Computes the memory blocks allocated. - /*! \return total used bytes. - */ - size_t Size() { - size_t size = 0; - for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) - size += c->size; - return size; - } - - //! Allocates a memory block. (concept Allocator) - void* Malloc(size_t size) { - if (chunkHead_->size + size > chunkHead_->capacity) - AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); - - char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size; - chunkHead_->size += size; - return buffer; - } - - //! Resizes a memory block (concept Allocator) - void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { - if (originalPtr == 0) - return Malloc(newSize); - - // Do not shrink if new size is smaller than original - if (originalSize >= newSize) - return originalPtr; - - // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { - size_t increment = newSize - originalSize; - if (chunkHead_->size + increment <= chunkHead_->capacity) { - chunkHead_->size += increment; - return originalPtr; - } - } - - // Realloc process: allocate and copy memory, do not free original buffer. - void* newBuffer = Malloc(newSize); - RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. - return memcpy(newBuffer, originalPtr, originalSize); - } - - //! Frees a memory block (concept Allocator) - static void Free(void *ptr) {} // Do nothing - -private: - //! Creates a new chunk. - /*! \param capacity Capacity of the chunk in bytes. - */ - void AddChunk(size_t capacity) { - ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity); - chunk->capacity = capacity; - chunk->size = 0; - chunk->next = chunkHead_; - chunkHead_ = chunk; - } - - static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. - - //! Chunk header for perpending to each chunk. - /*! Chunks are stored as a singly linked list. - */ - struct ChunkHeader { - size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). - size_t size; //!< Current size of allocated memory in bytes. - ChunkHeader *next; //!< Next chunk in the linked list. - }; - - ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. - size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. - char *userBuffer_; //!< User supplied buffer. - BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. - BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. -}; - -/////////////////////////////////////////////////////////////////////////////// -// Encoding - -/*! \class rapidjson::Encoding - \brief Concept for encoding of Unicode characters. - -\code -concept Encoding { - typename Ch; //! Type of character. - - //! \brief Encode a Unicode codepoint to a buffer. - //! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character. - //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. - //! \returns the pointer to the next character after the encoded data. - static Ch* Encode(Ch *buffer, unsigned codepoint); -}; -\endcode -*/ - -/////////////////////////////////////////////////////////////////////////////// -// UTF8 - -//! UTF-8 encoding. -/*! http://en.wikipedia.org/wiki/UTF-8 - \tparam CharType Type for storing 8-bit UTF-8 data. Default is char. - \implements Encoding -*/ -template -struct UTF8 { - typedef CharType Ch; - - static Ch* Encode(Ch *buffer, unsigned codepoint) { - if (codepoint <= 0x7F) - *buffer++ = codepoint & 0xFF; - else if (codepoint <= 0x7FF) { - *buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF); - *buffer++ = 0x80 | ((codepoint & 0x3F)); - } - else if (codepoint <= 0xFFFF) { - *buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF); - *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); - *buffer++ = 0x80 | (codepoint & 0x3F); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - *buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF); - *buffer++ = 0x80 | ((codepoint >> 12) & 0x3F); - *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); - *buffer++ = 0x80 | (codepoint & 0x3F); - } - return buffer; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// UTF16 - -//! UTF-16 encoding. -/*! http://en.wikipedia.org/wiki/UTF-16 - \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. - \implements Encoding -*/ -template -struct UTF16 { - typedef CharType Ch; - - static Ch* Encode(Ch* buffer, unsigned codepoint) { - if (codepoint <= 0xFFFF) { - RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair - *buffer++ = codepoint; - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - unsigned v = codepoint - 0x10000; - *buffer++ = (v >> 10) + 0xD800; - *buffer++ = (v & 0x3FF) + 0xDC00; - } - return buffer; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// UTF32 - -//! UTF-32 encoding. -/*! http://en.wikipedia.org/wiki/UTF-32 - \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. - \implements Encoding -*/ -template -struct UTF32 { - typedef CharType Ch; - - static Ch *Encode(Ch* buffer, unsigned codepoint) { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - *buffer++ = codepoint; - return buffer; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// Stream - -/*! \class rapidjson::Stream - \brief Concept for reading and writing characters. - - For read-only stream, no need to implement PutBegin(), Put() and PutEnd(). - - For write-only stream, only need to implement Put(). - -\code -concept Stream { - typename Ch; //!< Character type of the stream. - - //! Read the current character from stream without moving the read cursor. - Ch Peek() const; - - //! Read the current character from stream and moving the read cursor to next character. - Ch Take(); - - //! Get the current read cursor. - //! \return Number of characters read from start. - size_t Tell(); - - //! Begin writing operation at the current read pointer. - //! \return The begin writer pointer. - Ch* PutBegin(); - - //! Write a character. - void Put(Ch c); - - //! End the writing operation. - //! \param begin The begin write pointer returned by PutBegin(). - //! \return Number of characters written. - size_t PutEnd(Ch* begin); -} -\endcode -*/ - -//! Put N copies of a character to a stream. -template -inline void PutN(Stream& stream, Ch c, size_t n) { - for (size_t i = 0; i < n; i++) - stream.Put(c); -} - -/////////////////////////////////////////////////////////////////////////////// -// StringStream - -//! Read-only string stream. -/*! \implements Stream -*/ -template -struct GenericStringStream { - typedef typename Encoding::Ch Ch; - - GenericStringStream(const Ch *src) : src_(src), head_(src) {} - - Ch Peek() const { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() const { return src_ - head_; } - - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch c) { RAPIDJSON_ASSERT(false); } - size_t PutEnd(Ch* begin) { RAPIDJSON_ASSERT(false); return 0; } - - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. -}; - -typedef GenericStringStream > StringStream; - -/////////////////////////////////////////////////////////////////////////////// -// InsituStringStream - -//! A read-write string stream. -/*! This string stream is particularly designed for in-situ parsing. - \implements Stream -*/ -template -struct GenericInsituStringStream { - typedef typename Encoding::Ch Ch; - - GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} - - // Read - Ch Peek() { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() { return src_ - head_; } - - // Write - Ch* PutBegin() { return dst_ = src_; } - void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } - size_t PutEnd(Ch* begin) { return dst_ - begin; } - - Ch* src_; - Ch* dst_; - Ch* head_; -}; - -typedef GenericInsituStringStream > InsituStringStream; - -/////////////////////////////////////////////////////////////////////////////// -// Type - -//! Type of JSON value -enum Type { - kNullType = 0, //!< null - kFalseType = 1, //!< false - kTrueType = 2, //!< true - kObjectType = 3, //!< object - kArrayType = 4, //!< array - kStringType = 5, //!< string - kNumberType = 6, //!< number -}; - -} // namespace rapidjson - -#endif // RAPIDJSON_RAPIDJSON_H_ +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +// Version 0.1 + +#include // malloc(), realloc(), free() +#include // memcpy() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +// Here defines int64_t and uint64_t types in global namespace. +// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. +#ifndef RAPIDJSON_NO_INT64DEFINE +#ifdef _MSC_VER +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! GCC provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. +*/ +#ifndef RAPIDJSON_ENDIAN +#ifdef __BYTE_ORDER__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +#else +#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +#endif // __BYTE_ORDER__ +#else +#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise. +#endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +// Enable SSE2 optimization. +//#define RAPIDJSON_SSE2 + +// Enable SSE4.2 optimization. +//#define RAPIDJSON_SSE42 + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +namespace rapidjson { +//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t. +/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +} // namespace rapidjson +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! By default, rapidjson uses C assert() for assertion. + User can override it by defining RAPIDJSON_ASSERT(x) macro. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \implements Allocator +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { return malloc(size); } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { return realloc(originalPtr, newSize); } + static void Free(void *ptr) { free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \implements Allocator +*/ +template +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = new BaseAllocator(); + AddChunk(chunk_capacity_); + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = (ChunkHeader*)buffer; + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + delete ownBaseAllocator_; + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (chunkHead_->size + size > chunkHead_->capacity) + AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + + char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + size_t increment = newSize - originalSize; + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + void* newBuffer = Malloc(newSize); + RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. + return memcpy(newBuffer, originalPtr, originalSize); + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) {} // Do nothing + +private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + */ + void AddChunk(size_t capacity) { + ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity); + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + char *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. + + //! \brief Encode a Unicode codepoint to a buffer. + //! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + //! \returns the pointer to the next character after the encoded data. + static Ch* Encode(Ch *buffer, unsigned codepoint); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + \tparam CharType Type for storing 8-bit UTF-8 data. Default is char. + \implements Encoding +*/ +template +struct UTF8 { + typedef CharType Ch; + + static Ch* Encode(Ch *buffer, unsigned codepoint) { + if (codepoint <= 0x7F) + *buffer++ = codepoint & 0xFF; + else if (codepoint <= 0x7FF) { + *buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF); + *buffer++ = 0x80 | ((codepoint & 0x3F)); + } + else if (codepoint <= 0xFFFF) { + *buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF); + *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); + *buffer++ = 0x80 | (codepoint & 0x3F); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + *buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF); + *buffer++ = 0x80 | ((codepoint >> 12) & 0x3F); + *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); + *buffer++ = 0x80 | (codepoint & 0x3F); + } + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \implements Encoding +*/ +template +struct UTF16 { + typedef CharType Ch; + + static Ch* Encode(Ch* buffer, unsigned codepoint) { + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + *buffer++ = codepoint; + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + *buffer++ = (v >> 10) + 0xD800; + *buffer++ = (v & 0x3FF) + 0xDC00; + } + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \implements Encoding +*/ +template +struct UTF32 { + typedef CharType Ch; + + static Ch *Encode(Ch* buffer, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + *buffer++ = codepoint; + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put() and PutEnd(). + + For write-only stream, only need to implement Put(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + for (size_t i = 0; i < n; i++) + stream.Put(c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \implements Stream +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return src_ - head_; } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch c) { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch* begin) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \implements Stream +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return src_ - head_; } + + // Write + Ch* PutBegin() { return dst_ = src_; } + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + size_t PutEnd(Ch* begin) { return dst_ - begin; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +typedef GenericInsituStringStream > InsituStringStream; + +/////////////////////////////////////////////////////////////////////////////// +// Type + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6, //!< number +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/rapidjson/reader.h b/contrib/http_examples/twitter/rapidjson/reader.h similarity index 96% rename from libs/network/example/twitter/rapidjson/reader.h rename to contrib/http_examples/twitter/rapidjson/reader.h index a01649781..1360eb0a1 100644 --- a/libs/network/example/twitter/rapidjson/reader.h +++ b/contrib/http_examples/twitter/rapidjson/reader.h @@ -1,664 +1,664 @@ -#ifndef RAPIDJSON_READER_H_ -#define RAPIDJSON_READER_H_ - -// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) -// Version 0.1 - -#include "rapidjson.h" -#include "internal/pow10.h" -#include "internal/stack.h" -#include - -#ifdef RAPIDJSON_SSE42 -#include -#elif defined(RAPIDJSON_SSE2) -#include -#endif - -#ifndef RAPIDJSON_PARSE_ERROR -#define RAPIDJSON_PARSE_ERROR(msg, offset) do { parseError_ = msg; errorOffset_ = offset; longjmp(jmpbuf_, 1); } while(false) -#endif - -namespace rapidjson { - -/////////////////////////////////////////////////////////////////////////////// -// ParseFlag - -//! Combination of parseFlags -enum ParseFlag { - kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. - kParseInsituFlag = 1 //!< In-situ(destructive) parsing. -}; - -/////////////////////////////////////////////////////////////////////////////// -// Handler - -/*! \class rapidjson::Handler - \brief Concept for receiving events from GenericReader upon parsing. -\code -concept Handler { - typename Ch; - - void Null(); - void Bool(bool b); - void Int(int i); - void Uint(unsigned i); - void Int64(int64_t i); - void Uint64(uint64_t i); - void Double(double d); - void String(const Ch* str, SizeType length, bool copy); - void StartObject(); - void EndObject(SizeType memberCount); - void StartArray(); - void EndArray(SizeType elementCount); -}; -\endcode -*/ -/////////////////////////////////////////////////////////////////////////////// -// BaseReaderHandler - -//! Default implementation of Handler. -/*! This can be used as base class of any reader handler. - \implements Handler -*/ -template > -struct BaseReaderHandler { - typedef typename Encoding::Ch Ch; - - void Default() {} - void Null() { Default(); } - void Bool(bool b) { Default(); } - void Int(int i) { Default(); } - void Uint(unsigned i) { Default(); } - void Int64(int64_t i) { Default(); } - void Uint64(uint64_t i) { Default(); } - void Double(double d) { Default(); } - void String(const Ch* str, SizeType length, bool copy) { Default(); } - void StartObject() { Default(); } - void EndObject(SizeType memberCount) { Default(); } - void StartArray() { Default(); } - void EndArray(SizeType elementCount) { Default(); } -}; - -/////////////////////////////////////////////////////////////////////////////// -// SkipWhitespace - -//! Skip the JSON white spaces in a stream. -/*! \param stream A input stream for skipping white spaces. - \note This function has SSE2/SSE4.2 specialization. -*/ -template -void SkipWhitespace(Stream& stream) { - Stream s = stream; // Use a local copy for optimization - while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') - s.Take(); - stream = s; -} - -#ifdef RAPIDJSON_SSE42 -//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. -inline const char *SkipWhitespace_SIMD(const char* p) { - static const char whitespace[16] = " \n\r\t"; - __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); - - for (;;) { - __m128i s = _mm_loadu_si128((const __m128i *)p); - unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); - if (r == 0) // all 16 characters are whitespace - p += 16; - else { // some of characters may be non-whitespace -#ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - if (_BitScanForward(&offset, r)) - return p + offset; -#else - if (r != 0) - return p + __builtin_ffs(r) - 1; -#endif - } - } -} - -#elif defined(RAPIDJSON_SSE2) - -//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. -inline const char *SkipWhitespace_SIMD(const char* p) { - static const char whitespaces[4][17] = { - " ", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; - - __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); - __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); - __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); - __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); - - for (;;) { - __m128i s = _mm_loadu_si128((const __m128i *)p); - __m128i x = _mm_cmpeq_epi8(s, w0); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); - x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = ~_mm_movemask_epi8(x); - if (r == 0) // all 16 characters are whitespace - p += 16; - else { // some of characters may be non-whitespace -#ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - if (_BitScanForward(&offset, r)) - return p + offset; -#else - if (r != 0) - return p + __builtin_ffs(r) - 1; -#endif - } - } -} - -#endif // RAPIDJSON_SSE2 - -#ifdef RAPIDJSON_SIMD -//! Template function specialization for InsituStringStream -template<> inline void SkipWhitespace(InsituStringStream& stream) { - stream.src_ = const_cast(SkipWhitespace_SIMD(stream.src_)); -} - -//! Template function specialization for StringStream -template<> inline void SkipWhitespace(StringStream& stream) { - stream.src_ = SkipWhitespace_SIMD(stream.src_); -} -#endif // RAPIDJSON_SIMD - -/////////////////////////////////////////////////////////////////////////////// -// GenericReader - -//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. -/*! GenericReader parses JSON text from a stream, and send events synchronously to an - object implementing Handler concept. - - It needs to allocate a stack for storing a single decoded string during - non-destructive parsing. - - For in-situ parsing, the decoded string is directly written to the source - text string, no temporary buffer is required. - - A GenericReader object can be reused for parsing multiple JSON text. - - \tparam Encoding Encoding of both the stream and the parse output. - \tparam Allocator Allocator type for stack. -*/ -template > -class GenericReader { -public: - typedef typename Encoding::Ch Ch; - - //! Constructor. - /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) - \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) - */ - GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} - - //! Parse JSON text. - /*! \tparam parseFlags Combination of ParseFlag. - \tparam Stream Type of input stream. - \tparam Handler Type of handler which must implement Handler concept. - \param stream Input stream to be parsed. - \param handler The handler to receive events. - \return Whether the parsing is successful. - */ - template - bool Parse(Stream& stream, Handler& handler) { - parseError_ = 0; - errorOffset_ = 0; - - if (setjmp(jmpbuf_)) { - stack_.Clear(); - return false; - } - - SkipWhitespace(stream); - - if (stream.Peek() == '\0') - RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell()); - else { - switch (stream.Peek()) { - case '{': ParseObject(stream, handler); break; - case '[': ParseArray(stream, handler); break; - default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell()); return false; - } - SkipWhitespace(stream); - - if (stream.Peek() != '\0') - RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell()); - } - - return true; - } - - bool HasParseError() const { return parseError_ != 0; } - const char* GetParseError() const { return parseError_; } - size_t GetErrorOffset() const { return errorOffset_; } - -private: - // Parse object: { string : value, ... } - template - void ParseObject(Stream& stream, Handler& handler) { - RAPIDJSON_ASSERT(stream.Peek() == '{'); - stream.Take(); // Skip '{' - handler.StartObject(); - SkipWhitespace(stream); - - if (stream.Peek() == '}') { - stream.Take(); - handler.EndObject(0); // empty object - return; - } - - for (SizeType memberCount = 0;;) { - if (stream.Peek() != '"') { - RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell()); - break; - } - - ParseString(stream, handler); - SkipWhitespace(stream); - - if (stream.Take() != ':') { - RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell()); - break; - } - SkipWhitespace(stream); - - ParseValue(stream, handler); - SkipWhitespace(stream); - - ++memberCount; - - switch(stream.Take()) { - case ',': SkipWhitespace(stream); break; - case '}': handler.EndObject(memberCount); return; - default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell()); - } - } - } - - // Parse array: [ value, ... ] - template - void ParseArray(Stream& stream, Handler& handler) { - RAPIDJSON_ASSERT(stream.Peek() == '['); - stream.Take(); // Skip '[' - handler.StartArray(); - SkipWhitespace(stream); - - if (stream.Peek() == ']') { - stream.Take(); - handler.EndArray(0); // empty array - return; - } - - for (SizeType elementCount = 0;;) { - ParseValue(stream, handler); - ++elementCount; - SkipWhitespace(stream); - - switch (stream.Take()) { - case ',': SkipWhitespace(stream); break; - case ']': handler.EndArray(elementCount); return; - default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell()); - } - } - } - - template - void ParseNull(Stream& stream, Handler& handler) { - RAPIDJSON_ASSERT(stream.Peek() == 'n'); - stream.Take(); - - if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l') - handler.Null(); - else - RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); - } - - template - void ParseTrue(Stream& stream, Handler& handler) { - RAPIDJSON_ASSERT(stream.Peek() == 't'); - stream.Take(); - - if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e') - handler.Bool(true); - else - RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell()); - } - - template - void ParseFalse(Stream& stream, Handler& handler) { - RAPIDJSON_ASSERT(stream.Peek() == 'f'); - stream.Take(); - - if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e') - handler.Bool(false); - else - RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); - } - - // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). - template - unsigned ParseHex4(Stream& stream) { - Stream s = stream; // Use a local copy for optimization - unsigned codepoint = 0; - for (int i = 0; i < 4; i++) { - Ch c = s.Take(); - codepoint <<= 4; - codepoint += c; - if (c >= '0' && c <= '9') - codepoint -= '0'; - else if (c >= 'A' && c <= 'F') - codepoint -= 'A' - 10; - else if (c >= 'a' && c <= 'f') - codepoint -= 'a' - 10; - else { - RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); - return 0; - } - } - stream = s; // Restore stream - return codepoint; - } - - // Parse string, handling the prefix and suffix double quotes and escaping. - template - void ParseString(Stream& stream, Handler& handler) { -#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - static const Ch escape[256] = { - Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', - Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, - 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, - 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 - }; -#undef Z16 - - Stream s = stream; // Use a local copy for optimization - RAPIDJSON_ASSERT(s.Peek() == '\"'); - s.Take(); // Skip '\"' - Ch *head; - SizeType len; - if (parseFlags & kParseInsituFlag) - head = s.PutBegin(); - else - len = 0; - -#define RAPIDJSON_PUT(x) \ - do { \ - if (parseFlags & kParseInsituFlag) \ - s.Put(x); \ - else { \ - *stack_.template Push() = x; \ - ++len; \ - } \ - } while(false) - - for (;;) { - Ch c = s.Take(); - if (c == '\\') { // Escape - Ch e = s.Take(); - if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e]) - RAPIDJSON_PUT(escape[(unsigned char)e]); - else if (e == 'u') { // Unicode - unsigned codepoint = ParseHex4(s); - if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair - if (s.Take() != '\\' || s.Take() != 'u') { - RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2); - return; - } - unsigned codepoint2 = ParseHex4(s); - if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) { - RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2); - return; - } - codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; - } - - Ch buffer[4]; - SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]); - - if (parseFlags & kParseInsituFlag) - for (SizeType i = 0; i < count; i++) - s.Put(buffer[i]); - else { - memcpy(stack_.template Push(count), buffer, count * sizeof(Ch)); - len += count; - } - } - else { - RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1); - return; - } - } - else if (c == '"') { // Closing double quote - if (parseFlags & kParseInsituFlag) { - size_t length = s.PutEnd(head); - RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - RAPIDJSON_PUT('\0'); // null-terminate the string - handler.String(head, SizeType(length), false); - } - else { - RAPIDJSON_PUT('\0'); - handler.String(stack_.template Pop(len), len - 1, true); - } - stream = s; // restore stream - return; - } - else if (c == '\0') { - RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1); - return; - } - else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF - RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1); - return; - } - else - RAPIDJSON_PUT(c); // Normal character, just copy - } -#undef RAPIDJSON_PUT - } - - template - void ParseNumber(Stream& stream, Handler& handler) { - Stream s = stream; // Local copy for optimization - // Parse minus - bool minus = false; - if (s.Peek() == '-') { - minus = true; - s.Take(); - } - - // Parse int: zero / ( digit1-9 *DIGIT ) - unsigned i; - bool try64bit = false; - if (s.Peek() == '0') { - i = 0; - s.Take(); - } - else if (s.Peek() >= '1' && s.Peek() <= '9') { - i = s.Take() - '0'; - - if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 214748364) { // 2^31 = 2147483648 - if (i != 214748364 || s.Peek() > '8') { - try64bit = true; - break; - } - } - i = i * 10 + (s.Take() - '0'); - } - else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 429496729) { // 2^32 - 1 = 4294967295 - if (i != 429496729 || s.Peek() > '5') { - try64bit = true; - break; - } - } - i = i * 10 + (s.Take() - '0'); - } - } - else { - RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell()); - return; - } - - // Parse 64bit int - uint64_t i64; - bool useDouble = false; - if (try64bit) { - i64 = i; - if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 - if (i64 != 922337203685477580uLL || s.Peek() > '8') { - useDouble = true; - break; - } - i64 = i64 * 10 + (s.Take() - '0'); - } - else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 - if (i64 != 1844674407370955161uLL || s.Peek() > '5') { - useDouble = true; - break; - } - i64 = i64 * 10 + (s.Take() - '0'); - } - } - - // Force double for big integer - double d; - if (useDouble) { - d = (double)i64; - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (d >= 1E307) { - RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); - return; - } - d = d * 10 + (s.Take() - '0'); - } - } - - // Parse frac = decimal-point 1*DIGIT - int expFrac = 0; - if (s.Peek() == '.') { - if (!useDouble) { - d = try64bit ? (double)i64 : (double)i; - useDouble = true; - } - s.Take(); - - if (s.Peek() >= '0' && s.Peek() <= '9') { - d = d * 10 + (s.Take() - '0'); - --expFrac; - } - else { - RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell()); - return; - } - - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (expFrac > -16) { - d = d * 10 + (s.Peek() - '0'); - --expFrac; - } - s.Take(); - } - } - - // Parse exp = e [ minus / plus ] 1*DIGIT - int exp = 0; - if (s.Peek() == 'e' || s.Peek() == 'E') { - if (!useDouble) { - d = try64bit ? (double)i64 : (double)i; - useDouble = true; - } - s.Take(); - - bool expMinus = false; - if (s.Peek() == '+') - s.Take(); - else if (s.Peek() == '-') { - s.Take(); - expMinus = true; - } - - if (s.Peek() >= '0' && s.Peek() <= '9') { - exp = s.Take() - '0'; - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp > 308) { - RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); - return; - } - } - } - else { - RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); - return; - } - - if (expMinus) - exp = -exp; - } - - // Finish parsing, call event according to the type of number. - if (useDouble) { - d *= internal::Pow10(exp + expFrac); - handler.Double(minus ? -d : d); - } - else { - if (try64bit) { - if (minus) - handler.Int64(-(int64_t)i64); - else - handler.Uint64(i64); - } - else { - if (minus) - handler.Int(-(int)i); - else - handler.Uint(i); - } - } - - stream = s; // restore stream - } - - // Parse any JSON value - template - void ParseValue(Stream& stream, Handler& handler) { - switch (stream.Peek()) { - case 'n': ParseNull (stream, handler); break; - case 't': ParseTrue (stream, handler); break; - case 'f': ParseFalse (stream, handler); break; - case '"': ParseString(stream, handler); break; - case '{': ParseObject(stream, handler); break; - case '[': ParseArray (stream, handler); break; - default : ParseNumber(stream, handler); - } - } - - static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. - internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. - jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. - const char* parseError_; - size_t errorOffset_; -}; // class GenericReader - -//! Reader with UTF8 encoding and default allocator. -typedef GenericReader > Reader; - -} // namespace rapidjson - -#endif // RAPIDJSON_READER_H_ +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +// Version 0.1 + +#include "rapidjson.h" +#include "internal/pow10.h" +#include "internal/stack.h" +#include + +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(msg, offset) do { parseError_ = msg; errorOffset_ = offset; longjmp(jmpbuf_, 1); } while(false) +#endif + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +//! Combination of parseFlags +enum ParseFlag { + kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. + kParseInsituFlag = 1 //!< In-situ(destructive) parsing. +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. +\code +concept Handler { + typename Ch; + + void Null(); + void Bool(bool b); + void Int(int i); + void Uint(unsigned i); + void Int64(int64_t i); + void Uint64(uint64_t i); + void Double(double d); + void String(const Ch* str, SizeType length, bool copy); + void StartObject(); + void EndObject(SizeType memberCount); + void StartArray(); + void EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \implements Handler +*/ +template > +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + void Default() {} + void Null() { Default(); } + void Bool(bool b) { Default(); } + void Int(int i) { Default(); } + void Uint(unsigned i) { Default(); } + void Int64(int64_t i) { Default(); } + void Uint64(uint64_t i) { Default(); } + void Double(double d) { Default(); } + void String(const Ch* str, SizeType length, bool copy) { Default(); } + void StartObject() { Default(); } + void EndObject(SizeType memberCount) { Default(); } + void StartArray() { Default(); } + void EndArray(SizeType elementCount) { Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param stream A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(Stream& stream) { + Stream s = stream; // Use a local copy for optimization + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); + stream = s; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + static const char whitespace[16] = " \n\r\t"; + __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); + + for (;;) { + __m128i s = _mm_loadu_si128((const __m128i *)p); + unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r == 0) // all 16 characters are whitespace + p += 16; + else { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + if (_BitScanForward(&offset, r)) + return p + offset; +#else + if (r != 0) + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + + __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + + for (;;) { + __m128i s = _mm_loadu_si128((const __m128i *)p); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = ~_mm_movemask_epi8(x); + if (r == 0) // all 16 characters are whitespace + p += 16; + else { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + if (_BitScanForward(&offset, r)) + return p + offset; +#else + if (r != 0) + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& stream) { + stream.src_ = const_cast(SkipWhitespace_SIMD(stream.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& stream) { + stream.src_ = SkipWhitespace_SIMD(stream.src_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam Encoding Encoding of both the stream and the parse output. + \tparam Allocator Allocator type for stack. +*/ +template > +class GenericReader { +public: + typedef typename Encoding::Ch Ch; + + //! Constructor. + /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of ParseFlag. + \tparam Stream Type of input stream. + \tparam Handler Type of handler which must implement Handler concept. + \param stream Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool Parse(Stream& stream, Handler& handler) { + parseError_ = 0; + errorOffset_ = 0; + + if (setjmp(jmpbuf_)) { + stack_.Clear(); + return false; + } + + SkipWhitespace(stream); + + if (stream.Peek() == '\0') + RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell()); + else { + switch (stream.Peek()) { + case '{': ParseObject(stream, handler); break; + case '[': ParseArray(stream, handler); break; + default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell()); return false; + } + SkipWhitespace(stream); + + if (stream.Peek() != '\0') + RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell()); + } + + return true; + } + + bool HasParseError() const { return parseError_ != 0; } + const char* GetParseError() const { return parseError_; } + size_t GetErrorOffset() const { return errorOffset_; } + +private: + // Parse object: { string : value, ... } + template + void ParseObject(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == '{'); + stream.Take(); // Skip '{' + handler.StartObject(); + SkipWhitespace(stream); + + if (stream.Peek() == '}') { + stream.Take(); + handler.EndObject(0); // empty object + return; + } + + for (SizeType memberCount = 0;;) { + if (stream.Peek() != '"') { + RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell()); + break; + } + + ParseString(stream, handler); + SkipWhitespace(stream); + + if (stream.Take() != ':') { + RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell()); + break; + } + SkipWhitespace(stream); + + ParseValue(stream, handler); + SkipWhitespace(stream); + + ++memberCount; + + switch(stream.Take()) { + case ',': SkipWhitespace(stream); break; + case '}': handler.EndObject(memberCount); return; + default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell()); + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == '['); + stream.Take(); // Skip '[' + handler.StartArray(); + SkipWhitespace(stream); + + if (stream.Peek() == ']') { + stream.Take(); + handler.EndArray(0); // empty array + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(stream, handler); + ++elementCount; + SkipWhitespace(stream); + + switch (stream.Take()) { + case ',': SkipWhitespace(stream); break; + case ']': handler.EndArray(elementCount); return; + default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell()); + } + } + } + + template + void ParseNull(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 'n'); + stream.Take(); + + if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l') + handler.Null(); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); + } + + template + void ParseTrue(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 't'); + stream.Take(); + + if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e') + handler.Bool(true); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell()); + } + + template + void ParseFalse(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 'f'); + stream.Take(); + + if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e') + handler.Bool(false); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(Stream& stream) { + Stream s = stream; // Use a local copy for optimization + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = s.Take(); + codepoint <<= 4; + codepoint += c; + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); + return 0; + } + } + stream = s; // Restore stream + return codepoint; + } + + // Parse string, handling the prefix and suffix double quotes and escaping. + template + void ParseString(Stream& stream, Handler& handler) { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const Ch escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 + + Stream s = stream; // Use a local copy for optimization + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + Ch *head; + SizeType len; + if (parseFlags & kParseInsituFlag) + head = s.PutBegin(); + else + len = 0; + +#define RAPIDJSON_PUT(x) \ + do { \ + if (parseFlags & kParseInsituFlag) \ + s.Put(x); \ + else { \ + *stack_.template Push() = x; \ + ++len; \ + } \ + } while(false) + + for (;;) { + Ch c = s.Take(); + if (c == '\\') { // Escape + Ch e = s.Take(); + if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e]) + RAPIDJSON_PUT(escape[(unsigned char)e]); + else if (e == 'u') { // Unicode + unsigned codepoint = ParseHex4(s); + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair + if (s.Take() != '\\' || s.Take() != 'u') { + RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2); + return; + } + unsigned codepoint2 = ParseHex4(s); + if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) { + RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2); + return; + } + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + + Ch buffer[4]; + SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]); + + if (parseFlags & kParseInsituFlag) + for (SizeType i = 0; i < count; i++) + s.Put(buffer[i]); + else { + memcpy(stack_.template Push(count), buffer, count * sizeof(Ch)); + len += count; + } + } + else { + RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1); + return; + } + } + else if (c == '"') { // Closing double quote + if (parseFlags & kParseInsituFlag) { + size_t length = s.PutEnd(head); + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + RAPIDJSON_PUT('\0'); // null-terminate the string + handler.String(head, SizeType(length), false); + } + else { + RAPIDJSON_PUT('\0'); + handler.String(stack_.template Pop(len), len - 1, true); + } + stream = s; // restore stream + return; + } + else if (c == '\0') { + RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1); + return; + } + else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1); + return; + } + else + RAPIDJSON_PUT(c); // Normal character, just copy + } +#undef RAPIDJSON_PUT + } + + template + void ParseNumber(Stream& stream, Handler& handler) { + Stream s = stream; // Local copy for optimization + // Parse minus + bool minus = false; + if (s.Peek() == '-') { + minus = true; + s.Take(); + } + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i; + bool try64bit = false; + if (s.Peek() == '0') { + i = 0; + s.Take(); + } + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = s.Take() - '0'; + + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 214748364) { // 2^31 = 2147483648 + if (i != 214748364 || s.Peek() > '8') { + try64bit = true; + break; + } + } + i = i * 10 + (s.Take() - '0'); + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 429496729) { // 2^32 - 1 = 4294967295 + if (i != 429496729 || s.Peek() > '5') { + try64bit = true; + break; + } + } + i = i * 10 + (s.Take() - '0'); + } + } + else { + RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell()); + return; + } + + // Parse 64bit int + uint64_t i64; + bool useDouble = false; + if (try64bit) { + i64 = i; + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 + if (i64 != 922337203685477580uLL || s.Peek() > '8') { + useDouble = true; + break; + } + i64 = i64 * 10 + (s.Take() - '0'); + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 + if (i64 != 1844674407370955161uLL || s.Peek() > '5') { + useDouble = true; + break; + } + i64 = i64 * 10 + (s.Take() - '0'); + } + } + + // Force double for big integer + double d; + if (useDouble) { + d = (double)i64; + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (d >= 1E307) { + RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); + return; + } + d = d * 10 + (s.Take() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + if (s.Peek() == '.') { + if (!useDouble) { + d = try64bit ? (double)i64 : (double)i; + useDouble = true; + } + s.Take(); + + if (s.Peek() >= '0' && s.Peek() <= '9') { + d = d * 10 + (s.Take() - '0'); + --expFrac; + } + else { + RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell()); + return; + } + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (expFrac > -16) { + d = d * 10 + (s.Peek() - '0'); + --expFrac; + } + s.Take(); + } + } + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (s.Peek() == 'e' || s.Peek() == 'E') { + if (!useDouble) { + d = try64bit ? (double)i64 : (double)i; + useDouble = true; + } + s.Take(); + + bool expMinus = false; + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); + expMinus = true; + } + + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > 308) { + RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); + return; + } + } + } + else { + RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); + return; + } + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + if (useDouble) { + d *= internal::Pow10(exp + expFrac); + handler.Double(minus ? -d : d); + } + else { + if (try64bit) { + if (minus) + handler.Int64(-(int64_t)i64); + else + handler.Uint64(i64); + } + else { + if (minus) + handler.Int(-(int)i); + else + handler.Uint(i); + } + } + + stream = s; // restore stream + } + + // Parse any JSON value + template + void ParseValue(Stream& stream, Handler& handler) { + switch (stream.Peek()) { + case 'n': ParseNull (stream, handler); break; + case 't': ParseTrue (stream, handler); break; + case 'f': ParseFalse (stream, handler); break; + case '"': ParseString(stream, handler); break; + case '{': ParseObject(stream, handler); break; + case '[': ParseArray (stream, handler); break; + default : ParseNumber(stream, handler); + } + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. + const char* parseError_; + size_t errorOffset_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader > Reader; + +} // namespace rapidjson + +#endif // RAPIDJSON_READER_H_ diff --git a/libs/network/example/twitter/rapidjson/stringbuffer.h b/contrib/http_examples/twitter/rapidjson/stringbuffer.h similarity index 96% rename from libs/network/example/twitter/rapidjson/stringbuffer.h rename to contrib/http_examples/twitter/rapidjson/stringbuffer.h index d69e3d1cc..cc7501561 100644 --- a/libs/network/example/twitter/rapidjson/stringbuffer.h +++ b/contrib/http_examples/twitter/rapidjson/stringbuffer.h @@ -1,49 +1,49 @@ -#ifndef RAPIDJSON_STRINGBUFFER_H_ -#define RAPIDJSON_STRINGBUFFER_H_ - -#include "rapidjson.h" -#include "internal/stack.h" - -namespace rapidjson { - -//! Represents an in-memory output stream. -/*! - \tparam Encoding Encoding of the stream. - \tparam Allocator type for allocating memory buffer. - \implements Stream -*/ -template -struct GenericStringBuffer { - typedef typename Encoding::Ch Ch; - - GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} - - void Put(Ch c) { *stack_.template Push() = c; } - - void Clear() { stack_.Clear(); } - - const char* GetString() const { - // Push and pop a null terminator. This is safe. - *stack_.template Push() = '\0'; - stack_.template Pop(1); - - return stack_.template Bottom(); - } - - size_t Size() const { return stack_.Size(); } - - static const size_t kDefaultCapacity = 256; - mutable internal::Stack stack_; -}; - -typedef GenericStringBuffer > StringBuffer; - -//! Implement specialized version of PutN() with memset() for better performance. -template<> -inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { - memset(stream.stack_.Push(n), c, n * sizeof(c)); -} - -} // namespace rapidjson - -#endif // RAPIDJSON_STRINGBUFFER_H_ +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" + +namespace rapidjson { + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \implements Stream +*/ +template +struct GenericStringBuffer { + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + + void Clear() { stack_.Clear(); } + + const char* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + size_t Size() const { return stack_.Size(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericStringBuffer > StringBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +} // namespace rapidjson + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/libs/network/example/twitter/rapidjson/writer.h b/contrib/http_examples/twitter/rapidjson/writer.h similarity index 96% rename from libs/network/example/twitter/rapidjson/writer.h rename to contrib/http_examples/twitter/rapidjson/writer.h index 1d028cc69..6825319b4 100644 --- a/libs/network/example/twitter/rapidjson/writer.h +++ b/contrib/http_examples/twitter/rapidjson/writer.h @@ -1,224 +1,224 @@ -#ifndef RAPIDJSON_WRITER_H_ -#define RAPIDJSON_WRITER_H_ - -#include "rapidjson.h" -#include "internal/stack.h" -#include "internal/strfunc.h" -#include // snprintf() or _sprintf_s() -#include // placement new - -namespace rapidjson { - -//! JSON writer -/*! Writer implements the concept Handler. - It generates JSON text by events to an output stream. - - User may programmatically calls the functions of a writer to generate JSON text. - - On the other side, a writer can also be passed to objects that generates events, - - for example Reader::Parse() and Document::Accept(). - - \tparam Stream Type of ouptut stream. - \tparam Encoding Encoding of both source strings and output. - \implements Handler -*/ -template, typename Allocator = MemoryPoolAllocator<> > -class Writer { -public: - typedef typename Encoding::Ch Ch; - - Writer(Stream& stream, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : - stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level)) {} - - //@name Implementation of Handler - //@{ - Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } - Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } - Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } - Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } - Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } - Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } - Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } - - Writer& String(const Ch* str, SizeType length, bool copy = false) { - Prefix(kStringType); - WriteString(str, length); - return *this; - } - - Writer& StartObject() { - Prefix(kObjectType); - new (level_stack_.template Push()) Level(false); - WriteStartObject(); - return *this; - } - - Writer& EndObject(SizeType memberCount = 0) { - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); - level_stack_.template Pop(1); - WriteEndObject(); - return *this; - } - - Writer& StartArray() { - Prefix(kArrayType); - new (level_stack_.template Push()) Level(true); - WriteStartArray(); - return *this; - } - - Writer& EndArray(SizeType elementCount = 0) { - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); - level_stack_.template Pop(1); - WriteEndArray(); - return *this; - } - //@} - - //! Simpler but slower overload. - Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } - -protected: - //! Information for each nested level - struct Level { - Level(bool inArray) : inArray(inArray), valueCount(0) {} - bool inArray; //!< true if in array, otherwise in object - size_t valueCount; //!< number of values in this level - }; - - static const size_t kDefaultLevelDepth = 32; - - void WriteNull() { - stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l'); - } - - void WriteBool(bool b) { - if (b) { - stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e'); - } - else { - stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e'); - } - } - - void WriteInt(int i) { - if (i < 0) { - stream_.Put('-'); - i = -i; - } - WriteUint((unsigned)i); - } - - void WriteUint(unsigned u) { - char buffer[10]; - char *p = buffer; - do { - *p++ = (u % 10) + '0'; - u /= 10; - } while (u > 0); - - do { - --p; - stream_.Put(*p); - } while (p != buffer); - } - - void WriteInt64(int64_t i64) { - if (i64 < 0) { - stream_.Put('-'); - i64 = -i64; - } - WriteUint64((uint64_t)i64); - } - - void WriteUint64(uint64_t u64) { - char buffer[20]; - char *p = buffer; - do { - *p++ = char(u64 % 10) + '0'; - u64 /= 10; - } while (u64 > 0); - - do { - --p; - stream_.Put(*p); - } while (p != buffer); - } - - //! \todo Optimization with custom double-to-string converter. - void WriteDouble(double d) { - char buffer[100]; -#if _MSC_VER - int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); -#else - int ret = snprintf(buffer, sizeof(buffer), "%g", d); -#endif - RAPIDJSON_ASSERT(ret >= 1); - for (int i = 0; i < ret; i++) - stream_.Put(buffer[i]); - } - - void WriteString(const Ch* str, SizeType length) { - static const char hexDigits[] = "0123456789ABCDEF"; - static const char escape[256] = { -#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - //0 1 2 3 4 5 6 7 8 9 A B C D E F - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 - 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 - 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 - Z16, Z16, // 30~4F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 - Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF -#undef Z16 - }; - - stream_.Put('\"'); - for (const Ch* p = str; p != str + length; ++p) { - if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) { - stream_.Put('\\'); - stream_.Put(escape[(unsigned char)*p]); - if (escape[(unsigned char)*p] == 'u') { - stream_.Put('0'); - stream_.Put('0'); - stream_.Put(hexDigits[(*p) >> 4]); - stream_.Put(hexDigits[(*p) & 0xF]); - } - } - else - stream_.Put(*p); - } - stream_.Put('\"'); - } - - void WriteStartObject() { stream_.Put('{'); } - void WriteEndObject() { stream_.Put('}'); } - void WriteStartArray() { stream_.Put('['); } - void WriteEndArray() { stream_.Put(']'); } - - void Prefix(Type type) { - if (level_stack_.GetSize() != 0) { // this value is not at root - Level* level = level_stack_.template Top(); - if (level->valueCount > 0) { - if (level->inArray) - stream_.Put(','); // add comma if it is not the first element in array - else // in object - stream_.Put((level->valueCount % 2 == 0) ? ',' : ':'); - } - if (!level->inArray && level->valueCount % 2 == 0) - RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name - level->valueCount++; - } - else - RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); - } - - Stream& stream_; - internal::Stack level_stack_; -}; - -} // namespace rapidjson - -#endif // RAPIDJSON_RAPIDJSON_H_ +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include // snprintf() or _sprintf_s() +#include // placement new + +namespace rapidjson { + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output stream. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam Stream Type of ouptut stream. + \tparam Encoding Encoding of both source strings and output. + \implements Handler +*/ +template, typename Allocator = MemoryPoolAllocator<> > +class Writer { +public: + typedef typename Encoding::Ch Ch; + + Writer(Stream& stream, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level)) {} + + //@name Implementation of Handler + //@{ + Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } + Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } + Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } + Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } + Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } + Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } + Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } + + Writer& String(const Ch* str, SizeType length, bool copy = false) { + Prefix(kStringType); + WriteString(str, length); + return *this; + } + + Writer& StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + WriteStartObject(); + return *this; + } + + Writer& EndObject(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + WriteEndObject(); + return *this; + } + + Writer& StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + WriteStartArray(); + return *this; + } + + Writer& EndArray(SizeType elementCount = 0) { + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + WriteEndArray(); + return *this; + } + //@} + + //! Simpler but slower overload. + Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray) : inArray(inArray), valueCount(0) {} + bool inArray; //!< true if in array, otherwise in object + size_t valueCount; //!< number of values in this level + }; + + static const size_t kDefaultLevelDepth = 32; + + void WriteNull() { + stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l'); + } + + void WriteBool(bool b) { + if (b) { + stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e'); + } + else { + stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e'); + } + } + + void WriteInt(int i) { + if (i < 0) { + stream_.Put('-'); + i = -i; + } + WriteUint((unsigned)i); + } + + void WriteUint(unsigned u) { + char buffer[10]; + char *p = buffer; + do { + *p++ = (u % 10) + '0'; + u /= 10; + } while (u > 0); + + do { + --p; + stream_.Put(*p); + } while (p != buffer); + } + + void WriteInt64(int64_t i64) { + if (i64 < 0) { + stream_.Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + } + + void WriteUint64(uint64_t u64) { + char buffer[20]; + char *p = buffer; + do { + *p++ = char(u64 % 10) + '0'; + u64 /= 10; + } while (u64 > 0); + + do { + --p; + stream_.Put(*p); + } while (p != buffer); + } + + //! \todo Optimization with custom double-to-string converter. + void WriteDouble(double d) { + char buffer[100]; +#if _MSC_VER + int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); +#else + int ret = snprintf(buffer, sizeof(buffer), "%g", d); +#endif + RAPIDJSON_ASSERT(ret >= 1); + for (int i = 0; i < ret; i++) + stream_.Put(buffer[i]); + } + + void WriteString(const Ch* str, SizeType length) { + static const char hexDigits[] = "0123456789ABCDEF"; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + stream_.Put('\"'); + for (const Ch* p = str; p != str + length; ++p) { + if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) { + stream_.Put('\\'); + stream_.Put(escape[(unsigned char)*p]); + if (escape[(unsigned char)*p] == 'u') { + stream_.Put('0'); + stream_.Put('0'); + stream_.Put(hexDigits[(*p) >> 4]); + stream_.Put(hexDigits[(*p) & 0xF]); + } + } + else + stream_.Put(*p); + } + stream_.Put('\"'); + } + + void WriteStartObject() { stream_.Put('{'); } + void WriteEndObject() { stream_.Put('}'); } + void WriteStartArray() { stream_.Put('['); } + void WriteEndArray() { stream_.Put(']'); } + + void Prefix(Type type) { + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + stream_.Put(','); // add comma if it is not the first element in array + else // in object + stream_.Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else + RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); + } + + Stream& stream_; + internal::Stack level_stack_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/search.cpp b/contrib/http_examples/twitter/search.cpp similarity index 73% rename from libs/network/example/twitter/search.cpp rename to contrib/http_examples/twitter/search.cpp index 1d0f2fafa..67233a068 100644 --- a/libs/network/example/twitter/search.cpp +++ b/contrib/http_examples/twitter/search.cpp @@ -1,10 +1,11 @@ // Copyright (c) Glyn Matthews 2011, 2012. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) - -#include +#include +#include #include "rapidjson/rapidjson.h" #include "rapidjson/document.h" #include @@ -14,7 +15,7 @@ // https://dev.twitter.com/docs/using-search int main(int argc, char *argv[]) { - using namespace boost::network; + namespace http = network::http; using namespace rapidjson; if (argc != 2) { @@ -25,16 +26,19 @@ int main(int argc, char *argv[]) { try { http::client client; - uri::uri base_uri("http://search.twitter.com/search.json"); + network::uri base_uri("http://search.twitter.com/search.json"); std::cout << "Searching Twitter for query: " << argv[1] << std::endl; - uri::uri search; - search << base_uri << uri::query("q", uri::encoded(argv[1])); - http::client::request request(search); + + network::uri_builder builder(base_uri); + builder.query("q", argv[1])) + http::client::request request(builder.uri()); http::client::response response = client.get(request); Document d; - if (!d.Parse<0>(response.body().c_str()).HasParseError()) { + std::string body; + response.get_body(body); + if (!d.Parse<0>(body.c_str()).HasParseError()) { const Value &results = d["results"]; for (SizeType i = 0; i < results.Size(); ++i) { diff --git a/deps/gmock b/deps/gmock new file mode 160000 index 000000000..6b1759c38 --- /dev/null +++ b/deps/gmock @@ -0,0 +1 @@ +Subproject commit 6b1759c3816d574bddde3e1725c51a811c8870e7 diff --git a/deps/gtest b/deps/gtest new file mode 160000 index 000000000..a6772271f --- /dev/null +++ b/deps/gtest @@ -0,0 +1 @@ +Subproject commit a6772271f71672e889776bfe49ec4efd9da036df diff --git a/libs/network/doc/.gitignore b/doc/.gitignore similarity index 100% rename from libs/network/doc/.gitignore rename to doc/.gitignore diff --git a/libs/network/doc/_ext/adjusts.py b/doc/_ext/adjusts.py similarity index 100% rename from libs/network/doc/_ext/adjusts.py rename to doc/_ext/adjusts.py diff --git a/libs/network/doc/_static/Button-Info-icon.png b/doc/_static/Button-Info-icon.png similarity index 100% rename from libs/network/doc/_static/Button-Info-icon.png rename to doc/_static/Button-Info-icon.png diff --git a/libs/network/doc/_static/Button-Warning-icon.png b/doc/_static/Button-Warning-icon.png similarity index 100% rename from libs/network/doc/_static/Button-Warning-icon.png rename to doc/_static/Button-Warning-icon.png diff --git a/libs/network/doc/_static/boost.png b/doc/_static/boost.png similarity index 100% rename from libs/network/doc/_static/boost.png rename to doc/_static/boost.png diff --git a/libs/network/doc/_static/ftp_uri.png b/doc/_static/ftp_uri.png similarity index 100% rename from libs/network/doc/_static/ftp_uri.png rename to doc/_static/ftp_uri.png diff --git a/libs/network/doc/_static/http_uri.png b/doc/_static/http_uri.png similarity index 100% rename from libs/network/doc/_static/http_uri.png rename to doc/_static/http_uri.png diff --git a/libs/network/doc/_static/mailto_uri.png b/doc/_static/mailto_uri.png similarity index 100% rename from libs/network/doc/_static/mailto_uri.png rename to doc/_static/mailto_uri.png diff --git a/libs/network/doc/_static/orange-background.jpg b/doc/_static/orange-background.jpg similarity index 100% rename from libs/network/doc/_static/orange-background.jpg rename to doc/_static/orange-background.jpg diff --git a/libs/network/doc/_static/pygments.css b/doc/_static/pygments.css similarity index 100% rename from libs/network/doc/_static/pygments.css rename to doc/_static/pygments.css diff --git a/libs/network/doc/_static/reset-fonts-grids.css b/doc/_static/reset-fonts-grids.css similarity index 100% rename from libs/network/doc/_static/reset-fonts-grids.css rename to doc/_static/reset-fonts-grids.css diff --git a/libs/network/doc/_static/uri.svg b/doc/_static/uri.svg similarity index 100% rename from libs/network/doc/_static/uri.svg rename to doc/_static/uri.svg diff --git a/libs/network/doc/_templates/genindex.html b/doc/_templates/genindex.html similarity index 100% rename from libs/network/doc/_templates/genindex.html rename to doc/_templates/genindex.html diff --git a/libs/network/doc/_templates/layout.html b/doc/_templates/layout.html similarity index 100% rename from libs/network/doc/_templates/layout.html rename to doc/_templates/layout.html diff --git a/libs/network/doc/_templates/modindex.html b/doc/_templates/modindex.html similarity index 100% rename from libs/network/doc/_templates/modindex.html rename to doc/_templates/modindex.html diff --git a/libs/network/doc/_templates/search.html b/doc/_templates/search.html similarity index 100% rename from libs/network/doc/_templates/search.html rename to doc/_templates/search.html diff --git a/libs/network/doc/conf.py b/doc/conf.py similarity index 100% rename from libs/network/doc/conf.py rename to doc/conf.py diff --git a/libs/network/doc/contents.rst b/doc/contents.rst similarity index 100% rename from libs/network/doc/contents.rst rename to doc/contents.rst diff --git a/libs/network/doc/examples.rst b/doc/examples.rst similarity index 100% rename from libs/network/doc/examples.rst rename to doc/examples.rst diff --git a/libs/network/doc/examples/http/atom_reader.rst b/doc/examples/http/atom_reader.rst similarity index 100% rename from libs/network/doc/examples/http/atom_reader.rst rename to doc/examples/http/atom_reader.rst diff --git a/libs/network/doc/examples/http/hello_world_client.rst b/doc/examples/http/hello_world_client.rst similarity index 100% rename from libs/network/doc/examples/http/hello_world_client.rst rename to doc/examples/http/hello_world_client.rst diff --git a/libs/network/doc/examples/http/hello_world_server.rst b/doc/examples/http/hello_world_server.rst similarity index 100% rename from libs/network/doc/examples/http/hello_world_server.rst rename to doc/examples/http/hello_world_server.rst diff --git a/libs/network/doc/examples/http/http_client.rst b/doc/examples/http/http_client.rst similarity index 100% rename from libs/network/doc/examples/http/http_client.rst rename to doc/examples/http/http_client.rst diff --git a/libs/network/doc/examples/http/simple_wget.rst b/doc/examples/http/simple_wget.rst similarity index 100% rename from libs/network/doc/examples/http/simple_wget.rst rename to doc/examples/http/simple_wget.rst diff --git a/libs/network/doc/examples/http/twitter_search.rst b/doc/examples/http/twitter_search.rst similarity index 100% rename from libs/network/doc/examples/http/twitter_search.rst rename to doc/examples/http/twitter_search.rst diff --git a/libs/network/doc/getting_started.rst b/doc/getting_started.rst similarity index 100% rename from libs/network/doc/getting_started.rst rename to doc/getting_started.rst diff --git a/libs/network/doc/history.rst b/doc/history.rst similarity index 100% rename from libs/network/doc/history.rst rename to doc/history.rst diff --git a/libs/network/doc/html/.buildinfo b/doc/html/.buildinfo similarity index 100% rename from libs/network/doc/html/.buildinfo rename to doc/html/.buildinfo diff --git a/libs/network/doc/html/_images/boost.png b/doc/html/_images/boost.png similarity index 100% rename from libs/network/doc/html/_images/boost.png rename to doc/html/_images/boost.png diff --git a/libs/network/doc/html/_images/ftp_uri.png b/doc/html/_images/ftp_uri.png similarity index 100% rename from libs/network/doc/html/_images/ftp_uri.png rename to doc/html/_images/ftp_uri.png diff --git a/libs/network/doc/html/_images/http_uri.png b/doc/html/_images/http_uri.png similarity index 100% rename from libs/network/doc/html/_images/http_uri.png rename to doc/html/_images/http_uri.png diff --git a/libs/network/doc/html/_images/mailto_uri.png b/doc/html/_images/mailto_uri.png similarity index 100% rename from libs/network/doc/html/_images/mailto_uri.png rename to doc/html/_images/mailto_uri.png diff --git a/libs/network/doc/html/_sources/contents.txt b/doc/html/_sources/contents.txt similarity index 100% rename from libs/network/doc/html/_sources/contents.txt rename to doc/html/_sources/contents.txt diff --git a/libs/network/doc/html/_sources/examples.txt b/doc/html/_sources/examples.txt similarity index 100% rename from libs/network/doc/html/_sources/examples.txt rename to doc/html/_sources/examples.txt diff --git a/libs/network/doc/html/_sources/examples/http/atom_reader.txt b/doc/html/_sources/examples/http/atom_reader.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/atom_reader.txt rename to doc/html/_sources/examples/http/atom_reader.txt diff --git a/libs/network/doc/html/_sources/examples/http/hello_world_client.txt b/doc/html/_sources/examples/http/hello_world_client.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/hello_world_client.txt rename to doc/html/_sources/examples/http/hello_world_client.txt diff --git a/libs/network/doc/html/_sources/examples/http/hello_world_server.txt b/doc/html/_sources/examples/http/hello_world_server.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/hello_world_server.txt rename to doc/html/_sources/examples/http/hello_world_server.txt diff --git a/libs/network/doc/html/_sources/examples/http/http_client.txt b/doc/html/_sources/examples/http/http_client.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/http_client.txt rename to doc/html/_sources/examples/http/http_client.txt diff --git a/libs/network/doc/html/_sources/examples/http/simple_wget.txt b/doc/html/_sources/examples/http/simple_wget.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/simple_wget.txt rename to doc/html/_sources/examples/http/simple_wget.txt diff --git a/libs/network/doc/html/_sources/examples/http/twitter_search.txt b/doc/html/_sources/examples/http/twitter_search.txt similarity index 100% rename from libs/network/doc/html/_sources/examples/http/twitter_search.txt rename to doc/html/_sources/examples/http/twitter_search.txt diff --git a/libs/network/doc/html/_sources/getting_started.txt b/doc/html/_sources/getting_started.txt similarity index 100% rename from libs/network/doc/html/_sources/getting_started.txt rename to doc/html/_sources/getting_started.txt diff --git a/libs/network/doc/html/_sources/history.txt b/doc/html/_sources/history.txt similarity index 100% rename from libs/network/doc/html/_sources/history.txt rename to doc/html/_sources/history.txt diff --git a/libs/network/doc/html/_sources/in_depth.txt b/doc/html/_sources/in_depth.txt similarity index 100% rename from libs/network/doc/html/_sources/in_depth.txt rename to doc/html/_sources/in_depth.txt diff --git a/libs/network/doc/html/_sources/in_depth/http.txt b/doc/html/_sources/in_depth/http.txt similarity index 100% rename from libs/network/doc/html/_sources/in_depth/http.txt rename to doc/html/_sources/in_depth/http.txt diff --git a/libs/network/doc/html/_sources/in_depth/http_client_tags.txt b/doc/html/_sources/in_depth/http_client_tags.txt similarity index 100% rename from libs/network/doc/html/_sources/in_depth/http_client_tags.txt rename to doc/html/_sources/in_depth/http_client_tags.txt diff --git a/libs/network/doc/html/_sources/in_depth/message.txt b/doc/html/_sources/in_depth/message.txt similarity index 100% rename from libs/network/doc/html/_sources/in_depth/message.txt rename to doc/html/_sources/in_depth/message.txt diff --git a/libs/network/doc/html/_sources/in_depth/uri.txt b/doc/html/_sources/in_depth/uri.txt similarity index 100% rename from libs/network/doc/html/_sources/in_depth/uri.txt rename to doc/html/_sources/in_depth/uri.txt diff --git a/libs/network/doc/html/_sources/index.txt b/doc/html/_sources/index.txt similarity index 100% rename from libs/network/doc/html/_sources/index.txt rename to doc/html/_sources/index.txt diff --git a/libs/network/doc/html/_sources/reference.txt b/doc/html/_sources/reference.txt similarity index 100% rename from libs/network/doc/html/_sources/reference.txt rename to doc/html/_sources/reference.txt diff --git a/libs/network/doc/html/_sources/reference/http_client.txt b/doc/html/_sources/reference/http_client.txt similarity index 100% rename from libs/network/doc/html/_sources/reference/http_client.txt rename to doc/html/_sources/reference/http_client.txt diff --git a/libs/network/doc/html/_sources/reference/http_request.txt b/doc/html/_sources/reference/http_request.txt similarity index 100% rename from libs/network/doc/html/_sources/reference/http_request.txt rename to doc/html/_sources/reference/http_request.txt diff --git a/libs/network/doc/html/_sources/reference/http_response.txt b/doc/html/_sources/reference/http_response.txt similarity index 100% rename from libs/network/doc/html/_sources/reference/http_response.txt rename to doc/html/_sources/reference/http_response.txt diff --git a/libs/network/doc/html/_sources/reference/http_server.txt b/doc/html/_sources/reference/http_server.txt similarity index 100% rename from libs/network/doc/html/_sources/reference/http_server.txt rename to doc/html/_sources/reference/http_server.txt diff --git a/libs/network/doc/html/_sources/references.txt b/doc/html/_sources/references.txt similarity index 100% rename from libs/network/doc/html/_sources/references.txt rename to doc/html/_sources/references.txt diff --git a/libs/network/doc/html/_sources/techniques.txt b/doc/html/_sources/techniques.txt similarity index 100% rename from libs/network/doc/html/_sources/techniques.txt rename to doc/html/_sources/techniques.txt diff --git a/libs/network/doc/html/_sources/techniques/directives.txt b/doc/html/_sources/techniques/directives.txt similarity index 100% rename from libs/network/doc/html/_sources/techniques/directives.txt rename to doc/html/_sources/techniques/directives.txt diff --git a/libs/network/doc/html/_sources/techniques/polymorphism.txt b/doc/html/_sources/techniques/polymorphism.txt similarity index 100% rename from libs/network/doc/html/_sources/techniques/polymorphism.txt rename to doc/html/_sources/techniques/polymorphism.txt diff --git a/libs/network/doc/html/_sources/techniques/tag_metafunctions.txt b/doc/html/_sources/techniques/tag_metafunctions.txt similarity index 100% rename from libs/network/doc/html/_sources/techniques/tag_metafunctions.txt rename to doc/html/_sources/techniques/tag_metafunctions.txt diff --git a/libs/network/doc/html/_sources/whats_new.txt b/doc/html/_sources/whats_new.txt similarity index 100% rename from libs/network/doc/html/_sources/whats_new.txt rename to doc/html/_sources/whats_new.txt diff --git a/libs/network/doc/html/_static/Button-Info-icon.png b/doc/html/_static/Button-Info-icon.png similarity index 100% rename from libs/network/doc/html/_static/Button-Info-icon.png rename to doc/html/_static/Button-Info-icon.png diff --git a/libs/network/doc/html/_static/Button-Warning-icon.png b/doc/html/_static/Button-Warning-icon.png similarity index 100% rename from libs/network/doc/html/_static/Button-Warning-icon.png rename to doc/html/_static/Button-Warning-icon.png diff --git a/libs/network/doc/html/_static/basic.css b/doc/html/_static/basic.css similarity index 100% rename from libs/network/doc/html/_static/basic.css rename to doc/html/_static/basic.css diff --git a/libs/network/doc/html/_static/boost.png b/doc/html/_static/boost.png similarity index 100% rename from libs/network/doc/html/_static/boost.png rename to doc/html/_static/boost.png diff --git a/libs/network/doc/html/_static/default.css b/doc/html/_static/default.css similarity index 100% rename from libs/network/doc/html/_static/default.css rename to doc/html/_static/default.css diff --git a/libs/network/doc/html/_static/doctools.js b/doc/html/_static/doctools.js similarity index 100% rename from libs/network/doc/html/_static/doctools.js rename to doc/html/_static/doctools.js diff --git a/libs/network/doc/html/_static/file.png b/doc/html/_static/file.png similarity index 100% rename from libs/network/doc/html/_static/file.png rename to doc/html/_static/file.png diff --git a/libs/network/doc/html/_static/ftp_uri.png b/doc/html/_static/ftp_uri.png similarity index 100% rename from libs/network/doc/html/_static/ftp_uri.png rename to doc/html/_static/ftp_uri.png diff --git a/libs/network/doc/html/_static/http_uri.png b/doc/html/_static/http_uri.png similarity index 100% rename from libs/network/doc/html/_static/http_uri.png rename to doc/html/_static/http_uri.png diff --git a/libs/network/doc/html/_static/jquery.js b/doc/html/_static/jquery.js similarity index 100% rename from libs/network/doc/html/_static/jquery.js rename to doc/html/_static/jquery.js diff --git a/libs/network/doc/html/_static/mailto_uri.png b/doc/html/_static/mailto_uri.png similarity index 100% rename from libs/network/doc/html/_static/mailto_uri.png rename to doc/html/_static/mailto_uri.png diff --git a/libs/network/doc/html/_static/minus.png b/doc/html/_static/minus.png similarity index 100% rename from libs/network/doc/html/_static/minus.png rename to doc/html/_static/minus.png diff --git a/libs/network/doc/html/_static/orange-background.jpg b/doc/html/_static/orange-background.jpg similarity index 100% rename from libs/network/doc/html/_static/orange-background.jpg rename to doc/html/_static/orange-background.jpg diff --git a/libs/network/doc/html/_static/plus.png b/doc/html/_static/plus.png similarity index 100% rename from libs/network/doc/html/_static/plus.png rename to doc/html/_static/plus.png diff --git a/libs/network/doc/html/_static/pygments.css b/doc/html/_static/pygments.css similarity index 100% rename from libs/network/doc/html/_static/pygments.css rename to doc/html/_static/pygments.css diff --git a/libs/network/doc/html/_static/reset-fonts-grids.css b/doc/html/_static/reset-fonts-grids.css similarity index 100% rename from libs/network/doc/html/_static/reset-fonts-grids.css rename to doc/html/_static/reset-fonts-grids.css diff --git a/libs/network/doc/html/_static/searchtools.js b/doc/html/_static/searchtools.js similarity index 100% rename from libs/network/doc/html/_static/searchtools.js rename to doc/html/_static/searchtools.js diff --git a/libs/network/doc/html/_static/sidebar.js b/doc/html/_static/sidebar.js similarity index 100% rename from libs/network/doc/html/_static/sidebar.js rename to doc/html/_static/sidebar.js diff --git a/libs/network/doc/html/_static/underscore.js b/doc/html/_static/underscore.js similarity index 100% rename from libs/network/doc/html/_static/underscore.js rename to doc/html/_static/underscore.js diff --git a/libs/network/doc/html/_static/uri.svg b/doc/html/_static/uri.svg similarity index 100% rename from libs/network/doc/html/_static/uri.svg rename to doc/html/_static/uri.svg diff --git a/libs/network/doc/html/contents.html b/doc/html/contents.html similarity index 100% rename from libs/network/doc/html/contents.html rename to doc/html/contents.html diff --git a/libs/network/doc/html/examples.html b/doc/html/examples.html similarity index 100% rename from libs/network/doc/html/examples.html rename to doc/html/examples.html diff --git a/libs/network/doc/html/examples/http/atom_reader.html b/doc/html/examples/http/atom_reader.html similarity index 100% rename from libs/network/doc/html/examples/http/atom_reader.html rename to doc/html/examples/http/atom_reader.html diff --git a/libs/network/doc/html/examples/http/hello_world_client.html b/doc/html/examples/http/hello_world_client.html similarity index 100% rename from libs/network/doc/html/examples/http/hello_world_client.html rename to doc/html/examples/http/hello_world_client.html diff --git a/libs/network/doc/html/examples/http/hello_world_server.html b/doc/html/examples/http/hello_world_server.html similarity index 100% rename from libs/network/doc/html/examples/http/hello_world_server.html rename to doc/html/examples/http/hello_world_server.html diff --git a/libs/network/doc/html/examples/http/http_client.html b/doc/html/examples/http/http_client.html similarity index 100% rename from libs/network/doc/html/examples/http/http_client.html rename to doc/html/examples/http/http_client.html diff --git a/libs/network/doc/html/examples/http/simple_wget.html b/doc/html/examples/http/simple_wget.html similarity index 100% rename from libs/network/doc/html/examples/http/simple_wget.html rename to doc/html/examples/http/simple_wget.html diff --git a/libs/network/doc/html/examples/http/twitter_search.html b/doc/html/examples/http/twitter_search.html similarity index 100% rename from libs/network/doc/html/examples/http/twitter_search.html rename to doc/html/examples/http/twitter_search.html diff --git a/libs/network/doc/html/genindex.html b/doc/html/genindex.html similarity index 100% rename from libs/network/doc/html/genindex.html rename to doc/html/genindex.html diff --git a/libs/network/doc/html/getting_started.html b/doc/html/getting_started.html similarity index 100% rename from libs/network/doc/html/getting_started.html rename to doc/html/getting_started.html diff --git a/libs/network/doc/html/history.html b/doc/html/history.html similarity index 100% rename from libs/network/doc/html/history.html rename to doc/html/history.html diff --git a/libs/network/doc/html/in_depth.html b/doc/html/in_depth.html similarity index 100% rename from libs/network/doc/html/in_depth.html rename to doc/html/in_depth.html diff --git a/libs/network/doc/html/in_depth/http.html b/doc/html/in_depth/http.html similarity index 100% rename from libs/network/doc/html/in_depth/http.html rename to doc/html/in_depth/http.html diff --git a/libs/network/doc/html/in_depth/http_client_tags.html b/doc/html/in_depth/http_client_tags.html similarity index 100% rename from libs/network/doc/html/in_depth/http_client_tags.html rename to doc/html/in_depth/http_client_tags.html diff --git a/libs/network/doc/html/in_depth/message.html b/doc/html/in_depth/message.html similarity index 100% rename from libs/network/doc/html/in_depth/message.html rename to doc/html/in_depth/message.html diff --git a/libs/network/doc/html/in_depth/uri.html b/doc/html/in_depth/uri.html similarity index 100% rename from libs/network/doc/html/in_depth/uri.html rename to doc/html/in_depth/uri.html diff --git a/libs/network/doc/html/index.html b/doc/html/index.html similarity index 100% rename from libs/network/doc/html/index.html rename to doc/html/index.html diff --git a/libs/network/doc/html/objects.inv b/doc/html/objects.inv similarity index 100% rename from libs/network/doc/html/objects.inv rename to doc/html/objects.inv diff --git a/libs/network/doc/html/reference.html b/doc/html/reference.html similarity index 100% rename from libs/network/doc/html/reference.html rename to doc/html/reference.html diff --git a/libs/network/doc/html/reference/http_client.html b/doc/html/reference/http_client.html similarity index 100% rename from libs/network/doc/html/reference/http_client.html rename to doc/html/reference/http_client.html diff --git a/libs/network/doc/html/reference/http_request.html b/doc/html/reference/http_request.html similarity index 100% rename from libs/network/doc/html/reference/http_request.html rename to doc/html/reference/http_request.html diff --git a/libs/network/doc/html/reference/http_response.html b/doc/html/reference/http_response.html similarity index 100% rename from libs/network/doc/html/reference/http_response.html rename to doc/html/reference/http_response.html diff --git a/libs/network/doc/html/reference/http_server.html b/doc/html/reference/http_server.html similarity index 100% rename from libs/network/doc/html/reference/http_server.html rename to doc/html/reference/http_server.html diff --git a/libs/network/doc/html/references.html b/doc/html/references.html similarity index 100% rename from libs/network/doc/html/references.html rename to doc/html/references.html diff --git a/libs/network/doc/html/search.html b/doc/html/search.html similarity index 100% rename from libs/network/doc/html/search.html rename to doc/html/search.html diff --git a/libs/network/doc/html/searchindex.js b/doc/html/searchindex.js similarity index 100% rename from libs/network/doc/html/searchindex.js rename to doc/html/searchindex.js diff --git a/libs/network/doc/html/techniques.html b/doc/html/techniques.html similarity index 100% rename from libs/network/doc/html/techniques.html rename to doc/html/techniques.html diff --git a/libs/network/doc/html/techniques/directives.html b/doc/html/techniques/directives.html similarity index 100% rename from libs/network/doc/html/techniques/directives.html rename to doc/html/techniques/directives.html diff --git a/libs/network/doc/html/techniques/polymorphism.html b/doc/html/techniques/polymorphism.html similarity index 100% rename from libs/network/doc/html/techniques/polymorphism.html rename to doc/html/techniques/polymorphism.html diff --git a/libs/network/doc/html/techniques/tag_metafunctions.html b/doc/html/techniques/tag_metafunctions.html similarity index 100% rename from libs/network/doc/html/techniques/tag_metafunctions.html rename to doc/html/techniques/tag_metafunctions.html diff --git a/libs/network/doc/html/whats_new.html b/doc/html/whats_new.html similarity index 100% rename from libs/network/doc/html/whats_new.html rename to doc/html/whats_new.html diff --git a/libs/network/doc/in_depth.rst b/doc/in_depth.rst similarity index 100% rename from libs/network/doc/in_depth.rst rename to doc/in_depth.rst diff --git a/libs/network/doc/in_depth/http.rst b/doc/in_depth/http.rst similarity index 100% rename from libs/network/doc/in_depth/http.rst rename to doc/in_depth/http.rst diff --git a/libs/network/doc/in_depth/http_client_tags.rst b/doc/in_depth/http_client_tags.rst similarity index 100% rename from libs/network/doc/in_depth/http_client_tags.rst rename to doc/in_depth/http_client_tags.rst diff --git a/libs/network/doc/in_depth/message.rst b/doc/in_depth/message.rst similarity index 100% rename from libs/network/doc/in_depth/message.rst rename to doc/in_depth/message.rst diff --git a/libs/network/doc/in_depth/uri.rst b/doc/in_depth/uri.rst similarity index 100% rename from libs/network/doc/in_depth/uri.rst rename to doc/in_depth/uri.rst diff --git a/libs/network/doc/index.rst b/doc/index.rst similarity index 100% rename from libs/network/doc/index.rst rename to doc/index.rst diff --git a/libs/network/doc/make.bat b/doc/make.bat similarity index 100% rename from libs/network/doc/make.bat rename to doc/make.bat diff --git a/libs/network/doc/reference.rst b/doc/reference.rst similarity index 100% rename from libs/network/doc/reference.rst rename to doc/reference.rst diff --git a/libs/network/doc/reference/http_client.rst b/doc/reference/http_client.rst similarity index 98% rename from libs/network/doc/reference/http_client.rst rename to doc/reference/http_client.rst index 52c31a055..3a7e90c67 100644 --- a/libs/network/doc/reference/http_client.rst +++ b/doc/reference/http_client.rst @@ -233,11 +233,11 @@ and that there is an appropriately constructed response object named the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. -``response_ = client_.post(request_, content_type, body)`` +``response_ = client_.post(request_, body, content_type)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. -``response_ = client_.post(request_, content_type, body, _body_handler=callback)`` +``response_ = client_.post(request_, body, content_type, _body_handler=callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response @@ -263,11 +263,11 @@ and that there is an appropriately constructed response object named the ``callback`` parameter. The signature of ``callback`` should be the following: ``void(iterator_range const &, boost::system::error_code const &)``. -``response_ = client_.put(request_, content_type, body)`` +``response_ = client_.put(request_, body, content_type)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. -``response_ = client_.put(request_, content_type, body, _body_handler=callback)`` +``response_ = client_.put(request_, body, content_type, _body_handler=callback)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. Have the response diff --git a/libs/network/doc/reference/http_request.rst b/doc/reference/http_request.rst similarity index 100% rename from libs/network/doc/reference/http_request.rst rename to doc/reference/http_request.rst diff --git a/libs/network/doc/reference/http_response.rst b/doc/reference/http_response.rst similarity index 100% rename from libs/network/doc/reference/http_response.rst rename to doc/reference/http_response.rst diff --git a/libs/network/doc/reference/http_server.rst b/doc/reference/http_server.rst similarity index 100% rename from libs/network/doc/reference/http_server.rst rename to doc/reference/http_server.rst diff --git a/libs/network/doc/references.rst b/doc/references.rst similarity index 100% rename from libs/network/doc/references.rst rename to doc/references.rst diff --git a/libs/network/doc/techniques.rst b/doc/techniques.rst similarity index 100% rename from libs/network/doc/techniques.rst rename to doc/techniques.rst diff --git a/libs/network/doc/techniques/directives.rst b/doc/techniques/directives.rst similarity index 100% rename from libs/network/doc/techniques/directives.rst rename to doc/techniques/directives.rst diff --git a/libs/network/doc/techniques/polymorphism.rst b/doc/techniques/polymorphism.rst similarity index 100% rename from libs/network/doc/techniques/polymorphism.rst rename to doc/techniques/polymorphism.rst diff --git a/libs/network/doc/techniques/tag_metafunctions.rst b/doc/techniques/tag_metafunctions.rst similarity index 100% rename from libs/network/doc/techniques/tag_metafunctions.rst rename to doc/techniques/tag_metafunctions.rst diff --git a/libs/network/doc/whats_new.rst b/doc/whats_new.rst similarity index 100% rename from libs/network/doc/whats_new.rst rename to doc/whats_new.rst diff --git a/http/CMakeLists.txt b/http/CMakeLists.txt new file mode 100644 index 000000000..cad1c7ea6 --- /dev/null +++ b/http/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +add_subdirectory(src) + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif(CPP-NETLIB_BUILD_TESTS) diff --git a/http/src/CMakeLists.txt b/http/src/CMakeLists.txt new file mode 100644 index 000000000..5c7ee9379 --- /dev/null +++ b/http/src/CMakeLists.txt @@ -0,0 +1,185 @@ +# Copyright (c) Glyn Matthews 2011, 2012. +# Copyright 2011 Dean Michael Berris (dberris@google.com) +# Copyright 2012 A. Joel Lamotte (mjklaim@gmail.com) +# Copyright 2011 Google, Inc. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +include_directories( + ${CPP-NETLIB_SOURCE_DIR}/uri/src + ${CPP-NETLIB_SOURCE_DIR}/message/src + ${CPP-NETLIB_SOURCE_DIR}/logging/src + ${CPP-NETLIB_SOURCE_DIR}/http/src + ${CPP-NETLIB_SOURCE_DIR}) + +if (OPENSSL_FOUND) +include_directories(${OPENSSL_INCLUDE_DIR}) +endif() + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + if (HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") + elseif (HAVE_STD0X) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++0x") + endif() +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +set(CPP-NETLIB_HTTP_MESSAGE_SRCS http/request.cpp http/response.cpp) +add_library(cppnetlib-http-message ${CPP-NETLIB_HTTP_MESSAGE_SRCS}) +add_dependencies(cppnetlib-http-message +# ${Boost_LIBRARIES} + cppnetlib-message) +target_link_libraries(cppnetlib-http-message + ${Boost_LIBRARIES} + cppnetlib-message) +foreach (src_file ${CPP-NETLIB_HTTP_MESSAGE_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +set(CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS http/message/wrappers.cpp) +add_library(cppnetlib-http-message-wrappers ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS}) +foreach (src_file ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +#set(CPP-NETLIB_HTTP_SERVER_PARSERS_SRCS server_request_parsers_impl.cpp) +#add_library(cppnetlib-http-server-parsers ${CPP-NETLIB_HTTP_SERVER_PARSERS_SRCS}) +#foreach (src_file ${CPP-NETLIB_HTTP_SERVER_PARSERS_SRCS}) +#if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) +# set_source_files_properties(${src_file} +# PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +#elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) +# set_source_files_properties(${src_file} +# PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +#endif() +#endforeach(src_file) +# +#set(CPP-NETLIB_HTTP_SERVER_SRCS +# http/server_async_impl.cpp +# http/server_options.cpp +# http/server_socket_options_setter.cpp +# http/server_sync_impl.cpp +# ) +#add_library(cppnetlib-http-server ${CPP-NETLIB_HTTP_SERVER_SRCS}) +#add_dependencies(cppnetlib-http-server +# ${CPP-NETLIB_LOGGING_LIB} +# cppnetlib-constants +# cppnetlib-uri +# cppnetlib-message +# cppnetlib-message-wrappers +# cppnetlib-message-directives +# cppnetlib-http-message +# cppnetlib-http-message-wrappers +# cppnetlib-http-server-parsers +# cppnetlib-utils-thread_pool +# ) +#target_link_libraries(cppnetlib-http-server +# ${Boost_LIBRARIES} +# ${CPP-NETLIB_LOGGING_LIB} +# cppnetlib-constants +# cppnetlib-uri +# cppnetlib-message +# cppnetlib-message-wrappers +# cppnetlib-message-directives +# cppnetlib-http-message +# cppnetlib-http-message-wrappers +# cppnetlib-http-server-parsers +# cppnetlib-utils-thread_pool +# ) +#foreach (src_file ${CPP-NETLIB_HTTP_SERVER_SRCS}) +#if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) +# set_source_files_properties(${src_file} +# PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +#elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) +# set_source_files_properties(${src_file} +# PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +#endif() +#endforeach(src_file) + +set(CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS + http/client_connections.cpp + http/simple_connection_manager.cpp + http/simple_connection_factory.cpp + http/connection_delegate_factory.cpp + http/client_resolver_delegate.cpp + http/client_resolver_delegate_factory.cpp + http/client_connection_delegates.cpp + http/client_connection_factory.cpp + http/client_async_resolver.cpp + http/client_connection_normal.cpp) +add_library(cppnetlib-http-client-connections ${CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS}) +foreach (src_file ${CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +set(CPP-NETLIB_HTTP_CLIENT_SRCS + http/client.cpp) +add_library(cppnetlib-http-client ${CPP-NETLIB_HTTP_CLIENT_SRCS}) +add_dependencies(cppnetlib-http-client + ${CPP-NETLIB_LOGGING_LIB} + cppnetlib-constants + cppnetlib-uri + cppnetlib-message + cppnetlib-message-wrappers + cppnetlib-message-directives + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-http-client-connections + ) +target_link_libraries(cppnetlib-http-client + ${Boost_LIBRARIES} + ${CPP-NETLIB_LOGGING_LIB} + cppnetlib-constants + cppnetlib-uri + cppnetlib-message + cppnetlib-message-wrappers + cppnetlib-message-directives + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-http-client-connections + ) +foreach (src_file ${CPP-NETLIB_HTTP_CLIENT_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +set(CPP-NETLIB_CONSTANTS_SRCS constants.cpp) +add_library(cppnetlib-constants ${CPP-NETLIB_CONSTANTS_SRCS}) +foreach (src_file ${CPP-NETLIB_CONSTANTS_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) diff --git a/http/src/client.cpp b/http/src/client.cpp new file mode 100644 index 000000000..2616a1da6 --- /dev/null +++ b/http/src/client.cpp @@ -0,0 +1,17 @@ + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#warn Building the library even with NETWORK_NO_LIB defined. +#undef NETWORK_NO_LIB +#endif + +#include + +#ifdef NETWORK_ENABLE_HTTPS +#include +#endif diff --git a/http/src/constants.cpp b/http/src/constants.cpp new file mode 100644 index 000000000..54a3642f4 --- /dev/null +++ b/http/src/constants.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/client.cpp b/http/src/http/client.cpp new file mode 100644 index 000000000..5773e8733 --- /dev/null +++ b/http/src/http/client.cpp @@ -0,0 +1,15 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include +#include +#include + diff --git a/http/src/http/client_async_resolver.cpp b/http/src/http/client_async_resolver.cpp new file mode 100644 index 000000000..48b47bf14 --- /dev/null +++ b/http/src/http/client_async_resolver.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/client_connection_delegates.cpp b/http/src/http/client_connection_delegates.cpp new file mode 100644 index 000000000..337c6307f --- /dev/null +++ b/http/src/http/client_connection_delegates.cpp @@ -0,0 +1,14 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#ifdef NETWORK_ENABLE_HTTPS +#include +#endif diff --git a/http/src/http/client_connection_factory.cpp b/http/src/http/client_connection_factory.cpp new file mode 100644 index 000000000..cdab4271b --- /dev/null +++ b/http/src/http/client_connection_factory.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/client_connection_normal.cpp b/http/src/http/client_connection_normal.cpp new file mode 100644 index 000000000..c576528a3 --- /dev/null +++ b/http/src/http/client_connection_normal.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/client_connections.cpp b/http/src/http/client_connections.cpp new file mode 100644 index 000000000..5060504d7 --- /dev/null +++ b/http/src/http/client_connections.cpp @@ -0,0 +1,16 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include +#include +#include +#include +#include diff --git a/http/src/http/client_resolver_delegate.cpp b/http/src/http/client_resolver_delegate.cpp new file mode 100644 index 000000000..7c942e59f --- /dev/null +++ b/http/src/http/client_resolver_delegate.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/client_resolver_delegate_factory.cpp b/http/src/http/client_resolver_delegate_factory.cpp new file mode 100644 index 000000000..cc6b58ea0 --- /dev/null +++ b/http/src/http/client_resolver_delegate_factory.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/connection_delegate_factory.cpp b/http/src/http/connection_delegate_factory.cpp new file mode 100644 index 000000000..20a81a235 --- /dev/null +++ b/http/src/http/connection_delegate_factory.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/message/wrappers.cpp b/http/src/http/message/wrappers.cpp new file mode 100644 index 000000000..d1ab4594f --- /dev/null +++ b/http/src/http/message/wrappers.cpp @@ -0,0 +1,12 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include diff --git a/http/src/http/request.cpp b/http/src/http/request.cpp new file mode 100644 index 000000000..f458eb415 --- /dev/null +++ b/http/src/http/request.cpp @@ -0,0 +1,12 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include diff --git a/http/src/http/response.cpp b/http/src/http/response.cpp new file mode 100644 index 000000000..f6c0d65d6 --- /dev/null +++ b/http/src/http/response.cpp @@ -0,0 +1,16 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include + +#include +#include +#include diff --git a/boost/network/uri.hpp b/http/src/http/server_async_impl.cpp similarity index 51% rename from boost/network/uri.hpp rename to http/src/http/server_async_impl.cpp index e9ad1ffea..9393b9b9f 100644 --- a/boost/network/uri.hpp +++ b/http/src/http/server_async_impl.cpp @@ -1,12 +1,7 @@ -#ifndef BOOST_NETWORK_URL_HPP_ -#define BOOST_NETWORK_URL_HPP_ - -// Copyright 2009 Dean Michael Berris. +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include - -#endif - +#include diff --git a/http/src/http/server_options.cpp b/http/src/http/server_options.cpp new file mode 100644 index 000000000..5a56bca09 --- /dev/null +++ b/http/src/http/server_options.cpp @@ -0,0 +1,7 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include diff --git a/http/src/http/server_socket_options_setter.cpp b/http/src/http/server_socket_options_setter.cpp new file mode 100644 index 000000000..c5858de85 --- /dev/null +++ b/http/src/http/server_socket_options_setter.cpp @@ -0,0 +1,7 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include diff --git a/http/src/http/server_sync_impl.cpp b/http/src/http/server_sync_impl.cpp new file mode 100644 index 000000000..d96258a08 --- /dev/null +++ b/http/src/http/server_sync_impl.cpp @@ -0,0 +1,7 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include diff --git a/http/src/http/simple_connection_factory.cpp b/http/src/http/simple_connection_factory.cpp new file mode 100644 index 000000000..58cad8222 --- /dev/null +++ b/http/src/http/simple_connection_factory.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/http/simple_connection_manager.cpp b/http/src/http/simple_connection_manager.cpp new file mode 100644 index 000000000..ac74804b0 --- /dev/null +++ b/http/src/http/simple_connection_manager.cpp @@ -0,0 +1,11 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include diff --git a/http/src/network/constants.hpp b/http/src/network/constants.hpp new file mode 100644 index 000000000..8fc82213b --- /dev/null +++ b/http/src/network/constants.hpp @@ -0,0 +1,40 @@ +#ifndef NETWORK_CONSTANTS_HPP_20100808 +#define NETWORK_CONSTANTS_HPP_20100808 + +// Copyright 2010 (C) Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +namespace network { + +struct constants { + static char const * crlf(); + static char const * dot(); + static char dot_char(); + static char const * http_slash(); + static char const * space(); + static char space_char(); + static char const * slash(); + static char slash_char(); + static char const * host(); + static char const * colon(); + static char colon_char(); + static char const * accept(); + static char const * default_accept_mime(); + static char const * accept_encoding(); + static char const * default_accept_encoding(); + static char const * user_agent(); + static char const * default_user_agent(); + static char const * cpp_netlib_slash(); + static char question_mark_char(); + static char hash_char(); + static char const * connection(); + static char const * close(); + static char const * https(); +}; + +} // namespace network + +#endif // NETWORK_CONSTANTS_HPP_20100808 diff --git a/http/src/network/constants.ipp b/http/src/network/constants.ipp new file mode 100644 index 000000000..c72068b7e --- /dev/null +++ b/http/src/network/constants.ipp @@ -0,0 +1,128 @@ +#ifndef NETWORK_CONSTANTS_HPP_20111008 +#define NETWORK_CONSTANTS_HPP_20111008 + +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace network { + +char const * constants::crlf() { + static char crlf_[] = "\r\n"; + return crlf_; +} + +char const * constants::dot() { + static char dot_[] = "."; + return dot_; +} + +char constants::dot_char() { return '.'; } + +char const * constants::http_slash() { + static char http_slash_[] = "HTTP/"; + return http_slash_; +} + +char const * constants::space() { + static char space_[] = {' ', 0}; + return space_; +} + +char constants::space_char() { return ' '; } + +char const * constants::slash() { + static char slash_[] = {'/', 0}; + return slash_; +} + +char constants::slash_char() { return '/'; } + +char const * constants::host() { + static char host_[] = {'H', 'o', 's', 't', 0}; + return host_; +} + +char const * constants::colon() { + static char colon_[] = {':', 0}; + return colon_; +} + +char constants::colon_char() { return ':'; } + +char const * constants::accept() { + static char accept_[] = {'A', 'c', 'c', 'e', 'p', 't', 0}; + return accept_; +} + +char const * constants::default_accept_mime() { + static char mime_[] = { + '*', '/', '*', 0 + }; + return mime_; +} + +char const * constants::accept_encoding() { + static char accept_encoding_[] = { + 'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',0 + }; + return accept_encoding_; +} + +char const * constants::default_accept_encoding() { + static char default_accept_encoding_[] = { + 'i','d','e','n','t','i','t','y',';','q','=','1','.','0',',',' ','*',';','q','=','0',0 + }; + return default_accept_encoding_; +} + +char const * constants::user_agent() { + static char user_agent_[] = { + 'U','s','e','r','-','A','g','e','n','t',0 + }; + return user_agent_; +} + +char const * constants::cpp_netlib_slash() { + static char cpp_netlib_slash_[] = { + 'c','p','p','-','n','e','t','l','i','b','/',0 + }; + return cpp_netlib_slash_; +} + +char constants::question_mark_char() { + return '?'; +} + +char constants::hash_char() { + return '#'; +} + +char const * constants::connection() { + static char connection_[] = "Connection"; + return connection_; +} + +char const * constants::close() { + static char close_[] = "close"; + return close_; +} + +char const * constants::https() { + static char https_[] = "https"; + return https_; +} + +char const * constants::default_user_agent() { + static char user_agent_[] = "cpp-netlib/" NETLIB_VERSION; + return user_agent_; +} + +} // namespace network + +#endif /* NETWORK_CONSTANTS_HPP_20111008 */ diff --git a/http/src/network/http/client.hpp b/http/src/network/http/client.hpp new file mode 100644 index 000000000..3a72eaeff --- /dev/null +++ b/http/src/network/http/client.hpp @@ -0,0 +1,16 @@ +// Copyright (c) Glyn Matthews 2012. +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_HTTP_CLIENT_INC__ +#define NETWORK_HTTP_CLIENT_INC__ + +#include +#include +#include +#include + +#endif // NETWORK_HTTP_CLIENT_INC__ diff --git a/http/src/network/http/errors.hpp b/http/src/network/http/errors.hpp new file mode 100644 index 000000000..53a75b67d --- /dev/null +++ b/http/src/network/http/errors.hpp @@ -0,0 +1,11 @@ +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_HTTP_ERRORS_INC__ +#define NETWORK_HTTP_ERRORS_INC__ + +#include + +#endif // NETWORK_HTTP_ERRORS_INC__ diff --git a/http/src/network/http/request.hpp b/http/src/network/http/request.hpp new file mode 100644 index 000000000..bdcd47647 --- /dev/null +++ b/http/src/network/http/request.hpp @@ -0,0 +1,11 @@ +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_HTTP_REQUEST_INC__ +#define NETWORK_HTTP_REQUEST_INC__ + +#include + +#endif // NETWORK_HTTP_REQUEST_INC__ diff --git a/http/src/network/http/response.hpp b/http/src/network/http/response.hpp new file mode 100644 index 000000000..323495258 --- /dev/null +++ b/http/src/network/http/response.hpp @@ -0,0 +1,11 @@ +// Copyright (c) Glyn Matthews 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_HTTP_RESPONSE_INC__ +#define NETWORK_HTTP_RESPONSE_INC__ + +#include + +#endif // NETWORK_HTTP_RESPONSE_INC__ diff --git a/http/src/network/include/http/client.hpp b/http/src/network/include/http/client.hpp new file mode 100644 index 000000000..7bdcee434 --- /dev/null +++ b/http/src/network/include/http/client.hpp @@ -0,0 +1,21 @@ +// Copyright 2009 Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// This is the modular include file for using the HTTP Client + +#ifndef NETWORK_INCLUDE_HTTP_CLIENT_HPP_ +#define NETWORK_INCLUDE_HTTP_CLIENT_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#endif // NETWORK_INCLUDE_HTTP_CLIENT_HPP_ + diff --git a/http/src/network/include/http/server.hpp b/http/src/network/include/http/server.hpp new file mode 100644 index 000000000..8f8a9f9c6 --- /dev/null +++ b/http/src/network/include/http/server.hpp @@ -0,0 +1,17 @@ +// Copyright 2010-2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// This is the modular include file for using the HTTP Client + +#ifndef NETWORK_INCLUDE_HTTP_SERVER_HPP_ +#define NETWORK_INCLUDE_HTTP_SERVER_HPP_ + +#include +#include +#include +#include + +#endif diff --git a/boost/network/include/message.hpp b/http/src/network/include/message.hpp similarity index 57% rename from boost/network/include/message.hpp rename to http/src/network/include/message.hpp index 539292673..9b7669950 100644 --- a/boost/network/include/message.hpp +++ b/http/src/network/include/message.hpp @@ -1,15 +1,15 @@ -#ifndef BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ -#define BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ - // Copyright 2009 Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // This is the modular include file for using the basic message type -#include -#include +#ifndef NETWORK_INCLUDE_MESSAGE_HPP_ +#define NETWORK_INCLUDE_MESSAGE_HPP_ + +#include -#endif // BOOST_NETWORK_INCLUDE_MESSAGE_HPP_ +#endif // NETWORK_INCLUDE_MESSAGE_HPP_ diff --git a/http/src/network/protocol.hpp b/http/src/network/protocol.hpp new file mode 100644 index 000000000..188a97f8e --- /dev/null +++ b/http/src/network/protocol.hpp @@ -0,0 +1,16 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOLS_20070908_1_HPP +#define NETWORK_PROTOCOLS_20070908_1_HPP + +// Include all protocol implementation headers in protocol/* +// Author: Dean Michael Berris +// Date Created: Oct. 08, 2007 + +#include // include HTTP implementation + +#endif // NETWORK_PROTOCOLS_20070908-1_HPP diff --git a/http/src/network/protocol/http.hpp b/http/src/network/protocol/http.hpp new file mode 100644 index 000000000..8c29dc750 --- /dev/null +++ b/http/src/network/protocol/http.hpp @@ -0,0 +1,19 @@ +// Copyright Dean Michael Berris 2007, 2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_20070908_1_HPP +#define NETWORK_PROTOCOL_HTTP_20070908_1_HPP + +// Include HTTP implementation headers +// Author: Dean Michael Berris +// Date Created: Oct. 08, 2007 + +#include +#include +#include +#include + +#endif // NETWORK_PROTOCOL_HTTP_20070908-1_HPP diff --git a/http/src/network/protocol/http/algorithms/linearize.hpp b/http/src/network/protocol/http/algorithms/linearize.hpp new file mode 100644 index 000000000..56df0e089 --- /dev/null +++ b/http/src/network/protocol/http/algorithms/linearize.hpp @@ -0,0 +1,164 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 +#define NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct linearize_header { + typedef std::string string_type; + + template + struct result; + + template + struct result { + typedef string_type type; + }; + + template + BOOST_CONCEPT_REQUIRES( + ((Header)), + (string_type) + ) operator()(ValueType const & header) { + typedef std::ostringstream output_stream; + typedef constants consts; + output_stream header_line; + header_line << name(header) + << consts::colon() << consts::space() + << value(header) << consts::crlf(); + return header_line.str(); + } +}; + +template +BOOST_CONCEPT_REQUIRES( + ((ClientRequest)), + (OutputIterator) +) linearize( + Request const & request, + std::string const & method, + unsigned version_major, + unsigned version_minor, + OutputIterator oi + ) +{ + typedef constants consts; + typedef std::string string_type; + static string_type + http_slash = consts::http_slash() + , accept = consts::accept() + , accept_mime = consts::default_accept_mime() + , accept_encoding = consts::accept_encoding() + , default_accept_encoding = consts::default_accept_encoding() + , default_user_agent = consts::default_user_agent() + , user_agent = consts::user_agent() + , crlf = consts::crlf() + , host_const = consts::host() + , connection = consts::connection() + , close = consts::close() + ; + boost::copy(method, oi); + *oi = consts::space_char(); + { + std::string path_ = path(request); + if (path_.empty() || path_[0] != consts::slash_char()) + *oi = consts::slash_char(); + boost::copy(path_, oi); + } + { + std::string query_ = query(request); + if (!query_.empty()) { + *oi = consts::question_mark_char(); + boost::copy(query_, oi); + } + } + { + std::string anchor_ = anchor(request); + if (!anchor_.empty()) { + *oi = consts::hash_char(); + boost::copy(anchor_, oi); + } + } + *oi = consts::space_char(); + boost::copy(http_slash, oi); + string_type version_major_str = boost::lexical_cast(version_major), + version_minor_str = boost::lexical_cast(version_minor); + boost::copy(version_major_str, oi); + *oi = consts::dot_char(); + boost::copy(version_minor_str, oi); + boost::copy(crlf, oi); + boost::copy(host_const, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + { + std::string host_ = host(request); + boost::copy(host_, oi); + } + boost::optional port_ = port(request); + if (port_) { + string_type port_str = boost::lexical_cast(*port_); + *oi = consts::colon_char(); + boost::copy(port_str, oi); + } + boost::copy(crlf, oi); + boost::copy(accept, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(accept_mime, oi); + boost::copy(crlf, oi); + if (version_major == 1u && version_minor == 1u) { + boost::copy(accept_encoding, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(default_accept_encoding, oi); + boost::copy(crlf, oi); + } + typedef headers_wrapper::container_type headers_container; + typedef headers_container::const_iterator headers_iterator; + headers_container const & request_headers = network::headers(request); + headers_iterator iterator = boost::begin(request_headers), + end = boost::end(request_headers); + bool has_user_agent = false; + for (; iterator != end; ++iterator) { + string_type header_name = name(*iterator), + header_value = value(*iterator); + boost::copy(header_name, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(header_value, oi); + boost::copy(crlf, oi); + boost::to_lower(header_name); + has_user_agent = has_user_agent || header_name == "user-agent"; + } + if (!has_user_agent) { + boost::copy(user_agent, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(default_user_agent, oi); + boost::copy(crlf, oi); + } + boost::copy(crlf, oi); + auto body_data = network::body(request); + return std::copy(body_data.begin(), body_data.end(), oi); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ diff --git a/http/src/network/protocol/http/client.hpp b/http/src/network/protocol/http/client.hpp new file mode 100644 index 000000000..d6832919c --- /dev/null +++ b/http/src/network/protocol/http/client.hpp @@ -0,0 +1,46 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_20091215 +#define NETWORK_PROTOCOL_HTTP_CLIENT_20091215 + +#include +#include + +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct client : basic_client_facade { + private: + typedef basic_client_facade + base_facade_type; + public: + typedef network::http::request request; + typedef network::http::response response; + + // Constructor + // ================================================================= + // A client can be default constructed. + client(); + // This is a simplified constructor that takes a reference to a const + // client_options instance. To find out what the supported options are + // see the boost/network/protocol/http/client/options.hpp file. + // + explicit client(client_options const &options); + // + // ================================================================= +}; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_20091215 diff --git a/http/src/network/protocol/http/client.ipp b/http/src/network/protocol/http/client.ipp new file mode 100644 index 000000000..fa2fb9a6f --- /dev/null +++ b/http/src/network/protocol/http/client.ipp @@ -0,0 +1,30 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_IPP_20120306 +#define NETWORK_PROTOCOL_HTTP_CLIENT_IPP_20120306 + +#include +#include +#include + +namespace network { namespace http { + +client::client() +: base_facade_type() { + NETWORK_MESSAGE("client::client()"); +} + +client::client(client_options const &options) +: base_facade_type(options) +{ + NETWORK_MESSAGE("client::client(client_options const &)"); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_IPP_20120306 diff --git a/http/src/network/protocol/http/client/base.hpp b/http/src/network/protocol/http/client/base.hpp new file mode 100644 index 000000000..69255ba8d --- /dev/null +++ b/http/src/network/protocol/http/client/base.hpp @@ -0,0 +1,45 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_BASE_HPP_20111008 +#define NETWORK_PROTOCOL_HTTP_CLIENT_BASE_HPP_20111008 + +#include +#include + +namespace network { +namespace http { + +struct client_base_pimpl; +struct request; +struct response; + +class request_options; + +class client_options; + +struct client_base { + typedef + std::function const &, boost::system::error_code const &)> + body_callback_function_type; + + client_base(); + explicit client_base(client_options const &options); + ~client_base(); + response const request_skeleton(request const & request_, + std::string const & method, + bool get_body, + body_callback_function_type callback, + request_options const &options); + void clear_resolved_cache(); + private: + client_base_pimpl * pimpl; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_BASE_HPP_20111008 */ diff --git a/http/src/network/protocol/http/client/base.ipp b/http/src/network/protocol/http/client/base.ipp new file mode 100644 index 000000000..f3c5f3cb0 --- /dev/null +++ b/http/src/network/protocol/http/client/base.ipp @@ -0,0 +1,131 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 +#define NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + +struct client_base_pimpl { + typedef + std::function const &, boost::system::error_code const &)> + body_callback_function_type; + client_base_pimpl(client_options const &options); + response const request_skeleton(request const & request_, + std::string const & method, + bool get_body, + body_callback_function_type callback, + request_options const &options); + void clear_resolved_cache(); + ~client_base_pimpl(); + private: + client_options options_; + boost::asio::io_service * service_ptr; + std::shared_ptr sentinel_; + std::shared_ptr lifetime_thread_; + std::shared_ptr connection_manager_; + bool owned_service_; +}; + +client_base::client_base() +: pimpl(new client_base_pimpl(client_options())) { + NETWORK_MESSAGE("client_base::client_base()"); +} + +client_base::client_base(client_options const &options) +: pimpl(new client_base_pimpl(options)) { + NETWORK_MESSAGE("client_base::client_base(client_options const &)"); +} + +void client_base::clear_resolved_cache() { + pimpl->clear_resolved_cache(); +} + +response const client_base::request_skeleton(request const & request_, + std::string const & method, + bool get_body, + body_callback_function_type callback, + request_options const &options) { + NETWORK_MESSAGE("client_base::request_skeleton(...)"); + return pimpl->request_skeleton(request_, method, get_body, callback, options); +} + +client_base::~client_base() { + NETWORK_MESSAGE("client_base::~client_base()"); + delete pimpl; +} + +client_base_pimpl::client_base_pimpl(client_options const &options) + : options_(options), + service_ptr(options.io_service()), + sentinel_(), + connection_manager_(options.connection_manager()), + owned_service_(false) { + NETWORK_MESSAGE("client_base_pimpl::client_base_pimpl(client_options const &)"); + if (service_ptr == 0) { + NETWORK_MESSAGE("creating owned io_service."); + service_ptr = new boost::asio::io_service; + owned_service_ = true; + } + if (!connection_manager_.get()) { + NETWORK_MESSAGE("creating owned simple_connection_manager"); + connection_manager_.reset( + new simple_connection_manager(options)); + } + sentinel_.reset(new boost::asio::io_service::work(*service_ptr)); + auto local_ptr = service_ptr; + lifetime_thread_.reset(new std::thread([local_ptr]() { local_ptr->run(); })); + if (!lifetime_thread_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Cannot allocate client lifetime thread; not enough memory.")); +} + +client_base_pimpl::~client_base_pimpl() +{ + NETWORK_MESSAGE("client_base_pimpl::~client_base_pimpl()"); + sentinel_.reset(); + connection_manager_->reset(); + if (lifetime_thread_.get()) { + lifetime_thread_->join(); + lifetime_thread_.reset(); + } + if (owned_service_) delete service_ptr; +} + +response const client_base_pimpl::request_skeleton( + request const & request_, + std::string const & method, + bool get_body, + body_callback_function_type callback, + request_options const &options + ) +{ + NETWORK_MESSAGE("client_base_pimpl::request_skeleton(...)"); + std::shared_ptr connection_; + connection_ = connection_manager_->get_connection(*service_ptr, request_, options_); + return connection_->send_request(method, request_, get_body, callback, options); +} + +void client_base_pimpl::clear_resolved_cache() { + NETWORK_MESSAGE("client_base_pimpl::clear_resolved_cache()"); + connection_manager_->clear_resolved_cache(); +} + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 diff --git a/http/src/network/protocol/http/client/client_connection.hpp b/http/src/network/protocol/http/client/client_connection.hpp new file mode 100644 index 000000000..2b721f8f3 --- /dev/null +++ b/http/src/network/protocol/http/client/client_connection.hpp @@ -0,0 +1,40 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_HPP_20111103 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_HPP_20111103 + +#include +#include +#include + +namespace network { namespace http { + +struct request; +struct response; + +class request_options; + +struct client_connection { + typedef std::function< + void(boost::iterator_range const &, + boost::system::error_code const &)> + callback_type; + virtual response send_request(std::string const & method, + request const & request, + bool get_body, + callback_type callback, + request_options const &options) = 0; + virtual client_connection * clone() const = 0; + virtual void reset() = 0; + virtual ~client_connection() = 0; +}; + +} /* http */ + +} /* network */ + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_HPP_20111103 */ diff --git a/http/src/network/protocol/http/client/client_connection.ipp b/http/src/network/protocol/http/client/client_connection.ipp new file mode 100644 index 000000000..e734d1076 --- /dev/null +++ b/http/src/network/protocol/http/client/client_connection.ipp @@ -0,0 +1,33 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_IPP_20111103 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_IPP_20111103 + +#include +#include +#include + +namespace network { namespace http { + +client_connection::~client_connection() { + NETWORK_MESSAGE("client_connection::~client_connection()"); + // Do nothing here. +} + +client_connection * client_connection::clone() const { + NETWORK_MESSAGE("client_connection::clone()"); + // For exposition only. + BOOST_ASSERT(false && "This should not ever be called."); + return 0; +} + + +} /* http */ + +} /* network */ + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CLIENT_CONNECTION_IPP_20111103 */ diff --git a/http/src/network/protocol/http/client/connection/async_normal.hpp b/http/src/network/protocol/http/client/connection/async_normal.hpp new file mode 100644 index 000000000..91a172869 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_normal.hpp @@ -0,0 +1,54 @@ +// Copyright 2010 (C) Dean Michael Berris +// Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google,Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 +#define NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 + +#include +#include +#include + +namespace boost { namespace asio { +class io_service; +} // namespace asio +} // namespace boost + +namespace network { namespace http { + +struct request; +struct response; +struct resolver_delegate; +struct connection_delegate; + +struct http_async_connection_pimpl; + +struct http_async_connection : client_connection + , std::enable_shared_from_this { + using client_connection::callback_type; + http_async_connection(std::shared_ptr resolver_delegate, + std::shared_ptr connection_delegate, + boost::asio::io_service & io_service, + bool follow_redirects); + http_async_connection * clone() const; + virtual response send_request(std::string const & method, + request const & request, + bool get_body, + callback_type callback, + request_options const &options); // override + virtual void reset(); // override + virtual ~http_async_connection(); + private: + explicit http_async_connection(std::shared_ptr); + std::shared_ptr pimpl; +}; + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_CONNECTION_HPP_20100601 diff --git a/http/src/network/protocol/http/client/connection/async_normal.ipp b/http/src/network/protocol/http/client/connection/async_normal.ipp new file mode 100644 index 000000000..90106a7d1 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_normal.ipp @@ -0,0 +1,887 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_NORMAL_IPP_20111123 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_NORMAL_IPP_20111123 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NETWORK_ENABLE_HTTPS +#include +#endif + +namespace network { namespace http { + +struct http_async_connection_pimpl : std::enable_shared_from_this +{ + typedef http_async_connection::callback_type body_callback_function_type; + typedef resolver_delegate::resolver_iterator resolver_iterator; + typedef resolver_delegate::iterator_pair resolver_iterator_pair; + typedef http_async_connection_pimpl this_type; + + http_async_connection_pimpl( + std::shared_ptr resolver_delegate, + std::shared_ptr connection_delegate, + boost::asio::io_service & io_service, + bool follow_redirect) + : + follow_redirect_(follow_redirect), + request_strand_(io_service), + resolver_delegate_(resolver_delegate), + connection_delegate_(connection_delegate) { + NETWORK_MESSAGE("http_async_connection_pimpl::http_async_connection_pimpl(...)"); + } + + // This is the main entry point for the connection/request pipeline. We're + // overriding async_connection_base<...>::start(...) here which is called + // by the client. + response start(request const & request, + std::string const & method, + bool get_body, + body_callback_function_type callback, + request_options const &options) { + NETWORK_MESSAGE("http_async_connection_pimpl::start(...)"); + response response_; + this->init_response(response_); + // Use HTTP/1.1 -- at some point we might want to implement a different + // connection type just for HTTP/1.0. + // TODO: Implement a different connection type and factory for HTTP/1.0. + linearize(request, method, 1, 1, + std::ostreambuf_iterator(&command_streambuf)); + this->method = method; + NETWORK_MESSAGE("method: " << this->method); + boost::uint16_t port_ = port(request); + NETWORK_MESSAGE("port: " << port_); + this->host_ = host(request); + + resolver_delegate_->resolve( + this->host_, + port_, + request_strand_.wrap( + boost::bind( + &this_type::handle_resolved, + this_type::shared_from_this(), + port_, + get_body, + callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + return response_; + } + + http_async_connection_pimpl * clone() { + NETWORK_MESSAGE("http_async_connection_pimpl::clone()"); + return new http_async_connection_pimpl( + this->resolver_delegate_, + this->connection_delegate_, + request_strand_.get_io_service(), + follow_redirect_); + } + + void reset() { + // FIXME Perform the actual re-set of the internal state and pending stuff. + } + + private: + + http_async_connection_pimpl(http_async_connection_pimpl const &); // = delete + + void init_response(response &r) { + NETWORK_MESSAGE("http_async_connection_pimpl::init_response(...)"); + impl::setter_access accessor; + accessor.set_source_promise(r, this->source_promise); + accessor.set_destination_promise(r, this->destination_promise); + accessor.set_headers_promise(r, this->headers_promise); + accessor.set_body_promise(r, this->body_promise); + accessor.set_version_promise(r, this->version_promise); + accessor.set_status_promise(r, this->status_promise); + accessor.set_status_message_promise(r, this->status_message_promise); + NETWORK_MESSAGE("futures and promises lined up."); + } + + void set_errors(boost::system::error_code const & ec) { + NETWORK_MESSAGE("http_async_connection_pimpl::set_errors(...)"); + NETWORK_MESSAGE("error: " << ec); + boost::system::system_error error(ec); + this->version_promise.set_exception(std::make_exception_ptr(error)); + this->status_promise.set_exception(std::make_exception_ptr(error)); + this->status_message_promise.set_exception(std::make_exception_ptr(error)); + this->headers_promise.set_exception(std::make_exception_ptr(error)); + this->source_promise.set_exception(std::make_exception_ptr(error)); + this->destination_promise.set_exception(std::make_exception_ptr(error)); + this->body_promise.set_exception(std::make_exception_ptr(error)); + NETWORK_MESSAGE("promise+future exceptions set."); + } + + void handle_resolved(boost::uint16_t port, + bool get_body, + body_callback_function_type callback, + boost::system::error_code const & ec, + resolver_iterator_pair endpoint_range) { + NETWORK_MESSAGE("http_async_connection_pimpl::handle_resolved(...)"); + if (!ec && !boost::empty(endpoint_range)) { + // Here we deal with the case that there was no error encountered. + NETWORK_MESSAGE("resolved endpoint successfully"); + resolver_iterator iter = boost::begin(endpoint_range); + NETWORK_MESSAGE("trying connection to: " + << iter->endpoint().address() << ":" << port); + boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + + connection_delegate_->connect( + endpoint, + this->host_, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + boost::asio::placeholders::error))); + } else { + NETWORK_MESSAGE("error encountered while resolving."); + set_errors(ec ? ec : boost::asio::error::host_not_found); + } + } + + void handle_connected(boost::uint16_t port, + bool get_body, + body_callback_function_type callback, + resolver_iterator_pair endpoint_range, + boost::system::error_code const & ec) { + NETWORK_MESSAGE("http_async_connection_pimpl::handle_connected(...)"); + if (!ec) { + NETWORK_MESSAGE("connected successfully"); + BOOST_ASSERT(connection_delegate_.get() != 0); + NETWORK_MESSAGE("scheduling write..."); + + connection_delegate_->write(command_streambuf, + request_strand_.wrap( + boost::bind( + &this_type::handle_sent_request, + this_type::shared_from_this(), + get_body, + callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } else { + NETWORK_MESSAGE("connection unsuccessful"); + if (!boost::empty(endpoint_range)) { + resolver_iterator iter = boost::begin(endpoint_range); + NETWORK_MESSAGE("trying: " << iter->endpoint().address() << ":" << port); + boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + + connection_delegate_->connect(endpoint, + this->host_, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + boost::asio::placeholders::error))); + } else { + set_errors(ec ? ec : boost::asio::error::host_not_found); + } + } + } + + enum state_t { + version, status, status_message, headers, body + }; + + void handle_sent_request(bool get_body, + body_callback_function_type callback, + boost::system::error_code const & ec, + std::size_t bytes_transferred) { + NETWORK_MESSAGE("http_async_connection_pimpl::handle_sent_request(...)"); + if (!ec) { + NETWORK_MESSAGE("request sent successfuly; scheduling partial read..."); + + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } else { + NETWORK_MESSAGE("request sent unsuccessfully; setting errors"); + set_errors(ec); + } + } + + void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + NETWORK_MESSAGE("http_async_connection_pimpl::handle_received_data(...)"); + // Okay, there's some weirdness with Boost.Asio's handling of SSL errors + // so we need to do some acrobatics to make sure that we're handling the + // short-read errors correctly. This is such a PITA that we have to deal + // with this here. + static long short_read_error = 335544539; + bool is_short_read_error = +#ifdef NETWORK_ENABLE_HTTPS + ec.category() == boost::asio::error::ssl_category && + ec.value() == short_read_error +#else + false +#endif + ; + if (!ec || ec == boost::asio::error::eof || is_short_read_error) { + NETWORK_MESSAGE("processing data chunk, no error encountered so far..."); + boost::logic::tribool parsed_ok; + + size_t remainder; + switch(state) { + case version: + NETWORK_MESSAGE("parsing version..."); + parsed_ok = + this->parse_version(request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)), + bytes_transferred); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case status: + NETWORK_MESSAGE("parsing status..."); + parsed_ok = + this->parse_status(request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + status, get_body, callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)), + bytes_transferred); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case status_message: + NETWORK_MESSAGE("parsing status message..."); + parsed_ok = + this->parse_status_message( + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + status_message, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + bytes_transferred + ); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case headers: + NETWORK_MESSAGE("parsing headers..."); + // In the following, remainder is the number of bytes that remain + // in the buffer. We need this in the body processing to make sure + // that the data remaining in the buffer is dealt with before + // another call to get more data for the body is scheduled. + boost::fusion::tie(parsed_ok, remainder) = + this->parse_headers( + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + headers, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + bytes_transferred + ); + + if (!parsed_ok || indeterminate(parsed_ok)) return; + + if (!get_body) { + NETWORK_MESSAGE("not getting body..."); + // We short-circuit here because the user does not + // want to get the body (in the case of a HEAD + // request). + this->body_promise.set_value(""); + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + NETWORK_MESSAGE("processing done."); + return; + } + + if (callback) { + NETWORK_MESSAGE("callback provided, processing body..."); + // Here we deal with the spill-over data from the + // headers processing. This means the headers data + // has already been parsed appropriately and we're + // looking to treat everything that remains in the + // buffer. + buffer_type::const_iterator begin = this->part_begin; + buffer_type::const_iterator end = begin; + std::advance(end, std::min(bytes_transferred, remainder)); + + // We're setting the body promise here to an empty string because + // this can be used as a signaling mechanism for the user to + // determine that the body is now ready for processing, even + // though the callback is already provided. + this->body_promise.set_value(""); + + // The invocation of the callback is synchronous to allow us to + // wait before scheduling another read. + callback(boost::make_iterator_range(begin, end), ec); + + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } else { + NETWORK_MESSAGE("no callback provided, appending to body..."); + // Here we handle the body data ourself and append to an + // ever-growing string buffer. + this->parse_body( + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + remainder); + } + return; + case body: + NETWORK_MESSAGE("parsing body..."); + if (ec == boost::asio::error::eof || is_short_read_error) { + NETWORK_MESSAGE("end of the line."); + // Here we're handling the case when the connection has been + // closed from the server side, or at least that the end of file + // has been reached while reading the socket. This signals the end + // of the body processing chain. + if (callback) { + NETWORK_MESSAGE("callback provided, invoking callback..."); + buffer_type::const_iterator begin = + this->part.begin(), + end = begin; + std::advance(end, bytes_transferred); + + // We call the callback function synchronously passing the error + // condition (in this case, end of file) so that it can handle + // it appropriately. + callback(boost::make_iterator_range(begin, end), ec); + } else { + NETWORK_MESSAGE("no callback provided, appending to body..."); + std::string body_string; + std::swap(body_string, this->partial_parsed); + body_string.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body_string); + } + // TODO set the destination value somewhere! + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + } else { + NETWORK_MESSAGE("connection still active..."); + // This means the connection has not been closed yet and we want to get more + // data. + if (callback) { + NETWORK_MESSAGE("callback provided, invoking callback..."); + // Here we have a body_handler callback. Let's invoke the + // callback from here and make sure we're getting more data + // right after. + buffer_type::const_iterator begin = this->part.begin(); + buffer_type::const_iterator end = begin; + std::advance(end, bytes_transferred); + callback(boost::make_iterator_range(begin, end), ec); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1( + this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } else { + NETWORK_MESSAGE("no callback provided, appending to body..."); + bool get_more = true; + if (content_length_) { + buffer_type::const_iterator begin = this->part.begin(); + buffer_type::const_iterator end = begin; + std::advance(end, bytes_transferred); + get_more = (end - begin) < *content_length_; + NETWORK_MESSAGE("content_length = " << * content_length_ + << ", bytes read = " << (end - begin) << ", read more = " << get_more); + } + // Here we don't have a body callback. Let's + // make sure that we deal with the remainder + // from the headers part in case we do have data + // that's still in the buffer. + if (get_more) { + this->parse_body(request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)), + bytes_transferred); + } else { + std::string body_string; + std::swap(body_string, this->partial_parsed); + body_string.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body_string); + // TODO set the destination value somewhere! + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + } + } + } + return; + default: + BOOST_ASSERT(false && "Bug, report this to the developers!"); + } + } else { + boost::system::system_error error(ec); + NETWORK_MESSAGE("error encountered: " << error.what() << " (" << ec << ")"); + this->source_promise.set_exception(std::make_exception_ptr(error)); + this->destination_promise.set_exception(std::make_exception_ptr(error)); + switch (state) { + case version: + this->version_promise.set_exception(std::make_exception_ptr(error)); + case status: + this->status_promise.set_exception(std::make_exception_ptr(error)); + case status_message: + this->status_message_promise.set_exception(std::make_exception_ptr(error)); + case headers: + this->headers_promise.set_exception(std::make_exception_ptr(error)); + case body: + this->body_promise.set_exception(std::make_exception_ptr(error)); + break; + default: + BOOST_ASSERT(false && "Bug, report this to the developers!"); + } + } + } + +#ifdef NETWORK_DEBUG + struct debug_escaper { + std::string & string; + explicit debug_escaper(std::string & string_) + : string(string_) {} + debug_escaper(debug_escaper const & other) + : string(other.string) {} + void operator()( std::string::value_type input) { + if (!boost::algorithm::is_print()(input)) { + std::ostringstream escaped_stream; + if (input == '\r') { + string.append("\\r"); + } else if (input == '\n') { + string.append("\\n"); + } else { + escaped_stream << "\\x" << static_cast(input); + string.append(escaped_stream.str()); + } + } else { + string.push_back(input); + } + } + }; +#endif + + struct to_http_headers { + template + std::string const operator() (U const & pair) const { + std::ostringstream header_line; + header_line << pair.first + << constants::colon() + << constants::space() + << pair.second + << constants::crlf(); + return header_line.str(); + } + }; + + boost::logic::tribool parse_version( + std::function callback, + size_t bytes) { + boost::logic::tribool parsed_ok; + part_begin = part.begin(); + buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + boost::fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser::http_version_done, + input_range); + if (parsed_ok == true) { + std::string version; + std::swap(version, partial_parsed); + version.append(boost::begin(result_range), + boost::end(result_range)); + boost::algorithm::trim(version); + version_promise.set_value(version); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { +#ifdef NETWORK_DEBUG + std::string escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif + std::runtime_error error("Invalid Version Part."); + version_promise.set_exception(std::make_exception_ptr(error)); + status_promise.set_exception(std::make_exception_ptr(error)); + status_message_promise.set_exception( + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range) + ); + part_begin = part.begin(); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } + + boost::logic::tribool parse_status( + std::function callback, + size_t bytes) { + boost::logic::tribool parsed_ok; + buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + boost::iterator_range< buffer_type::const_iterator> + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + boost::fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser::http_status_done, + input_range); + if (parsed_ok == true) { + std::string status; + std::swap(status, partial_parsed); + status.append(boost::begin(result_range), + boost::end(result_range)); + boost::trim(status); + boost::uint16_t status_int = + boost::lexical_cast(status); + status_promise.set_value(status_int); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { +#ifdef NETWORK_DEBUG + std::string escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif + std::runtime_error error("Invalid status part."); + status_promise.set_exception(std::make_exception_ptr(error)); + status_message_promise.set_exception( + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range) + ); + part_begin = part.begin(); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } + + boost::logic::tribool parse_status_message( + std::function callback, + size_t bytes) { + boost::logic::tribool parsed_ok; + buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + boost::iterator_range< buffer_type::const_iterator> + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + boost::fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser::http_status_message_done, + input_range); + if (parsed_ok == true) { + std::string status_message; + std::swap(status_message, partial_parsed); + status_message.append(boost::begin(result_range), + boost::end(result_range)); + boost::algorithm::trim(status_message); + status_message_promise.set_value(status_message); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { +#ifdef NETWORK_DEBUG + std::string escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif + std::runtime_error error("Invalid status message part."); + status_message_promise.set_exception( + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + part_begin = part.begin(); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } + + void parse_headers_real(std::string & headers_part) { + boost::iterator_range< std::string::const_iterator> + input_range = boost::make_iterator_range(headers_part) + , result_range; + boost::logic::tribool parsed_ok; + response_parser headers_parser( + response_parser::http_header_line_done); + std::multimap headers; + std::pair header_pair; + while (!boost::empty(input_range)) { + boost::fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser::http_header_colon, + input_range); + if (headers_parser.state() + != response_parser::http_header_colon) + break; + header_pair.first = std::string(boost::begin(result_range), + boost::end(result_range)); + input_range.advance_begin(boost::distance(result_range)); + boost::fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser::http_header_line_done, + input_range); + header_pair.second = std::string(boost::begin(result_range), + boost::end(result_range)); + input_range.advance_begin(boost::distance(result_range)); + + boost::trim(header_pair.first); + if (header_pair.first.size() > 1) { + header_pair.first.erase( + header_pair.first.size() - 1 + ); + } + boost::trim(header_pair.second); + headers.insert(header_pair); + } + // Set content length + content_length_ = boost::none; + auto it = headers.find("Content-Length"); + if (it != headers.end()) { + try { + content_length_ = std::stoul(it->second); + NETWORK_MESSAGE("Content-Length: " << *content_length_); + } catch(const std::invalid_argument&) { + NETWORK_MESSAGE("invalid argument exception while interpreting " + << it->second << " as content length"); + } catch(const std::out_of_range&) { + NETWORK_MESSAGE("out of range exception while interpreting " + << it->second << " as content length"); + } + } + headers_promise.set_value(headers); + } + + boost::fusion::tuple parse_headers( + std::function callback, + size_t bytes) { + boost::logic::tribool parsed_ok; + buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + boost::fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser::http_headers_done, + input_range); + if (parsed_ok == true) { + std::string headers_string; + std::swap(headers_string, partial_parsed); + headers_string.append(boost::begin(result_range), + boost::end(result_range)); + part_begin = boost::end(result_range); + this->parse_headers_real(headers_string); + } else if (parsed_ok == false) { + // We want to output the contents of the buffer that caused + // the error in debug builds. +#ifdef NETWORK_DEBUG + std::string escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\" consumed length: " + << boost::distance(result_range)); +#endif + std::runtime_error error("Invalid header part."); + headers_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + } else { + partial_parsed.append(boost::begin(result_range), + boost::end(result_range)); + part_begin = part.begin(); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return boost::fusion::make_tuple( + parsed_ok, + std::distance( + boost::end(result_range) + , part_end + ) + ); + } + + void parse_body(std::function callback, size_t bytes) { + // TODO: we should really not use a string for the partial body + // buffer. + partial_parsed.append(part_begin, bytes); + part_begin = part.begin(); + connection_delegate_->read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + + bool follow_redirect_; + boost::asio::io_service::strand request_strand_; + std::shared_ptr resolver_delegate_; + std::shared_ptr connection_delegate_; + boost::asio::streambuf command_streambuf; + std::string method; + response_parser response_parser_; + std::promise version_promise; + std::promise status_promise; + std::promise status_message_promise; + std::promise > headers_promise; + boost::optional content_length_; + std::promise source_promise; + std::promise destination_promise; + std::promise body_promise; + typedef boost::array buffer_type; + buffer_type part; + buffer_type::const_iterator part_begin; + std::string partial_parsed; + std::string host_; +}; + +// END OF PIMPL DEFINITION + +http_async_connection::http_async_connection(std::shared_ptr resolver_delegate, + std::shared_ptr connection_delegate, + boost::asio::io_service & io_service, + bool follow_redirects) +: pimpl(new http_async_connection_pimpl(resolver_delegate, + connection_delegate, + io_service, + follow_redirects)) {} + +http_async_connection::http_async_connection(std::shared_ptr new_pimpl) +: pimpl(new_pimpl) {} + +http_async_connection::~http_async_connection() {} + +http_async_connection * http_async_connection::clone() const { + std::shared_ptr new_pimpl(pimpl->clone()); + return new http_async_connection(new_pimpl); +} + +response http_async_connection::send_request(std::string const & method, + request const & request, + bool get_body, + callback_type callback, + request_options const &options) { + return pimpl->start(request, method, get_body, callback, options); +} + +void http_async_connection::reset() { + pimpl->reset(); // NOTE: We're not resetting the pimpl, just the internal state. +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_NORMAL_IPP_20111123 */ diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/http/src/network/protocol/http/client/connection/async_protocol_handler.hpp similarity index 61% rename from boost/network/protocol/http/client/connection/async_protocol_handler.hpp rename to http/src/network/protocol/http/client/connection/async_protocol_handler.hpp index f0368c0e1..b6a85849b 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/http/src/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -1,6 +1,3 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ - // Copyright 2010 (C) Dean Michael Berris // Copyright 2011 Dean Michael Berris (dberris@google.com). // Copyright 2011 Google, Inc. @@ -8,27 +5,29 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ +#define NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ + +#include +#include -namespace boost { namespace network { namespace http { namespace impl { +namespace network { +namespace http { +namespace impl { - template struct http_async_protocol_handler { protected: - typedef typename string::type string_type; - -#ifdef BOOST_NETWORK_DEBUG +#ifdef NETWORK_DEBUG struct debug_escaper { - string_type & string; - explicit debug_escaper(string_type & string_) + std::string & string; + explicit debug_escaper(std::string & string_) : string(string_) {} debug_escaper(debug_escaper const & other) : string(other.string) {} - void operator()(typename string_type::value_type input) { + void operator()( std::string::value_type input) { if (!algorithm::is_print()(input)) { - typename ostringstream::type escaped_stream; + std::ostringstream escaped_stream; if (input == '\r') { string.append("\\r"); } else if (input == '\n') { @@ -44,38 +43,34 @@ namespace boost { namespace network { namespace http { namespace impl { }; #endif - template - void init_response(ResponseType & response_, bool get_body) { - boost::shared_future source_future( + void init_response(response & response_) { + boost::shared_future source_future( source_promise.get_future()); source(response_, source_future); - boost::shared_future destination_future( + boost::shared_future destination_future( destination_promise.get_future()); destination(response_, destination_future); - boost::shared_future::type> + boost::shared_future > headers_future(headers_promise.get_future()); headers(response_, headers_future); - boost::shared_future body_future( + boost::shared_future body_future( body_promise.get_future()); body(response_, body_future); - boost::shared_future version_future( + boost::shared_future version_future( version_promise.get_future()); version(response_, version_future); boost::shared_future status_future( status_promise.get_future()); status(response_, status_future); - boost::shared_future status_message_future( + boost::shared_future status_message_future( status_message_promise.get_future()); status_message(response_, status_message_future); } struct to_http_headers { - typedef typename string::type string_type; template - string_type const operator() (U const & pair) const { - typedef typename ostringstream::type ostringstream_type; - typedef constants constants; - ostringstream_type header_line; + std::string const operator() (U const & pair) const { + std::ostringstream header_line; header_line << pair.first << constants::colon() << constants::space() @@ -91,16 +86,16 @@ namespace boost { namespace network { namespace http { namespace impl { size_t bytes) { logic::tribool parsed_ok; part_begin = part.begin(); - typename buffer_type::const_iterator part_end = part.begin(); + buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); - typename boost::iterator_range + boost::iterator_range< buffer_type::const_iterator> result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_version_done, + response_parser::http_version_done, input_range); if (parsed_ok == true) { - string_type version; + std::string version; std::swap(version, partial_parsed); version.append(boost::begin(result_range), boost::end(result_range)); @@ -108,25 +103,25 @@ namespace boost { namespace network { namespace http { namespace impl { version_promise.set_value(version); part_begin = boost::end(result_range); } else if (parsed_ok == false) { -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; +#ifdef NETWORK_DEBUG + std::string escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" + NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\""); #endif std::runtime_error error("Invalid Version Part."); - version_promise.set_exception(boost::copy_exception(error)); - status_promise.set_exception(boost::copy_exception(error)); + version_promise.set_exception(std::make_exception_ptr(error)); + status_promise.set_exception(std::make_exception_ptr(error)); status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); } else { partial_parsed.append( boost::begin(result_range), @@ -134,7 +129,7 @@ namespace boost { namespace network { namespace http { namespace impl { ); part_begin = part.begin(); delegate_->read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), + asio::mutable_buffers_1(part.c_array(), part.size()), callback ); } @@ -146,16 +141,16 @@ namespace boost { namespace network { namespace http { namespace impl { Callback callback, size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); + buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); - typename boost::iterator_range + boost::iterator_range< buffer_type::const_iterator> result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_status_done, + response_parser::http_status_done, input_range); if (parsed_ok == true) { - string_type status; + std::string status; std::swap(status, partial_parsed); status.append(boost::begin(result_range), boost::end(result_range)); @@ -165,24 +160,24 @@ namespace boost { namespace network { namespace http { namespace impl { status_promise.set_value(status_int); part_begin = boost::end(result_range); } else if (parsed_ok == false) { -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; +#ifdef NETWORK_DEBUG + std::string escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" + NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped << "\""); #endif std::runtime_error error("Invalid status part."); - status_promise.set_exception(boost::copy_exception(error)); + status_promise.set_exception(std::make_exception_ptr(error)); status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); } else { partial_parsed.append( boost::begin(result_range), @@ -190,7 +185,7 @@ namespace boost { namespace network { namespace http { namespace impl { ); part_begin = part.begin(); delegate_->read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), + asio::mutable_buffers_1(part.c_array(), part.size()), callback ); } @@ -202,16 +197,16 @@ namespace boost { namespace network { namespace http { namespace impl { Callback callback, size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); + buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); - typename boost::iterator_range + boost::iterator_range< buffer_type::const_iterator> result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_status_message_done, + response_parser::http_status_message_done, input_range); if (parsed_ok == true) { - string_type status_message; + std::string status_message; std::swap(status_message, partial_parsed); status_message.append(boost::begin(result_range), boost::end(result_range)); @@ -219,11 +214,11 @@ namespace boost { namespace network { namespace http { namespace impl { status_message_promise.set_value(status_message); part_begin = boost::end(result_range); } else if (parsed_ok == false) { -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; +#ifdef NETWORK_DEBUG + std::string escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" + NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped @@ -231,49 +226,49 @@ namespace boost { namespace network { namespace http { namespace impl { #endif std::runtime_error error("Invalid status message part."); status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); + std::make_exception_ptr(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); } else { partial_parsed.append( boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), + asio::mutable_buffers_1(part.c_array(), part.size()), callback ); } return parsed_ok; } - void parse_headers_real(string_type & headers_part) { - typename boost::iterator_range + void parse_headers_real(std::string & headers_part) { + boost::iterator_range< std::string::const_iterator> input_range = boost::make_iterator_range(headers_part) , result_range; logic::tribool parsed_ok; - response_parser_type headers_parser( - response_parser_type::http_header_line_done); - typename headers_container::type headers; - std::pair header_pair; + response_parser headers_parser( + response_parser::http_header_line_done); + std::multimap headers; + std::pair header_pair; while (!boost::empty(input_range)) { fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( - response_parser_type::http_header_colon, + response_parser::http_header_colon, input_range); if (headers_parser.state() - != response_parser_type::http_header_colon) + != response_parser::http_header_colon) break; - header_pair.first = string_type(boost::begin(result_range), + header_pair.first = std::string(boost::begin(result_range), boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( - response_parser_type::http_header_line_done, + response_parser::http_header_line_done, input_range); - header_pair.second = string_type(boost::begin(result_range), + header_pair.second = std::string(boost::begin(result_range), boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); @@ -294,16 +289,16 @@ namespace boost { namespace network { namespace http { namespace impl { Callback callback, size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); + buffer_type::const_iterator part_end = part.begin(); std::advance(part_end, bytes); - typename boost::iterator_range + boost::iterator_range< buffer_type::const_iterator> result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_headers_done, + response_parser::http_headers_done, input_range); if (parsed_ok == true) { - string_type headers_string; + std::string headers_string; std::swap(headers_string, partial_parsed); headers_string.append(boost::begin(result_range), boost::end(result_range)); @@ -312,11 +307,11 @@ namespace boost { namespace network { namespace http { namespace impl { } else if (parsed_ok == false) { // We want to output the contents of the buffer that caused // the error in debug builds. -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; +#ifdef NETWORK_DEBUG + std::string escaped; debug_escaper escaper(escaped); std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" + NETWORK_MESSAGE("[parser:" << response_parser_.state() << "] buffer contents: \"" << escaped @@ -324,16 +319,16 @@ namespace boost { namespace network { namespace http { namespace impl { << boost::distance(result_range)); #endif std::runtime_error error("Invalid header part."); - headers_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); + headers_promise.set_exception(std::make_exception_ptr(error)); + body_promise.set_exception(std::make_exception_ptr(error)); + source_promise.set_exception(std::make_exception_ptr(error)); + destination_promise.set_exception(std::make_exception_ptr(error)); } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); delegate_->read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), + asio::mutable_buffers_1(part.c_array(), part.size()), callback ); } @@ -353,35 +348,28 @@ namespace boost { namespace network { namespace http { namespace impl { partial_parsed.append(part_begin, bytes); part_begin = part.begin(); delegate_->read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), + asio::mutable_buffers_1(part.c_array(), part.size()), callback ); } - typedef response_parser response_parser_type; - // TODO: make 1024 go away and become a configurable value. - typedef boost::array::type, 1024> buffer_type; - - response_parser_type response_parser_; - boost::promise version_promise; - boost::promise status_promise; - boost::promise status_message_promise; - boost::promise::type> headers_promise; - boost::promise source_promise; - boost::promise destination_promise; - boost::promise body_promise; + response_parser response_parser_; + std::promise version_promise; + std::promise status_promise; + std::promise status_message_promise; + std::promise > headers_promise; + std::promise source_promise; + std::promise destination_promise; + std::promise body_promise; + typedef boost::array buffer_type; buffer_type part; - typename buffer_type::const_iterator part_begin; - string_type partial_parsed; + buffer_type::const_iterator part_begin; + std::string partial_parsed; }; -} /* impl */ - -} /* http */ - -} /* network */ - -} /* boost */ +} // namespace impl +} // namespace http +} // namespace network -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 */ +#endif /* NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 */ diff --git a/http/src/network/protocol/http/client/connection/async_resolver.hpp b/http/src/network/protocol/http/client/connection/async_resolver.hpp new file mode 100644 index 000000000..c3f7ae071 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_resolver.hpp @@ -0,0 +1,38 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_20111126 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_20111126 + +#include +#include + +namespace network { +namespace http { + +struct async_resolver_pimpl; + +struct async_resolver : resolver_delegate { + using resolver_delegate::resolve_completion_function; + + async_resolver(boost::asio::io_service & service, bool cache_resolved); + virtual void resolve(std::string const & host, + uint16_t port, + resolve_completion_function once_resolved); // override + virtual void clear_resolved_cache(); // override + virtual ~async_resolver(); + + protected: + // We need a shared_ptr because the pimpl may live on long after the resolver + // delegate (instances of this type) is actually destroyed. + std::shared_ptr pimpl; +}; + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_20111126 diff --git a/http/src/network/protocol/http/client/connection/async_resolver.ipp b/http/src/network/protocol/http/client/connection/async_resolver.ipp new file mode 100644 index 000000000..53191183b --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_resolver.ipp @@ -0,0 +1,135 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_IPP_20110911 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_IPP_20111126 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + struct async_resolver_pimpl : std::enable_shared_from_this { + typedef resolver_delegate::resolve_completion_function resolve_completion_function; + async_resolver_pimpl(boost::asio::io_service & service, bool cache_resolved); + void resolve(std::string const & host, + uint16_t port, + resolve_completion_function once_resolved); + void clear_resolved_cache(); + private: + boost::asio::ip::udp::resolver resolver_; + bool cache_resolved_; + typedef boost::asio::ip::udp::resolver::iterator + resolver_iterator; + typedef std::unordered_map > + endpoint_cache; + endpoint_cache endpoint_cache_; + std::unique_ptr resolver_strand_; + + void handle_resolve(std::string const & host, + resolve_completion_function once_resolved, + boost::system::error_code const & ec, + resolver_iterator endpoint_iterator); + }; + + async_resolver_pimpl::async_resolver_pimpl(boost::asio::io_service & service, bool cache_resolved) + : resolver_(service), + cache_resolved_(cache_resolved), + endpoint_cache_(), + resolver_strand_(new(std::nothrow) boost::asio::io_service::strand(service)) + { + // Do nothing + } + + void async_resolver_pimpl::clear_resolved_cache() { + if (cache_resolved_) + endpoint_cache().swap(endpoint_cache_); + } + + void async_resolver_pimpl::resolve(std::string const & host, + boost::uint16_t port, + resolve_completion_function once_resolved) { + if (!resolver_strand_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error( + "Uninitialized resolver strand, ran out of memory.")); + + if (cache_resolved_) { + endpoint_cache::iterator iter = + endpoint_cache_.find(boost::to_lower_copy(host)); + if (iter != endpoint_cache_.end()) { + boost::system::error_code ignored; + once_resolved(ignored, iter->second); + return; + } + } + + std::string port_str = boost::lexical_cast(port); + boost::asio::ip::udp::resolver::query query(host, port_str); + using namespace std::placeholders; + resolver_.async_resolve(query, + resolver_strand_->wrap(std::bind(&async_resolver_pimpl::handle_resolve, + async_resolver_pimpl::shared_from_this(), + boost::to_lower_copy(host), + once_resolved, + _1, + _2))); + } + + void async_resolver_pimpl::handle_resolve(std::string const & host, + resolve_completion_function once_resolved, + boost::system::error_code const & ec, + resolver_iterator endpoint_iterator) { + endpoint_cache::iterator iter; + bool inserted = false; + if (!ec && cache_resolved_) { + boost::fusion::tie(iter, inserted) = + endpoint_cache_.insert( + std::make_pair(host, + std::make_pair(endpoint_iterator, + resolver_iterator()))); + once_resolved(ec, iter->second); + } else { + once_resolved(ec, std::make_pair(endpoint_iterator,resolver_iterator())); + } + } + + async_resolver::async_resolver(boost::asio::io_service & service, bool cache_resolved) + : pimpl(new (std::nothrow) async_resolver_pimpl(service, cache_resolved)) + {} + + void async_resolver::resolve(std::string const & host, + uint16_t port, + resolve_completion_function once_resolved) { + BOOST_ASSERT(pimpl.get() && "Uninitialized pimpl, probably ran out of memory."); + pimpl->resolve(host, port, once_resolved); + } + + void async_resolver::clear_resolved_cache() { + BOOST_ASSERT(pimpl.get() && "Uninitialized pimpl, probably ran out of memory."); + pimpl->clear_resolved_cache(); + } + + async_resolver::~async_resolver() { + // Do nothing + } + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_ASYNC_RESOLVER_IPP_20111126 */ diff --git a/http/src/network/protocol/http/client/connection/connection_delegate.hpp b/http/src/network/protocol/http/client/connection/connection_delegate.hpp new file mode 100644 index 000000000..249303257 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate.hpp @@ -0,0 +1,31 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ + +#include +#include +#include + +namespace network { +namespace http { + +struct connection_delegate { + virtual void connect(boost::asio::ip::tcp::endpoint & endpoint, + std::string const & host, + std::function handler) = 0; + virtual void write(boost::asio::streambuf & command_streambuf, + std::function handler) = 0; + virtual void read_some(boost::asio::mutable_buffers_1 const & read_buffer, + std::function handler) = 0; + virtual ~connection_delegate() {} +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ */ diff --git a/http/src/network/protocol/http/client/connection/connection_delegate_factory.hpp b/http/src/network/protocol/http/client/connection/connection_delegate_factory.hpp new file mode 100644 index 000000000..541862af4 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate_factory.hpp @@ -0,0 +1,39 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 + +#include +#include +#include + +namespace network { + namespace http { + + class client_options; + + struct connection_delegate_factory { + typedef std::shared_ptr connection_delegate_ptr; + + connection_delegate_factory(); + + // This is the factory method that actually returns the delegate instance. + virtual connection_delegate_ptr create_connection_delegate(boost::asio::io_service & service, + bool https, + client_options const &options); + + virtual ~connection_delegate_factory(); + + private: + connection_delegate_factory(connection_delegate_factory const &); // = delete + connection_delegate_factory& operator=(connection_delegate_factory); // = delete + }; + + } // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/http/src/network/protocol/http/client/connection/connection_delegate_factory.ipp b/http/src/network/protocol/http/client/connection/connection_delegate_factory.ipp new file mode 100644 index 000000000..c686ded77 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate_factory.ipp @@ -0,0 +1,53 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_FACTORY_IPP_20111123 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_FACTORY_IPP_20111123 + +#include +#ifdef NETWORK_ENABLE_HTTPS +#include +#endif /* NETWORK_ENABLE_HTTPS */ + +#include +#include +#include + +namespace network { namespace http { + + connection_delegate_factory::connection_delegate_factory() { + NETWORK_MESSAGE("connection_delegate_factory::connection_delegate_factory()"); + } + + connection_delegate_factory::connection_delegate_ptr + connection_delegate_factory::create_connection_delegate(boost::asio::io_service & service, + bool https, + client_options const &options) { + NETWORK_MESSAGE("connection_delegate_factory::create_connection_delegate(...)"); + connection_delegate_ptr delegate; + if (https) { +#ifdef NETWORK_ENABLE_HTTPS + NETWORK_MESSAGE("creating an SSL delegate"); + delegate.reset(new ssl_delegate(service, options)); +#else + NETWORK_MESSAGE("creating an SSL delegate, but not supported"); + BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported.")); +#endif /* NETWORK_ENABLE_HTTPS */ + } else { + NETWORK_MESSAGE("creating a normal delegate"); + delegate.reset(new normal_delegate(service)); + } + return delegate; + } + + connection_delegate_factory::~connection_delegate_factory() { + NETWORK_MESSAGE("connection_delegate_factory::~connection_delegate_factory()"); + } + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_FACTORY_IPP_20111123 */ diff --git a/http/src/network/protocol/http/client/connection/connection_factory.hpp b/http/src/network/protocol/http/client/connection/connection_factory.hpp new file mode 100644 index 000000000..f8baf7dfa --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_factory.hpp @@ -0,0 +1,34 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_HPP_20111112 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_HPP_20111112 + +#include + +namespace boost { namespace asio { +class io_service; +} // namespace asio +} // namespace boost + +namespace network { namespace http { + +class client_options; +struct client_connection; +struct request_base; + +struct connection_factory { + virtual std::shared_ptr create_connection( + boost::asio::io_service &service, + request_base const & request, + client_options const &options) = 0; + virtual ~connection_factory() = 0; // pure virtual, interface only. +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_HPP_20111112 */ diff --git a/http/src/network/protocol/http/client/connection/connection_factory.ipp b/http/src/network/protocol/http/client/connection/connection_factory.ipp new file mode 100644 index 000000000..5816adb3d --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_factory.ipp @@ -0,0 +1,19 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_IPP_20111126 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_IPP_20111126 + +#include + +namespace network { namespace http { + +connection_factory::~connection_factory() {} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_FACTORY_IPP_20111126 diff --git a/http/src/network/protocol/http/client/connection/normal_delegate.hpp b/http/src/network/protocol/http/client/connection/normal_delegate.hpp new file mode 100644 index 000000000..da92cd5bc --- /dev/null +++ b/http/src/network/protocol/http/client/connection/normal_delegate.hpp @@ -0,0 +1,47 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 + +#include +#include + +namespace boost { namespace asio { + +class io_service; + +} // namespace asio + +} // namespace boost + +namespace network { +namespace http { + +struct normal_delegate : connection_delegate { + normal_delegate(boost::asio::io_service & service); + + virtual void connect(boost::asio::ip::tcp::endpoint & endpoint, + std::string const &host, + std::function handler); + virtual void write(boost::asio::streambuf & command_streambuf, + std::function handler); + virtual void read_some(boost::asio::mutable_buffers_1 const & read_buffer, + std::function handler); + ~normal_delegate(); + + private: + boost::asio::io_service & service_; + std::unique_ptr socket_; + + normal_delegate(normal_delegate const &); // = delete + normal_delegate& operator=(normal_delegate); // = delete +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 */ diff --git a/http/src/network/protocol/http/client/connection/normal_delegate.ipp b/http/src/network/protocol/http/client/connection/normal_delegate.ipp new file mode 100644 index 000000000..151b921f3 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/normal_delegate.ipp @@ -0,0 +1,46 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 + +#include +#include +#include +#include +#include +#include +#include + +network::http::normal_delegate::normal_delegate(boost::asio::io_service & service) +: service_(service) +{} + +void network::http::normal_delegate::connect(boost::asio::ip::tcp::endpoint & endpoint, + std::string const &host, + std::function handler) { + socket_.reset(new boost::asio::ip::tcp::socket(service_)); + socket_->async_connect(endpoint, handler); +} + +void network::http::normal_delegate::write(boost::asio::streambuf & command_streambuf, + std::function handler) { + NETWORK_MESSAGE("normal_delegate::write(...)"); + NETWORK_MESSAGE("scheduling asynchronous write..."); + boost::asio::async_write(*socket_, command_streambuf, handler); +} + +void network::http::normal_delegate::read_some(boost::asio::mutable_buffers_1 const & read_buffer, + std::function handler) { + NETWORK_MESSAGE("normal_delegate::read_some(...)"); + NETWORK_MESSAGE("scheduling asynchronous read some..."); + socket_->async_read_some(read_buffer, handler); + NETWORK_MESSAGE("scheduled asynchronous read some..."); +} + +network::http::normal_delegate::~normal_delegate() {} + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 */ diff --git a/http/src/network/protocol/http/client/connection/resolver_delegate.hpp b/http/src/network/protocol/http/client/connection/resolver_delegate.hpp new file mode 100644 index 000000000..7f146a222 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate.hpp @@ -0,0 +1,33 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_HPP_20111016 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_HPP_20111016 + +#include +#include +#include + +namespace network { +namespace http { + +struct resolver_delegate { + typedef boost::asio::ip::udp::resolver::iterator resolver_iterator; + typedef std::pair + iterator_pair; + typedef std::function + resolve_completion_function; + virtual void resolve(std::string const & host, + uint16_t port, + resolve_completion_function once_resolved) = 0; + virtual void clear_resolved_cache() = 0; + virtual ~resolver_delegate() = 0; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_HPP_20111016 */ diff --git a/http/src/network/protocol/http/client/connection/resolver_delegate.ipp b/http/src/network/protocol/http/client/connection/resolver_delegate.ipp new file mode 100644 index 000000000..b6646c1bf --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate.ipp @@ -0,0 +1,21 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_IPP_20111126 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_IPP_20111126 + +#include +#include + +namespace network { +namespace http { + +resolver_delegate::~resolver_delegate() {} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_IPP_20111126 diff --git a/http/src/network/protocol/http/client/connection/resolver_delegate_factory.hpp b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.hpp new file mode 100644 index 000000000..b5f0ce467 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.hpp @@ -0,0 +1,30 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_HPP_20110930 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_HPP_20110930 + +#include +#include +#include + +namespace network { namespace http { + +struct resolver_delegate_factory { + resolver_delegate_factory(); + virtual std::shared_ptr create_resolver_delegate( + boost::asio::io_service & service, + bool cache_resolved); + virtual ~resolver_delegate_factory(); + private: + resolver_delegate_factory(resolver_delegate_factory const &); // = delete + resolver_delegate_factory& operator=(resolver_delegate_factory); // = delete +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_HPP_20110930 */ diff --git a/http/src/network/protocol/http/client/connection/resolver_delegate_factory.ipp b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.ipp new file mode 100644 index 000000000..224330756 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.ipp @@ -0,0 +1,35 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_IPP_20111126 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_IPP_20111126 + +#include +#include +#include + +namespace network { +namespace http { + +resolver_delegate_factory::resolver_delegate_factory() { + NETWORK_MESSAGE("resolver_delegate_factory::resolver_delegate_factory()"); +} + +std::shared_ptr +resolver_delegate_factory::create_resolver_delegate(boost::asio::io_service & service, + bool cache_resolved) { + NETWORK_MESSAGE("resolver_delegate_factory::create_resolver_delegate(...)"); + return std::make_shared(service, cache_resolved); +} + +resolver_delegate_factory::~resolver_delegate_factory() { + NETWORK_MESSAGE("resolver_delegate_factory::~resolver_delegate_factory()"); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_RESOLVER_DELEGATE_FACTORY_IPP_20111126 diff --git a/http/src/network/protocol/http/client/connection/simple_connection_factory.hpp b/http/src/network/protocol/http/client/connection/simple_connection_factory.hpp new file mode 100644 index 000000000..5eab04e10 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/simple_connection_factory.hpp @@ -0,0 +1,37 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111112 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111112 + +#include +#include +#include +#include + +namespace network { +namespace http { + +struct simple_connection_factory_pimpl; + +struct simple_connection_factory : connection_factory { + simple_connection_factory(); + simple_connection_factory(std::shared_ptr conn_delegate_factory, + std::shared_ptr res_delegate_factory); + virtual std::shared_ptr create_connection(boost::asio::io_service & service, + request_base const & request, + client_options const & options) override; + virtual ~simple_connection_factory(); + private: + std::unique_ptr pimpl; + simple_connection_factory(simple_connection_factory const &); // = delete + simple_connection_factory& operator=(simple_connection_factory); // = delete +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111112 */ diff --git a/http/src/network/protocol/http/client/connection/simple_connection_factory.ipp b/http/src/network/protocol/http/client/connection/simple_connection_factory.ipp new file mode 100644 index 000000000..ad9db4861 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/simple_connection_factory.ipp @@ -0,0 +1,89 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111120 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111120 + +#include +#include +#include +#include +#include +#include +#include +#ifdef NETWORK_DEBUG +#include +#endif +#include +#include + +#include + +namespace network { +namespace http { + +struct simple_connection_factory_pimpl { + simple_connection_factory_pimpl(std::shared_ptr conn_delegate_factory, + std::shared_ptr res_delegate_factory) + : conn_delegate_factory_(conn_delegate_factory) + , res_delegate_factory_(res_delegate_factory) { + NETWORK_MESSAGE("simple_connection_factory_pimpl::simple_connection_factory_pimpl(...)"); + } + + std::shared_ptr create_connection( + boost::asio::io_service & service, + request_base const & request, + client_options const & options) { + NETWORK_MESSAGE("simple_connection_factory_pimpl::create_connection(...)"); + ::network::uri uri_ = http::uri(request); + NETWORK_MESSAGE("destination: " << uri_); + bool https = boost::algorithm::to_lower_copy(std::string(*uri_.scheme())) == "https"; + return std::make_shared( + res_delegate_factory_->create_resolver_delegate(service, options.cache_resolved()), + conn_delegate_factory_->create_connection_delegate(service, https, options), + service, + options.follow_redirects()); + } + + private: + std::shared_ptr conn_delegate_factory_; + std::shared_ptr res_delegate_factory_; +}; + +simple_connection_factory::simple_connection_factory() { + NETWORK_MESSAGE("simple_connection_factory::simple_connection_factory()"); + std::shared_ptr connection_delegate_factory_; + connection_delegate_factory_.reset(new (std::nothrow) connection_delegate_factory()); + std::shared_ptr resolver_delegate_factory_; + resolver_delegate_factory_.reset(new (std::nothrow) resolver_delegate_factory()); + pimpl.reset(new (std::nothrow) simple_connection_factory_pimpl( + connection_delegate_factory_, resolver_delegate_factory_)); +} + +simple_connection_factory::simple_connection_factory(std::shared_ptr conn_delegate_factory, + std::shared_ptr res_delegate_factory) +: pimpl(new (std::nothrow) simple_connection_factory_pimpl(conn_delegate_factory, res_delegate_factory)) +{ + NETWORK_MESSAGE("simple_connection_factory::simple_connection_factory(...)"); +} + +std::shared_ptr +simple_connection_factory::create_connection(boost::asio::io_service & service, + request_base const & request, + client_options const &options) { + NETWORK_MESSAGE("simple_connection_factory::create_connection(...)"); + return pimpl->create_connection(service, request, options); +} + +simple_connection_factory::~simple_connection_factory() { + NETWORK_MESSAGE("simple_connection_factory::~simple_connection_factory()"); + // do nothing +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SIMPLE_CONNECTION_FACTORY_20111120 */ diff --git a/http/src/network/protocol/http/client/connection/ssl_delegate.hpp b/http/src/network/protocol/http/client/connection/ssl_delegate.hpp new file mode 100644 index 000000000..fd200bd22 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/ssl_delegate.hpp @@ -0,0 +1,54 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 + +#include +#include +#include +#include +#include + +namespace boost { +namespace asio { +class io_service; +} // namespace asio +} // namespace boost + +namespace network { +namespace http { + +struct ssl_delegate : connection_delegate, boost::enable_shared_from_this { + ssl_delegate(boost::asio::io_service & service, + client_options const &options); + + virtual void connect(boost::asio::ip::tcp::endpoint & endpoint, + std::string const &host, + std::function handler); + virtual void write(boost::asio::streambuf & command_streambuf, + std::function handler); + virtual void read_some(boost::asio::mutable_buffers_1 const & read_buffer, + std::function handler); + ~ssl_delegate(); + + private: + boost::asio::io_service & service_; + client_options options_; + std::unique_ptr context_; + std::unique_ptr> socket_; + + ssl_delegate(ssl_delegate const &); // = delete + ssl_delegate& operator=(ssl_delegate); // = delete + + void handle_connected(boost::system::error_code const & ec, + std::function handler); +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 */ diff --git a/http/src/network/protocol/http/client/connection/ssl_delegate.ipp b/http/src/network/protocol/http/client/connection/ssl_delegate.ipp new file mode 100755 index 000000000..8c57bfd05 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/ssl_delegate.ipp @@ -0,0 +1,102 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 + +#include +#include +#include +#include +#include + +network::http::ssl_delegate::ssl_delegate(boost::asio::io_service & service, + client_options const &options) : +service_(service), +options_(options) { + NETWORK_MESSAGE("ssl_delegate::ssl_delegate(...)"); +} + +void network::http::ssl_delegate::connect(boost::asio::ip::tcp::endpoint & endpoint, + std::string const &host, + std::function handler) { + NETWORK_MESSAGE("ssl_delegate::connect(...)"); + context_.reset(new boost::asio::ssl::context(boost::asio::ssl::context::sslv23)); + std::list const & certificate_paths = + options_.openssl_certificate_paths(); + std::list const & verifier_paths = + options_.openssl_verify_paths(); + bool use_default_verification = certificate_paths.empty() && verifier_paths.empty(); + if (!use_default_verification) { + for (std::list::const_iterator it = certificate_paths.begin(); + it != certificate_paths.end(); ++it) { + context_->load_verify_file(*it); + } + for (std::list::const_iterator it = verifier_paths.begin(); + it != verifier_paths.begin(); ++it) { + context_->add_verify_path(*it); + } + NETWORK_MESSAGE("verifying peer: " << host); + context_->set_verify_mode(boost::asio::ssl::context::verify_peer); + context_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); + } else { + NETWORK_MESSAGE("not verifying peer"); + context_->set_default_verify_paths(); + context_->set_verify_mode(boost::asio::ssl::context::verify_peer); + context_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); + } + socket_.reset(new boost::asio::ssl::stream(service_, *context_)); + NETWORK_MESSAGE("scheduling asynchronous connection..."); + using namespace std::placeholders; + socket_->lowest_layer().async_connect(endpoint, + std::bind(&network::http::ssl_delegate::handle_connected, + network::http::ssl_delegate::shared_from_this(), + _1, + handler)); +} + + +void network::http::ssl_delegate::handle_connected(boost::system::error_code const & ec, + std::function handler) { + NETWORK_MESSAGE("ssl_delegate::handle_connected(...)"); + if (!ec) { + NETWORK_MESSAGE("connected to endpoint."); + // Here we check if there's an existing session for the connection. + SSL_SESSION *existing_session = SSL_get1_session(socket_->impl()->ssl); + if (existing_session == NULL) { + NETWORK_MESSAGE("found no existing session, performing handshake."); + socket_->async_handshake(boost::asio::ssl::stream_base::client, handler); + } else { + NETWORK_MESSAGE("found existing session, bypassing handshake."); + SSL_set_session(socket_->impl()->ssl, existing_session); + SSL_connect(socket_->impl()->ssl); + handler(ec); + } + } else { + NETWORK_MESSAGE("encountered error: " << ec); + handler(ec); + } +} + +void network::http::ssl_delegate::write(boost::asio::streambuf & command_streambuf, + std::function handler) { + NETWORK_MESSAGE("ssl_delegate::write(...)"); + NETWORK_MESSAGE("scheduling asynchronous write..."); + boost::asio::async_write(*socket_, command_streambuf, handler); +} + +void network::http::ssl_delegate::read_some(boost::asio::mutable_buffers_1 const & read_buffer, + std::function handler) { + NETWORK_MESSAGE("ssl_delegate::read_some(...)"); + NETWORK_MESSAGE("scheduling asynchronous read_some..."); + socket_->async_read_some(read_buffer, handler); +} + +network::http::ssl_delegate::~ssl_delegate() { + NETWORK_MESSAGE("ssl_delegate::~ssl_delegate()"); +} + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/http/src/network/protocol/http/client/connection/sync_base.hpp similarity index 76% rename from boost/network/protocol/http/client/connection/sync_base.hpp rename to http/src/network/protocol/http/client/connection/sync_base.hpp index 1df519b9f..3d1ff1cf1 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/http/src/network/protocol/http/client/connection/sync_base.hpp @@ -1,27 +1,28 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 - -// Copyright Dean Michael Berris 2009. +// Copyright Dean Michael Berris 2009. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 +#define NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 + +#include +#include +#include +#include +#include +#include +#include #include -#include +#include -#include -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include +#include +#ifdef NETWORK_ENABLE_HTTPS +#include #endif -namespace boost { namespace network { namespace http { namespace impl { +namespace network { namespace http { namespace impl { template struct sync_connection_base_impl { @@ -33,8 +34,8 @@ namespace boost { namespace network { namespace http { namespace impl { template void init_socket(Socket & socket_, resolver_type & resolver_, string_type const & hostname, string_type const & port, resolver_function_type resolve_) { - using boost::asio::ip::tcp; - boost::system::error_code error = boost::asio::error::host_not_found; + using asio::ip::tcp; + asio::error_code error = asio::error::host_not_found; typename resolver_type::iterator endpoint_iterator, end; boost::tie(endpoint_iterator, end) = resolve_(resolver_, hostname, port); while (error && endpoint_iterator != end) { @@ -50,12 +51,12 @@ namespace boost { namespace network { namespace http { namespace impl { } if (error) - throw boost::system::system_error(error); + throw std::system_error(error); } template - void read_status(Socket & socket_, basic_response & response_, boost::asio::streambuf & response_buffer) { - boost::asio::read_until(socket_, response_buffer, "\r\n"); + void read_status(Socket & socket_, basic_response & response_, asio::streambuf & response_buffer) { + asio::read_until(socket_, response_buffer, "\r\n"); std::istream response_stream(&response_buffer); string_type http_version; unsigned int status_code; @@ -75,8 +76,8 @@ namespace boost { namespace network { namespace http { namespace impl { } template - void read_headers(Socket & socket_, basic_response & response_, boost::asio::streambuf & response_buffer) { - boost::asio::read_until(socket_, response_buffer, "\r\n\r\n"); + void read_headers(Socket & socket_, basic_response & response_, asio::streambuf & response_buffer) { + asio::read_until(socket_, response_buffer, "\r\n\r\n"); std::istream response_stream(&response_buffer); string_type header_line, name; while (std::getline(response_stream, header_line) && header_line != "\r") { @@ -100,24 +101,24 @@ namespace boost { namespace network { namespace http { namespace impl { } template - void send_request_impl(Socket & socket_, string_type const & method, boost::asio::streambuf & request_buffer) { + void send_request_impl(Socket & socket_, string_type const & method, asio::streambuf & request_buffer) { write(socket_, request_buffer); } template - void read_body_normal(Socket & socket_, basic_response & response_, boost::asio::streambuf & response_buffer, typename ostringstream::type & body_stream) { - boost::system::error_code error; + void read_body_normal(Socket & socket_, basic_response & response_, asio::streambuf & response_buffer, typename ostringstream::type & body_stream) { + asio::error_code error; if (response_buffer.size() > 0) body_stream << &response_buffer; - while (boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error)) { + while (asio::read(socket_, response_buffer, asio::transfer_at_least(1), error)) { body_stream << &response_buffer; } } template - void read_body_transfer_chunk_encoding(Socket & socket_, basic_response & response_, boost::asio::streambuf & response_buffer, typename ostringstream::type & body_stream) { - boost::system::error_code error; + void read_body_transfer_chunk_encoding(Socket & socket_, basic_response & response_, asio::streambuf & response_buffer, typename ostringstream::type & body_stream) { + asio::error_code error; // look for the content-length header typename headers_range >::type content_length_range = headers(response_)["Content-Length"]; @@ -132,7 +133,7 @@ namespace boost { namespace network { namespace http { namespace impl { bool stopping = false; do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); - if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); + if ((chunk_size_line == 0) && (error != asio::error::eof)) throw std::system_error(error); std::size_t chunk_size = 0; string_type data; { @@ -143,18 +144,24 @@ namespace boost { namespace network { namespace http { namespace impl { } if (chunk_size == 0) { stopping = true; - if (!read_until(socket_, response_buffer, "\r\n", error) && (error != boost::asio::error::eof)) - throw boost::system::system_error(error); + if (!read_until(socket_, response_buffer, "\r\n", error) && (error != asio::error::eof)) + throw std::system_error(error); } else { bool stopping_inner = false; + std::istreambuf_iterator eos; + std::istreambuf_iterator stream_iterator0(&response_buffer); + for (; chunk_size > 0 && stream_iterator0 != eos; --chunk_size) + body_stream << *stream_iterator0++; + do { - std::size_t chunk_bytes_read = read(socket_, response_buffer, boost::asio::transfer_at_least(chunk_size), error); - if (chunk_bytes_read == 0) { - if (error != boost::asio::error::eof) throw boost::system::system_error(error); - stopping_inner = true; + if (chunk_size != 0) { + std::size_t chunk_bytes_read = read(socket_, response_buffer, asio::transfer_at_least(chunk_size), error); + if (chunk_bytes_read == 0) { + if (error != asio::error::eof) throw std::system_error(error); + stopping_inner = true; + } } - std::istreambuf_iterator eos; std::istreambuf_iterator stream_iterator(&response_buffer); for (; chunk_size > 0 && stream_iterator != eos; --chunk_size) body_stream << *stream_iterator++; @@ -174,7 +181,7 @@ namespace boost { namespace network { namespace http { namespace impl { if ( length == 0 ) return; size_t bytes_read = 0; - while ((bytes_read = boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error))) { + while ((bytes_read = asio::read(socket_, response_buffer, asio::transfer_at_least(1), error))) { body_stream << &response_buffer; length -= bytes_read; if ((length <= 0) || error) @@ -184,7 +191,7 @@ namespace boost { namespace network { namespace http { namespace impl { } template - void read_body(Socket & socket_, basic_response & response_, boost::asio::streambuf & response_buffer) { + void read_body(Socket & socket_, basic_response & response_, asio::streambuf & response_buffer) { typename ostringstream::type body_stream; // TODO tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1 if (version_major == 1 && version_minor == 0) { @@ -213,7 +220,7 @@ namespace boost { namespace network { namespace http { namespace impl { // FIXME make the certificate filename and verify path parameters be optional ranges static sync_connection_base * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https, optional const & cert_filename = optional(), optional const & verify_path = optional()) { if (https) { -#ifdef BOOST_NETWORK_ENABLE_HTTPS +#ifdef NETWORK_ENABLE_HTTPS return dynamic_cast*>(new https_sync_connection(resolver, resolve, cert_filename, verify_path)); #else throw std::runtime_error("HTTPS not supported."); @@ -224,9 +231,9 @@ namespace boost { namespace network { namespace http { namespace impl { virtual void init_socket(string_type const & hostname, string_type const & port) = 0; virtual void send_request_impl(string_type const & method, basic_request const & request_) = 0; - virtual void read_status(basic_response & response_, boost::asio::streambuf & response_buffer) = 0; - virtual void read_headers(basic_response & response_, boost::asio::streambuf & response_buffer) = 0; - virtual void read_body(basic_response & response_, boost::asio::streambuf & response_buffer) = 0; + virtual void read_status(basic_response & response_, asio::streambuf & response_buffer) = 0; + virtual void read_headers(basic_response & response_, asio::streambuf & response_buffer) = 0; + virtual void read_body(basic_response & response_, asio::streambuf & response_buffer) = 0; virtual bool is_open() = 0; virtual void close_socket() = 0; virtual ~sync_connection_base() {} @@ -234,13 +241,9 @@ namespace boost { namespace network { namespace http { namespace impl { sync_connection_base() {} }; -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost +} // namespace impl +} // namespace http +} // namespace network -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 +#endif // NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 diff --git a/http/src/network/protocol/http/client/connection/sync_normal.hpp b/http/src/network/protocol/http/client/connection/sync_normal.hpp new file mode 100644 index 000000000..366a0adda --- /dev/null +++ b/http/src/network/protocol/http/client/connection/sync_normal.hpp @@ -0,0 +1,86 @@ +// Copyright 2010 (C) Dean Michael Berris +// Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 +#define NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601 + +#include +#include + +namespace network { +namespace http { +namespace impl { + +template +struct sync_connection_base_impl; + +template +struct sync_connection_base; + +template +struct http_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { + typedef typename resolver_policy::type resolver_base; + typedef typename resolver_base::resolver_type resolver_type; + typedef typename string::type string_type; + typedef function resolver_function_type; + typedef sync_connection_base_impl connection_base; + + http_sync_connection(resolver_type & resolver, resolver_function_type resolve) + : connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.get_io_service()) { } + + void init_socket(string_type const & hostname, string_type const & port) { + connection_base::init_socket(socket_, resolver_, hostname, port, resolve_); + } + + void send_request_impl(string_type const & method, basic_request const & request_) { + asio::streambuf request_buffer; + linearize(request_, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&request_buffer)); + connection_base::send_request_impl(socket_, method, request_buffer); + } + + void read_status(basic_response & response_, asio::streambuf & response_buffer) { + connection_base::read_status(socket_, response_, response_buffer); + } + + void read_headers(basic_response & response, asio::streambuf & response_buffer) { + connection_base::read_headers(socket_, response, response_buffer); + } + + void read_body(basic_response & response_, asio::streambuf & response_buffer) { + connection_base::read_body(socket_, response_, response_buffer); + typename headers_range >::type connection_range = + headers(response_)["Connection"]; + if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { + close_socket(); + } else if (version_major == 1 && version_minor == 0) { + close_socket(); + } + } + + bool is_open() { return socket_.is_open(); } + + void close_socket() { + if (!is_open()) return; + asio::error_code ignored; + socket_.shutdown(asio::ip::tcp::socket::shutdown_both, ignored); + if (ignored) return; + socket_.close(ignored); + } + + private: + + resolver_type & resolver_; + resolver_function_type resolve_; + asio::ip::tcp::socket socket_; +}; + +} // namespace impl +} // nmaespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100 diff --git a/http/src/network/protocol/http/client/connection/sync_ssl.hpp b/http/src/network/protocol/http/client/connection/sync_ssl.hpp new file mode 100644 index 000000000..cb7197b1c --- /dev/null +++ b/http/src/network/protocol/http/client/connection/sync_ssl.hpp @@ -0,0 +1,106 @@ +// Copyright 2010 (C) Dean Michael Berris +// Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 +#define NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 + +#include + +namespace network { +namespace http { +namespace impl { + +template +struct sync_connection_base_impl; + +template +struct sync_connection_base; + +template +struct https_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { + typedef typename resolver_policy::type resolver_base; + typedef typename resolver_base::resolver_type resolver_type; + typedef typename string::type string_type; + typedef function resolver_function_type; + typedef sync_connection_base_impl connection_base; + + // FIXME make the certificate filename and verify path parameters be optional ranges + https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional const & certificate_filename = optional(), optional const & verify_path = optional()) + : connection_base(), + resolver_(resolver), + resolve_(resolve), + context_(resolver.get_io_service(), asio::ssl::context::sslv23_client), + socket_(resolver.get_io_service(), context_) { + if (certificate_filename || verify_path) { + context_.set_verify_mode(asio::ssl::context::verify_peer); + // FIXME make the certificate filename and verify path parameters be optional ranges + if (certificate_filename) context_.load_verify_file(*certificate_filename); + if (verify_path) context_.add_verify_path(*verify_path); + } else { + context_.set_verify_mode(asio::ssl::context::verify_none); + } + } + + void init_socket(string_type const & hostname, string_type const & port) { + connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_); + socket_.handshake(asio::ssl::stream_base::client); + } + + void send_request_impl(string_type const & method, basic_request const & request_) { + asio::streambuf request_buffer; + linearize(request_, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&request_buffer)); + connection_base::send_request_impl(socket_, method, request_buffer); + } + + void read_status(basic_response & response_, asio::streambuf & response_buffer) { + connection_base::read_status(socket_, response_, response_buffer); + } + + void read_headers(basic_response & response_, asio::streambuf & response_buffer) { + connection_base::read_headers(socket_, response_, response_buffer); + } + + void read_body(basic_response & response_, asio::streambuf & response_buffer) { + connection_base::read_body(socket_, response_, response_buffer); + typename headers_range >::type connection_range = + headers(response_)["Connection"]; + if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) { + close_socket(); + } else if (version_major == 1 && version_minor == 0) { + close_socket(); + } + } + + bool is_open() { + return socket_.lowest_layer().is_open(); + } + + void close_socket() { + asio::error_code ignored; + socket_.lowest_layer().shutdown(asio::ip::tcp::socket::shutdown_both, ignored); + if (ignored) return; + socket_.lowest_layer().close(ignored); + } + + ~https_sync_connection() { + close_socket(); + } + + private: + resolver_type & resolver_; + resolver_function_type resolve_; + asio::ssl::context context_; + asio::ssl::stream socket_; + +}; + +} // namespace impl +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601 diff --git a/http/src/network/protocol/http/client/connection_manager.hpp b/http/src/network/protocol/http/client/connection_manager.hpp new file mode 100644 index 000000000..9f5b09373 --- /dev/null +++ b/http/src/network/protocol/http/client/connection_manager.hpp @@ -0,0 +1,37 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_HPP_20110930 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_HPP_20110930 + +#include + +namespace boost { namespace asio { +class io_service; +} // namespace asio +} // namespace boost + +namespace network { +namespace http { + +struct client_connection; +struct request_base; +class client_options; + +struct connection_manager { + virtual std::shared_ptr get_connection( + boost::asio::io_service & service, + request_base const & request, + client_options const & options) = 0; + virtual void clear_resolved_cache() = 0; + virtual void reset() = 0; + virtual ~connection_manager() = 0; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_HPP_20110930 */ diff --git a/http/src/network/protocol/http/client/connection_manager.ipp b/http/src/network/protocol/http/client/connection_manager.ipp new file mode 100644 index 000000000..e9e773d1f --- /dev/null +++ b/http/src/network/protocol/http/client/connection_manager.ipp @@ -0,0 +1,23 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_IPP_20111103 +#define NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_IPP_20111103 + +#include +#include + +namespace network { namespace http { + +connection_manager::~connection_manager() { + NETWORK_MESSAGE("connection_manager::~connection_manager()"); + // default implementation, for linkage only. +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_MANAGER_IPP_20111103 */ diff --git a/http/src/network/protocol/http/client/facade.hpp b/http/src/network/protocol/http/client/facade.hpp new file mode 100644 index 000000000..69e52b221 --- /dev/null +++ b/http/src/network/protocol/http/client/facade.hpp @@ -0,0 +1,51 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 +#define NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 + +#include +#include +#include +#include + +namespace network { +namespace http { + +struct basic_client_facade { + typedef client_base::body_callback_function_type body_callback_function_type; + + basic_client_facade(); + explicit basic_client_facade(client_options const &options); + + response const head(request const &request, request_options const&options=request_options()); + response const get(request const &request, + body_callback_function_type body_handler = body_callback_function_type(), + request_options const &options=request_options()); + response const post(request request, + boost::optional body = boost::optional(), + boost::optional content_type = boost::optional(), + body_callback_function_type body_handler = body_callback_function_type(), + request_options const&options = request_options()); + response const put(request request, + boost::optional body = boost::optional(), + boost::optional content_type = boost::optional(), + body_callback_function_type body_handler = body_callback_function_type(), + request_options const & options = request_options()); + response const delete_(request const & request, + body_callback_function_type body_handler = body_callback_function_type(), + request_options const & options = request_options()); + void clear_resolved_cache(); + + + protected: + boost::scoped_ptr base; +}; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623 diff --git a/http/src/network/protocol/http/client/facade.ipp b/http/src/network/protocol/http/client/facade.ipp new file mode 100644 index 000000000..09b5c91c8 --- /dev/null +++ b/http/src/network/protocol/http/client/facade.ipp @@ -0,0 +1,118 @@ +// Copyright Dean Michael Berris 2012. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_IPP_20120303 +#define NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_IPP_20120303 + +#include +#include +#include + +namespace network { +namespace http { + +basic_client_facade::basic_client_facade() +: base(new (std::nothrow) client_base()) { + NETWORK_MESSAGE("basic_client_facade::basic_client_facade()"); +} + +basic_client_facade::basic_client_facade(client_options const &options) +: base(new (std::nothrow) client_base(options)) { + NETWORK_MESSAGE("basic_client_facade::basic_client_facade(client_options const &)"); +} + +response const basic_client_facade::head(request const &request, + request_options const&options) { + NETWORK_MESSAGE("basic_client_facade::head(...)"); + return base->request_skeleton(request, + "HEAD", + false, + body_callback_function_type(), + options); +} + +response const basic_client_facade::get(request const &request, + body_callback_function_type body_handler, + request_options const &options) { + NETWORK_MESSAGE("basic_client_facade::get(...)"); + return base->request_skeleton(request, "GET", true, body_handler, options); +} + +response const basic_client_facade::post(request request, + boost::optional body, + boost::optional content_type, + body_callback_function_type body_handler, + request_options const &options) { + NETWORK_MESSAGE("basic_client_facade::post(...)"); + if (body) { + NETWORK_MESSAGE("using body provided."); + request << remove_header("Content-Length") + << header("Content-Length", boost::lexical_cast(body->size())) + << network::body(*body); + } + + headers_wrapper::container_type const & headers_ = + headers(request); + if (content_type) { + NETWORK_MESSAGE("using provided content type."); + request << remove_header("Content-Type") + << header("Content-Type", *content_type); + } else { + NETWORK_MESSAGE("using default content type."); + if (boost::empty(headers_.equal_range("Content-Type"))) { + static char default_content_type[] = "x-application/octet-stream"; + request << header("Content-Type", default_content_type); + } + } + return base->request_skeleton(request, "POST", true, body_handler, options); +} + +response const basic_client_facade::put(request request, + boost::optional body, + boost::optional content_type, + body_callback_function_type body_handler, + request_options const & options) { + NETWORK_MESSAGE("basic_client_facade::put(...)"); + if (body) { + NETWORK_MESSAGE("using body provided."); + request << remove_header("Content-Length") + << header("Content-Length", boost::lexical_cast(body->size())) + << network::body(*body); + } + + headers_wrapper::container_type const & headers_ = + headers(request); + if (content_type) { + NETWORK_MESSAGE("using provided content type."); + request << remove_header("Content-Type") + << header("Content-Type", *content_type); + } else { + NETWORK_MESSAGE("using default content type."); + if (boost::empty(headers_.equal_range("Content-Type"))) { + static char default_content_type[] = "x-application/octet-stream"; + request << header("Content-Type", default_content_type); + } + } + return base->request_skeleton(request, "PUT", true, body_handler, options); +} + +response const basic_client_facade::delete_(request const & request, + body_callback_function_type body_handler, + request_options const & options) { + NETWORK_MESSAGE("basic_client_facade::delete_(...)"); + return base->request_skeleton(request, "DELETE", true, body_handler, options); +} + +void basic_client_facade::clear_resolved_cache() { + NETWORK_MESSAGE("basic_client_facade::clear_resolved_cache()"); + base->clear_resolved_cache(); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_IPP_20120303 + diff --git a/http/src/network/protocol/http/client/macros.hpp b/http/src/network/protocol/http/client/macros.hpp new file mode 100644 index 000000000..2e461dc61 --- /dev/null +++ b/http/src/network/protocol/http/client/macros.hpp @@ -0,0 +1,19 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 +#define NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 + +#include +#include + +#ifndef NETWORK_HTTP_BODY_CALLBACK +#define NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, error_name) \ + void function_name (boost::iterator_range const & range_name, boost::system::error_code const & error_name) +#endif + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ + diff --git a/http/src/network/protocol/http/client/options.hpp b/http/src/network/protocol/http/client/options.hpp new file mode 100644 index 000000000..a955552c7 --- /dev/null +++ b/http/src/network/protocol/http/client/options.hpp @@ -0,0 +1,149 @@ +// Copyright Dean Michael Berris 2012. +// Copyright Google, Inc. 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP +#define NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + + // Forward-declare the pimpl. + class client_options_pimpl; + + // This file defines all the options supported by the HTTP client + // implementation. + class client_options { + public: + client_options(); + client_options(client_options const &other); // Copy constructible. + client_options(client_options &&other); // Move constructible. + client_options& operator=(client_options const &rhs); // Copy assignable. + client_options& operator=(client_options &&rhs); // Move assignable. + void swap(client_options &other); // Swappable. + ~client_options(); // Non-virtual destructor by design. + + // When adding more supported options, follow the pattern: + // + // client_options& name_of_option(type variable); + // type name_of_option() const; + // + // These names have to be self-documenting but should still be documented + // to signify their intent and reason for being an option. The reason for + // returning a client_options& (usually *this) is so that it the operations + // can be chained properly. An example of usage would be: + // + // client_options options; + // options.io_service(&my_io_service) + // .follow_redirects() + // .cache_resolved(); + // client client_(options); + + // These are the setter and getter for the Boost.Asio io_service to use. + // The default setting when un-set is nullptr, meaning it signals the client + // implementation that the user doesn't want to use his own io_service + // instance. + client_options& io_service(boost::asio::io_service *io_service); + boost::asio::io_service* io_service() const; + + // The following option determines whether the client should follow + // HTTP redirects when the implementation encounters them. The default + // behavior is to return false. + client_options& follow_redirects(bool setting=false); + bool follow_redirects() const; + + // The following options determines whether the client should cache + // resolved endpoints. The default behavior is to not cache resolved + // endpoints. + client_options& cache_resolved(bool setting=true); + bool cache_resolved() const; + + // The following options provide the OpenSSL certificate paths to use. + // Setting these options without OpenSSL support is valid, but the client + // may throw an exception when attempting to make SSL connections. The + // default implementation doesn't define certificate paths. + client_options& add_openssl_certificate_path(std::string const &path); + std::list const & openssl_certificate_paths() const; + + // The following options provide the OpenSSL certificate authority paths + // where the certificates can be found. Setting these options without OpenSSL + // support is valid, but the client may throw an exception when attempting + // to make SSL connections. The default implementation doesn't define + // certificate authority paths. + client_options& add_openssl_verify_path(std::string const &path); + std::list const & openssl_verify_paths() const; + + // The following options provide the connection manager shared pointer that + // is what the client will use to manage connections. + client_options& connection_manager(std::shared_ptr manager); + std::shared_ptr connection_manager() const; + + // The following supports providing the connection factory instance responsible + // for creating the correct instances of the appropriate connection. + client_options& connection_factory(std::shared_ptr factory); + std::shared_ptr connection_factory() const; + + // More options go here... + + private: + // We hide the options in a pimpl, so that when new options get added + // we can keep backward binary compatibility and re-link to the new + // supported options without having to break those + client_options_pimpl *pimpl; + }; + + // Forward declare the request_options pimpl. + class request_options_pimpl; + + // This is the per-request options we allow users to provide. These allow + // for defining operational options that control a request's flow. + class request_options { + public: + request_options(); // Default constructor. + request_options(request_options const &other); // Copy constructible. + request_options& operator=(request_options rhs); // Assignable. + void swap(request_options &other); // Swappable. + ~request_options(); // Non-virtual destructor by design. + + // We follow the same pattern as the client_options class and use the + // chaining call pattern to set the options. When adding new options + // to support, they should look roughly like so: + // + // request_options& name_of_option(type_of_option variable=default_value); + // type_of_option name_of_option() const; + // + // See client_options above for a usage example in the same vein. + + // These determine the timeout when performing requests. The default timeout + // is 30,000 milliseconds (30 seconds). + request_options& timeout(uint64_t milliseconds = 30 * 1000); + uint64_t timeout() const; + + // These determine the maximum number of redirects to follow. The default + // implementation uses 10 as the maximum. A negative value means to keep + // following redirects until they no longer redirect. + request_options& max_redirects(int redirects=10); + int max_redirects() const; + + // More options go here... + + private: + // For the same reason as the client_options being a pimpl, we do this for + // minimizing the need to break ABI compatibility when adding new supported + // options. + request_options_pimpl *pimpl; + }; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP diff --git a/http/src/network/protocol/http/client/options.ipp b/http/src/network/protocol/http/client/options.ipp new file mode 100644 index 000000000..a860aa5d2 --- /dev/null +++ b/http/src/network/protocol/http/client/options.ipp @@ -0,0 +1,285 @@ +// Copyright Dean Michael Berris 2012. +// Copyright Google, Inc. 2012. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_IPP +#define NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_IPP + +#include +#include +#include + +namespace network { namespace http { + + class client_options_pimpl { + public: + client_options_pimpl() + : io_service_(0) + , follow_redirects_(false) + , cache_resolved_(false) + , openssl_certificate_paths_() + , openssl_verify_paths_() + , connection_manager_() + , connection_factory_() + { + } + + client_options_pimpl *clone() const { + return new (std::nothrow) client_options_pimpl(*this); + } + + void io_service(boost::asio::io_service *io_service) { + io_service_ = io_service_; + } + + boost::asio::io_service* io_service() const { + return io_service_; + } + + void follow_redirects(bool setting) { + follow_redirects_ = setting; + } + + bool follow_redirects() const { + return follow_redirects_; + } + + void cache_resolved(bool setting) { + cache_resolved_ = setting; + } + + bool cache_resolved() const { + return cache_resolved_; + } + + void add_openssl_certificate_path(std::string const &path) { + openssl_certificate_paths_.push_back(path); + } + + std::list const & openssl_certificate_paths() const { + return openssl_certificate_paths_; + } + + void add_openssl_verify_path(std::string const &path) { + openssl_verify_paths_.push_back(path); + } + + std::list const & openssl_verify_paths() const { + return openssl_verify_paths_; + } + + void connection_manager(std::shared_ptr manager) { + connection_manager_ = manager; + } + + std::shared_ptr connection_manager() const { + return connection_manager_; + } + + void connection_factory(std::shared_ptr factory) { + connection_factory_ = factory; + } + + std::shared_ptr connection_factory() const { + return connection_factory_; + } + + private: + client_options_pimpl(client_options_pimpl const &other) + : io_service_(other.io_service_) + , follow_redirects_(other.follow_redirects_) + , cache_resolved_(other.cache_resolved_) + , openssl_certificate_paths_(other.openssl_certificate_paths_) + , openssl_verify_paths_(other.openssl_verify_paths_) + , connection_manager_(other.connection_manager_) + , connection_factory_(other.connection_factory_) + {} + + client_options_pimpl& operator=(client_options_pimpl); // cannot assign + + // Here's the list of members. + boost::asio::io_service *io_service_; + bool follow_redirects_, cache_resolved_; + std::list openssl_certificate_paths_, openssl_verify_paths_; + std::shared_ptr connection_manager_; + std::shared_ptr connection_factory_; + }; + + client_options::client_options() + : pimpl(new (std::nothrow) client_options_pimpl()) + {} + + client_options::client_options(client_options const &other) + : pimpl(other.pimpl->clone()) + {} + + client_options& client_options::operator=(client_options const &rhs) { + client_options copy(rhs); + copy.swap(*this); + return *this; + } + + client_options& client_options::operator=(client_options &&rhs) { + rhs.swap(*this); + return *this; + } + + void client_options::swap(client_options &other) { + using std::swap; + swap(other.pimpl, this->pimpl); + } + + client_options::~client_options() { + delete pimpl; + pimpl = nullptr; + } + + client_options& client_options::io_service(boost::asio::io_service *io_service) { + pimpl->io_service(io_service); + return *this; + } + + boost::asio::io_service* client_options::io_service() const { + return pimpl->io_service(); + } + + client_options& client_options::follow_redirects(bool follow_redirects) { + pimpl->follow_redirects(follow_redirects); + return *this; + } + + bool client_options::follow_redirects() const { + return pimpl->follow_redirects(); + } + + client_options& client_options::cache_resolved(bool cache_resolved) { + pimpl->cache_resolved(cache_resolved); + return *this; + } + + bool client_options::cache_resolved() const { + return pimpl->cache_resolved(); + } + + client_options& client_options::add_openssl_certificate_path(std::string const &path) { + pimpl->add_openssl_certificate_path(path); + return *this; + } + + std::list const & client_options::openssl_certificate_paths() const { + return pimpl->openssl_certificate_paths(); + } + + client_options& client_options::add_openssl_verify_path(std::string const &path) { + pimpl->add_openssl_verify_path(path); + return *this; + } + + std::list const & client_options::openssl_verify_paths() const { + return pimpl->openssl_verify_paths(); + } + + client_options& client_options::connection_manager(std::shared_ptr manager) { + pimpl->connection_manager(manager); + return *this; + } + + std::shared_ptr client_options::connection_manager() const { + return pimpl->connection_manager(); + } + + client_options& client_options::connection_factory(std::shared_ptr factory) { + pimpl->connection_factory(factory); + return *this; + } + + std::shared_ptr client_options::connection_factory() const { + return pimpl->connection_factory(); + } + + // End of client_options. + + class request_options_pimpl { + public: + request_options_pimpl() + : timeout_ms_(30 * 1000) + , max_redirects_(10) + {} + + request_options_pimpl *clone() const { + return new (std::nothrow) request_options_pimpl(*this); + } + + void timeout(uint64_t milliseconds) { + timeout_ms_ = milliseconds; + } + + uint64_t timeout() const { + return timeout_ms_; + } + + void max_redirects(int redirects) { + max_redirects_ = redirects; + } + + int max_redirects() const { + return max_redirects_; + } + + private: + uint64_t timeout_ms_; + int max_redirects_; + + request_options_pimpl(request_options_pimpl const &other) + : timeout_ms_(other.timeout_ms_) + , max_redirects_(other.max_redirects_) + {} + + request_options_pimpl& operator=(request_options_pimpl); // cannot be assigned. + }; + + request_options::request_options() + : pimpl(new (std::nothrow) request_options_pimpl) + {} + + request_options::request_options(request_options const &other) + : pimpl(other.pimpl->clone()) + {} + + request_options& request_options::operator=(request_options rhs) { + rhs.swap(*this); + return *this; + } + + void request_options::swap(request_options &other) { + std::swap(other.pimpl, this->pimpl); + } + + request_options::~request_options() { + delete pimpl; + } + + request_options& request_options::timeout(uint64_t milliseconds) { + pimpl->timeout(milliseconds); + return *this; + } + + uint64_t request_options::timeout() const { + return pimpl->timeout(); + } + + request_options& request_options::max_redirects(int redirects) { + pimpl->max_redirects(redirects); + return *this; + } + + int request_options::max_redirects() const { + return pimpl->max_redirects(); + } + +} // namespace http +} // namespace network + +#endif diff --git a/http/src/network/protocol/http/client/parameters.hpp b/http/src/network/protocol/http/client/parameters.hpp new file mode 100644 index 000000000..ee178826b --- /dev/null +++ b/http/src/network/protocol/http/client/parameters.hpp @@ -0,0 +1,30 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 +#define NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 + +#include + +namespace network { namespace http { + + PARAMETER_NAME(follow_redirects) + PARAMETER_NAME(cache_resolved) + PARAMETER_NAME(openssl_certificate) + PARAMETER_NAME(openssl_verify_path) + + PARAMETER_NAME(request) + PARAMETER_NAME(body) + PARAMETER_NAME(content_type) + PARAMETER_NAME(body_handler) + + PARAMETER_NAME(connection_manager) + PARAMETER_NAME(connection_factory) + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 */ diff --git a/http/src/network/protocol/http/client/pimpl.hpp b/http/src/network/protocol/http/client/pimpl.hpp new file mode 100644 index 000000000..589464ffc --- /dev/null +++ b/http/src/network/protocol/http/client/pimpl.hpp @@ -0,0 +1,85 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 +#define NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 + +#include +#include +#include +#include + +#include +#include + +namespace network { +namespace http { + +template +struct basic_client_impl; + +namespace impl { + + template + struct async_client; + + template + struct sync_client; + + + template + struct client_base { + typedef unsupported_tag type; + }; + + template + struct client_base >::type> { + typedef async_client type; + }; + + template + struct client_base >::type> { + typedef sync_client type; + }; + +} // namespace impl + +template +struct basic_client; + +template +struct basic_client_impl + : impl::client_base::type +{ + STATIC_ASSERT(( + mpl::not_< + mpl::and_< + is_async, + is_sync + > + >::value + )); + + typedef typename impl::client_base::type base_type; + typedef typename base_type::string_type string_type; + + basic_client_impl(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) + : base_type(cache_resolved, follow_redirect, certificate_filename, verify_path) + {} + + basic_client_impl(bool cache_resolved, bool follow_redirect, asio::io_service & service, optional const & certificate_filename, optional const & verify_path) + : base_type(cache_resolved, follow_redirect, service, certificate_filename, verify_path) + {} + + ~basic_client_impl() + {} +}; + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623 diff --git a/http/src/network/protocol/http/client/simple_connection_manager.hpp b/http/src/network/protocol/http/client/simple_connection_manager.hpp new file mode 100644 index 000000000..b338cb981 --- /dev/null +++ b/http/src/network/protocol/http/client/simple_connection_manager.hpp @@ -0,0 +1,88 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_HPP_20111105 +#define NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_HPP_20111105 + +#include +#include +#include + +namespace network { +namespace http { + +/// Forward declaration of simple_connection_manager_pimpl. +struct simple_connection_manager_pimpl; + +/// Forward declaration of the client_options class. +class client_options; + +/** simple_connection_manager + * + * This connection manager implementation doesn't do any connection tracking + * and mostly delegates the connection creation from a connection factory. + */ +struct simple_connection_manager : connection_manager { + /** Constructor + * + * Args: + * options: A properly construction client_options instance. + */ + explicit simple_connection_manager(client_options const &options); + + /** get_connection + * + * Args: + * asio::io_service & service: The io_service instance to which the + * connection should be bound to (for newly + * created objects, ignored for already + * created objects). + * request_base const & request: The request object that includes the + * information required by the connection. + * client_options const & options: The options relating to the client + * options. + * + * Returns: + * shared_ptr -- either an already-generated object + * or a newly constructed connection configured to perform the request. + */ + virtual std::shared_ptr get_connection( + boost::asio::io_service & service, + request_base const & request, + client_options const & options) override; + + /** reset + * + * This function resets the internal caches and intermediary data structures + * used by the connection manager to perform its functions. In the case of + * this simple_connection_manager, the call to reset will not do anything. + */ + virtual void reset() override; + + /** clear_resolved_cache + * + * This function resets all the resolved endpoints that have been cached. + */ + virtual void clear_resolved_cache(); + + /** Destructor. + */ + virtual ~simple_connection_manager() override; + + protected: + std::unique_ptr pimpl; + + private: + /// Disabled copy constructor. + simple_connection_manager(simple_connection_manager const &); // = delete + /// Disabled assignment operator. + simple_connection_manager & operator=(simple_connection_manager); // = delete +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_HPP_20111105 */ diff --git a/http/src/network/protocol/http/client/simple_connection_manager.ipp b/http/src/network/protocol/http/client/simple_connection_manager.ipp new file mode 100644 index 000000000..03cacb101 --- /dev/null +++ b/http/src/network/protocol/http/client/simple_connection_manager.ipp @@ -0,0 +1,90 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_IPP_20111112 +#define NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_IPP_20111112 + +#include +#include +#include +#include + +namespace network { namespace http { + +struct simple_connection_manager_pimpl { + simple_connection_manager_pimpl(client_options const &options) + : options_(options) + , connection_factory_(options.connection_factory()) + { + NETWORK_MESSAGE( + "simple_connection_manager_pimpl::simple_connection_manager_pimpl(" + "client_options const &)"); + if (!connection_factory_.get()) { + NETWORK_MESSAGE("creating simple connection factory"); + connection_factory_.reset( + new (std::nothrow) simple_connection_factory()); + } + } + + std::shared_ptr get_connection(boost::asio::io_service & service, + request_base const & request, + client_options const &options) { + NETWORK_MESSAGE("simple_connection_manager_pimpl::get_connection(...)"); + return connection_factory_->create_connection(service, request, options_); + } + + void reset() { + // do nothing here. + } + + void clear_resolved_cache() { + // TODO(deanberris): Make this happen! + } + + ~simple_connection_manager_pimpl() { + NETWORK_MESSAGE("simple_connection_manager_pimpl::~simple_connection_manager_pimpl()"); + // do nothing here. + } + +private: + client_options options_; + std::shared_ptr connection_factory_; +}; + +simple_connection_manager::simple_connection_manager(client_options const &options) +: pimpl(new (std::nothrow) simple_connection_manager_pimpl(options)) +{ + NETWORK_MESSAGE("simple_connection_manager::simple_connection_manager(" + "client_options const &)"); +} + +std::shared_ptr simple_connection_manager::get_connection( + boost::asio::io_service & service, + request_base const & request, + client_options const &options) { + NETWORK_MESSAGE("simple_connection_manager::get_connection(...)"); + return pimpl->get_connection(service, request, options); +} + +void simple_connection_manager::reset() { + NETWORK_MESSAGE("simple_connection_manager::reset()"); + pimpl->reset(); +} + +void simple_connection_manager::clear_resolved_cache() { + NETWORK_MESSAGE("simple_connection_manager::clear_resolved_cache()"); + pimpl->clear_resolved_cache(); +} + +simple_connection_manager::~simple_connection_manager() { + NETWORK_MESSAGE("simple_connection_manager::~simple_connection_manager()"); + // do nothing here. +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_CLIENT_SIMPLE_CONNECTION_MANAGER_IPP_20111112 */ diff --git a/http/src/network/protocol/http/client/sync_impl.hpp b/http/src/network/protocol/http/client/sync_impl.hpp new file mode 100644 index 000000000..2472103fe --- /dev/null +++ b/http/src/network/protocol/http/client/sync_impl.hpp @@ -0,0 +1,74 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 +#define NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 + +namespace network { namespace http { + +template +struct basic_client_impl; + +namespace impl { + +template +struct sync_client : + connection_policy::type +{ + typedef typename string::type string_type; + typedef typename connection_policy::type connection_base; + typedef typename resolver::type resolver_type; + typedef function const &, system::error_code const &)> body_callback_function_type; + friend struct basic_client_impl; + + asio::io_service * service_ptr; + asio::io_service & service_; + resolver_type resolver_; + optional certificate_file, verify_path; + + sync_client(bool cache_resolved, bool follow_redirect + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) + : connection_base(cache_resolved, follow_redirect), + service_ptr(new asio::io_service), + service_(*service_ptr), + resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) + {} + + sync_client(bool cache_resolved, bool follow_redirect, asio::io_service & service + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) + : connection_base(cache_resolved, follow_redirect), + service_ptr(0), + service_(service), + resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) + {} + + ~sync_client() { + connection_base::cleanup(); + delete service_ptr; + } + + basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body, body_callback_function_type callback) { + typename connection_base::connection_ptr connection_; + connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); + return connection_->send_request(method, request_, get_body, callback); + } + + }; + +} // namespace impl + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623 diff --git a/http/src/network/protocol/http/client_fwd.hpp b/http/src/network/protocol/http/client_fwd.hpp new file mode 100644 index 000000000..2c8379c60 --- /dev/null +++ b/http/src/network/protocol/http/client_fwd.hpp @@ -0,0 +1,25 @@ +// Copyright Dean Michael Berris 2007-2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP +#define NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP + +#include +#include + +namespace network { +namespace http { + +// Forward declaration of basic_client template. +template +class basic_client; + +typedef basic_client client; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_CLIENT_20080923_1_HPP diff --git a/http/src/network/protocol/http/errors.hpp b/http/src/network/protocol/http/errors.hpp new file mode 100644 index 000000000..7935939e5 --- /dev/null +++ b/http/src/network/protocol/http/errors.hpp @@ -0,0 +1,26 @@ +// Copyright Dean Michael Berris 2007, 2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP +#define NETWORK_PROTOCOL_HTTP_ERRORS_20080516_HPP + +#include + +namespace network { +namespace http { +namespace errors { + +struct connection_timeout_exception : std::runtime_error +{}; + +typedef connection_timeout_exception connection_timeout; + +} // namespace errors +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_20080516_HPP + diff --git a/http/src/network/protocol/http/impl/access.hpp b/http/src/network/protocol/http/impl/access.hpp new file mode 100644 index 000000000..8a8001f62 --- /dev/null +++ b/http/src/network/protocol/http/impl/access.hpp @@ -0,0 +1,37 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_ACCESS_HPP_20111202 +#define NETWORK_PROTOCOL_HTTP_IMPL_ACCESS_HPP_20111202 + +#include +#include +#include + +namespace network { +namespace http { + +struct response; + +namespace impl { + +struct setter_access { + void set_version_promise(response &r, std::promise &p); + void set_status_promise(response &r, std::promise &p); + void set_status_message_promise(response &r, std::promise&p); + void set_headers_promise(response &r, std::promise > &p); + void set_source_promise(response &r, std::promise &p); + void set_destination_promise(response &r, std::promise &p); + void set_body_promise(response &r, std::promise &p); +}; + +} // namespace impl + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_IMPL_ACCESS_HPP_20111202 diff --git a/http/src/network/protocol/http/impl/access.ipp b/http/src/network/protocol/http/impl/access.ipp new file mode 100644 index 000000000..2e12c4a14 --- /dev/null +++ b/http/src/network/protocol/http/impl/access.ipp @@ -0,0 +1,44 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace network { +namespace http { +namespace impl { + +void setter_access::set_version_promise(response &r, std::promise &p) { + return r.set_version_promise(p); +} + +void setter_access::set_status_promise(response &r, std::promise &p) { + return r.set_status_promise(p); +} + +void setter_access::set_status_message_promise(response &r, std::promise &p) { + return r.set_status_message_promise(p); +} + +void +setter_access::set_headers_promise(response &r, std::promise > &p) { + return r.set_headers_promise(p); +} + +void setter_access::set_source_promise(response &r, std::promise &p) { + return r.set_source_promise(p); +} + +void setter_access::set_destination_promise(response &r, std::promise &p) { + return r.set_destination_promise(p); +} + +void setter_access::set_body_promise(response &r, std::promise &p) { + return r.set_body_promise(p); +} + +} // namespace impl +} // namespace http +} // namespace network diff --git a/http/src/network/protocol/http/impl/message.ipp b/http/src/network/protocol/http/impl/message.ipp new file mode 100644 index 000000000..5e0f7fe4a --- /dev/null +++ b/http/src/network/protocol/http/impl/message.ipp @@ -0,0 +1,268 @@ +// This file is part of the Boost Network library +// Based on the Pion Network Library (r421) +// Copyright Atomic Labs, Inc. 2007-2008 +// See http://cpp-netlib.sourceforge.net for library home page. +// +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_IPP +#define NETWORK_PROTOCOL_HTTP_MESSAGE_IPP + +#include +#include +#include +#include + +namespace network { +namespace http { + +// static member functions of boost::network::http::message + +template +typename message_impl::string_type const message_impl::url_decode(typename message_impl::string_type const & str) +{ + char decode_buf[3]; + typename message_impl::string_type result; + result.reserve(str.size()); + + for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { + switch(str[pos]) { + case '+': + // convert to space character + result += ' '; + break; + case '%': + // decode hexidecimal value + if (pos + 2 < str.size()) { + decode_buf[0] = str[++pos]; + decode_buf[1] = str[++pos]; + decode_buf[2] = '\0'; + result += static_cast( strtol(decode_buf, 0, 16) ); + } else { + // recover from error by not decoding character + result += '%'; + } + break; + default: + // character does not need to be escaped + result += str[pos]; + } + }; + + return result; +} + +template +typename message_impl::string_type const message_impl::url_encode(typename message_impl::string_type const & str) +{ + char encode_buf[4]; + typename message_impl::string_type result; + encode_buf[0] = '%'; + result.reserve(str.size()); + + // character selection for this algorithm is based on the following url: + // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm + + for (typename message_impl::string_type::size_type pos = 0; pos < str.size(); ++pos) { + switch(str[pos]) { + default: + if (str[pos] >= 32 && str[pos] < 127) { + // character does not need to be escaped + result += str[pos]; + break; + } + // else pass through to next case + + case '$': case '&': case '+': case ',': case '/': case ':': + case ';': case '=': case '?': case '@': case '"': case '<': + case '>': case '#': case '%': case '{': case '}': case '|': + case '\\': case '^': case '~': case '[': case ']': case '`': + // the character needs to be encoded + sprintf(encode_buf+1, "%02X", str[pos]); + result += encode_buf; + break; + } + }; + + return result; +} + +template +typename message_impl::string_type const message_impl::make_query_string(typename query_container::type const & query_params) +{ + typename message_impl::string_type query_string; + for (typename query_container::type::const_iterator i = query_params.begin(); + i != query_params.end(); ++i) + { + if (i != query_params.begin()) + query_string += '&'; + query_string += url_encode(i->first); + query_string += '='; + query_string += url_encode(i->second); + } + return query_string; +} + +template +typename message_impl::string_type const message_impl::make_set_cookie_header(typename message_impl::string_type const & name, + typename message_impl::string_type const & value, + typename message_impl::string_type const & path, + bool const has_max_age, + unsigned long const max_age) +{ + typename message_impl::string_type set_cookie_header(name); + set_cookie_header += "=\""; + set_cookie_header += value; + set_cookie_header += "\"; Version=\"1\""; + if (! path.empty()) { + set_cookie_header += "; Path=\""; + set_cookie_header += path; + set_cookie_header += '\"'; + } + if (has_max_age) { + set_cookie_header += "; Max-Age=\""; + set_cookie_header += boost::lexical_cast::string_type>(max_age); + set_cookie_header += '\"'; + } + return set_cookie_header; +} + +template +bool message_impl::base64_decode(const typename message_impl::string_type &input, typename message_impl::string_type &output) +{ + static const char nop = -1; + static const char decoding_data[] = { + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop, 62, nop,nop,nop, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,nop,nop, nop,nop,nop,nop, + nop, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,nop, nop,nop,nop,nop, + nop,26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, + nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop, nop,nop,nop,nop + }; + + unsigned int input_length=input.size(); + const char * input_ptr = input.data(); + + // allocate space for output string + output.clear(); + output.reserve(((input_length+2)/3)*4); + + // for each 4-bytes sequence from the input, extract 4 6-bits sequences by droping first two bits + // and regenerate into 3 8-bits sequence + + for (unsigned int i=0; i(input_ptr[i])]; + if(base64code0==nop) // non base64 character + return false; + if(!(++i(input_ptr[i])]; + if(base64code1==nop) // non base64 character + return false; + + output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3)); + + if(++i(input_ptr[i])]; + if(base64code2==nop) // non base64 character + return false; + + output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f); + } + + if(++i(input_ptr[i])]; + if(base64code3==nop) // non base64 character + return false; + + output += (((base64code2 << 6) & 0xc0) | base64code3 ); + } + + } + + return true; +} + +template +bool message_impl::base64_encode(typename message_impl::string_type const & input, typename message_impl::string_type & output) +{ + static const char encoding_data[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + unsigned int input_length=input.size(); + const char * input_ptr = input.data(); + + // allocate space for output string + output.clear(); + output.reserve(((input_length+2)/3)*4); + + // for each 3-bytes sequence from the input, extract 4 6-bits sequences and encode using + // encoding_data lookup table. + // if input do not contains enough chars to complete 3-byte sequence,use pad char '=' + for (unsigned int i=0; i> 2) & 0x3f; // 1-byte 6 bits + output += encoding_data[base64code0]; + base64code1 = (input_ptr[i] << 4 ) & 0x3f; // 1-byte 2 bits + + + if (++i < input_length) { + base64code1 |= (input_ptr[i] >> 4) & 0x0f; // 2-byte 4 bits + output += encoding_data[base64code1]; + base64code2 = (input_ptr[i] << 2) & 0x3f; // 2-byte 4 bits + + + if (++i < input_length) { + base64code2 |= (input_ptr[i] >> 6) & 0x03; // 3-byte 2 bits + base64code3 = input_ptr[i] & 0x3f; // 3-byte 6 bits + output += encoding_data[base64code2]; + output += encoding_data[base64code3]; + } else { + output += encoding_data[base64code2]; + output += '='; + } + } else { + output += encoding_data[base64code1]; + output += '='; + output += '='; + } + } + + return true; +} + + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_HPP diff --git a/http/src/network/protocol/http/impl/parser.ipp b/http/src/network/protocol/http/impl/parser.ipp new file mode 100644 index 000000000..462fffc49 --- /dev/null +++ b/http/src/network/protocol/http/impl/parser.ipp @@ -0,0 +1,780 @@ +// This file is part of the Boost Network library +// Based on the Pion Network Library (r421) +// Copyright Atomic Labs, Inc. 2007-2008 +// See http://cpp-netlib.sourceforge.net for library home page. +// +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_PARSER_IPP +#define NETWORK_PROTOCOL_HTTP_PARSER_IPP + +#include + +namespace network { namespace http { + +// member functions for class basic_parser + +template +boost::tribool basic_parser::parse_http_headers(basic_message& http_msg) +{ + // + // note that boost::tribool may have one of THREE states: + // + // false: encountered an error while parsing HTTP headers + // true: finished successfully parsing the HTTP headers + // indeterminate: parsed bytes, but the HTTP headers are not yet finished + // + const char *read_start_ptr = m_read_ptr; + m_bytes_last_read = 0; + while (m_read_ptr < m_read_end_ptr) { + + switch (m_headers_parse_state) { + case PARSE_METHOD_START: + // we have not yet started parsing the HTTP method string + if (*m_read_ptr != ' ' && *m_read_ptr!='\r' && *m_read_ptr!='\n') { // ignore leading whitespace + if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) + return false; + m_headers_parse_state = PARSE_METHOD; + m_method.erase(); + m_method.push_back(*m_read_ptr); + } + break; + + case PARSE_METHOD: + // we have started parsing the HTTP method string + if (*m_read_ptr == ' ') { + m_resource.erase(); + m_headers_parse_state = PARSE_URI_STEM; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else if (m_method.size() >= ParserTraits::METHOD_MAX) { + return false; + } else { + m_method.push_back(*m_read_ptr); + } + break; + + case PARSE_URI_STEM: + // we have started parsing the URI stem (or resource name) + if (*m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HTTP_VERSION_H; + } else if (*m_read_ptr == '?') { + m_query_string.erase(); + m_headers_parse_state = PARSE_URI_QUERY; + } else if (is_control(*m_read_ptr)) { + return false; + } else if (m_resource.size() >= ParserTraits::RESOURCE_MAX) { + return false; + } else { + m_resource.push_back(*m_read_ptr); + } + break; + + case PARSE_URI_QUERY: + // we have started parsing the URI query string + if (*m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HTTP_VERSION_H; + } else if (is_control(*m_read_ptr)) { + return false; + } else if (m_query_string.size() >= ParserTraits::QUERY_STRING_MAX) { + return false; + } else { + m_query_string.push_back(*m_read_ptr); + } + break; + + case PARSE_HTTP_VERSION_H: + // parsing "HTTP" + if (*m_read_ptr != 'H') return false; + m_headers_parse_state = PARSE_HTTP_VERSION_T_1; + break; + + case PARSE_HTTP_VERSION_T_1: + // parsing "HTTP" + if (*m_read_ptr != 'T') return false; + m_headers_parse_state = PARSE_HTTP_VERSION_T_2; + break; + + case PARSE_HTTP_VERSION_T_2: + // parsing "HTTP" + if (*m_read_ptr != 'T') return false; + m_headers_parse_state = PARSE_HTTP_VERSION_P; + break; + + case PARSE_HTTP_VERSION_P: + // parsing "HTTP" + if (*m_read_ptr != 'P') return false; + m_headers_parse_state = PARSE_HTTP_VERSION_SLASH; + break; + + case PARSE_HTTP_VERSION_SLASH: + // parsing slash after "HTTP" + if (*m_read_ptr != '/') return false; + m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR_START; + break; + + case PARSE_HTTP_VERSION_MAJOR_START: + // parsing the first digit of the major version number + if (!is_digit(*m_read_ptr)) return false; + http_msg.setVersionMajor(*m_read_ptr - '0'); + m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR; + break; + + case PARSE_HTTP_VERSION_MAJOR: + // parsing the major version number (not first digit) + if (*m_read_ptr == '.') { + m_headers_parse_state = PARSE_HTTP_VERSION_MINOR_START; + } else if (is_digit(*m_read_ptr)) { + http_msg.setVersionMajor( (http_msg.getVersionMajor() * 10) + + (*m_read_ptr - '0') ); + } else { + return false; + } + break; + + case PARSE_HTTP_VERSION_MINOR_START: + // parsing the first digit of the minor version number + if (!is_digit(*m_read_ptr)) return false; + http_msg.setVersionMinor(*m_read_ptr - '0'); + m_headers_parse_state = PARSE_HTTP_VERSION_MINOR; + break; + + case PARSE_HTTP_VERSION_MINOR: + // parsing the major version number (not first digit) + if (*m_read_ptr == ' ') { + // should only happen for responses + if (m_is_request) return false; + m_headers_parse_state = PARSE_STATUS_CODE_START; + } else if (*m_read_ptr == '\r') { + // should only happen for requests + if (! m_is_request) return false; + m_headers_parse_state = PARSE_EXPECTING_NEWLINE; + } else if (*m_read_ptr == '\n') { + // should only happen for requests + if (! m_is_request) return false; + m_headers_parse_state = PARSE_EXPECTING_CR; + } else if (is_digit(*m_read_ptr)) { + http_msg.setVersionMinor( (http_msg.getVersionMinor() * 10) + + (*m_read_ptr - '0') ); + } else { + return false; + } + break; + + case PARSE_STATUS_CODE_START: + // parsing the first digit of the response status code + if (!is_digit(*m_read_ptr)) return false; + m_status_code = (*m_read_ptr - '0'); + m_headers_parse_state = PARSE_STATUS_CODE; + break; + + case PARSE_STATUS_CODE: + // parsing the response status code (not first digit) + if (*m_read_ptr == ' ') { + m_status_message.erase(); + m_headers_parse_state = PARSE_STATUS_MESSAGE; + } else if (is_digit(*m_read_ptr)) { + m_status_code = ( (m_status_code * 10) + (*m_read_ptr - '0') ); + } else { + return false; + } + break; + + case PARSE_STATUS_MESSAGE: + // parsing the response status message + if (*m_read_ptr == '\r') { + m_headers_parse_state = PARSE_EXPECTING_NEWLINE; + } else if (*m_read_ptr == '\n') { + m_headers_parse_state = PARSE_EXPECTING_CR; + } else if (is_control(*m_read_ptr)) { + return false; + } else if (m_status_message.size() >= ParserTraits::STATUS_MESSAGE_MAX) { + return false; + } else { + m_status_message.push_back(*m_read_ptr); + } + break; + + case PARSE_EXPECTING_NEWLINE: + // we received a CR; expecting a newline to follow + if (*m_read_ptr == '\n') { + m_headers_parse_state = PARSE_HEADER_START; + } else if (*m_read_ptr == '\r') { + // we received two CR's in a row + // assume CR only is (incorrectly) being used for line termination + // therefore, the message is finished + ++m_read_ptr; + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return true; + } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HEADER_WHITESPACE; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else { + // assume it is the first character for the name of a header + m_header_name.erase(); + m_header_name.push_back(*m_read_ptr); + m_headers_parse_state = PARSE_HEADER_NAME; + } + break; + + case PARSE_EXPECTING_CR: + // we received a newline without a CR + if (*m_read_ptr == '\r') { + m_headers_parse_state = PARSE_HEADER_START; + } else if (*m_read_ptr == '\n') { + // we received two newlines in a row + // assume newline only is (incorrectly) being used for line termination + // therefore, the message is finished + ++m_read_ptr; + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return true; + } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HEADER_WHITESPACE; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else { + // assume it is the first character for the name of a header + m_header_name.erase(); + m_header_name.push_back(*m_read_ptr); + m_headers_parse_state = PARSE_HEADER_NAME; + } + break; + + case PARSE_HEADER_WHITESPACE: + // parsing whitespace before a header name + if (*m_read_ptr == '\r') { + m_headers_parse_state = PARSE_EXPECTING_NEWLINE; + } else if (*m_read_ptr == '\n') { + m_headers_parse_state = PARSE_EXPECTING_CR; + } else if (*m_read_ptr != '\t' && *m_read_ptr != ' ') { + if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) + return false; + // assume it is the first character for the name of a header + m_header_name.erase(); + m_header_name.push_back(*m_read_ptr); + m_headers_parse_state = PARSE_HEADER_NAME; + } + break; + + case PARSE_HEADER_START: + // parsing the start of a new header + if (*m_read_ptr == '\r') { + m_headers_parse_state = PARSE_EXPECTING_FINAL_NEWLINE; + } else if (*m_read_ptr == '\n') { + m_headers_parse_state = PARSE_EXPECTING_FINAL_CR; + } else if (*m_read_ptr == '\t' || *m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HEADER_WHITESPACE; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else { + // first character for the name of a header + m_header_name.erase(); + m_header_name.push_back(*m_read_ptr); + m_headers_parse_state = PARSE_HEADER_NAME; + } + break; + + case PARSE_HEADER_NAME: + // parsing the name of a header + if (*m_read_ptr == ':') { + m_header_value.erase(); + m_headers_parse_state = PARSE_SPACE_BEFORE_HEADER_VALUE; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else if (m_header_name.size() >= ParserTraits::HEADER_NAME_MAX) { + return false; + } else { + // character (not first) for the name of a header + m_header_name.push_back(*m_read_ptr); + } + break; + + case PARSE_SPACE_BEFORE_HEADER_VALUE: + // parsing space character before a header's value + if (*m_read_ptr == ' ') { + m_headers_parse_state = PARSE_HEADER_VALUE; + } else if (*m_read_ptr == '\r') { + http_msg.addHeader(m_header_name, m_header_value); + m_headers_parse_state = PARSE_EXPECTING_NEWLINE; + } else if (*m_read_ptr == '\n') { + http_msg.addHeader(m_header_name, m_header_value); + m_headers_parse_state = PARSE_EXPECTING_CR; + } else if (!is_char(*m_read_ptr) || is_control(*m_read_ptr) || is_special(*m_read_ptr)) { + return false; + } else { + // assume it is the first character for the value of a header + m_header_value.push_back(*m_read_ptr); + m_headers_parse_state = PARSE_HEADER_VALUE; + } + break; + + case PARSE_HEADER_VALUE: + // parsing the value of a header + if (*m_read_ptr == '\r') { + http_msg.addHeader(m_header_name, m_header_value); + m_headers_parse_state = PARSE_EXPECTING_NEWLINE; + } else if (*m_read_ptr == '\n') { + http_msg.addHeader(m_header_name, m_header_value); + m_headers_parse_state = PARSE_EXPECTING_CR; + } else if (is_control(*m_read_ptr)) { + return false; + } else if (m_header_value.size() >= ParserTraits::HEADER_VALUE_MAX) { + return false; + } else { + // character (not first) for the value of a header + m_header_value.push_back(*m_read_ptr); + } + break; + + case PARSE_EXPECTING_FINAL_NEWLINE: + if (*m_read_ptr == '\n') ++m_read_ptr; + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return true; + + case PARSE_EXPECTING_FINAL_CR: + if (*m_read_ptr == '\r') ++m_read_ptr; + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return true; + } + + ++m_read_ptr; + } + + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return boost::indeterminate; +} + +template +boost::tribool basic_parser::parse_chunks(types::chunk_cache_t& chunk_buffers) +{ + // + // note that boost::tribool may have one of THREE states: + // + // false: encountered an error while parsing message + // true: finished successfully parsing the message + // indeterminate: parsed bytes, but the message is not yet finished + // + const char *read_start_ptr = m_read_ptr; + m_bytes_last_read = 0; + while (m_read_ptr < m_read_end_ptr) { + + switch (m_chunked_content_parse_state) { + case PARSE_CHUNK_SIZE_START: + // we have not yet started parsing the next chunk size + if (is_hex_digit(*m_read_ptr)) { + m_chunk_size_str.erase(); + m_chunk_size_str.push_back(*m_read_ptr); + m_chunked_content_parse_state = PARSE_CHUNK_SIZE; + } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09' || *m_read_ptr == '\x0D' || *m_read_ptr == '\x0A') { + // Ignore leading whitespace. Technically, the standard probably doesn't allow white space here, + // but we'll be flexible, since there's no ambiguity. + break; + } else { + return false; + } + break; + + case PARSE_CHUNK_SIZE: + if (is_hex_digit(*m_read_ptr)) { + m_chunk_size_str.push_back(*m_read_ptr); + } else if (*m_read_ptr == '\x0D') { + m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; + } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { + // Ignore trailing tabs or spaces. Technically, the standard probably doesn't allow this, + // but we'll be flexible, since there's no ambiguity. + m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE; + } else { + return false; + } + break; + + case PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE: + if (*m_read_ptr == '\x0D') { + m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE; + } else if (*m_read_ptr == ' ' || *m_read_ptr == '\x09') { + // Ignore trailing tabs or spaces. Technically, the standard probably doesn't allow this, + // but we'll be flexible, since there's no ambiguity. + break; + } else { + return false; + } + break; + + case PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE: + // We received a CR; expecting LF to follow. We can't be flexible here because + // if we see anything other than LF, we can't be certain where the chunk starts. + if (*m_read_ptr == '\x0A') { + m_bytes_read_in_current_chunk = 0; + m_size_of_current_chunk = strtol(m_chunk_size_str.c_str(), 0, 16); + if (m_size_of_current_chunk == 0) { + m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK; + } else { + m_current_chunk.clear(); + m_chunked_content_parse_state = PARSE_CHUNK; + } + } else { + return false; + } + break; + + case PARSE_CHUNK: + if (m_bytes_read_in_current_chunk < m_size_of_current_chunk) { + m_current_chunk.push_back(*m_read_ptr); + m_bytes_read_in_current_chunk++; + } + if (m_bytes_read_in_current_chunk == m_size_of_current_chunk) { + chunk_buffers.push_back(m_current_chunk); + m_current_chunk.clear(); + m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK; + } + break; + + case PARSE_EXPECTING_CR_AFTER_CHUNK: + // we've read exactly m_size_of_current_chunk bytes since starting the current chunk + if (*m_read_ptr == '\x0D') { + m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK; + } else { + return false; + } + break; + + case PARSE_EXPECTING_LF_AFTER_CHUNK: + // we received a CR; expecting LF to follow + if (*m_read_ptr == '\x0A') { + m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; + } else { + return false; + } + break; + + case PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK: + // we've read the final chunk; expecting final CRLF + if (*m_read_ptr == '\x0D') { + m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK; + } else { + return false; + } + break; + + case PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK: + // we received the final CR; expecting LF to follow + if (*m_read_ptr == '\x0A') { + ++m_read_ptr; + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return true; + } else { + return false; + } + } + + ++m_read_ptr; + } + + m_bytes_last_read = (m_read_ptr - read_start_ptr); + m_bytes_total_read += m_bytes_last_read; + return boost::indeterminate; +} + +template +std::size_t basic_parser::consume_content(basic_message& http_msg) +{ + // get the payload content length from the HTTP headers + http_msg.updateContentLengthUsingHeader(); + + // read the post content + std::size_t content_bytes_to_read = http_msg.getContentLength(); + char *post_buffer = http_msg.createContentBuffer(); + + if (m_read_ptr < m_read_end_ptr) { + // there are extra bytes left from the last read operation + // copy them into the beginning of the content buffer + const std::size_t bytes_left_in_read_buffer = bytes_available(); + + if (bytes_left_in_read_buffer >= http_msg.getContentLength()) { + // the last read operation included all of the payload content + memcpy(post_buffer, m_read_ptr, http_msg.getContentLength()); + content_bytes_to_read = 0; + m_read_ptr += http_msg.getContentLength(); + } else { + // only some of the post content has been read so far + memcpy(post_buffer, m_read_ptr, bytes_left_in_read_buffer); + content_bytes_to_read -= bytes_left_in_read_buffer; + m_read_ptr = m_read_end_ptr; + } + } + + m_bytes_last_read = (http_msg.getContentLength() - content_bytes_to_read); + m_bytes_total_read += m_bytes_last_read; + return m_bytes_last_read; +} + +template +std::size_t basic_parser::consume_content_as_next_chunk(types::chunk_cache_t& chunk_buffers) +{ + if (bytes_available() == 0) { + m_bytes_last_read = 0; + } else { + std::vector next_chunk; + while (m_read_ptr < m_read_end_ptr) { + next_chunk.push_back(*m_read_ptr); + ++m_read_ptr; + } + chunk_buffers.push_back(next_chunk); + m_bytes_last_read = next_chunk.size(); + m_bytes_total_read += m_bytes_last_read; + } + return m_bytes_last_read; +} + +template +void basic_parser::finish(basic_request& http_request) +{ + http_request.setIsValid(true); + http_request.setMethod(m_method); + http_request.setResource(m_resource); + http_request.setQueryString(m_query_string); + + // parse query pairs from the URI query string + if (! m_query_string.empty()) { + if (! parseURLEncoded(http_request.getQueryParams(), + m_query_string.c_str(), + m_query_string.size())) + } + + // parse query pairs from post content (x-www-form-urlencoded) + if (http_request.getHeader(types::HEADER_CONTENT_TYPE) == + types::CONTENT_TYPE_URLENCODED) + { + if (! parseURLEncoded(http_request.getQueryParams(), + http_request.getContent(), + http_request.getContentLength())) + } + + // parse "Cookie" headers + std::pair + cookie_pair = http_request.getHeaders().equal_range(types::HEADER_COOKIE); + for (types::headers::const_iterator cookie_iterator = cookie_pair.first; + cookie_iterator != http_request.getHeaders().end() + && cookie_iterator != cookie_pair.second; ++cookie_iterator) + { + if (! parseCookieHeader(http_request.getCookieParams(), + cookie_iterator->second) ) + } +} + +template +void basic_parser::finish(basic_response& http_response) +{ + http_response.setIsValid(true); + http_response.setStatusCode(m_status_code); + http_response.setStatusMessage(m_status_message); +} + +template +inline void basic_parser::reset(void) +{ + m_headers_parse_state = (m_is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H); + m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START; + m_status_code = 0; + m_status_message.erase(); + m_method.erase(); + m_resource.erase(); + m_query_string.erase(); + m_current_chunk.clear(); + m_bytes_last_read = m_bytes_total_read = 0; +} + + template + static bool basic_parser::parse_url_encoded(types::query_params& params, + const char *ptr, const std::size_t len) +{ + // used to track whether we are parsing the name or value + enum query_parse_state_t { + QUERY_PARSE_NAME, QUERY_PARSE_VALUE + } parse_state = QUERY_PARSE_NAME; + + // misc other variables used for parsing + const char * const end = ptr + len; + string_type query_name; + string_type query_value; + + // iterate through each encoded character + while (ptr < end) { + switch (parse_state) { + + case QUERY_PARSE_NAME: + // parsing query name + if (*ptr == '=') { + // end of name found + if (query_name.empty()) return false; + parse_state = QUERY_PARSE_VALUE; + } else if (*ptr == '&') { + // value is empty (OK) + if (query_name.empty()) return false; + params.insert( std::make_pair(query_name, query_value) ); + query_name.erase(); + } else if (is_control(*ptr) || query_name.size() >= ParserTraits::QUERY_NAME_MAX) { + // control character detected, or max sized exceeded + return false; + } else { + // character is part of the name + query_name.push_back(*ptr); + } + break; + + case QUERY_PARSE_VALUE: + // parsing query value + if (*ptr == '&') { + // end of value found (OK if empty) + params.insert( std::make_pair(query_name, query_value) ); + query_name.erase(); + query_value.erase(); + parse_state = QUERY_PARSE_NAME; + } else if (is_control(*ptr) || query_value.size() >= ParserTraits::QUERY_VALUE_MAX) { + // control character detected, or max sized exceeded + return false; + } else { + // character is part of the value + query_value.push_back(*ptr); + } + break; + } + + ++ptr; + } + + // handle last pair in string + if (! query_name.empty()) + params.insert( std::make_pair(query_name, query_value) ); + + return true; +} + +template +static bool basic_parser::parse_cookie_header(types::cookie_params& params, + const string_type& cookie_header) +{ + // BASED ON RFC 2109 + // + // The current implementation ignores cookie attributes which begin with '$' + // (i.e. $Path=/, $Domain=, etc.) + + // used to track what we are parsing + enum cookie_parse_state_t { + COOKIE_PARSE_NAME, COOKIE_PARSE_VALUE, COOKIE_PARSE_IGNORE + } parse_state = COOKIE_PARSE_NAME; + + // misc other variables used for parsing + string_type cookie_name; + string_type cookie_value; + char value_quote_character = '\0'; + + // iterate through each character + for (string_type::const_iterator string_iterator = cookie_header.begin(); + string_iterator != cookie_header.end(); ++string_iterator) + { + switch (parse_state) { + + case COOKIE_PARSE_NAME: + // parsing cookie name + if (*string_iterator == '=') { + // end of name found + if (cookie_name.empty()) return false; + value_quote_character = '\0'; + parse_state = COOKIE_PARSE_VALUE; + } else if (*string_iterator == ';' || *string_iterator == ',') { + // ignore empty cookie names since this may occur naturally + // when quoted values are encountered + if (! cookie_name.empty()) { + // value is empty (OK) + if (cookie_name[0] != '$') + params.insert( std::make_pair(cookie_name, cookie_value) ); + cookie_name.erase(); + } + } else if (*string_iterator != ' ') { // ignore whitespace + // check if control character detected, or max sized exceeded + if (is_control(*string_iterator) || cookie_name.size() >= ParserTraits::COOKIE_NAME_MAX) + return false; + // character is part of the name + // cookie names are case insensitive -> convert to lowercase + cookie_name.push_back( tolower(*string_iterator) ); + } + break; + + case COOKIE_PARSE_VALUE: + // parsing cookie value + if (value_quote_character == '\0') { + // value is not (yet) quoted + if (*string_iterator == ';' || *string_iterator == ',') { + // end of value found (OK if empty) + if (cookie_name[0] != '$') + params.insert( std::make_pair(cookie_name, cookie_value) ); + cookie_name.erase(); + cookie_value.erase(); + parse_state = COOKIE_PARSE_NAME; + } else if (*string_iterator == '\'' || *string_iterator == '"') { + if (cookie_value.empty()) { + // begin quoted value + value_quote_character = *string_iterator; + } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { + // max size exceeded + return false; + } else { + // assume character is part of the (unquoted) value + cookie_value.push_back(*string_iterator); + } + } else if (*string_iterator != ' ') { // ignore unquoted whitespace + // check if control character detected, or max sized exceeded + if (is_control(*string_iterator) || cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) + return false; + // character is part of the (unquoted) value + cookie_value.push_back(*string_iterator); + } + } else { + // value is quoted + if (*string_iterator == value_quote_character) { + // end of value found (OK if empty) + if (cookie_name[0] != '$') + params.insert( std::make_pair(cookie_name, cookie_value) ); + cookie_name.erase(); + cookie_value.erase(); + parse_state = COOKIE_PARSE_IGNORE; + } else if (cookie_value.size() >= ParserTraits::COOKIE_VALUE_MAX) { + // max size exceeded + return false; + } else { + // character is part of the (quoted) value + cookie_value.push_back(*string_iterator); + } + } + break; + + case COOKIE_PARSE_IGNORE: + // ignore everything until we reach a comma "," or semicolon ";" + if (*string_iterator == ';' || *string_iterator == ',') + parse_state = COOKIE_PARSE_NAME; + break; + } + } + + // handle last cookie in string + if (! cookie_name.empty() && cookie_name[0] != '$') + params.insert( std::make_pair(cookie_name, cookie_value) ); + + return true; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_PARSER_IPP diff --git a/http/src/network/protocol/http/impl/request.hpp b/http/src/network/protocol/http/impl/request.hpp new file mode 100644 index 000000000..0859a602c --- /dev/null +++ b/http/src/network/protocol/http/impl/request.hpp @@ -0,0 +1,255 @@ +// Copyright Dean Michael Berris 2007,2009,2010. +// Copyright Michael Dickey 2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP +#define NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace network { + +/** Specialize the traits for the http_server tag. */ +template <> +struct headers_container : + vector::apply::type> +{}; + +template <> +struct headers_container : + vector::apply::type> +{}; + +namespace http { + +/** request.hpp + * + * This file implements the basic request object required + * by the HTTP client implementation. The basic_request + * object encapsulates a URI which is parsed at runtime. + */ + +template +struct basic_request : public basic_message +{ + + mutable network::uri uri_; + typedef basic_message base_type; + +public: + typedef typename sync_only::type tag; + typedef typename string::type string_type; + typedef boost::uint16_t port_type; + + explicit basic_request(string_type const & uri_) + : uri_(uri_) + { } + + explicit basic_request(network::uri const & uri_) + : uri_(uri_) + { } + + void uri(string_type const & new_uri) { + uri_ = new_uri; + } + + void uri(network::uri const & new_uri) { + uri_ = new_uri; + } + + basic_request() + : base_type() + { } + + basic_request(basic_request const & other) + : base_type(other), uri_(other.uri_) + { } + + basic_request & operator=(basic_request rhs) { + rhs.swap(*this); + return *this; + } + + void swap(basic_request & other) { + base_type & base_ref(other); + basic_request & this_ref(*this); + base_ref.swap(this_ref); + boost::swap(other.uri_, this->uri_); + } + + string_type const host() const { + return uri_.host(); + } + + port_type port() const { + boost::optional port = uri::port_us(uri_); + if (!port) + { + typedef constants consts; + return boost::iequals(uri_.scheme(), + string_type(consts::https()))? 443 : 80; + } + return *port; + } + + string_type const path() const { + return uri_.path(); + } + + string_type const query() const { + return uri_.query(); + } + + string_type const anchor() const { + return uri_.fragment(); + } + + string_type const protocol() const { + return uri_.scheme(); + } + + void uri(string_type const & new_uri) const { + uri_ = new_uri; + } + + network::uri const & uri() const { + return uri_; + } + +}; + +/** This is the implementation of a POD request type + * that is specificially used by the HTTP server + * implementation. This fully specializes the + * basic_request template above to be + * primarily and be solely a POD for performance + * reasons. + * + * Reality check: This is not a POD because it contains a non-POD + * member, the headers vector. :( + */ +template +struct not_quite_pod_request_base { + typedef Tag tag; + typedef typename string::type string_type; + typedef typename request_header::type header_type; + typedef typename vector:: + template apply::type + vector_type; + typedef vector_type headers_container_type; + typedef boost::uint16_t port_type; + mutable string_type source; + mutable string_type method; + mutable string_type destination; + mutable boost::uint8_t http_version_major; + mutable boost::uint8_t http_version_minor; + mutable vector_type headers; + mutable string_type body; + + void swap(not_quite_pod_request_base & r) const { + using std::swap; + swap(method, r.method); + swap(source, r.source); + swap(destination, r.destination); + swap(http_version_major, r.http_version_major); + swap(http_version_minor, r.http_version_minor); + swap(headers, r.headers); + swap(body, r.body); + } +}; + +template <> +struct basic_request +: not_quite_pod_request_base +{}; + +template <> +struct basic_request +: not_quite_pod_request_base +{}; + +template +struct ServerRequest; + +BOOST_CONCEPT_ASSERT((ServerRequest >)); +BOOST_CONCEPT_ASSERT((ServerRequest >)); + +template +inline void swap(basic_request & lhs, basic_request & rhs) { + lhs.swap(rhs); +} + +} // namespace http + +namespace http { namespace impl { + + template <> + struct request_headers_wrapper { + basic_request const & request_; + request_headers_wrapper(basic_request const & request_) + : request_(request_) {} + typedef headers_container::type headers_container_type; + operator headers_container_type () { + return request_.headers; + } + }; + + template <> + struct body_wrapper > { + typedef string::type string_type; + basic_request const & request_; + body_wrapper(basic_request const & request_) + : request_(request_) {} + operator string_type () { + return request_.body; + } + }; + + template <> + struct request_headers_wrapper { + basic_request const & request_; + request_headers_wrapper(basic_request const & request_) + : request_(request_) {} + typedef headers_container::type headers_container_type; + operator headers_container_type () { + return request_.headers; + } + }; + + template <> + struct body_wrapper > { + typedef string::type string_type; + basic_request const & request_; + body_wrapper(basic_request const & request_) + : request_(request_) {} + operator string_type () { + return request_.body; + } + }; + +} // namespace impl + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP + diff --git a/boost/network/protocol/http/impl/request_parser.ipp b/http/src/network/protocol/http/impl/request_parser.ipp similarity index 94% rename from boost/network/protocol/http/impl/request_parser.ipp rename to http/src/network/protocol/http/impl/request_parser.ipp index 071e64f20..be3f123bd 100644 --- a/boost/network/protocol/http/impl/request_parser.ipp +++ b/http/src/network/protocol/http/impl/request_parser.ipp @@ -5,19 +5,20 @@ // Implementation file for the header-only version of the request_parser. // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) +// Copyright (c) 2009 Dean Michael Berris (dberris@google.com) // Copyright (c) 2009 Tarroo, Inc. // +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP -#define BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP +#ifndef NETWORK_HTTP_REQUEST_PARSER_IPP +#define NETWORK_HTTP_REQUEST_PARSER_IPP -#include +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template boost::tribool basic_request_parser::consume(basic_request & req, char input) @@ -322,11 +323,8 @@ bool basic_request_parser::is_digit(int c) return c >= '0' && c <= '9'; } -} // namespace http +} // namespace http +} // namespace network -} // namespace network - -} // namespace boost - -#endif //BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP +#endif //NETWORK_HTTP_REQUEST_PARSER_IPP diff --git a/http/src/network/protocol/http/impl/response.ipp b/http/src/network/protocol/http/impl/response.ipp new file mode 100644 index 000000000..194640689 --- /dev/null +++ b/http/src/network/protocol/http/impl/response.ipp @@ -0,0 +1,320 @@ +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2009 Dean Michael Berris (dberris@google.com) +// Copyright (c) 2009 Tarroo, Inc. +// +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Note: This implementation has significantly changed from the original example +// from a plain header file into a header-only implementation using C++ templates +// to reduce the dependence on building an external library. +// + +#ifndef NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP +#define NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP + +#include +#include +#include + +namespace network { namespace http { + +/// A reply to be sent to a client. +template class Vector = std::vector> +struct basic_response : response_base { + + /// The status of the reply. + enum status_type { + ok = 200, + created = 201, + accepted = 202, + no_content = 204, + multiple_choices = 300, + moved_permanently = 301, + moved_temporarily = 302, + not_modified = 304, + bad_request = 400, + unauthorized = 401, + forbidden = 403, + not_found = 404, + not_supported = 405, + not_acceptable = 406, + internal_server_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503 + } status; + + /// The headers to be included in the reply. + typedef Vector > headers_vector; + headers_vector headers; + + /// Convert the reply into a vector of buffers. The buffers do not own the + /// underlying memory blocks, therefore the reply object must remain valid and + /// not be changed until the write operation has completed. + std::vector to_buffers() { + // FIXME: Rethink this and do this asynchronously. + using asio::const_buffer; + using asio::buffer; + static const char name_value_separator[] = { ':', ' ' }; + static const char crlf[] = { '\r', '\n' }; + std::vector buffers; + buffers.push_back(to_buffer(status)); + for (std::size_t i = 0; i < headers.size(); ++i) { + response_header & h = headers[i]; + buffers.push_back(buffer(h.name)); + buffers.push_back(buffer(name_value_separator)); + buffers.push_back(buffer(h.value)); + buffers.push_back(buffer(crlf)); + } + buffers.push_back(buffer(crlf)); + return buffers; + } + + /// Get a stock reply. + static basic_response stock_reply(status_type status) { + return stock_reply(status, to_string(status)); + } + + /// Get a stock reply with custom plain text data. + static basic_response stock_reply(status_type status, String const & content) { + using boost::lexical_cast; + basic_response rep; + rep.status = status; + rep.content = content; + rep.headers.resize(2); + rep.headers[0].name = "Content-Length"; + rep.headers[0].value = lexical_cast(rep.content.size()); + rep.headers[1].name = "Content-Type"; + rep.headers[1].value = "text/html"; + return rep; + } + + /// Swap response objects + void swap(basic_response &r) { + using std::swap; + swap(headers, r.headers); + // swap(content, r.content); + } + + private: + + static String to_string(status_type status) { + static const char ok[] = ""; + static const char created[] = + "" + "Created" + "

201 Created

" + ""; + static const char accepted[] = + "" + "Accepted" + "

202 Accepted

" + ""; + static const char no_content[] = + "" + "No Content" + "

204 Content

" + ""; + static const char multiple_choices[] = + "" + "Multiple Choices" + "

300 Multiple Choices

" + ""; + static const char moved_permanently[] = + "" + "Moved Permanently" + "

301 Moved Permanently

" + ""; + static const char moved_temporarily[] = + "" + "Moved Temporarily" + "

302 Moved Temporarily

" + ""; + static const char not_modified[] = + "" + "Not Modified" + "

304 Not Modified

" + ""; + static const char bad_request[] = + "" + "Bad Request" + "

400 Bad Request

" + ""; + static const char unauthorized[] = + "" + "Unauthorized" + "

401 Unauthorized

" + ""; + static const char forbidden[] = + "" + "Forbidden" + "

403 Forbidden

" + ""; + static const char not_found[] = + "" + "Not Found" + "

404 Not Found

" + ""; + static const char not_supported[] = + "" + "Method Not Supported" + "

Method Not Supported

" + ""; + static const char not_acceptable[] = + "" + "Request Not Acceptable" + "

Request Not Acceptable

" + ""; + static const char internal_server_error[] = + "" + "Internal Server Error" + "

500 Internal Server Error

" + ""; + static const char not_implemented[] = + "" + "Not Implemented" + "

501 Not Implemented

" + ""; + static const char bad_gateway[] = + "" + "Bad Gateway" + "

502 Bad Gateway

" + ""; + static const char service_unavailable[] = + "" + "Service Unavailable" + "

503 Service Unavailable

" + ""; + + switch (status) + { + case basic_response::ok: + return ok; + case basic_response::created: + return created; + case basic_response::accepted: + return accepted; + case basic_response::no_content: + return no_content; + case basic_response::multiple_choices: + return multiple_choices; + case basic_response::moved_permanently: + return moved_permanently; + case basic_response::moved_temporarily: + return moved_temporarily; + case basic_response::not_modified: + return not_modified; + case basic_response::bad_request: + return bad_request; + case basic_response::unauthorized: + return unauthorized; + case basic_response::forbidden: + return forbidden; + case basic_response::not_found: + return not_found; + case basic_response::not_supported: + return not_supported; + case basic_response::not_acceptable: + return not_acceptable; + case basic_response::internal_server_error: + return internal_server_error; + case basic_response::not_implemented: + return not_implemented; + case basic_response::bad_gateway: + return bad_gateway; + case basic_response::service_unavailable: + return service_unavailable; + default: + return internal_server_error; + } + } + + asio::const_buffer to_buffer(status_type status) { + using asio::buffer; + static const String ok = + "HTTP/1.0 200 OK\r\n"; + static const String created = + "HTTP/1.0 201 Created\r\n"; + static const String accepted = + "HTTP/1.0 202 Accepted\r\n"; + static const String no_content = + "HTTP/1.0 204 No Content\r\n"; + static const String multiple_choices = + "HTTP/1.0 300 Multiple Choices\r\n"; + static const String moved_permanently = + "HTTP/1.0 301 Moved Permanently\r\n"; + static const String moved_temporarily = + "HTTP/1.0 302 Moved Temporarily\r\n"; + static const String not_modified = + "HTTP/1.0 304 Not Modified\r\n"; + static const String bad_request = + "HTTP/1.0 400 Bad Request\r\n"; + static const String unauthorized = + "HTTP/1.0 401 Unauthorized\r\n"; + static const String forbidden = + "HTTP/1.0 403 Forbidden\r\n"; + static const String not_found = + "HTTP/1.0 404 Not Found\r\n"; + static const String not_supported = + "HTTP/1.0 405 Method Not Supported\r\n"; + static const String not_acceptable = + "HTTP/1.0 406 Method Not Acceptable\r\n"; + static const String internal_server_error = + "HTTP/1.0 500 Internal Server Error\r\n"; + static const String not_implemented = + "HTTP/1.0 501 Not Implemented\r\n"; + static const String bad_gateway = + "HTTP/1.0 502 Bad Gateway\r\n"; + static const String service_unavailable = + "HTTP/1.0 503 Service Unavailable\r\n"; + + switch (status) { + case basic_response::ok: + return buffer(ok); + case basic_response::created: + return buffer(created); + case basic_response::accepted: + return buffer(accepted); + case basic_response::no_content: + return buffer(no_content); + case basic_response::multiple_choices: + return buffer(multiple_choices); + case basic_response::moved_permanently: + return buffer(moved_permanently); + case basic_response::moved_temporarily: + return buffer(moved_temporarily); + case basic_response::not_modified: + return buffer(not_modified); + case basic_response::bad_request: + return buffer(bad_request); + case basic_response::unauthorized: + return buffer(unauthorized); + case basic_response::forbidden: + return buffer(forbidden); + case basic_response::not_found: + return buffer(not_found); + case basic_response::not_supported: + return buffer(not_supported); + case basic_response::not_acceptable: + return buffer(not_acceptable); + case basic_response::internal_server_error: + return buffer(internal_server_error); + case basic_response::not_implemented: + return buffer(not_implemented); + case basic_response::bad_gateway: + return buffer(bad_gateway); + case basic_response::service_unavailable: + return buffer(service_unavailable); + default: + return buffer(internal_server_error); + } + } +}; + + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP diff --git a/http/src/network/protocol/http/message/async_message.hpp b/http/src/network/protocol/http/message/async_message.hpp new file mode 100644 index 000000000..bd7d81ed7 --- /dev/null +++ b/http/src/network/protocol/http/message/async_message.hpp @@ -0,0 +1,163 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 + +#include +#include +#include + +//FIXME move this out to a trait +#include +#include +#include + +namespace network { +namespace http { +namespace impl { +template +struct ready_wrapper; +} // namespace impl + +template +struct async_message { + + typedef typename string::type string_type; + typedef typename headers_container::type headers_container_type; + typedef typename headers_container_type::value_type header_type; + + async_message() + : status_message_(), + version_(), + source_(), + destination_(), + status_(), + headers_(), + body_() + {} + + async_message(async_message const & other) + : status_message_(other.status_message_), + version_(other.version_), + source_(other.source_), + destination_(other.destination_), + status_(other.status_), + headers_(other.headers_), + body_(other.body_) + {} + + string_type const status_message() const { + return status_message_.get(); + } + + void status_message(boost::shared_future const & future) const { + status_message_ = future; + } + + string_type const version() const { + return version_.get(); + } + + void version(boost::shared_future const & future) const { + version_ = future; + } + + boost::uint16_t status() const { + return status_.get(); + } + + void status(boost::shared_future const & future) const { + status_ = future; + } + + string_type const source() const { + return source_.get(); + } + + void source(boost::shared_future const & future) const { + source_ = future; + } + + string_type const destination() const { + return destination_.get(); + } + + void destination(boost::shared_future const & future) const { + destination_ = future; + } + + headers_container_type const & headers() const { + if (retrieved_headers_) return *retrieved_headers_; + headers_container_type raw_headers = headers_.get(); + raw_headers.insert(added_headers.begin(), added_headers.end()); + FOREACH(string_type const & key, removed_headers) { + raw_headers.erase(key); + } + retrieved_headers_ = raw_headers; + return *retrieved_headers_; + } + + void headers(boost::shared_future const & future) const { + headers_ = future; + } + + void add_header(typename headers_container_type::value_type const & pair_) const { + added_headers.insert(added_headers.end(), pair_); + } + + void remove_header(typename headers_container_type::key_type const & key_) const { + removed_headers.insert(key_); + } + + string_type const body() const { + return body_.get(); + } + + void body(boost::shared_future const & future) const { + body_ = future; + } + + void swap(async_message & other) { + std::swap(status_message_, other.status_message_); + std::swap(status_, other.status_); + std::swap(version_, other.version_); + std::swap(source_, other.source_); + std::swap(destination_, other.destination_); + std::swap(headers_, other.headers_); + std::swap(body_, other.body_); + } + + async_message & operator=(async_message other) { + other.swap(*this); + return *this; + } + +private: + + mutable boost::shared_future status_message_, + version_, source_, destination_; + mutable boost::shared_future status_; + mutable boost::shared_future headers_; + mutable headers_container_type added_headers; + mutable std::set removed_headers; + mutable boost::shared_future body_; + mutable boost::optional retrieved_headers_; + + friend struct boost::network::http::impl::ready_wrapper; +}; + +template +inline void swap(async_message & lhs, async_message & rhs) { + lhs.swap(rhs); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622 diff --git a/http/src/network/protocol/http/message/directives.hpp b/http/src/network/protocol/http/message/directives.hpp new file mode 100644 index 000000000..dbdc49413 --- /dev/null +++ b/http/src/network/protocol/http/message/directives.hpp @@ -0,0 +1,16 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_HPP_20111201 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_HPP_20111201 + +#include +#include +#include +#include +#include + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_HPP_20111201 diff --git a/http/src/network/protocol/http/message/directives/major_version.hpp b/http/src/network/protocol/http/message/directives/major_version.hpp new file mode 100644 index 000000000..7a158c120 --- /dev/null +++ b/http/src/network/protocol/http/message/directives/major_version.hpp @@ -0,0 +1,28 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 + +#include + +namespace network { namespace http { + +struct major_version_directive { + boost::uint8_t major_version; + explicit major_version_directive(boost::uint8_t major_version); + void operator()(request_base &request) const; +}; + +inline major_version_directive +major_version(boost::uint8_t major_version_) { + return major_version_directive(major_version_); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 */ diff --git a/http/src/network/protocol/http/message/directives/method.hpp b/http/src/network/protocol/http/message/directives/method.hpp new file mode 100644 index 000000000..6d3f914d2 --- /dev/null +++ b/http/src/network/protocol/http/message/directives/method.hpp @@ -0,0 +1,18 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 + +namespace network { +namespace http { + +NETWORK_STRING_DIRECTIVE(method); + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 */ diff --git a/http/src/network/protocol/http/message/directives/minor_version.hpp b/http/src/network/protocol/http/message/directives/minor_version.hpp new file mode 100644 index 000000000..ac872461f --- /dev/null +++ b/http/src/network/protocol/http/message/directives/minor_version.hpp @@ -0,0 +1,39 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 + +#include +#include +#include + +namespace network { +namespace http { + +template +struct basic_request; + +struct minor_version_directive { + boost::uint8_t minor_version; + explicit minor_version_directive(boost::uint8_t minor_version) + : minor_version(minor_version) {} + template + void operator()(basic_request & request) const { + request.http_version_minor = minor_version; + } +}; + +inline minor_version_directive +minor_version(boost::uint8_t minor_version_) { + return minor_version_directive(minor_version_); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 */ + diff --git a/http/src/network/protocol/http/message/directives/status.hpp b/http/src/network/protocol/http/message/directives/status.hpp new file mode 100644 index 000000000..9b163c962 --- /dev/null +++ b/http/src/network/protocol/http/message/directives/status.hpp @@ -0,0 +1,34 @@ +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 + +#include +#include +#include +#include + +namespace network { +namespace http { + +struct status_directive { + explicit status_directive(std::string const & s); + void operator()(response_base & response) const; + + protected: + std::string status_; +}; + +inline status_directive status(std::string const & response) { + return status_directive(response); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603 diff --git a/http/src/network/protocol/http/message/directives/status_message.hpp b/http/src/network/protocol/http/message/directives/status_message.hpp new file mode 100644 index 000000000..35c3c192f --- /dev/null +++ b/http/src/network/protocol/http/message/directives/status_message.hpp @@ -0,0 +1,21 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 + +#include + +namespace network { +namespace http { + +NETWORK_STRING_DIRECTIVE(status_message); + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_MESSAGE_HPP_20100603 diff --git a/http/src/network/protocol/http/message/directives/uri.hpp b/http/src/network/protocol/http/message/directives/uri.hpp new file mode 100644 index 000000000..66567673e --- /dev/null +++ b/http/src/network/protocol/http/message/directives/uri.hpp @@ -0,0 +1,21 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 + +#include + +namespace network { +namespace http { + +NETWORK_STRING_DIRECTIVE(uri); + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_URI_HPP_20100620 diff --git a/http/src/network/protocol/http/message/directives/version.hpp b/http/src/network/protocol/http/message/directives/version.hpp new file mode 100644 index 000000000..b8f9d7b60 --- /dev/null +++ b/http/src/network/protocol/http/message/directives/version.hpp @@ -0,0 +1,21 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 + +#include + +namespace network { +namespace http { + +NETWORK_STRING_DIRECTIVE(version); + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_VERSION_HPP_20100603 diff --git a/http/src/network/protocol/http/message/header.hpp b/http/src/network/protocol/http/message/header.hpp new file mode 100644 index 000000000..815a38569 --- /dev/null +++ b/http/src/network/protocol/http/message/header.hpp @@ -0,0 +1,61 @@ +// +// header.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2009,2010 Dean Michael Berris (dberris@google.com) +// Copyright (c) 2009 Tarroo, Inc. +// +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 + +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct request_header { + typedef std::string string_type; + std::string name, value; +}; + +inline void swap(request_header & l, request_header & r) { + swap(l.name, r.name); + swap(l.value, r.value); +} + +struct response_header { + typedef std::string string_type; + std::string name, value; +}; + +inline void swap(response_header & l, response_header & r) { + std::swap(l.name, r.name); + std::swap(l.value, r.value); +} + +} // namespace http +} // namespace network + +BOOST_FUSION_ADAPT_STRUCT( + network::http::request_header, + (std::string, name) + (std::string, value) + ) + +BOOST_FUSION_ADAPT_STRUCT( + network::http::response_header, + (std::string, name) + (std::string, value) + ) + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 diff --git a/http/src/network/protocol/http/message/header/name.hpp b/http/src/network/protocol/http/message/header/name.hpp new file mode 100644 index 000000000..bab4c2653 --- /dev/null +++ b/http/src/network/protocol/http/message/header/name.hpp @@ -0,0 +1,35 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 + +#include +#include + +namespace network { +namespace http { + +template +inline T1 const & +name(std::pair const & p) { + return p.first; +} + +inline std::string const & +name(request_header const & h) { + return h.name; +} + +inline std::string const & +name(response_header const & h) { + return h.name; +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 */ diff --git a/http/src/network/protocol/http/message/header/value.hpp b/http/src/network/protocol/http/message/header/value.hpp new file mode 100644 index 000000000..1112a2430 --- /dev/null +++ b/http/src/network/protocol/http/message/header/value.hpp @@ -0,0 +1,37 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 + +#include +#include + +namespace network { namespace http { + +struct request_header; +struct response_header; + +template +inline T1 const & value(std::pair const & p) { + return p.second; +} + +inline std::string const & +value(request_header const & h) { + return h.value; +} + +inline std::string const & +value(response_header const & h) { + return h.value; +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 */ + diff --git a/http/src/network/protocol/http/message/header_concept.hpp b/http/src/network/protocol/http/message/header_concept.hpp new file mode 100644 index 000000000..cca90d313 --- /dev/null +++ b/http/src/network/protocol/http/message/header_concept.hpp @@ -0,0 +1,36 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 + +namespace network { namespace http { + +template +struct Header + : boost::DefaultConstructible + , boost::Assignable + , boost::CopyConstructible +{ + + BOOST_CONCEPT_USAGE(Header) { + typedef typename H::string_type string_type; + string_type name_ = name(header); + string_type value_ = value(header); + H h1, h2; + swap(h1,h2); // ADL Swap! + (void)name_; + (void)value_; + } + +private: + H header; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 */ diff --git a/http/src/network/protocol/http/message/modifiers.hpp b/http/src/network/protocol/http/message/modifiers.hpp new file mode 100644 index 000000000..dad29a25c --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers.hpp @@ -0,0 +1,16 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_HPP_20111201 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_HPP_20111201 + +#include +#include +#include +#include +#include + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_HPP_20111201 diff --git a/http/src/network/protocol/http/message/modifiers/major_version.hpp b/http/src/network/protocol/http/message/modifiers/major_version.hpp new file mode 100644 index 000000000..cac881bae --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/major_version.hpp @@ -0,0 +1,29 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 + +#include +#include +#include + +namespace network { +namespace http { + +template +struct basic_request; + +template +inline typename enable_if, void>::type +major_version(basic_request & request, boost::uint8_t major_version_) { + request.http_version_major = major_version_; +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/http/src/network/protocol/http/message/modifiers/method.hpp b/http/src/network/protocol/http/message/modifiers/method.hpp new file mode 100644 index 000000000..a8a6d3439 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/method.hpp @@ -0,0 +1,21 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 + +#include + +namespace network { namespace http { + +inline void method(request_base & request, std::string const & method_) { + request.set_method(method_); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 */ diff --git a/http/src/network/protocol/http/message/modifiers/minor_version.hpp b/http/src/network/protocol/http/message/modifiers/minor_version.hpp new file mode 100644 index 000000000..92a1a46d5 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/minor_version.hpp @@ -0,0 +1,29 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 + +#include +#include +#include + +namespace network { namespace http { + +template +struct basic_request; + +template +inline typename enable_if, void>::type +minor_version(basic_request & request, boost::uint8_t minor_version_) { + request.http_version_minor = minor_version_; +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 */ + diff --git a/http/src/network/protocol/http/message/modifiers/status.hpp b/http/src/network/protocol/http/message/modifiers/status.hpp new file mode 100644 index 000000000..880950ec8 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/status.hpp @@ -0,0 +1,22 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 + +#include + +namespace network { namespace http { + +inline void status(response_base & response, boost::uint16_t value) { + response.set_status(value); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608 diff --git a/http/src/network/protocol/http/message/modifiers/status_message.hpp b/http/src/network/protocol/http/message/modifiers/status_message.hpp new file mode 100644 index 000000000..b591ab8f2 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/status_message.hpp @@ -0,0 +1,23 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 + +#include + +namespace network { +namespace http { + +inline void status_message(response_base & response, std::string const & value) { + response.set_status_message(value); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608 diff --git a/http/src/network/protocol/http/message/modifiers/uri.hpp b/http/src/network/protocol/http/message/modifiers/uri.hpp new file mode 100644 index 000000000..51d2952ce --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/uri.hpp @@ -0,0 +1,26 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 + +#include + +namespace network { namespace http { + +inline void uri(request_base & request, std::string const & value) { + request.set_uri(value); +} + +inline void uri(request_base & request, ::network::uri const & value) { + request.set_uri(value); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621 diff --git a/http/src/network/protocol/http/message/modifiers/version.hpp b/http/src/network/protocol/http/message/modifiers/version.hpp new file mode 100644 index 000000000..8042e2aa3 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/version.hpp @@ -0,0 +1,23 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 + +#include + +namespace network { +namespace http { + +inline void version(response_base & response, std::string const & value) { + response.set_version(value); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608 diff --git a/http/src/network/protocol/http/message/wrappers.hpp b/http/src/network/protocol/http/message/wrappers.hpp new file mode 100644 index 000000000..176224e4e --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers.hpp @@ -0,0 +1,23 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HPP_20111201 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HPP_20111201 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HPP_20111201 diff --git a/http/src/network/protocol/http/message/wrappers/anchor.hpp b/http/src/network/protocol/http/message/wrappers/anchor.hpp new file mode 100644 index 000000000..abdb479ee --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/anchor.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 + +#include + +namespace network { +namespace http { + +struct anchor_wrapper { + explicit anchor_wrapper(request_base const & request); + operator std::string () const; + private: + request_base const & request_; +}; + +inline anchor_wrapper const +anchor(request_base const & request) { + return anchor_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_HPP_20100618 diff --git a/http/src/network/protocol/http/message/wrappers/anchor.ipp b/http/src/network/protocol/http/message/wrappers/anchor.ipp new file mode 100644 index 000000000..efe8b14ef --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/anchor.ipp @@ -0,0 +1,30 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Googl,Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_IPP_20111204 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_IPP_20111204 + +#include +#include + +namespace network { +namespace http { + +anchor_wrapper::anchor_wrapper(request_base const & request) +: request_(request) {} + +anchor_wrapper::operator std::string () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto fragment = uri_.fragment(); + return fragment? std::string(*fragment) : std::string(); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_ANCHOR_IPP_20111204 diff --git a/boost/network/protocol/http/message/wrappers/helper.hpp b/http/src/network/protocol/http/message/wrappers/helper.hpp similarity index 91% rename from boost/network/protocol/http/message/wrappers/helper.hpp rename to http/src/network/protocol/http/message/wrappers/helper.hpp index e433249ee..6ba958a2e 100644 --- a/boost/network/protocol/http/message/wrappers/helper.hpp +++ b/http/src/network/protocol/http/message/wrappers/helper.hpp @@ -1,15 +1,16 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 - // Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 + #include -#ifndef BOOST_NETWORK_DEFINE_HTTP_WRAPPER -#define BOOST_NETWORK_DEFINE_HTTP_WRAPPER(name, accessor, pod_field) \ +#ifndef NETWORK_DEFINE_HTTP_WRAPPER +#define NETWORK_DEFINE_HTTP_WRAPPER(name, accessor, pod_field) \ struct name##_pod_accessor { \ protected: \ template \ @@ -66,7 +67,7 @@ return name##_wrapper >(message); \ } -#endif /* BOOST_NETWORK_DEFINE_HTTP_WRAPPER */ +#endif /* NETWORK_DEFINE_HTTP_WRAPPER */ -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 */ +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 */ diff --git a/http/src/network/protocol/http/message/wrappers/host.hpp b/http/src/network/protocol/http/message/wrappers/host.hpp new file mode 100644 index 000000000..cfd9e83fb --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/host.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 + +#include + +namespace network { +namespace http { + +struct host_wrapper { + explicit host_wrapper(request_base const & request); + operator std::string () const; + private: + request_base const & request_; +}; + +inline host_wrapper const +host(request_base const & request) { + return host_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_HOST_HPP_20100618 diff --git a/http/src/network/protocol/http/message/wrappers/host.ipp b/http/src/network/protocol/http/message/wrappers/host.ipp new file mode 100644 index 000000000..a448b9dde --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/host.ipp @@ -0,0 +1,28 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_IPP_20111204 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_IPP_20111204 + +#include +#include + +namespace network { namespace http { + +host_wrapper::host_wrapper(request_base const & request) +: request_(request) {} + +host_wrapper::operator std::string () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto host = uri_.host(); + return host? std::string(*host) : std::string(""); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_IPP_20111204 diff --git a/http/src/network/protocol/http/message/wrappers/major_version.hpp b/http/src/network/protocol/http/message/wrappers/major_version.hpp new file mode 100644 index 000000000..50205c206 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/major_version.hpp @@ -0,0 +1,39 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 + +#include +#include +#include + +namespace network { +namespace http { + +template +struct basic_request; + +template +struct major_version_wrapper { + basic_request const & request; + explicit major_version_wrapper(basic_request const & request) + : request(request) {} + operator boost::uint8_t () { + return request.http_version_major; + } +}; + +template +inline typename enable_if, major_version_wrapper >::type +major_version(basic_request const & request) { + return major_version_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/http/src/network/protocol/http/message/wrappers/method.hpp b/http/src/network/protocol/http/message/wrappers/method.hpp new file mode 100644 index 000000000..19139fbf6 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/method.hpp @@ -0,0 +1,30 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 + +#include + +namespace network { +namespace http { + +struct method_wrapper { + explicit method_wrapper(request_base & message); + operator std::string () const; + private: + request_base & message_; +}; + +inline method_wrapper const +method(request_base & message) { + return method_wrapper(message); +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 */ diff --git a/boost/network/protocol/http/message/wrappers/minor_version.hpp b/http/src/network/protocol/http/message/wrappers/minor_version.hpp similarity index 67% rename from boost/network/protocol/http/message/wrappers/minor_version.hpp rename to http/src/network/protocol/http/message/wrappers/minor_version.hpp index b105227a4..774fe4ed1 100644 --- a/boost/network/protocol/http/message/wrappers/minor_version.hpp +++ b/http/src/network/protocol/http/message/wrappers/minor_version.hpp @@ -1,16 +1,17 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 + #include -#include +#include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct basic_request; @@ -31,11 +32,8 @@ namespace boost { namespace network { namespace http { return minor_version_wrapper(request); } -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 */ +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 */ diff --git a/http/src/network/protocol/http/message/wrappers/path.hpp b/http/src/network/protocol/http/message/wrappers/path.hpp new file mode 100644 index 000000000..9ac0bc24b --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/path.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 + +#include + +namespace network { +namespace http { + +struct path_wrapper { + explicit path_wrapper(request_base const & request); + operator std::string () const; + private: + request_base const & request_; +}; + +inline path_wrapper const +path(request_base const & request) { + return path_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_PATH_HPP_20100618 diff --git a/http/src/network/protocol/http/message/wrappers/path.ipp b/http/src/network/protocol/http/message/wrappers/path.ipp new file mode 100644 index 000000000..7e9970c32 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/path.ipp @@ -0,0 +1,28 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PATH_IPP_20111204 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PATH_IPP_20111204 + +#include +#include + +namespace network { namespace http { + +path_wrapper::path_wrapper(request_base const & request) +: request_(request) {} + +path_wrapper::operator std::string () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto path = uri_.path(); + return path? std::string(*path) : std::string(""); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PATH_IPP_20111204 diff --git a/http/src/network/protocol/http/message/wrappers/port.hpp b/http/src/network/protocol/http/message/wrappers/port.hpp new file mode 100644 index 000000000..d331608bc --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/port.hpp @@ -0,0 +1,33 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 + +#include +#include +#include + +namespace network { namespace http { + +struct port_wrapper { + port_wrapper(request_base const & request); + operator boost::uint16_t () const; + operator boost::optional () const; + private: + request_base const & request_; +}; + +inline port_wrapper const +port(request_base const & request) { + return port_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_PORT_HPP_20100618 diff --git a/http/src/network/protocol/http/message/wrappers/port.ipp b/http/src/network/protocol/http/message/wrappers/port.ipp new file mode 100644 index 000000000..bcc787b52 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/port.ipp @@ -0,0 +1,48 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PORT_IPP_20111204 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PORT_IPP_20111204 + +#include +#include + +namespace network { +namespace http { + +port_wrapper::port_wrapper(request_base const & request) +: request_(request) {} + +port_wrapper::operator boost::uint16_t () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto optional_port = uri_.port(); + if (!optional_port) { + auto scheme_ = uri_.scheme(); + assert(scheme_); + if (*scheme_ == "http") { + return 80u; + } else if (*scheme_ == "https") { + return 443u; + } + } + return std::stoul(std::string(*optional_port)); +} + +port_wrapper::operator boost::optional () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto optional_port = uri_.port(); + if (!optional_port) { + return boost::optional(); + } + return std::stoul(std::string(*optional_port)); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PORT_IPP_20111204 diff --git a/http/src/network/protocol/http/message/wrappers/protocol.hpp b/http/src/network/protocol/http/message/wrappers/protocol.hpp new file mode 100644 index 000000000..c947f22a6 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/protocol.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 + +#include + +namespace network { +namespace http { + +struct protocol_wrapper { + explicit protocol_wrapper(request_base const & request); + operator std::string () const; + private: + request_base const & request_; +}; + +inline protocol_wrapper const +protocol(request_base const & request) { + return protocol_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_PROTOCOL_HPP_20100619 diff --git a/http/src/network/protocol/http/message/wrappers/query.hpp b/http/src/network/protocol/http/message/wrappers/query.hpp new file mode 100644 index 000000000..c83faba63 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/query.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 + +#include + +namespace network { +namespace http { + +struct query_wrapper { + explicit query_wrapper(request_base const & request); + operator std::string () const; + private: + request_base const & request_; +}; + +inline query_wrapper const +query(request_base const & request) { + return query_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_HPP_20100618 diff --git a/http/src/network/protocol/http/message/wrappers/query.ipp b/http/src/network/protocol/http/message/wrappers/query.ipp new file mode 100644 index 000000000..eb4bc321b --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/query.ipp @@ -0,0 +1,28 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_IPP_20111204 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_IPP_20111204 + +#include +#include + +namespace network { namespace http { + +query_wrapper::query_wrapper(request_base const & request) +: request_(request) {} + +query_wrapper::operator std::string () const { + ::network::uri uri_; + request_.get_uri(uri_); + auto query = uri_.query(); + return query? std::string(*query) : std::string(""); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_QUERY_IPP_20111204 diff --git a/boost/network/protocol/http/message/wrappers/ready.hpp b/http/src/network/protocol/http/message/wrappers/ready.hpp similarity index 64% rename from boost/network/protocol/http/message/wrappers/ready.hpp rename to http/src/network/protocol/http/message/wrappers/ready.hpp index b45ee4277..ca1a53108 100644 --- a/boost/network/protocol/http/message/wrappers/ready.hpp +++ b/http/src/network/protocol/http/message/wrappers/ready.hpp @@ -1,22 +1,23 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 + +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct async_message; namespace impl { template - struct ready_wrapper : boost::network::detail::wrapper_base_const > { - typedef boost::network::detail::wrapper_base_const > + struct ready_wrapper : network::detail::wrapper_base_const > { + typedef network::detail::wrapper_base_const > wrapper_base; explicit ready_wrapper(async_message const & message) : wrapper_base(message) {} @@ -36,10 +37,7 @@ namespace boost { namespace network { namespace http { return impl::ready_wrapper(message); } -} /* http */ - -} /* network */ - -} /* boost */ +} // namespace http +} // namespace network -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 */ +#endif /* NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 */ diff --git a/http/src/network/protocol/http/message/wrappers/status.hpp b/http/src/network/protocol/http/message/wrappers/status.hpp new file mode 100644 index 000000000..59b570fb7 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status.hpp @@ -0,0 +1,31 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 + +#include + +namespace network { namespace http { + +struct status_wrapper { + explicit status_wrapper(response_base & response); + operator uint16_t () const; + private: + response_base & response_; +}; + +inline +status_wrapper const +status(response_base & response) { + return status_wrapper(response); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_HPP_20100603 diff --git a/http/src/network/protocol/http/message/wrappers/status.ipp b/http/src/network/protocol/http/message/wrappers/status.ipp new file mode 100644 index 000000000..0064f0656 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status.ipp @@ -0,0 +1,27 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_IPP_20120311 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_IPP_20120311 + +#include + +namespace network { namespace http { + +status_wrapper::status_wrapper(response_base &response) +: response_(response) +{} + +status_wrapper::operator uint16_t () const { + uint16_t status; + response_.get_status(status); + return status; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_IPP_20120311 diff --git a/http/src/network/protocol/http/message/wrappers/status_message.hpp b/http/src/network/protocol/http/message/wrappers/status_message.hpp new file mode 100644 index 000000000..940f218db --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status_message.hpp @@ -0,0 +1,39 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_HPP_20100603 + +#include +#include +#include + +namespace network { +namespace http { + +struct status_message_wrapper { + explicit status_message_wrapper(response_base & response); + operator std::string () const; + private: + response_base & response_; + mutable boost::optional cache_; +}; + +inline std::ostream & operator<<(std::ostream & os, status_message_wrapper const & status_message) { + return os << static_cast(status_message); +} + +inline +status_message_wrapper +status_message(response_base & response) { + return status_message_wrapper(response); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_STATUS_MESSAGE_HPP_20100603 diff --git a/http/src/network/protocol/http/message/wrappers/status_message.ipp b/http/src/network/protocol/http/message/wrappers/status_message.ipp new file mode 100644 index 000000000..7f42a8204 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status_message.ipp @@ -0,0 +1,29 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_IPP_20120311 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_IPP_20120311 + +#include + +namespace network { namespace http { + +status_message_wrapper::status_message_wrapper(response_base &response) +: response_(response) +{} + +status_message_wrapper::operator std::string () const { + if (cache_) return *cache_; + std::string tmp; + response_.get_status_message(tmp); + cache_ = tmp; + return *cache_; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_STATUS_MESSAGE_IPP_20120311 diff --git a/http/src/network/protocol/http/message/wrappers/uri.hpp b/http/src/network/protocol/http/message/wrappers/uri.hpp new file mode 100644 index 000000000..78dde18be --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/uri.hpp @@ -0,0 +1,34 @@ +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 + +#include +#include + +namespace network { +namespace http { + +struct uri_wrapper { + explicit uri_wrapper(request_base const & request_); + operator std::string() const; + operator ::network::uri() const; + private: + request_base const & request_; +}; + +inline +uri_wrapper const +uri(request_base const & request) { + return uri_wrapper(request); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 diff --git a/http/src/network/protocol/http/message/wrappers/uri.ipp b/http/src/network/protocol/http/message/wrappers/uri.ipp new file mode 100644 index 000000000..20d6988bf --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/uri.ipp @@ -0,0 +1,35 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_IPP_20120315 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_IPP_20120315 + +#include + +namespace network { +namespace http { + +uri_wrapper::uri_wrapper(request_base const & request_) +: request_(request_) { + // do nothing here +} + +uri_wrapper::operator std::string() const { + std::string uri; + request_.get_uri(uri); + return uri; +} + +uri_wrapper::operator ::network::uri() const { + ::network::uri uri; + request_.get_uri(uri); + return uri; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_IPP_20120315 diff --git a/http/src/network/protocol/http/message/wrappers/version.hpp b/http/src/network/protocol/http/message/wrappers/version.hpp new file mode 100644 index 000000000..fcfdb97b2 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/version.hpp @@ -0,0 +1,38 @@ +// Copyright 2010-2012 (c) Dean Michael Berris +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 + +#include +#include +#include + +namespace network { namespace http { + +struct version_wrapper { + explicit version_wrapper(response_base & response_); + operator std::string() const; + private: + response_base & response_; + mutable boost::optional cache_; +}; + +inline std::ostream & operator<< (std::ostream & os, version_wrapper const & version) { + return os << static_cast(version); +} + +inline +version_wrapper +version(response_base & response) { + return version_wrapper(response); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_HPP_20100603 diff --git a/http/src/network/protocol/http/message/wrappers/version.ipp b/http/src/network/protocol/http/message/wrappers/version.ipp new file mode 100644 index 000000000..6387ab378 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/version.ipp @@ -0,0 +1,29 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_IPP_20120311 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_IPP_20120311 + +#include + +namespace network { namespace http { + +version_wrapper::version_wrapper(response_base & response) +: response_(response) +{} + +version_wrapper::operator std::string() const { + if (cache_) return *cache_; + std::string tmp; + response_.get_version(tmp); + cache_ = tmp; + return *cache_; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_VERSION_IPP_20120311 diff --git a/boost/network/protocol/http/parser.hpp b/http/src/network/protocol/http/parser.hpp similarity index 95% rename from boost/network/protocol/http/parser.hpp rename to http/src/network/protocol/http/parser.hpp index a7bd42ff4..5a58f694c 100644 --- a/boost/network/protocol/http/parser.hpp +++ b/http/src/network/protocol/http/parser.hpp @@ -3,22 +3,23 @@ // Copyright Atomic Labs, Inc. 2007-2008 // See http://cpp-netlib.sourceforge.net for library home page. // +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP +#ifndef NETWORK_PROTOCOL_HTTP_PARSER_HPP +#define NETWORK_PROTOCOL_HTTP_PARSER_HPP -#include -#include -#include +#include +#include +#include #include #include #include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { // forward declarations used to finish HTTP requests template @@ -302,13 +303,10 @@ namespace boost { namespace network { namespace http { /// typedef for the default HTTP protocol parser implementation typedef basic_parser parser; -}; // namespace http - -}; // namespace network - -}; // namespace boost +} // namespace http +} // namespace network // import implementation file -#include +#include -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP +#endif // NETWORK_PROTOCOL_HTTP_PARSER_HPP diff --git a/http/src/network/protocol/http/parser/incremental.hpp b/http/src/network/protocol/http/parser/incremental.hpp new file mode 100644 index 000000000..537197eab --- /dev/null +++ b/http/src/network/protocol/http/parser/incremental.hpp @@ -0,0 +1,285 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 +#define NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 + +#include +#include +#include +#include +#include + +namespace network { namespace http { + +struct response_parser { + + enum state_t { + http_response_begin, + http_version_h, + http_version_t1, + http_version_t2, + http_version_p, + http_version_slash, + http_version_major, + http_version_dot, + http_version_minor, + http_version_done, + http_status_digit, + http_status_done, + http_status_message_char, + http_status_message_cr, + http_status_message_done, + http_header_name_char, + http_header_colon, + http_header_value_char, + http_header_line_cr, + http_header_line_done, + http_headers_end_cr, + http_headers_done + }; + + explicit response_parser (state_t state=http_response_begin) + : state_(state) {} + + response_parser (response_parser const & other) + : state_(other.state_) {} + + ~response_parser () {} + + void swap(response_parser & other) { + std::swap(other.state_, this->state_); + } + + response_parser & operator=(response_parser rhs) { + rhs.swap(*this); + return *this; + } + + template + boost::fusion::tuple > parse_until(state_t stop_state, Range & range_) { + boost::logic::tribool parsed_ok(boost::logic::indeterminate); + typename Range::const_iterator start = boost::begin(range_), + current = start, + end = boost::end(range_); + boost::iterator_range + local_range = boost::make_iterator_range(start, end); + if (boost::empty(local_range)) parsed_ok = false; + while (!boost::empty(local_range) && indeterminate(parsed_ok)) { + current = boost::begin(local_range); + if (state_ == stop_state) { + parsed_ok = true; + } else { + switch(state_) { + case http_response_begin: + if (*current == ' ' || *current == '\r' || *current == '\n') { + // skip valid leading whitespace + ++start; + ++current; + } else if (*current == 'H') { + state_ = http_version_h; + start = current; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_h: + if (*current == 'T') { + state_ = http_version_t1; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_t1: + if (*current == 'T') { + state_ = http_version_t2; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_t2: + if (*current == 'P') { + state_ = http_version_p; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_p: + if (*current == '/') { + state_ = http_version_slash; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_slash: + if (boost::algorithm::is_digit()(*current)) { + state_ = http_version_major; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_major: + if (*current == '.') { + state_ = http_version_dot; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_dot: + if (boost::algorithm::is_digit()(*current)) { + state_ = http_version_minor; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_minor: + if (*current == ' ') { + state_ = http_version_done; + ++current; + } else { + parsed_ok = false; + } + break; + case http_version_done: + if (boost::algorithm::is_digit()(*current)) { + state_ = http_status_digit; + ++current; + } else { + parsed_ok = false; + } + break; + case http_status_digit: + if (boost::algorithm::is_digit()(*current)) { + ++current; + } else if (*current == ' ') { + state_ = http_status_done; + ++current; + } else { + parsed_ok = false; + } + break; + case http_status_done: + if (boost::algorithm::is_alnum()(*current)) { + state_ = http_status_message_char; + ++current; + } else { + parsed_ok = false; + } + break; + case http_status_message_char: + if (boost::algorithm::is_alnum()(*current) || boost::algorithm::is_punct()(*current) || (*current == ' ')) { + ++current; + } else if (*current == '\r') { + state_ = http_status_message_cr; + ++current; + } else { + parsed_ok = false; + } + break; + case http_status_message_cr: + if (*current == '\n') { + state_ = http_status_message_done; + ++current; + } else { + parsed_ok = false; + } + break; + case http_status_message_done: + case http_header_line_done: + if (boost::algorithm::is_alnum()(*current)) { + state_ = http_header_name_char; + ++current; + } else if (*current == '\r') { + state_ = http_headers_end_cr; + ++current; + } else { + parsed_ok = false; + } + break; + case http_header_name_char: + if (*current == ':') { + state_ = http_header_colon; + ++current; + } else if (boost::algorithm::is_alnum()(*current) || boost::algorithm::is_space()(*current) || boost::algorithm::is_punct()(*current)) { + ++current; + } else { + parsed_ok = false; + } + break; + case http_header_colon: + if (boost::algorithm::is_space()(*current)) { + ++current; + } else if (boost::algorithm::is_alnum()(*current) || boost::algorithm::is_punct()(*current)) { + state_ = http_header_value_char; + ++current; + } else { + parsed_ok = false; + } + break; + case http_header_value_char: + if (*current == '\r') { + state_ = http_header_line_cr; + ++current; + } else if (boost::algorithm::is_cntrl()(*current)) { + parsed_ok = false; + } else { + ++current; + } + break; + case http_header_line_cr: + if (*current == '\n') { + state_ = http_header_line_done; + ++current; + } else { + parsed_ok = false; + } + break; + case http_headers_end_cr: + if (*current == '\n') { + state_ = http_headers_done; + ++current; + } else { + parsed_ok = false; + } + break; + default: + parsed_ok = false; + } + } + + local_range = boost::make_iterator_range(current, end); + } + if (state_ == stop_state) parsed_ok = true; + return boost::fusion::make_tuple(parsed_ok,boost::make_iterator_range(start, current)); + } + + state_t state() { + return state_; + } + + void reset(state_t new_state = http_response_begin) { + state_ = new_state; + } + + private: + state_t state_; + +}; + + +} // namespace http +} // namespace network + +#endif diff --git a/http/src/network/protocol/http/policies/async_connection.hpp b/http/src/network/protocol/http/policies/async_connection.hpp new file mode 100644 index 000000000..4df97bfe0 --- /dev/null +++ b/http/src/network/protocol/http/policies/async_connection.hpp @@ -0,0 +1,76 @@ +// Copyright 2010 (C) Dean Michael Berris +// Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 +#define NETWORK_POLICY_ASYNC_CONNECTION_HPP_20100529 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + +struct simple_async_connection_manager : connection_manager { + simple_async_connection_manager(bool cache_resolved, + bool follow_redirects, + optional openssl_certificate, + optional openssl_verify_path); + simple_async_connection_manager(bool cache_resolved, + bool follow_redirects, + std::string const & openssl_certificate, + std::string const & openssl_verify_path); + virtual shared_ptr get_connection( + asio::io_service & service, + request_base const & request); // override + virtual void reset(); // override + virtual ~simple_async_connection_manager(); // override + protected: + bool cache_resolved_, follow_redirects_; + mutex shared_resolver_mutex; + shared_ptr shared_resolver_delegate; +}; + +struct http_1_1_async_connection; + +struct http_1_1_async_connection_manager : connection_manager, enable_shared_from_this { + http_1_1_async_connection_manager(bool cache_resolved, + bool follow_redirects, + optional openssl_certificate, + optional openssl_verify_path); + http_1_1_async_connection_manager(bool cache_resolved, + bool follow_redirects, + std::string const & openssl_certificate, + std::string const & openssl_verify_path); + virtual shared_ptr get_connection( + asio::io_service & service, + request_base const & request); // override + virtual void reset(); // override + virtual ~http_1_1_async_connection_manager(); // override + + protected: + friend struct http_1_1_async_connection; + void add_ready_connection(shared_ptr connection_ptr); + shared_ptr get_ready_connection(std::string const & host); + bool cache_resolved, follow_redirects_; + mutex shared_resolver_mutex; + shared_ptr shared_resolver_delegate; + boost::unordered_map > ready_connections; +}; + +} // namespace http +} // namespace network + +#endif // NETWORK_POLICY_ASYNC_CONNECTION_HPP_ diff --git a/http/src/network/protocol/http/policies/async_connection.ipp b/http/src/network/protocol/http/policies/async_connection.ipp new file mode 100644 index 000000000..973648f4d --- /dev/null +++ b/http/src/network/protocol/http/policies/async_connection.ipp @@ -0,0 +1,170 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_CONNECTION_IPP_20110930 +#define NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_CONNECTION_IPP_20110930 + +namespace network { namespace http { + +struct simple_async_client_connection : client_connection { + simple_async_client_connection(bool follow_redirects, + shared_ptr resolver_delegate, + shared_ptr connection_delegate); + virtual shared_ptr send_request(std::string const & method, + request_base const & request, + bool get_body, + callback_type callback); // override + virtual void reset(); // override + virtual ~simple_async_client_connection(); // override + protected: + bool follow_redirects_; + shared_ptr resolver_delegate_; + shared_ptr connection_delegate_; +}; + +simple_async_client_connection::simple_async_client_connection( + bool follow_redirects, + shared_ptr resolver_delegate, + shared_ptr connection_delegate) +: follow_redirects_(follow_redirects), + resolver_delegate_(resolver_delegate), + connection_delegate_(connection_delegate), +{} + +shared_ptr simple_async_client_connection::send_request( + std::string const & method, + request_base const & request, + bool get_body, + callback_type callback) { + shared_ptr response; + shared_ptr connection_; + connection_.reset(new(std::nothrow) impl::async_connection( + resolver_delegate_, + follow_redirects_, + connection_delegate_)) + if (!connection_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Insufficient memory.")); + response = connection_->start(request, method, get_body, callback); + return response +} + +void simple_async_client_connection::reset() { + // Do nothing here +} + +simple_async_client_connection::~simple_async_client_connection() {} + +} // namespace http +} // namespace network + +network::http::simple_async_connection_manager(bool cache_resolved, + bool follow_redirects, + boost::optional openssl_certificate, + boost::optional openssl_verify_path) +: cache_resolved_(cache_resolved), + follow_redirects_(follow_redirects), + openssl_certificate_(openssl_certificate), + openssl_verify_path_(openssl_verify_path), +{} + +boost::shared_ptr +network::http::simple_async_connection_manager::get_connection( + asio::io_service & service, + request_base const & request) { + // TODO move out calls to new to a factory, taken as a parameter at + // construction time so that we are not tied to actual hard-coded + // dependencies. + shared_ptr connection; + shared_ptr resolver_delegate; + if (cache_resolved_) { + scoped_lock delegate_lock(this->resolver_mutex); + if (!this->shared_resolver_delegate.get()) + this->shared_resolver_delegate.reset( + new (std::nothrow) async_resolver_delegate(service)); + resolver_delegate = this->shared_resolver_delegate; + if (!resolver_delegate_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Insufficient memory.")); + } else { + resolver_delegate.reset(new(std::nothrow) async_resolver(service)); + if (!resolver_delegate_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Insuffucient memory.")); + } + shared_ptr connection_delegate; + bool https = (scheme(request) == "https"); + connection_delegate = + connection_delegate_factory::new_connection_delegate( + service, openssl_certificate_, openssl_verify_path_); + connection.reset( + new(std::nothrow) simple_async_client_connection(follow_redirects_, + resolver_delegate, + connection_delegate)); + if (!connection.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Insufficient memory.")); + return connection; +} + +void network::http::simple_async_connection_manager::reset() { + if (cache_resolved_) { + scoped_lock delegate_lock(this->resolver_mutex); + this->shared_resolver_delegate.reset(); + } +} + +namespace network { namespace http { + +struct http_1_1_async_connection : client_connection { + http_1_1_async_connection(bool follow_redirects, + shared_ptr resolver_delegate, + shared_ptr connection_delegate); + virtual shared_ptr send_request(std::string const & method, + request_base const & request, + bool get_body, + callback_type callback); //override + virtual void reset(); // override + virtual ~http_1_1_async_connection(); // override + protected: + bool follow_redirects_; + shared_ptr resolver_delegate_; + shared_ptr connection_delegate_; + shared_ptr connection_; +}; + +http_1_1_async_connection::http_1_1_async_connection( + bool follow_redirects, + shared_ptr resolver_delegate, + shared_ptr connection_delegate) +: follow_redirects_(follow_redirects), + resolver_delegate_(resolver_delegate), + connection_delegate_(connection_delegate) +{ + connection_.reset(new(std::nothrow) impl::async_connection( + resolver_delegate_, + follow_redirects_, + connection_delegate_)) +} + +shared_ptr http_1_1_async_connection::send_request( + std::string const & method, + request_base const & request, + bool get_body, + callback_type callback) { + if (!connection_.get()) + BOOST_THROW_EXCEPTION(std::runtime_error("Insufficient memory.")); + response = connection_->start(request, method, get_body, callback); + return response; +} + +void http_1_1_async_connection::reset() { + connection_.reset(); +} + +http_1_1_async_connection::~http_1_1_async_connection() +{} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_POLICIES_ASYNC_CONNECTION_IPP_20110930 */ diff --git a/http/src/network/protocol/http/request.hpp b/http/src/network/protocol/http/request.hpp new file mode 100644 index 000000000..0e302cc26 --- /dev/null +++ b/http/src/network/protocol/http/request.hpp @@ -0,0 +1,13 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_HPP_20111021 +#define NETWORK_PROTOCOL_HTTP_REQUEST_HPP_20111021 + +#include + +#endif // NETWORK_PROTOCOL_HTTP_REQUEST_HPP_20111021 diff --git a/http/src/network/protocol/http/request/request.hpp b/http/src/network/protocol/http/request/request.hpp new file mode 100644 index 000000000..ee3aff418 --- /dev/null +++ b/http/src/network/protocol/http/request/request.hpp @@ -0,0 +1,111 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_REQUEST_HPP_20111021 +#define NETWORK_PROTOCOL_HTTP_REQUEST_REQUEST_HPP_20111021 + +#ifndef NETWORK_DEFAULT_CHUNK_SIZE +#define NETWORK_DEFAULT_CHUNK_SIZE 4096 +#endif // NETWORK_DEFAULT_CHUNK_SIZE + +#include +#include +#include +#include +#include + +namespace network { namespace http { + + struct request_pimpl; + + struct request : request_base { + // We support full value semantics. + request(); + explicit request(std::string const & url); + explicit request(::network::uri const & url); + request(request const &); + request& operator=(request); + + // Then we lift the swap and equals implementation. + using request_base::swap; + using request_base::equals; + + // From message_base... + // Mutators + virtual void set_destination(std::string const & destination); + virtual void set_source(std::string const & source); + virtual void append_header(std::string const & name, + std::string const & value); + virtual void remove_headers(std::string const & name); + virtual void remove_headers(); + virtual void set_body(std::string const & body); + virtual void append_body(std::string const & data); + + // Retrievers + virtual void get_destination(std::string & destination) const; + virtual void get_source(std::string & source) const; + virtual void get_headers(std::function inserter) const; + virtual void get_headers(std::string const & name, std::function inserter) const; + virtual void get_headers(std::function predicate, std::function inserter) const; + virtual void get_body(std::string & body) const; + virtual void get_body(std::function chunk_reader, size_t size) const; + + // From request_base... + // Setters + virtual void set_method(std::string const & method); + virtual void set_status(std::string const & status); + virtual void set_status_message(std::string const & status_message); + virtual void set_body_writer(std::function writer); + virtual void set_uri(std::string const &uri); + virtual void set_uri(::network::uri const &uri); + virtual void set_version_major(unsigned short major_version); + virtual void set_version_minor(unsigned short minor_version); + + // Getters + virtual void get_uri(::network::uri &uri) const; + virtual void get_uri(std::string &uri) const; + virtual void get_method(std::string & method) const; + virtual void get_status(std::string & status) const; + virtual void get_status_message(std::string & status_message) const; + virtual void get_body(std::function chunk_reader) const; + virtual void get_version_major(unsigned short &major_version); + virtual void get_version_minor(unsigned short &minor_version); + + virtual ~request(); + private: + request_pimpl* pimpl_; + }; + + template + request_base & operator<< (request_base & request, + Directive const & directive) { + directive(request); + return request; + } + + inline void swap(request &l, request &r) { + l.swap(r); + } + + inline bool operator==(request const &l, request const &r) { + return l.equals(r); + } + + inline bool operator!=(request const &l, request const &r) { + return !l.equals(r); + } + +} // namespace http +} // namespace network + +#include +#include +#include +#include +#include +#include + +#endif /* NETWORK_PROTOCOL_HTTP_REQUEST_REQUEST_HPP_20111021 */ diff --git a/http/src/network/protocol/http/request/request.ipp b/http/src/network/protocol/http/request/request.ipp new file mode 100644 index 000000000..9a73c4a85 --- /dev/null +++ b/http/src/network/protocol/http/request/request.ipp @@ -0,0 +1,313 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_IPP_20110910 +#define NETWORK_PROTOCOL_HTTP_REQUEST_IPP_20110910 + +#include +#include +#include + +#ifdef NETWORK_DEBUG +BOOST_CONCEPT_ASSERT((network::http::ClientRequest)); +#endif + +namespace network { namespace http { + +struct request_pimpl { + request_pimpl() + : uri_() + , read_offset_(0) + , source_() + , destination_() + , headers_() + {} + + explicit request_pimpl(std::string const & url) + : uri_(url) + , read_offset_(0) + , source_() + , destination_() + , headers_() + {} + + explicit request_pimpl(::network::uri const & url) + : uri_(url) + , read_offset_(0) + , source_() + , destination_() + , headers_() + {} + + request_pimpl* clone() const { + return new (std::nothrow) request_pimpl(*this); + } + + void set_uri(std::string const & uri) { + set_uri(::network::uri(uri)); + } + + void set_uri(::network::uri const & uri) { + uri_ = uri; + } + + void get_uri(std::string &uri) { + uri = uri_.string(); + } + + void get_uri(::network::uri &uri) { + uri = uri_; + } + + void append_header(std::string const & name, std::string const & value) { + headers_.insert(std::make_pair(name, value)); + } + + void get_headers(std::function predicate, + std::function inserter) const { + headers_type::const_iterator it = headers_.begin(); + for (; it != headers_.end(); ++it) { + if (predicate(it->first, it->second)) { + inserter(it->first, it->second); + } + } + } + + void get_headers(std::function inserter) const { + headers_type::const_iterator it = headers_.begin(); + for (; it != headers_.end(); ++it) { + inserter(it->first, it->second); + } + } + + void get_headers(std::string const &name, + std::function inserter) const { + headers_type::const_iterator it = headers_.begin(); + for (; it != headers_.end(); ++it) { + if (it->first == name) { + inserter(it->first, it->second); + } + } + } + + void set_source(std::string const &source) { + source_ = source; + } + + void get_source(std::string &source) const { + source = source_; + } + + void set_destination(std::string const &destination) { + destination_ = destination; + } + + void get_destination(std::string &destination) const { + destination = destination_; + } + + size_t read_offset() const { + return read_offset_; + } + + void advance_read_offset(size_t bytes) { + read_offset_ += bytes; + } + + bool equals(request_pimpl const &other) const { + return uri_ == other.uri_ && + read_offset_ == other.read_offset_ && + source_ == other.source_ && + destination_ == other.destination_ && + headers_ == other.headers_; + } + + void set_version_major(unsigned short major_version) { + version_major_ = major_version; + } + + void set_version_minor(unsigned short minor_version) { + version_minor_ = minor_version; + } + + void get_version_major(unsigned short &major_version) { + major_version = version_major_; + } + + void get_version_minor(unsigned short &minor_version) { + minor_version = version_minor_; + } + + private: + typedef std::multimap headers_type; + + ::network::uri uri_; + size_t read_offset_; + std::string source_, destination_; + headers_type headers_; + unsigned short version_major_, version_minor_; + + request_pimpl(request_pimpl const &other) + : uri_(other.uri_) + , read_offset_(other.read_offset_) + , source_(other.source_) + , destination_(other.destination_) + , headers_(other.headers_) + {} +}; + +request::~request() { + // do nothing here +} + +request::request() +: pimpl_(new (std::nothrow) request_pimpl()) +{} + +request::request(std::string const & url) +: pimpl_(new (std::nothrow) request_pimpl(url)) +{} + +request::request(::network::uri const & url) +: pimpl_(new (std::nothrow) request_pimpl(url)) +{} + +request::request(request const &other) +: pimpl_(other.pimpl_->clone()) +{} + +request& request::operator=(request rhs) { + rhs.swap(*this); + return *this; +} + +// From message_base... +// Mutators +void request::set_destination(std::string const & destination) { + pimpl_->set_destination(destination); +} + +void request::set_source(std::string const & source) { + pimpl_->set_source(source); +} + +void request::append_header(std::string const & name, + std::string const & value) { + pimpl_->append_header(name, value); +} + +void request::remove_headers(std::string const & name) { +} + +void request::remove_headers() { +} + +void request::set_body(std::string const & body) { + this->clear(); + this->append(body.data(), body.size()); +} + +void request::append_body(std::string const & data) { + this->append(data.data(), data.size()); +} + +// Retrievers +void request::get_destination(std::string & destination) const { + pimpl_->get_destination(destination); +} + +void request::get_source(std::string & source) const { + pimpl_->get_source(source); +} + +void request::get_headers(std::function inserter) const { + pimpl_->get_headers(inserter); +} + +void request::get_headers(std::string const & name, std::function inserter) const { + pimpl_->get_headers(name, inserter); +} + +void request::get_headers(std::function predicate, std::function inserter) const { + pimpl_->get_headers(predicate, inserter); +} + +void request::get_body(std::string & body) const { + this->flatten(body); +} + +void request::get_body(std::function chunk_reader, size_t size) const { + std::string local_buffer; + size_t bytes_read = this->read(local_buffer, pimpl_->read_offset(), size); + pimpl_->advance_read_offset(bytes_read); + chunk_reader(local_buffer.cbegin(), bytes_read); +} + +void request::get_body(std::function chunk_reader) const { + this->get_body(chunk_reader, NETWORK_DEFAULT_CHUNK_SIZE); +} + +// From request_base... +// Setters +void request::set_method(std::string const & method) { +} + +void request::set_status(std::string const & status) { +} + +void request::set_status_message(std::string const & status_message) { +} + +void request::set_body_writer(std::function writer) { +} + +void request::set_uri(std::string const &uri) { + pimpl_->set_uri(uri); +} + +void request::set_uri(::network::uri const &uri) { + pimpl_->set_uri(uri); +} + +void request::set_version_major(unsigned short major_version) { + pimpl_->set_version_major(major_version); +} + +void request::set_version_minor(unsigned short minor_version) { + pimpl_->set_version_minor(minor_version); +} + +// Getters +void request::get_uri(::network::uri &uri) const { + pimpl_->get_uri(uri); +} + +void request::get_uri(std::string &uri) const { + pimpl_->get_uri(uri); +} + +void request::get_version_major(unsigned short &major_version) { + pimpl_->get_version_major(major_version); +} + +void request::get_version_minor(unsigned short &minor_version) { + pimpl_->get_version_minor(minor_version); +} + +void request::get_method(std::string & method) const { +} + +void request::get_status(std::string & status) const { +} + +void request::get_status_message(std::string & status_message) const { +} + +} // namespace http + +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_REQUEST_IPP_20110910 */ diff --git a/http/src/network/protocol/http/request/request_base.hpp b/http/src/network/protocol/http/request/request_base.hpp new file mode 100644 index 000000000..d8349755d --- /dev/null +++ b/http/src/network/protocol/http/request/request_base.hpp @@ -0,0 +1,65 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_BASE_HPP_20111008 +#define NETWORK_PROTOCOL_HTTP_REQUEST_BASE_HPP_20111008 + +#ifndef NETWORK_BUFFER_CHUNK +#define NETWORK_BUFFER_CHUNK 1024 // We want 1KiB worth of data at least. +#endif + +#include +#include + +namespace network { namespace http { + +struct body_source { + virtual std::streamsize read(std::string&, std::streamsize size); + virtual ~body_source(); +}; + +struct request_storage_base_pimpl; + +struct request_storage_base { + protected: + request_storage_base(size_t chunk_size = NETWORK_BUFFER_CHUNK); + request_storage_base(request_storage_base const &other); + virtual void append(char const *data, size_t size); + virtual size_t read(std::string &destination, size_t offset, size_t size) const; + virtual void flatten(std::string &destination) const; + virtual void clear(); + virtual bool equals(request_storage_base const &other) const; + virtual void swap(request_storage_base &other); + virtual ~request_storage_base(); + + private: + request_storage_base_pimpl *pimpl_; +}; + +struct request_base : message_base, request_storage_base { + // Setters + virtual void set_method(std::string const & method) = 0; + virtual void set_status(std::string const & status) = 0; + virtual void set_status_message(std::string const & status_message) = 0; + virtual void set_body_writer(std::function writer) = 0; + virtual void set_uri(std::string const &uri) = 0; + virtual void set_uri(::network::uri const &uri) = 0; + + // Getters + virtual void get_uri(::network::uri &uri) const = 0; + virtual void get_uri(std::string &uri) const = 0; + virtual void get_method(std::string & method) const = 0; + virtual void get_status(std::string & status) const = 0; + virtual void get_status_message(std::string & status_message) const = 0; + virtual void get_body(std::function chunk_reader, size_t size) const = 0; + virtual void get_body(std::string & body) const = 0; + virtual ~request_base() = 0; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_REQUEST_BASE_HPP_20111008 */ diff --git a/http/src/network/protocol/http/request/request_base.ipp b/http/src/network/protocol/http/request/request_base.ipp new file mode 100644 index 000000000..c9c67604e --- /dev/null +++ b/http/src/network/protocol/http/request/request_base.ipp @@ -0,0 +1,209 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_RPTOCOL_HTTP_REQUEST_BASE_IPP_20111102 +#define NETWORK_RPTOCOL_HTTP_REQUEST_BASE_IPP_20111102 + +#include +#include +#include + +namespace network { namespace http { + +request_base::~request_base() { + // default implementation, only required for linking. +} + +struct request_storage_base_pimpl { + explicit request_storage_base_pimpl(size_t chunk_size); + request_storage_base_pimpl *clone() const; + void append(char const *data, size_t size); + size_t read(std::string &destination, size_t offset, size_t size) const; + void flatten(std::string &destination) const; + void clear(); + bool equals(request_storage_base_pimpl const &other) const; + void swap(request_storage_base_pimpl &other); + ~request_storage_base_pimpl(); + + private: + size_t chunk_size_; + typedef std::vector > chunks_vector; + chunks_vector chunks_; + mutable std::mutex chunk_mutex_; + + request_storage_base_pimpl(request_storage_base_pimpl const &other); +}; + +request_storage_base::request_storage_base(size_t chunk_size) +: pimpl_(new (std::nothrow) request_storage_base_pimpl(chunk_size)) +{} + +request_storage_base::request_storage_base(request_storage_base const &other) +: pimpl_(other.pimpl_->clone()) +{} + +request_storage_base::~request_storage_base() { + delete pimpl_; +} + +void request_storage_base::append(char const *data, size_t size) { + pimpl_->append(data, size); +} + +size_t request_storage_base::read(std::string &destination, size_t offset, size_t size) const { + return pimpl_->read(destination, offset, size); +} + +void request_storage_base::flatten(std::string &destination) const { + pimpl_->flatten(destination); +} + +void request_storage_base::clear() { + pimpl_->clear(); +} + +bool request_storage_base::equals(request_storage_base const &other) const { + return pimpl_->equals(*other.pimpl_); +} + +void request_storage_base::swap(request_storage_base &other) { + return other.pimpl_->swap(*pimpl_); +} + +request_storage_base_pimpl::request_storage_base_pimpl(size_t chunk_size) +: chunk_size_(chunk_size) +, chunks_() +{ + // do nothing here. +} + +request_storage_base_pimpl::request_storage_base_pimpl(request_storage_base_pimpl const &other) +: chunk_size_(other.chunk_size_) +, chunks_(0) { + std::lock_guard scoped_lock(other.chunk_mutex_); + chunks_.reserve(other.chunks_.size()); + chunks_vector::const_iterator it = other.chunks_.begin(); + for (; it != other.chunks_.end(); ++it) { + chunks_vector::value_type pair = + std::make_pair( + new (std::nothrow) char[other.chunk_size_], + it->second); + std::memcpy(pair.first, it->first, it->second); + chunks_.push_back(pair); + } +} + +request_storage_base_pimpl * request_storage_base_pimpl::clone() const { + return new(std::nothrow) request_storage_base_pimpl(*this); +} + +void request_storage_base_pimpl::append(char const *data, size_t size) { + std::lock_guard scoped_lock(chunk_mutex_); + if (chunks_.empty()) { + chunks_.push_back(std::make_pair( + new (std::nothrow) char[chunk_size_], 0)); + } + std::pair *chunk = &chunks_.back(); + BOOST_ASSERT(chunk_size_ >= chunk->second); + size_t remaining = chunk_size_ - chunk->second; + while (remaining < size) { + size_t bytes_to_write = std::min(size - remaining, chunk_size_); + std::memcpy(chunk->first + chunk->second, data, bytes_to_write); + chunk->second += bytes_to_write; + BOOST_ASSERT(chunk->second <= chunk_size_); + data += bytes_to_write; + size -= bytes_to_write; + chunks_.push_back(std::make_pair( + new (std::nothrow) char[chunk_size_], 0)); + chunk = &chunks_.back(); + remaining = chunk_size_; + } + if (size > 0) { + std::memcpy(chunk->first + chunk->second, data, size); + chunk->second += size; + } +} + +size_t request_storage_base_pimpl::read(std::string &destination, size_t offset, size_t size) const { + std::lock_guard scoped_lock(chunk_mutex_); + if (chunks_.empty()) return 0; + // First we find which chunk we're going to read from using the provided + // offset and some arithmetic to determine the correct one. + size_t chunk_index = offset / chunk_size_; + offset = offset % chunk_size_; + + // Then we start copying up to size data either until we've reached the end + size_t chunks_count = chunks_.size(); + size_t read_count = 0; + while (size > 0 && chunk_index < chunks_count) { + size_t bytes_to_read = std::min(chunks_[chunk_index].second, size); + destination.append(chunks_[chunk_index].first+offset, + chunks_[chunk_index].first+offset+bytes_to_read); + read_count += bytes_to_read; + size -= bytes_to_read; + offset = 0; + ++chunk_index; + } + return read_count; +} + +void request_storage_base_pimpl::flatten(std::string &destination) const { + std::lock_guard scpoped_lock(chunk_mutex_); + chunks_vector::const_iterator chunk_iterator = chunks_.begin(); + for (; chunk_iterator != chunks_.end(); ++chunk_iterator) { + destination.append(chunk_iterator->first, chunk_iterator->second); + } +} + +void request_storage_base_pimpl::clear() { + std::lock_guard scoped_lock(chunk_mutex_); + chunks_vector::const_iterator chunk_iterator = chunks_.begin(); + for (; chunk_iterator != chunks_.end(); ++chunk_iterator) { + delete [] chunk_iterator->first; + } + chunks_vector().swap(chunks_); +} + +bool request_storage_base_pimpl::equals(request_storage_base_pimpl const &other) const { + std::lock(other.chunk_mutex_, this->chunk_mutex_); + if (other.chunk_size_ != chunk_size_ || other.chunks_.size() != chunks_.size()) { + other.chunk_mutex_.unlock(); + this->chunk_mutex_.unlock(); + return false; + } + chunks_vector::const_iterator chunk_iterator = chunks_.begin(); + chunks_vector::const_iterator other_iterator = other.chunks_.begin(); + for (; chunk_iterator != chunks_.begin() && other_iterator != other.chunks_.end(); + ++chunk_iterator, ++other_iterator) { + if (chunk_iterator->second != other_iterator->second || + strncmp(chunk_iterator->first, other_iterator->first, chunk_iterator->second)) { + other.chunk_mutex_.unlock(); + this->chunk_mutex_.unlock(); + return false; + } + } + other.chunk_mutex_.unlock(); + this->chunk_mutex_.unlock(); + return true; +} + +void request_storage_base_pimpl::swap(request_storage_base_pimpl &other) { + std::lock(other.chunk_mutex_, this->chunk_mutex_); + std::swap(chunk_size_, other.chunk_size_); + std::swap(chunks_, other.chunks_); + other.chunk_mutex_.unlock(); + this->chunk_mutex_.unlock(); +} + +request_storage_base_pimpl::~request_storage_base_pimpl() { + clear(); +} + + +} // namespace http +} // namespace network + +#endif /* NETWORK_RPTOCOL_HTTP_REQUEST_BASE_IPP_20111102 */ diff --git a/boost/network/protocol/http/request_concept.hpp b/http/src/network/protocol/http/request/request_concept.hpp similarity index 51% rename from boost/network/protocol/http/request_concept.hpp rename to http/src/network/protocol/http/request/request_concept.hpp index 5b0ee99eb..d78ff8829 100644 --- a/boost/network/protocol/http/request_concept.hpp +++ b/http/src/network/protocol/http/request/request_concept.hpp @@ -1,32 +1,31 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 - // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 + #include -#include +#include #include #include #include +#include +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct ServerRequest { - typedef typename R::string_type string_type; - typedef typename R::tag tag; - typedef typename R::headers_container_type headers_container_type; - BOOST_CONCEPT_USAGE(ServerRequest) { - string_type source_, method_, destination_; + std::string source_, method_, destination_; boost::uint8_t major_version_, minor_version_; - headers_container_type headers_; - string_type body_; + std::multimap headers_; + std::string body_; source_ = source(request); method_ = method(request); @@ -42,20 +41,20 @@ namespace boost { namespace network { namespace http { major_version(request, major_version_); minor_version(request, minor_version_); headers(request, headers_); - add_header(request, string_type(), string_type()); - remove_header(request, string_type()); + add_header(request, std::string(), std::string()); + remove_header(request, std::string()); clear_headers(request); body(request, body_); - string_type name, value; + std::string name, value; - request << ::boost::network::source(source_) - << ::boost::network::destination(destination_) - << ::boost::network::http::method(method_) - << ::boost::network::http::major_version(major_version_) - << ::boost::network::http::minor_version(minor_version_) - << ::boost::network::header(name, value) - << ::boost::network::body(body_); + request << network::source(source_) + << network::destination(destination_) + << network::http::method(method_) + << network::http::major_version(major_version_) + << network::http::minor_version(minor_version_) + << network::header(name, value) + << network::body(body_); (void)source_;(void)method_;(void)destination_; (void)major_version_;(void)minor_version_;(void)headers_; @@ -68,26 +67,23 @@ namespace boost { namespace network { namespace http { template struct ClientRequest - : boost::network::Message + : network::Message { - typedef typename R::string_type string_type; - typedef typename R::port_type port_type; - BOOST_CONCEPT_USAGE(ClientRequest) { - string_type tmp; + std::string tmp; R request_(tmp); swap(request, request_); // swappable via ADL - string_type host_ = host(request); - port_type port_ = port(request); - string_type path_ = path(request); - string_type query_ = query(request); - string_type anchor_ = anchor(request); - string_type protocol_ = protocol(request); + std::string host_ = host(request); + boost::uint16_t port_ = port(request); + std::string path_ = path(request); + std::string query_ = query(request); + std::string anchor_ = anchor(request); + std::string protocol_ = protocol(request); - request << uri(string_type()); + request << uri(std::string()); - boost::network::http::uri(request, string_type()); + network::http::uri(request, std::string()); (void)host_; (void)port_; @@ -105,6 +101,4 @@ namespace boost { namespace network { namespace http { } // namespace network -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 +#endif // NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 diff --git a/boost/network/protocol/http/request_parser.hpp b/http/src/network/protocol/http/request_parser.hpp similarity index 75% rename from boost/network/protocol/http/request_parser.hpp rename to http/src/network/protocol/http/request_parser.hpp index 13818cbf2..d9d76a977 100644 --- a/boost/network/protocol/http/request_parser.hpp +++ b/http/src/network/protocol/http/request_parser.hpp @@ -2,14 +2,15 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009 Dean Michael Berris (mikhailberis at gmail dot com) -// Copyright (c) 2009 Tarro, Inc. +// Copyright 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright 2009-2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Copyright 2009 Tarroo, Inc. // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -// Modifications by Dean Michael Berris +// Modifications by Dean Michael Berris // #ifndef HTTP_SERVER3_REQUEST_PARSER_HPP @@ -17,21 +18,20 @@ #include #include -#include +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { namespace tag { struct default_; } /// Parser for incoming requests. -template -class basic_request_parser +class request_parser { public: /// Construct ready to parse the request method. - basic_request_parser() : state_(method_start) {} + request_parser() : state_(method_start) {} /// Reset to initial parser state. void reset() { state_ = method_start; } @@ -41,7 +41,7 @@ class basic_request_parser /// data is required. The InputIterator return value indicates how much of the /// input has been consumed. template - boost::tuple parse_headers(basic_request & req, + boost::tuple parse_headers(request & req, InputIterator begin, InputIterator end) { while (begin != end) @@ -56,7 +56,7 @@ class basic_request_parser private: /// Handle the next character of input. - boost::tribool consume(basic_request & req, char input); + boost::tribool consume(request & req, char input); /// Check if a byte is an HTTP character. static bool is_char(int c); @@ -98,11 +98,8 @@ class basic_request_parser }; } // namespace http - } // namespace network -} // namespace boost - -#include +#include #endif // HTTP_SERVER3_REQUEST_PARSER_HPP diff --git a/http/src/network/protocol/http/response.hpp b/http/src/network/protocol/http/response.hpp new file mode 100644 index 000000000..e8634878f --- /dev/null +++ b/http/src/network/protocol/http/response.hpp @@ -0,0 +1,31 @@ +// Copyright Dean Michael Berris 2007. +// Copyright Michael Dickey 2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_HPP +#define NETWORK_PROTOCOL_HTTP_RESPONSE_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#endif // NETWORK_PROTOCOL_HTTP_RESPONSE_HPP diff --git a/http/src/network/protocol/http/response/response.hpp b/http/src/network/protocol/http/response/response.hpp new file mode 100644 index 000000000..1a00a3a77 --- /dev/null +++ b/http/src/network/protocol/http/response/response.hpp @@ -0,0 +1,96 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_HPP_20111021 +#define NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_HPP_20111021 + +#include +#include + +namespace network { namespace http { + + struct response_pimpl; + + struct response : response_base { + response(); + response(response const &); + response& operator=(response); + void swap(response &); + bool equals(response const &) const; + + // From message_base... + // Mutators + virtual void set_destination(std::string const & destination); + virtual void set_source(std::string const & source); + virtual void append_header(std::string const & name, + std::string const & value); + virtual void remove_headers(std::string const & name); + virtual void remove_headers(); + virtual void set_body(std::string const & body); + virtual void append_body(std::string const & data); + + // Retrievers + virtual void get_destination(std::string & destination) const; + virtual void get_source(std::string & source) const; + virtual void get_headers(std::function inserter) const; + virtual void get_headers(std::string const & name, + std::function inserter) const; + virtual void get_headers(std::function predicate, + std::function inserter) const; + virtual void get_body(std::string & body) const; + virtual void get_body(std::function chunk_reader, + size_t size) const; + + // From response_base... + virtual void set_status(uint16_t new_status); + virtual void set_status_message(std::string const & new_status_message); + virtual void set_version(std::string const & new_version); + virtual void get_status(uint16_t &status) const; + virtual void get_status_message(std::string &status_message) const; + virtual void get_version(std::string &version) const; + virtual ~response(); + + private: + friend struct impl::setter_access; // Hide access through accessor class. + // These methods are unique to the response type which will allow for creating + // promises that can be set appropriately. + void set_version_promise(std::promise&); + void set_status_promise(std::promise&); + void set_status_message_promise(std::promise&); + void set_headers_promise(std::promise >&); + void set_source_promise(std::promise&); + void set_destination_promise(std::promise&); + void set_body_promise(std::promise&); + + response_pimpl *pimpl_; + }; + + inline void swap(response &l, response &r) { + l.swap(r); + } + + inline bool operator==(response const &l, response const &r) { + return l.equals(r); + } + + inline bool operator!=(response const &l, response const &r) { + return !l.equals(r); + } + + template + response & operator<<( + response & message, + Directive const & directive + ) + { + directive(message); + return message; + } + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_HPP_20111021 */ diff --git a/http/src/network/protocol/http/response/response.ipp b/http/src/network/protocol/http/response/response.ipp new file mode 100644 index 000000000..2b0cffdf1 --- /dev/null +++ b/http/src/network/protocol/http/response/response.ipp @@ -0,0 +1,436 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_IPP_20111206 +#define NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_IPP_20111206 + +#include +#include + +namespace network { namespace http { + +struct response_pimpl { + response_pimpl() {} + + response_pimpl * clone() { + return new (std::nothrow) response_pimpl(*this); + } + + void set_destination(std::string const &destination) { + std::promise destination_promise; + destination_promise.set_value(destination); + std::future tmp_future = destination_promise.get_future(); + destination_future_ = std::move(tmp_future); + } + + void get_destination(std::string &destination) { + if (!destination_future_.valid()) { + destination = ""; + } else { + destination = destination_future_.get(); + } + } + + void set_source(std::string const &source) { + std::promise source_promise; + source_promise.set_value(source); + source_future_ = source_promise.get_future().share(); + } + + void get_source(std::string &source) { + if (!source_future_.valid()) { + source = ""; + } else { + source = source_future_.get(); + } + } + + void append_header(std::string const & name, + std::string const & value) { + added_headers_.insert(std::make_pair(name, value)); + } + + void remove_headers(std::string const &name) { + removed_headers_.insert(name); + } + + void remove_headers() { + if (!headers_future_.valid()) { + std::promise > headers_promise; + headers_promise.set_value(std::multimap()); + std::future > tmp = + headers_promise.get_future(); + std::multimap().swap(added_headers_); + std::set().swap(removed_headers_); + headers_future_ = std::move(tmp); + } + } + + void get_headers( + std::function inserter) { + std::multimap::const_iterator it; + if (!headers_future_.valid()) { + it = added_headers_.begin(); + for (;it != added_headers_.end(); ++it) { + if (removed_headers_.find(it->first) == removed_headers_.end()) { + inserter(it->first, it->second); + } + } + } else { + std::multimap const & headers_ = + headers_future_.get(); + it = headers_.begin(); + for (;it != headers_.end(); ++it) { + if (removed_headers_.find(it->first) == removed_headers_.end()) { + inserter(it->first, it->second); + } + } + } + } + void get_headers( + std::string const & name, + std::function inserter) { /* FIXME: Do something! */ } + void get_headers( + std::function predicate, + std::function inserter) { /* FIXME: Do something! */ } + + void set_body(std::string const &body) { + std::promise body_promise; + body_promise.set_value(body); + std::future tmp_future = body_promise.get_future(); + body_future_ = std::move(tmp_future); + } + + void append_body(std::string const & data) { /* FIXME: Do something! */ } + + void get_body(std::string &body) { + if (!body_future_.valid()) { + body = ""; + } else { + body = body_future_.get(); + } + } + + void get_body( + std::function chunk_reader, + size_t size) { /* FIXME: Do something! */ } + + void set_status(boost::uint16_t status) { + std::promise status_promise; + status_promise.set_value(status); + std::future tmp_future = status_promise.get_future(); + status_future_ = std::move(tmp_future); + } + + void get_status(boost::uint16_t &status) { + if (!status_future_.valid()) { + status = 0u; + } else { + status = status_future_.get(); + } + } + + void set_status_message(std::string const &status_message) { + std::promise status_message_promise_; + status_message_promise_.set_value(status_message); + std::future tmp_future = status_message_promise_.get_future(); + status_message_future_ = std::move(tmp_future); + } + + void get_status_message(std::string &status_message) { + if (!status_message_future_.valid()) { + status_message = ""; + } else { + status_message = status_message_future_.get(); + } + } + + void set_version(std::string const &version) { + std::promise version_promise; + version_promise.set_value(version); + std::future tmp_future = version_promise.get_future(); + version_future_ = std::move(tmp_future); + } + + void get_version(std::string &version) { + if (!version_future_.valid()) { + version = ""; + } else { + version = version_future_.get(); + } + } + + void set_source_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + source_future_ = std::move(tmp_future); + } + + void set_destination_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + destination_future_ = std::move(tmp_future); + } + + void set_headers_promise(std::promise > &promise_) { + std::future > tmp_future = promise_.get_future(); + headers_future_ = std::move(tmp_future); + } + + void set_status_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + status_future_ = std::move(tmp_future); + } + + void set_status_message_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + status_message_future_ = std::move(tmp_future); + } + + void set_version_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + version_future_ = std::move(tmp_future); + } + + void set_body_promise(std::promise &promise_) { + std::future tmp_future = promise_.get_future(); + body_future_ = std::move(tmp_future); + } + + bool equals(response_pimpl const &other) { + if (source_future_.valid()) { + if (!other.source_future_.valid()) + return false; + if (source_future_.get() != other.source_future_.get()) + return false; + } else { + if (other.source_future_.valid()) + return false; + } + if (destination_future_.valid()) { + if (!other.destination_future_.valid()) + return false; + if (destination_future_.get() != other.destination_future_.get()) + return false; + } else { + if (other.destination_future_.valid()) + return false; + } + if (headers_future_.valid()) { + if (!other.headers_future_.valid()) + return false; + if (headers_future_.get() != other.headers_future_.get()) + return false; + } else { + if (other.headers_future_.valid()) + return false; + } + if (status_future_.valid()) { + if (!other.status_future_.valid()) + return false; + if (status_future_.get() != other.status_future_.get()) + return false; + } else { + if (other.status_future_.valid()) + return false; + } + if (status_message_future_.valid()) { + if (!other.status_message_future_.valid()) + return false; + if (status_message_future_.get() != other.status_message_future_.get()) + return false; + } else { + if (other.status_message_future_.valid()) + return false; + } + if (version_future_.valid()) { + if (!other.version_future_.valid()) + return false; + if (version_future_.get() != other.version_future_.get()) + return false; + } else { + if (other.version_future_.valid()) + return false; + } + if (body_future_.valid()) { + if (!other.body_future_.valid()) + return false; + if (body_future_.get() != other.body_future_.get()) + return false; + } else { + if (other.body_future_.valid()) + return false; + } + if (other.added_headers_ != added_headers_ || other.removed_headers_ != removed_headers_) + return false; + return true; + } + + private: + mutable std::shared_future source_future_; + mutable std::shared_future destination_future_; + mutable std::shared_future > + headers_future_; + mutable std::shared_future status_future_; + mutable std::shared_future status_message_future_; + mutable std::shared_future version_future_; + mutable std::shared_future body_future_; + // TODO: use unordered_map and unordered_set here. + std::multimap added_headers_; + std::set removed_headers_; + + response_pimpl(response_pimpl const &other) + : source_future_(other.source_future_) + , destination_future_(other.destination_future_) + , headers_future_(other.headers_future_) + , status_future_(other.status_future_) + , status_message_future_(other.status_message_future_) + , version_future_(other.version_future_) + , body_future_(other.body_future_) + , added_headers_(other.added_headers_) + , removed_headers_(other.removed_headers_) + {} +}; + +response::response() +: pimpl_(new (std::nothrow) response_pimpl) +{} + +response::response(response const & other) +: pimpl_(other.pimpl_->clone()) +{} + +response& response::operator=(response rhs) { + rhs.swap(*this); + return *this; +} + +void response::swap(response &other) { + std::swap(this->pimpl_, other.pimpl_); +} + +bool response::equals(response const &other) const { + return other.pimpl_->equals(*pimpl_); +} + +void response::set_destination(std::string const &destination) { + pimpl_->set_destination(destination); +} + +void response::set_source(std::string const &source) { + pimpl_->set_source(source); +} + +void response::append_header(std::string const &name, + std::string const &value) { + pimpl_->append_header(name, value); +} + +void response::remove_headers(std::string const &name) { + pimpl_->remove_headers(name); +} + +void response::remove_headers() { + pimpl_->remove_headers(); +} + +void response::set_body(std::string const &body) { + pimpl_->set_body(body); +} + +void response::append_body(std::string const &data) { + pimpl_->append_body(data); +} + +void response::get_destination(std::string &destination) const { + pimpl_->get_destination(destination); +} + +void response::get_source(std::string &source) const { + pimpl_->get_source(source); +} + +void response::get_headers(std::function inserter) const { + pimpl_->get_headers(inserter); +} + +void response::get_headers(std::string const &name, + std::function inserter) const { + pimpl_->get_headers(name, inserter); +} + +void response::get_headers(std::function predicate, + std::function inserter) const { + pimpl_->get_headers(predicate, inserter); +} + +void response::get_body(std::string &body) const { + pimpl_->get_body(body); +} + +void response::get_body(std::function chunk_reader, size_t size) const { + pimpl_->get_body(chunk_reader, size); +} + +void response::set_status(boost::uint16_t new_status) { + pimpl_->set_status(new_status); +} + +void response::set_status_message(std::string const &new_status_message) { + pimpl_->set_status_message(new_status_message); +} + +void response::set_version(std::string const &new_version) { + pimpl_->set_version(new_version); +} + +void response::get_status(boost::uint16_t &status) const { + pimpl_->get_status(status); +} + +void response::get_status_message(std::string &status_message) const { + pimpl_->get_status_message(status_message); +} + +void response::get_version(std::string &version) const { + pimpl_->get_version(version); +} + +response::~response() { + delete pimpl_; +} + +void response::set_version_promise(std::promise &promise) { + return pimpl_->set_version_promise(promise); +} + +void response::set_status_promise(std::promise &promise) { + return pimpl_->set_status_promise(promise); +} + +void response::set_status_message_promise(std::promise &promise) { + return pimpl_->set_status_message_promise(promise); +} + +void response::set_headers_promise(std::promise > &promise) { + return pimpl_->set_headers_promise(promise); +} + +void response::set_source_promise(std::promise &promise) { + return pimpl_->set_source_promise(promise); +} + +void response::set_destination_promise(std::promise &promise) { + return pimpl_->set_destination_promise(promise); +} + +void response::set_body_promise(std::promise &promise) { + return pimpl_->set_body_promise(promise); +} + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_IPP_20111206 diff --git a/http/src/network/protocol/http/response/response_base.hpp b/http/src/network/protocol/http/response/response_base.hpp new file mode 100644 index 000000000..f7d24c98a --- /dev/null +++ b/http/src/network/protocol/http/response/response_base.hpp @@ -0,0 +1,28 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_BASE_HPP_20110930 +#define NETWORK_PROTOCOL_HTTP_RESPONSE_BASE_HPP_20110930 + +#include +#include + +namespace network { namespace http { + +struct response_base : message_base { + virtual void set_status(std::uint16_t new_status) = 0; + virtual void set_status_message(std::string const & new_status_message) = 0; + virtual void set_version(std::string const & new_version) = 0; + virtual void get_status(std::uint16_t &status) const = 0; + virtual void get_status_message(std::string &status_message) const = 0; + virtual void get_version(std::string &version) const = 0; + virtual ~response_base() = 0; +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_RESPONSE_BASE_HPP_20110930 */ diff --git a/http/src/network/protocol/http/response/response_base.ipp b/http/src/network/protocol/http/response/response_base.ipp new file mode 100644 index 000000000..4bebd6280 --- /dev/null +++ b/http/src/network/protocol/http/response/response_base.ipp @@ -0,0 +1,21 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_BASE_IPP_20111102 +#define NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_BASE_IPP_20111102 + +#include + +namespace network { namespace http { + +response_base::~response_base() { + // default implementation, required only for linking. +} + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_RESPONSE_RESPONSE_BASE_IPP_20111102 */ diff --git a/boost/network/protocol/http/response_concept.hpp b/http/src/network/protocol/http/response/response_concept.hpp similarity index 62% rename from boost/network/protocol/http/response_concept.hpp rename to http/src/network/protocol/http/response/response_concept.hpp index ef6bf0f62..9b09ced54 100644 --- a/boost/network/protocol/http/response_concept.hpp +++ b/http/src/network/protocol/http/response/response_concept.hpp @@ -1,24 +1,22 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 -#define BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 - // Copyright 2010 (c) Dean Michael Berris. // Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 +#define NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 + #include -#include -#include -#include -#include +#include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct Response - : boost::network::Message + : network::Message { typedef typename R::string_type string_type; @@ -26,9 +24,9 @@ namespace boost { namespace network { namespace http { R response_; swap(response, response_); // swappable via ADL - typedef typename traits::version::type version_type; - typedef typename traits::status::type status_type; - typedef typename traits::status_message::type status_message_type; + typedef std::string version_type; + typedef std::string status_type; + typedef std::string status_message_type; response << version(version_type()) // version directive << status(status_type()) // status directive @@ -53,9 +51,6 @@ namespace boost { namespace network { namespace http { }; } // namespace http - } // namespace network -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 +#endif // NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 diff --git a/http/src/network/protocol/http/server.hpp b/http/src/network/protocol/http/server.hpp new file mode 100644 index 000000000..6027dfbe2 --- /dev/null +++ b/http/src/network/protocol/http/server.hpp @@ -0,0 +1,76 @@ +// Copyright 2009 Tarroo, Inc. +// Copyright 2010 Glyn Matthews +// Copyright 2003-2008 Chris Kholhoff +// Copyright 2009-2012 Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_HTTP_SERVER_HPP_ +#define NETWORK_HTTP_SERVER_HPP_ + +#include + +namespace network { namespace utils { + +struct thread_pool; + +} // namespace utils + +} // namespace network + +namespace network { namespace http { + +class server_options; +class sync_server_impl; +class async_server_impl; +class async_server_connection; +struct request; +struct response; + + +template +class sync_server { + public: + sync_server(server_options const &options, SyncHandler &handler); + void run(); + void stop(); + void listen(); + ~sync_server(); + + typedef http::request request; + typedef http::response response; + private: + sync_server_impl *pimpl_; + sync_server(sync_server const &other); // = delete + sync_server& operator=(sync_server other); // = delete +}; + +template +class async_server { + public: + explicit async_server(server_options const &options, AsyncHandler &handler, utils::thread_pool &pool); + void run(); + void stop(); + void listen(); + ~async_server(); + + typedef http::request request; + typedef boost::shared_ptr connection_ptr; + private: + async_server_impl *pimpl_; + async_server(async_server const &other); // = delete + async_server& operator=(async_server other); // = delete +}; + +} // namespace http + +} // namespace network + +// We're hiding the implementation from here, but still explicitly including +// it here. This is mostly a style point, to keep this header clean. +#include + +#endif // NETWORK_HTTP_SERVER_HPP_ + diff --git a/http/src/network/protocol/http/server/async_impl.hpp b/http/src/network/protocol/http/server/async_impl.hpp new file mode 100644 index 000000000..63b47ffc8 --- /dev/null +++ b/http/src/network/protocol/http/server/async_impl.hpp @@ -0,0 +1,58 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_20120318 + +#include +#include +#include +#include +#include + +namespace network { namespace utils { +struct thread_pool; +} // namespace util +} // namespace network + +namespace network { namespace http { + +struct request; + +class async_server_connection; + +class async_server_impl : protected socket_options_setter { + public: + typedef std::shared_ptr connection_ptr; + async_server_impl(server_options const &options, + std::function handler, + utils::thread_pool &thread_pool); + ~async_server_impl(); + void run(); + void stop(); + void listen(); + + private: + server_options options_; + std::string address_, port_; + boost::asio::io_service *service_; + boost::asio::ip::tcp::acceptor *acceptor_; + std::shared_ptr new_connection_; + std::mutex listening_mutex_, stopping_mutex_; + std::function handler_; + utils::thread_pool &pool_; + bool listening_, owned_service_, stopping_; + + void handle_stop(); + void start_listening(); + void handle_accept(boost::system::error_code const &ec); +}; + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_20120318 diff --git a/http/src/network/protocol/http/server/async_impl.ipp b/http/src/network/protocol/http/server/async_impl.ipp new file mode 100644 index 000000000..7aff4b21f --- /dev/null +++ b/http/src/network/protocol/http/server/async_impl.ipp @@ -0,0 +1,153 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_IPP_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_IPP_20120318 + +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + +async_server_impl::async_server_impl(server_options const &options, + std::function handler, + utils::thread_pool &thread_pool) +: options_(options) +, address_(options.address()) +, port_(options.port()) +, service_(options.io_service()) +, acceptor_(0) +, new_connection_() +, listening_mutex_() +, stopping_mutex_() +, handler_(handler) +, pool_(thread_pool) +, listening_(false) +, owned_service_(false) +, stopping_(false) { + if (service_ == 0) { + service_ = new boost::asio::io_service; + owned_service_ = true; + } + BOOST_ASSERT(service_ != 0); + acceptor_ = new boost::asio::ip::tcp::acceptor(*service_); + BOOST_ASSERT(acceptor_ != 0); +} + +async_server_impl::~async_server_impl() { + if (owned_service_) delete service_; + delete acceptor_; +} + +void async_server_impl::run() { + listen(); + service_->run(); +} + +void async_server_impl::stop() { + std::lock_guard listening_lock(listening_mutex_); + if (listening_) { + std::lock_guard stopping_lock(stopping_mutex_); + stopping_ = true; + boost::system::error_code ignored; + acceptor_->close(ignored); + listening_ = false; + service_->post( + boost::bind(&async_server_impl::handle_stop, this)); + } +} + +void async_server_impl::listen() { + std::lock_guard listening_lock(listening_mutex_); + NETWORK_MESSAGE("listening on " << address_ << ':' << port_); + if (!listening_) start_listening(); + if (!listening_) { + NETWORK_MESSAGE("error listening on " << address_ << ':' << port_); + BOOST_THROW_EXCEPTION(std::runtime_error("Error listening on provided address:port.")); + } +} + +void async_server_impl::handle_stop() { + std::lock_guard stopping_lock(stopping_mutex_); + // A user may have stopped listening again before the stop command is + // reached. + if (stopping_) service_->stop(); +} + +void async_server_impl::handle_accept(boost::system::error_code const & ec) { + { + std::lock_guard stopping_lock(stopping_mutex_); + // We dont want to add another handler instance, and we dont want to know + // about errors for a socket we dont need anymore. + if (stopping_) return; + } + if (!ec) { + set_socket_options(options_, new_connection_->socket()); + new_connection_->start(); + new_connection_.reset( + new async_server_connection(*service_, handler_, pool_)); + acceptor_->async_accept( + new_connection_->socket(), + boost::bind( + &async_server_impl::handle_accept, + this, + boost::asio::placeholders::error)); + } else { + NETWORK_MESSAGE("Error accepting connection, reason: " << ec); + } +} + +void async_server_impl::start_listening() { + using boost::asio::ip::tcp; + boost::system::error_code error; + service_->reset(); // allows repeated cycles of run->stop->run + tcp::resolver resolver(*service_); + tcp::resolver::query query(address_, port_); + tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); + if (error) { + NETWORK_MESSAGE("error resolving '" << address_ << ':' << port_); + BOOST_THROW_EXCEPTION(std::runtime_error("Error resolving address:port combination.")); + } + tcp::endpoint endpoint = *endpoint_iterator; + acceptor_->open(endpoint.protocol(), error); + if (error) { + NETWORK_MESSAGE("error opening socket: " << address_ << ":" << port_); + BOOST_THROW_EXCEPTION(std::runtime_error("Error opening socket.")); + } + set_acceptor_options(options_, *acceptor_); + acceptor_->bind(endpoint, error); + if (error) { + NETWORK_MESSAGE("error binding socket: " << address_ << ":" << port_); + BOOST_THROW_EXCEPTION(std::runtime_error("Error binding socket.")); + } + acceptor_->listen(boost::asio::socket_base::max_connections, error); + if (error) { + NETWORK_MESSAGE("error listening on socket: '" << error << "' on " << address_ << ":" << port_); + BOOST_THROW_EXCEPTION(std::runtime_error("Error listening on socket.")); + } + new_connection_.reset(new async_server_connection(*service_, handler_, pool_)); + acceptor_->async_accept( + new_connection_->socket(), + boost::bind( + &async_server_impl::handle_accept, + this, + boost::asio::placeholders::error)); + listening_ = true; + std::lock_guard stopping_lock(stopping_mutex_); + stopping_ = false; // if we were in the process of stopping, we revoke that command and continue listening + NETWORK_MESSAGE("now listening on '" << address_ << ":" << port_ << "'"); +} + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_IMPL_IPP_20120318 diff --git a/boost/network/protocol/http/server/async_server.hpp b/http/src/network/protocol/http/server/async_server.hpp similarity index 74% rename from boost/network/protocol/http/server/async_server.hpp rename to http/src/network/protocol/http/server/async_server.hpp index c56af236e..d0bb4eb86 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/http/src/network/protocol/http/server/async_server.hpp @@ -1,19 +1,20 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 +#define NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 + +#include +#include #include -#include -#include -#include +#include +#include +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct async_server_base : server_storage_base, socket_options_base { @@ -64,16 +65,16 @@ namespace boost { namespace network { namespace http { system::error_code ignored; acceptor.close(ignored); listening = false; - service_.post(boost::bind(&async_server_base::handle_stop, this)); + service_.post(std::bind(&async_server_base::handle_stop, this)); } } void listen() { scoped_mutex_lock listening_lock(listening_mutex_); - BOOST_NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); + NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); if (!listening) start_listening(); // we only initialize our acceptor/sockets if we arent already listening if (!listening) { - BOOST_NETWORK_MESSAGE("Error listening on " << address_ << ':' << port_); + NETWORK_MESSAGE("Error listening on " << address_ << ':' << port_); boost::throw_exception(std::runtime_error("Error listening on provided port.")); } } @@ -94,7 +95,7 @@ namespace boost { namespace network { namespace http { if (stopping) service_.stop(); // a user may have started listening again before the stop command is reached } - void handle_accept(boost::system::error_code const & ec) { + void handle_accept(asio::error_code const & ec) { { scoped_mutex_lock stopping_lock(stopping_mutex_); if (stopping) return; // we dont want to add another handler instance, and we dont want to know about errors for a socket we dont need anymore @@ -110,19 +111,19 @@ namespace boost { namespace network { namespace http { ) ); acceptor.async_accept(new_connection->socket(), - boost::bind( + std::bind( &async_server_base::handle_accept , this - , boost::asio::placeholders::error + , asio::placeholders::error ) ); } else { - BOOST_NETWORK_MESSAGE("Error accepting connection, reason: " << ec); + NETWORK_MESSAGE("Error accepting connection, reason: " << ec); } } void start_listening() { - using boost::asio::ip::tcp; + using asio::ip::tcp; system::error_code error; @@ -132,43 +133,40 @@ namespace boost { namespace network { namespace http { tcp::resolver::query query(address_, port_); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); if (error) { - BOOST_NETWORK_MESSAGE("Error resolving '" << address_ << ':' << port_); + NETWORK_MESSAGE("Error resolving '" << address_ << ':' << port_); return; } tcp::endpoint endpoint = *endpoint_iterator; acceptor.open(endpoint.protocol(), error); if (error) { - BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ":" << port_); + NETWORK_MESSAGE("Error opening socket: " << address_ << ":" << port_); return; } socket_options_base::acceptor_options(acceptor); acceptor.bind(endpoint, error); if (error) { - BOOST_NETWORK_MESSAGE("Error binding socket: " << address_ << ":" << port_); + NETWORK_MESSAGE("Error binding socket: " << address_ << ":" << port_); return; } acceptor.listen(asio::socket_base::max_connections, error); if (error) { - BOOST_NETWORK_MESSAGE("Error listening on socket: '" << error << "' on " << address_ << ":" << port_); + NETWORK_MESSAGE("Error listening on socket: '" << error << "' on " << address_ << ":" << port_); return; } new_connection.reset(new connection(service_, handler, thread_pool)); acceptor.async_accept(new_connection->socket(), - boost::bind( + std::bind( &async_server_base::handle_accept , this - , boost::asio::placeholders::error)); + , asio::placeholders::error)); listening = true; scoped_mutex_lock stopping_lock(stopping_mutex_); stopping = false; // if we were in the process of stopping, we revoke that command and continue listening - BOOST_NETWORK_MESSAGE("Now listening on socket: '" << address_ << ":" << port_ << "'"); + NETWORK_MESSAGE("Now listening on socket: '" << address_ << ":" << port_ << "'"); } }; -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 */ diff --git a/http/src/network/protocol/http/server/connection/async.hpp b/http/src/network/protocol/http/server/connection/async.hpp new file mode 100644 index 000000000..e3cb001fe --- /dev/null +++ b/http/src/network/protocol/http/server/connection/async.hpp @@ -0,0 +1,648 @@ +// Copyright 2010-2012 Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_ASYNC_HPP_20101027 +#define NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_ASYNC_HPP_20101027 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE +/** Here we define a page's worth of header connection buffer data. + * This can be tuned to reduce the memory cost of connections, but this + * default size is set to be friendly to typical service applications. + * This is the maximum size though and Boost.Asio's internal representation + * of a streambuf would make appropriate decisions on how big a buffer + * is to begin with. + * + * This kinda assumes that a page is by default 4096. Since we're using + * the default allocator with the static buffers, it's not guaranteed that + * the static buffers will be page-aligned when they are allocated. + */ +#define NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE 4096 +#endif /* NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE */ + +#ifndef NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE +/** Here we're making the assumption again that the page size of the system + * is 4096 and that it's better to have page-aligned chunks when creating + * buffers for memory use efficiency. + */ +#define NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 4096uL +#endif + +namespace network { namespace http { + + extern void parse_version(std::string const & partial_parsed, boost::fusion::tuple & version_pair); + extern void parse_headers(std::string const & input, std::vector > & container); + + class async_server_connection : public std::enable_shared_from_this { + public: + enum status_t { + ok = 200 + , created = 201 + , accepted = 202 + , no_content = 204 + , multiple_choices = 300 + , moved_permanently = 301 + , moved_temporarily = 302 + , not_modified = 304 + , bad_request = 400 + , unauthorized = 401 + , forbidden = 403 + , not_found = 404 + , not_supported = 405 + , not_acceptable = 406 + , internal_server_error = 500 + , not_implemented = 501 + , bad_gateway = 502 + , service_unavailable = 503 + }; + + typedef std::string string_type; + typedef std::shared_ptr connection_ptr; + + private: + static char const * status_message(status_t status) { + static char const + ok_[] = "OK" + , created_[] = "Created" + , accepted_[] = "Accepted" + , no_content_[] = "No Content" + , multiple_choices_[] = "Multiple Choices" + , moved_permanently_[] = "Moved Permanently" + , moved_temporarily_[] = "Moved Temporarily" + , not_modified_[] = "Not Modified" + , bad_request_[] = "Bad Request" + , unauthorized_[] = "Unauthorized" + , forbidden_[] = "Fobidden" + , not_found_[] = "Not Found" + , not_supported_[] = "Not Supported" + , not_acceptable_[] = "Not Acceptable" + , internal_server_error_[] = "Internal Server Error" + , not_implemented_[] = "Not Implemented" + , bad_gateway_[] = "Bad Gateway" + , service_unavailable_[] = "Service Unavailable" + , unknown_[] = "Unknown" + ; + switch(status) { + case ok: return ok_; + case created: return created_; + case accepted: return accepted_; + case no_content: return no_content_; + case multiple_choices: return multiple_choices_; + case moved_permanently: return moved_permanently_; + case moved_temporarily: return moved_temporarily_; + case not_modified: return not_modified_; + case bad_request: return bad_request_; + case unauthorized: return unauthorized_; + case forbidden: return forbidden_; + case not_found: return not_found_; + case not_supported: return not_supported_; + case not_acceptable: return not_acceptable_; + case internal_server_error: return internal_server_error_; + case not_implemented: return not_implemented_; + case bad_gateway: return bad_gateway_; + case service_unavailable: return service_unavailable_; + default: return unknown_; + } + } + + public: + + async_server_connection( + boost::asio::io_service & io_service + , std::function handler + , utils::thread_pool & thread_pool + ) + : socket_(io_service) + , strand(io_service) + , handler(handler) + , thread_pool_(thread_pool) + , headers_already_sent(false) + , headers_in_progress(false) + , headers_buffer(NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE) + { + new_start = read_buffer_.begin(); + } + + ~async_server_connection() throw () { + boost::system::error_code ignored; + socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_receive, ignored); + } + + /** Function: template set_headers(Range headers) + * Precondition: headers have not been sent yet + * Postcondition: headers have been linearized to a buffer, + * and assumed to have been sent already when the function exits + * Throws: std::logic_error in case the headers have already been sent. + * + * A call to set_headers takes a Range where each element models the + * Header concept. This Range will be linearized onto a buffer, which is + * then sent as soon as the first call to `write` or `flush` commences. + */ + template + void set_headers(Range headers) { + lock_guard lock(headers_mutex); + if (headers_in_progress || headers_already_sent) + boost::throw_exception(std::logic_error("Headers have already been sent.")); + + if (error_encountered) + boost::throw_exception(boost::system::system_error(*error_encountered)); + + { + std::ostream stream(&headers_buffer); + stream + << constants::http_slash() << 1<< constants::dot() << 1 << constants::space() + << status << constants::space() << status_message(status) + << constants::crlf(); + if (!boost::empty(headers)) { + typedef typename Range::const_iterator iterator; + boost::transform(headers, + std::ostream_iterator(stream), + linearize_header()); + } else { + stream << constants::crlf(); + } + stream << constants::crlf(); + } + + write_headers_only( + boost::bind( + &async_server_connection::do_nothing + , async_server_connection::shared_from_this() + )); + } + + void set_status(status_t new_status) { + lock_guard lock(headers_mutex); + if (headers_already_sent) boost::throw_exception(std::logic_error("Headers have already been sent, cannot reset status.")); + if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + + status = new_status; + } + + template + void write(Range const & range) { + lock_guard lock(headers_mutex); + if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + std::function f = + std::bind( + &async_server_connection::default_error + , async_server_connection::shared_from_this() + , std::placeholders::_1); + + write_impl( + boost::make_iterator_range(range) + , f + ); + } + + template + typename std::enable_if::value>::type + write(Range const & range, Callback const & callback) { + lock_guard lock(headers_mutex); + if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + write_impl(boost::make_iterator_range(range), callback); + } + + template + typename std::enable_if::value>::type + write(ConstBufferSeq const & seq, Callback const & callback) + { + write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); + } + + private: + typedef boost::array buffer_type; + + public: + typedef boost::iterator_range input_range; + typedef std::function read_callback_function; + + void read(read_callback_function callback) { + if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + if (new_start != read_buffer_.begin()) + { + input_range input = boost::make_iterator_range(new_start, read_buffer_.end()); + thread_pool().post( + boost::bind( + callback + , input + , boost::system::error_code() + , std::distance(new_start, data_end) + , async_server_connection::shared_from_this()) + ); + new_start = read_buffer_.begin(); + return; + } + + socket().async_read_some( + boost::asio::buffer(read_buffer_) + , strand.wrap( + boost::bind( + &async_server_connection::wrap_read_handler + , async_server_connection::shared_from_this() + , callback + , boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + } + + boost::asio::ip::tcp::socket & socket() { return socket_; } + utils::thread_pool & thread_pool() { return thread_pool_; } + bool has_error() { return (!!error_encountered); } + boost::optional error() + { return error_encountered; } + + private: + + void wrap_read_handler(read_callback_function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (ec) error_encountered = boost::in_place(ec); + buffer_type::const_iterator data_start = read_buffer_.begin() + ,data_end = read_buffer_.begin(); + std::advance(data_end, bytes_transferred); + thread_pool().post( + boost::bind( + callback + , boost::make_iterator_range(data_start, data_end) + , ec + , bytes_transferred + , async_server_connection::shared_from_this())); + } + + void default_error(boost::system::error_code const & ec) { + error_encountered = boost::in_place(ec); + } + + typedef boost::array array; + typedef std::list > array_list; + typedef std::shared_ptr shared_array_list; + typedef std::shared_ptr > shared_buffers; + typedef std::lock_guard lock_guard; + typedef std::list > pending_actions_list; + + boost::asio::ip::tcp::socket socket_; + boost::asio::io_service::strand strand; + std::function handler; + utils::thread_pool & thread_pool_; + volatile bool headers_already_sent, headers_in_progress; + boost::asio::streambuf headers_buffer; + + std::recursive_mutex headers_mutex; + buffer_type read_buffer_; + status_t status; + request_parser parser; + request request_; + buffer_type::iterator new_start, data_end; + std::string partial_parsed; + boost::optional error_encountered; + pending_actions_list pending_actions; + + friend class async_server_impl; + + enum state_t { + method, uri, version, headers + }; + + void start() { + std::ostringstream ip_stream; + ip_stream << socket_.remote_endpoint().address().to_string() << ':' + << socket_.remote_endpoint().port(); + request_.set_source(ip_stream.str()); + read_more(method); + } + + void read_more(state_t state) { + socket_.async_read_some( + boost::asio::buffer(read_buffer_) + , strand.wrap( + boost::bind( + &async_server_connection::handle_read_data, + async_server_connection::shared_from_this(), + state, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred + ) + ) + ); + } + + void handle_read_data(state_t state, boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec) { + boost::logic::tribool parsed_ok; + boost::iterator_range result_range, input_range; + data_end = read_buffer_.begin(); + std::advance(data_end, bytes_transferred); + switch (state) { + case method: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser.parse_until( + request_parser::method_done, input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + std::string method; + swap(partial_parsed, method); + method.append(boost::begin(result_range), + boost::end(result_range)); + boost::trim(method); + request_.set_method(method); + new_start = boost::end(result_range); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(method); + break; + } + case uri: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser.parse_until( + request_parser::uri_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + std::string destination; + swap(partial_parsed, destination); + destination.append(boost::begin(result_range), + boost::end(result_range)); + boost::trim(destination); + request_.set_destination(destination); + new_start = boost::end(result_range); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(uri); + break; + } + case version: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser.parse_until( + request_parser::version_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + boost::fusion::tuple version_pair; + partial_parsed.append(boost::begin(result_range), boost::end(result_range)); + parse_version(partial_parsed, version_pair); + request_.set_version_major(boost::fusion::get<0>(version_pair)); + request_.set_version_minor(boost::fusion::get<1>(version_pair)); + new_start = boost::end(result_range); + partial_parsed.clear(); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(version); + break; + } + case headers: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser.parse_until( + request_parser::headers_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + std::vector > headers; + parse_headers(partial_parsed, headers); + for (std::vector >::const_iterator it = headers.begin(); + it != headers.end(); + ++it) { + request_.append_header(it->first, it->second); + } + new_start = boost::end(result_range); + thread_pool().post( + boost::bind( + handler, + boost::cref(request_), + async_server_connection::shared_from_this())); + return; + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(headers); + break; + } + default: + BOOST_ASSERT(false && "This is a bug, report to the cpp-netlib devel mailing list!"); + std::abort(); + } + } else { + error_encountered = boost::in_place(ec); + } + } + + void client_error() { + static char const * bad_request = + "HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; + + boost::asio::async_write( + socket() + , boost::asio::buffer(bad_request, strlen(bad_request)) + , strand.wrap( + boost::bind( + &async_server_connection::client_error_sent + , async_server_connection::shared_from_this() + , boost::asio::placeholders::error + , boost::asio::placeholders::bytes_transferred))); + } + + void client_error_sent(boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec) { + boost::system::error_code ignored; + socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); + socket().close(ignored); + } else { + error_encountered = boost::in_place(ec); + } + } + + void do_nothing() {} + + void write_headers_only(std::function callback) { + if (headers_in_progress) return; + headers_in_progress = true; + boost::asio::async_write( + socket() + , headers_buffer + , strand.wrap( + boost::bind( + &async_server_connection::handle_write_headers + , async_server_connection::shared_from_this() + , callback + , boost::asio::placeholders::error + , boost::asio::placeholders::bytes_transferred))); + } + + void handle_write_headers(std::function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + lock_guard lock(headers_mutex); + if (!ec) { + headers_buffer.consume(headers_buffer.size()); + headers_already_sent = true; + thread_pool().post(callback); + pending_actions_list::iterator start = pending_actions.begin() + , end = pending_actions.end(); + while (start != end) { + thread_pool().post(*start++); + } + pending_actions_list().swap(pending_actions); + } else { + error_encountered = boost::in_place(ec); + } + } + + void handle_write( + std::function callback + , shared_array_list temporaries + , shared_buffers buffers + , boost::system::error_code const & ec + , std::size_t bytes_transferred + ) { + // we want to forget the temporaries and buffers + thread_pool().post(boost::bind(callback, ec)); + } + + template + void write_impl(Range range, std::function callback) { + // linearize the whole range into a vector + // of fixed-sized buffers, then schedule an asynchronous + // write of these buffers -- make sure they are live + // by making these linearized buffers shared and made + // part of the completion handler. + // + // once the range has been linearized and sent, schedule + // a wrapper to be called in the io_service's thread, that + // will re-schedule the given callback into the thread pool + // referred to here so that the io_service's thread can concentrate + // on doing I/O. + // + + static std::size_t const connection_buffer_size = + NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE; + shared_array_list temporaries = + std::make_shared(); + shared_buffers buffers = + std::make_shared >(0); + + std::size_t range_size = boost::distance(range); + buffers->reserve( + (range_size / connection_buffer_size) + + ((range_size % connection_buffer_size)?1:0) + ); + std::size_t slice_size = + std::min(range_size,connection_buffer_size); + typename boost::range_iterator::type + start = boost::begin(range) + , end = boost::end(range); + while (slice_size != 0) { + using boost::adaptors::sliced; + std::shared_ptr new_array = std::make_shared(); + boost::copy( + range | sliced(0,slice_size) + , new_array->begin() + ); + temporaries->push_back(new_array); + buffers->push_back(boost::asio::buffer(new_array->data(), slice_size)); + std::advance(start, slice_size); + range = boost::make_iterator_range(start, end); + range_size = boost::distance(range); + slice_size = std::min(range_size, connection_buffer_size); + } + + if (!buffers->empty()) { + write_vec_impl(*buffers, callback, temporaries, buffers); + } + } + + template + void write_vec_impl(ConstBufferSeq const & seq + ,Callback const & callback + ,shared_array_list temporaries + ,shared_buffers buffers) + { + lock_guard lock(headers_mutex); + if (error_encountered) + boost::throw_exception(boost::system::system_error(*error_encountered)); + + std::function callback_function = + callback; + + std::function continuation = boost::bind( + &async_server_connection::template write_vec_impl > + ,async_server_connection::shared_from_this() + ,seq, callback_function, temporaries, buffers + ); + + if (!headers_already_sent && !headers_in_progress) { + write_headers_only(continuation); + return; + } else if (headers_in_progress && !headers_already_sent) { + pending_actions.push_back(continuation); + return; + } + + boost::asio::async_write( + socket_ + ,seq + ,boost::bind( + &async_server_connection::handle_write + ,async_server_connection::shared_from_this() + ,callback_function + ,temporaries + ,buffers + ,boost::asio::placeholders::error + ,boost::asio::placeholders::bytes_transferred) + ); + } + }; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_CONNECTION_HPP_20101027 */ diff --git a/http/src/network/protocol/http/server/connection/sync.hpp b/http/src/network/protocol/http/server/connection/sync.hpp new file mode 100644 index 000000000..3b439a4d4 --- /dev/null +++ b/http/src/network/protocol/http/server/connection/sync.hpp @@ -0,0 +1,340 @@ +// Copyright 2009 (c) Dean Michael Berris +// Copyright 2009 (c) Tarroo, Inc. +// Adapted from Christopher Kholhoff's Boost.Asio Example, released under +// the Boost Software License, Version 1.0. (See acccompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ +#define NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ + +#ifndef NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE +#define NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 4096uL +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + +#ifndef NETWORK_NO_LIB + extern void parse_version(std::string const & partial_parsed, boost::fusion::tuple & version_pair); + extern void parse_headers(std::string const & input, std::vector > & container); +#endif + +class sync_server_connection : public boost::enable_shared_from_this { + public: + sync_server_connection(boost::asio::io_service & service, + std::function handler) + : service_(service) + , handler_(handler) + , socket_(service_) + , wrapper_(service_) + { + } + + boost::asio::ip::tcp::socket & socket() { + return socket_; + } + + void start() { + using boost::asio::ip::tcp; + boost::system::error_code option_error; + // TODO make no_delay an option in server_options. + socket_.set_option(tcp::no_delay(true), option_error); + std::ostringstream ip_stream; + ip_stream << socket_.remote_endpoint().address().to_string() << ':' + << socket_.remote_endpoint().port(); + request_.set_source(ip_stream.str()); + socket_.async_read_some( + boost::asio::buffer(read_buffer_), + wrapper_.wrap( + boost::bind( + &sync_server_connection::handle_read_data, + sync_server_connection::shared_from_this(), + method, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); + } + + private: + + enum state_t { + method, uri, version, headers, body + }; + + + void handle_read_data(state_t state, boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec) { + boost::logic::tribool parsed_ok; + boost::iterator_range result_range, input_range; + data_end = read_buffer_.begin(); + std::advance(data_end, bytes_transferred); + switch (state) { + case method: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser_.parse_until( + request_parser::method_done, input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + std::string method; + swap(partial_parsed, method); + method.append(boost::begin(result_range), + boost::end(result_range)); + boost::trim(method); + request_.set_method(method); + new_start = boost::end(result_range); + // Determine whether we're going to need to parse the body of the + // request. All we do is peek at the first character of the method + // to determine whether it's a POST or a PUT. + read_body_ = method.size() ? method[0] == 'P' : false; + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(method); + break; + } + case uri: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser_.parse_until( + request_parser::uri_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + std::string destination; + swap(partial_parsed, destination); + destination.append(boost::begin(result_range), + boost::end(result_range)); + boost::trim(destination); + request_.set_destination(destination); + new_start = boost::end(result_range); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(uri); + break; + } + case version: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser_.parse_until( + request_parser::version_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + boost::fusion::tuple version_pair; + partial_parsed.append(boost::begin(result_range), boost::end(result_range)); + parse_version(partial_parsed, version_pair); + request_.set_version_major(boost::fusion::get<0>(version_pair)); + request_.set_version_minor(boost::fusion::get<1>(version_pair)); + new_start = boost::end(result_range); + partial_parsed.clear(); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(version); + break; + } + case headers: + input_range = boost::make_iterator_range( + new_start, data_end); + boost::fusion::tie(parsed_ok, result_range) = parser_.parse_until( + request_parser::headers_done, + input_range); + if (!parsed_ok) { + client_error(); + break; + } else if (parsed_ok == true) { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + std::vector > headers; + parse_headers(partial_parsed, headers); + for (std::vector >::const_iterator it = headers.begin(); + it != headers.end(); + ++it) { + request_.append_header(it->first, it->second); + } + new_start = boost::end(result_range); + if (read_body_) { + } else { + response response_; + handler_(request_, response_); + flatten_response(); + std::vector response_buffers(output_buffers_.size()); + std::transform(output_buffers_.begin(), output_buffers_.end(), + response_buffers.begin(), + [](buffer_type const &buffer) { + return boost::asio::const_buffer(buffer.data(), buffer.size()); + }); + boost::asio::async_write( + socket_, + response_buffers, + wrapper_.wrap( + boost::bind( + &sync_server_connection::handle_write, + sync_server_connection::shared_from_this(), + boost::asio::placeholders::error))); + } + return; + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + new_start = read_buffer_.begin(); + read_more(headers); + break; + } + default: + BOOST_ASSERT(false && "This is a bug, report to the cpp-netlib devel mailing list!"); + std::abort(); + } + } else { + error_encountered = boost::in_place(ec); + } + } + + void handle_write(boost::system::error_code const &ec) { + // First thing we do is clear out the output buffers. + output_buffers_.clear(); + if (ec) { + // TODO maybe log the error here. + } + } + + void client_error() { + static char const bad_request[] = + "HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; + + boost::asio::async_write( + socket() + , boost::asio::buffer(bad_request, strlen(bad_request)) + , wrapper_.wrap( + boost::bind( + &sync_server_connection::client_error_sent + , sync_server_connection::shared_from_this() + , boost::asio::placeholders::error + , boost::asio::placeholders::bytes_transferred))); + } + + void client_error_sent(boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec) { + boost::system::error_code ignored; + socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); + socket().close(ignored); + } else { + error_encountered = boost::in_place(ec); + } + } + + void read_more(state_t state) { + socket_.async_read_some( + boost::asio::buffer(read_buffer_) + , wrapper_.wrap( + boost::bind( + &sync_server_connection::handle_read_data, + sync_server_connection::shared_from_this(), + state, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred + ) + ) + ); + } + + void flatten_response() { + uint16_t status = http::status(response_); + std::string status_message = http::status_message(response_); + headers_wrapper::container_type headers = network::headers(response_); + std::ostringstream status_line; + status_line << status << constants::space() << status_message << constants::space() + << constants::http_slash() + << "1.1" // TODO: make this a constant + << constants::crlf(); + segmented_write(status_line.str()); + std::ostringstream header_stream; + auto it = std::begin(headers), end = std::end(headers); + for (; it != end; ++it) { + const auto &header = *it; + //for (auto const &header : headers) { + header_stream << header.first << constants::colon() << constants::space() + << header.second << constants::crlf(); + } + header_stream << constants::crlf(); + segmented_write(header_stream.str()); + bool done = false; + while (!done) { + buffer_type buffer; + response_.get_body([&done, &buffer](std::string::const_iterator start, size_t length) { + if (!length) done = true; + else { + std::string::const_iterator past_end = start; + std::advance(past_end, length); + std::copy(start, past_end, buffer.begin()); + } + }, buffer.size()); + if (!done) output_buffers_.emplace_back(std::move(buffer)); + } + } + + void segmented_write(std::string data) { + while (!boost::empty(data)) { + buffer_type buffer; + auto end = std::copy_n(boost::begin(data), buffer.size(), buffer.begin()); + data.erase(0, std::distance(buffer.begin(), end)); + output_buffers_.emplace_back(std::move(buffer)); + } + } + + boost::asio::io_service & service_; + std::function handler_; + boost::asio::ip::tcp::socket socket_; + boost::asio::io_service::strand wrapper_; + + typedef boost::array buffer_type; + buffer_type read_buffer_; + buffer_type::iterator new_start, data_end; + request_parser parser_; + request request_; + response response_; + std::list output_buffers_; + std::string partial_parsed; + boost::optional error_encountered; + bool read_body_; +}; + + +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_SERVER_SYNC_CONNECTION_HPP_ diff --git a/boost/network/protocol/http/server/impl/parsers.ipp b/http/src/network/protocol/http/server/impl/parsers.ipp similarity index 65% rename from boost/network/protocol/http/server/impl/parsers.ipp rename to http/src/network/protocol/http/server/impl/parsers.ipp index e39c7b26d..0bbf358d7 100644 --- a/boost/network/protocol/http/server/impl/parsers.ipp +++ b/http/src/network/protocol/http/server/impl/parsers.ipp @@ -1,28 +1,30 @@ -#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 -#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 - -#include - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 +#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 + +#include + +#include +#include #include -#ifdef BOOST_NETWORK_NO_LIB -# ifndef BOOST_NETWORK_INLINE -# define BOOST_NETWORK_INLINE inline +#ifdef NETWORK_NO_LIB +# ifndef NETWORK_INLINE +# define NETWORK_INLINE inline # endif #else -# define BOOST_NETWORK_INLINE +# define NETWORK_INLINE #endif #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { - BOOST_NETWORK_INLINE void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { + NETWORK_INLINE void parse_version(std::string const & partial_parsed, boost::fusion::tuple & version_pair) { using namespace boost::spirit::qi; parse( partial_parsed.begin(), partial_parsed.end(), @@ -35,7 +37,7 @@ namespace boost { namespace network { namespace http { , version_pair); } - BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector & container) { + NETWORK_INLINE void parse_headers(std::string const & input, std::vector > & container) { using namespace boost::spirit::qi; parse( input.begin(), input.end(), @@ -50,10 +52,7 @@ namespace boost { namespace network { namespace http { ); } -} /* http */ - -} /* network */ +} // namespace http +} // namespace network -} /* boost */ - #endif /* SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 */ diff --git a/http/src/network/protocol/http/server/impl/socket_options_setter.hpp b/http/src/network/protocol/http/server/impl/socket_options_setter.hpp new file mode 100644 index 000000000..05121cf08 --- /dev/null +++ b/http/src/network/protocol/http/server/impl/socket_options_setter.hpp @@ -0,0 +1,25 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPIONS_SETTER_20120319 +#define NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPIONS_SETTER_20120319 + +#include + +namespace network { namespace http { + +class server_options; + +class socket_options_setter { + protected: + void set_socket_options(server_options const &options, boost::asio::ip::tcp::socket &socket); + void set_acceptor_options(server_options const &options, boost::asio::ip::tcp::acceptor &acceptor); +}; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPIONS_SETTER_20120319 diff --git a/http/src/network/protocol/http/server/impl/socket_options_setter.ipp b/http/src/network/protocol/http/server/impl/socket_options_setter.ipp new file mode 100644 index 000000000..6f0010726 --- /dev/null +++ b/http/src/network/protocol/http/server/impl/socket_options_setter.ipp @@ -0,0 +1,53 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPTIONS_SETTER_IPP_20120319 +#define NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPTIONS_SETTER_IPP_20120319 + +#include +#include + +namespace network { namespace http { + +void socket_options_setter::set_socket_options(server_options const & options, boost::asio::ip::tcp::socket &socket) { + boost::system::error_code ignored; + socket.non_blocking(options.non_blocking_io(), ignored); + if (options.linger()) { + boost::asio::ip::tcp::socket::linger linger(true, options.linger_timeout()); + socket.set_option(linger, ignored); + } + if (int buf_size = options.receive_buffer_size() >= 0) { + boost::asio::ip::tcp::socket::receive_buffer_size receive_buffer_size(buf_size); + socket.set_option(receive_buffer_size, ignored); + } + if (int buf_size = options.send_buffer_size() >= 0) { + boost::asio::ip::tcp::socket::send_buffer_size send_buffer_size(buf_size); + socket.set_option(send_buffer_size, ignored); + } + if (int buf_size = options.receive_low_watermark() >= 0) { + boost::asio::ip::tcp::socket::receive_low_watermark receive_low_watermark(buf_size); + socket.set_option(receive_low_watermark, ignored); + } + if (int buf_size = options.send_low_watermark() >= 0) { + boost::asio::ip::tcp::socket::send_low_watermark send_low_watermark(buf_size); + socket.set_option(send_low_watermark, ignored); + } +} + +void socket_options_setter::set_acceptor_options(server_options const &options, boost::asio::ip::tcp::acceptor &acceptor) { + boost::system::error_code ignored; + acceptor.set_option( + boost::asio::ip::tcp::acceptor::reuse_address(options.reuse_address()), + ignored); + acceptor.set_option( + boost::asio::ip::tcp::acceptor::enable_connection_aborted(options.report_aborted()), + ignored); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_IMPL_SOCKET_OPTIONS_SETTER_IPP_20120319 diff --git a/http/src/network/protocol/http/server/options.hpp b/http/src/network/protocol/http/server/options.hpp new file mode 100644 index 000000000..9cdc3499d --- /dev/null +++ b/http/src/network/protocol/http/server/options.hpp @@ -0,0 +1,82 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_HPP_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_HPP_20120318 + +#include + +namespace boost { namespace asio { + +class io_service; + +} // namespace asio + +} // namespace boost + +namespace network { namespace http { + +class server_options_pimpl; + +class server_options { + public: + server_options(); + server_options(server_options const &other); + void swap(server_options &other); + server_options& operator=(server_options rhs); + ~server_options(); + + server_options& address(std::string const &address); + std::string const address() const; + + server_options& port(std::string const &port); + std::string const port() const; + + server_options& io_service(boost::asio::io_service *service); + boost::asio::io_service *io_service() const; + + server_options& reuse_address(bool setting); + bool reuse_address() const; + + server_options& report_aborted(bool setting); + bool report_aborted() const; + + // Set the receive buffer size for a socket. -1 means just use the default. + server_options& receive_buffer_size(int buffer_size); + int receive_buffer_size() const; + + // Set the send buffer size for a socket. -1 means just use the default. + server_options& send_buffer_size(int buffer_size); + int send_buffer_size() const; + + // Set the receive low watermark for a socket. -1 means just use the default. + server_options& receive_low_watermark(int low_watermark); + int receive_low_watermark() const; + + // Set the send low watermark for a socket. -1 means just use the default. + server_options& send_low_watermark(int low_watermark); + int send_low_watermark() const; + + server_options& non_blocking_io(bool setting); + bool non_blocking_io() const; + + server_options& linger(bool setting); + bool linger() const; + + // Set the socket linger timeout. This is only relevant if linger is true + // (see linger above). -1 means just use the default. + server_options& linger_timeout(int setting); + int linger_timeout() const; + + private: + server_options_pimpl *pimpl_; +}; + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_HPP_20120318 diff --git a/http/src/network/protocol/http/server/options.ipp b/http/src/network/protocol/http/server/options.ipp new file mode 100644 index 000000000..bccba3983 --- /dev/null +++ b/http/src/network/protocol/http/server/options.ipp @@ -0,0 +1,290 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_IPP_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_IPP_20120318 + +#include +#include + +namespace network { namespace http { + +class server_options_pimpl { + public: + server_options_pimpl() + : address_("0.0.0.0") + , port_("80") + , io_service_(0) + , receive_buffer_size_(-1) + , send_buffer_size_(-1) + , receive_low_watermark_(-1) + , send_low_watermark_(-1) + , linger_timeout_(30) + , reuse_address_(false) + , report_aborted_(false) + , non_blocking_io_(true) + , linger_(false) + {} + + server_options_pimpl *clone() const { + return new server_options_pimpl(*this); + } + + void address(std::string const &address) { + address_ = address; + } + + std::string const address() const { + return address_; + } + + void port(std::string const &port) { + port_ = port; + } + + std::string const port() const { + return port_; + } + + void io_service(boost::asio::io_service *service) { + io_service_ = service; + } + + boost::asio::io_service *io_service() const { + return io_service_; + } + + void reuse_address(bool setting) { + reuse_address_ = setting; + } + + bool reuse_address() const { + return reuse_address_; + } + + void report_aborted(bool setting) { + report_aborted_ = setting; + } + + bool report_aborted() const { + return report_aborted_; + } + + void receive_buffer_size(int buffer_size) { + receive_buffer_size_ = buffer_size; + } + + int receive_buffer_size() const { + return receive_buffer_size_; + } + + void send_buffer_size(int buffer_size) { + send_buffer_size_ = buffer_size; + } + + int send_buffer_size() const { + return send_buffer_size_; + } + + void receive_low_watermark(int buffer_size) { + receive_low_watermark_ = buffer_size; + } + + int receive_low_watermark() const { + return receive_low_watermark_; + } + + void send_low_watermark(int buffer_size) { + send_low_watermark_ = buffer_size; + } + + int send_low_watermark() const { + return send_low_watermark_; + } + + void non_blocking_io(bool setting) { + non_blocking_io_ = setting; + } + + bool non_blocking_io() const { + return non_blocking_io_; + } + + void linger(bool setting) { + linger_ = setting; + } + + bool linger() const { + return linger_; + } + + void linger_timeout(int setting) { + linger_timeout_ = setting; + } + + int linger_timeout() const { + return linger_timeout_; + } + + private: + std::string address_, port_; + boost::asio::io_service *io_service_; + int receive_buffer_size_, send_buffer_size_, + receive_low_watermark_, send_low_watermark_, + linger_timeout_; + bool reuse_address_, report_aborted_, + non_blocking_io_, linger_; + + server_options_pimpl(server_options_pimpl const &other) + : address_(other.address_) + , port_(other.port_) + , io_service_(other.io_service_) + , receive_buffer_size_(other.receive_buffer_size_) + , send_buffer_size_(other.send_buffer_size_) + , receive_low_watermark_(other.receive_low_watermark_) + , send_low_watermark_(other.send_low_watermark_) + , linger_timeout_(other.linger_timeout_) + , reuse_address_(other.reuse_address_) + , report_aborted_(other.report_aborted_) + , non_blocking_io_(other.non_blocking_io_) + , linger_(other.linger_) {} + +}; + +server_options::server_options() +: pimpl_(new (std::nothrow) server_options_pimpl) +{} + +server_options::server_options(server_options const &other) +: pimpl_(other.pimpl_->clone()) +{} + +server_options::~server_options() { + delete pimpl_; +} + +void server_options::swap(server_options &other) { + std::swap(other.pimpl_, this->pimpl_); +} + +server_options& server_options::operator=(server_options other) { + other.swap(*this); + return *this; +} + +server_options& server_options::address(std::string const &address) { + pimpl_->address(address); + return *this; +} + +std::string const server_options::address() const { + return pimpl_->address(); +} + +server_options& server_options::port(std::string const &port) { + pimpl_->port(port); + return *this; +} + +std::string const server_options::port() const { + return pimpl_->port(); +} + +server_options& server_options::io_service(boost::asio::io_service *io_service) { + pimpl_->io_service(io_service); + return *this; +} + +boost::asio::io_service* server_options::io_service() const { + return pimpl_->io_service(); +} + +server_options& server_options::non_blocking_io(bool setting) { + pimpl_->non_blocking_io(setting); + return *this; +} + +bool server_options::non_blocking_io() const { + return pimpl_->non_blocking_io(); +} + +server_options& server_options::reuse_address(bool setting) { + pimpl_->reuse_address(setting); + return *this; +} + +bool server_options::reuse_address() const { + return pimpl_->reuse_address(); +} + +server_options& server_options::report_aborted(bool setting) { + pimpl_->report_aborted(setting); + return *this; +} + +bool server_options::report_aborted() const { + return pimpl_->report_aborted(); +} + +server_options& server_options::receive_buffer_size(int buffer_size) { + pimpl_->receive_buffer_size(buffer_size); + return *this; +} + +int server_options::receive_buffer_size() const { + return pimpl_->receive_buffer_size(); +} + +server_options& server_options::send_buffer_size(int buffer_size) { + pimpl_->send_buffer_size(buffer_size); + return *this; +} + +int server_options::send_buffer_size() const { + return pimpl_->send_buffer_size(); +} + +server_options& server_options::receive_low_watermark(int buffer_size) { + pimpl_->receive_low_watermark(buffer_size); + return *this; +} + +int server_options::receive_low_watermark() const { + return pimpl_->receive_low_watermark(); +} + +server_options& server_options::send_low_watermark(int buffer_size) { + pimpl_->send_low_watermark(buffer_size); + return *this; +} + +int server_options::send_low_watermark() const { + return pimpl_->send_low_watermark(); +} + +server_options& server_options::linger(bool setting) { + pimpl_->linger(setting); + return *this; +} + +bool server_options::linger() const { + return pimpl_->linger(); +} + +server_options& server_options::linger_timeout(int buffer_size) { + pimpl_->linger_timeout(buffer_size); + return *this; +} + +int server_options::linger_timeout() const { + return pimpl_->linger_timeout(); +} + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_OPTIONS_IPP_20120318 diff --git a/boost/network/protocol/http/server/parameters.hpp b/http/src/network/protocol/http/server/parameters.hpp similarity index 66% rename from boost/network/protocol/http/server/parameters.hpp rename to http/src/network/protocol/http/server/parameters.hpp index 06b59b174..1400e743e 100644 --- a/boost/network/protocol/http/server/parameters.hpp +++ b/http/src/network/protocol/http/server/parameters.hpp @@ -1,14 +1,15 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 + +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { BOOST_PARAMETER_NAME(address) BOOST_PARAMETER_NAME(port) @@ -25,10 +26,7 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(linger) BOOST_PARAMETER_NAME(linger_timeout) -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/request.hpp b/http/src/network/protocol/http/server/request.hpp similarity index 79% rename from boost/network/protocol/http/server/request.hpp rename to http/src/network/protocol/http/server/request.hpp index c5fed5deb..e07910140 100644 --- a/boost/network/protocol/http/server/request.hpp +++ b/http/src/network/protocol/http/server/request.hpp @@ -3,22 +3,23 @@ // ~~~~~~~~~~~ // // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) +// Copyright (c) 2009 Dean Michael Berris (dberris@google.com) // Copyright (c) 2009 Tarro, Inc. // +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef BOOST_NETWORK_HTTP_REQUEST_HPP -#define BOOST_NETWORK_HTTP_REQUEST_HPP +#ifndef NETWORK_HTTP_REQUEST_HPP +#define NETWORK_HTTP_REQUEST_HPP #include #include #include #include "header.hpp" -namespace boost { namespace network { namespace http { +namespace network { namespace http { /// A request received from a client. struct request @@ -42,10 +43,7 @@ namespace boost { namespace network { namespace http { } } // namespace http - } // namespace network -} // namespace boost - -#endif // BOOST_NETWORK_HTTP_REQUEST_HPP +#endif // NETWORK_HTTP_REQUEST_HPP diff --git a/boost/network/protocol/http/server/request_parser.hpp b/http/src/network/protocol/http/server/request_parser.hpp similarity index 74% rename from boost/network/protocol/http/server/request_parser.hpp rename to http/src/network/protocol/http/server/request_parser.hpp index bb6421b66..34093e265 100644 --- a/boost/network/protocol/http/server/request_parser.hpp +++ b/http/src/network/protocol/http/server/request_parser.hpp @@ -1,20 +1,20 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 +#define NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 + #include #include #include #include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { - template struct request_parser { enum state_t { @@ -53,14 +53,14 @@ namespace boost { namespace network { namespace http { state_t state() const { return internal_state; } template - fusion::tuple > + boost::fusion::tuple > parse_until(state_t stop_state, Range & range) { - logic::tribool parsed_ok = logic::indeterminate; - typedef typename range_iterator::type iterator; + boost::logic::tribool parsed_ok = boost::logic::indeterminate; + typedef typename boost::range_iterator::type iterator; iterator start = boost::begin(range) , end = boost::end(range) , current_iterator = start; - iterator_range local_range = + boost::iterator_range local_range = boost::make_iterator_range(start, end); while ( !boost::empty(local_range) @@ -70,22 +70,22 @@ namespace boost { namespace network { namespace http { current_iterator = boost::begin(local_range); switch(internal_state) { case method_start: - if (algorithm::is_upper()(*current_iterator)) internal_state = method_char; + if (boost::algorithm::is_upper()(*current_iterator)) internal_state = method_char; else parsed_ok = false; break; case method_char: - if (algorithm::is_upper()(*current_iterator)) break; - else if (algorithm::is_space()(*current_iterator)) internal_state = method_done; + if (boost::algorithm::is_upper()(*current_iterator)) break; + else if (boost::algorithm::is_space()(*current_iterator)) internal_state = method_done; else parsed_ok = false; break; case method_done: - if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; - else if (algorithm::is_space()(*current_iterator)) parsed_ok = false; + if (boost::algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; + else if (boost::algorithm::is_space()(*current_iterator)) parsed_ok = false; else internal_state = uri_char; break; case uri_char: - if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; - else if (algorithm::is_space()(*current_iterator)) internal_state = uri_done; + if (boost::algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; + else if (boost::algorithm::is_space()(*current_iterator)) internal_state = uri_done; break; case uri_done: if (*current_iterator == 'H') internal_state = version_h; @@ -108,7 +108,7 @@ namespace boost { namespace network { namespace http { else parsed_ok = false; break; case version_slash: - if (algorithm::is_digit()(*current_iterator)) internal_state = version_d1; + if (boost::algorithm::is_digit()(*current_iterator)) internal_state = version_d1; else parsed_ok = false; break; case version_d1: @@ -116,7 +116,7 @@ namespace boost { namespace network { namespace http { else parsed_ok = false; break; case version_dot: - if (algorithm::is_digit()(*current_iterator)) internal_state = version_d2; + if (boost::algorithm::is_digit()(*current_iterator)) internal_state = version_d2; else parsed_ok = false; break; case version_d2: @@ -128,13 +128,13 @@ namespace boost { namespace network { namespace http { else parsed_ok = false; break; case version_done: - if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name; + if (boost::algorithm::is_alnum()(*current_iterator)) internal_state = header_name; else if (*current_iterator == '\r') internal_state = headers_cr; else parsed_ok = false; break; case header_name: if (*current_iterator == ':') internal_state = header_colon; - else if (algorithm::is_alnum()(*current_iterator) || algorithm::is_punct()(*current_iterator)) break; + else if (boost::algorithm::is_alnum()(*current_iterator) || boost::algorithm::is_punct()(*current_iterator)) break; else parsed_ok = false; break; case header_colon: @@ -143,7 +143,7 @@ namespace boost { namespace network { namespace http { break; case header_value: if (*current_iterator == '\r') internal_state = header_cr; - else if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; + else if (boost::algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; break; case header_cr: if (*current_iterator == '\n') internal_state = header_line_done; @@ -151,7 +151,7 @@ namespace boost { namespace network { namespace http { break; case header_line_done: if (*current_iterator == '\r') internal_state = headers_cr; - else if (algorithm::is_alnum()(*current_iterator)) internal_state = header_name; + else if (boost::algorithm::is_alnum()(*current_iterator)) internal_state = header_name; else parsed_ok = false; break; case headers_cr: @@ -168,7 +168,7 @@ namespace boost { namespace network { namespace http { local_range = boost::make_iterator_range( ++current_iterator, end); } - return fusion::make_tuple( + return boost::fusion::make_tuple( parsed_ok, boost::make_iterator_range( start, current_iterator @@ -181,10 +181,7 @@ namespace boost { namespace network { namespace http { }; -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 */ diff --git a/http/src/network/protocol/http/server/server.ipp b/http/src/network/protocol/http/server/server.ipp new file mode 100644 index 000000000..d4c8ece06 --- /dev/null +++ b/http/src/network/protocol/http/server/server.ipp @@ -0,0 +1,70 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_SERVER_IPP_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_SERVER_IPP_20120318 + +#include +#include +#include + +namespace network { namespace http { + +template +sync_server::sync_server(server_options const &options, SyncHandler &handler) +: pimpl_(new sync_server_impl(options, handler)) +{} + +template +void sync_server::run() { + pimpl_->run(); +} + +template +void sync_server::stop() { + pimpl_->stop(); +} + +template +void sync_server::listen() { + pimpl_->listen(); +} + +template +sync_server::~sync_server() { + delete pimpl_; +} + +template +async_server::async_server(server_options const &options, AsyncHandler &handler, utils::thread_pool &pool) +: pimpl_(new async_server_impl(options, handler, pool)) +{} + +template +void async_server::run() { + pimpl_->run(); +} + +template +void async_server::stop() { + pimpl_->stop(); +} + +template +void async_server::listen() { + pimpl_->listen(); +} + +template +async_server::~async_server() { + delete pimpl_; +} + +} // namespace http + +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_SERVER_IPP_20120318 diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/http/src/network/protocol/http/server/socket_options_base.hpp similarity index 83% rename from boost/network/protocol/http/server/socket_options_base.hpp rename to http/src/network/protocol/http/server/socket_options_base.hpp index 0563272a6..82c5309f6 100644 --- a/boost/network/protocol/http/server/socket_options_base.hpp +++ b/http/src/network/protocol/http/server/socket_options_base.hpp @@ -1,16 +1,17 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 + +#include #include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { struct socket_options_base { protected: @@ -36,13 +37,13 @@ namespace boost { namespace network { namespace http { set_optional(send_low_watermark, args, _send_low_watermark); } - void acceptor_options(boost::asio::ip::tcp::acceptor & acceptor) { + void acceptor_options(asio::ip::tcp::acceptor & acceptor) { acceptor.set_option(acceptor_reuse_address); acceptor.set_option(acceptor_report_aborted); } - void socket_options(boost::asio::ip::tcp::socket & socket) { - boost::system::error_code ignored; + void socket_options(asio::ip::tcp::socket & socket) { + asio::error_code ignored; socket.io_control(non_blocking_io, ignored); socket.set_option(linger, ignored); if (receive_buffer_size) socket.set_option(*receive_buffer_size, ignored); @@ -81,10 +82,8 @@ namespace boost { namespace network { namespace http { }; -} /* http */ +} // namespace http -} /* network */ +} // namespace network -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/storage_base.hpp b/http/src/network/protocol/http/server/storage_base.hpp similarity index 66% rename from boost/network/protocol/http/server/storage_base.hpp rename to http/src/network/protocol/http/server/storage_base.hpp index ccfe3fd12..6151070f8 100644 --- a/boost/network/protocol/http/server/storage_base.hpp +++ b/http/src/network/protocol/http/server/storage_base.hpp @@ -1,14 +1,15 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 + +#include -namespace boost { namespace network { namespace http { +namespace network { namespace http { struct server_storage_base { struct no_io_service {}; @@ -16,7 +17,7 @@ namespace boost { namespace network { namespace http { protected: template server_storage_base(ArgPack const & /* args */, no_io_service) - : self_service_(new boost::asio::io_service()) + : self_service_(new asio::io_service()) , service_(*self_service_) {} @@ -36,10 +37,8 @@ namespace boost { namespace network { namespace http { }; -} /* http */ +} // namespace http -} /* network */ +} // namespace network -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 */ diff --git a/http/src/network/protocol/http/server/sync_impl.hpp b/http/src/network/protocol/http/server/sync_impl.hpp new file mode 100644 index 000000000..07195c82b --- /dev/null +++ b/http/src/network/protocol/http/server/sync_impl.hpp @@ -0,0 +1,49 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_IMPL_HPP_20120318 +#define NETWORK_PROTOCOL_HTTP_SERVER_IMPL_HPP_20120318 + +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace http { + +class sync_server_connection; +struct request; +struct response; + +class sync_server_impl : protected socket_options_setter { + public: + sync_server_impl(server_options const &options, + std::function handler); + void run(); + void stop(); + void listen(); + + private: + server_options options_; + std::string address_, port_; + boost::asio::io_service *service_; + boost::asio::ip::tcp::acceptor *acceptor_; + std::shared_ptr new_connection_; + std::mutex listening_mutex_; + bool listening_, owned_service_; + std::function handler_; + + void start_listening(); + void handle_accept(boost::system::error_code const &ec); +}; + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_IMPL_HPP_20120318 diff --git a/http/src/network/protocol/http/server/sync_impl.ipp b/http/src/network/protocol/http/server/sync_impl.ipp new file mode 100644 index 000000000..467e5fac6 --- /dev/null +++ b/http/src/network/protocol/http/server/sync_impl.ipp @@ -0,0 +1,106 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_SYNC_IMPL_IPP_20120319 +#define NETWORK_PROTOCOL_HTTP_SERVER_SYNC_IMPL_IPP_20120319 + +#include +#include +#include +#include + +namespace network { namespace http { + +sync_server_impl::sync_server_impl(server_options const &options, + std::function handler) +: options_(options) +, address_(options.address()) +, port_(options.port()) +, service_(options.io_service()) +, acceptor_(0) +, new_connection_() +, listening_mutex_() +, listening_(false) +, owned_service_(false) { + if (service_ == 0) { + service_ = new boost::asio::io_service; + owned_service_ = true; + BOOST_ASSERT(service_ != 0); + } + acceptor_ = new boost::asio::ip::tcp::acceptor(*service_); + BOOST_ASSERT(acceptor_ != 0); +} + +void sync_server_impl::run() { + listen(); + service_->run(); +} + +void sync_server_impl::stop() { + boost::system::error_code ignored; + acceptor_->close(ignored); + service_->stop(); +} + +void sync_server_impl::listen() { + std::lock_guard listening_lock(listening_mutex_); + if (!listening_) start_listening(); +} + +void sync_server_impl::handle_accept(boost::system::error_code const &ec) { + if (!ec) { + set_socket_options(options_, new_connection_->socket()); + new_connection_->start(); + new_connection_.reset(new sync_server_connection(*service_, handler_)); + acceptor_->async_accept(new_connection_->socket(), + boost::bind(&sync_server_impl::handle_accept, + this, + boost::asio::placeholders::error)); + } else { + NETWORK_MESSAGE("error accepting connection: " << ec); + this->stop(); + } +} + +void sync_server_impl::start_listening() { + using boost::asio::ip::tcp; + boost::system::error_code error; + tcp::resolver resolver(*service_); + tcp::resolver::query query(address_, port_); + tcp::resolver::iterator endpoint_ = resolver.resolve(query, error); + if (error) { + NETWORK_MESSAGE("error resolving address: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + BOOST_THROW_EXCEPTION(std::runtime_error("Error resolving provided address:port combination.")); + } + tcp::endpoint endpoint = *endpoint_; + acceptor_->open(endpoint.protocol(), error); + if (error) { + NETWORK_MESSAGE("error opening socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + BOOST_THROW_EXCEPTION(std::runtime_error("Error opening socket for acceptor.")); + } + set_acceptor_options(options_, *acceptor_); + acceptor_->bind(endpoint, error); + if (error) { + NETWORK_MESSAGE("error boost::binding to socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + BOOST_THROW_EXCEPTION(std::runtime_error("Error boost::binding to socket for acceptor.")); + } + acceptor_->listen(tcp::socket::max_connections, error); + if (error) { + NETWORK_MESSAGE("error listening on socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + BOOST_THROW_EXCEPTION(std::runtime_error("Error listening on socket for acceptor.")); + } + new_connection_.reset(new sync_server_connection(*service_, handler_)); + acceptor_->async_accept(new_connection_->socket(), + boost::bind(&sync_server_impl::handle_accept, + this, + boost::asio::placeholders::error)); + listening_ = true; +} + +} // namespace http +} // namespace network + +#endif // NETWORK_PROTOCOL_HTTP_SERVER_SYNC_IMPL_IPP_20120319 diff --git a/boost/network/protocol/http/server/sync_server.hpp b/http/src/network/protocol/http/server/sync_server.hpp similarity index 65% rename from boost/network/protocol/http/server/sync_server.hpp rename to http/src/network/protocol/http/server/sync_server.hpp index 71619bce3..6aeb83cac 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/http/src/network/protocol/http/server/sync_server.hpp @@ -1,27 +1,27 @@ - // Copyright 2010 Dean Michael Berris. // Copyright 2010 Glyn Matthews. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 +#ifndef NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 +#define NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 -#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct sync_server_base : server_storage_base, socket_options_base { @@ -72,61 +72,58 @@ namespace boost { namespace network { namespace http { Handler & handler_; string_type address_, port_; - boost::asio::ip::tcp::acceptor acceptor_; + asio::ip::tcp::acceptor acceptor_; boost::shared_ptr > new_connection; boost::mutex listening_mutex_; bool listening_; - void handle_accept(boost::system::error_code const & ec) { + void handle_accept(asio::error_code const & ec) { if (!ec) { socket_options_base::socket_options(new_connection->socket()); new_connection->start(); new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept(new_connection->socket(), - boost::bind(&sync_server_base::handle_accept, - this, boost::asio::placeholders::error)); + std::bind(&sync_server_base::handle_accept, + this, asio::placeholders::error)); } } void start_listening() { - using boost::asio::ip::tcp; + using asio::ip::tcp; system::error_code error; tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); if (error) { - BOOST_NETWORK_MESSAGE("Error resolving address: " << address_ << ':' << port_); + NETWORK_MESSAGE("Error resolving address: " << address_ << ':' << port_); return; } tcp::endpoint endpoint = *endpoint_iterator; acceptor_.open(endpoint.protocol(), error); if (error) { - BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + NETWORK_MESSAGE("Error opening socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); return; } socket_options_base::acceptor_options(acceptor_); acceptor_.bind(endpoint, error); if (error) { - BOOST_NETWORK_MESSAGE("Error binding to socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + NETWORK_MESSAGE("Error binding to socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); return; } acceptor_.listen(tcp::socket::max_connections, error); if (error) { - BOOST_NETWORK_MESSAGE("Error listening on socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); + NETWORK_MESSAGE("Error listening on socket: " << address_ << ':' << port_ << " -- reason: '" << error << '\''); return; } new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept(new_connection->socket(), - boost::bind(&sync_server_base::handle_accept, - this, boost::asio::placeholders::error)); + std::bind(&sync_server_base::handle_accept, + this, asio::placeholders::error)); listening_ = true; } }; -} /* http */ - -} /* network */ +} // namespace http +} // namespace network -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ diff --git a/boost/network/protocol/http/support/client_or_server.hpp b/http/src/network/protocol/http/support/client_or_server.hpp similarity index 61% rename from boost/network/protocol/http/support/client_or_server.hpp rename to http/src/network/protocol/http/support/client_or_server.hpp index 2ad74b105..83596167d 100644 --- a/boost/network/protocol/http/support/client_or_server.hpp +++ b/http/src/network/protocol/http/support/client_or_server.hpp @@ -1,16 +1,17 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 -#define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#ifndef NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 +#define NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 + +#include +#include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct unsupported_tag; @@ -33,10 +34,7 @@ namespace boost { namespace network { namespace http { typedef tags::client type; }; -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 */ +#endif /* NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 */ diff --git a/boost/network/protocol/http/support/is_client.hpp b/http/src/network/protocol/http/support/is_client.hpp similarity index 57% rename from boost/network/protocol/http/support/is_client.hpp rename to http/src/network/protocol/http/support/is_client.hpp index e15b89603..d31f147b1 100644 --- a/boost/network/protocol/http/support/is_client.hpp +++ b/http/src/network/protocol/http/support/is_client.hpp @@ -1,15 +1,15 @@ -#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 -#define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 - // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 +#define NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 + #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct is_client : mpl::false_ {}; @@ -17,11 +17,8 @@ namespace boost { namespace network { namespace http { template struct is_client::type> : mpl::true_ {}; -} /* http */ +} // namespace http +} // namespace network -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 */ +#endif /* NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 */ diff --git a/boost/network/support/is_http.hpp b/http/src/network/protocol/http/support/is_http.hpp similarity index 63% rename from boost/network/support/is_http.hpp rename to http/src/network/protocol/http/support/is_http.hpp index c104e7b42..78f6d77ee 100644 --- a/boost/network/support/is_http.hpp +++ b/http/src/network/protocol/http/support/is_http.hpp @@ -1,15 +1,16 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 -#define BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 - // Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_SUPPORT_IS_HTTP_HPP_20100622 +#define NETWORK_SUPPORT_IS_HTTP_HPP_20100622 + +#include #include -namespace boost { namespace network { +namespace network { namespace http { template struct is_http : mpl::false_ {}; @@ -17,8 +18,8 @@ namespace boost { namespace network { template struct is_http::type> : mpl::true_ {}; -} // namespace network +} // namespace http -} // namespace boost +} // namespace network -#endif // BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 +#endif // NETWORK_SUPPORT_IS_HTTP_HPP_20100622 diff --git a/boost/network/protocol/http/support/is_keepalive.hpp b/http/src/network/protocol/http/support/is_keepalive.hpp similarity index 62% rename from boost/network/protocol/http/support/is_keepalive.hpp rename to http/src/network/protocol/http/support/is_keepalive.hpp index c3fa73a07..ce27abb51 100644 --- a/boost/network/protocol/http/support/is_keepalive.hpp +++ b/http/src/network/protocol/http/support/is_keepalive.hpp @@ -1,15 +1,16 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 -#define BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 - // Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#ifndef NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 +#define NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 + +#include #include -namespace boost { namespace network { namespace http { +namespace network { namespace http { template struct unsupported_tag; @@ -20,10 +21,8 @@ namespace boost { namespace network { namespace http { template struct is_keepalive::type> : mpl::true_ {}; -} /* http */ +} // namespace http -} /* network */ +} // namespace network -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ +#endif /* NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ diff --git a/http/src/network/protocol/http/support/is_server.hpp b/http/src/network/protocol/http/support/is_server.hpp new file mode 100644 index 000000000..519dd53c2 --- /dev/null +++ b/http/src/network/protocol/http/support/is_server.hpp @@ -0,0 +1,24 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 +#define NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 + +#include + +namespace network { namespace http { + + template + struct is_server : boost::mpl::false_ {}; + + template + struct is_server::type> : boost::mpl::true_ {}; + +} // namespace http + +} // namespace network + +#endif /* NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 */ diff --git a/boost/network/support/is_simple.hpp b/http/src/network/protocol/http/support/is_simple.hpp similarity index 60% rename from boost/network/support/is_simple.hpp rename to http/src/network/protocol/http/support/is_simple.hpp index 98406d41a..e27f3c110 100644 --- a/boost/network/support/is_simple.hpp +++ b/http/src/network/protocol/http/support/is_simple.hpp @@ -1,24 +1,25 @@ -#ifndef BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 -#define BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 - // Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include +#ifndef NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 +#define NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 -namespace boost { namespace network { +#include +#include +namespace network { namespace http { + template struct is_simple : mpl::false_ {}; template struct is_simple::type> : mpl::true_ {}; -} /* network */ - -} /* boost */ +} // namespace http -#endif /* BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ +} // namespace network + +#endif /* NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ diff --git a/http/src/network/protocol/http/support/sync_only.hpp b/http/src/network/protocol/http/support/sync_only.hpp new file mode 100644 index 000000000..275cc0ab8 --- /dev/null +++ b/http/src/network/protocol/http/support/sync_only.hpp @@ -0,0 +1,31 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 +#define NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 + +#include +#include + +namespace network { namespace http { + + template + struct sync_only : + mpl::inherit_linearly< + typename mpl::replace_if< + typename tags::components::type, + is_same, + tags::sync + >::type + , mpl::inherit + > + {}; + +} // namespace http + +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_SUPPORT_SYNC_ONLY_HPP_20100927 */ diff --git a/http/src/network/version.hpp b/http/src/network/version.hpp new file mode 100644 index 000000000..55f256501 --- /dev/null +++ b/http/src/network/version.hpp @@ -0,0 +1,23 @@ +// Copyright Dean Michael Berris 2009. +// Copyright Glyn Matthews 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_VERSION_HPP_20091214 +#define NETWORK_VERSION_HPP_20091214 + +#include + +#define NETLIB_VERSION_MAJOR 1 +#define NETLIB_VERSION_MINOR 0 +#define NETLIB_VERSION_INCREMENT 0a + +#ifndef NETLIB_VERSION +#define NETLIB_VERSION \ + BOOST_STRINGIZE(NETLIB_VERSION_MAJOR) "." \ + BOOST_STRINGIZE(NETLIB_VERSION_MINOR) "." \ + BOOST_STRINGIZE(NETLIB_VERSION_INCREMENT) +#endif // NETLIB_VERSION +#endif // NETWORK_VERSION_HPP_20091214 diff --git a/libs/network/src/server_request_parsers_impl.cpp b/http/src/server_request_parsers_impl.cpp similarity index 60% rename from libs/network/src/server_request_parsers_impl.cpp rename to http/src/server_request_parsers_impl.cpp index 91dfafb77..b694aea6e 100644 --- a/libs/network/src/server_request_parsers_impl.cpp +++ b/http/src/server_request_parsers_impl.cpp @@ -1,11 +1,12 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifdef BOOST_NETWORK_NO_LIB -#undef BOOST_NETWORK_NO_LIB +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB #endif -#include +#include diff --git a/http/test/CMakeLists.txt b/http/test/CMakeLists.txt new file mode 100644 index 000000000..c0fa2920b --- /dev/null +++ b/http/test/CMakeLists.txt @@ -0,0 +1,130 @@ +# Copyright 2010 Dean Michael Berris. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories( + ${CPP-NETLIB_SOURCE_DIR}/uri/src + ${CPP-NETLIB_SOURCE_DIR}/message/src + ${CPP-NETLIB_SOURCE_DIR}/logging/src + ${CPP-NETLIB_SOURCE_DIR}/http/src + ${CPP-NETLIB_SOURCE_DIR}) + +if (OPENSSL_FOUND) + include_directories( ${OPENSSL_INCLUDE_DIR} ) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + +if( NOT CPP-NETLIB_DISABLE_LOGGING ) + set( CPP-NETLIB_LOGGING_LIB cppnetlib-logging ) +endif() + + # this library name is defined only if we created the target + # if not then it will be empty + set( CPP-NETLIB_LOGGING_LIB cppnetlib-logging ) + +if (Boost_FOUND) + # These are the internal (simple) tests. + set ( MESSAGE_TESTS + request_base_test + request_test + request_linearize_test + response_test + ) + foreach ( test ${MESSAGE_TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-${test} ${test}.cpp) + add_dependencies(cpp-netlib-http-${test} + cppnetlib-message + cppnetlib-message-wrappers + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-uri + cppnetlib-constants + ) + target_link_libraries(cpp-netlib-http-${test} + ${Boost_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-message + cppnetlib-message-wrappers + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-uri + cppnetlib-constants + ) + set_target_properties(cpp-netlib-http-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + endforeach(test) + + set ( TESTS + client_constructor_test + client_get_test + client_get_different_port_test + client_get_timeout_test + client_get_streaming_test + ) + foreach ( test ${TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-${test} + ${Boost_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-constants + cppnetlib-uri + cppnetlib-message + cppnetlib-message-wrappers + cppnetlib-message-directives + ${CPP-NETLIB_LOGGING_LIB} + cppnetlib-http-message + cppnetlib-http-message-wrappers + cppnetlib-http-client + cppnetlib-http-client-connections) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-http-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + endforeach (test) + + #set ( SERVER_API_TESTS + # server_constructor_test + # server_async_run_stop_concurrency + # ) + #foreach ( test ${SERVER_API_TESTS} ) + # if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + # set_source_files_properties(${test}.cpp + # PROPERTIES COMPILE_FLAGS "-Wall") + # endif() + # add_executable(cpp-netlib-http-${test} ${test}.cpp) + # target_link_libraries(cpp-netlib-http-${test} + # ${Boost_LIBRARIES} + # ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + # ${CMAKE_THREAD_LIBS_INIT} + # cppnetlib-constants + # cppnetlib-uri + # cppnetlib-message + # cppnetlib-message-wrappers + # cppnetlib-http-message + # cppnetlib-http-server + # cppnetlib-http-server-parsers + # cppnetlib-utils-thread_pool + # ) + # set_target_properties(cpp-netlib-http-${test} + # PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + # add_test(cpp-netlib-http-${test} + # ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + #endforeach (test) + +endif() diff --git a/http/test/Jamfile.v2 b/http/test/Jamfile.v2 new file mode 100644 index 000000000..c299afce5 --- /dev/null +++ b/http/test/Jamfile.v2 @@ -0,0 +1,138 @@ + +# Copyright 2011 Dean Michael Berris. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import testing ; +import modules ; +import feature ; + +project network_test/http : + requirements + debug:NETWORK_DEBUG + gcc:-std=c++0x + ; + +run request_base_test.cpp /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-constants ; + +run request_test.cpp /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-constants ; + +run request_linearize_test.cpp /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-constants ; + +run response_test.cpp /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-constants ; + +run client_constructor_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-message-directives + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-http-client + /cpp-netlib//cppnetlib-http-client-connections ; + +run client_get_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-message-directives + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-http-client + /cpp-netlib//cppnetlib-http-client-connections ; + +run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-message-directives + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-http-client + /cpp-netlib//cppnetlib-http-client-connections ; + +run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-message-directives + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-http-client + /cpp-netlib//cppnetlib-http-client-connections ; + +run client_get_streaming_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-message-directives + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-message-wrappers + /cpp-netlib//cppnetlib-http-client + /cpp-netlib//cppnetlib-http-client-connections ; + +run server_constructor_test.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-server + /cpp-netlib//cppnetlib-http-server-parsers + /cpp-netlib//cppnetlib-utils-thread_pool ; + +run server_async_run_stop_concurrency.cpp /cpp-netlib//cppnetlib-constants + /cpp-netlib//cppnetlib-uri + /cpp-netlib//cppnetlib-message + /cpp-netlib//cppnetlib-message-wrappers + /cpp-netlib//cppnetlib-http-message + /cpp-netlib//cppnetlib-http-server + /cpp-netlib//cppnetlib-http-server-parsers + /cpp-netlib//cppnetlib-utils-thread_pool ; + +#run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-http-client-connections ; +#run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-http-client-connections ; +#run message_async_ready_test.cpp ; +#run message_test.cpp /cpp-netlib//cppnetlib-uri ; +#run request_incremental_parser_test.cpp ; +#run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; +#run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-http-server-parsers ; +#run server_constructor_test.cpp /cpp-netlib//cppnetlib-http-server-parsers ; +#run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; + +#exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-http-server-parsers ; +#exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-http-server-parsers ; +#exe http_async_less_copy_server : server_async_less_copy.cpp /cpp-netlib//cppnetlib-http-server-parsers ; +#exe http_async_run_stop_concurrency_server : server_async_run_stop_concurrency.cpp /cpp-netlib//cppnetlib-http-server-parsers ; + +#make httplib_acceptance.passed : ../httplib_acceptance.py hello_world : @httplib_acceptance ; +#make httplib_async_acceptance.passed : ../httplib_acceptance.py http_async_server : @httplib_acceptance ; +#make httplib_async_less_copy_acceptance.passed : ../httplib_acceptance.py http_async_less_copy_server : @httplib_acceptance ; +#make httplib_async_run_stop_concurrency_acceptance.passed : ../httplib_acceptance.py http_async_run_stop_concurrency_server : @httplib_acceptance ; + +actions httplib_acceptance { + export TEST_SCRIPT=`echo "$(>)" | awk '{print $1}'` + export EXECUTABLE=`echo "$(>)" | awk '{print $2}'` + export PORT=`echo "import random; print random.randint(8000, 8010)" | python` + python $TEST_SCRIPT $EXECUTABLE $PORT $(<) +} diff --git a/http/test/client_constructor_test.cpp b/http/test/client_constructor_test.cpp new file mode 100644 index 000000000..e1f789cee --- /dev/null +++ b/http/test/client_constructor_test.cpp @@ -0,0 +1,32 @@ + +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP 1.0 Client Constructor Test +#include +#include + +namespace http = network::http; + +BOOST_AUTO_TEST_CASE(http_client_constructor_test) { + // Here's the simplest way to construct a client. + http::client instance; + + // The next way we're supporting is actually to construct an options object + // that allows you to set options. This class replaces the Boost.Parameter + // based approach to a much simpler model that scales better. + http::client_options options; + boost::asio::io_service io_service; + options.io_service(&io_service) + .follow_redirects() + .cache_resolved() + .add_openssl_certificate_path("/dev/zero") + .add_openssl_verify_path("/dev/null"); + http::client instance2(options); +} diff --git a/http/test/client_get_different_port_test.cpp b/http/test/client_get_different_port_test.cpp new file mode 100644 index 000000000..3d929e356 --- /dev/null +++ b/http/test/client_get_different_port_test.cpp @@ -0,0 +1,26 @@ + +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Client Get Different Port Test +#include +#include + +namespace http = network::http; +namespace net = network; + +BOOST_AUTO_TEST_CASE(http_get_test_different_port) { + http::request request_("http://www.boost.org/"); + http::client client_; + http::response response_ = client_.get(request_); + net::headers_wrapper::container_type const &headers_ = headers(response_); + BOOST_CHECK( !headers_.empty() ); + BOOST_CHECK( body(response_).size() > 0 ); +} + diff --git a/http/test/client_get_streaming_test.cpp b/http/test/client_get_streaming_test.cpp new file mode 100644 index 000000000..92c2a0668 --- /dev/null +++ b/http/test/client_get_streaming_test.cpp @@ -0,0 +1,56 @@ +// Copyright 2011 Dean Michael Berris <dberris@google.com>. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test +#include +#include +#include + +namespace net = network; +namespace http = network::http; + +struct body_handler { + + explicit body_handler(std::string & body) + : body(body) {} + + NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { + body.append(boost::begin(range), boost::end(range)); + } + + std::string & body; + +}; + + +BOOST_AUTO_TEST_CASE(http_client_get_streaming_test) { + http::client::request request("http://www.boost.org/"); + http::client::response response; + std::string body_string; + std::string dummy_body; + body_handler handler_instance(body_string); + { + http::client client_; + BOOST_CHECK_NO_THROW( response = client_.get(request, handler_instance) ); + net::headers_wrapper::container_type const & headers_ = headers(response); + BOOST_CHECK ( !boost::empty(headers_) ); + BOOST_CHECK_EQUAL ( body(response).size(), 0u ); + std::string version_, status_message_; + boost::uint16_t status_; + version_ = version(response); + status_ = status(response); + status_message_ = status_message(response); + BOOST_CHECK_EQUAL ( version_.substr(0, 7), std::string("HTTP/1.") ); + BOOST_CHECK_EQUAL ( status_, 200u ); + BOOST_CHECK_EQUAL ( status_message_, std::string("OK") ); + dummy_body = body(response); + } + BOOST_CHECK ( dummy_body == std::string() ); +} + diff --git a/http/test/client_get_test.cpp b/http/test/client_get_test.cpp new file mode 100644 index 000000000..6bd1dac36 --- /dev/null +++ b/http/test/client_get_test.cpp @@ -0,0 +1,57 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP 1.0 Get Test +#include +#include + +namespace net = network; +namespace http = network::http; + +BOOST_AUTO_TEST_CASE(http_client_get_test) { + http::client::request request("http://www.google.com/"); + request << net::header("Connection", "close"); + http::client client_; + http::client::response response; + BOOST_REQUIRE_NO_THROW ( response = client_.get(request) ); + std::multimap headers_ = net::headers(response); + BOOST_CHECK ( !boost::empty(headers_) ); + BOOST_REQUIRE_NO_THROW ( BOOST_CHECK ( body(response).size() != 0 ) ); + std::string version_, status_message_; + response.get_version(version_); + uint16_t status_; + response.get_status(status_); + response.get_status_message(status_message_); + BOOST_CHECK_EQUAL ( version_.substr(0,7), "HTTP/1."); + BOOST_CHECK ( status_ == 302u || status_ == 200u ); + BOOST_CHECK ( status_message_ == std::string("Found") || status_message_ == std::string("OK") ); +} + +#ifdef NETWORK_ENABLE_HTTPS + +BOOST_AUTO_TEST_CASE(https_client_get_test) { + http::client::request request("https://www.google.com/"); + request << net::header("Connection", "close"); + http::client client_; + http::client::response response; + BOOST_REQUIRE_NO_THROW ( response = client_.get(request) ); + std::multimap headers_ = net::headers(response); + BOOST_CHECK ( !boost::empty(headers_) ); + BOOST_REQUIRE_NO_THROW ( BOOST_CHECK ( body(response).size() != 0 ) ); + std::string version_, status_message_; + response.get_version(version_); + uint16_t status_; + response.get_status(status_); + response.get_status_message(status_message_); + BOOST_CHECK_EQUAL ( version_.substr(0,7), "HTTP/1."); + BOOST_CHECK ( status_ == 302u || status_ == 200u ); + BOOST_CHECK ( status_message_ == std::string("Found") || status_message_ == std::string("OK") ); +} + +#endif diff --git a/libs/network/test/http/client_get_timeout_test.cpp b/http/test/client_get_timeout_test.cpp similarity index 56% rename from libs/network/test/http/client_get_timeout_test.cpp rename to http/test/client_get_timeout_test.cpp index 4f8aa5e1b..d8cfb768d 100644 --- a/libs/network/test/http/client_get_timeout_test.cpp +++ b/http/test/client_get_timeout_test.cpp @@ -1,22 +1,25 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif #define BOOST_TEST_MODULE HTTP Client Get Timeout Test -#include +#include #include -#include "client_types.hpp" -namespace http = boost::network::http; +namespace http = network::http; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, client, client_types) { - typename client::request request("http://localhost:12121/"); - typename client::response response_; - client client_; +BOOST_AUTO_TEST_CASE(http_get_test_timeout_1_0) { + http::client::request request("http://localhost:12121/"); + http::client::response response_; + http::client client_; boost::uint16_t port_ = port(request); - typename client::response::string_type temp; + std::string temp; BOOST_CHECK_EQUAL ( 12121, port_ ); BOOST_CHECK_THROW ( response_ = client_.get(request); temp = body(response_); , std::exception ); } diff --git a/libs/network/test/http/client_include_inlined.cpp b/http/test/client_include_inlined.cpp similarity index 76% rename from libs/network/test/http/client_include_inlined.cpp rename to http/test/client_include_inlined.cpp index a83664800..f7f1d4def 100644 --- a/libs/network/test/http/client_include_inlined.cpp +++ b/http/test/client_include_inlined.cpp @@ -1,10 +1,11 @@ -// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. +// Copyright 2011 Dean Michael Berris <dberris@google.com>. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#define BOOST_NETWORK_NO_LIB -#include +#define NETWORK_NO_LIB +#include int main(int argc, char * argv[]) { using namespace boost; diff --git a/libs/network/test/http/client_localhost_normal_test.cpp b/http/test/client_localhost_normal_test.cpp similarity index 99% rename from libs/network/test/http/client_localhost_normal_test.cpp rename to http/test/client_localhost_normal_test.cpp index 3a3711c1c..d332b430a 100644 --- a/libs/network/test/http/client_localhost_normal_test.cpp +++ b/http/test/client_localhost_normal_test.cpp @@ -1,5 +1,6 @@ // // Copyright Divye Kapoor 2008. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -12,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libs/network/test/http/client_localhost_ssl_test.cpp b/http/test/client_localhost_ssl_test.cpp similarity index 99% rename from libs/network/test/http/client_localhost_ssl_test.cpp rename to http/test/client_localhost_ssl_test.cpp index 5bbf20390..e1e1f173f 100644 --- a/libs/network/test/http/client_localhost_ssl_test.cpp +++ b/http/test/client_localhost_ssl_test.cpp @@ -1,5 +1,6 @@ // // Copyright Divye Kapoor 2008. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // https://www.boost.org/LICENSE_1_0.txt) @@ -12,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libs/network/test/http/http_test_server.hpp b/http/test/http_test_server.hpp similarity index 99% rename from libs/network/test/http/http_test_server.hpp rename to http/test/http_test_server.hpp index 293c9d9d8..c5ae823cb 100644 --- a/libs/network/test/http/http_test_server.hpp +++ b/http/test/http_test_server.hpp @@ -1,5 +1,6 @@ // // Copyright Kim Grasman 2008. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) diff --git a/libs/network/test/http/message_async_ready_test.cpp b/http/test/message_async_ready_test.cpp similarity index 87% rename from libs/network/test/http/message_async_ready_test.cpp rename to http/test/message_async_ready_test.cpp index 60b3502cc..31570aded 100644 --- a/libs/network/test/http/message_async_ready_test.cpp +++ b/http/test/message_async_ready_test.cpp @@ -1,12 +1,13 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #define BOOST_TEST_MODULE HTTP Async Response Test #include -#include +#include namespace http = boost::network::http; diff --git a/libs/network/test/http/message_test.cpp b/http/test/message_test.cpp similarity index 98% rename from libs/network/test/http/message_test.cpp rename to http/test/message_test.cpp index dde3a9303..abffdeef9 100644 --- a/libs/network/test/http/message_test.cpp +++ b/http/test/message_test.cpp @@ -1,5 +1,6 @@ // Copyright 2010 (c) Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -7,8 +8,8 @@ #define BOOST_TEST_MODULE HTTP message test #include #include -#include -#include +#include +#include #include #include diff --git a/http/test/request_base_test.cpp b/http/test/request_base_test.cpp new file mode 100644 index 000000000..a44a39c5f --- /dev/null +++ b/http/test/request_base_test.cpp @@ -0,0 +1,75 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Request Storage Base Test +#include +#include + +namespace http = network::http; + +// In this test we make sure that the implementation of the default request +// storage base actually doesn't have bugs and works as advertised. Although we +// don't intend to expose this interface to users, we use the test as a sanity +// check on the internals of the implementation. +struct request_test : http::request_storage_base { + typedef http::request_storage_base base_type; + + // Expose the protected functions so that we can test them. + using base_type::append; + using base_type::read; + using base_type::flatten; + using base_type::clear; + + explicit request_test(size_t chunk_size) + : base_type(chunk_size) + {} + + request_test(request_test const &other) + : base_type(other) + {} + + ~request_test() { + // do nothing here. + } +}; + +BOOST_AUTO_TEST_CASE(request_storage_flow) { + // Use a few byte chunks just to make it manageable. + request_test simple(64); + static char data[] = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus vitae ante sed nunc dapibus convallis in at neque. Vestibulum sed congue nunc. Sed tempus lorem non dui ultrices porttitor porta ligula venenatis. Sed a orci gravida tellus condimentum laoreet. Vivamus pulvinar, tortor eu adipiscing tempus, dolor urna tincidunt enim, id pretium eros ante quis dui. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. In hac habitasse platea dictumst. Maecenas mattis metus."; + simple.append(data, sizeof(data)); + std::string output; + size_t bytes_read = simple.read(output, 0, sizeof(data)); + BOOST_CHECK_EQUAL(bytes_read, sizeof(data)); + std::string flattened; + simple.flatten(flattened); + BOOST_CHECK_EQUAL(flattened, std::string(output, sizeof(data))); + BOOST_CHECK_EQUAL(std::string(data, sizeof(data)), std::string(output, sizeof(data))); + simple.clear(); +} + +BOOST_AUTO_TEST_CASE(request_storage_copy) { + // Use a few byt chunks just to make it manageable. + request_test original(64); + static char quick_brown[] = "The quick brown fox jumps over the lazy dog."; + original.append(quick_brown, sizeof(quick_brown)); + std::string output; + request_test copy(original); + size_t bytes_read = copy.read(output, 0, sizeof(quick_brown)); + BOOST_CHECK_EQUAL(bytes_read, sizeof(quick_brown)); + std::string flattened; + copy.flatten(flattened); + BOOST_CHECK_EQUAL(flattened, std::string(output, sizeof(quick_brown))); + BOOST_CHECK_EQUAL(std::string(quick_brown, sizeof(quick_brown)), std::string(output, sizeof(quick_brown))); + copy.clear(); + flattened.clear(); + original.flatten(flattened); + BOOST_CHECK_EQUAL(flattened, std::string(quick_brown, sizeof(quick_brown))); +} diff --git a/libs/network/test/http/request_incremental_parser_test.cpp b/http/test/request_incremental_parser_test.cpp similarity index 97% rename from libs/network/test/http/request_incremental_parser_test.cpp rename to http/test/request_incremental_parser_test.cpp index 00f1657f2..59dccf2e9 100644 --- a/libs/network/test/http/request_incremental_parser_test.cpp +++ b/http/test/request_incremental_parser_test.cpp @@ -1,4 +1,5 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -6,8 +7,8 @@ #define BOOST_TEST_MODULE HTTP Incremental Request Parser Test #include #include -#include -#include +#include +#include #include #include #include diff --git a/http/test/request_linearize_test.cpp b/http/test/request_linearize_test.cpp new file mode 100644 index 000000000..336f4c1d1 --- /dev/null +++ b/http/test/request_linearize_test.cpp @@ -0,0 +1,25 @@ + +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Request Linearize Test +#include +#include +#include +#include + +namespace http = network::http; +namespace net = network; + +BOOST_AUTO_TEST_CASE(linearize_request) { + http::request request("http://www.boost.org/"); + linearize(request, "GET", 1, 0, std::ostream_iterator(std::cout)); + linearize(request, "GET", 1, 1, std::ostream_iterator(std::cout)); +} + diff --git a/http/test/request_test.cpp b/http/test/request_test.cpp new file mode 100644 index 000000000..12fae9b5f --- /dev/null +++ b/http/test/request_test.cpp @@ -0,0 +1,107 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Request Test +#include +#include +#include +#include +#include + +namespace http = network::http; +namespace net = network; + +BOOST_AUTO_TEST_CASE(request_construction) { + http::request request; + http::request other(request); +} + +BOOST_AUTO_TEST_CASE(request_value_semantics) { + // First let's default construct a request. + http::request original; + // Next let's copy the request. + http::request copy(original); + // Next let's compare the requests. + BOOST_CHECK(original == copy); + // Next let's assign the original to another request. + http::request assigned; + assigned = original; + // Next we modify the assigned object and make sure it's not the same as the + // original. + assigned.set_uri("http://www.google.com/"); + assigned.set_source("127.0.0.1"); + assigned.set_destination("http://www.google.com/"); + assigned.append_header("Connection", "close"); + assigned.set_body("Hello, world!"); + BOOST_CHECK(original != assigned); + // Next we swap the assigned and copy. + std::swap(assigned, copy); + BOOST_CHECK(copy != assigned); + BOOST_CHECK(copy != original); + BOOST_CHECK(original == assigned); +} + +//BOOST_AUTO_TEST_CASE(request_uri_test) { +// http::request request; +// request.set_uri("http://www.google.com/"); +// http::request other(request); +// std::string original, copied; +// request.get_uri(original); +// other.get_uri(copied); +// BOOST_CHECK_EQUAL(std::string("http://www.google.com/"), original); +// BOOST_CHECK_EQUAL(original, copied); +// +// // Now we test the bare uri instance with accessing using the request +// // convenience wrapper. +// network::uri uri_; +// request.get_uri(uri_); +// std::string host_ = http::host(request); +// BOOST_CHECK(network::valid(uri_)); +// BOOST_CHECK_EQUAL(std::string("www.google.com"), host_); +// BOOST_CHECK_EQUAL(uri_.host(), host_); +// BOOST_CHECK_EQUAL(std::string("www.google.com"), uri_.host()); +//} + +BOOST_AUTO_TEST_CASE(request_url_constructor_test) { + http::request request("http://www.google.com/"); + http::request other; + other.set_uri("http://www.google.com/"); + network::uri original, other_uri; + request.get_uri(original); + other.get_uri(other_uri); + BOOST_CHECK_EQUAL(original, other_uri); + + // Now test the directives.. + network::uri directive_original = http::uri(request); + BOOST_CHECK_EQUAL(original, directive_original); +} + +BOOST_AUTO_TEST_CASE(request_basics_test) { + http::request request; + request.set_uri("http://www.google.com/"); + request.set_source("127.0.0.1"); + request.set_destination("destination!"); + request.append_header("X-Referer", "http://cpp-netlib.github.com/"); + request.append_header("Connection", "close"); + request.append_body("The quick brown fox jumps over the lazy dog!"); + + network::uri uri_; + std::string source_, destination_, body_; + net::headers_wrapper::container_type const &headers_ = headers(request); + request.get_uri(uri_); + request.get_source(source_); + request.get_destination(destination_); + request.get_body(body_); + + BOOST_CHECK_EQUAL(uri_.string(), std::string("http://www.google.com/")); + BOOST_CHECK_EQUAL(source_, std::string("127.0.0.1")); + BOOST_CHECK_EQUAL(destination_, std::string("destination!")); + BOOST_CHECK_EQUAL(body_, std::string("The quick brown fox jumps over the lazy dog!")); + BOOST_CHECK(!boost::empty(headers_)); +} diff --git a/libs/network/test/http/response_incremental_parser_test.cpp b/http/test/response_incremental_parser_test.cpp similarity index 98% rename from libs/network/test/http/response_incremental_parser_test.cpp rename to http/test/response_incremental_parser_test.cpp index 9026ec0bc..dd3ab1e7b 100644 --- a/libs/network/test/http/response_incremental_parser_test.cpp +++ b/http/test/response_incremental_parser_test.cpp @@ -1,5 +1,6 @@ // Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -7,7 +8,7 @@ #define BOOST_TEST_MODULE HTTP Incremental Parser Test #include #include -#include +#include #include #include #include @@ -45,7 +46,7 @@ * semantics are according to expectations. * * Date: September 9, 2010 - * Author: Dean Michael Berris + * Author: Dean Michael Berris */ namespace tags = boost::network::tags; diff --git a/http/test/response_test.cpp b/http/test/response_test.cpp new file mode 100644 index 000000000..4e93db284 --- /dev/null +++ b/http/test/response_test.cpp @@ -0,0 +1,74 @@ +// Copyright 2012 Dean Michael Berris . +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Client Response Test +#include +#include + +namespace http = network::http; + +BOOST_AUTO_TEST_CASE(response_constructor_test) { + http::response created; +} + +BOOST_AUTO_TEST_CASE(response_value_semantics_test) { + http::response original; + http::response copy(original); + http::response assigned; + assigned = original; + BOOST_CHECK(original == assigned); + assigned.set_source("http://www.google.com/"); + BOOST_CHECK(original != assigned); + std::swap(assigned, copy); + BOOST_CHECK(assigned == original); + BOOST_CHECK(copy != original); + BOOST_CHECK(assigned != copy); + original = copy; + BOOST_CHECK(original == copy); +} + +struct multimap_inserter { + void operator()(std::string const &name, std::string const &value) const { + multimap_.insert(std::make_pair(name, value)); + } + explicit multimap_inserter(std::multimap &multimap) + : multimap_(multimap) + {} + std::multimap & multimap_; +}; + +BOOST_AUTO_TEST_CASE(response_setters_and_getters_test) { + http::response response; + response.set_source("http://www.google.com/"); + response.set_destination("127.0.0.1"); + response.append_header("Connection", "close"); + response.append_header("Content-Type", "text/plain"); + response.set_body("Hello, World!"); + response.set_status(200u); + response.set_status_message("OK"); + response.set_version("HTTP/1.1"); + std::string source, destination, body, status_message, version; + std::multimap headers, expected_headers; + expected_headers.insert(std::make_pair("Connection", "close")); + expected_headers.insert(std::make_pair("Content-Type", "text/plain")); + boost::uint16_t status; + response.get_source(source); + response.get_destination(destination); + response.get_body(body); + response.get_status_message(status_message); + response.get_version(version); + response.get_headers(multimap_inserter(headers)); + response.get_status(status); + BOOST_CHECK_EQUAL(source, std::string("http://www.google.com/")); + BOOST_CHECK_EQUAL(destination, std::string("127.0.0.1")); + BOOST_CHECK_EQUAL(body, std::string("Hello, World!")); + BOOST_CHECK_EQUAL(status, 200u); + BOOST_CHECK_EQUAL(version, std::string("HTTP/1.1")); + BOOST_CHECK(expected_headers == headers); +} diff --git a/libs/network/test/http/server_async.cpp b/http/test/server_async.cpp similarity index 84% rename from libs/network/test/http/server_async.cpp rename to http/test/server_async.cpp index 95f8646dd..a90eb0d46 100644 --- a/libs/network/test/http/server_async.cpp +++ b/http/test/server_async.cpp @@ -1,5 +1,6 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -7,8 +8,8 @@ #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests #include -#include -#include +#include +#include #include namespace net = boost::network; @@ -46,7 +47,11 @@ int main(int argc, char * argv[]) { async_hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; - server instance("localhost", port, handler, thread_pool, http::_reuse_address=true); + http::server_options options; + options.port(port) + .address("localhost") + .reuse_address(true); + server instance(options, thread_pool, handler); instance.run(); return 0; } diff --git a/libs/network/test/http/server_async_less_copy.cpp b/http/test/server_async_less_copy.cpp similarity index 94% rename from libs/network/test/http/server_async_less_copy.cpp rename to http/test/server_async_less_copy.cpp index c1ca4786b..41a65f0c6 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/http/test/server_async_less_copy.cpp @@ -1,5 +1,6 @@ // Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -9,8 +10,8 @@ #include #include -#include -#include +#include +#include #include #include diff --git a/libs/network/test/http/server_async_run_stop_concurrency.cpp b/http/test/server_async_run_stop_concurrency.cpp similarity index 84% rename from libs/network/test/http/server_async_run_stop_concurrency.cpp rename to http/test/server_async_run_stop_concurrency.cpp index e9a4e25ac..70d2602e1 100644 --- a/libs/network/test/http/server_async_run_stop_concurrency.cpp +++ b/http/test/server_async_run_stop_concurrency.cpp @@ -1,11 +1,15 @@ +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +# define BOOST_TEST_NO_MAIN +#endif #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests -#include +#include #include #include -namespace http = boost::network::http; -namespace util = boost::network::utils; +namespace http = network::http; +namespace util = network::utils; struct dummy_async_handler; typedef http::async_server async_server; @@ -21,20 +25,20 @@ struct dummy_async_handler { int main(int argc, char * argv[]) { dummy_async_handler async_handler; + http::server_options options; + options.address("127.0.0.1") + .port("8007") + .reuse_address(true); #define ASYNC_SERVER_TEST_CONFIG \ - http::_address = "127.0.0.1", \ - http::_port = "8007", \ - http::_handler = async_handler, \ - http::_thread_pool = pool, \ - http::_reuse_address = true + options, async_handler, pool #define ASYNC_SERVER_SLEEP_TIME \ boost::posix_time::milliseconds(100) // stop from main thread { - BOOST_NETWORK_MESSAGE("TEST: stop without running"); + NETWORK_MESSAGE("TEST: stop without running"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); server_instance.stop(); @@ -42,7 +46,7 @@ int main(int argc, char * argv[]) { // run-stop from main thread { - BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); + NETWORK_MESSAGE("TEST: stop from main thread"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); @@ -55,7 +59,7 @@ int main(int argc, char * argv[]) { // run-stop from another thread { - BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); + NETWORK_MESSAGE("TEST: stop from another thread"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); @@ -71,7 +75,7 @@ int main(int argc, char * argv[]) { // run-stop-run-stop from another thread { - BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); + NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); @@ -95,7 +99,7 @@ int main(int argc, char * argv[]) { // run-run-stop from another thread { - BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); + NETWORK_MESSAGE("TEST: run-run-stop from another thread"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); @@ -115,7 +119,7 @@ int main(int argc, char * argv[]) { // run-stop-stop from another thread { - BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); + NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); util::thread_pool pool; async_server server_instance(ASYNC_SERVER_TEST_CONFIG); diff --git a/http/test/server_constructor_test.cpp b/http/test/server_constructor_test.cpp new file mode 100644 index 000000000..35907a634 --- /dev/null +++ b/http/test/server_constructor_test.cpp @@ -0,0 +1,86 @@ + +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE HTTP Server Construtor Tests + +#include +#include + +namespace http = network::http; +namespace util = network::utils; + +struct dummy_sync_handler; +struct dummy_async_handler; +typedef http::sync_server sync_server; +typedef http::async_server async_server; + +struct dummy_sync_handler { + void operator()(sync_server::request const & req, + sync_server::response & res) { + // Really, this is just for testing purposes + } + + void log(char const *) { + } +}; + +struct dummy_async_handler { + void operator()(async_server::request const & req, + async_server::connection_ptr conn) { + // Really, this is just for testing purposes + } +}; + +BOOST_AUTO_TEST_CASE(minimal_constructor) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + http::server_options options; + options.address("127.0.0.1") + .port("80"); + + BOOST_CHECK_NO_THROW(sync_server sync_instance(options, sync_handler) ); + BOOST_CHECK_NO_THROW(async_server async_instance(options, async_handler, pool) ); +} + +BOOST_AUTO_TEST_CASE(with_io_service_parameter) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + boost::asio::io_service io_service; + http::server_options options; + options.address("127.0.0.1") + .port("80") + .io_service(&io_service); + + BOOST_CHECK_NO_THROW(sync_server sync_instance(options, sync_handler)); + BOOST_CHECK_NO_THROW(async_server async_instance(options, async_handler, pool)); +} + +BOOST_AUTO_TEST_CASE(with_socket_options_parameter) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + http::server_options options; + options.address("127.0.0.1") + .port("80") + .reuse_address(true) + .report_aborted(true) + .receive_buffer_size(4096) + .send_buffer_size(4096) + .receive_low_watermark(1024) + .send_low_watermark(1024) + .non_blocking_io(true) + .linger(true) + .linger_timeout(0); + + BOOST_CHECK_NO_THROW(sync_server sync_instance(options, sync_handler)); + BOOST_CHECK_NO_THROW(async_server async_instance(options, async_handler, pool)); +} diff --git a/libs/network/test/http/server_hello_world.cpp b/http/test/server_hello_world.cpp similarity index 78% rename from libs/network/test/http/server_hello_world.cpp rename to http/test/server_hello_world.cpp index 86857a9f2..aaff707c1 100644 --- a/libs/network/test/http/server_hello_world.cpp +++ b/http/test/server_hello_world.cpp @@ -1,5 +1,6 @@ // Copyright 2009 (c) Tarro, Inc. -// Copyright 2009-2010 (c) Dean Michael Berris +// Copyright 2009-2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -7,7 +8,7 @@ #include #include -#include +#include #include #include #include @@ -21,7 +22,7 @@ using std::cerr; using std::endl; struct hello_world; -typedef http::server server; +typedef http::sync_server server; struct hello_world { @@ -45,7 +46,11 @@ int main(int argc, char * argv[]) { hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; - server server_("127.0.0.1", port, handler, http::_reuse_address=true); + http::server_options options; + options.address("127.0.0.1") + .port(port) + .reuse_address(true); + server server_(options, handler); server_.run(); return EXIT_SUCCESS; } diff --git a/libs/network/test/http/server_include_inlined.cpp b/http/test/server_include_inlined.cpp similarity index 90% rename from libs/network/test/http/server_include_inlined.cpp rename to http/test/server_include_inlined.cpp index 1f286bba6..6eef71412 100644 --- a/libs/network/test/http/server_include_inlined.cpp +++ b/http/test/server_include_inlined.cpp @@ -1,5 +1,6 @@ // Copyright 2009 (c) Tarro, Inc. -// Copyright 2009-2010 (c) Dean Michael Berris +// Copyright 2009-2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -7,8 +8,8 @@ #include #include -#define BOOST_NETWORK_NO_LIB -#include +#define NETWORK_NO_LIB +#include #include #include #include diff --git a/libs/mime/test/CMakeLists.txt b/libs/mime/test/CMakeLists.txt deleted file mode 100644 index 006a3f0b1..000000000 --- a/libs/mime/test/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package ( Boost 1.41.0 COMPONENTS unit_test_framework ) -set ( Boost_USE_STATIC_LIBS ON ) -set ( Boost_USE_MULTITHREADED ON ) - -if ( Boost_FOUND ) - add_executable ( mime-roundtrip mime-roundtrip.cpp ) - target_link_libraries ( mime-roundtrip ${Boost_LIBRARIES} ) - add_test ( mime-roundtrip mime-roundtrip ) -endif () - diff --git a/libs/network/benchmarks/README.rst b/libs/network/benchmarks/README.rst deleted file mode 100644 index edf409403..000000000 --- a/libs/network/benchmarks/README.rst +++ /dev/null @@ -1,3 +0,0 @@ -Here we can collect some statistics about different areas of -performance in the :mod:`cpp-netlib`, including run-time and -compile-time. diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt deleted file mode 100644 index dc1c0d0be..000000000 --- a/libs/network/build/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.45.0 COMPONENTS unit_test_framework system regex thread filesystem ) - -add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) -add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) - diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 deleted file mode 100644 index 2d1a33b89..000000000 --- a/libs/network/build/Jamfile.v2 +++ /dev/null @@ -1,30 +0,0 @@ - -# Copyright Dean Michael Berris 2007. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import os ; - -local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; - -project cpp-netlib : - requirements - ../../../ - $(BOOST_ROOT) - 256 - : source-location ../../../ -; - -cpp-pch client : boost/network/include/http/client.hpp ; -cpp-pch server : boost/network/include/http/server.hpp ; -lib cppnetlib-uri : libs/network/src/uri/parse.cpp ; -lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; -lib cppnetlib-client-connections : libs/network/src/client.cpp ; - -install headers : client server - : ../../../boost/network/include/http ; - -install libraries : cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ; - -alias all : headers ; diff --git a/libs/network/doc/Makefile b/libs/network/doc/Makefile deleted file mode 100644 index 1726c89cb..000000000 --- a/libs/network/doc/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cpp-netlib.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cpp-netlib.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/libs/network/doc/_static/cpp-netlib.css b/libs/network/doc/_static/cpp-netlib.css deleted file mode 100644 index 3c4f3b612..000000000 --- a/libs/network/doc/_static/cpp-netlib.css +++ /dev/null @@ -1,721 +0,0 @@ -@import url('https://github.com/reset-fonts-grids.css'); - -html,body -{ - background-repeat: no-repeat; - background-position: left top; - background-attachment: fixed; - background-color: #fa2; -} - -body -{ - font: 12pt sans-serif; - color: black; -} - -#custom-doc -{ - width: 80%; - *width: 960px; - min-width: 960px; - max-width: 1240px; - margin: auto; - text-align: left; - padding-top: 16px; - margin-top: 0; -} - -#hd -{ - padding: 4px 0 12px 0; -} - -#bd -{ - /*background: #C5D88A;*/ -} - -#ft -{ - color: #C5D88A; - font-size: 90%; - padding-bottom: 2em; -} - -pre -{ - font-family: Monaco,monospace; - font-size: 14px; - background: #333; - background: -moz-linear-gradient(-90deg,#333,#222 60%); - background: -webkit-gradient(linear,0 top,0 bottom,from(#333),to(#222),color-stop(60%,#222)); - border-width: 1px 0; - margin: 1em 0; - padding: .3em .4em; - overflow: auto; - line-height: 1.3em; - color: #CCC; - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - padding: 1em; -} - -/*** links ***/ -a -{ - text-decoration: none; - font-weight: bold -} - -a img -{ - border: none -} - -a: link,a: visited -{ - color: #800000 -} - -#bd a: link,#bd a: visited -{ - color: #800000; - text-decoration: underline -} - -#bd #sidebar a: link,#bd #sidebar a: visited -{ - color: #8B4513; - text-decoration: none -} - -a: hover -{ - color: #000 -} - -#bd a: hover -{ - background-color: #FF9955; - color: black; - text-decoration: none -} - -#bd #sidebar a: hover -{ - color: #FF9955; - background: none -} - -h2 a,h3 a,h4 a -{ - text-decoration: none !important -} - -a.reference em -{ - /*color: #FF9955;*/ - font-style: normal; - font-weight: bold; -} - -/*** sidebar ***/ -#sidebar div.sphinxsidebarwrapper -{ - font-size: 92%; - margin-right: 14px -} - -#sidebar h3,#sidebar h4 -{ - color: #487858; - font-size: 125% -} - -#sidebar a -{ - color: #8B4513 -} - -#sidebar ul ul -{ - margin-top: 0; - margin-bottom: 0 -} - -#sidebar li -{ - margin-top: 0.2em; - margin-bottom: 0.2em; - list-style-position: inside; - list-style-type: square; -} - -/*** nav ***/ -div.nav -{ - margin: 0; - font-size: 14px; - text-align: right; - color: #fff -} - -div.nav a: link,div.nav a: visited -{ - color: white -} - -#hd div.nav -{ - margin-top: -27px -} - -#ft div.nav -{ - margin-bottom: -18px -} - -#hd h1 a -{ - color: #EFFFEF -} - -#global-nav -{ - position: absolute; - top: 5px; - margin-left: -5px; - padding: 7px 0; - color: #263E2B -} - -#global-nav a -{ - padding: 0 4px -} - -#global-nav a.about -{ - padding-left: 0 -} - -#global-nav a -{ - color: #fff -} - -/*** content ***/ -#yui-main -{ - -moz-border-radius: 3px; - -moz-box-shadow: 0 0 9px rgba(0,0,0,0.5); - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 0 9px rgba(0,0,0,0.5); - border-radius: 3px; - box-shadow: 0 0 9px rgba(0,0,0,0.5); - background: none repeat scroll 0 0 #6ABDFB; -} - -#yui-main div.yui-b -{ - position: relative -} - -#yui-main div.yui-b -{ - background: #FFF; - min-height: 330px; - color: #164B2B; - padding: 0.3em 2em 1em 2em -} - -/*** basic styles ***/ -dd -{ - margin-left: 15px -} - -h1,h2,h3,h4 -{ - margin-top: 1em; - font-weight: normal -} - -h1 -{ - font-size: 218%; - font-weight: bold; - margin-top: 0.6em; - margin-bottom: .4em; - line-height: 1.1em -} - -h2 -{ - font-size: 175%; - font-weight: bold; - margin-bottom: .6em; - line-height: 1.2em; - color: #092e20 -} - -h3 -{ - font-size: 150%; - font-weight: bold; - margin-bottom: .2em; - color: #487858 -} - -h4 -{ - font-size: 125%; - font-weight: bold; - margin-top: 1.5em; - margin-bottom: 3px -} - -div.figure -{ - text-align: center -} - -div.figure p.caption -{ - font-size: 1em; - margin-top: 0; - margin-bottom: 1.5em; - color: black -} - -hr -{ - color: #ccc; - background-color: #ccc; - height: 1px; - border: 0 -} - -p,ul,dl -{ - margin-top: .6em; - color: #333 -} - -#yui-main div.yui-b img -{ - max-width: 50em; - margin-left: auto; - margin-right: auto; - display: block; - margin-top: 10px; - margin-bottom: 10px -} - -caption -{ - font-size: 1em; - font-weight: bold; - margin-top: 0.5em; - margin-bottom: 0.5em; - margin-left: 2px; - text-align: center -} - -blockquote -{ - padding: 0 1em; - margin: 1em 0; - font: "Times New Roman",serif; - color: #234f32 -} - -strong -{ - font-weight: bold -} - -em -{ - font-style: italic -} - -ins -{ - font-weight: bold; - text-decoration: none -} - -/*** lists ***/ -ol.arabic li -{ - list-style-type: decimal -} - -ul li -{ - font-size: 1em -} - -ol li -{ - margin-bottom: .4em -} - -ul ul -{ - padding-left: 1.2em -} - -ul ul ul -{ - padding-left: 1em -} - -ul.linklist,ul.toc -{ - padding-left: 0 -} - -ul.toc ul -{ - margin-left: .6em -} - -ul.toc ul li -{ - list-style-type: square -} - -ul.toc ul ul li -{ - list-style-type: disc -} - -ul.linklist li,ul.toc li -{ - list-style-type: none -} - -dt -{ - font-weight: bold; - margin-top: .5em; - font-size: 1em -} - -dd -{ - margin-bottom: .8em -} - -ol.toc -{ - margin-bottom: 2em -} - -ol.toc li -{ - font-size: 125%; - padding: .5em; - line-height: 1.2em; - clear: right -} - -ol.toc li.b -{ - background-color: #E0FFB8 -} - -ol.toc li a: hover -{ - background-color: transparent !important; - text-decoration: underline !important -} - -ol.toc span.release-date -{ - color: #487858; - float: right; - font-size: 85%; - padding-right: .5em -} - -ol.toc span.comment-count -{ - font-size: 75%; - color: #999 -} - -ul.simple li -{ - list-style-type: disc; - margin-left: 2em -} - -/*** tables ***/ -table -{ - color: #000; - margin-bottom: 1em; - width: 100% -} - -table.docutils td p -{ - margin-top: 0; - margin-bottom: .5em -} - -table.docutils td,table.docutils th -{ - border-bottom: 1px solid #dfdfdf; - padding: 4px 2px -} - -table.docutils thead th -{ - border-bottom: 2px solid #dfdfdf; - text-align: left; - font-weight: bold; - #487858-space: nowrap -} - -table.docutils thead th p -{ - margin: 0; - padding: 0 -} - -table.docutils -{ - border-collapse: collapse -} - -/*** code blocks ***/ -.literal -{ - #487858-space: nowrap -} - -.literal -{ - color: #234f32 -} - -#sidebar .literal -{ - color: #487858; - background: transparent; - font-size: 11px -} - -h4 .literal -{ - color: #234f32; - font-size: 13px -} - -dt .literal,table .literal -{ - background: none -} - -#bd a.reference -{ - text-decoration: none -} - -#bd a.reference tt.literal -{ - border-bottom: 1px #234f32 dotted -} - -/*** notes & admonitions ***/ -.note,.admonition -{ - padding: .8em 1em .8em; - margin: 1em 0; - background-color: #6ABDFB; - -moz-border-radius: 3px; - -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.3); - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.3); - border-radius: 3px; - box-shadow: 0 1px 2px rgba(0,0,0,0.3); -} - -.admonition-title -{ - font-weight: bold; - margin-top: 0 !important; - margin-bottom: 0 !important -} - -.admonition .last -{ - margin-bottom: 0 !important -} - -.note -{ - padding-left: 85px; - background: #6ABDFB url(https://github.com/Button-Info-icon.png) .8em .8em no-repeat -} - -.warning -{ - padding-left: 85px; - background: #6ABDFB url(https://github.com/Button-Warning-icon.png) .8em .8em no-repeat -} - -/*** versoinadded/changes ***/ -div.versionadded,div.versionchanged -{ -} - -div.versionadded span.title,div.versionchanged span.title -{ - font-weight: bold -} - -/*** p-links ***/ -a.headerlink -{ - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; - visibility: hidden -} - -h1: hover > a.headerlink,h2: hover > a.headerlink,h3: hover > a.headerlink,h4: hover > a.headerlink,h5: hover > a.headerlink,h6: hover > a.headerlink,dt: hover > a.headerlink -{ - visibility: visible -} - -/*** index ***/ -table.indextable td -{ - text-align: left; - vertical-align: top -} - -table.indextable dl,table.indextable dd -{ - margin-top: 0; - margin-bottom: 0 -} - -table.indextable tr.pcap -{ - height: 10px -} - -table.indextable tr.cap -{ - margin-top: 10px; - background-color: #f2f2f2 -} - -/*** page-specific overrides ***/ -div#contents ul -{ - margin-bottom: 0 -} - -div#contents ul li -{ - margin-bottom: 0 -} - -div#contents ul ul li -{ - margin-top: 0.3em -} - -/*** IE hacks ***/ -* pre -{ -} - -.footer -{ - color: white; -} - -.footer a -{ - color: #333; -} - -img -{ - margin: 10px 0 10px 0; -} - -#index p.rubric -{ - font-size: 150%; - font-weight: normal; - margin-bottom: .2em; - color: #252; -} - -#index div.section dt -{ - font-weight: normal; -} - -#index #cpp-netlib-getting-cpp-netlib, #index #cpp-netlib-boost { - background:none repeat scroll 0 0 #6ABDFB; - margin: 2em 0 2em 2em; - - border-radius:6px 6px; - -webkit-border-radius:6px; - -moz-border-radius:6px 6px; - - box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - -webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - -moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - - overflow:visible; - float:right; - clear:both; - padding:1em; - width: 380px; -} - -#index #cpp-netlib-getting-cpp-netlib a -{ - font-weight: bold; - font-size: 14px; -} - -#index #cpp-netlib-getting-cpp-netlib h1 -{ - color: #333; -} - -#index #cpp-netlib-getting-cpp-netlib h2 -{ - margin: 0; -} - -#index #cpp-netlib-getting-cpp-netlib strong -{ - font-size: 20px; -} - -tt.py-exc.literal -{ - color: red; -} - -tt.xref span.pre -{ - color: green; -} - diff --git a/libs/network/doc/html/_static/cpp-netlib.css b/libs/network/doc/html/_static/cpp-netlib.css deleted file mode 100644 index 3c4f3b612..000000000 --- a/libs/network/doc/html/_static/cpp-netlib.css +++ /dev/null @@ -1,721 +0,0 @@ -@import url('https://github.com/reset-fonts-grids.css'); - -html,body -{ - background-repeat: no-repeat; - background-position: left top; - background-attachment: fixed; - background-color: #fa2; -} - -body -{ - font: 12pt sans-serif; - color: black; -} - -#custom-doc -{ - width: 80%; - *width: 960px; - min-width: 960px; - max-width: 1240px; - margin: auto; - text-align: left; - padding-top: 16px; - margin-top: 0; -} - -#hd -{ - padding: 4px 0 12px 0; -} - -#bd -{ - /*background: #C5D88A;*/ -} - -#ft -{ - color: #C5D88A; - font-size: 90%; - padding-bottom: 2em; -} - -pre -{ - font-family: Monaco,monospace; - font-size: 14px; - background: #333; - background: -moz-linear-gradient(-90deg,#333,#222 60%); - background: -webkit-gradient(linear,0 top,0 bottom,from(#333),to(#222),color-stop(60%,#222)); - border-width: 1px 0; - margin: 1em 0; - padding: .3em .4em; - overflow: auto; - line-height: 1.3em; - color: #CCC; - border-radius: 3px; - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - padding: 1em; -} - -/*** links ***/ -a -{ - text-decoration: none; - font-weight: bold -} - -a img -{ - border: none -} - -a: link,a: visited -{ - color: #800000 -} - -#bd a: link,#bd a: visited -{ - color: #800000; - text-decoration: underline -} - -#bd #sidebar a: link,#bd #sidebar a: visited -{ - color: #8B4513; - text-decoration: none -} - -a: hover -{ - color: #000 -} - -#bd a: hover -{ - background-color: #FF9955; - color: black; - text-decoration: none -} - -#bd #sidebar a: hover -{ - color: #FF9955; - background: none -} - -h2 a,h3 a,h4 a -{ - text-decoration: none !important -} - -a.reference em -{ - /*color: #FF9955;*/ - font-style: normal; - font-weight: bold; -} - -/*** sidebar ***/ -#sidebar div.sphinxsidebarwrapper -{ - font-size: 92%; - margin-right: 14px -} - -#sidebar h3,#sidebar h4 -{ - color: #487858; - font-size: 125% -} - -#sidebar a -{ - color: #8B4513 -} - -#sidebar ul ul -{ - margin-top: 0; - margin-bottom: 0 -} - -#sidebar li -{ - margin-top: 0.2em; - margin-bottom: 0.2em; - list-style-position: inside; - list-style-type: square; -} - -/*** nav ***/ -div.nav -{ - margin: 0; - font-size: 14px; - text-align: right; - color: #fff -} - -div.nav a: link,div.nav a: visited -{ - color: white -} - -#hd div.nav -{ - margin-top: -27px -} - -#ft div.nav -{ - margin-bottom: -18px -} - -#hd h1 a -{ - color: #EFFFEF -} - -#global-nav -{ - position: absolute; - top: 5px; - margin-left: -5px; - padding: 7px 0; - color: #263E2B -} - -#global-nav a -{ - padding: 0 4px -} - -#global-nav a.about -{ - padding-left: 0 -} - -#global-nav a -{ - color: #fff -} - -/*** content ***/ -#yui-main -{ - -moz-border-radius: 3px; - -moz-box-shadow: 0 0 9px rgba(0,0,0,0.5); - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 0 9px rgba(0,0,0,0.5); - border-radius: 3px; - box-shadow: 0 0 9px rgba(0,0,0,0.5); - background: none repeat scroll 0 0 #6ABDFB; -} - -#yui-main div.yui-b -{ - position: relative -} - -#yui-main div.yui-b -{ - background: #FFF; - min-height: 330px; - color: #164B2B; - padding: 0.3em 2em 1em 2em -} - -/*** basic styles ***/ -dd -{ - margin-left: 15px -} - -h1,h2,h3,h4 -{ - margin-top: 1em; - font-weight: normal -} - -h1 -{ - font-size: 218%; - font-weight: bold; - margin-top: 0.6em; - margin-bottom: .4em; - line-height: 1.1em -} - -h2 -{ - font-size: 175%; - font-weight: bold; - margin-bottom: .6em; - line-height: 1.2em; - color: #092e20 -} - -h3 -{ - font-size: 150%; - font-weight: bold; - margin-bottom: .2em; - color: #487858 -} - -h4 -{ - font-size: 125%; - font-weight: bold; - margin-top: 1.5em; - margin-bottom: 3px -} - -div.figure -{ - text-align: center -} - -div.figure p.caption -{ - font-size: 1em; - margin-top: 0; - margin-bottom: 1.5em; - color: black -} - -hr -{ - color: #ccc; - background-color: #ccc; - height: 1px; - border: 0 -} - -p,ul,dl -{ - margin-top: .6em; - color: #333 -} - -#yui-main div.yui-b img -{ - max-width: 50em; - margin-left: auto; - margin-right: auto; - display: block; - margin-top: 10px; - margin-bottom: 10px -} - -caption -{ - font-size: 1em; - font-weight: bold; - margin-top: 0.5em; - margin-bottom: 0.5em; - margin-left: 2px; - text-align: center -} - -blockquote -{ - padding: 0 1em; - margin: 1em 0; - font: "Times New Roman",serif; - color: #234f32 -} - -strong -{ - font-weight: bold -} - -em -{ - font-style: italic -} - -ins -{ - font-weight: bold; - text-decoration: none -} - -/*** lists ***/ -ol.arabic li -{ - list-style-type: decimal -} - -ul li -{ - font-size: 1em -} - -ol li -{ - margin-bottom: .4em -} - -ul ul -{ - padding-left: 1.2em -} - -ul ul ul -{ - padding-left: 1em -} - -ul.linklist,ul.toc -{ - padding-left: 0 -} - -ul.toc ul -{ - margin-left: .6em -} - -ul.toc ul li -{ - list-style-type: square -} - -ul.toc ul ul li -{ - list-style-type: disc -} - -ul.linklist li,ul.toc li -{ - list-style-type: none -} - -dt -{ - font-weight: bold; - margin-top: .5em; - font-size: 1em -} - -dd -{ - margin-bottom: .8em -} - -ol.toc -{ - margin-bottom: 2em -} - -ol.toc li -{ - font-size: 125%; - padding: .5em; - line-height: 1.2em; - clear: right -} - -ol.toc li.b -{ - background-color: #E0FFB8 -} - -ol.toc li a: hover -{ - background-color: transparent !important; - text-decoration: underline !important -} - -ol.toc span.release-date -{ - color: #487858; - float: right; - font-size: 85%; - padding-right: .5em -} - -ol.toc span.comment-count -{ - font-size: 75%; - color: #999 -} - -ul.simple li -{ - list-style-type: disc; - margin-left: 2em -} - -/*** tables ***/ -table -{ - color: #000; - margin-bottom: 1em; - width: 100% -} - -table.docutils td p -{ - margin-top: 0; - margin-bottom: .5em -} - -table.docutils td,table.docutils th -{ - border-bottom: 1px solid #dfdfdf; - padding: 4px 2px -} - -table.docutils thead th -{ - border-bottom: 2px solid #dfdfdf; - text-align: left; - font-weight: bold; - #487858-space: nowrap -} - -table.docutils thead th p -{ - margin: 0; - padding: 0 -} - -table.docutils -{ - border-collapse: collapse -} - -/*** code blocks ***/ -.literal -{ - #487858-space: nowrap -} - -.literal -{ - color: #234f32 -} - -#sidebar .literal -{ - color: #487858; - background: transparent; - font-size: 11px -} - -h4 .literal -{ - color: #234f32; - font-size: 13px -} - -dt .literal,table .literal -{ - background: none -} - -#bd a.reference -{ - text-decoration: none -} - -#bd a.reference tt.literal -{ - border-bottom: 1px #234f32 dotted -} - -/*** notes & admonitions ***/ -.note,.admonition -{ - padding: .8em 1em .8em; - margin: 1em 0; - background-color: #6ABDFB; - -moz-border-radius: 3px; - -moz-box-shadow: 0 1px 2px rgba(0,0,0,0.3); - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.3); - border-radius: 3px; - box-shadow: 0 1px 2px rgba(0,0,0,0.3); -} - -.admonition-title -{ - font-weight: bold; - margin-top: 0 !important; - margin-bottom: 0 !important -} - -.admonition .last -{ - margin-bottom: 0 !important -} - -.note -{ - padding-left: 85px; - background: #6ABDFB url(https://github.com/Button-Info-icon.png) .8em .8em no-repeat -} - -.warning -{ - padding-left: 85px; - background: #6ABDFB url(https://github.com/Button-Warning-icon.png) .8em .8em no-repeat -} - -/*** versoinadded/changes ***/ -div.versionadded,div.versionchanged -{ -} - -div.versionadded span.title,div.versionchanged span.title -{ - font-weight: bold -} - -/*** p-links ***/ -a.headerlink -{ - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; - visibility: hidden -} - -h1: hover > a.headerlink,h2: hover > a.headerlink,h3: hover > a.headerlink,h4: hover > a.headerlink,h5: hover > a.headerlink,h6: hover > a.headerlink,dt: hover > a.headerlink -{ - visibility: visible -} - -/*** index ***/ -table.indextable td -{ - text-align: left; - vertical-align: top -} - -table.indextable dl,table.indextable dd -{ - margin-top: 0; - margin-bottom: 0 -} - -table.indextable tr.pcap -{ - height: 10px -} - -table.indextable tr.cap -{ - margin-top: 10px; - background-color: #f2f2f2 -} - -/*** page-specific overrides ***/ -div#contents ul -{ - margin-bottom: 0 -} - -div#contents ul li -{ - margin-bottom: 0 -} - -div#contents ul ul li -{ - margin-top: 0.3em -} - -/*** IE hacks ***/ -* pre -{ -} - -.footer -{ - color: white; -} - -.footer a -{ - color: #333; -} - -img -{ - margin: 10px 0 10px 0; -} - -#index p.rubric -{ - font-size: 150%; - font-weight: normal; - margin-bottom: .2em; - color: #252; -} - -#index div.section dt -{ - font-weight: normal; -} - -#index #cpp-netlib-getting-cpp-netlib, #index #cpp-netlib-boost { - background:none repeat scroll 0 0 #6ABDFB; - margin: 2em 0 2em 2em; - - border-radius:6px 6px; - -webkit-border-radius:6px; - -moz-border-radius:6px 6px; - - box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - -webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - -moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.6); - - overflow:visible; - float:right; - clear:both; - padding:1em; - width: 380px; -} - -#index #cpp-netlib-getting-cpp-netlib a -{ - font-weight: bold; - font-size: 14px; -} - -#index #cpp-netlib-getting-cpp-netlib h1 -{ - color: #333; -} - -#index #cpp-netlib-getting-cpp-netlib h2 -{ - margin: 0; -} - -#index #cpp-netlib-getting-cpp-netlib strong -{ - font-size: 20px; -} - -tt.py-exc.literal -{ - color: red; -} - -tt.xref span.pre -{ - color: green; -} - diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt deleted file mode 100644 index 20ab9acaf..000000000 --- a/libs/network/example/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (c) Dean Michael Berris 2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -include_directories(${CPP-NETLIB_SOURCE_DIR}) -if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) -endif (OPENSSL_FOUND) - -add_executable(http_client http_client.cpp) -add_executable(simple_wget simple_wget.cpp) -add_executable(atom_reader atom/atom.cpp atom/main.cpp) -add_executable(rss_reader rss/rss.cpp rss/main.cpp) -add_executable(twitter_search twitter/search.cpp) -add_executable(hello_world_server http/hello_world_server.cpp) -add_executable(hello_world_client http/hello_world_client.cpp) -if (UNIX) - add_executable(fileserver http/fileserver.cpp) -endif (UNIX) -add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) -add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) -add_dependencies(atom_reader cppnetlib-uri cppnetlib-client-connections) -add_dependencies(rss_reader cppnetlib-uri cppnetlib-client-connections) -add_dependencies(twitter_search cppnetlib-uri cppnetlib-client-connections) -set(BOOST_CLIENT_LIBS - ${Boost_PROGRAM_OPTIONS_LIBRARY} - ${Boost_THREAD_LIBRARY} - ${Boost_DATE_TIME_LIBRARY} - ${Boost_REGEX_LIBRARY} - ${Boost_SYSTEM_LIBRARY}) - -set(BOOST_SERVER_LIBS - ${Boost_THREAD_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_DATE_TIME_LIBRARY} - ${Boost_PROGRAM_OPTIONS_LIBRARY}) - -target_link_libraries(http_client - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -target_link_libraries(simple_wget - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -target_link_libraries(atom_reader - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -target_link_libraries(rss_reader - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -target_link_libraries(twitter_search - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -target_link_libraries(hello_world_server - ${BOOST_SERVER_LIBS} - ${CMAKE_THREAD_LIBS_INIT}) - -target_link_libraries(hello_world_client - ${BOOST_CLIENT_LIBS} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - -if (OPENSSL_FOUND) - target_link_libraries(http_client ${OPENSSL_LIBRARIES}) - target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) - target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) - target_link_libraries(rss_reader ${OPENSSL_LIBRARIES}) - target_link_libraries(twitter_search ${OPENSSL_LIBRARIES}) - target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) - target_link_libraries(hello_world_client ${OPENSSL_LIBRARIES}) -endif (OPENSSL_FOUND) - -if (UNIX) - target_link_libraries(fileserver - ${BOOST_SERVER_LIBS} - ${Boost_FILESYSTEM_LIBRARY} - ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-server-parsers) -endif (UNIX) - -set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(rss_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(twitter_search PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(hello_world_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -if (UNIX) - set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -endif (UNIX) diff --git a/libs/network/example/http_client.cpp b/libs/network/example/http_client.cpp deleted file mode 100644 index 1f8264a04..000000000 --- a/libs/network/example/http_client.cpp +++ /dev/null @@ -1,81 +0,0 @@ - -// Copyright Dean Michael Berris 2008. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -//[ http_client_main -/*` - This application takes a URL as a command line argument and prints - the resource to the console. -*/ -#include -#include -#include -#include -#include - -namespace po = boost::program_options; - -int main(int argc, char * argv[]) { - using namespace boost::network; - po::options_description options("Allowed options"); - std::string output_filename, source; - bool show_headers; - options.add_options() - ("help,h", "produce help message") - ("headers,H", "print headers") - ("source,s", po::value(&source), "source URL") - ; - - po::positional_options_description positional_options; - positional_options.add("source", 1); - po::variables_map vm; - try { - po::store(po::command_line_parser(argc, argv).options(options).positional(positional_options).run(), - vm); - po::notify(vm); - } catch(std::exception & e) { - std::cout << "Error: " << e.what() << std::endl; - std::cout << options << std::endl; - return EXIT_FAILURE; - }; - - if (vm.count("help")) { - std::cout << options << std::endl; - return EXIT_SUCCESS; - }; - - if (vm.count("source") < 1) { - std::cout << "Error: Source URL required." << std::endl; - std::cout << options << std::endl; - return EXIT_FAILURE; - }; - - show_headers = vm.count("headers") ? true : false ; - - - typedef http::basic_client - http_client; - - http_client::request request(source); - http_client::string_type destination_ = host(request); - - request << ::boost::network::header("Connection", "close"); - http_client client(http::_follow_redirects=true); - http_client::response response = client.get(request); - - if (show_headers) { - headers_range::type headers_ = response.headers(); - typedef std::pair header_type; - BOOST_FOREACH(header_type const & header, headers_) { - std::cout << header.first << ": " << header.second << std::endl; - } - std::cout << std::endl; - }; - - body_range::type body_ = body(response).range(); - boost::copy(body_, std::ostream_iterator::type>(std::cout)); - return EXIT_SUCCESS; -} -//] diff --git a/libs/network/example/http_client1.cpp b/libs/network/example/http_client1.cpp deleted file mode 100644 index 8bdbc0352..000000000 --- a/libs/network/example/http_client1.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright Dean Michael Berris 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include -#include - -int main(int argc, char * argv[]) { - using namespace boost::network; - - if (argc != 2) { std::cout << "Usage: " << argv[0] << " " << std::endl; return 1; } - - http::client client; - http::client::request request(argv[1]); - request << header("Connection", "close"); - http::client::response response = client.get(request); - std::cout << body(response) << std::endl; - - return 0; -} - diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp deleted file mode 100644 index baf9aaae6..000000000 --- a/libs/network/example/simple_wget.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Glyn Matthews 2009, 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -//[ simple_wget_main -/*` - This is a very basic clone of wget. It's missing a lot of - features, such as content-type detection, but it does the - fundamental things the same. - - It demonstrates the use the `uri` and the `http::client`. -*/ - - -#include -#include -#include -#include -#include - - -namespace http = boost::network::http; -namespace uri = boost::network::uri; - - -namespace { -std::string get_filename(const uri::uri &url) { - std::string path = uri::path(url); - std::size_t index = path.find_last_of('/'); - std::string filename = path.substr(index + 1); - return filename.empty()? "index.html" : filename; -} -} // namespace - - -int -main(int argc, char *argv[]) { - - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " url" << std::endl; - return 1; - } - - try { - http::client client; - http::client::request request(argv[1]); - http::client::response response = client.get(request); - - std::string filename = get_filename(request.uri()); - std::cout << "Saving to: " << filename << std::endl; - std::ofstream ofs(filename.c_str()); - ofs << static_cast(body(response)) << std::endl; - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - return 1; - } - - return 0; -} -//] diff --git a/libs/network/example/uri_builder.cpp b/libs/network/example/uri_builder.cpp deleted file mode 100644 index e37160d0b..000000000 --- a/libs/network/example/uri_builder.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include -#include -#include - - -using namespace boost::network; - - -int -main(int argc, char *argv[]) { - - uri::uri url; - url << uri::scheme("http") - << uri::host("www.github.com") - << uri::path("/cpp-netlib"); - std::cout << url << std::endl; - - return 0; -} diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt deleted file mode 100644 index 2722a5542..000000000 --- a/libs/network/src/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Glyn Matthews 2011. -# Copyright 2011 Dean Michael Berris (dberris@google.com) -# Copyright 2011 Google, Inc. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - - -include_directories(${CPP-NETLIB_SOURCE_DIR}) - -set(CPP-NETLIB_URI_SRCS uri/uri.cpp uri/schemes.cpp) -add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS}) - -set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) -add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) - -set(CPP-NETLIB_HTTP_CLIENT_SRCS client.cpp) -add_library(cppnetlib-client-connections ${CPP-NETLIB_HTTP_CLIENT_SRCS}) diff --git a/libs/network/src/client.cpp b/libs/network/src/client.cpp deleted file mode 100644 index 3ce8c1f19..000000000 --- a/libs/network/src/client.cpp +++ /dev/null @@ -1,17 +0,0 @@ - -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Copyright 2011 Google, Inc. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifdef BOOST_NETWORK_NO_LIB -#warn Building the library even with BOOST_NETWORK_NO_LIB defined. -#undef BOOST_NETWORK_NO_LIB -#endif - -#include - -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include -#endif diff --git a/libs/network/src/uri/schemes.cpp b/libs/network/src/uri/schemes.cpp deleted file mode 100644 index e0b671196..000000000 --- a/libs/network/src/uri/schemes.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include -#include - - -namespace boost { -namespace network { -namespace uri { -namespace { -static boost::unordered_set hierarchical_schemes_; -static boost::unordered_set opaque_schemes_; - -bool register_hierarchical_schemes() { - hierarchical_schemes_.insert("http"); - hierarchical_schemes_.insert("https"); - hierarchical_schemes_.insert("shttp"); - hierarchical_schemes_.insert("ftp"); - hierarchical_schemes_.insert("file"); - hierarchical_schemes_.insert("dns"); - hierarchical_schemes_.insert("nfs"); - hierarchical_schemes_.insert("imap"); - hierarchical_schemes_.insert("nntp"); - hierarchical_schemes_.insert("pop"); - hierarchical_schemes_.insert("rsync"); - hierarchical_schemes_.insert("snmp"); - hierarchical_schemes_.insert("telnet"); - hierarchical_schemes_.insert("svn"); - hierarchical_schemes_.insert("svn+ssh"); - hierarchical_schemes_.insert("git"); - hierarchical_schemes_.insert("git+ssh"); - return true; -} - -bool register_opaque_schemes() { - opaque_schemes_.insert("mailto"); - opaque_schemes_.insert("news"); - opaque_schemes_.insert("im"); - opaque_schemes_.insert("sip"); - opaque_schemes_.insert("sms"); - opaque_schemes_.insert("xmpp"); - return true; -} - - -static bool hierarchical = register_hierarchical_schemes(); -static bool opaque = register_opaque_schemes(); -} // namespace - -bool hierarchical_schemes::exists(const std::string &scheme) { - return hierarchical_schemes_.end() != hierarchical_schemes_.find(scheme); -} - -bool opaque_schemes::exists(const std::string &scheme) { - return opaque_schemes_.end() != opaque_schemes_.find(scheme); -} -} // namespace uri -} // namespace network -} // namespace boost diff --git a/libs/network/src/uri/uri.cpp b/libs/network/src/uri/uri.cpp deleted file mode 100644 index 613bcb1fa..000000000 --- a/libs/network/src/uri/uri.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2012 Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt deleted file mode 100644 index 8a63cfa3b..000000000 --- a/libs/network/test/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) Dean Michael Berris 2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -include_directories(${CPP-NETLIB_SOURCE_DIR}) - -add_subdirectory(uri) -add_subdirectory(http) - -if (Boost_FOUND) - set( - TESTS - message_test - message_transform_test - utils_thread_pool - ) - foreach (test ${TESTS}) - if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - endif() - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) - -endif() - diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 deleted file mode 100644 index 3375ac148..000000000 --- a/libs/network/test/Jamfile.v2 +++ /dev/null @@ -1,55 +0,0 @@ - -# Copyright Dean Michael Berris 2007. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import testing ; -import os ; - -if [ os.name ] = CYGWIN -{ - lib ws2_32 ; - lib mswsock ; -} - -project network_test : - requirements - ../../../ - . - /boost//unit_test_framework - /boost//system - /boost//date_time - /boost//regex - /boost//thread - /boost//filesystem - debug:BOOST_NETWORK_DEBUG - gcc:BOOST_NETWORK_ENABLE_HTTPS - gcc:-lpthread - gcc:-lssl - gcc:-lcrypto - darwin:BOOST_NETWORK_ENABLE_HTTPS - darwin:-lpthread - darwin:-lssl - darwin:-lcrypto - clang:BOOST_NETWORK_ENABLE_HTTPS - clang:-lpthread - clang:-lssl - clang:-lcrypto - cygwin,gcc:_WIN32_WINNT=0x0501 - cygwin,gcc:__USE_W32_SOCKETS - cygwin,gcc:ws2_32 - cygwin,gcc:mswsock - msvc:BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN - msvc:WIN32_LEAN_AND_MEAN - msvc:_SCL_SECURE_NO_WARNINGS - msvc:_WIN32_WINNT=0x0501 - 256 - static - ; - -build-project http ; -build-project uri ; - -run message_test.cpp ; -run message_transform_test.cpp ; diff --git a/libs/network/test/client_server_include_failure.cpp b/libs/network/test/client_server_include_failure.cpp deleted file mode 100644 index 6ce27857e..000000000 --- a/libs/network/test/client_server_include_failure.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Glyn Matthews 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - - -# define BOOST_TEST_MODULE Client and server includes -# include - - -// -// The problem here is a bizarre compilation failure in including -// these two files, and instantiating a client. It's described at -// http://github.com/cpp-netlib/cpp-netlib/issues#issue/13 -// -# include -# include - - -BOOST_AUTO_TEST_CASE(test1) { - typedef boost::network::http::basic_client< - boost::network::http::tags::http_keepalive_8bit_udp_resolve, 1, 1> http_client; - http_client client; -} diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt deleted file mode 100644 index 88ac4ed45..000000000 --- a/libs/network/test/http/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ - -# Copyright 2010 Dean Michael Berris. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -include_directories(${CPP-NETLIB_SOURCE_DIR}) - -if (OPENSSL_FOUND) - include_directories( ${OPENSSL_INCLUDE_DIR} ) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) -endif() - -if (Boost_FOUND) - set ( TESTS - client_constructor_test - client_get_test - client_get_different_port_test - client_get_timeout_test - client_get_streaming_test - ) - foreach ( test ${TESTS} ) - if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - endif() - add_executable(cpp-netlib-http-${test} ${test}.cpp) - add_dependencies(cpp-netlib-http-${test} - cppnetlib-uri - cppnetlib-client-connections) - target_link_libraries(cpp-netlib-http-${test} - ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} - cppnetlib-uri - cppnetlib-client-connections) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-http-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-http-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) - endforeach (test) - - set ( SERVER_API_TESTS - server_constructor_test - server_async_run_stop_concurrency - ) - foreach ( test ${SERVER_API_TESTS} ) - if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - endif() - add_executable(cpp-netlib-http-${test} ${test}.cpp) - add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) - set_target_properties(cpp-netlib-http-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-http-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) - endforeach (test) - -endif() diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 deleted file mode 100644 index 9f587c50b..000000000 --- a/libs/network/test/http/Jamfile.v2 +++ /dev/null @@ -1,49 +0,0 @@ - -# Copyright 2011 Dean Michael Berris. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import testing ; -import modules ; -import feature ; - -project network_test/http : - requirements - ../../../../ - ../ - debug:BOOST_NETWORK_DEBUG - ; - -run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -run client_get_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -#run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -run message_async_ready_test.cpp ; -run message_test.cpp /cpp-netlib//cppnetlib-uri ; -run request_incremental_parser_test.cpp ; -run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; -run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-server-parsers ; -run server_constructor_test.cpp /cpp-netlib//cppnetlib-server-parsers ; -#run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; - -exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe http_async_less_copy_server : server_async_less_copy.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe http_async_run_stop_concurrency_server : server_async_run_stop_concurrency.cpp /cpp-netlib//cppnetlib-server-parsers ; - -make httplib_acceptance.passed : ../httplib_acceptance.py hello_world : @httplib_acceptance ; -make httplib_async_acceptance.passed : ../httplib_acceptance.py http_async_server : @httplib_acceptance ; -make httplib_async_less_copy_acceptance.passed : ../httplib_acceptance.py http_async_less_copy_server : @httplib_acceptance ; -make httplib_async_run_stop_concurrency_acceptance.passed : ../httplib_acceptance.py http_async_run_stop_concurrency_server : @httplib_acceptance ; - -actions httplib_acceptance { - export TEST_SCRIPT=`echo "$(>)" | awk '{print $1}'` - export EXECUTABLE=`echo "$(>)" | awk '{print $2}'` - export PORT=`echo "import random; print random.randint(8000, 8010)" | python` - python $TEST_SCRIPT $EXECUTABLE $PORT $(<) -} - diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp deleted file mode 100644 index 9fa0b15b2..000000000 --- a/libs/network/test/http/client_constructor_test.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP 1.0 Client Constructor Test -#include -#include -#include "client_types.hpp" - -namespace http = boost::network::http; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, client, client_types) { - client instance; - boost::asio::io_service io_service; - client instance2(io_service); - client instance3(http::_io_service=io_service); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client_types) { - client instance( - http::_follow_redirects=true, - http::_cache_resolved=true - ); - boost::asio::io_service io_service; - client instance2( - http::_follow_redirects=true, - http::_io_service=io_service, - http::_cache_resolved=true - ); - client instance3( - http::_openssl_certificate="foo", - http::_openssl_verify_path="bar" - ); -} diff --git a/libs/network/test/http/client_get_different_port_test.cpp b/libs/network/test/http/client_get_different_port_test.cpp deleted file mode 100644 index 9feee918f..000000000 --- a/libs/network/test/http/client_get_different_port_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP Client Get Different Port Test -#include -#include -#include "client_types.hpp" - -namespace net = boost::network; -namespace http = boost::network::http; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port, client, client_types) { - typename client::request request("http://www.boost.org/"); - client client_; - typename client::response response_ = client_.get(request); - typename net::headers_range::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp deleted file mode 100644 index aa1bdd902..000000000 --- a/libs/network/test/http/client_get_streaming_test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test -#include -#include -#include -#include "client_types.hpp" - -namespace net = boost::network; -namespace http = boost::network::http; - -struct body_handler { - - explicit body_handler(std::string & body) - : body(body) {} - - BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { - body.append(boost::begin(range), boost::end(range)); - } - - std::string & body; - -}; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, async_only_client_types) { - typename client::request request("http://www.boost.org/"); - typename client::response response; - typename client::string_type body_string; - typename client::string_type dummy_body; - body_handler handler_instance(body_string); - { - client client_; - BOOST_CHECK_NO_THROW( response = client_.get(request, http::_body_handler=handler_instance) ); - typename net::headers_range::type range = headers(response)["Content-Type"]; - BOOST_CHECK ( !boost::empty(range) ); - BOOST_CHECK_EQUAL ( body(response).size(), 0u ); - BOOST_CHECK_EQUAL ( response.version().substr(0, 7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response.status(), 200u ); - BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); - dummy_body = body(response); - } - BOOST_CHECK ( dummy_body == typename client::string_type() ); -} - diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp deleted file mode 100644 index 1a2b558b1..000000000 --- a/libs/network/test/http/client_get_test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP 1.0 Get Test -#include -#include -#include "client_types.hpp" - -namespace net = boost::network; -namespace http = boost::network::http; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, client, client_types) { - typename client::request request("http://www.boost.org/"); - client client_; - typename client::response response; - BOOST_REQUIRE_NO_THROW ( response = client_.get(request) ); - typename net::headers_range::type range = headers(response)["Content-Type"]; - BOOST_CHECK ( !boost::empty(range) ); - BOOST_REQUIRE_NO_THROW ( BOOST_CHECK ( body(response).size() != 0 ) ); - BOOST_CHECK_EQUAL ( response.version().substr(0,7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response.status(), 200u ); - BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); -} - -#ifdef BOOST_NETWORK_ENABLE_HTTPS - -BOOST_AUTO_TEST_CASE_TEMPLATE(https_client_get_test, client, client_types) { - typename client::request request("https://www.google.com/"); - client client_; - typename client::response response_ = client_.get(request); - typename net::headers_range::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK( body(response_).size() != 0 ); -} - -#endif diff --git a/libs/network/test/http/client_types.hpp b/libs/network/test/http/client_types.hpp deleted file mode 100644 index 3bed03afe..000000000 --- a/libs/network/test/http/client_types.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef CLIENT_TYPES_ROOWQCLE -#define CLIENT_TYPES_ROOWQCLE - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include "tag_types.hpp" -#include -#include -#include -#include -#include -#include - -namespace mpl = boost::mpl ; - -template -struct client_adapter { - template - struct apply { - typedef boost::network::http::basic_client type; - }; -}; - -typedef - mpl::transform< - tag_types, - client_adapter<1,0> - >::type - client_1_0; - -typedef - mpl::transform< - tag_types, - client_adapter<1,1> - >::type - client_1_1; - -typedef mpl::joint_view< - client_1_0 - , client_1_1 ->::type client_types; - -typedef - mpl::joint_view< - mpl::transform< - mpl::remove_if< - tag_types, - boost::network::is_sync< - boost::mpl::_ - > - >::type, - client_adapter<1,0> - >::type, - mpl::transform< - mpl::remove_if< - tag_types, - boost::network::is_sync< - boost::mpl::_ - > - >::type, - client_adapter<1,1> - >::type - >::type async_only_client_types; - -#endif /* CLIENT_TYPES_ROOWQCLE */ diff --git a/libs/network/test/http/request_linearize_test.cpp b/libs/network/test/http/request_linearize_test.cpp deleted file mode 100644 index c2151a054..000000000 --- a/libs/network/test/http/request_linearize_test.cpp +++ /dev/null @@ -1,31 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP Request Linearize Test -#include -#include -#include -#include -#include - -namespace http = boost::network::http; -namespace tags = boost::network::http::tags; -namespace mpl = boost::mpl; -namespace net = boost::network; - -typedef mpl::list< - tags::http_default_8bit_tcp_resolve - , tags::http_default_8bit_udp_resolve - , tags::http_async_8bit_tcp_resolve - , tags::http_async_8bit_udp_resolve - > tag_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(linearize_request, T, tag_types) { - http::basic_request request("http://www.boost.org/"); - linearize(request, "GET", 1, 0, std::ostream_iterator::type>(std::cout)); - linearize(request, "GET", 1, 1, std::ostream_iterator::type>(std::cout)); -} - diff --git a/libs/network/test/http/server_constructor_test.cpp b/libs/network/test/http/server_constructor_test.cpp deleted file mode 100644 index b2b4fe8eb..000000000 --- a/libs/network/test/http/server_constructor_test.cpp +++ /dev/null @@ -1,84 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP Server Construtor Tests - -#include -#include - -namespace http = boost::network::http; -namespace util = boost::network::utils; - -struct dummy_sync_handler; -struct dummy_async_handler; -typedef http::server sync_server; -typedef http::async_server async_server; - -struct dummy_sync_handler { - void operator()(sync_server::request const & req, - sync_server::response & res) { - // Really, this is just for testing purposes - } - - void log(char const *) { - } -}; - -struct dummy_async_handler { - void operator()(async_server::request const & req, - async_server::connection_ptr conn) { - // Really, this is just for testing purposes - } -}; - -BOOST_AUTO_TEST_CASE(minimal_constructor) { - dummy_sync_handler sync_handler; - dummy_async_handler async_handler; - util::thread_pool pool; - - BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler) ); - BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool) ); -} - -BOOST_AUTO_TEST_CASE(with_io_service_parameter) { - dummy_sync_handler sync_handler; - dummy_async_handler async_handler; - util::thread_pool pool; - boost::asio::io_service io_service; - - BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler, io_service)); - BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool, io_service)); -} - -BOOST_AUTO_TEST_CASE(with_socket_options_parameter) { - dummy_sync_handler sync_handler; - dummy_async_handler async_handler; - util::thread_pool pool; - - BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler, - http::_reuse_address=true, - http::_report_aborted=true, - http::_receive_buffer_size=4096, - http::_send_buffer_size=4096, - http::_receive_low_watermark=1024, - http::_send_low_watermark=1024, - http::_non_blocking_io=true, - http::_linger=true, - http::_linger_timeout=0 - )); - BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool, - http::_reuse_address=true, - http::_report_aborted=true, - http::_receive_buffer_size=4096, - http::_send_buffer_size=4096, - http::_receive_low_watermark=1024, - http::_send_low_watermark=1024, - http::_non_blocking_io=true, - http::_linger=true, - http::_linger_timeout=0 - )); - -} diff --git a/libs/network/test/http/tag_types.hpp b/libs/network/test/http/tag_types.hpp deleted file mode 100644 index 219ae9303..000000000 --- a/libs/network/test/http/tag_types.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef TAG_TYPES_4NNM8B5T -#define TAG_TYPES_4NNM8B5T - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace http = boost::network::http; - -typedef boost::mpl::vector< - http::tags::http_default_8bit_tcp_resolve - , http::tags::http_default_8bit_udp_resolve - , http::tags::http_keepalive_8bit_tcp_resolve - , http::tags::http_keepalive_8bit_udp_resolve - , http::tags::http_async_8bit_udp_resolve - , http::tags::http_async_8bit_tcp_resolve -> tag_types; - - -#endif /* TAG_TYPES_4NNM8B5T */ diff --git a/libs/network/test/http_server_async_less_copy.cpp b/libs/network/test/http_server_async_less_copy.cpp deleted file mode 100644 index 8ff076bdc..000000000 --- a/libs/network/test/http_server_async_less_copy.cpp +++ /dev/null @@ -1,74 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests - -#include - -#include -#include -#include -#include - -namespace net = boost::network; -namespace http = boost::network::http; -namespace utils = boost::network::utils; - -struct async_hello_world; -typedef http::async_server server; - -struct async_hello_world { - - struct is_content_length { - template - bool operator()(Header const & header) { - return boost::iequals(header.name, "content-length"); - } - }; - - void operator()(server::request const & request, server::connection_ptr connection) { - static server::response_header headers[] = { - {"Connection", "close"} - , {"Content-Type", "text/plain"} - , {"Server", "cpp-netlib/0.9-devel"} - }; - if (request.method == "HEAD") { - connection->set_status(server::connection::ok); - connection->set_headers(boost::make_iterator_range(headers, headers+3)); - } else { - if (request.method == "PUT" || request.method == "POST") { - static std::string bad_request("Bad Request."); - server::request::headers_container_type::iterator found = - boost::find_if(request.headers, is_content_length()); - if (found == request.headers.end()) { - connection->set_status(server::connection::bad_request); - connection->set_headers(boost::make_iterator_range(headers, headers+3)); - connection->write(bad_request); - return; - } - } - static char const * hello_world = "Hello, World!"; - connection->set_status(server::connection::ok); - connection->set_headers(boost::make_iterator_range(headers, headers+3)); - std::vector iovec; - iovec.push_back(boost::asio::const_buffer(hello_world, 13)); - connection->write(iovec, boost::bind(&async_hello_world::error, this, _1)); - } - } - - void error(boost::system::error_code const & ec) { - // do nothing here. - } -}; - -int main(int argc, char * argv[]) { - utils::thread_pool thread_pool(2); - async_hello_world handler; - server instance("127.0.0.1", "8000", handler, thread_pool); - instance.run(); - return 0; -} - diff --git a/libs/network/test/httplib_acceptance.py b/libs/network/test/httplib_acceptance.py deleted file mode 100644 index 935b98601..000000000 --- a/libs/network/test/httplib_acceptance.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright (c) 2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -#!/bin/env python - -from sys import argv -from time import sleep -import httplib2 as httplib -from subprocess import Popen,PIPE - -if len(argv) < 4: - print('I need the executable to run, the port to run it on, and the final touched file indicator.') - exit(1) - -print('Running {0} on port {1}...'.format(argv[1], argv[2])) - -pipe = None -try: - pipe = Popen(args=[argv[1], argv[2]], executable=argv[1], stdin=PIPE, stdout=PIPE, close_fds=True) - print('Done with spawning {0}.'.format(argv[1])) - print('Sleeping to give the server a chance to run...') - sleep(1) -except: - print('I cannot spawn \'{0}\' properly.'.format(argv[1])) - exit(1) - -status = 0 -client = httplib.Http(timeout=5) -expected = b'Hello, World!' - -def test(url, method, expected, headers={}, body=''): - global status - try: - print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), - resp, content = client.request(url, method, headers=headers, body=body) - if content != expected: - print('ERROR: \'{0}\' != \'{1}\'; sizes: {2} != {3}'.format(content, expected, len(content), len(expected))) - status = 1 - else: - print('... passed.') - except Exception as e: - print('Caught Exception: {0}'.format(e)) - status = 1 - -def test_status(url, method, expected, headers={}, body=''): - global status - try: - print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), - resp, content = client.request('http://localhost:8000/', 'PUT', body='') - if resp['status'] != expected: - print('ERROR: response status (got {0}) != expecting {1}'.format(resp['status'], expected)) - status = 1 - else: - print('... passed.') - except Exception as e: - print('Caught Exception: {0}'.format(e)) - status = 1 - -url = 'http://127.0.0.1:{0}/'.format(argv[2]) -test(url, 'GET', expected) -test(url, 'DELETE', expected) -# Good request case, there's a content-length header for POST -test(url, 'POST', expected, {'Content-Length': '0'}) -# Good request case, there's a content-length header for PUT -test(url, 'PUT', expected, {'Content-Length': '0'}) -# Bad request case, no content-length for POST -test_status(url, 'POST', '400') -# Bad request case, no content-length for PUT -test_status(url, 'PUT', '400') - -if status != 0: - print('Failures encountered.') - pipe.terminate() - exit(status) - -open(argv[len(argv) - 1], 'w').close() -print('All tests pass.') -pipe.terminate() - diff --git a/libs/network/test/message_test.cpp b/libs/network/test/message_test.cpp deleted file mode 100644 index a3d7d4b36..000000000 --- a/libs/network/test/message_test.cpp +++ /dev/null @@ -1,175 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE message test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - http::tags::http_default_8bit_tcp_resolve, - http::tags::http_default_8bit_udp_resolve, - http::tags::http_keepalive_8bit_tcp_resolve, - http::tags::http_keepalive_8bit_udp_resolve, - tags::default_string, - tags::default_wstring -> tag_types; - -struct string_header_name { - static std::string string; -}; - -std::string string_header_name::string = "Header"; - -struct wstring_header_name { - static std::wstring string; -}; - -std::wstring wstring_header_name::string = L"Header"; - -struct string_header_value { - static std::string string; -}; - -std::string string_header_value::string = "Value"; - -struct wstring_header_value { - static std::wstring string; -}; - -std::wstring wstring_header_value::string = L"Value"; - -template -struct header_name : string_header_name {}; - -template <> -struct header_name : wstring_header_name {}; - -template -struct header_value : string_header_value {}; - -template <> -struct header_value : wstring_header_value {}; - -struct string_body_data { - static std::string string; -}; - -std::string string_body_data::string = "The quick brown fox jumps over the lazy dog."; - -struct wstring_body_data { - static std::wstring string; -}; - -std::wstring wstring_body_data::string = L"The quick brown fox jumps over the lazy dog."; - -template -struct body_data : string_body_data {}; - -template <> -struct body_data : wstring_body_data {}; - -struct string_source_data { - static std::string string; -}; - -std::string string_source_data::string = "Source"; - -struct wstring_source_data { - static std::wstring string; -}; - -std::wstring wstring_source_data::string = L"Source"; - -template -struct source_data : string_source_data {}; - -template <> -struct source_data : wstring_body_data {}; - -struct string_destination_data { - static std::string string; -}; - -std::string string_destination_data::string = "Destination"; - -struct wstring_destination_data { - static std::wstring string; -}; - -std::wstring wstring_destination_data::string = L"Destination"; - -template -struct destination_data : string_destination_data {}; - -template <> -struct destination_data : wstring_destination_data {}; - - -/** - * Defines a set of template functions that can be used to test - * generic code. - */ - -BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { - basic_message instance; - instance << header(header_name::string, header_value::string); - basic_message copy(instance); - BOOST_CHECK_EQUAL(headers(copy).count(header_name::string), static_cast(1)); - typename headers_range >::type range = headers(copy)[header_name::string]; - BOOST_CHECK (boost::begin(range) != boost::end(range)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(swap_test, T, tag_types) { - basic_message instance; - instance << header(header_name::string, header_value::string); - basic_message other; - swap(instance, other); - BOOST_CHECK_EQUAL (headers(instance).count(header_name::string), static_cast(0)); - BOOST_CHECK_EQUAL (headers(other).count(header_name::string), static_cast(1)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(headers_directive_test, T, tag_types) { - basic_message instance; - instance << header(header_name::string, header_value::string); - BOOST_CHECK_EQUAL ( headers(instance).count(header_name::string), static_cast(1) ); - typename headers_range >::type range = headers(instance)[header_name::string]; - BOOST_CHECK (boost::begin(range) != boost::end(range)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(body_directive_test, T, tag_types) { - basic_message instance; - instance << ::boost::network::body(body_data::string); - typename string::type body_string = body(instance); - BOOST_CHECK ( body_string == body_data::string ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(source_directive_test, T, tag_types) { - basic_message instance; - instance << ::boost::network::source(source_data::string); - typename string::type source_string = source(instance); - BOOST_CHECK ( source_string == source_data::string ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(destination_directive_test, T, tag_types) { - basic_message instance; - instance << destination(destination_data::string); - BOOST_CHECK ( destination(instance) == destination_data::string ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(remove_header_directive_test, T, tag_types) { - basic_message instance; - instance << header(header_name::string, header_value::string) - << remove_header(header_name::string); - typename headers_range >::type range = headers(instance); - BOOST_CHECK ( boost::begin(range) == boost::end(range) ); -} - - diff --git a/libs/network/test/message_transform_test.cpp b/libs/network/test/message_transform_test.cpp deleted file mode 100644 index c1be57148..000000000 --- a/libs/network/test/message_transform_test.cpp +++ /dev/null @@ -1,40 +0,0 @@ - -// Copyright Dean Michael Berris 2007. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE message test -#include -#include -#include -#include - -BOOST_AUTO_TEST_CASE ( message_transform_toupper ) { - using namespace boost::network; - - message msg; - msg << source("me"); - BOOST_CHECK_EQUAL ( source(msg), "me" ); - msg << transform(to_upper_, source_); - BOOST_CHECK_EQUAL ( source(msg), "ME" ); - msg << destination("you"); - BOOST_CHECK_EQUAL ( destination(msg), "you"); - msg << transform(to_upper_, destination_); - BOOST_CHECK_EQUAL ( destination(msg), "YOU"); -} - -BOOST_AUTO_TEST_CASE ( message_transform_tolower ) { - using namespace boost::network; - - message msg; - msg << source("ME"); - BOOST_CHECK_EQUAL ( source(msg), "ME" ); - msg << transform(to_lower_, source_); - BOOST_CHECK_EQUAL ( source(msg), "me" ); - msg << destination("YOU"); - BOOST_CHECK_EQUAL ( destination(msg), "YOU" ); - msg << transform(to_lower_, destination_); - BOOST_CHECK_EQUAL ( destination(msg), "you" ); -} - diff --git a/libs/network/test/server/boost.jpg b/libs/network/test/server/boost.jpg deleted file mode 100644 index 3857e53db..000000000 Binary files a/libs/network/test/server/boost.jpg and /dev/null differ diff --git a/libs/network/test/server/certificate.pem b/libs/network/test/server/certificate.pem deleted file mode 100644 index 7e1b6cff1..000000000 --- a/libs/network/test/server/certificate.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICAzCCAWwCCQDVrANJOmGIcjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB -VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0 -cyBQdHkgTHRkMCAXDTA5MTIxNzIzMTcwN1oYDzE5MTcwMzExMTAyMDM1WjBFMQsw -CQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJu -ZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw -c3j9E+LMKqw2PBf/a5zLIAfNxDadFW2OB3S85kXgr72x/00oi5JiPOeA7LGrmhuJ -+nDXiO+AWL1O6fOzOkyTd0Nh1hCHJzjrJEfIt3iqdQGHiocVupWN5iCQRzCrErbP -vtvvs/r7mMheb9W3q9lntKPwiZ7mmr/daYdAbVuQpQIDAQABMA0GCSqGSIb3DQEB -BQUAA4GBAHz1OhxKYSc5kYmgkMYYwtmHFWWTL2jy6xk4+yv5sGAmze4dvtQqCNiA -TaljCHWdAkHaXXBzbZ7+e3qem2M1Y31HqO0ZiQezpJ1TFLPc5/0uNX8JIPovb+s7 -c/wevNe16tw4dhM0DQ2V3FH8AwiQANUtZ8yFk91RH4rTaQBQDYOE ------END CERTIFICATE----- diff --git a/libs/network/test/server/cgi-bin/cgisupport.py b/libs/network/test/server/cgi-bin/cgisupport.py deleted file mode 100755 index 45d80177f..000000000 --- a/libs/network/test/server/cgi-bin/cgisupport.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python -# -# Copyright Kim Grasman 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# - -class http_headers: - def __init__(self, header_str): - self.parse(header_str) - - def raw_headers(self): - return self.raw - - def iteritems(self): - return self.headers.iteritems() - - def value(self, name): - return self.headers[name] - - def parse(self, header_str): - self.raw = header_str - self.headers = self.__parse_headers(header_str) - - def __parse_headers(self, str): - dict = {} - - # I'm sure there are better ways to do this in Python, - # but I don't know my way around so well - lines = str.split('\n') - for line in lines: - header = line.split(': ') - if len(header) > 0: - name = header[0] - if len(header) > 1: - value = ': '.join(header[1:]) # re-join the rest of the items as value - - if len(name) > 0: - dict[name] = value - - return dict diff --git a/libs/network/test/server/cgi-bin/echo_body.py b/libs/network/test/server/cgi-bin/echo_body.py deleted file mode 100755 index 51d62aff9..000000000 --- a/libs/network/test/server/cgi-bin/echo_body.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python -# -# Copyright Divye Kapoor 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI application on localhost -# It can be accessed by http://localhost:8000/cgi-bin/echo_form.py -# It returns the query parameters passed to the CGI Script as plain text. -# -import cgitb; cgitb.enable() # for debugging only -import cgi -import os, sys - -sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) -sys.stdout.write( "\r\n" ) - -# POST data/form data is available in the .value property -sys.stdout.write( cgi.FieldStorage().value ) diff --git a/libs/network/test/server/cgi-bin/echo_headers.py b/libs/network/test/server/cgi-bin/echo_headers.py deleted file mode 100755 index 8546e01e3..000000000 --- a/libs/network/test/server/cgi-bin/echo_headers.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/python -# -# Copyright Kim Grasman 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI application on localhost -# It can be accessed by http://localhost:8000/cgi-bin/echo_headers.py -# -import cgi -import os, sys -import cgisupport - -sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) -sys.stdout.write( "\r\n" ) - -hdrs = cgisupport.http_headers(os.environ.get('HTTP_ALL_HEADERS')) - -for h,v in hdrs.iteritems(): - print h + ": " + v diff --git a/libs/network/test/server/cgi-bin/multiline-header.py b/libs/network/test/server/cgi-bin/multiline-header.py deleted file mode 100755 index ce66a2887..000000000 --- a/libs/network/test/server/cgi-bin/multiline-header.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python -# -# Copyright Divye Kapoor 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI application on localhost -# It can be accessed by http://localhost:8000/cgi-bin/requestinfo.py -# It returns the query parameters passed to the CGI Script as plain text. -# -import cgitb; cgitb.enable() # for debugging only -import cgi -import os, sys - -print "X-CppNetlib-Test: multi-line-header\r\n" -print " that-should-concatenate\r\n" -print "Content-type: text/plain; charset=us-ascii\r\n\r\n" -print "\r\n" - -form = cgi.FieldStorage() -qstring = "" -qstring_dict = {} - -if os.environ.has_key("QUERY_STRING"): - qstring = os.environ["QUERY_STRING"] - try: - qstring_dict = cgi.parse_qs(qstring,1,1) # parse_qs(query_string,keep_blanks,strict_parsing) - except ValueError: - print "Error parsing query string." - -print "Query string:", qstring - -print "GET parameters:", -for i in qstring_dict.keys(): - print i,"-",qstring_dict[i],";", -print - -# Remove GET params and print only the POST ones -print "POST parameters:", -for i in form.keys(): - if i not in qstring_dict.keys(): - print i,"-",form.getfirst(i, ""),";", -print diff --git a/libs/network/test/server/cgi-bin/requestinfo.py b/libs/network/test/server/cgi-bin/requestinfo.py deleted file mode 100755 index 332c36637..000000000 --- a/libs/network/test/server/cgi-bin/requestinfo.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python -# -# Copyright Divye Kapoor 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI application on localhost -# It can be accessed by http://localhost:8000/cgi-bin/requestinfo.py -# It returns the query parameters passed to the CGI Script as plain text. -# -import cgitb; cgitb.enable() # for debugging only -import cgi -import os, sys - -sys.stdout.write( "HTTP/1.0 200 Requestinfo.py Output follows\r\n" ) -sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) -sys.stdout.write( "\r\n" ) - -form = cgi.FieldStorage() -qstring = "" -qstring_dict = {} - -print "Headers: ",form.headers - -if os.environ.has_key("QUERY_STRING"): - qstring = os.environ["QUERY_STRING"] - try: - qstring_dict = cgi.parse_qs(qstring,1,1) # parse_qs(query_string,keep_blanks,strict_parsing) - except ValueError: - print "Error parsing query string." - - -print "Query string:", qstring - -print "GET parameters:", -for i in qstring_dict.keys(): - print i,"-",qstring_dict[i],";", -print - -# Remove GET params and print only the POST ones -print "POST parameters:", -try: - for i in form.keys(): - if i not in qstring_dict.keys(): - print i,"-",form.getfirst(i, ""),";", - print -except TypeError: # In case of empty POST bodies. - pass - -print 'HTTP HEADERS-------------------' -print 'Content-Type:', os.environ.get('CONTENT_TYPE') -print 'Content-Length:', os.environ.get('CONTENT_LENGTH') -for k in os.environ.keys(): - if k.startswith('HTTP_'): - print k, ':', os.environ[k] diff --git a/libs/network/test/server/cgi_server.py b/libs/network/test/server/cgi_server.py deleted file mode 100644 index 53ef7065a..000000000 --- a/libs/network/test/server/cgi_server.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/python -# -# Copyright Divye Kapoor 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http:#www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI HTTP Server at port 8000 on localhost -# It will be used to test the http::client interface of the library - -import CGIHTTPServer -import BaseHTTPServer -import threading - -from threading import Thread, Event - -stop_serving = Event() -server_thread = None - -def run(server_class=BaseHTTPServer.HTTPServer, handler_class=CGIHTTPServer.CGIHTTPRequestHandler): - server_address = ('',8000) - httpd = server_class(server_address, handler_class) - while not stop_serving.isSet(): - httpd.handle_request() - - -def start_server(): - server_thread = Thread(None, run, "HTTP Server",(), None, None) - server_thread.start() - server_thread.join() - - -if __name__ == '__main__': - start_server() diff --git a/libs/network/test/server/http_test_server.py b/libs/network/test/server/http_test_server.py deleted file mode 100644 index ba96c4fe9..000000000 --- a/libs/network/test/server/http_test_server.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -# -# Copyright Allister Levi Sanchez 2008. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) -# -# This program sets up a CGI HTTP Server at port 8000 on localhost -# It will be used to test the http::client interface of the library - -import BaseHTTPServer -import CGIHTTPServer -import os - -class HttpTestHandler(CGIHTTPServer.CGIHTTPRequestHandler): - - def run_cgi(self): - """Version of run_cgi that provides more HTTP headers.""" - headers_str = '' - for a in self.headers.items(): - headers_str += "%s: %s\n" % a - - os.environ['HTTP_ALL_HEADERS'] = headers_str - - # run the rest of run_cgi - CGIHTTPServer.CGIHTTPRequestHandler.run_cgi(self) - -def run_server(server_class=BaseHTTPServer.HTTPServer, handler_class=HttpTestHandler): - server_address = ('',8000) - httpd = server_class(server_address, handler_class) - httpd.serve_forever() - -if __name__ == '__main__': - run_server() diff --git a/libs/network/test/server/https_test_server.py b/libs/network/test/server/https_test_server.py deleted file mode 100644 index 23cd3a007..000000000 --- a/libs/network/test/server/https_test_server.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# Copyright 2009 Jeroen Habraken -# Copyright 2009 Dean Michael Berris -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import socket - -from BaseHTTPServer import HTTPServer -from SimpleHTTPServer import SimpleHTTPRequestHandler -from CGIHTTPServer import CGIHTTPRequestHandler - -from OpenSSL import SSL - -import os - -class SecureHTTPServer(HTTPServer): - def __init__(self, server_address, HandlerClass): - HTTPServer.__init__(self, server_address, HandlerClass) - - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.use_privatekey_file ("key.pem") - ctx.use_certificate_file("certificate.pem") - self.socket = SSL.Connection(ctx, socket.socket(self.address_family, - self.socket_type)) - self.server_bind() - self.server_activate() - -class SecureHTTPRequestHandler(CGIHTTPRequestHandler): - def setup(self): - self.connection = self.request - self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) - self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) - - def run_cgi(self): - """Version of run_cgi that provides more HTTP headers.""" - headers_str = '' - for a in self.headers.items(): - headers_str += "%s: %s\n" % a - - os.environ['HTTP_ALL_HEADERS'] = headers_str - - # run the rest of run_cgi - CGIHTTPRequestHandler.run_cgi(self) - -if __name__ == '__main__': - SecureHTTPServer(('127.0.0.1', 8443), SecureHTTPRequestHandler).serve_forever() - diff --git a/libs/network/test/server/key.pem b/libs/network/test/server/key.pem deleted file mode 100644 index 773af7712..000000000 --- a/libs/network/test/server/key.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQCwc3j9E+LMKqw2PBf/a5zLIAfNxDadFW2OB3S85kXgr72x/00o -i5JiPOeA7LGrmhuJ+nDXiO+AWL1O6fOzOkyTd0Nh1hCHJzjrJEfIt3iqdQGHiocV -upWN5iCQRzCrErbPvtvvs/r7mMheb9W3q9lntKPwiZ7mmr/daYdAbVuQpQIDAQAB -AoGBAIJ7MXn8TZdq6uRENf7ERjMTIZIwya4JnXUM4G+b3QqVCrLottcHtxz8Krl0 -zsG1+S1kTDOmaG1BseP8LyFXOC4Ni8H6vjnFG/vTzuArPhtoB9B5wXDnPfPQH22a -10XH3aGbOoyP9sg0HF0ZJsnou3QgQfg49whWa8gl8SUSckI1AkEA4NFwJ7GpVmIA -ZuVzguKEKNNxC9PNUDeGUCyjH5fejolL2wIQQ4rKpml05TbUuugQByxBi+Gbd51j -hGeFOncVywJBAMjsrWoOyGpDJIe2H0Aklecp9awn2H59GFNBmDvUO6LAAkr5Dkky -64QGLCZLAdswH9QaMuBvzKSZkzGcfDKwpU8CQBxTJt9Jaf1hMY3FQO1vnpkKMsb7 -s3V02W5GgXLcjoTE1ZLNSsFHvkqDJOAwLVMzI7nToJqAHTdP1Bb9d/KqyEsCQA0x -/fGJJwBTiIKhI0xDGtUjnE7CDyW/cWmGVUkYlxIJKh1iXd3QykbRYPTi2Cxc7Lox -PkYfEYF91Hzdmgp6L2ECQFcCg0qKfvy1YeTChrDFMBrZx4yoqYGBnqEqxshksAJg -o1r5HVSlO71aVgeAs/5DD4IIb2OyiJE/dv6t0L8TQeQ= ------END RSA PRIVATE KEY----- diff --git a/libs/network/test/server/test.xml b/libs/network/test/server/test.xml deleted file mode 100644 index 54decb475..000000000 --- a/libs/network/test/server/test.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Hi! This is node 1 - Node 2 here. - diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt deleted file mode 100644 index ad899b1e7..000000000 --- a/libs/network/test/uri/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) Dean Michael Berris 2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -include_directories(${CPP-NETLIB_SOURCE_DIR}) - -if (Boost_FOUND) - set( - TESTS - uri_test - uri_builder_test - uri_builder_stream_test - uri_encoding_test - relative_uri_test - ) - foreach (test ${TESTS}) - if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - endif() - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri) - target_link_libraries(cpp-netlib-${test} - ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) - -endif() diff --git a/libs/network/test/uri/Jamfile.v2 b/libs/network/test/uri/Jamfile.v2 deleted file mode 100644 index aacbd1ac6..000000000 --- a/libs/network/test/uri/Jamfile.v2 +++ /dev/null @@ -1,17 +0,0 @@ - -# Copyright Glyn Matthews 2011. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -import testing ; - -project network_test/uri : - requirements - ../../../../ - ../ - ; - -run url_test.cpp /cpp-netlib//cppnetlib-uri ; -run url_builder_test.cpp /cpp-netlib//cppnetlib-uri ; -run url_encoding_test.cpp /cpp-netlib//cppnetlib-uri ; diff --git a/libs/network/test/uri/relative_uri_test.cpp b/libs/network/test/uri/relative_uri_test.cpp deleted file mode 100644 index a12836e8b..000000000 --- a/libs/network/test/uri/relative_uri_test.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Glyn Matthews 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE Relative URL Test -#include -#include -#include -#include - -using namespace boost::network; - -BOOST_AUTO_TEST_CASE(relative_uri_test) { - // don't yet support relative URIs - uri::uri instance("example.com"); - BOOST_REQUIRE(!uri::valid(instance)); -} diff --git a/libs/network/test/uri/uri_builder_stream_test.cpp b/libs/network/test/uri/uri_builder_stream_test.cpp deleted file mode 100644 index cf8f7660e..000000000 --- a/libs/network/test/uri/uri_builder_stream_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE URI builder stream test -#include -#include -#include -#include -#include - - -using namespace boost::network; - - -BOOST_AUTO_TEST_CASE(builder_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); - -} - -BOOST_AUTO_TEST_CASE(full_uri_builder_test) -{ - uri::uri instance; - instance << uri::scheme("http") - << uri::user_info("user:password") - << uri::host("www.example.com") - << uri::port("80") - << uri::path("/path") - << uri::query("query") - << uri::fragment("fragment") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://user:password@www.example.com/path?query#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(port_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com:8000/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(encoded_path_test) -{ - uri::uri instance; - instance << uri::scheme("http") - << uri::host("www.example.com") - << uri::port(8000) - << uri::encoded_path("/Path With (Some) Encoded Characters!") - ; - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com:8000/Path%20With%20%28Some%29%20Encoded%20Characters%21", instance.string()); -} - -BOOST_AUTO_TEST_CASE(query_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") - << uri::query("key", "value") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/?key=value", instance.string()); -} - -BOOST_AUTO_TEST_CASE(query_2_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") - << uri::query("key1", "value1") << uri::query("key2", "value2") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/?key1=value1&key2=value2", instance.string()); -} - -BOOST_AUTO_TEST_CASE(fragment_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(from_base_test) -{ - uri::uri base_uri("http://www.example.com/"); - uri::uri instance; - instance << base_uri << uri::path("/") << uri::fragment("fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(scheme_http_test) -{ - uri::uri instance; - instance << uri::schemes::http << uri::host("www.example.com") << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(scheme_https_test) -{ - uri::uri instance; - instance << uri::schemes::https << uri::host("www.example.com") << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("https://www.example.com/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(encoded_null_char_test) -{ - // there is a potential bug in the way we process ranges if the - // strings are null terminated. - uri::uri instance; - instance << uri::scheme("http") - << uri::host("www.example.com") - << uri::encoded_path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(mailto_builder_test) -{ - uri::uri instance; - instance << uri::scheme("mailto") << uri::path("cpp-netlib@example.com"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("mailto:cpp-netlib@example.com", instance.string()); -} diff --git a/libs/network/test/uri/uri_builder_test.cpp b/libs/network/test/uri/uri_builder_test.cpp deleted file mode 100644 index 3d864d50f..000000000 --- a/libs/network/test/uri/uri_builder_test.cpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) Glyn Matthews 2012. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE URI builder test -#include -#include -#include -#include - - -using namespace boost::network; - - -BOOST_AUTO_TEST_CASE(builder_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(full_uri_builder_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .user_info("user:password") - .host("www.example.com") - .port("80") - .path("/path") - .query("query") - .fragment("fragment") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://user:password@www.example.com/path?query#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(port_test) -{ - uri::uri instance; - uri::builder(instance).scheme("http").host("www.example.com").port(8000).path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com:8000/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(encoded_path_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .port(8000) - .encoded_path("/Path With (Some) Encoded Characters!") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com:8000/Path%20With%20%28Some%29%20Encoded%20Characters%21", instance.string()); -} - -BOOST_AUTO_TEST_CASE(query_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .path("/") - .query("key", "value") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/?key=value", instance.string()); -} - -BOOST_AUTO_TEST_CASE(query_2_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .path("/") - .query("key1", "value1") - .query("key2", "value2") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/?key1=value1&key2=value2", instance.string()); -} - -BOOST_AUTO_TEST_CASE(fragment_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .path("/") - .fragment("fragment") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(from_base_test) -{ - uri::uri instance("http://www.example.com/"); - uri::builder builder(instance); - builder - .path("/") - .fragment("fragment") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/#fragment", instance.string()); -} - -BOOST_AUTO_TEST_CASE(encoded_null_char_test) -{ - // there is a potential bug in the way we process ranges if the - // strings are null terminated. - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host("www.example.com") - .encoded_path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://www.example.com/", instance.string()); -} - -BOOST_AUTO_TEST_CASE(mailto_builder_test) -{ - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("mailto") - .path("cpp-netlib@example.com") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("mailto:cpp-netlib@example.com", instance.string()); -} - -BOOST_AUTO_TEST_CASE(ipv4_address) { - using namespace boost::asio::ip; - uri::uri instance; - uri::builder builder(instance); - builder - .scheme("http") - .host(address_v4::loopback()) - .path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL("http://127.0.0.1/", instance.string()); -} - -//BOOST_AUTO_TEST_CASE(ipv6_address) { -// using namespace boost::asio::ip; -// uri::uri instance; -// uri::builder builder(instance); -// builder -// .scheme("http") -// .host(address_v6::loopback()) -// .path("/") -// ; -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK_EQUAL("http://[::1]/", instance.string()); -//} diff --git a/libs/network/test/uri/uri_encoding_test.cpp b/libs/network/test/uri/uri_encoding_test.cpp deleted file mode 100644 index 6ca37939b..000000000 --- a/libs/network/test/uri/uri_encoding_test.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE URL encoding test -#include -#include -#include -#include -#include - - -using namespace boost::network; - - -BOOST_AUTO_TEST_CASE(encoding_test) { - const std::string unencoded(" !\"#$%&\'()*"); - const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - - std::string instance; - uri::encode(unencoded, std::back_inserter(instance)); - BOOST_CHECK_EQUAL(instance, encoded); -} - -BOOST_AUTO_TEST_CASE(decoding_test) { - const std::string unencoded(" !\"#$%&\'()*"); - const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - - std::string instance; - uri::decode(encoded, std::back_inserter(instance)); - BOOST_CHECK_EQUAL(instance, unencoded); -} diff --git a/libs/network/test/uri/uri_test.cpp b/libs/network/test/uri/uri_test.cpp deleted file mode 100644 index 7a601991d..000000000 --- a/libs/network/test/uri/uri_test.cpp +++ /dev/null @@ -1,504 +0,0 @@ -// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt of copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE URL Test -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace boost::network; - -BOOST_AUTO_TEST_CASE(basic_uri_scheme_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); -} - -BOOST_AUTO_TEST_CASE(basic_uri_user_info_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::user_info(instance), ""); -} - -BOOST_AUTO_TEST_CASE(basic_uri_host_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); -} - -BOOST_AUTO_TEST_CASE(basic_uri_port_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::port(instance), ""); -} - -BOOST_AUTO_TEST_CASE(basic_uri_path_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(basic_uri_query_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::query(instance), ""); -} - -BOOST_AUTO_TEST_CASE(basic_uri_fragment_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::fragment(instance), ""); -} - -BOOST_AUTO_TEST_CASE(basic_uri_value_semantics_test) { - uri::uri original; - uri::uri assigned; - assigned = original; - BOOST_CHECK(original == assigned); - assigned = "http://www.example.com/"; - BOOST_CHECK(original != assigned); - uri::uri copy(assigned); - BOOST_CHECK(copy == assigned); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_scheme_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.scheme_range()); - BOOST_CHECK(instance.begin() == boost::begin(instance.scheme_range())); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_user_info_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(!instance.user_info_range()); - BOOST_CHECK(boost::begin(instance.host_range()) == boost::begin(instance.user_info_range())); - BOOST_CHECK(boost::begin(instance.host_range()) == boost::end(instance.user_info_range())); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_host_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.host_range()); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_port_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(!instance.port_range()); - BOOST_CHECK(boost::end(instance.host_range()) == boost::begin(instance.port_range())); - BOOST_CHECK(boost::end(instance.host_range()) == boost::end(instance.port_range())); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_path_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.path_range()); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); - BOOST_CHECK(instance.end() == boost::end(instance.path_range())); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_query_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(!instance.query_range()); - BOOST_CHECK(instance.end() == boost::begin(instance.query_range())); - BOOST_CHECK(instance.end() == boost::end(instance.query_range())); -} - -BOOST_AUTO_TEST_CASE(basic_uri_range_fragment_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(!instance.fragment_range()); - BOOST_CHECK(instance.end() == boost::begin(instance.fragment_range())); - BOOST_CHECK(instance.end() == boost::end(instance.fragment_range())); -} - -BOOST_AUTO_TEST_CASE(full_uri_scheme_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); -} - -BOOST_AUTO_TEST_CASE(full_uri_user_info_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); -} - -BOOST_AUTO_TEST_CASE(full_uri_host_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); -} - -BOOST_AUTO_TEST_CASE(full_uri_port_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::port(instance), "80"); - BOOST_CHECK(uri::port_us(instance)); - BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); -} - -BOOST_AUTO_TEST_CASE(full_uri_path_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::path(instance), "/path"); -} - -BOOST_AUTO_TEST_CASE(full_uri_query_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::query(instance), "query"); -} - -BOOST_AUTO_TEST_CASE(full_uri_fragment_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_scheme_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.scheme_range()); - BOOST_CHECK(instance.begin() == boost::begin(instance.scheme_range())); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_user_info_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.user_info_range()); - BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_host_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.host_range()); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_port_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.port_range()); - BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_path_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.path_range()); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_query_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.query_range()); - BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_fragment_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(instance.fragment_range()); - BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); - BOOST_CHECK(instance.end() == boost::end(instance.fragment_range())); -} - -BOOST_AUTO_TEST_CASE(mailto_test) { - uri::uri instance("mailto:john.doe@example.com"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "mailto"); - BOOST_CHECK_EQUAL(uri::path(instance), "john.doe@example.com"); -} - -BOOST_AUTO_TEST_CASE(file_test) { - uri::uri instance("file:///bin/bash"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "file"); - BOOST_CHECK_EQUAL(uri::path(instance), "/bin/bash"); -} - -BOOST_AUTO_TEST_CASE(xmpp_test) { - uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "xmpp"); - BOOST_CHECK_EQUAL(uri::path(instance), "example-node@example.com"); - BOOST_CHECK_EQUAL(uri::query(instance), "message;subject=Hello%20World"); -} - -BOOST_AUTO_TEST_CASE(ipv4_address_test) { - uri::uri instance("http://129.79.245.252/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "129.79.245.252"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ipv4_loopback_test) { - uri::uri instance("http://127.0.0.1/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "127.0.0.1"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ipv6_address_test_1) { - uri::uri instance("http://[1080::8:800:200c:417a]/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "[1080:0:0:0:8:800:200C:417A]"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ipv6_address_test_2) { - uri::uri instance("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -//BOOST_AUTO_TEST_CASE(ipv6_loopback_test) { -// uri::uri instance("http://[::1]/"); -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); -// BOOST_CHECK_EQUAL(uri::host(instance), "[::1]"); -// BOOST_CHECK_EQUAL(uri::path(instance), "/"); -//} - -BOOST_AUTO_TEST_CASE(ftp_test) { - uri::uri instance("ftp://john.doe@ftp.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "ftp"); - BOOST_CHECK_EQUAL(uri::user_info(instance), "john.doe"); - BOOST_CHECK_EQUAL(uri::host(instance), "ftp.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(news_test) { - uri::uri instance("news:comp.infosystems.www.servers.unix"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "news"); - BOOST_CHECK_EQUAL(uri::path(instance), "comp.infosystems.www.servers.unix"); -} - -BOOST_AUTO_TEST_CASE(tel_test) { - uri::uri instance("tel:+1-816-555-1212"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "tel"); - BOOST_CHECK_EQUAL(uri::path(instance), "+1-816-555-1212"); -} - -BOOST_AUTO_TEST_CASE(encoded_uri_test) { - uri::uri instance("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); -} - -BOOST_AUTO_TEST_CASE(copy_constructor_test) { - uri::uri instance("http://www.example.com/"); - uri::uri copy = instance; - BOOST_CHECK_EQUAL(instance, copy); -} - -BOOST_AUTO_TEST_CASE(assignment_test) { - uri::uri instance("http://www.example.com/"); - uri::uri copy; - copy = instance; - BOOST_CHECK_EQUAL(instance, copy); -} - -BOOST_AUTO_TEST_CASE(swap_test) { - uri::uri instance("http://www.example.com/"); - uri::uri copy("http://www.example.org/"); - uri::swap(instance, copy); - BOOST_CHECK_EQUAL(instance.string(), "http://www.example.org/"); - BOOST_CHECK_EQUAL(copy.string(), "http://www.example.com/"); -} - -BOOST_AUTO_TEST_CASE(equality_test) { - uri::uri uri_1("http://www.example.com/"); - uri::uri uri_2("http://www.example.com/"); - BOOST_CHECK(uri_1 == uri_2); -} - -BOOST_AUTO_TEST_CASE(equality_test_1) { - uri::uri uri_1("http://www.example.com/"); - std::string uri_2("http://www.example.com/"); - BOOST_CHECK(uri_1 == uri_2); -} - -BOOST_AUTO_TEST_CASE(equality_test_2) { - std::string uri_1("http://www.example.com/"); - uri::uri uri_2("http://www.example.com/"); - BOOST_CHECK(uri_1 == uri_2); -} - -BOOST_AUTO_TEST_CASE(equality_test_3) { - uri::uri uri_1("http://www.example.com/"); - std::string uri_2("http://www.example.com/"); - BOOST_CHECK(uri_1 == uri_2.c_str()); -} - -BOOST_AUTO_TEST_CASE(equality_test_4) { - std::string uri_1("http://www.example.com/"); - uri::uri uri_2("http://www.example.com/"); - BOOST_CHECK(uri_1.c_str() == uri_2); -} - -BOOST_AUTO_TEST_CASE(inequality_test) { - uri::uri uri_1("http://www.example.com/"); - uri::uri uri_2("http://www.example.com/"); - BOOST_CHECK(!(uri_1 != uri_2)); -} - -BOOST_AUTO_TEST_CASE(less_than_test) { - // uri_1 is lexicographically less than uri_2 - uri::uri uri_1("http://www.example.com/"); - uri::uri uri_2("http://www.example.org/"); - BOOST_CHECK(uri_1 < uri_2); -} - -BOOST_AUTO_TEST_CASE(username_test) { - uri::uri instance("ftp://john.doe@ftp.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::username(instance), "john.doe"); -} - -BOOST_AUTO_TEST_CASE(pasword_test) { - uri::uri instance("ftp://john.doe:password@ftp.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::password(instance), "password"); -} - -BOOST_AUTO_TEST_CASE(hierarchical_part_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::hierarchical_part(instance), "user:password@www.example.com:80/path"); -} - -BOOST_AUTO_TEST_CASE(partial_hierarchical_part_test) { - uri::uri instance("http://www.example.com/?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::hierarchical_part(instance), "www.example.com"); -} - -BOOST_AUTO_TEST_CASE(authority_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); -} - -BOOST_AUTO_TEST_CASE(partial_authority_test) { - uri::uri instance("http://www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::authority(instance), "www.example.com"); -} - -BOOST_AUTO_TEST_CASE(http_query_map_test) { - uri::uri instance("http://user:password@www.example.com/path?query=something#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - - std::map queries; - uri::query_map(instance, queries); - BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK_EQUAL(queries.begin()->first, "query"); - BOOST_CHECK_EQUAL(queries.begin()->second, "something"); -} - -BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { - uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); - BOOST_REQUIRE(uri::valid(instance)); - - std::map queries; - uri::query_map(instance, queries); - BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK_EQUAL(queries.begin()->first, "message"); - BOOST_CHECK_EQUAL(queries.begin()->second, ""); - BOOST_CHECK_EQUAL((++queries.begin())->first, "subject"); - BOOST_CHECK_EQUAL((++queries.begin())->second, "Hello%20World"); -} - -BOOST_AUTO_TEST_CASE(range_test) { - const std::string url("http://www.example.com/"); - uri::uri instance(url); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance, url)); -} - -BOOST_AUTO_TEST_CASE(issue_67_test) { - // https://github.com/cpp-netlib/cpp-netlib/issues/67 - const std::string site_name("http://www.google.com/"); - uri::uri bar0; - uri::uri bar1 = site_name; - bar0 = site_name; - BOOST_CHECK(uri::is_valid(bar0)); - BOOST_CHECK(uri::is_valid(bar1)); -} - -BOOST_AUTO_TEST_CASE(from_parts_1) { - BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path?query#fragment"), - uri::from_parts(uri::uri("http://www.example.com/"), "/path", "query", "fragment")); -} - -BOOST_AUTO_TEST_CASE(from_parts_2) { - BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path?query#fragment"), - uri::from_parts("http://www.example.com/", "/path", "query", "fragment")); -} - -BOOST_AUTO_TEST_CASE(from_parts_3) { - BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path?query"), - uri::from_parts("http://www.example.com/", "/path", "query")); -} - -BOOST_AUTO_TEST_CASE(from_parts_4) { - BOOST_CHECK_EQUAL(uri::uri("http://www.example.com/path"), - uri::from_parts("http://www.example.com/", "/path")); -} - -BOOST_AUTO_TEST_CASE(from_file) { - boost::filesystem::path path("/a/path/to/a/file.txt"); - BOOST_CHECK_EQUAL(uri::uri("file:///a/path/to/a/file.txt"), uri::from_file(path)); -} - -BOOST_AUTO_TEST_CASE(issue_104_test) { - // https://github.com/cpp-netlib/cpp-netlib/issues/104 - boost::scoped_ptr instance(new uri::uri("http://www.example.com/")); - uri::uri copy = *instance; - instance.reset(); - BOOST_CHECK_EQUAL(uri::scheme(copy), "http"); -} - -BOOST_AUTO_TEST_CASE(uri_set_test) { - std::set uri_set; - uri_set.insert(uri::uri("http://www.example.com/")); - BOOST_REQUIRE(!uri_set.empty()); - BOOST_CHECK_EQUAL((*uri_set.begin()), uri::uri("http://www.example.com/")); -} - -BOOST_AUTO_TEST_CASE(uri_unordered_set_test) { - boost::unordered_set uri_set; - uri_set.insert(uri::uri("http://www.example.com/")); - BOOST_REQUIRE(!uri_set.empty()); - BOOST_CHECK_EQUAL((*uri_set.begin()), uri::uri("http://www.example.com/")); -} diff --git a/logging/CMakeLists.txt b/logging/CMakeLists.txt new file mode 100644 index 000000000..5f1c1ef7a --- /dev/null +++ b/logging/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +if( CPP-NETLIB_ALWAYS_LOGGING ) + add_definitions( /D NETWORK_ENABLE_LOGGING ) +endif() + +if( NOT CPP-NETLIB_DISABLE_LOGGING ) + add_subdirectory(src) + + # this library name is defined only if we created the target + # if not then it will be empty + set( CPP-NETLIB_LOGGING_LIB cppnetlib-logging ) + + if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) + endif(CPP-NETLIB_BUILD_TESTS) + +endif() diff --git a/logging/src/CMakeLists.txt b/logging/src/CMakeLists.txt new file mode 100644 index 000000000..0eca48291 --- /dev/null +++ b/logging/src/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +include_directories(${CPP-NETLIB_SOURCE_DIR}/logging/src) +set(CPP-NETLIB_LOGGING_SRCS logging.cpp) +add_library(cppnetlib-logging ${CPP-NETLIB_LOGGING_SRCS}) +foreach (src_file ${CPP-NETLIB_LOGGING_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) diff --git a/logging/src/logging.cpp b/logging/src/logging.cpp new file mode 100644 index 000000000..bd38116d4 --- /dev/null +++ b/logging/src/logging.cpp @@ -0,0 +1,58 @@ +// Copyright 2011 A. Joel Lamotte . +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include +#include + +namespace network { namespace logging { + + const char* log_record::UNKNOWN_FILE_NAME = "unknown"; + + +namespace handler +{ + namespace + { + void std_log_handler( const log_record& log ) + { + std::cerr << "[network " << log.filename() << ":" << log.line() << "] " + << log.message() << std::endl; + } + } + + log_record_handler get_std_log_handler() { return &std_log_handler; } + log_record_handler get_default_log_handler() { return &std_log_handler; } +} + + +namespace +{ + // the log handler have to manage itself the thread safety on call + static auto current_log_record_handler = std::make_shared( &handler::std_log_handler ); + +} + + +void set_log_record_handler( log_record_handler handler ) +{ + current_log_record_handler = std::make_shared( handler ); +} + +void log( const log_record& log ) +{ + auto log_handler = current_log_record_handler; + if( log_handler ) + { + (*log_handler)( log ); + } +} + + +}} \ No newline at end of file diff --git a/logging/src/network/logging/logging.hpp b/logging/src/network/logging/logging.hpp new file mode 100644 index 000000000..a9bc0dfeb --- /dev/null +++ b/logging/src/network/logging/logging.hpp @@ -0,0 +1,86 @@ +// Copyright (c) 2012 A. Joel Lamotte . +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_LOGGING_HPP_20121112 +#define NETWORK_LOGGING_HPP_20121112 + +#include +#include + +namespace network { namespace logging { + +class log_record; + +//using log_record_handler = std::function< void (const std::string&) >; // use this when VS can compile it... +typedef std::function< void (const log_record&) > log_record_handler; + +void set_log_record_handler( log_record_handler handler ); +void log( const log_record& message ); + +namespace handler +{ + log_record_handler get_std_log_handler(); + log_record_handler get_default_log_handler(); +} + +/** Helper to build a log record as a stream. */ +class log_record +{ +public: + log_record() + : m_filename( UNKNOWN_FILE_NAME ) + , m_line(0) + {} // = default; + + static const char* UNKNOWN_FILE_NAME; + + // Implicit construction from anything serializable to text. + template< typename TypeOfSomething > + log_record( TypeOfSomething&& message ) + : m_filename( UNKNOWN_FILE_NAME ) + , m_line(0) + { + write( std::forward(message) ); + } + + // Construction with recording context informations. + log_record( std::string filename, unsigned long line ) + : m_filename( filename ) + , m_line( line ) + { + } + + template< typename TypeOfSomething > + log_record& write( TypeOfSomething&& something ) + { + m_text_stream << std::forward(something); + return *this; + } + + template< typename TypeOfSomething > + inline log_record& operator<<( TypeOfSomething&& something ) + { + return write( std::forward(something) ); + } + + std::string message() const { return m_text_stream.str(); } + const std::string& filename() const { return m_filename; } + unsigned long line() const { return m_line; } + +private: + + // disable copy + log_record( const log_record& ); // = delete; + log_record& operator=( const log_record& ); // = delete; + + std::ostringstream m_text_stream; // stream in which we build the message + std::string m_filename; // = UNKNOWN_FILE_NAME; + unsigned long m_line; // = 0; +}; + +}} + + +#endif /* end of include guard: NETWORK_LOGGING_HPP_20121112 */ diff --git a/logging/test/CMakeLists.txt b/logging/test/CMakeLists.txt new file mode 100644 index 000000000..34e70348c --- /dev/null +++ b/logging/test/CMakeLists.txt @@ -0,0 +1,31 @@ +# Copyright (c) A. Joel Lamotte 2012. +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}/uri/src) +include_directories(${CPP-NETLIB_SOURCE_DIR}/message/src) +include_directories(${CPP-NETLIB_SOURCE_DIR}/logging/src) + +if (Boost_FOUND) + set( + TESTS + logging_log_record + logging_custom_handler + ) + foreach (test ${TESTS}) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-logging) + target_link_libraries(cpp-netlib-${test} + ${Boost_LIBRARIES} cppnetlib-logging) + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif() diff --git a/logging/test/logging_custom_handler.cpp b/logging/test/logging_custom_handler.cpp new file mode 100644 index 000000000..989955439 --- /dev/null +++ b/logging/test/logging_custom_handler.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2012 A. Joel Lamotte +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#define BOOST_TEST_MODULE logging log_record +#include +#include + +#include + +using namespace network::logging; + +BOOST_AUTO_TEST_CASE(custom_log_handler_output) { + + std::stringstream log_output; + auto custom_log_handler = [&]( const log_record& log ) + { + log_output << "[CPPNETLIB]<" << log.filename() << ":" << log.line() << "> " + << log.message(); + }; + + const auto line_num = 42; + const auto file_name = "somewhere.cpp"; + const auto message = "At line " + std::to_string(line_num) + " we check the code."; + + set_log_record_handler( custom_log_handler ); + log( log_record( file_name, line_num ) << "At line " << line_num << " we check the code." ); + + const auto result_output = log_output.str(); + + BOOST_CHECK( !result_output.empty() ); + BOOST_CHECK( result_output == "[CPPNETLIB] " + message ); +} diff --git a/logging/test/logging_log_record.cpp b/logging/test/logging_log_record.cpp new file mode 100644 index 000000000..212c8f055 --- /dev/null +++ b/logging/test/logging_log_record.cpp @@ -0,0 +1,78 @@ +// Copyright (c) 2012 A. Joel Lamotte +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#define BOOST_TEST_MODULE logging log_record +#include +#include + +#include +#define NETWORK_ENABLE_LOGGING +#include + +using namespace network::logging; + +BOOST_AUTO_TEST_CASE(default_constructor) { + log_record record; + BOOST_CHECK( record.message() == "" ); + BOOST_CHECK( record.filename() == log_record::UNKNOWN_FILE_NAME ); + BOOST_CHECK( record.line() == 0 ); +} + +BOOST_AUTO_TEST_CASE(cstring_constructor) { + const auto message = "This is a test."; + log_record record( message ); + BOOST_CHECK( record.message() == message ); + BOOST_CHECK( record.filename() == log_record::UNKNOWN_FILE_NAME ); + BOOST_CHECK( record.line() == 0 ); +} + +BOOST_AUTO_TEST_CASE(string_constructor) { + const std::string message("This is a test."); + log_record record( message ); + BOOST_CHECK( record.message() == message ); + BOOST_CHECK( record.filename() == log_record::UNKNOWN_FILE_NAME ); + BOOST_CHECK( record.line() == 0 ); +} + +BOOST_AUTO_TEST_CASE(int_constructor) { + const auto num = 42; + log_record record( num ); + BOOST_CHECK( record.message() == std::to_string( num ) ); + BOOST_CHECK( record.filename() == log_record::UNKNOWN_FILE_NAME ); + BOOST_CHECK( record.line() == 0 ); +} + +BOOST_AUTO_TEST_CASE(info_constructor) { + const auto line_num = 42; + const auto file_name = "somewhere.cpp"; + log_record record( file_name, line_num ); + BOOST_CHECK( record.message() == "" ); + BOOST_CHECK( record.filename() == file_name ); + BOOST_CHECK( record.line() == line_num ); +} + +BOOST_AUTO_TEST_CASE(text_stream) { + const auto line_num = 42; + const auto file_name = "somewhere.cpp"; + const auto message = "At line " + std::to_string(line_num) + " we check the code."; + log_record record( file_name, line_num ); + + record << "At line " << line_num << " we check the code."; + + BOOST_CHECK( record.message() == message ); + BOOST_CHECK( record.filename() == file_name ); + BOOST_CHECK( record.line() == line_num ); +} + +BOOST_AUTO_TEST_CASE(raw_log) { + log( "This is a raw log." ); +} + +BOOST_AUTO_TEST_CASE(macro_log) { + NETWORK_MESSAGE( "This is a log through the macro." ); + NETWORK_MESSAGE( "This is a log through the macro, with a stream! Num=" << 42 << " - OK!" ); +} \ No newline at end of file diff --git a/message/CMakeLists.txt b/message/CMakeLists.txt new file mode 100644 index 000000000..cad1c7ea6 --- /dev/null +++ b/message/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +add_subdirectory(src) + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif(CPP-NETLIB_BUILD_TESTS) diff --git a/message/src/CMakeLists.txt b/message/src/CMakeLists.txt new file mode 100644 index 000000000..4971eaeda --- /dev/null +++ b/message/src/CMakeLists.txt @@ -0,0 +1,52 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +include_directories(${CPP-NETLIB_SOURCE_DIR}/uri/src ${CPP-NETLIB_SOURCE_DIR}/message/src) + +set(CPP-NETLIB_MESSAGE_SRCS message.cpp) +add_library(cppnetlib-message ${CPP-NETLIB_MESSAGE_SRCS}) +add_dependencies(cppnetlib-message cppnetlib-uri) +target_link_libraries(cppnetlib-message cppnetlib-uri) +foreach (src_file ${CPP-NETLIB_MESSAGE_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +set(CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS directives.cpp) +add_library(cppnetlib-message-directives ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS}) +foreach (src_file ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) + +set(CPP-NETLIB_MESSAGE_WRAPPERS_SRCS wrappers.cpp) +add_library(cppnetlib-message-wrappers ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS}) +foreach (src_file ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS}) +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + set_source_files_properties(${src_file} + PROPERTIES COMPILE_FLAGS ${CPP-NETLIB_CXXFLAGS}) +endif() +endforeach(src_file) diff --git a/message/src/directives.cpp b/message/src/directives.cpp new file mode 100644 index 000000000..d2c9400ca --- /dev/null +++ b/message/src/directives.cpp @@ -0,0 +1,15 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This is the directives file where all standard directives on messages are +// pulled in and compiled into a library. + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include diff --git a/message/src/message.cpp b/message/src/message.cpp new file mode 100644 index 000000000..9e9058baf --- /dev/null +++ b/message/src/message.cpp @@ -0,0 +1,15 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This is the conglomeration of all message-related implementation files. All +// we're doing is including all the .ipp files that are relevant. + +#ifdef NETWORK_NO_LIB +#undef NETWORK_NO_LIB +#endif + +#include +#include diff --git a/message/src/network/detail/debug.hpp b/message/src/network/detail/debug.hpp new file mode 100644 index 000000000..8396b1352 --- /dev/null +++ b/message/src/network/detail/debug.hpp @@ -0,0 +1,38 @@ +#ifndef NETWORK_DEBUG_HPP_20110410 +#define NETWORK_DEBUG_HPP_20110410 + +// (c) Copyright 2011 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Copyright 2012 A. Joel Lamotte +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/** NETWORK_MESSAGE is a debugging macro used by cpp-netlib to + print out network-related errors through standard error. This is only + useful when NETWORK_DEBUG is turned on. Otherwise the macro amounts to a + no-op. + + The user can force the logging to be enabled by defining NETWORK_ENABLE_LOGGING. +*/ +#if defined(NETWORK_DEBUG) && !defined(NETWORK_ENABLE_LOGGING) +# define NETWORK_ENABLE_LOGGING +#endif + +#ifdef NETWORK_ENABLE_LOGGING + +# include +# ifndef NETWORK_MESSAGE +# define NETWORK_MESSAGE(msg) { network::logging::log( network::logging::log_record( __FILE__, __LINE__ ) << msg ); } +# endif + +#else + +# ifndef NETWORK_MESSAGE +# define NETWORK_MESSAGE(msg) +# endif + +#endif + + +#endif /* end of include guard: NETWORK_DEBUG_HPP_20110410 */ diff --git a/message/src/network/detail/directive_base.hpp b/message/src/network/detail/directive_base.hpp new file mode 100644 index 000000000..58cd4f319 --- /dev/null +++ b/message/src/network/detail/directive_base.hpp @@ -0,0 +1,20 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ +#define NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ + +/** Defines the base type from which all directives inherit + * to allow friend access to message and other types' internals. + */ +namespace network { namespace detail { + +} // namespace detail + +} // namespace network + +#endif // NETWORK_DETAIL_DIRECTIVE_BASE_HPP__ diff --git a/message/src/network/detail/wrapper_base.hpp b/message/src/network/detail/wrapper_base.hpp new file mode 100644 index 000000000..84b635b60 --- /dev/null +++ b/message/src/network/detail/wrapper_base.hpp @@ -0,0 +1,12 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_DETAIL_WRAPPER_BASE_HPP__ +#define NETWORK_DETAIL_WRAPPER_BASE_HPP__ + +#endif // NETWORK_DETAIL_WRAPPER_BASE_HPP__ + diff --git a/message/src/network/message.hpp b/message/src/network/message.hpp new file mode 100644 index 000000000..072ab1480 --- /dev/null +++ b/message/src/network/message.hpp @@ -0,0 +1,31 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_HPP_20111021 +#define NETWORK_MESSAGE_HPP_20111021 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef NETWORK_DEBUG +#include +#endif + +#endif // NETWORK_MESSAGE_HPP_20111021 diff --git a/message/src/network/message/basic_message.hpp b/message/src/network/message/basic_message.hpp new file mode 100644 index 000000000..1fdc7ac17 --- /dev/null +++ b/message/src/network/message/basic_message.hpp @@ -0,0 +1,48 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_BASIC_MESSAGE_HPP_20110911 +#define NETWORK_MESSAGE_BASIC_MESSAGE_HPP_20110911 + +#include +#include + +namespace network { + +struct basic_storage_pimpl; + +struct basic_storage_base : message_base { + basic_storage_base(); + basic_storage_base(basic_storage_base const &); + basic_storage_base(basic_storage_base &&); + virtual void set_destination(std::string const & destination); + virtual void set_source(std::string const & source); + virtual void append_header(std::string const & name, + std::string const & value); + virtual void remove_headers(std::string const & name); + virtual void remove_headers(); + virtual void set_body(std::string const & body); + virtual void append_body(std::string const & data); + + virtual void get_destination(std::string & destination); + virtual void get_source(std::string & source); + virtual void get_headers(function inserter); + virtual void get_headers(std::string const & name, function inserter); + virtual void get_body(std::string & body); + virtual void get_body(function)> chunk_reader, size_t size); + + virtual void swap(basic_storage_base & other); + + virtual ~basic_storage_base(); + protected: + scoped_ptr pimpl; +}; + +void swap(basic_storage_base & l, basic_storage_base & r); + +} // namespace network + +#endif /* NETWORK_MESSAGE_BASIC_MESSAGE_HPP_20110911 */ diff --git a/message/src/network/message/basic_message.ipp b/message/src/network/message/basic_message.ipp new file mode 100644 index 000000000..6b7b953d1 --- /dev/null +++ b/message/src/network/message/basic_message.ipp @@ -0,0 +1,110 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_BASIC_MESSAGE_IPP_20110911 +#define NETWORK_MESSAGE_BASIC_MESSAGE_IPP_20110911 + +namespace network { + +struct basic_storage_pimpl { + basic_storage_pimpl(); + basic_storage_pimpl(basic_storage_pimpl const &); + + virtual basic_storage_pimpl* clone(); + protected: + friend struct basic_storage_base; + std::string source_, destination_; + typedef std::multimap headers_container_type; + headers_container_type headers_; + std::string body_; +}; + +basic_storage_base::basic_storage_base() +: pimpl(new (std::nothrow) basic_storage_pimpl()) +{} + +basic_storage_base::basic_storage_base(basic_storage_base const & other) +: pimpl(other.clone()) +{} + +void basic_storage_base::set_destination(std::string const & destination) { + pimpl->destination_ = destination; +} + +void basic_storage_base::set_source(std::string const & source) { + pimpl->source_ = source; +} + +void basic_storage_base::append_header(std::string const & name, + std::string const & value) { + pimpl->headers_.insert(std::make_pair(name, value)); +} + +void basic_storage_base::remove_headers(std::string const & name) { + pimpl->headers_.erase(name); +} + +void basic_storage_base::remove_headers() { + basic_storage_pimpl::headers_container_type().swap(pimpl->headers_); +} + +void basic_storage_base::set_body(std::string const & body) { + pimpl->body = body; +} + +void basic_storage_base::append_body(std::string const & data) { + pimpl->body.append(data); +} + +void basic_storage_base::get_destination(std::string & destination) { + destination = pimpl->destination; +} + +void basic_storage_base::get_source(std::string & source) { + source = pimpl->source; +} + +void basic_storage_base::get_headers(function inserter) { + copy(pimpl->headers_, inserter); +} + +void basic_storage_base::get_headers(std::string const & name, function inserter) { + basic_storage_pimpl::headers_container_type::const_iterator + it = pimpl->headers_.find(name), + pe = pimpl->headers_.end(); + for (; it != pe; ++it) + inserter(it->first, it->second); +} + +void basic_storage_base::get_body(std::string & body) { + // TODO use iostreams! + body = pimpl_->body; +} + +void basic_storage_base::get_body(function)> chunk_reader, size_t size) { + // TODO use iostreams! + std::string::const_iterator it = pimpl->body.begin(), + pe = pimpl->body.end(); + std::advance(it, size); + chunk_reader(make_iterator_range(it, pe)); + pimpl->body.assign(it, pe); +} + +basic_storage_base::~basic_storage_base() { + pimpl->reset(); +} + +void basic_storage_base::swap(basic_storage_base & other) { + std::swap(pimpl, other.pimpl); +} + +void swap(basic_storage_base & l, basic_storage_base & r) { + l.swap(r); +} + +} /* network */ + +#endif /* NETWORK_MESSAGE_BASIC_MESSAGE_IPP_20110911 */ diff --git a/message/src/network/message/directives.hpp b/message/src/network/message/directives.hpp new file mode 100644 index 000000000..971226ad0 --- /dev/null +++ b/message/src/network/message/directives.hpp @@ -0,0 +1,22 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_HPP__ +#define NETWORK_MESSAGE_DIRECTIVES_HPP__ + +#include +#include +#include + +namespace network { + +NETWORK_STRING_DIRECTIVE(source); +NETWORK_STRING_DIRECTIVE(destination); +NETWORK_STRING_DIRECTIVE(body); + +} // namespace network + +#endif // NETWORK_MESSAGE_DIRECTIVES_HPP__ diff --git a/message/src/network/message/directives/detail/string_directive.hpp b/message/src/network/message/directives/detail/string_directive.hpp new file mode 100644 index 000000000..503012866 --- /dev/null +++ b/message/src/network/message/directives/detail/string_directive.hpp @@ -0,0 +1,49 @@ +// Copyright 2010-2012 Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 +#define NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 + +#include +#include +#include +#include +#include +#include + +// To create your own string directive, you can use the preprocessor macro +// NETWORK_STRING_DIRECTIVE which takes three parameters: the name of +// the directive, a name for the variable to use in the directive visitor, +// and the body to be implemented in the visitor. An example directive for +// setting the source of a message would look something like this given the +// NETWORK_STRING_DIRECTIVE macro: +// +// NETWORK_STRING_DIRECTIVE(source, source_, +// message.source(source_) +// , message.source=source_); +// + +#ifndef NETWORK_STRING_DIRECTIVE +#define NETWORK_STRING_DIRECTIVE(name) \ + struct name##_directive { \ + std::string const & value; \ + explicit name##_directive(std::string const & value_) \ + : value(value_) {} \ + name##_directive(name##_directive const & other) \ + : value(other.value) {} \ + template \ + void operator()(Message & message) const { \ + message.set_##name(value); \ + } \ + }; \ + \ + inline name##_directive const \ + name (std::string const & input) { \ + return name##_directive(input); \ + } +#endif /* NETWORK_STRING_DIRECTIVE */ + +#endif /* NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 */ diff --git a/message/src/network/message/directives/detail/string_value.hpp b/message/src/network/message/directives/detail/string_value.hpp new file mode 100644 index 000000000..3dc48561b --- /dev/null +++ b/message/src/network/message/directives/detail/string_value.hpp @@ -0,0 +1,40 @@ +// Copyright Dean Michael Berris 2010. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 +#define NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 + +#include +#include +#include +#include +#include +#include +#include + +namespace network { namespace detail { + +template +struct string_value : + mpl::if_< + is_async, + boost::shared_future::type>, + typename mpl::if_< + mpl::or_< + is_sync, + is_same, + is_same + >, + typename string::type, + unsupported_tag + >::type + > +{}; + +} // namespace detail +} // namespace network + +#endif /* NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 */ diff --git a/message/src/network/message/directives/header.hpp b/message/src/network/message/directives/header.hpp new file mode 100644 index 000000000..d2e7fdeff --- /dev/null +++ b/message/src/network/message/directives/header.hpp @@ -0,0 +1,34 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ +#define NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ + +#include + +namespace network { + +namespace impl { + +struct header_directive { + explicit header_directive(std::string const & name, + std::string const & value); + void operator() (message_base & msg) const; + private: + std::string const & name_; + std::string const & value_; +}; + +} // namespace impl + +inline impl::header_directive +header(std::string const & header_name, std::string const & header_value) { + return impl::header_directive(header_name, header_value); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__ diff --git a/message/src/network/message/directives/header.ipp b/message/src/network/message/directives/header.ipp new file mode 100644 index 000000000..2030f8cc5 --- /dev/null +++ b/message/src/network/message/directives/header.ipp @@ -0,0 +1,27 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_IPP_20111021 +#define NETWORK_MESSAGE_DIRECTIVES_IPP_20111021 + +#include +#include + +namespace network { namespace impl { + +header_directive::header_directive(std::string const & name, + std::string const & value): + name_(name), + value_(value) {} + +void header_directive::operator() (message_base & msg) const { + msg.append_header(name_, value_); +} + +} // namespace impl +} // namespace network + +#endif /* NETWORK_MESSAGE_DIRECTIVES_IPP_20111021 */ diff --git a/message/src/network/message/directives/remove_header.hpp b/message/src/network/message/directives/remove_header.hpp new file mode 100644 index 000000000..4e7d8c06a --- /dev/null +++ b/message/src/network/message/directives/remove_header.hpp @@ -0,0 +1,29 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP_20111021 +#define NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP_20111021 + +namespace network { +namespace impl { + +struct remove_header_directive { + explicit remove_header_directive(std::string const & header_name); + void operator() (message_base & msg) const; + private: + std::string const & header_name_; +}; + +} // namespace impl + +inline impl::remove_header_directive const +remove_header(std::string const & header_name) { + return impl::remove_header_directive(header_name); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP_20111021 diff --git a/message/src/network/message/directives/remove_header.ipp b/message/src/network/message/directives/remove_header.ipp new file mode 100644 index 000000000..0c4d9a8af --- /dev/null +++ b/message/src/network/message/directives/remove_header.ipp @@ -0,0 +1,25 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_IPP_20111021 +#define NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_IPP_20111021 + +#include + +namespace network { +namespace impl { + +remove_header_directive::remove_header_directive(std::string const & header_name): + header_name_(header_name) {} + +void remove_header_directive::operator() (message_base & msg) const { + msg.remove_headers(header_name_); +} + +} // namespace impl +} // namespace network + +#endif /* NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_IPP_20111021 */ diff --git a/message/src/network/message/message.hpp b/message/src/network/message/message.hpp new file mode 100644 index 000000000..d1290ee1e --- /dev/null +++ b/message/src/network/message/message.hpp @@ -0,0 +1,79 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MESSAGE_HPP_20111021 +#define NETWORK_MESSAGE_MESSAGE_HPP_20111021 + +#include +#include +#include +#include +#include + +namespace network { + + struct message_pimpl; + + // The common message type. + struct message : message_base { + // Nested types + typedef boost::iterator_range< + std::multimap::const_iterator> + headers_range; + + // Constructors + message(); + message(message const & other); +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + message(message && other) = default; +#endif // !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + + // Assignment + message& operator=(message const &other); + message& operator=(message &&other); + + // Mutators + virtual void set_destination(std::string const & destination); + virtual void set_source(std::string const & source); + virtual void append_header(std::string const & name, + std::string const & value); + virtual void remove_headers(std::string const & name); + virtual void remove_headers(); + virtual void set_body(std::string const & body); + virtual void append_body(std::string const & data); + + // Retrievers + virtual void get_destination(std::string & destination) const; + virtual void get_source(std::string & source) const; + virtual void get_headers(std::function inserter) const; + virtual void get_headers(std::string const & name, + std::function inserter) const; + virtual void get_headers(std::function predicate, + std::function inserter) const; + virtual void get_body(std::string & body) const; + virtual void get_body(std::function chunk_reader, size_t size) const; + + void swap(message & other); + + // Destructor + virtual ~message(); + private: + message_pimpl * pimpl; + }; + + inline void swap(message & left, message & right) { + left.swap(right); + } + + template + message_base & operator<< (message_base & msg, Directive directive) { + directive(msg); + return msg; + } + +} // namespace network + +#endif /* NETWORK_MESSAGE_MESSAGE_HPP_20111021 */ diff --git a/message/src/network/message/message.ipp b/message/src/network/message/message.ipp new file mode 100644 index 000000000..6afc155e1 --- /dev/null +++ b/message/src/network/message/message.ipp @@ -0,0 +1,213 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_IPP_20111020 +#define NETWORK_MESSAGE_IPP_20111020 + +#include +#include +#include +#include + +namespace network { + + struct message_pimpl { + message_pimpl() : + destination_(), + source_(), + headers_(), + body_(), + body_read_pos(0) + {} + + void set_destination(std::string const & destination) { + destination_ = destination; + } + + void set_source(std::string const & source) { + source_ = source; + } + + void append_header(std::string const & name, + std::string const & value) { + headers_.insert(std::make_pair(name, value)); + } + + void remove_headers(std::string const & name) { + headers_.erase(name); + } + + void remove_headers() { + std::multimap().swap(headers_); + } + + void set_body(std::string const & body) { + body_ = body; + } + + void append_body(std::string const & data) { + body_.append(data); + } + + // Retrievers + void get_destination(std::string & destination) const { + destination = destination_; + } + + void get_source(std::string & source) const { + source = source_; + } + + void get_headers(std::function inserter) const { + std::multimap::const_iterator it = headers_.begin(), + end = headers_.end(); + for (; it != end; ++it) inserter(it->first, it->second); + } + + void get_headers(std::string const & name, + std::function inserter) const { + std::multimap::const_iterator it = headers_.find(name), + end= headers_.end(); + while (it != end) { + inserter(it->first, it->second); + ++it; + } + } + + void get_headers(std::function predicate, + std::function inserter) const { + std::multimap::const_iterator it = headers_.begin(), + end = headers_.end(); + while (it != end) { + if (predicate(it->first, it->second)) + inserter(it->first, it->second); + ++it; + } + } + + void get_body(std::string & body) { + body = body_; + } + + void get_body(std::function chunk_reader, size_t size) const { + if (body_read_pos == body_.size()) chunk_reader(body_.end(), 0); + std::string::const_iterator it = body_.begin(), + end = body_.end(); + std::advance(it, body_read_pos); + size_t max_size = std::distance(it, end); + size_t max_read = std::min(max_size, size); + std::string::const_iterator start = it; + end = start; + std::advance(end, max_read); + body_read_pos += max_read; + chunk_reader(start, max_read); + } + + message_pimpl * clone() { + message_pimpl * other = new(std::nothrow) message_pimpl; + other->destination_ = this->destination_; + other->source_ = this->source_; + other->headers_ = this->headers_; + other->body_ = this->body_; + return other; + } + + private: + std::string destination_, source_; + std::multimap headers_; + // TODO: use Boost.IOStreams here later on. + std::string body_; + mutable size_t body_read_pos; + }; + + message::message() + : pimpl(new (std::nothrow) message_pimpl) + {} + + message::message(message const & other) + : pimpl(other.pimpl->clone()) + {} + + message& message::operator=(message const &other) { + *pimpl = *other.pimpl; + return *this; + } + + message& message::operator=(message &&other) { + *pimpl = *std::move(other.pimpl); + return *this; + } + + message::~message() { + delete pimpl; + } + + void message::set_destination(std::string const & destination) { + pimpl->set_destination(destination); + } + + void message::set_source(std::string const & source) { + pimpl->set_source(source); + } + + void message::append_header(std::string const & name, + std::string const & value) { + pimpl->append_header(name, value); + } + + void message::remove_headers(std::string const & name) { + pimpl->remove_headers(name); + } + + void message::remove_headers() { + pimpl->remove_headers(); + } + + void message::set_body(std::string const & body) { + pimpl->set_body(body); + } + + void message::append_body(std::string const & data) { + pimpl->append_body(data); + } + + void message::get_destination(std::string & destination) const { + pimpl->get_destination(destination); + } + + void message::get_source(std::string & source) const { + pimpl->get_source(source); + } + + void message::get_headers(std::function inserter) const { + pimpl->get_headers(inserter); + } + + void message::get_headers(std::string const & name, + std::function inserter) const { + pimpl->get_headers(name, inserter); + } + + void message::get_headers(std::function predicate, + std::function inserter) const { + pimpl->get_headers(predicate, inserter); + } + + void message::get_body(std::string & body) const { + pimpl->get_body(body); + } + + void message::get_body(std::function chunk_reader, size_t size) const { + pimpl->get_body(chunk_reader, size); + } + + void message::swap(message & other) { + std::swap(this->pimpl, other.pimpl); + } + +} /* network */ + +#endif /* NETWORK_MESSAGE_IPP_20111020 */ diff --git a/message/src/network/message/message_base.hpp b/message/src/network/message/message_base.hpp new file mode 100644 index 000000000..74d268fc8 --- /dev/null +++ b/message/src/network/message/message_base.hpp @@ -0,0 +1,41 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_BASE_HPP_20110910 +#define NETWORK_MESSAGE_BASE_HPP_20110910 + +#include +#include + +namespace network { + +struct message_base { + // Mutators + virtual void set_destination(std::string const & destination) = 0; + virtual void set_source(std::string const & source) = 0; + virtual void append_header(std::string const & name, + std::string const & value) = 0; + virtual void remove_headers(std::string const & name) = 0; + virtual void remove_headers() = 0; + virtual void set_body(std::string const & body) = 0; + virtual void append_body(std::string const & data) = 0; + + // Retrievers + virtual void get_destination(std::string & destination) const = 0; + virtual void get_source(std::string & source) const = 0; + virtual void get_headers(std::function inserter) const = 0; + virtual void get_headers(std::string const & name, std::function inserter) const = 0; + virtual void get_headers(std::function predicate, std::function inserter) const = 0; + virtual void get_body(std::function chunk_reader, size_t size) const = 0; + virtual void get_body(std::string & body) const = 0; + + // Destructor + virtual ~message_base() = 0; // pure virtual +}; + +} // namespace network + +#endif /* NETWORK_MESSAGE_BASE_HPP_20110910 */ diff --git a/message/src/network/message/message_base.ipp b/message/src/network/message/message_base.ipp new file mode 100644 index 000000000..ee7380a12 --- /dev/null +++ b/message/src/network/message/message_base.ipp @@ -0,0 +1,21 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_BASE_IPP_20111020 +#define NETWORK_MESSAGE_BASE_IPP_20111020 + +#include + +namespace network { + +message_base::~message_base() { + // This is never used, but is required even though message_base's destructor + // is a pure virtual one. +} + +} // namespace network + +#endif /* NETWORK_MESSAGE_BASE_IPP_20111020 */ diff --git a/message/src/network/message/message_concept.hpp b/message/src/network/message/message_concept.hpp new file mode 100644 index 000000000..6f06d4d94 --- /dev/null +++ b/message/src/network/message/message_concept.hpp @@ -0,0 +1,65 @@ +// Copyright (c) Glyn Matthews 2010. +// Copyright 2010 (c) Dean Michael Berris. +// Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 +#define NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 + +#include +#include +#include +#include +#include + +namespace network { + + template + struct Message + : boost::DefaultConstructible, + boost::CopyConstructible, + boost::Assignable { + + BOOST_CONCEPT_USAGE(Message) { + M message_; + swap(message, message_); + typedef std::string source_type; + typedef std::string destination_type; + typedef std::string body_type; + typedef std::string header_key_type; + typedef std::string header_value_type; + + std::multimap headers_ = headers(message); + std::string body_ = body(message); + std::string source_ = source(message); + std::string destination_ = destination(message); + + message << source(source_type()) + << destination(destination_type()) + << header(std::string(), std::string()) + << body(body_type()); + + add_header(message, std::string(), std::string()); + remove_header(message, std::string()); + clear_headers(message); + source(message, source_type()); + destination(message, destination_type()); + body(message, body_type()); + + (void)headers_; + (void)body_; + (void)source_; + (void)destination_; + } + + private: + + M message; + }; + +} // namespace network + +#endif // NETWORK_MESSAGE_MESSAGE_CONCEPT_HPP_20100903 diff --git a/message/src/network/message/modifiers.hpp b/message/src/network/message/modifiers.hpp new file mode 100644 index 000000000..89eef3572 --- /dev/null +++ b/message/src/network/message/modifiers.hpp @@ -0,0 +1,17 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MODIFIERS_HPP_20111201 +#define NETWORK_MESSAGE_MODIFIERS_HPP_20111201 + +#include +#include +#include +#include +#include +#include + +#endif // NETWORK_MESSAGE_MODIFIERS_HPP_20111201 diff --git a/message/src/network/message/modifiers/add_header.hpp b/message/src/network/message/modifiers/add_header.hpp new file mode 100644 index 000000000..5493f9752 --- /dev/null +++ b/message/src/network/message/modifiers/add_header.hpp @@ -0,0 +1,24 @@ +#ifndef NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 +#define NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 + +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace network { + +inline void add_header(message_base & message, + std::string const & key, + std::string const & value) { + message.append_header(key, value); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_MODIFIER_ADD_HEADER_HPP_20100824 diff --git a/message/src/network/message/modifiers/body.hpp b/message/src/network/message/modifiers/body.hpp new file mode 100644 index 000000000..f1db40a2a --- /dev/null +++ b/message/src/network/message/modifiers/body.hpp @@ -0,0 +1,22 @@ +#ifndef NETWORK_MODIFIERS_BODY_HPP_20100824 +#define NETWORK_MODIFIERS_BODY_HPP_20100824 + +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +namespace network { + +inline void body(message_base & message, std::string const & body_) { + message.set_body(body_); +} + +inline void append_body(message_base & message, std::string const & data) { + message.append_body(data); +} + +} // namespace network + +#endif // NETWORK_MODIFIERS_BODY_HPP_20100824 diff --git a/message/src/network/message/modifiers/clear_headers.hpp b/message/src/network/message/modifiers/clear_headers.hpp new file mode 100644 index 000000000..1d9692404 --- /dev/null +++ b/message/src/network/message/modifiers/clear_headers.hpp @@ -0,0 +1,20 @@ +#ifndef NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 +#define NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 + +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace network { + +inline void clear_headers(message_base & message) { + message.remove_headers(); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824 diff --git a/message/src/network/message/modifiers/destination.hpp b/message/src/network/message/modifiers/destination.hpp new file mode 100644 index 000000000..a048466e0 --- /dev/null +++ b/message/src/network/message/modifiers/destination.hpp @@ -0,0 +1,18 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 +#define NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 + +namespace network { + +inline void destination(message_base & message, std::string const & destination_) { + message.set_destination(destination_); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824 diff --git a/message/src/network/message/modifiers/remove_header.hpp b/message/src/network/message/modifiers/remove_header.hpp new file mode 100644 index 000000000..8902ef5bf --- /dev/null +++ b/message/src/network/message/modifiers/remove_header.hpp @@ -0,0 +1,22 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 +#define NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 + +#include +#include + +namespace network { + +inline +void remove_header(message_base & message, std::string const & key) { + message.remove_headers(key); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 diff --git a/message/src/network/message/modifiers/source.hpp b/message/src/network/message/modifiers/source.hpp new file mode 100644 index 000000000..3ddedb1c0 --- /dev/null +++ b/message/src/network/message/modifiers/source.hpp @@ -0,0 +1,18 @@ +// Copyright 2010 (c) Dean Michael Berris +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 +#define NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 + +namespace network { + +inline void source(message_base & message, std::string const & source_) { + message.set_source(source_); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824 diff --git a/message/src/network/message/transformers.hpp b/message/src/network/message/transformers.hpp new file mode 100644 index 000000000..fdfda264c --- /dev/null +++ b/message/src/network/message/transformers.hpp @@ -0,0 +1,61 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_TRANSFORMERS_HPP +#define NETWORK_MESSAGE_TRANSFORMERS_HPP + +/** transformers.hpp + * + * Pulls in all the transformers files. + */ +#include +#include +#include +#include +#include + +namespace network { +namespace impl { + +template +struct get_real_algorithm { + typedef typename boost::function_traits< + typename boost::remove_pointer< + Algorithm + >::type + > + ::result_type:: + template type< + typename boost::function_traits< + typename boost::remove_pointer< + Selector + >::type + >::result_type + > type; +}; + +template +struct transform_impl : public get_real_algorithm::type {}; + +} // namspace impl + +template +inline impl::transform_impl +transform(Algorithm, Selector) { + return impl::transform_impl(); +} + +template +message_base & operator<< ( + message_base & msg_, + impl::transform_impl const & transformer) { + transformer(msg_); + return msg_; +} + +} // namespace network + +#endif // NETWORK_MESSAGE_TRANSFORMERS_HPP diff --git a/message/src/network/message/transformers/selectors.hpp b/message/src/network/message/transformers/selectors.hpp new file mode 100644 index 000000000..46cf657cd --- /dev/null +++ b/message/src/network/message/transformers/selectors.hpp @@ -0,0 +1,50 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP +#define NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP + +namespace network { +namespace selectors { +struct source_selector; +struct destination_selector; +} // namespace selectors + +selectors::source_selector source_(selectors::source_selector); +selectors::destination_selector destination_(selectors::destination_selector); + +namespace selectors { + +struct source_selector { + private: + source_selector() {}; + source_selector(source_selector const &) {}; + friend source_selector network::source_(source_selector); +}; + +struct destination_selector { + private: + destination_selector() {}; + destination_selector(destination_selector const &) {}; + friend destination_selector network::destination_(destination_selector); +}; + +} // namespace selectors + +typedef selectors::source_selector (*source_selector_t)(selectors::source_selector); +typedef selectors::destination_selector (*destination_selector_t)(selectors::destination_selector); + +inline selectors::source_selector source_(selectors::source_selector) { + return selectors::source_selector(); +} + +inline selectors::destination_selector destination_(selectors::destination_selector) { + return selectors::destination_selector(); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_TRANSFORMERS_SELECTORS_HPP diff --git a/message/src/network/message/transformers/to_lower.hpp b/message/src/network/message/transformers/to_lower.hpp new file mode 100644 index 000000000..717776510 --- /dev/null +++ b/message/src/network/message/transformers/to_lower.hpp @@ -0,0 +1,84 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP +#define NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP + +#include +#include + +/** to_lower.hpp + * + * Implements the to_lower transformer. This applies + * the to_lower string algorithm to a string, which + * is selected by the appropriate selector. + * + * This defines a type, to be applied using template + * metaprogramming on the selected string target. + */ +namespace network { +namespace impl { + +template +struct to_lower_transformer {}; + +template <> +struct to_lower_transformer { + void operator() (message_base & message_) const { + std::string source_; + message_.get_source(source_); + boost::to_lower(source_); + message_.set_source(source_); + } + + protected: + ~to_lower_transformer() { } +}; + +template <> +struct to_lower_transformer { + void operator() (message_base & message_) const { + std::string destination_; + message_.get_destination(destination_); + boost::to_lower(destination_); + message_.set_destination(destination_); + } + + protected: + ~to_lower_transformer() { }; +}; + +} // namespace impl + +namespace detail { +struct to_lower_placeholder_helper; +} // namespace detail + +detail::to_lower_placeholder_helper to_lower_(detail::to_lower_placeholder_helper); + +namespace detail { + +struct to_lower_placeholder_helper { + template + struct type : public impl::to_lower_transformer { }; + private: + to_lower_placeholder_helper() {} + to_lower_placeholder_helper(to_lower_placeholder_helper const &) {} + friend to_lower_placeholder_helper network::to_lower_(to_lower_placeholder_helper); +}; + +} // namespace detail + +typedef detail::to_lower_placeholder_helper (*to_lower_placeholder)(detail::to_lower_placeholder_helper); + +inline detail::to_lower_placeholder_helper to_lower_(detail::to_lower_placeholder_helper) { + return detail::to_lower_placeholder_helper(); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_TRANSFORMERS_TO_LOWER_HPP diff --git a/message/src/network/message/transformers/to_upper.hpp b/message/src/network/message/transformers/to_upper.hpp new file mode 100644 index 000000000..a5698653c --- /dev/null +++ b/message/src/network/message/transformers/to_upper.hpp @@ -0,0 +1,85 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP +#define NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP + +#include +#include + +/** to_upper.hpp + * + * Implements the to_upper transformer. This applies + * the to_upper string algorithm to a string, which + * is selected by the appropriate selector. + * + * This defines a type, to be applied using template + * metaprogramming on the selected string target. + */ +namespace network { +namespace impl { + +template +struct to_upper_transformer {}; + +template <> +struct to_upper_transformer { + void operator() (message_base & message_) const { + std::string source_; + message_.get_source(source_); + boost::to_upper(source_); + message_.set_source(source_); + } + + protected: + ~to_upper_transformer() {}; +}; + +template <> +struct to_upper_transformer { + void operator() (message_base & message_) const { + std::string destination_; + message_.get_destination(destination_); + boost::to_upper(destination_); + message_.set_destination(destination_); + } + + protected: + ~to_upper_transformer() {}; +}; + +} // namespace impl + +namespace detail { + struct to_upper_placeholder_helper; +} // namespace detail + +detail::to_upper_placeholder_helper to_upper_(detail::to_upper_placeholder_helper); + +namespace detail { + +struct to_upper_placeholder_helper { + template + struct type : public impl::to_upper_transformer { }; + + private: + to_upper_placeholder_helper() {} + to_upper_placeholder_helper(to_upper_placeholder_helper const &) {} + friend to_upper_placeholder_helper network::to_upper_(to_upper_placeholder_helper); +}; + +} // namespace detail + +typedef detail::to_upper_placeholder_helper (*to_upper_placeholder)(detail::to_upper_placeholder_helper); + +inline detail::to_upper_placeholder_helper to_upper_(detail::to_upper_placeholder_helper) { + return detail::to_upper_placeholder_helper(); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_TRANSFORMERS_TO_UPPER_HPP diff --git a/message/src/network/message/wrappers.hpp b/message/src/network/message/wrappers.hpp new file mode 100644 index 000000000..dd943448c --- /dev/null +++ b/message/src/network/message/wrappers.hpp @@ -0,0 +1,19 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_HPP +#define NETWORK_MESSAGE_WRAPPERS_HPP + +/** wrappers.hpp + * + * Pulls in all the wrapper header files. + */ +#include +#include +#include +#include + +#endif // __NETWORK_MESSAGE_WRAPPERS_HPP__ diff --git a/message/src/network/message/wrappers/body.hpp b/message/src/network/message/wrappers/body.hpp new file mode 100644 index 000000000..198661bf3 --- /dev/null +++ b/message/src/network/message/wrappers/body.hpp @@ -0,0 +1,41 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_BODY_HPP_20110930 +#define NETWORK_MESSAGE_WRAPPERS_BODY_HPP_20110930 + +#include +#include +#include +#include + +namespace network { + +struct body_wrapper { + explicit body_wrapper(message_base const & message); + operator std::string () const; + std::size_t size() const; + operator boost::iterator_range () const; + std::string::const_iterator begin() const; + std::string::const_iterator end() const; + private: + message_base const & message_; + mutable boost::optional cache_; +}; + +inline std::ostream & operator<<(std::ostream & os, body_wrapper const & body) { + os << static_cast(body); + return os; +} + +inline body_wrapper const +body(message_base const & message_) { + return body_wrapper(message_); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_WRAPPERS_BODY_HPP diff --git a/message/src/network/message/wrappers/body.ipp b/message/src/network/message/wrappers/body.ipp new file mode 100644 index 000000000..e6ccd6caf --- /dev/null +++ b/message/src/network/message/wrappers/body.ipp @@ -0,0 +1,69 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_BODY_IPP_20111021 +#define NETWORK_MESSAGE_WRAPPERS_BODY_IPP_20111021 + +#include + +namespace network { + +body_wrapper::body_wrapper(message_base const & message): + message_(message) {} + +body_wrapper::operator std::string () const { + if (cache_) { + return *cache_; + } + std::string tmp; + message_.get_body(tmp); + cache_ = tmp; + return *cache_; +} + +std::size_t body_wrapper::size() const { + if (cache_) { + return cache_->size(); + } + std::string tmp; + message_.get_body(tmp); + cache_ = tmp; + return cache_->size(); +} + +body_wrapper::operator boost::iterator_range () const { + if (cache_) { + return boost::make_iterator_range(*cache_); + } + std::string tmp; + message_.get_body(tmp); + cache_ = tmp; + return boost::make_iterator_range(*cache_); +} + +std::string::const_iterator body_wrapper::begin() const { + if (cache_) { + return cache_->begin(); + } + std::string tmp; + message_.get_body(tmp); + cache_ = tmp; + return cache_->begin(); +} + +std::string::const_iterator body_wrapper::end() const { + if (cache_) { + return cache_->end(); + } + std::string tmp; + message_.get_body(tmp); + cache_ = tmp; + return cache_->end(); +} + +} /* network */ + +#endif /* NETWORK_MESSAGE_WRAPPERS_BODY_IPP_20111021 */ diff --git a/message/src/network/message/wrappers/destination.hpp b/message/src/network/message/wrappers/destination.hpp new file mode 100644 index 000000000..464fd546d --- /dev/null +++ b/message/src/network/message/wrappers/destination.hpp @@ -0,0 +1,33 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP +#define NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP + +#include + +namespace network { + +struct destination_wrapper { + explicit destination_wrapper(message_base const & message); + operator std::string () const; + private: + message_base const & message_; + mutable boost::optional cache_; +}; + +inline destination_wrapper const +destination(message_base const & message_) { + return destination_wrapper(message_); +} + +inline std::ostream & operator<< (std::ostream &os, destination_wrapper const &d) { + return os << static_cast(d); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP diff --git a/message/src/network/message/wrappers/destination.ipp b/message/src/network/message/wrappers/destination.ipp new file mode 100644 index 000000000..3a7b7dfb6 --- /dev/null +++ b/message/src/network/message/wrappers/destination.ipp @@ -0,0 +1,29 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_DESTINATION_IPP_20111021 +#define NETWORK_MESSAGE_WRAPPERS_DESTINATION_IPP_20111021 + +#include + +namespace network { + +destination_wrapper::destination_wrapper(message_base const & message): + message_(message) {} + +destination_wrapper::operator std::string () const { + if (cache_) { + return *cache_; + } + std::string tmp; + message_.get_destination(tmp); + cache_ = tmp; + return *cache_; +} + +} // namespace network + +#endif /* NETWORK_MESSAGE_WRAPPERS_DESTINATION_IPP_20111021 */ diff --git a/message/src/network/message/wrappers/headers.hpp b/message/src/network/message/wrappers/headers.hpp new file mode 100644 index 000000000..18355e5d0 --- /dev/null +++ b/message/src/network/message/wrappers/headers.hpp @@ -0,0 +1,32 @@ +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ +#define NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ + +#include + +namespace network { + +struct message_base; + +struct headers_wrapper { + typedef std::multimap container_type; + explicit headers_wrapper(message_base const & message); + operator container_type () const; + private: + message_base const & message_; +}; + +/// Factory method to create the right wrapper object +inline headers_wrapper const +headers(message_base const & message_) { + return headers_wrapper(message_); +} + +} // namespace network + +#endif // __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__ diff --git a/message/src/network/message/wrappers/headers.ipp b/message/src/network/message/wrappers/headers.ipp new file mode 100644 index 000000000..812b0966f --- /dev/null +++ b/message/src/network/message/wrappers/headers.ipp @@ -0,0 +1,40 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_HEADERS_IPP_20110911 +#define NETWORK_MESSAGE_WRAPPERS_HEADERS_IPP_20110911 + +#include +#include +#include + +namespace network { + +headers_wrapper::headers_wrapper(message_base const & message) +: message_(message) +{} + +template +struct kv_inserter { + kv_inserter(Map & m) + : m_(m) {} + void operator() (std::string const & k, std::string const & v) const { + m_.insert(std::make_pair(k, v)); + } + private: + Map & m_; +}; + +headers_wrapper::operator headers_wrapper::container_type () const { + container_type tmp; + kv_inserter inserter(tmp); + message_.get_headers(inserter); + return tmp; +} + +} /* network */ + +#endif /* NETWORK_MESSAGE_WRAPPERS_HEADERS_IPP_20110911 */ diff --git a/message/src/network/message/wrappers/source.hpp b/message/src/network/message/wrappers/source.hpp new file mode 100644 index 000000000..7f26b61ba --- /dev/null +++ b/message/src/network/message/wrappers/source.hpp @@ -0,0 +1,33 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP_20111021 +#define NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP_20111021 + +#include + +namespace network { + +struct source_wrapper { + explicit source_wrapper(message_base const & message); + operator std::string () const; + private: + message_base const & message_; + mutable boost::optional cache_; +}; + +inline source_wrapper const +source(message_base const & message_) { + return source_wrapper(message_); +} + +inline std::ostream & operator<<(std::ostream &os, source_wrapper const &s) { + return os << static_cast(s); +} + +} // namespace network + +#endif // NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP_20111021 diff --git a/message/src/network/message/wrappers/source.ipp b/message/src/network/message/wrappers/source.ipp new file mode 100644 index 000000000..f32c0e507 --- /dev/null +++ b/message/src/network/message/wrappers/source.ipp @@ -0,0 +1,29 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef NETWORK_MESSAGE_WRAPPERS_SOURCE_IPP_20111021 +#define NETWORK_MESSAGE_WRAPPERS_SOURCE_IPP_20111021 + +#include + +namespace network { + +source_wrapper::source_wrapper(message_base const & message): + message_(message) {} + +source_wrapper::operator std::string () const { + if (cache_) { + return *cache_; + } + std::string tmp; + message_.get_source(tmp); + cache_ = tmp; + return *cache_; +} + +} /* network */ + +#endif /* NETWORK_MESSAGE_WRAPPERS_SOURCE_IPP_20111021 */ diff --git a/message/src/network/message_fwd.hpp b/message/src/network/message_fwd.hpp new file mode 100644 index 000000000..62430d325 --- /dev/null +++ b/message/src/network/message_fwd.hpp @@ -0,0 +1,17 @@ +// Copyright (c) Glyn Matthews 2008. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef MESSAGE_FWS_INC_20120928 +#define MESSAGE_FWS_INC_20120928 + +namespace network { + +template +struct basic_message; + +} // namespace network + +#endif // MESSAGE_FWS_INC_20120928 diff --git a/message/src/wrappers.cpp b/message/src/wrappers.cpp new file mode 100644 index 000000000..0eb21567b --- /dev/null +++ b/message/src/wrappers.cpp @@ -0,0 +1,13 @@ +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This file conglomerates all the standard wrappers that come with cpp-netlib. +// It just includes all the implementation files that get turned into a library. + +#include +#include +#include +#include diff --git a/message/test/CMakeLists.txt b/message/test/CMakeLists.txt new file mode 100644 index 000000000..e5fd3dcbc --- /dev/null +++ b/message/test/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}/uri/src) +include_directories(${CPP-NETLIB_SOURCE_DIR}/message/src) + +if (Boost_FOUND) + set( + TESTS + message_test + message_transform_test + ) + foreach (test ${TESTS}) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri cppnetlib-message cppnetlib-message-directives cppnetlib-message-wrappers) + target_link_libraries(cpp-netlib-${test} + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-message cppnetlib-message-directives cppnetlib-message-wrappers) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif (Boost_FOUND) diff --git a/message/test/message_test.cpp b/message/test/message_test.cpp new file mode 100644 index 000000000..63b958c9c --- /dev/null +++ b/message/test/message_test.cpp @@ -0,0 +1,83 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE message test +#include +#include +#include +#include + +using namespace network; + +/** + * Defines a set of template functions that can be used to test + * generic code. + */ + +BOOST_AUTO_TEST_CASE(copy_constructor_test) { + message instance; + instance << header("name", "value"); + message copy(instance); + headers_wrapper::container_type const &headers_ = headers(copy); + BOOST_CHECK_EQUAL(headers_.count("name"), static_cast(1)); + message::headers_range range = headers_.equal_range("name"); + BOOST_CHECK (!boost::empty(range)); +} + +BOOST_AUTO_TEST_CASE(swap_test) { + message instance; + instance << header("name", "value"); + message other; + swap(instance, other); + headers_wrapper::container_type const &instance_headers = headers(instance); + headers_wrapper::container_type const &other_headers = headers(other); + BOOST_CHECK_EQUAL (instance_headers.count("name"), static_cast(0)); + BOOST_CHECK_EQUAL (other_headers.count("name"), static_cast(1)); +} + +BOOST_AUTO_TEST_CASE(headers_directive_test) { + message instance; + instance << header("name", "value"); + headers_wrapper::container_type const &instance_headers = headers(instance); + BOOST_CHECK_EQUAL ( instance_headers.count("name"), static_cast(1) ); + message::headers_range range = instance_headers.equal_range("name"); + BOOST_CHECK (boost::begin(range) != boost::end(range)); +} + +BOOST_AUTO_TEST_CASE(body_directive_test) { + message instance; + instance << ::network::body("body"); + std::string body_string = body(instance); + BOOST_CHECK ( body_string == "body" ); +} + +BOOST_AUTO_TEST_CASE(source_directive_test) { + message instance; + instance << ::network::source("source"); + std::string source_string = source(instance); + BOOST_CHECK ( source_string == "source" ); +} + +BOOST_AUTO_TEST_CASE(destination_directive_test) { + message instance; + instance << destination("destination"); + std::string const & destination_ = destination(instance); + BOOST_CHECK ( destination_ == "destination" ); +} + +BOOST_AUTO_TEST_CASE(remove_header_directive_test) { + message instance; + instance << header("name", "value") + << remove_header("name"); + headers_wrapper::container_type const &instance_headers = + headers(instance); + message::headers_range range = instance_headers.equal_range("name"); + BOOST_CHECK ( boost::begin(range) == boost::end(range) ); +} diff --git a/message/test/message_transform_test.cpp b/message/test/message_transform_test.cpp new file mode 100644 index 000000000..fc62c86e5 --- /dev/null +++ b/message/test/message_transform_test.cpp @@ -0,0 +1,52 @@ + +// Copyright Dean Michael Berris 2007. +// Copyright 2012 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BUILD_SHARED_LIBS +# define BOOST_TEST_DYN_LINK +#endif +#define BOOST_TEST_MODULE message test +#include +#include +#include +#include + +BOOST_AUTO_TEST_CASE ( message_transform_toupper ) { + using namespace network; + + message msg; + msg << source("me"); + std::string const & source_orig = source(msg); + BOOST_CHECK_EQUAL ( source_orig, "me" ); + msg << transform(to_upper_, source_); + std::string const & source_upper = source(msg); + BOOST_CHECK_EQUAL ( source_upper, "ME" ); + msg << destination("you"); + std::string const & destination_orig = destination(msg); + BOOST_CHECK_EQUAL ( destination_orig, "you"); + msg << transform(to_upper_, destination_); + std::string const & destination_upper = destination(msg); + BOOST_CHECK_EQUAL ( destination_upper, "YOU"); +} + +BOOST_AUTO_TEST_CASE ( message_transform_tolower ) { + using namespace network; + + message msg; + msg << source("ME"); + std::string const & source_orig = source(msg); + BOOST_CHECK_EQUAL ( source_orig, "ME" ); + msg << transform(to_lower_, source_); + std::string const & source_lower = source(msg); + BOOST_CHECK_EQUAL ( source_lower, "me" ); + msg << destination("YOU"); + std::string const & destination_orig = destination(msg); + BOOST_CHECK_EQUAL ( destination_orig, "YOU" ); + msg << transform(to_lower_, destination_); + std::string const & destination_lower = destination(msg); + BOOST_CHECK_EQUAL ( destination_lower, "you" ); +} + diff --git a/mime/CMakeLists.txt b/mime/CMakeLists.txt new file mode 100644 index 000000000..b5c1ce909 --- /dev/null +++ b/mime/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif(CPP-NETLIB_BUILD_TESTS) diff --git a/libs/mime/To-Do.txt b/mime/To-Do.txt similarity index 100% rename from libs/mime/To-Do.txt rename to mime/To-Do.txt diff --git a/libs/mime/doc/Jamfile.v2 b/mime/doc/Jamfile.v2 similarity index 100% rename from libs/mime/doc/Jamfile.v2 rename to mime/doc/Jamfile.v2 diff --git a/libs/mime/doc/mime.qbk b/mime/doc/mime.qbk similarity index 100% rename from libs/mime/doc/mime.qbk rename to mime/doc/mime.qbk diff --git a/libs/mime/doc/quick_start.qbk b/mime/doc/quick_start.qbk similarity index 100% rename from libs/mime/doc/quick_start.qbk rename to mime/doc/quick_start.qbk diff --git a/libs/mime/example/Jamfile.v2 b/mime/example/Jamfile.v2 similarity index 100% rename from libs/mime/example/Jamfile.v2 rename to mime/example/Jamfile.v2 diff --git a/libs/mime/example/basic_parsing.cpp b/mime/example/basic_parsing.cpp similarity index 100% rename from libs/mime/example/basic_parsing.cpp rename to mime/example/basic_parsing.cpp diff --git a/libs/mime/example/basic_usage.cpp b/mime/example/basic_usage.cpp similarity index 100% rename from libs/mime/example/basic_usage.cpp rename to mime/example/basic_usage.cpp diff --git a/boost/mime.hpp b/mime/src/boost/mime.hpp similarity index 100% rename from boost/mime.hpp rename to mime/src/boost/mime.hpp diff --git a/mime/test/CMakeLists.txt b/mime/test/CMakeLists.txt new file mode 100644 index 000000000..8f4506c1f --- /dev/null +++ b/mime/test/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (c) Glyn Matthews 2012. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11") +elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang) + CHECK_CXX_COMPILER_FLAG(-std=c++11 HAVE_STD11) + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") + set(CPP-NETLIB_CXXFLAGS "-Wall -std=c++11 -stdlib=libc++") +endif() + +include_directories(${CPP-NETLIB_SOURCE_DIR}/mime/src) + +if ( Boost_FOUND ) + add_executable ( mime-roundtrip mime-roundtrip.cpp ) + target_link_libraries ( mime-roundtrip ) + add_test ( mime-roundtrip mime-roundtrip ) +endif () + diff --git a/libs/mime/test/Jamfile.v2 b/mime/test/Jamfile.v2 similarity index 100% rename from libs/mime/test/Jamfile.v2 rename to mime/test/Jamfile.v2 diff --git a/libs/mime/test/TestMessages/.gitattributes b/mime/test/TestMessages/.gitattributes similarity index 100% rename from libs/mime/test/TestMessages/.gitattributes rename to mime/test/TestMessages/.gitattributes diff --git a/libs/mime/test/TestMessages/00000001 b/mime/test/TestMessages/00000001 similarity index 100% rename from libs/mime/test/TestMessages/00000001 rename to mime/test/TestMessages/00000001 diff --git a/libs/mime/test/TestMessages/00000019 b/mime/test/TestMessages/00000019 similarity index 100% rename from libs/mime/test/TestMessages/00000019 rename to mime/test/TestMessages/00000019 diff --git a/libs/mime/test/TestMessages/00000431 b/mime/test/TestMessages/00000431 similarity index 100% rename from libs/mime/test/TestMessages/00000431 rename to mime/test/TestMessages/00000431 diff --git a/libs/mime/test/TestMessages/00000975 b/mime/test/TestMessages/00000975 similarity index 100% rename from libs/mime/test/TestMessages/00000975 rename to mime/test/TestMessages/00000975 diff --git a/libs/mime/test/TestMessages/0019-NoBoundary b/mime/test/TestMessages/0019-NoBoundary similarity index 100% rename from libs/mime/test/TestMessages/0019-NoBoundary rename to mime/test/TestMessages/0019-NoBoundary diff --git a/libs/mime/test/mime-roundtrip.cpp b/mime/test/mime-roundtrip.cpp similarity index 100% rename from libs/mime/test/mime-roundtrip.cpp rename to mime/test/mime-roundtrip.cpp diff --git a/libs/mime/test/mime-structure.cpp b/mime/test/mime-structure.cpp similarity index 100% rename from libs/mime/test/mime-structure.cpp rename to mime/test/mime-structure.cpp diff --git a/libs/mime/test/mimeParse.py b/mime/test/mimeParse.py similarity index 100% rename from libs/mime/test/mimeParse.py rename to mime/test/mimeParse.py diff --git a/uri b/uri new file mode 160000 index 000000000..4a8aa56c3 --- /dev/null +++ b/uri @@ -0,0 +1 @@ +Subproject commit 4a8aa56c3f0e5b4f9c4645b629814880025d6856