diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..60e9548ee --- /dev/null +++ b/.clang-format @@ -0,0 +1,39 @@ +# BasedOnStyle: Google +AccessModifierOffset: -1 +ConstructorInitializerIndentWidth: 4 +AlignEscapedNewlinesLeft: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true +AlwaysBreakTemplateDeclarations: true +AlwaysBreakBeforeMultilineStrings: true +BreakBeforeBinaryOperators: false +BreakConstructorInitializersBeforeComma: false +BinPackParameters: true +ColumnLimit: 80 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +DerivePointerBinding: true +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCSpaceBeforeProtocolList: false +PenaltyBreakComment: 60 +PenaltyBreakString: 1000 +PenaltyBreakFirstLessLess: 120 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerBindsToType: true +SpacesBeforeTrailingComments: 2 +Cpp11BracedListStyle: true +Standard: Auto +IndentWidth: 2 +TabWidth: 8 +UseTab: false +BreakBeforeBraces: Attach +IndentFunctionDeclarationAfterType: true +SpacesInParentheses: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpaceAfterControlStatementKeyword: true diff --git a/.gitignore b/.gitignore index f8f6375ac..72815b038 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,8 @@ -*.cmake *.swp *.pyc -CMakeCache.txt -CMakeFiles -Makefile -Testing *.gch libs/mime/test/mime-roundtrip -*.a +bin/ +tests/ _build +*~ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..791a6213c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,16 @@ +[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 +[submodule "deps/igloo"] + path = deps/igloo + url = git://github.com/joakimkarlsson/igloo.git +[submodule "deps/asio"] + path = deps/asio + url = git://github.com/cpp-netlib/asio + branch = cmake-build diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..a4c995187 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,38 @@ +language: + - cpp + +compiler: + - clang + - gcc + +env: + - BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" + - BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" + - BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" + - BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" + +before_install: + - sudo add-apt-repository ppa:apokluda/boost1.53 --yes + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test --yes # libstdc++-4.8 + - if [ "${CXX}" == "clang++" ]; then sudo add-apt-repository --yes ppa:h-rayflood/llvm; fi # clang++-3.2 + - sudo apt-get update + +install: + - if [ "${CXX}" == "clang++" ]; then sudo apt-get -qq install clang-3.2; fi + - sudo apt-get install g++-4.8; # clang need it for libstdc++ update + - sudo apt-get install libboost-system1.53-dev + - sudo apt-get install libboost-regex1.53-dev + - sudo apt-get install libboost-filesystem1.53-dev + +before_script: + # update compilers + - if [ "${CXX}" == "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi + - if [ "${CXX}" == "clang++" ]; then export CXX="clang++-3.2" CC="clang-3.2"; fi + +script: + - mkdir _build + - cd _build + # Note: clang not support libc++ + - cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DCPP-NETLIB_DISABLE_LIBCXX=YES -DCPP-NETLIB_DISABLE_FEATURE_TESTS=YES .. + - make + - make test diff --git a/CMakeLists.txt b/CMakeLists.txt index 4667f235f..c951518b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,40 +1,197 @@ -# Copyright (c) Dean Michael Berris 2010. +# Copyright (c) Dean Michael Berris 2010. +# Copyright (c) Google, Inc. 2012. +# Copyright (c) Glyn Matthews 2013. # Distributed under the 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_SINGLE_LIB "Build cpp-netlib into a single library" 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 ) +option( CPP-NETLIB_DISABLE_LIBCXX "Disable using libc++ when compiling with clang." OFF ) +option( CPP-NETLIB_DISABLE_FEATURE_TESTS "Disable the feature tests (which may use a network connection)." OFF ) + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +find_package( ICU ) + +if(CPP-NETLIB_BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) + set(Boost_USE_STATIC_LIBS OFF) + set(CPP-NETLIB_BUILD_SHARED_LIBS ON) + set(BUILD_SHARED_LIBS ON) +else() + set(Boost_USE_STATIC_LIBS ON) + set(CPP-NETLIB_BUILD_SHARED_LIBS OFF) + set(BUILD_SHARED_LIBS OFF) +endif() +set(Boost_USE_MULTITHREADED ON) +set(Boost_COMPONENTS system regex filesystem ) +find_package( Boost 1.53 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) -endif() - -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) -endif(Boost_FOUND) - -enable_testing() + 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 "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") + set(CMAKE_CXX_FLAGS "${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) + if (CPP-NETLIB_DISABLE_LIBCXX) + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + else() + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++") + set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -stdlib=libc++") + endif() + 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(STATUS "C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}") +message(STATUS "C++ Flags: ${CMAKE_CXX_FLAGS} link flags: ${CMAKE_CXX_LINK_FLAGS}") + +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}) + +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_SINGLE_LIB: ${CPP-NETLIB_BUILD_SINGLE_LIB}\t(Build cpp-netlib into a single library: 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 " CPP-NETLIB_DISABLE_LIBCXX: ${CPP-NETLIB_DISABLE_LIBCXX}\t(Disable using libc++ when building with clang: ON, OFF)") +message(STATUS " CPP-NETLIB_DISABLE_FEATURE_TESTS: ${CPP-NETLIB_DISABLE_FEATURE_TESTS}\t(Disable the feature tests (which may use a network connection): ON, OFF)") +message(STATUS "CMake build options selected:") + +# Takes one or more lists as parameter and prepends the prefix to every element. +function(prependToElements prefix) + foreach(list ${ARGN} ) # iterate over lists + set(newlist "") + foreach(ele ${${list}} ) # iterate over the elements + set(newlist ${newlist} "${prefix}${ele}") + endforeach(ele) + set(${list} ${newlist} PARENT_SCOPE) # replace the original list + endforeach(list) +endfunction(prependToElements) + +############################################################################ +# +# 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_LIBRARY gtest) + set(GTEST_MAIN_LIBRARY gtest_main) + set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) + + set(GMOCK_ROOT ${CPP-NETLIB_SOURCE_DIR}/deps/gmock) + set(GMOCK_FOUND ON) + set(GMOCK_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_ROOT}/include) + set(GMOCK_LIBRARY ${GTEST_LIBRARIES} gmock) + set(GMOCK_MAIN_LIBRARY gmock_main) + set(GMOCK_BOTH_LIBRARIES ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY}) + + set(IGLOO_ROOT ${CPP-NETLIB_SOURCE_DIR}/deps/igloo) + set(IGLOO_FOUND ON) + set(IGLOO_INCLUDE_DIR ${IGLOO_ROOT}) +endif() + +# Documentation +find_package(Doxygen) +if (DOXYGEN_FOUND) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM) + set(CPP-NETLIB_GENERATE_DOCS ON) +endif(DOXYGEN_FOUND) + +if(CPP-NETLIB_BUILD_SINGLE_LIB) + include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/config/src + ${CMAKE_CURRENT_SOURCE_DIR}/concurrency/src + ${CMAKE_CURRENT_SOURCE_DIR}/http/src + ${CMAKE_CURRENT_SOURCE_DIR}/logging/src + ${CMAKE_CURRENT_SOURCE_DIR}/message/src + ${CMAKE_CURRENT_SOURCE_DIR}/uri/src + ${CMAKE_CURRENT_SOURCE_DIR} + ) +endif() + +add_subdirectory(uri) +add_subdirectory(message) +add_subdirectory(logging) +add_subdirectory(http) +add_subdirectory(concurrency) +#add_subdirectory(mime) +if(CPP-NETLIB_BUILD_EXAMPLES) + add_subdirectory(contrib/http_examples) +endif() + +if(CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(cppnetlib + ${Uri_SRCS} + ${CPP-NETLIB_MESSAGE_SRCS} + ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS} + ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS} + ${CPP-NETLIB_LOGGING_SRCS} + ${CPP-NETLIB_HTTP_CLIENT_SRCS} + ${CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS} + ${CPP-NETLIB_HTTP_SERVER_SRCS} + ${CPP-NETLIB_HTTP_MESSAGE_SRCS} + ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS} + ${CPP-NETLIB_CONSTANTS_SRCS} + ${CPP-NETLIB_CONCURRENCY_SRCS} + ) + target_link_libraries(cppnetlib ${Boost_LIBRARIES}) +endif() diff --git a/Doxyfile.in b/Doxyfile.in new file mode 100644 index 000000000..44ad4bc51 --- /dev/null +++ b/Doxyfile.in @@ -0,0 +1,1790 @@ +# Doxyfile 1.7.6.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = "C++ Network Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 1.0 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = @CMAKE_CURRENT_SOURCE_DIR@/error/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/uri/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/http/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/concurrency/src/ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/error/ \ + @CMAKE_CURRENT_SOURCE_DIR@/uri/src/network/ \ + @CMAKE_CURRENT_SOURCE_DIR@/http/src/network/http/ \ + @CMAKE_CURRENT_SOURCE_DIR@/concurrency/src/network/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.hpp + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/uri/src/network/uri/detail + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = *-inl.hpp + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = @CMAKE_CURRENT_SOURCE_DIR@/error/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/uri/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/http/src/ \ + @CMAKE_CURRENT_SOURCE_DIR@/concurrency/src/ + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES 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 deleted file mode 100644 index 965e8d30e..000000000 --- a/Jamroot +++ /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) - -import os ; - -local BOOST_ROOT = [ os.environ BOOST_ROOT ] ; - -use-project /boost : $(BOOST_ROOT) ; -use-project /cpp-netlib : libs/network/build ; - -using testing ; - -build-project libs/network/build ; -build-project libs/network/test ; -build-project libs/mime/test ; - diff --git a/README.rst b/README.rst index b0f219767..6afcaeb9e 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,9 @@ C++ Network Library =================== +.. image:: https://travis-ci.org/cpp-netlib/cpp-netlib.png?branch=master + :target: https://travis-ci.org/cpp-netlib/cpp-netlib + Introduction ------------ @@ -33,31 +36,44 @@ 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 init + $ 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 \ + $ cd ~/cpp-netlib-build # cmake is built out of source + $ cmake ~/cpp-netlib \ # we're assuming it's where cpp-netlib is + > -DCMAKE_BUILD_TYPE=Debug \ > -DCMAKE_C_COMPILER=clang \ - > -DCMAKE_CXX_COMPILER=clang++ \ - > . + > -DCMAKE_CXX_COMPILER=clang++ 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 @@ -65,33 +81,12 @@ If for some reason some of the tests fail, you can send the files in ``Testing/Temporary/`` as attachments to the cpp-netlib `developers mailing list`_. -.. _`developers mailing list`: cpp-netlib@googlegroups.com +API documentation can be generated by running the following command:: -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 + $ cd ~/cpp-netlib-build + $ make doc -And then attach the ``build-test.log`` file to the email you will send to the -cpp-netlib `developers mailing list`_. +The HTML output can be found in the ``html`` subdirectory. .. _`developers mailing list`: cpp-netlib@googlegroups.com @@ -101,8 +96,8 @@ 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 +131,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/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp deleted file mode 100644 index f0368c0e1..000000000 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ /dev/null @@ -1,387 +0,0 @@ -#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. -// Distributed under the 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 http_async_protocol_handler { - protected: - - typedef typename string::type string_type; - -#ifdef BOOST_NETWORK_DEBUG - struct debug_escaper { - string_type & string; - explicit debug_escaper(string_type & string_) - : string(string_) {} - debug_escaper(debug_escaper const & other) - : string(other.string) {} - void operator()(typename string_type::value_type input) { - if (!algorithm::is_print()(input)) { - typename ostringstream::type 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 - - template - void init_response(ResponseType & response_, bool get_body) { - boost::shared_future source_future( - source_promise.get_future()); - source(response_, source_future); - boost::shared_future destination_future( - destination_promise.get_future()); - destination(response_, destination_future); - boost::shared_future::type> - headers_future(headers_promise.get_future()); - headers(response_, headers_future); - boost::shared_future body_future( - body_promise.get_future()); - body(response_, body_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( - 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; - header_line << pair.first - << constants::colon() - << constants::space() - << pair.second - << constants::crlf(); - return header_line.str(); - } - }; - - template - logic::tribool parse_version(Delegate & delegate_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - part_begin = part.begin(); - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - 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, - input_range); - if (parsed_ok == true) { - string_type version; - std::swap(version, partial_parsed); - version.append(boost::begin(result_range), - boost::end(result_range)); - algorithm::trim(version); - version_promise.set_value(version); - part_begin = boost::end(result_range); - } else if (parsed_ok == false) { -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_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)); - 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)); - } 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()), - callback - ); - } - return parsed_ok; - } - - template - logic::tribool parse_status(Delegate & delegate_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - 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, - input_range); - if (parsed_ok == true) { - string_type status; - std::swap(status, partial_parsed); - status.append(boost::begin(result_range), - boost::end(result_range)); - trim(status); - boost::uint16_t status_int = - lexical_cast(status); - status_promise.set_value(status_int); - part_begin = boost::end(result_range); - } else if (parsed_ok == false) { -#ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_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_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)); - } 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()), - callback - ); - } - return parsed_ok; - } - - template - logic::tribool parse_status_message(Delegate & delegate_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - 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, - input_range); - if (parsed_ok == true) { - string_type status_message; - std::swap(status_message, partial_parsed); - status_message.append(boost::begin(result_range), - boost::end(result_range)); - algorithm::trim(status_message); - 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; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" - << response_parser_.state() - << "] buffer contents: \"" - << escaped - << "\""); -#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)); - } 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()), - callback - ); - } - return parsed_ok; - } - - void parse_headers_real(string_type & headers_part) { - typename boost::iterator_range - 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; - while (!boost::empty(input_range)) { - fusion::tie(parsed_ok, result_range) = - headers_parser.parse_until( - response_parser_type::http_header_colon, - input_range); - if (headers_parser.state() - != response_parser_type::http_header_colon) - break; - header_pair.first = string_type(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, - input_range); - header_pair.second = string_type(boost::begin(result_range), - boost::end(result_range)); - input_range.advance_begin(boost::distance(result_range)); - - trim(header_pair.first); - if (header_pair.first.size() > 1) { - header_pair.first.erase( - header_pair.first.size() - 1 - ); - } - trim(header_pair.second); - headers.insert(header_pair); - } - headers_promise.set_value(headers); - } - - template - fusion::tuple parse_headers(Delegate & delegate_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - 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, - input_range); - if (parsed_ok == true) { - string_type 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 BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_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(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)); - } 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()), - callback - ); - } - return fusion::make_tuple( - parsed_ok, - std::distance( - boost::end(result_range) - , part_end - ) - ); - } - - template - void parse_body(Delegate & delegate_, Callback 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(); - delegate_->read_some( - boost::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; - buffer_type part; - typename buffer_type::const_iterator part_begin; - string_type partial_parsed; - }; - - -} /* impl */ - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 */ 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_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp deleted file mode 100644 index 1df519b9f..000000000 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ /dev/null @@ -1,246 +0,0 @@ -#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. -// Distributed under the 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 -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include -#endif - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct sync_connection_base_impl { - protected: - 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; - - 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; - typename resolver_type::iterator endpoint_iterator, end; - boost::tie(endpoint_iterator, end) = resolve_(resolver_, hostname, port); - while (error && endpoint_iterator != end) { - socket_.close(); - socket_.connect( - tcp::endpoint( - endpoint_iterator->endpoint().address() - , endpoint_iterator->endpoint().port() - ) - , error - ); - ++endpoint_iterator; - } - - if (error) - throw boost::system::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"); - std::istream response_stream(&response_buffer); - string_type http_version; - unsigned int status_code; - string_type status_message; - response_stream >> http_version - >> status_code; - std::getline(response_stream, status_message); - trim_left(status_message); - trim_right_if(status_message, boost::is_space() || boost::is_any_of("\r")); - - if (!response_stream || http_version.substr(0, 5) != "HTTP/") - throw std::runtime_error("Invalid response"); - - response_ << http::version(http_version) - << http::status(status_code) - << http::status_message(status_message); - } - - 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"); - std::istream response_stream(&response_buffer); - string_type header_line, name; - while (std::getline(response_stream, header_line) && header_line != "\r") { - trim_right_if(header_line, boost::is_space() || boost::is_any_of("\r")); - typename string_type::size_type colon_offset; - if (header_line.size() && header_line[0] == ' ') { - assert(!name.empty()); - if (name.empty()) - throw std::runtime_error( - std::string("Malformed header: ") - + header_line - ); - response_ - << header(name, trim_left_copy(header_line)); - } else if ((colon_offset = header_line.find_first_of(':')) != string_type::npos) { - name = header_line.substr(0, colon_offset); - response_ - << header(name, header_line.substr(colon_offset+2)); - } - } - } - - template - void send_request_impl(Socket & socket_, string_type const & method, boost::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; - if (response_buffer.size() > 0) - body_stream << &response_buffer; - - while (boost::asio::read(socket_, response_buffer, boost::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; - // look for the content-length header - typename headers_range >::type content_length_range = - headers(response_)["Content-Length"]; - if (empty(content_length_range)) { - typename headers_range >::type transfer_encoding_range = - headers(response_)["Transfer-Encoding"]; - if (empty(transfer_encoding_range)) { - read_body_normal(socket_, response_, response_buffer, body_stream); - return; - } - if (boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { - 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); - std::size_t chunk_size = 0; - string_type data; - { - std::istream chunk_stream(&response_buffer); - std::getline(chunk_stream, data); - typename istringstream::type chunk_size_stream(data); - chunk_size_stream >> std::hex >> chunk_size; - } - 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); - } else { - bool stopping_inner = false; - 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; - } - - std::istreambuf_iterator eos; - std::istreambuf_iterator stream_iterator(&response_buffer); - for (; chunk_size > 0 && stream_iterator != eos; --chunk_size) - body_stream << *stream_iterator++; - response_buffer.consume(2); - } while (!stopping_inner && chunk_size != 0); - - if (chunk_size != 0) - throw std::runtime_error("Size mismatch between tranfer encoding chunk data size and declared chunk size."); - } - } while (!stopping); - } else throw std::runtime_error("Unsupported Transfer-Encoding."); - } else { - size_t already_read = response_buffer.size( ); - if ( already_read ) - body_stream << &response_buffer; - size_t length = lexical_cast(boost::begin(content_length_range)->second) - already_read; - 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))) { - body_stream << &response_buffer; - length -= bytes_read; - if ((length <= 0) || error) - break; - } - } - } - - template - void read_body(Socket & socket_, basic_response & response_, boost::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) { - read_body_normal(socket_, response_, response_buffer, body_stream); - } else if (version_major == 1 && version_minor == 1) { - if (response_.version() == "HTTP/1.0") - read_body_normal(socket_, response_, response_buffer, body_stream); - else - read_body_transfer_chunk_encoding(socket_, response_, response_buffer, body_stream); - } else { - throw std::runtime_error("Unsupported HTTP version number."); - } - - response_ << network::body(body_stream.str()); - } - - }; - - template - struct sync_connection_base { - 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; - - // 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 - return dynamic_cast*>(new https_sync_connection(resolver, resolve, cert_filename, verify_path)); -#else - throw std::runtime_error("HTTPS not supported."); -#endif - } - return dynamic_cast*>(new http_sync_connection(resolver, resolve)); - } - - 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 bool is_open() = 0; - virtual void close_socket() = 0; - virtual ~sync_connection_base() {} - protected: - sync_connection_base() {} - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217 - 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/request_parser.ipp b/boost/network/protocol/http/impl/request_parser.ipp deleted file mode 100644 index 071e64f20..000000000 --- a/boost/network/protocol/http/impl/request_parser.ipp +++ /dev/null @@ -1,332 +0,0 @@ -// -// request_parser.ipp -// ~~~~~~~~~~~~~~~~~~ -// -// 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 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_HTTP_REQUEST_PARSER_IPP -#define BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP - -#include - -namespace boost { namespace network { namespace http { - -template -boost::tribool basic_request_parser::consume(basic_request & req, char input) -{ - switch (state_) - { - case method_start: - if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - state_ = method; - req.method.push_back(input); - return boost::indeterminate; - } - case method: - if (input == ' ') - { - state_ = uri; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.method.push_back(input); - return boost::indeterminate; - } - case uri_start: - if (is_ctl(input)) - { - return false; - } - else - { - state_ = uri; - req.destination.push_back(input); - return boost::indeterminate; - } - case uri: - if (input == ' ') - { - state_ = http_version_h; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.destination.push_back(input); - return boost::indeterminate; - } - case http_version_h: - if (input == 'H') - { - state_ = http_version_t_1; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_1: - if (input == 'T') - { - state_ = http_version_t_2; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_t_2: - if (input == 'T') - { - state_ = http_version_p; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_p: - if (input == 'P') - { - state_ = http_version_slash; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_slash: - if (input == '/') - { - req.http_version_major = 0; - req.http_version_minor = 0; - state_ = http_version_major_start; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major_start: - if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - state_ = http_version_major; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_major: - if (input == '.') - { - state_ = http_version_minor_start; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_major = req.http_version_major * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor_start: - if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - state_ = http_version_minor; - return boost::indeterminate; - } - else - { - return false; - } - case http_version_minor: - if (input == '\r') - { - state_ = expecting_newline_1; - return boost::indeterminate; - } - else if (is_digit(input)) - { - req.http_version_minor = req.http_version_minor * 10 + input - '0'; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_1: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case header_line_start: - if (input == '\r') - { - state_ = expecting_newline_3; - return boost::indeterminate; - } - else if (!req.headers.empty() && (input == ' ' || input == '\t')) - { - state_ = header_lws; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.push_back(typename request_header::type()); - req.headers.back().name.push_back(input); - state_ = header_name; - return boost::indeterminate; - } - case header_lws: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (input == ' ' || input == '\t') - { - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - state_ = header_value; - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case header_name: - if (input == ':') - { - state_ = space_before_header_value; - return boost::indeterminate; - } - else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) - { - return false; - } - else - { - req.headers.back().name.push_back(input); - return boost::indeterminate; - } - case space_before_header_value: - if (input == ' ') - { - state_ = header_value; - return boost::indeterminate; - } - else - { - return false; - } - case header_value: - if (input == '\r') - { - state_ = expecting_newline_2; - return boost::indeterminate; - } - else if (is_ctl(input)) - { - return false; - } - else - { - req.headers.back().value.push_back(input); - return boost::indeterminate; - } - case expecting_newline_2: - if (input == '\n') - { - state_ = header_line_start; - return boost::indeterminate; - } - else - { - return false; - } - case expecting_newline_3: - return (input == '\n'); - default: - return false; - } -} - -template -bool basic_request_parser::is_char(int c) -{ - return c >= 0 && c <= 127; -} - -template -bool basic_request_parser::is_ctl(int c) -{ - return (c >= 0 && c <= 31) || (c == 127); -} - -template -bool basic_request_parser::is_tspecial(int c) -{ - switch (c) - { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } -} - -template -bool basic_request_parser::is_digit(int c) -{ - return c >= '0' && c <= '9'; -} - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif //BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP - 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/helper.hpp b/boost/network/protocol/http/message/wrappers/helper.hpp deleted file mode 100644 index e433249ee..000000000 --- a/boost/network/protocol/http/message/wrappers/helper.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 - -// 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 - -#ifndef BOOST_NETWORK_DEFINE_HTTP_WRAPPER -#define BOOST_NETWORK_DEFINE_HTTP_WRAPPER(name, accessor, pod_field) \ - struct name##_pod_accessor { \ - protected: \ - template \ - typename Message::string_type const & \ - get_value(Message const & message) const { \ - return message.pod_field; \ - } \ - }; \ - \ - struct name##_member_accessor { \ - protected: \ - template \ - typename Message::string_type \ - get_value(Message const & message) const { \ - return message.accessor(); \ - } \ - }; \ - \ - template \ - struct name##_wrapper_impl : \ - mpl::if_< \ - is_base_of, \ - name##_pod_accessor, \ - name##_member_accessor \ - > \ - {}; \ - \ - template \ - struct name##_wrapper : \ - name##_wrapper_impl::type { \ - typedef typename string::type \ - string_type; \ - Message const & message_; \ - name##_wrapper(Message const & message) \ - : message_(message) {} \ - name##_wrapper(name##_wrapper const & other) \ - : message_(other.message_) {} \ - operator string_type () const { \ - return this->get_value(message_); \ - } \ - }; \ - \ - template \ - inline \ - name##_wrapper > const \ - name (basic_response const & message) { \ - return name##_wrapper >(message); \ - } \ - \ - template \ - inline \ - name##_wrapper > const \ - name (basic_request const & message) { \ - return name##_wrapper >(message); \ - } - -#endif /* BOOST_NETWORK_DEFINE_HTTP_WRAPPER */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 */ - 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/minor_version.hpp b/boost/network/protocol/http/message/wrappers/minor_version.hpp deleted file mode 100644 index b105227a4..000000000 --- a/boost/network/protocol/http/message/wrappers/minor_version.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#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. -// Distributed under the 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 minor_version_wrapper { - basic_request const & request; - explicit minor_version_wrapper(basic_request const & request) - : request(request) {} - operator boost::uint8_t () { - return request.http_version_minor; - } - }; - - template - inline typename enable_if, minor_version_wrapper >::type - minor_version(basic_request const & request) { - return minor_version_wrapper(request); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 */ - 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/ready.hpp b/boost/network/protocol/http/message/wrappers/ready.hpp deleted file mode 100644 index b45ee4277..000000000 --- a/boost/network/protocol/http/message/wrappers/ready.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#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. -// Distributed under the 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 async_message; - - namespace impl { - template - struct ready_wrapper : boost::network::detail::wrapper_base_const > { - typedef boost::network::detail::wrapper_base_const > - wrapper_base; - explicit ready_wrapper(async_message const & message) - : wrapper_base(message) {} - operator bool () { - return - wrapper_base::_message.version_.is_ready() - && wrapper_base::_message.status_.is_ready() - && wrapper_base::_message.status_message_.is_ready() - && wrapper_base::_message.headers_.is_ready() - && wrapper_base::_message.body_.is_ready(); - } - }; - } // namespace impl - - template - inline bool ready(async_message const & message) { - return impl::ready_wrapper(message); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_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.hpp b/boost/network/protocol/http/parser.hpp deleted file mode 100644 index a7bd42ff4..000000000 --- a/boost/network/protocol/http/parser.hpp +++ /dev/null @@ -1,314 +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_HPP -#define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - // forward declarations used to finish HTTP requests - template - class basic_request; - - // forward declarations used to finish HTTP requests - template - class basic_response; - - /// an incremental HTTP 1.0/1.1 protocol parser - template > - class basic_parser : - private boost::noncopyable - { - public: - - // import types from ParserTraits template - typedef ParserTraits traits_type; - typedef typename string::type string_type; - - // default destructor - virtual ~basic_parser() {} - - /** - * creates a new HTTP protocol parser - * - * @param is_request if true, the message is parsed as an HTTP request; - * if false, the message is parsed as an HTTP response - */ - basic_parser(const bool is_request) : - m_is_request(is_request), m_read_ptr(NULL), m_read_end_ptr(NULL), - m_headers_parse_state(is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H), - m_chunked_content_parse_state(PARSE_CHUNK_SIZE_START), - m_status_code(0), m_bytes_last_read(0), m_bytes_total_read(0) - {} - - /** - * parses an HTTP message up to the end of the headers using bytes - * available in the read buffer - * - * @param http_msg the HTTP message object to populate from parsing - * - * @return boost::tribool result of parsing: - * false = message has an error, - * true = finished parsing HTTP headers, - * indeterminate = not yet finished parsing HTTP headers - */ - boost::tribool parse_http_headers(basic_message& http_msg); - - /** - * parses a chunked HTTP message-body using bytes available in the read buffer - * - * @param chunk_buffers buffers to be populated from parsing chunked content - * - * @return boost::tribool result of parsing: - * false = message has an error, - * true = finished parsing message, - * indeterminate = message is not yet finished - */ - boost::tribool parse_chunks(types::chunk_cache_t& chunk_buffers); - - /** - * prepares the payload content buffer and consumes any content remaining - * in the parser's read buffer - * - * @param http_msg the HTTP message object to consume content for - * @return unsigned long number of content bytes consumed, if any - */ - std::size_t consume_content(basic_message& http_msg); - - /** - * consume the bytes available in the read buffer, converting them into - * the next chunk for the HTTP message - * - * @param chunk_buffers buffers to be populated from parsing chunked content - * @return unsigned long number of content bytes consumed, if any - */ - std::size_t consume_content_as_next_chunk(types::chunk_cache_t& chunk_buffers); - - /** - * finishes parsing an HTTP request message (copies over request-only data) - * - * @param http_request the HTTP request object to finish - */ - void finish(basic_request& http_request); - - /** - * finishes an HTTP response message (copies over response-only data) - * - * @param http_request the HTTP response object to finish - */ - void finish(basic_response& http_response); - - /** - * resets the location and size of the read buffer - * - * @param ptr pointer to the first bytes available to be read - * @param len number of bytes available to be read - */ - inline void set_read_buffer(const char *ptr, std::size_t len) { - m_read_ptr = ptr; - m_read_end_ptr = ptr + len; - } - - /** - * saves the current read position bookmark - * - * @param read_ptr points to the next character to be consumed in the read_buffer - * @param read_end_ptr points to the end of the read_buffer (last byte + 1) - */ - inline void save_read_position(const char *&read_ptr, const char *&read_end_ptr) const { - read_ptr = m_read_ptr; - read_end_ptr = m_read_end_ptr; - } - - /// resets the parser to its initial state - inline void reset(void); - - /// returns true if there are no more bytes available in the read buffer - inline bool eof(void) const { - return m_read_ptr == NULL || m_read_ptr >= m_read_end_ptr; - } - - /// returns the number of bytes read during the last parse operation - inline std::size_t gcount(void) const { return m_bytes_last_read; } - - /// returns the total number of bytes read while parsing the HTTP message - inline std::size_t bytes_read(void) const { return m_bytes_total_read; } - - /// returns the number of bytes available in the read buffer - inline std::size_t bytes_available(void) const { - return (eof() ? 0 : (m_read_end_ptr - m_read_ptr)); - } - - - protected: - - /** - * parse key-value pairs out of a url-encoded string - * (i.e. this=that&a=value) - * - * @param params container for key-values string pairs - * @param ptr points to the start of the encoded string - * @param len length of the encoded string, in bytes - * - * @return bool true if successful - */ - static bool parse_url_encoded(types::query_params& params, - const char *ptr, const std::size_t len); - - /** - * parse key-value pairs out of a "Cookie" request header - * (i.e. this=that; a=value) - * - * @param params container for key-values string pairs - * @param cookie_header header string to be parsed - * - * @return bool true if successful - */ - static bool parse_cookie_header(types::cookie_params& params, - const string_type& cookie_header); - - - /// true if the message is an HTTP request; false if it is an HTTP response - const bool m_is_request; - - /// points to the next character to be consumed in the read_buffer - const char * m_read_ptr; - - /// points to the end of the read_buffer (last byte + 1) - const char * m_read_end_ptr; - - - private: - - // returns true if the argument is a special character - inline static bool is_special(int c) { - switch (c) { - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - return true; - default: - return false; - } - } - - // returns true if the argument is a character - inline static bool is_char(int c) { - return(c >= 0 && c <= 127); - } - - // returns true if the argument is a control character - inline static bool is_control(int c) { - return( (c >= 0 && c <= 31) || c == 127); - } - - // returns true if the argument is a digit - inline static bool is_digit(int c) { - return(c >= '0' && c <= '9'); - } - - // returns true if the argument is a hexadecimal digit - inline static bool is_hex_digit(int c) { - return((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')); - } - - - /// state used to keep track of where we are in parsing the HTTP headers - enum headers_parse_state_t { - PARSE_METHOD_START, PARSE_METHOD, PARSE_URI_STEM, PARSE_URI_QUERY, - PARSE_HTTP_VERSION_H, PARSE_HTTP_VERSION_T_1, PARSE_HTTP_VERSION_T_2, - PARSE_HTTP_VERSION_P, PARSE_HTTP_VERSION_SLASH, - PARSE_HTTP_VERSION_MAJOR_START, PARSE_HTTP_VERSION_MAJOR, - PARSE_HTTP_VERSION_MINOR_START, PARSE_HTTP_VERSION_MINOR, - PARSE_STATUS_CODE_START, PARSE_STATUS_CODE, PARSE_STATUS_MESSAGE, - PARSE_EXPECTING_NEWLINE, PARSE_EXPECTING_CR, - PARSE_HEADER_WHITESPACE, PARSE_HEADER_START, PARSE_HEADER_NAME, - PARSE_SPACE_BEFORE_HEADER_VALUE, PARSE_HEADER_VALUE, - PARSE_EXPECTING_FINAL_NEWLINE, PARSE_EXPECTING_FINAL_CR - }; - - /// state used to keep track of where we are in parsing chunked content - enum chunked_content_parse_state_t { - PARSE_CHUNK_SIZE_START, PARSE_CHUNK_SIZE, - PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE, - PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE, PARSE_CHUNK, - PARSE_EXPECTING_CR_AFTER_CHUNK, PARSE_EXPECTING_LF_AFTER_CHUNK, - PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK, - PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK - }; - - - /// the current state of parsing HTTP headers - headers_parse_state_t m_headers_parse_state; - - /// the current state of parsing chunked content - chunked_content_parse_state_t m_chunked_content_parse_state; - - /// Used for parsing the HTTP response status code - boost::uint16_t m_status_code; - - /// Used for parsing the HTTP response status message - string_type m_status_message; - - /// Used for parsing the request method - string_type m_method; - - /// Used for parsing the name of resource requested - string_type m_resource; - - /// Used for parsing the query string portion of a URI - string_type m_query_string; - - /// Used for parsing the name of HTTP headers - string_type m_header_name; - - /// Used for parsing the value of HTTP headers - string_type m_header_value; - - /// Used for parsing the chunk size - string_type m_chunk_size_str; - - /// Used for parsing the current chunk - std::vector m_current_chunk; - - /// number of bytes in the chunk currently being parsed - std::size_t m_size_of_current_chunk; - - /// number of bytes read so far in the chunk currently being parsed - std::size_t m_bytes_read_in_current_chunk; - - /// number of bytes read during last parse operation - std::size_t m_bytes_last_read; - - /// total number of bytes read while parsing the HTTP message - std::size_t m_bytes_total_read; - }; - - /// typedef for the default HTTP protocol parser implementation - typedef basic_parser parser; - -}; // namespace http - -}; // namespace network - -}; // namespace boost - -// import implementation file -#include - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_PARSER_HPP 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/request_concept.hpp b/boost/network/protocol/http/request_concept.hpp deleted file mode 100644 index 5b0ee99eb..000000000 --- a/boost/network/protocol/http/request_concept.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#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. -// Distributed under the 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 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_; - boost::uint8_t major_version_, minor_version_; - headers_container_type headers_; - string_type body_; - - source_ = source(request); - method_ = method(request); - destination_ = destination(request); - major_version_ = major_version(request); - minor_version_ = minor_version(request); - headers_ = headers(request); - body_ = body(request); - - source(request, source_); - method(request, method_); - destination(request, destination_); - 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()); - clear_headers(request); - body(request, body_); - - string_type 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_); - - (void)source_;(void)method_;(void)destination_; - (void)major_version_;(void)minor_version_;(void)headers_; - (void)body_;(void)name;(void)value; - } - - private: - R request; - }; - - template - struct ClientRequest - : boost::network::Message - { - typedef typename R::string_type string_type; - typedef typename R::port_type port_type; - - BOOST_CONCEPT_USAGE(ClientRequest) { - string_type 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); - - request << uri(string_type()); - - boost::network::http::uri(request, string_type()); - - (void)host_; - (void)port_; - (void)path_; - (void)query_; - (void)anchor_; - (void)protocol_; - } - - private: - R request; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_REQUEST_CONCEPT_HPP_20100603 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/response_concept.hpp b/boost/network/protocol/http/response_concept.hpp deleted file mode 100644 index ef6bf0f62..000000000 --- a/boost/network/protocol/http/response_concept.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#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. -// Distributed under the 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 Response - : boost::network::Message - { - typedef typename R::string_type string_type; - - BOOST_CONCEPT_USAGE(Response) { - 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; - - response << version(version_type()) // version directive - << status(status_type()) // status directive - << status_message(status_message_type()) // status_message directive - ; - - version(response, version_type()); - status(response, status_type()); - status_message(response, status_message_type()); - - string_type version_ = version(response); - boost::uint16_t status_ = status(response); - string_type status_message_ = status_message(response); - - (void)version_; - (void)status_; - (void)status_message_; - } - - private: - R response; - }; - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_RESPONSE_CONCEPT_HPP_20100603 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/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp deleted file mode 100644 index c56af236e..000000000 --- a/boost/network/protocol/http/server/async_server.hpp +++ /dev/null @@ -1,174 +0,0 @@ -#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. -// Distributed under the 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 async_server_base : server_storage_base, socket_options_base { - typedef basic_request request; - typedef basic_response response; - typedef typename string::type string_type; - typedef typename boost::network::http::response_header::type response_header; - typedef async_connection connection; - typedef shared_ptr connection_ptr; - typedef boost::unique_lock scoped_mutex_lock; - - template - async_server_base(ArgPack const & args) - : server_storage_base(args, - typename mpl::if_< - is_same< - typename parameter::value_type::type, - void - >, - server_storage_base::no_io_service, - server_storage_base::has_io_service - >::type()) - , socket_options_base(args) - , handler(args[_handler]) - , address_(args[_address]) - , port_(args[_port]) - , thread_pool(args[_thread_pool]) - , acceptor(server_storage_base::service_) - , stopping(false) - , new_connection() - , listening_mutex_() - , stopping_mutex_() - , listening(false) - {} - - void run() { - listen(); - service_.run(); - }; - - void stop() { - // stop accepting new requests and let all the existing - // handlers finish. - scoped_mutex_lock listening_lock(listening_mutex_); - if (listening) { // we dont bother stopping if we arent currently listening - scoped_mutex_lock stopping_lock(stopping_mutex_); - stopping = true; - system::error_code ignored; - acceptor.close(ignored); - listening = false; - service_.post(boost::bind(&async_server_base::handle_stop, this)); - } - } - - void listen() { - scoped_mutex_lock listening_lock(listening_mutex_); - BOOST_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_); - boost::throw_exception(std::runtime_error("Error listening on provided port.")); - } - } - - private: - Handler & handler; - string_type address_, port_; - utils::thread_pool & thread_pool; - asio::ip::tcp::acceptor acceptor; - bool stopping; - connection_ptr new_connection; - boost::mutex listening_mutex_; - boost::mutex stopping_mutex_; - bool listening; - - void handle_stop() { - scoped_mutex_lock stopping_lock(stopping_mutex_); - 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) { - { - 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 - } - if (!ec) { - socket_options_base::socket_options(new_connection->socket()); - new_connection->start(); - new_connection.reset( - new connection( - service_ - , handler - , thread_pool - ) - ); - acceptor.async_accept(new_connection->socket(), - boost::bind( - &async_server_base::handle_accept - , this - , boost::asio::placeholders::error - ) - ); - } else { - BOOST_NETWORK_MESSAGE("Error accepting connection, reason: " << ec); - } - } - - void start_listening() { - using boost::asio::ip::tcp; - - system::error_code error; - - service_.reset(); // this 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) { - BOOST_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_); - return; - } - socket_options_base::acceptor_options(acceptor); - acceptor.bind(endpoint, error); - if (error) { - BOOST_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_); - return; - } - new_connection.reset(new connection(service_, handler, thread_pool)); - acceptor.async_accept(new_connection->socket(), - boost::bind( - &async_server_base::handle_accept - , this - , boost::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_ << "'"); - } - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 */ diff --git a/boost/network/protocol/http/server/impl/parsers.ipp b/boost/network/protocol/http/server/impl/parsers.ipp deleted file mode 100644 index e39c7b26d..000000000 --- a/boost/network/protocol/http/server/impl/parsers.ipp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 -#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 - -#include - -// 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 - -#ifdef BOOST_NETWORK_NO_LIB -# ifndef BOOST_NETWORK_INLINE -# define BOOST_NETWORK_INLINE inline -# endif -#else -# define BOOST_NETWORK_INLINE -#endif -#include - -namespace boost { namespace network { namespace http { - - BOOST_NETWORK_INLINE void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { - using namespace boost::spirit::qi; - parse( - partial_parsed.begin(), partial_parsed.end(), - ( - lit("HTTP/") - >> ushort_ - >> '.' - >> ushort_ - ) - , version_pair); - } - - BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector & container) { - using namespace boost::spirit::qi; - parse( - input.begin(), input.end(), - *( - +(alnum|(punct-':')) - >> lit(": ") - >> +((alnum|space|punct) - '\r' - '\n') - >> lit("\r\n") - ) - >> lit("\r\n") - , container - ); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 */ diff --git a/boost/network/protocol/http/server/parameters.hpp b/boost/network/protocol/http/server/parameters.hpp deleted file mode 100644 index 06b59b174..000000000 --- a/boost/network/protocol/http/server/parameters.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_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) - -#include - -namespace boost { namespace network { namespace http { - - BOOST_PARAMETER_NAME(address) - BOOST_PARAMETER_NAME(port) - BOOST_PARAMETER_NAME(handler) - BOOST_PARAMETER_NAME(thread_pool) - - BOOST_PARAMETER_NAME(reuse_address) - BOOST_PARAMETER_NAME(report_aborted) - BOOST_PARAMETER_NAME(receive_buffer_size) - BOOST_PARAMETER_NAME(send_buffer_size) - BOOST_PARAMETER_NAME(receive_low_watermark) - BOOST_PARAMETER_NAME(send_low_watermark) - BOOST_PARAMETER_NAME(non_blocking_io) - BOOST_PARAMETER_NAME(linger) - BOOST_PARAMETER_NAME(linger_timeout) - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/request.hpp b/boost/network/protocol/http/server/request.hpp deleted file mode 100644 index c5fed5deb..000000000 --- a/boost/network/protocol/http/server/request.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// request.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2009 Dean Michael Berris (mikhailberis@gmail.com) -// Copyright (c) 2009 Tarro, Inc. -// -// Distributed under the 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 - -#include -#include -#include -#include "header.hpp" - -namespace boost { namespace network { namespace http { - - /// A request received from a client. - struct request - { - std::string method; - std::string uri; - int http_version_major; - int http_version_minor; - std::vector
headers; - std::string body; - }; - - inline void swap(request & l, request & r) { - using std::swap; - swap(l.method, r.method); - swap(l.uri, r.uri); - swap(l.http_version_major, r.http_version_major); - swap(l.http_version_minor, r.http_version_minor); - swap(l.headers, r.headers); - swap(l.body, r.body); - } - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_HTTP_REQUEST_HPP - diff --git a/boost/network/protocol/http/server/request_parser.hpp b/boost/network/protocol/http/server/request_parser.hpp deleted file mode 100644 index bb6421b66..000000000 --- a/boost/network/protocol/http/server/request_parser.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#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. -// Distributed under the 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 request_parser { - - enum state_t { - method_start - , method_char - , method_done - , uri_char - , uri_done - , version_h - , version_t1 - , version_t2 - , version_p - , version_slash - , version_d1 - , version_dot - , version_d2 - , version_cr - , version_done - , header_name - , header_colon - , header_value - , header_cr - , header_line_done - , headers_cr - , headers_done - }; - - explicit request_parser(state_t start_state = method_start) - : internal_state(start_state) - {} - - void reset(state_t start_state = method_start) { - internal_state = method_start; - } - - state_t state() const { return internal_state; } - - template - fusion::tuple > - parse_until(state_t stop_state, Range & range) { - logic::tribool parsed_ok = logic::indeterminate; - typedef typename range_iterator::type iterator; - iterator start = boost::begin(range) - , end = boost::end(range) - , current_iterator = start; - iterator_range local_range = - boost::make_iterator_range(start, end); - while ( - !boost::empty(local_range) - && stop_state != internal_state - && indeterminate(parsed_ok) - ) { - current_iterator = boost::begin(local_range); - switch(internal_state) { - case method_start: - if (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; - 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; - 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; - break; - case uri_done: - if (*current_iterator == 'H') internal_state = version_h; - else parsed_ok = false; - break; - case version_h: - if (*current_iterator == 'T') internal_state = version_t1; - else parsed_ok = false; - break; - case version_t1: - if (*current_iterator == 'T') internal_state = version_t2; - else parsed_ok = false; - break; - case version_t2: - if (*current_iterator == 'P') internal_state = version_p; - else parsed_ok = false; - break; - case version_p: - if (*current_iterator == '/') internal_state = version_slash; - else parsed_ok = false; - break; - case version_slash: - if (algorithm::is_digit()(*current_iterator)) internal_state = version_d1; - else parsed_ok = false; - break; - case version_d1: - if (*current_iterator == '.') internal_state = version_dot; - else parsed_ok = false; - break; - case version_dot: - if (algorithm::is_digit()(*current_iterator)) internal_state = version_d2; - else parsed_ok = false; - break; - case version_d2: - if (*current_iterator == '\r') internal_state = version_cr; - else parsed_ok = false; - break; - case version_cr: - if (*current_iterator == '\n') internal_state = version_done; - else parsed_ok = false; - break; - case version_done: - if (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 parsed_ok = false; - break; - case header_colon: - if (*current_iterator == ' ') internal_state = header_value; - else parsed_ok = false; - break; - case header_value: - if (*current_iterator == '\r') internal_state = header_cr; - else if (algorithm::is_cntrl()(*current_iterator)) parsed_ok = false; - break; - case header_cr: - if (*current_iterator == '\n') internal_state = header_line_done; - else parsed_ok = false; - 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 parsed_ok = false; - break; - case headers_cr: - if (*current_iterator == '\n') internal_state = headers_done; - else parsed_ok = false; - break; - case headers_done: - // anything that follows after headers_done is allowed. - break; - default: - parsed_ok = false; - }; - if (internal_state == stop_state) parsed_ok = true; - local_range = boost::make_iterator_range( - ++current_iterator, end); - } - return fusion::make_tuple( - parsed_ok, - boost::make_iterator_range( - start, current_iterator - ) - ); - } - - private: - state_t internal_state; - - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_REQUEST_PARSER_HPP_20101005 */ diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/boost/network/protocol/http/server/socket_options_base.hpp deleted file mode 100644 index 0563272a6..000000000 --- a/boost/network/protocol/http/server/socket_options_base.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#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. -// Distributed under the 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 { - - struct socket_options_base { - protected: - asio::socket_base::reuse_address acceptor_reuse_address; - asio::socket_base::enable_connection_aborted acceptor_report_aborted; - boost::optional receive_buffer_size; - boost::optional send_buffer_size; - boost::optional receive_low_watermark; - boost::optional send_low_watermark; - asio::socket_base::non_blocking_io non_blocking_io; - asio::socket_base::linger linger; - - template - socket_options_base(ArgPack const & args) - : acceptor_reuse_address(args[_reuse_address|false]) - , acceptor_report_aborted(args[_report_aborted|false]) - , non_blocking_io(args[_non_blocking_io|true]) - , linger(args[_linger|true], args[_linger_timeout|0]) - { - set_optional(receive_buffer_size, args, _receive_buffer_size); - set_optional(send_buffer_size, args, _send_buffer_size); - set_optional(receive_low_watermark, args, _receive_low_watermark); - set_optional(send_low_watermark, args, _send_low_watermark); - } - - void acceptor_options(boost::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; - socket.io_control(non_blocking_io, ignored); - socket.set_option(linger, ignored); - if (receive_buffer_size) socket.set_option(*receive_buffer_size, ignored); - if (receive_low_watermark) socket.set_option(*receive_low_watermark, ignored); - if (send_buffer_size) socket.set_option(*send_buffer_size, ignored); - if (send_low_watermark) socket.set_option(*send_low_watermark, ignored); - } - - private: - - template - typename boost::enable_if< - mpl::not_< - boost::is_same< - typename boost::parameter::value_type::type - , void - > - > - , void - >::type - set_optional(Optional & option, Args const & args, Keyword const & keyword) { - option = in_place(args[keyword]); - } - - template - typename boost::enable_if< - boost::is_same< - typename boost::parameter::value_type::type - , void - > - , void - >::type - set_optional(Optional &, Args const &, Keyword const &) { - // do nothing - } - - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/storage_base.hpp b/boost/network/protocol/http/server/storage_base.hpp deleted file mode 100644 index ccfe3fd12..000000000 --- a/boost/network/protocol/http/server/storage_base.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#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. -// Distributed under the 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 server_storage_base { - struct no_io_service {}; - struct has_io_service {}; - protected: - template - server_storage_base(ArgPack const & /* args */, no_io_service) - : self_service_(new boost::asio::io_service()) - , service_(*self_service_) - {} - - template - server_storage_base(ArgPack const & args, has_io_service) - : self_service_(0) - , service_(args[_io_service]) - {} - - ~server_storage_base() { - delete self_service_; - self_service_ = 0; - } - - asio::io_service * self_service_; - asio::io_service & service_; - }; - - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 */ 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/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp deleted file mode 100644 index 71619bce3..000000000 --- a/boost/network/protocol/http/server/sync_server.hpp +++ /dev/null @@ -1,132 +0,0 @@ - -// Copyright 2010 Dean Michael Berris. -// Copyright 2010 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_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct sync_server_base : server_storage_base, socket_options_base { - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef typename boost::network::http::response_header::type response_header; - - template - sync_server_base(ArgPack const & args) - : server_storage_base(args, - typename mpl::if_< - is_same< - typename parameter::value_type::type, - void - >, - server_storage_base::no_io_service, - server_storage_base::has_io_service - >::type()) - , socket_options_base(args) - , handler_(args[_handler]) - , address_(args[_address]) - , port_(args[_port]) - , acceptor_(server_storage_base::service_) - , new_connection() - , listening_mutex_() - , listening_(false) - {} - - void run() { - listen(); - service_.run(); - } - - void stop() { - // stop accepting new connections and let all the existing handlers finish. - system::error_code ignored; - acceptor_.close(ignored); - service_.stop(); - } - - void listen() { - boost::unique_lock listening_lock(listening_mutex_); - if (!listening_) start_listening(); - } - - private: - - Handler & handler_; - string_type address_, port_; - boost::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) { - 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)); - } - } - - void start_listening() { - using boost::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_); - return; - } - tcp::endpoint endpoint = *endpoint_iterator; - acceptor_.open(endpoint.protocol(), error); - if (error) { - BOOST_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 << '\''); - return; - } - acceptor_.listen(tcp::socket::max_connections, error); - if (error) { - BOOST_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)); - listening_ = true; - } - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ diff --git a/boost/network/protocol/http/support/client_or_server.hpp b/boost/network/protocol/http/support/client_or_server.hpp deleted file mode 100644 index 2ad74b105..000000000 --- a/boost/network/protocol/http/support/client_or_server.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#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. -// Distributed under the 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 unsupported_tag; - - template - struct client_or_server - { - typedef unsupported_tag type; - }; - - template - struct client_or_server >::type> - { - typedef tags::server type; - }; - - template - struct client_or_server >::type> - { - typedef tags::client type; - }; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 */ diff --git a/boost/network/protocol/http/support/is_client.hpp b/boost/network/protocol/http/support/is_client.hpp deleted file mode 100644 index e15b89603..000000000 --- a/boost/network/protocol/http/support/is_client.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 -#define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_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_client : mpl::false_ {}; - - template - struct is_client::type> : mpl::true_ {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 */ - 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_keepalive.hpp b/boost/network/protocol/http/support/is_keepalive.hpp deleted file mode 100644 index c3fa73a07..000000000 --- a/boost/network/protocol/http/support/is_keepalive.hpp +++ /dev/null @@ -1,29 +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 { namespace http { - - template - struct unsupported_tag; - - template - struct is_keepalive : mpl::false_ {}; - - template - struct is_keepalive::type> : mpl::true_ {}; - -} /* http */ - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_KEEPALIVE_HPP_20100927 */ 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_http.hpp b/boost/network/support/is_http.hpp deleted file mode 100644 index c104e7b42..000000000 --- a/boost/network/support/is_http.hpp +++ /dev/null @@ -1,24 +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 { - - template - struct is_http : mpl::false_ {}; - - template - struct is_http::type> : mpl::true_ {}; - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_SUPPORT_IS_HTTP_HPP_20100622 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_simple.hpp b/boost/network/support/is_simple.hpp deleted file mode 100644 index 98406d41a..000000000 --- a/boost/network/support/is_simple.hpp +++ /dev/null @@ -1,24 +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 { - - template - struct is_simple : mpl::false_ {}; - - template - struct is_simple::type> : mpl::true_ {}; - -} /* network */ - -} /* boost */ - -#endif /* BOOST_NETWORK_SUPPORT_IS_SIMPLE_HPP_20100927 */ 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..6ef114efb --- /dev/null +++ b/concurrency/CMakeLists.txt @@ -0,0 +1,14 @@ +# 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) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_CONCURRENCY_SRCS ${CPP-NETLIB_CONCURRENCY_SRCS} PARENT_SCOPE) diff --git a/concurrency/src/CMakeLists.txt b/concurrency/src/CMakeLists.txt new file mode 100644 index 000000000..6a894f880 --- /dev/null +++ b/concurrency/src/CMakeLists.txt @@ -0,0 +1,20 @@ +# 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) + +set(CPP-NETLIB_CONCURRENCY_SRCS + thread_pool.cpp) + +if(NOT CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(network-concurrency ${CPP-NETLIB_CONCURRENCY_SRCS}) +endif() + +# prepend current directory to make paths absolute +prependToElements( "${CMAKE_CURRENT_SOURCE_DIR}/" + CPP-NETLIB_CONCURRENCY_SRCS ) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_CONCURRENCY_SRCS ${CPP-NETLIB_CONCURRENCY_SRCS} PARENT_SCOPE) diff --git a/concurrency/src/network/concurrency/thread_pool.hpp b/concurrency/src/network/concurrency/thread_pool.hpp new file mode 100644 index 000000000..a61d82d10 --- /dev/null +++ b/concurrency/src/network/concurrency/thread_pool.hpp @@ -0,0 +1,107 @@ +// Copyright 2010 Dean Michael Berris. +// Copyright 2012 Google, Inc. +// Copyright (c) Glyn Matthews 2012, 2013, 2014. +// Distributed under the 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_INC +#define NETWORK_CONCURRENCY_THREAD_POOL_INC + +/** + * \defgroup concurrency Basic Concurrency Types + * + * This module contains a simple concurrency types for use inside the + * cpp-netlib network libraries. + * + * \file + * \brief Contains a thread_pool type. + */ + +#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; + + /** + * \ingroup concurrency + * \class thread_pool network/concurrency/thread_pool.hpp + * \brief A very simple thread pool. + */ + class thread_pool { + + thread_pool(thread_pool const&) = delete; + thread_pool& operator=(thread_pool const&) = delete; + + public: + + /** + * \brief Constructor. + * \param thread_count The number of threads in the thread pool. + * \param io_service An external io_service. + * \param worker_threads An external thread pool. + */ + thread_pool(std::size_t thread_count = 1, + io_service_ptr io_service = io_service_ptr(), + std::vector worker_threads = std::vector()); + + /** + * \brief Move constuctor. + * \param other The other thread_pool object. + */ + thread_pool(thread_pool&& other); + + /** + * \brief Destructor. + */ + ~thread_pool(); + + /** + * \brief Swap function. + * \param other The other thread_pool object. + */ + void swap(thread_pool& other); + + /** + * \brief Move assignment operator. + * \param other The other thread_pool object. + */ + thread_pool& operator=(thread_pool&& other); + + /** + * \brief Returns the number of threads in the thread pool. + * \returns The number of threads in the thread pool. + */ + std::size_t const thread_count() const; + + /** + * \brief Posts a task to the thread pool. + * \param task The task to be executed. + */ + void post(std::function task); + + private: + + struct impl; + impl* pimpl_; + + }; + + inline + void swap(thread_pool& l, thread_pool& r) { + l.swap(r); + } + + } // namespace concurrency +} // namespace network + +#endif // NETWORK_CONCURRENCY_THREAD_POOL_INC diff --git a/concurrency/src/network/concurrency/thread_pool.ipp b/concurrency/src/network/concurrency/thread_pool.ipp new file mode 100644 index 000000000..baaa5a69c --- /dev/null +++ b/concurrency/src/network/concurrency/thread_pool.ipp @@ -0,0 +1,107 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, Inc. +// Copyright (c) Glyn Matthews 2012, 2013. +// Distributed under the 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::impl { + impl(std::size_t thread_count = 1, + io_service_ptr io_service = io_service_ptr(), + std::vector worker_threads = std::vector()) + : thread_count_(thread_count), + 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 < thread_count_; ++counter) { + worker_threads_.emplace_back([local_io_service]() { + local_io_service->run(); + }); + } + + commit = true; + } + + ~impl() { + 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(); + } + } + + std::size_t thread_count_; + io_service_ptr io_service_; + std::vector worker_threads_; + sentinel_ptr sentinel_; + + }; + + thread_pool::thread_pool(std::size_t thread_count, + io_service_ptr io_service, + std::vector worker_threads) + : pimpl_(new (std::nothrow) + impl(thread_count, 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_->io_service_->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..8695cfa88 --- /dev/null +++ b/concurrency/src/network/utils/thread_pool.hpp @@ -0,0 +1,17 @@ +// Copyright (c) Glyn Matthews 2012, 2013. +// Distributed under the 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..abff4a019 --- /dev/null +++ b/concurrency/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) + +include_directories(${CPP-NETLIB_SOURCE_DIR}/concurrency/src + ${GTEST_INCLUDE_DIRS} + ${CPP-NETLIB_SOURCE_DIR} +) +if (CPP-NETLIB_BUILD_TESTS) + add_executable(cpp-netlib-thread_pool_test thread_pool_test.cpp) + target_link_libraries(cpp-netlib-thread_pool_test + network-concurrency + ${Boost_LIBRARIES} + ${GTEST_BOTH_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) +endif() diff --git a/concurrency/test/thread_pool_test.cpp b/concurrency/test/thread_pool_test.cpp new file mode 100644 index 000000000..8ebef15b7 --- /dev/null +++ b/concurrency/test/thread_pool_test.cpp @@ -0,0 +1,45 @@ + +// Copyright 2010, 2012 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) + +#include +#include +#include + +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 +// tests that this unit test requires of thread pools. Ultimately the +// requirements will show up in the Concept documentation, but this test is the +// canonical definition of what a thread pool should look like at least +// syntactically. +// + +TEST(concurrency_test, default_constructor) { + thread_pool pool; + ASSERT_EQ(pool.thread_count(), std::size_t(1)); +} + +struct foo { + foo() : val_(0) {} + void bar(int val) { val_ += val; } + int const val() const { return val_; } + protected: + int val_; +}; + +TEST(concurrency_test, post_work) { + foo instance; + { + thread_pool pool; + ASSERT_NO_THROW(pool.post(std::bind(&foo::bar, &instance, 1))); + ASSERT_NO_THROW(pool.post(std::bind(&foo::bar, &instance, 2))); + // require that pool is destroyed here, RAII baby + } + ASSERT_EQ(3, instance.val()); +} diff --git a/config/src/network/config.hpp b/config/src/network/config.hpp new file mode 100644 index 000000000..1dc0e1a62 --- /dev/null +++ b/config/src/network/config.hpp @@ -0,0 +1,45 @@ +// Copyright (c) Glyn Matthews 2012, 2013. +// 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_CONFIG_INC +#define NETWORK_CONFIG_INC + +#include +#include + +#if defined(BOOST_ALL_DYN_LINK) +#define NETWORK_DECL BOOST_SYMBOL_EXPORT +#else +#define NETWORK_DECL +#endif // defined(BOOST_ALL_DYN_LINK) + +#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) +#define NETWORK_DEFAULTED_FUNCTION {} +#else +#define NETWORK_DEFAULTED_FUNCTION = default +#endif // defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#define NETWORK_DELETED_FUNCTION {} +#else +#define NETWORK_DELETED_FUNCTION = delete +#endif // defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +#if defined(BOOST_NO_CXX11_NOEXCEPT) +#define NETWORK_NOEXCEPT throw() +#else +#define NETWORK_NOEXCEPT noexcept +#endif // defined(BOOST_NO_CXX11_NOEXCEPT) + +#if defined(BOOST_NO_CXX11_OVERRIDE) +#define NETWORK_OVERRIDE +#else +#define NETWORK_OVERRIDE override +#endif // defined(BOOST_NO_CXX11_OVERRIDE) + +#endif // NETWORK_CONFIG_INC diff --git a/contrib/http_examples/CMakeLists.txt b/contrib/http_examples/CMakeLists.txt new file mode 100644 index 000000000..0745b2d58 --- /dev/null +++ b/contrib/http_examples/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) Dean Michael Berris 2010. +# Copyright (c) Glyn Matthews 2013. +# Distributed under the 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}/config/src + ${CPP-NETLIB_SOURCE_DIR}/uri/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) + +set( CPP-NETLIB_LOGGING_LIB "" ) +if( NOT CPP-NETLIB_DISABLE_LOGGING AND NOT CPP-NETLIB_BUILD_SINGLE_LIB) + set( CPP-NETLIB_LOGGING_LIB network-logging ) +endif() + +set(EXAMPLES + simple_wget + read_headers + ) + +foreach(example ${EXAMPLES}) + add_executable(${example} ${example}.cpp) + target_link_libraries(${example} + network-uri + network-http-v2-client + ${Boost_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + set_target_properties(${example} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +endforeach(example) diff --git a/contrib/http_examples/read_headers.cpp b/contrib/http_examples/read_headers.cpp new file mode 100644 index 000000000..c53b53611 --- /dev/null +++ b/contrib/http_examples/read_headers.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2013 by 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 http = network::http; + + +int +main(int argc, char *argv[]) { + + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " url" << std::endl; + return 1; + } + + try { + http::client client; + http::request request{network::uri{std::string{argv[1]}}}; + request.version("1.0"); + request.append_header("Connection", "close"); + request.append_header("User-Agent", "cpp-netlib read_headers example"); + auto future_response = client.head(request); + auto response = future_response.get(); + + std::cout << "HTTP version: " << response.version() << std::endl; + std::cout << "HTTP status: " << static_cast(response.status()) << std::endl; + std::cout << "HTTP status message: " << response.status_message() << std::endl; + std::cout << std::endl; + for (auto header : response.headers()) { + std::cout << header.first << ": " << header.second << std::endl; + } + } + catch (std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/contrib/http_examples/simple_wget.cpp b/contrib/http_examples/simple_wget.cpp new file mode 100644 index 000000000..f4b9de49f --- /dev/null +++ b/contrib/http_examples/simple_wget.cpp @@ -0,0 +1,58 @@ +// Copyright (c) Glyn Matthews 2009-2013. +// 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 of the `uri` and the `http::client`. +*/ + +#include +#include +#include +#include + +namespace http = network::http; + +namespace { +std::string get_filename(const std::string& path) { + auto index = path.find_last_of('/'); + auto 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::request request{network::uri{std::string{argv[1]}}}; + request.version("1.0"); + request.append_header("Connection", "close"); + request.append_header("User-Agent", "cpp-netlib simple_wget example"); + auto future_response = client.get(request); + auto response = future_response.get(); + + auto filename = get_filename(request.path()); + std::cout << "Saving to: " << filename << std::endl; + std::ofstream ofs(filename.c_str()); + ofs << response.body() << std::endl; + } + catch (std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/deps/asio b/deps/asio new file mode 160000 index 000000000..e80030ffa --- /dev/null +++ b/deps/asio @@ -0,0 +1 @@ +Subproject commit e80030ffa178dbcca11d84ab607a87495a711a17 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/deps/igloo b/deps/igloo new file mode 160000 index 000000000..7d5ad81e7 --- /dev/null +++ b/deps/igloo @@ -0,0 +1 @@ +Subproject commit 7d5ad81e705e61453adc16990dab8c825b41e20b 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..9c3d0d45f --- /dev/null +++ b/http/CMakeLists.txt @@ -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) + +add_subdirectory(src) + +if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) +endif(CPP-NETLIB_BUILD_TESTS) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_HTTP_MESSAGE_SRCS ${CPP-NETLIB_HTTP_MESSAGE_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS ${CPP-NETLIB_HTTP_CLIENT_CONNECTIONS_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_CLIENT_SRCS ${CPP-NETLIB_HTTP_CLIENT_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_SERVER_SRCS ${CPP-NETLIB_HTTP_SERVER_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_CONSTANTS_SRCS ${CPP-NETLIB_CONSTANTS_SRCS} PARENT_SCOPE) diff --git a/http/src/CMakeLists.txt b/http/src/CMakeLists.txt new file mode 100644 index 000000000..4621f502a --- /dev/null +++ b/http/src/CMakeLists.txt @@ -0,0 +1,84 @@ +# Copyright (c) Glyn Matthews 2011, 2012, 2013. +# 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}/config/src + ${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() + +set(CPP-NETLIB_HTTP_MESSAGE_SRCS + http/request.cpp + http/response.cpp) + +if(NOT CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(network-http-message ${CPP-NETLIB_HTTP_MESSAGE_SRCS}) + target_link_libraries(network-http-message + ${Boost_LIBRARIES} + network-message) +endif() + +set(CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS + http/message/wrappers.cpp) + +if(NOT CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(network-http-message-wrappers ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS}) +endif() + +set(CPP-NETLIB_CONSTANTS_SRCS + constants.cpp) + +if(NOT CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(network-constants ${CPP-NETLIB_CONSTANTS_SRCS}) +endif() + +# Server implementation files. +set(CPP-NETLIB_HTTP_SERVER_SRCS + http/server/session.cpp + http/server/simple_sessions.cpp + http/server/dynamic_dispatcher.cpp) + +if (NOT CPP-NETLIB_BUILD_SINGLE_LIB) + add_library(network-http-server ${CPP-NETLIB_HTTP_SERVER_SRCS}) +endif() + +# HTTP client +set(CPP-NETLIB_HTTP_V2_CLIENT_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/http/v2/client/client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/http/v2/client/client_errors.cpp + ) +add_library(network-http-v2-client ${CPP-NETLIB_HTTP_V2_CLIENT_SRCS}) +target_link_libraries(network-http-v2-client + ${Boost_LIBRARIES} + network-uri + ) +if (OPENSSL_FOUND) + target_link_libraries(network-http-v2-client ${OPENSSL_LIBRARIES}) +endif() + +# prepend current directory to make paths absolute +prependToElements( "${CMAKE_CURRENT_SOURCE_DIR}/" + CPP-NETLIB_HTTP_MESSAGE_SRCS + CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS + CPP-NETLIB_CONSTANTS_SRCS + CPP-NETLIB_HTTP_SERVER_SRCS + CPP-NETLIB_HTTP_V2_CLIENT_SRCS ) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_HTTP_MESSAGE_SRCS ${CPP-NETLIB_HTTP_MESSAGE_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS ${CPP-NETLIB_HTTP_MESSAGE_WRAPPERS_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_SERVER_SRCS ${CPP-NETLIB_HTTP_SERVER_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_CONSTANTS_SRCS ${CPP-NETLIB_CONSTANTS_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_HTTP_V2_CLIENT_SRCS ${CPP-NETLIB_HTTP_V2_CLIENT_SRCS} PARENT SCOPE) 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..28cd3ed54 --- /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/http/src/http/server.hpp b/http/src/http/server.hpp new file mode 100644 index 000000000..d3d4deea2 --- /dev/null +++ b/http/src/http/server.hpp @@ -0,0 +1,41 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_HPP_20130327 +#define NETWORK_HTTP_SERVER_HPP_20130327 + +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct dynamic_dispatcher; +struct no_auth; +struct default_connection_manager; +struct connection; + +template +struct basic_server { + void register_handler( + boost::string_ref spec, + std::function)> handler); +}; + +typedef basic_server<> server; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_HPP_20130327 */ + diff --git a/http/src/http/server/connection.hpp b/http/src/http/server/connection.hpp new file mode 100644 index 000000000..fa1229957 --- /dev/null +++ b/http/src/http/server/connection.hpp @@ -0,0 +1,20 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_CONNECTION_HPP_20130410 +#define NETWORK_HTTP_SERVER_CONNECTION_HPP_20130410 + +namespace network { +namespace http { + +struct connection { +}; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_CONNECTION_HPP_20130410 */ + diff --git a/http/src/http/server/default_connection_manager.hpp b/http/src/http/server/default_connection_manager.hpp new file mode 100644 index 000000000..8e787793f --- /dev/null +++ b/http/src/http/server/default_connection_manager.hpp @@ -0,0 +1,19 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_DEFAULT_CONNECTION_MANAGER_20130408 +#define NETWORK_HTTP_SERVER_DEFAULT_CONNECTION_MANAGER_20130408 + +namespace network { +namespace http { + +struct default_connection_manager { +}; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_DEFAULT_CONNECTION_MANAGER_20130408 */ diff --git a/http/src/http/server/dynamic_dispatcher.cpp b/http/src/http/server/dynamic_dispatcher.cpp new file mode 100644 index 000000000..bf1e9eb88 --- /dev/null +++ b/http/src/http/server/dynamic_dispatcher.cpp @@ -0,0 +1,27 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 network { +namespace http { + +void dynamic_dispatcher::register_handler(boost::string_ref pattern, std::function)> handler) { + auto inserted = handlers_.insert(make_pair(static_cast(pattern), + handler)); + if (!inserted.second) + inserted.first->second = handler; +} + +void dynamic_dispatcher::dispatch(boost::string_ref path, session& s, std::shared_ptr c) { + auto entry = handlers_.find(static_cast(path)); + if (entry != handlers_.end()) { + entry->second(s, c); + } +} + +} // namespace http +} // namespace network diff --git a/http/src/http/server/dynamic_dispatcher.hpp b/http/src/http/server/dynamic_dispatcher.hpp new file mode 100644 index 000000000..39d304467 --- /dev/null +++ b/http/src/http/server/dynamic_dispatcher.hpp @@ -0,0 +1,33 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_DYNAMIC_DISPATCHER_HPP_20130327 +#define NETWORK_HTTP_SERVER_DYNAMIC_DISPATCHER_HPP_20130327 + +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct dynamic_dispatcher{ + void register_handler(boost::string_ref pattern, std::function)> handler); + void dispatch(boost::string_ref path, session& s, std::shared_ptr c); + private: + std::unordered_map< + std::string, + std::function)> > handlers_; +}; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_DYNAMIC_DISPATCHER_HPP_20130327 */ + diff --git a/http/src/http/server/session.cpp b/http/src/http/server/session.cpp new file mode 100644 index 000000000..12b7dfa31 --- /dev/null +++ b/http/src/http/server/session.cpp @@ -0,0 +1,33 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 network { +namespace http { + +std::string session::get(boost::string_ref key, boost::string_ref value) const { + session_map_type::const_iterator entry = session_map_.find( + static_cast(key)); + return entry == session_map_.end() ? static_cast(value) : + entry->second.second; +} + +void session::set(boost::string_ref key, boost::string_ref value, + bool server_only) { + auto new_value = make_pair(server_only, static_cast(value)); + std::pair result = + session_map_.insert(make_pair(static_cast(key), new_value)); + if (!result.second) + result.first->second = std::move(new_value); +} + +std::string session::operator[](boost::string_ref key) const { + return get(key, ""); +} + +} // namespace http +} // namespace network diff --git a/http/src/http/server/session.hpp b/http/src/http/server/session.hpp new file mode 100644 index 000000000..76eca5cad --- /dev/null +++ b/http/src/http/server/session.hpp @@ -0,0 +1,36 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_SESSION_HPP_20130405 +#define NETWORK_HTTP_SERVER_SESSION_HPP_20130405 + +#include +#include +#include + +namespace network { +namespace http { + +struct session { + session() = default; + session(const session&) = default; + session(session&&) = default; + session& operator=(const session&) = default; + session& operator=(session&&) = default; + + void set(boost::string_ref key, boost::string_ref value, bool server_only = false); + std::string get(boost::string_ref key, boost::string_ref default_value) const; + std::string operator[](boost::string_ref key) const; + private: + typedef std::unordered_map> session_map_type; + session_map_type session_map_; +}; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_SESSION_HPP_20130405 */ + diff --git a/http/src/http/server/simple_sessions.cpp b/http/src/http/server/simple_sessions.cpp new file mode 100644 index 000000000..f08e5d43b --- /dev/null +++ b/http/src/http/server/simple_sessions.cpp @@ -0,0 +1,48 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 network { +namespace http { + +session simple_sessions::lookup(boost::string_ref session_id) { + std::string real_session_id = + session_id.empty() ? std::to_string(next_session_id_.fetch_add( + 1, std::memory_order::memory_order_seq_cst)) : + static_cast(session_id); + assert(real_session_id != ""); + std::lock_guard lock_sessions(sessions_mutex_); + std::pair result = + sessions_.insert(make_pair(std::move(real_session_id), session())); + if (result.second) { + result.first->second.set("id", result.first->first); + assert(result.first->second["id"] != ""); + } + return result.first->second; +} + +void simple_sessions::update(boost::string_ref session_id, session&& session) { + std::string real_session_id = + session_id.empty() ? std::to_string(next_session_id_.fetch_add( + 1, std::memory_order::memory_order_seq_cst)) : + static_cast(session_id); + assert(real_session_id != ""); + std::lock_guard lock_sessions(sessions_mutex_); + auto it = sessions_.find(real_session_id); + if (it != sessions_.end()) { + it->second = session; + } else { + bool added = false; + std::tie(it, added) = sessions_.insert(make_pair(std::move(real_session_id), + session)); + assert(added && " -- for some reason we cannot add here."); + } +} + +} // namespace http +} // namespace network diff --git a/http/src/http/server/simple_sessions.hpp b/http/src/http/server/simple_sessions.hpp new file mode 100644 index 000000000..ed063b0c4 --- /dev/null +++ b/http/src/http/server/simple_sessions.hpp @@ -0,0 +1,40 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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) + +#ifndef NETWORK_HTTP_SERVER_SIMPLE_SESSIONS_HPP_20130327 +#define NETWORK_HTTP_SERVER_SIMPLE_SESSIONS_HPP_20130327 + +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +struct simple_sessions { + simple_sessions() = default; + simple_sessions(const simple_sessions&) = delete; + simple_sessions(simple_sessions&&) = delete; + simple_sessions& operator=(const simple_sessions&) = delete; + simple_sessions& operator=(simple_sessions&) = delete; + + session lookup(boost::string_ref session_id); + void update(boost::string_ref session_id, session&& session); + private: + typedef std::unordered_map session_map_type; + std::mutex sessions_mutex_; + session_map_type sessions_; + std::atomic_uint_fast64_t next_session_id_; +}; + +} // namespace http +} // namespace network + +#endif /* end of include guard: NETWORK_HTTP_SERVER_SIMPLE_SESSIONS_HPP_20130327 */ + diff --git a/http/src/http/server_async_impl.cpp b/http/src/http/server_async_impl.cpp new file mode 100644 index 000000000..9393b9b9f --- /dev/null +++ b/http/src/http/server_async_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/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/http/v2/client/client.cpp b/http/src/http/v2/client/client.cpp new file mode 100644 index 000000000..2ee705f76 --- /dev/null +++ b/http/src/http/v2/client/client.cpp @@ -0,0 +1,512 @@ +// Copyright (C) 2013, 2014 by 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { + namespace http { + namespace v2 { + using boost::asio::ip::tcp; + + struct request_context { + + std::shared_ptr connection_; + + request request_; + request_options options_; + + std::promise response_promise_; + + boost::asio::streambuf request_buffer_; + boost::asio::streambuf response_buffer_; + + std::uint64_t total_bytes_written_, total_bytes_read_; + + request_context( + std::shared_ptr connection, + request request, request_options options) + : connection_(connection), + request_(request), + options_(options), + total_bytes_written_(0), + total_bytes_read_(0) {} + }; + + struct client::impl { + + explicit impl(client_options options); + + impl(std::unique_ptr mock_resolver, + std::unique_ptr + mock_connection, client_options options); + + ~impl(); + + void set_error(const boost::system::error_code &ec, + std::shared_ptr context); + + std::future execute(std::shared_ptr context); + + void timeout(const boost::system::error_code &ec, + std::shared_ptr context); + + void connect(const boost::system::error_code &ec, + tcp::resolver::iterator endpoint_iterator, + std::shared_ptr context); + + void write_request(const boost::system::error_code &ec, + std::shared_ptr context); + + void write_body(const boost::system::error_code &ec, + std::size_t bytes_written, + std::shared_ptr context); + + void read_response(const boost::system::error_code &ec, + std::size_t bytes_written, + std::shared_ptr context); + + void read_response_status(const boost::system::error_code &ec, + std::size_t bytes_written, + std::shared_ptr context); + + void read_response_headers(const boost::system::error_code &ec, + std::size_t bytes_read, + std::shared_ptr context, + std::shared_ptr res); + + void read_response_body(const boost::system::error_code &ec, + std::size_t bytes_read, + std::shared_ptr context, + std::shared_ptr res); + + client_options options_; + boost::asio::io_service io_service_; + std::unique_ptr sentinel_; + boost::asio::io_service::strand strand_; + std::unique_ptr resolver_; + std::shared_ptr mock_connection_; + bool timedout_; + boost::asio::deadline_timer timer_; + std::thread lifetime_thread_; + + }; + + client::impl::impl(client_options options) + : options_(options), + sentinel_(new boost::asio::io_service::work(io_service_)), + strand_(io_service_), + resolver_(new client_connection::tcp_resolver( + io_service_, options_.cache_resolved())), + timedout_(false), + timer_(io_service_), + lifetime_thread_([=]() { io_service_.run(); }) {} + + client::impl::impl( + std::unique_ptr mock_resolver, + std::unique_ptr mock_connection, + client_options options) + : options_(options), + sentinel_(new boost::asio::io_service::work(io_service_)), + strand_(io_service_), + resolver_(std::move(mock_resolver)), + timedout_(false), + timer_(io_service_), + lifetime_thread_([=]() { io_service_.run(); }) {} + + client::impl::~impl() { + sentinel_.reset(); + lifetime_thread_.join(); + } + + + void client::impl::set_error(const boost::system::error_code &ec, + std::shared_ptr context) { + context->response_promise_.set_exception(std::make_exception_ptr( + std::system_error(ec.value(), std::system_category()))); + timer_.cancel(); + } + + std::future client::impl::execute( + std::shared_ptr context) { + std::future res = context->response_promise_.get_future(); + + // If there is no user-agent, provide one as a default. + auto user_agent = context->request_.header("User-Agent"); + if (!user_agent) { + context->request_.append_header("User-Agent", options_.user_agent()); + } + + // Get the host and port from the request and resolve + auto url = context->request_.url(); + auto host = url.host() ? uri::string_type(std::begin(*url.host()), + std::end(*url.host())) + : uri::string_type(); + auto port = url.port() ? *url.port() : 80; + + resolver_->async_resolve( + host, port, + strand_.wrap([=](const boost::system::error_code &ec, + tcp::resolver::iterator endpoint_iterator) { + connect(ec, endpoint_iterator, context); + })); + + if (options_.timeout() > std::chrono::milliseconds(0)) { + timer_.expires_from_now(boost::posix_time::milliseconds(options_.timeout().count())); + timer_.async_wait(strand_.wrap([=](const boost::system::error_code &ec) { + timeout(ec, context); + })); + } + + return res; + } + + void client::impl::timeout(const boost::system::error_code &ec, + std::shared_ptr context) { + if (!ec) { + context->connection_->disconnect(); + } + timedout_ = true; + } + + void client::impl::connect(const boost::system::error_code &ec, + tcp::resolver::iterator endpoint_iterator, + std::shared_ptr context) { + if (ec) { + set_error(ec, context); + return; + } + + // make a connection to an endpoint + auto host = context->request_.url().host(); + tcp::endpoint endpoint(*endpoint_iterator); + context->connection_->async_connect( + endpoint, std::string(std::begin(*host), std::end(*host)), + strand_.wrap([=](const boost::system::error_code &ec) { + // If there is no connection, try again on another endpoint + if (ec && endpoint_iterator != tcp::resolver::iterator()) { + // copy iterator because it is const after the lambda + // capture + auto it = endpoint_iterator; + boost::system::error_code ignore; + connect(ignore, ++it, context); + return; + } + + write_request(ec, context); + })); + } + + void client::impl::write_request( + const boost::system::error_code &ec, + std::shared_ptr context) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec) { + set_error(ec, context); + return; + } + + // write the request to an I/O stream. + std::ostream request_stream(&context->request_buffer_); + request_stream << context->request_; + if (!request_stream) { + context->response_promise_.set_exception(std::make_exception_ptr( + client_exception(client_error::invalid_request))); + timer_.cancel(); + } + + context->connection_->async_write( + context->request_buffer_, + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_written) { + write_body(ec, bytes_written, context); + })); + } + + void client::impl::write_body(const boost::system::error_code &ec, + std::size_t bytes_written, + std::shared_ptr context) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec) { + set_error(ec, context); + return; + } + + // update progress + context->total_bytes_written_ += bytes_written; + if (auto progress = context->options_.progress()) { + progress(client_message::transfer_direction::bytes_written, + context->total_bytes_written_); + } + + // write the body to an I/O stream + std::ostream request_stream(&context->request_buffer_); + // TODO write payload to request_buffer_ + if (!request_stream) { + context->response_promise_.set_exception(std::make_exception_ptr( + client_exception(client_error::invalid_request))); + } + + context->connection_->async_write( + context->request_buffer_, + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_written) { + read_response(ec, bytes_written, context); + })); + } + + void client::impl::read_response( + const boost::system::error_code &ec, std::size_t bytes_written, + std::shared_ptr context) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec) { + set_error(ec, context); + return; + } + + // update progress. + context->total_bytes_written_ += bytes_written; + if (auto progress = context->options_.progress()) { + progress(client_message::transfer_direction::bytes_written, + context->total_bytes_written_); + } + + // Create a response object and fill it with the status from the server. + context->connection_->async_read_until( + context->response_buffer_, "\r\n", + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_read) { + read_response_status(ec, bytes_read, context); + })); + } + + void client::impl::read_response_status( + const boost::system::error_code &ec, std::size_t, + std::shared_ptr context) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec) { + set_error(ec, context); + return; + } + + // Update the reponse status. + std::istream is(&context->response_buffer_); + string_type version; + is >> version; + unsigned int status; + is >> status; + string_type message; + std::getline(is, message); + + // if options_.follow_redirects() + // and if status in range 300 - 307 + // then take the request and reset the URL from the 'Location' header + // restart connection + // Not that the 'Location' header can be a *relative* URI + + std::shared_ptr res(new response{}); + res->set_version(version); + res->set_status(network::http::status::code(status)); + res->set_status_message(boost::trim_copy(message)); + + // Read the response headers. + context->connection_->async_read_until( + context->response_buffer_, "\r\n\r\n", + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_read) { + read_response_headers(ec, bytes_read, context, res); + })); + } + + void client::impl::read_response_headers( + const boost::system::error_code &ec, std::size_t, + std::shared_ptr context, + std::shared_ptr res) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec) { + set_error(ec, context); + return; + } + + // fill headers + std::istream is(&context->response_buffer_); + string_type header; + while (std::getline(is, header) && (header != "\r")) { + auto delim = boost::find_first_of(header, ":"); + string_type key(std::begin(header), delim); + while (*++delim == ' ') { + } + string_type value(delim, std::end(header)); + res->add_header(key, value); + } + + // read the response body. + context->connection_->async_read( + context->response_buffer_, + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_read) { + read_response_body(ec, bytes_read, context, res); + })); + } + + namespace { + // I don't want to to delimit with newlines when using the input + // stream operator, so that's why I wrote this function. + std::istream &getline_with_newline(std::istream &is, + std::string &line) { + line.clear(); + + std::istream::sentry se(is, true); + std::streambuf *sb = is.rdbuf(); + + while (true) { + int c = sb->sbumpc(); + switch (c) { + case EOF: + if (line.empty()) { + is.setstate(std::ios::eofbit); + } + return is; + default: + line += static_cast(c); + } + } + } + } // namespace + + void client::impl::read_response_body( + const boost::system::error_code &ec, std::size_t bytes_read, + std::shared_ptr context, + std::shared_ptr res) { + if (timedout_) { + set_error(boost::asio::error::timed_out, context); + return; + } + + if (ec && ec != boost::asio::error::eof) { + set_error(ec, context); + return; + } + + // update progress. + context->total_bytes_read_ += bytes_read; + if (auto progress = context->options_.progress()) { + progress(client_message::transfer_direction::bytes_read, + context->total_bytes_read_); + } + + // If there's no data else to read, then set the response and exit. + if (bytes_read == 0) { + context->response_promise_.set_value(*res); + timer_.cancel(); + return; + } + + std::istream is(&context->response_buffer_); + string_type line; + line.reserve(bytes_read); + while (!getline_with_newline(is, line).eof()) { + res->append_body(std::move(line)); + } + + // Keep reading the response body until we have nothing else to read. + context->connection_->async_read( + context->response_buffer_, + strand_.wrap([=](const boost::system::error_code &ec, + std::size_t bytes_read) { + read_response_body(ec, bytes_read, context, res); + })); + } + + client::client(client_options options) : pimpl_(new impl(options)) {} + + client::client( + std::unique_ptr mock_resolver, + std::unique_ptr mock_connection, + client_options options) + : pimpl_(new impl(std::move(mock_resolver), + std::move(mock_connection), options)) {} + + client::~client() { } + + std::future client::execute(request req, + request_options options) { + std::shared_ptr connection; + if (pimpl_->mock_connection_) { + connection = pimpl_->mock_connection_; + } else { + // TODO factory based on HTTP or HTTPS + connection = std::make_shared( + pimpl_->io_service_); + } + return pimpl_->execute( + std::make_shared(connection, req, options)); + } + + std::future client::get(request req, request_options options) { + req.method(method::get); + return execute(req, options); + } + + std::future client::post(request req, request_options options) { + req.method(method::post); + return execute(req, options); + } + + std::future client::put(request req, request_options options) { + req.method(method::put); + return execute(req, options); + } + + std::future client::delete_(request req, + request_options options) { + req.method(method::delete_); + return execute(req, options); + } + + std::future client::head(request req, request_options options) { + req.method(method::head); + return execute(req, options); + } + + std::future client::options(request req, + request_options options) { + req.method(method::options); + return execute(req, options); + } + } // namespace v2 + } // namespace http +} // namespace network diff --git a/http/src/http/v2/client/client_errors.cpp b/http/src/http/v2/client/client_errors.cpp new file mode 100644 index 000000000..783453e3d --- /dev/null +++ b/http/src/http/v2/client/client_errors.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2013, 2014 by 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 + +namespace network { + namespace http { + inline namespace v2 { + class client_category_impl : public std::error_category { + + public: + client_category_impl() = default; + + virtual ~client_category_impl() noexcept override; + + virtual const char *name() const noexcept override; + + virtual std::string message(int ev) const override; + }; + + client_category_impl::~client_category_impl() noexcept {} + + const char *client_category_impl::name() const noexcept { + static const char name[] = "client_error"; + return name; + } + + std::string client_category_impl::message(int ev) const { + switch (client_error(ev)) { + + case client_error::invalid_request: + return "Invalid HTTP request."; + case client_error::invalid_response: + return "Invalid HTTP response."; + default: + break; + } + return "Unknown client error."; + } + + const std::error_category &client_category() { + static client_category_impl client_category; + return client_category; + } + + std::error_code make_error_code(client_error e) { + return std::error_code(static_cast(e), client_category()); + } + + invalid_url::invalid_url() + : std::invalid_argument("Requires HTTP or HTTPS URL.") {} + + invalid_url::~invalid_url() noexcept {} + + client_exception::client_exception(client_error error) + : std::system_error(make_error_code(error)) {} + + client_exception::~client_exception() noexcept {} + } // namespace v2 + } // namespace http +} // namespace network diff --git a/http/src/network/constants.hpp b/http/src/network/constants.hpp new file mode 100644 index 000000000..bf969c1d6 --- /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..e552ae818 --- /dev/null +++ b/http/src/network/constants.ipp @@ -0,0 +1,152 @@ +#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..c88ea94a5 --- /dev/null +++ b/http/src/network/http/client.hpp @@ -0,0 +1,31 @@ +// Copyright (c) Glyn Matthews 2012, 2013. +// 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 + +namespace network { + namespace http { + using v2::client; + using v2::client_options; + using v2::request; + using v2::request_options; + using v2::response; + using v2::method; + namespace status = v2::status; + using v2::client_error; + using v2::invalid_url; + using v2::client_exception; + } // namespace http +} // namespace network + + +#endif // NETWORK_HTTP_CLIENT_INC diff --git a/http/src/network/http/v2/client.hpp b/http/src/network/http/v2/client.hpp new file mode 100644 index 000000000..6148b9c04 --- /dev/null +++ b/http/src/network/http/v2/client.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_INC +#define NETWORK_HTTP_V2_CLIENT_INC + +/** + * \defgroup http_client HTTP Client + */ + +#include + +#endif // NETWORK_HTTP_V2_CLIENT_INC diff --git a/http/src/network/http/v2/client/client.hpp b/http/src/network/http/v2/client/client.hpp new file mode 100644 index 000000000..e69a9491a --- /dev/null +++ b/http/src/network/http/v2/client/client.hpp @@ -0,0 +1,364 @@ +// Copyright (C) 2013, 2014 by Glyn Matthews +// 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) + +/** + * \file + * \brief An HTTP client and configuration options. + */ + +#ifndef NETWORK_HTTP_V2_CLIENT_CLIENT_INC +#define NETWORK_HTTP_V2_CLIENT_CLIENT_INC + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +namespace client_connection { +class async_resolver; +class async_connection; +} // namespace client_connection + +/** + * \ingroup http_client + * \class client_options network/http/v2/client/client.hpp network/http/v2/client.hpp + * \brief A set of options to configure an HTTP client. + */ +class client_options { + +public: + + /** + * \brief Constructor. + */ + client_options() + : follow_redirects_(false) + , cache_resolved_(false) + , use_proxy_(false) + , always_verify_peer_(false) + , user_agent_(std::string("cpp-netlib/") + NETLIB_VERSION) + , timeout_(30000) { } + + /** + * \brief Copy constructor. + */ + client_options(const client_options &other) = default; + + /** + * \brief Move constructor. + */ + client_options(client_options &&other) = default; + + /** + * \brief Assignment operator. + */ + client_options &operator = (client_options other) { + other.swap(*this); + return *this; + } + + /** + * \brief Destructor. + */ + ~client_options() = default; + + /** + * \brief Swap. + */ + void swap(client_options &other) noexcept { + using std::swap; + swap(follow_redirects_, other.follow_redirects_); + swap(cache_resolved_, other.cache_resolved_); + swap(use_proxy_, other.use_proxy_); + swap(always_verify_peer_, other.always_verify_peer_); + swap(user_agent_, other.user_agent_); + swap(timeout_, other.timeout_); + swap(openssl_certificate_paths_, other.openssl_certificate_paths_); + swap(openssl_verify_paths_, other.openssl_verify_paths_); + } + + /** + * \brief Tells the client to follow redirects. + * \param follow_redirects If \c true, then the client must + * follow redirects, if \c false it doesn't. + * \returns \c *this + */ + client_options &follow_redirects(bool follow_redirects) { + follow_redirects_ = follow_redirects; + return *this; + } + + /** + * \brief Tests if the client follows redirects. + * \returns \c true if the client follows redirects, \c false + * otherwise. + */ + bool follow_redirects() const { + return follow_redirects_; + } + + /** + * \brief Tells the client to cache resolved connections. + * \param cache_resolved If \c true, then the client must + * cache resolved connections, if \c false it + * doesn't. + * \returns \c *this + */ + client_options &cache_resolved(bool cache_resolved) { + cache_resolved_ = cache_resolved; + return *this; + } + + /** + * \brief Tests if the client caches resolved connections. + * \returns \c true if the client caches resolved connections, + * \c false otherwise. + */ + bool cache_resolved() const { + return cache_resolved_; + } + + /** + * \brief Tells the client to use a proxy. + * \param use_proxy If \c true, then the client must use a + * proxy, if \c false it doesn't. + * \returns \c *this + */ + client_options &use_proxy(bool use_proxy) { + use_proxy_ = use_proxy; + return *this; + } + + /** + * \brief Tests if the client uses a proxy. + * \returns \c true if the client uses a proxy, \c false + * otherwise. + */ + bool use_proxy() const { + return use_proxy_; + } + + /** + * \brief Sets the client timeout in milliseconds. + * \param timeout The timeout value in milliseconds. + * \returns \c *this + */ + client_options &timeout(std::chrono::milliseconds timeout) { + timeout_ = timeout; + return *this; + } + + /** + * \brief Gets the current timeout value. + * \returns The timeout value in milliseconds. + */ + std::chrono::milliseconds timeout() const { + return timeout_; + } + + /** + * \brief Adds an OpenSSL certificate path. + * \param path The certificate path. + * \returns \c *this + */ + client_options &openssl_certificate_path(std::string path) { + openssl_certificate_paths_.emplace_back(std::move(path)); + return *this; + } + + /** + * \brief Returns a list of OpenSSL certificate paths. + * \returns A list of OpenSSL certificate paths. + */ + std::vector openssl_certificate_paths() const { + return openssl_certificate_paths_; + } + + /** + * \brief Adds an OpenSSL verify path. + * \param path The verify path. + * \returns \c *this + */ + client_options &openssl_verify_path(std::string path) { + openssl_verify_paths_.emplace_back(std::move(path)); + return *this; + } + + /** + * \brief Returns a list of OpenSSL verify paths. + * \returns A list of OpenSSL verify paths. + */ + std::vector openssl_verify_paths() const { + return openssl_verify_paths_; + } + + /** + * \brief + * \returns \c *this + */ + client_options &always_verify_peer(bool always_verify_peer) { + always_verify_peer_ = always_verify_peer; + return *this; + } + + /** + * \brief + * \returns + */ + bool always_verify_peer() const { + return always_verify_peer_; + } + + /** + * \brief + * \returns \c *this + */ + client_options &user_agent(const std::string &user_agent) { + user_agent_ = user_agent; + return *this; + } + + /** + * \brief + * \returns + */ + std::string user_agent() const { + return user_agent_; + } + +private: + + bool follow_redirects_; + bool cache_resolved_; + bool use_proxy_; + bool always_verify_peer_; + std::string user_agent_; + std::chrono::milliseconds timeout_; + std::vector openssl_certificate_paths_; + std::vector openssl_verify_paths_; + +}; + +/** + * \brief + * \param lhs + * \param rhs + */ +inline +void swap(client_options &lhs, client_options &rhs) noexcept { + lhs.swap(rhs); +} + +typedef client_message::request_options request_options; +typedef client_message::request request; +typedef client_message::response response; + +/** + * \ingroup http_client + * \class client network/http/v2/client/client.hpp network/http/v2/client.hpp + * \brief A class that encapsulates the operations and methods + * for communicating with an HTTP server. + */ +class client { + + client(const client&) = delete; + client& operator=(const client&) = delete; + +public: + + /** + * \typedef string_type + * \brief The client string_type. + */ + typedef request::string_type string_type; + + /** + * \brief Constructor. + * \param options Client options. + */ + explicit client(client_options options = client_options()); + + client(std::unique_ptr mock_resolver, + std::unique_ptr mock_connection, + client_options options = client_options()); + + /** + * \brief Destructor. + */ + ~client(); + + /** + * \brief Executes an HTTP request. + * \param req The request object. + * \param options The request options. + */ + std::future execute(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP GET request. + * \param req The request object. + * \param options The request options. + */ + std::future get(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP POST request. + * \param req The request object. + * \param options The request options. + */ + std::future post(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP PUT request. + * \param req The request object. + * \param options The request options. + */ + std::future put(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP DELETE request. + * \param req The request object. + * \param options The request options. + */ + std::future delete_(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP HEAD request. + * \param req The request object. + * \param options The request options. + */ + std::future head(request req, request_options options = request_options()); + + /** + * \brief Executes an HTTP OPTIONS request. + * \param req The request object. + * \param options The request options. + */ + std::future options(request req, request_options options = request_options()); + +private: + + struct impl; + std::unique_ptr pimpl_; + +}; +} // namespace v2 +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CLIENT_INC diff --git a/http/src/network/http/v2/client/client_errors.hpp b/http/src/network/http/v2/client/client_errors.hpp new file mode 100644 index 000000000..72a9a88cc --- /dev/null +++ b/http/src/network/http/v2/client/client_errors.hpp @@ -0,0 +1,91 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_CLIENT_ERRORS_INC +#define NETWORK_HTTP_V2_CLIENT_CLIENT_ERRORS_INC + +/** + * \file + * \brief Contains a set of error classes and exceptions for HTTP + * clients. + */ + +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +/** + * \ingroup http_client + * \enum client_error network/http/v2/client/client_errors.hpp network/http/v2/client.hpp + * \brief An enumeration of all types of client error. + */ +enum class client_error { + // request + invalid_request, + + // response + invalid_response, +}; + +/** + * \brief Gets the error category for HTTP client errors. + */ +const std::error_category &client_category(); + +/** + * \brief Makes an error code object from a client_error enum. + */ +std::error_code make_error_code(client_error e); + +/** + * \ingroup http_client + * \class invalid_url network/http/v2/client/client_errors.hpp network/http/v2/client.hpp + * \brief An exception thrown if the URL provides is invalid. + */ +class invalid_url : public std::invalid_argument { + +public: + + /** + * \brief Constructor. + */ + explicit invalid_url(); + + /** + * \brief Destructor. + */ + virtual ~invalid_url() noexcept; + +}; + +/** + * \ingroup http_client + * \class client_exception network/http/v2/client/client_errors.hpp network/http/v2/client.hpp + * \brief An exception thrown when there is a client error. + */ +class client_exception : public std::system_error { + +public: + + /** + * \brief Constructor. + */ + explicit client_exception(client_error error); + + /** + * \brief Destructor. + */ + virtual ~client_exception() noexcept; + +}; + +} // namespace v2 +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CLIENT_ERRORS_INC diff --git a/http/src/network/http/v2/client/connection/async_connection.hpp b/http/src/network/http/v2/client/connection/async_connection.hpp new file mode 100644 index 000000000..60f97a256 --- /dev/null +++ b/http/src/network/http/v2/client/connection/async_connection.hpp @@ -0,0 +1,113 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_CONNECTION_ASYNC_CONNECTION_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_ASYNC_CONNECTION_INC + +/** + * \file + * \brief + */ + +#include +#include +#include +#include +#include +#include + +namespace network { + namespace http { + inline namespace v2 { + namespace client_connection { + /** + * \class async_connection network/http/v2/client/connection/async_connection.hpp + * \brief Manages a connection through a socket. + */ + class async_connection { + + async_connection(const async_connection &) = delete; + async_connection &operator = (const async_connection &) = delete; + + public: + + /** + * \typedef connect_callback + */ + typedef std::function connect_callback; + + /** + * \typedef write_callback + */ + typedef std::function write_callback; + + /** + * \typedef read_callback + */ + typedef std::function read_callback; + + /** + * \brief Constructor. + */ + async_connection() = default; + + /** + * \brief Destructor. + */ + virtual ~async_connection() noexcept { } + + /** + * \brief Asynchronously creates a connection to an endpoint. + * \param endpoint The endpoint to which to connect. + * \param callback A callback handler. + */ + virtual void async_connect(const boost::asio::ip::tcp::endpoint &endpoint, + const std::string &host, + connect_callback callback) = 0; + + /** + * \brief Asynchronously writes data across the connection. + * \param command_streambuf + * \param callback A callback handler. + */ + virtual void async_write(boost::asio::streambuf &command_streambuf, + write_callback callback) = 0; + + /** + * \brief Asynchronously reads some data from the connection. + * \param command_streambuf + * \param delim A delimiter string which, if found, the socket + * will stop reading. + * \param callback A callback handler. + */ + virtual void async_read_until(boost::asio::streambuf &command_streambuf, + const std::string &delim, + read_callback callback) = 0; + + /** + * \brief Asynchronously reads some data from the connection. + * \param command_streambuf + * \param callback A callback handler. + */ + virtual void async_read(boost::asio::streambuf &command_streambuf, + read_callback callback) = 0; + + /** + * \brief Breaks the connection. + */ + virtual void disconnect() = 0; + + /** + * \brief Cancels an operation on a connection. + */ + virtual void cancel() = 0; + + }; + } // namespace client_connection + } // namespace v2 + } // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_ASYNC_CONNECTION_INC diff --git a/http/src/network/http/v2/client/connection/async_resolver.hpp b/http/src/network/http/v2/client/connection/async_resolver.hpp new file mode 100644 index 000000000..f88cd9fbc --- /dev/null +++ b/http/src/network/http/v2/client/connection/async_resolver.hpp @@ -0,0 +1,84 @@ +// Copyright (C) 2013 by Glyn Matthews +// 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_HTTP_V2_CLIENT_CONNECTION_ASYNC_RESOLVER_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_ASYNC_RESOLVER_INC + +/** + * \file + * \brief + */ + +#include +#include + +namespace network { + namespace http { + inline namespace v2 { + namespace client_connection { + /** + * \class async_resolver network/http/v2/client/connection/async_resolver.hpp + * \brief Resolves and maintains a cache of hosts. + */ + class async_resolver { + + async_resolver(const async_resolver &) = delete; + async_resolver &operator = (const async_resolver &) = delete; + + public: + + /** + * \brief resolver + */ + typedef boost::asio::ip::tcp::resolver resolver; + + /** + * \brief resolver_iterator + */ + typedef resolver::iterator resolver_iterator; + + /** + * \typedef resolve_callback + */ + typedef std::function resolve_callback; + + /** + * \brief Constructor. + */ + async_resolver() { + + } + + /** + * \brief Destructor. + */ + virtual ~async_resolver() noexcept { + + } + + /** + * \brief Resolves a host asynchronously. + * \param host The hostname to resolve. + * \param port The port number. + * \param callback A callback handler. + */ + virtual void async_resolve(const std::string &host, std::uint16_t port, + resolve_callback handler) = 0; + + /** + * \brief Clears the cache of already resolved endpoints. + */ + virtual void clear_resolved_cache() = 0; + + }; + } // namespace client_connection + } // namespace v2 + } // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_ASYNC_RESOLVER_INC diff --git a/http/src/network/http/v2/client/connection/endpoint_cache.hpp b/http/src/network/http/v2/client/connection/endpoint_cache.hpp new file mode 100644 index 000000000..b3cf13015 --- /dev/null +++ b/http/src/network/http/v2/client/connection/endpoint_cache.hpp @@ -0,0 +1,100 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_CONNECTION_ENDPOINT_CACHE_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_ENDPOINT_CACHE_INC + +/** + * \file + * \brief + */ + +#include +#include +#include +#include + +namespace network { + namespace http { + inline namespace v2 { + namespace client_connection { + + /** + * \class endpoint_cache network/http/v2/client/connection/endpoint_cache.hpp + * \brief + */ + class endpoint_cache { + + /** + * \brief + */ + typedef boost::asio::ip::tcp::resolver resolver; + + typedef resolver::iterator resolver_iterator; + + typedef std::unordered_map cache_type; + + public: + + /** + * \brief + */ + typedef cache_type::iterator iterator; + + /** + * \brief + */ + cache_type::iterator begin() { + return endpoints_.begin(); + } + + /** + * \brief + */ + cache_type::iterator end() { + return endpoints_.end(); + } + + /** + * \brief + */ + void insert(const std::string &host, + resolver_iterator endpoint_iterator) { + endpoints_.insert(std::make_pair(host, endpoint_iterator)); + } + + /** + * \brief + */ + iterator find(const std::string &host) { + return endpoints_.find(boost::to_lower_copy(host)); + } + + /** + * \brief + */ + void clear() { + endpoint_cache().swap(*this); + } + + /** + * \brief + */ + void swap(endpoint_cache &other) noexcept { + endpoints_.swap(other.endpoints_); + } + + private: + + cache_type endpoints_; + + }; + } // namespace client_connection + } // namespace v2 + } // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_ENDPOINT_CACHE_INC diff --git a/http/src/network/http/v2/client/connection/normal_connection.hpp b/http/src/network/http/v2/client/connection/normal_connection.hpp new file mode 100644 index 000000000..4b2cce67b --- /dev/null +++ b/http/src/network/http/v2/client/connection/normal_connection.hpp @@ -0,0 +1,103 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_CONNECTION_NORMAL_CONNECTION_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_NORMAL_CONNECTION_INC + +/** + * \file + * \brief + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace network { + namespace http { + inline namespace v2 { + namespace client_connection { + + /** + * \class + * \brief + */ + class normal_connection : public async_connection { + + normal_connection(const normal_connection &) = delete; + normal_connection &operator = (const normal_connection &) = delete; + + public: + + /** + * \brief + */ + explicit normal_connection(boost::asio::io_service &io_service) + : io_service_(io_service) { + + } + + /** + * \brief Destructor. + */ + virtual ~normal_connection() noexcept { + + } + + virtual void async_connect(const boost::asio::ip::tcp::endpoint &endpoint, + const std::string &host, + connect_callback callback) { + using boost::asio::ip::tcp; + socket_.reset(new tcp::socket{io_service_}); + socket_->async_connect(endpoint, callback); + } + + virtual void async_write(boost::asio::streambuf &command_streambuf, + write_callback callback) { + boost::asio::async_write(*socket_, command_streambuf, callback); + } + + virtual void async_read_until(boost::asio::streambuf &command_streambuf, + const std::string &delim, + read_callback callback) { + boost::asio::async_read_until(*socket_, command_streambuf, delim, callback); + } + + virtual void async_read(boost::asio::streambuf &command_streambuf, + read_callback callback) { + boost::asio::async_read(*socket_, command_streambuf, + boost::asio::transfer_at_least(1), callback); + } + + virtual void disconnect() { + if (socket_ && socket_->is_open()) { + boost::system::error_code ec; + socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + if (!ec) { + socket_->close(ec); + } + } + } + + virtual void cancel() { + socket_->cancel(); + } + + private: + + boost::asio::io_service &io_service_; + std::unique_ptr socket_; + + }; + } // namespace client_connection + } // namespace v2 + } // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_NORMAL_CONNECTION_INC diff --git a/http/src/network/http/v2/client/connection/ssl_connection.hpp b/http/src/network/http/v2/client/connection/ssl_connection.hpp new file mode 100644 index 000000000..92bd9983f --- /dev/null +++ b/http/src/network/http/v2/client/connection/ssl_connection.hpp @@ -0,0 +1,148 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_CLIENT_CONNECTION_SSL_CONNECTION_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_SSL_CONNECTION_INC + +/** + * \file + * \brief + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { + namespace http { + inline namespace v2 { + namespace client_connection { + /** + * \class + * \brief + */ + class ssl_connection : public async_connection { + + ssl_connection(const ssl_connection &) = delete; + ssl_connection &operator = (const ssl_connection &) = delete; + + public: + + /** + * \brief + */ + ssl_connection(boost::asio::io_service &io_service, const client_options &options) + : io_service_(io_service) + , options_(options) { + + } + + /** + * \brief Destructor. + */ + virtual ~ssl_connection() noexcept { + + } + + virtual void async_connect(const boost::asio::ip::tcp::endpoint &endpoint, + const std::string &host, + connect_callback callback) { + context_.reset(new boost::asio::ssl::context(boost::asio::ssl::context::sslv23)); + auto certificate_paths = options_.openssl_certificate_paths(); + auto verifier_paths = options_.openssl_verify_paths(); + bool use_default_verification = certificate_paths.empty() && verifier_paths.empty(); + if (!use_default_verification) { + for (auto path : certificate_paths) { + context_->load_verify_file(path); + } + for (auto path : verifier_paths) { + context_->add_verify_path(path); + } + context_->set_verify_mode(boost::asio::ssl::context::verify_peer); + context_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); + } + else { + context_->set_default_verify_paths(); + context_->set_verify_mode(boost::asio::ssl::context::verify_none); + } + socket_.reset(new boost::asio::ssl::stream< + boost::asio::ip::tcp::socket>(io_service_, *context_)); + + using namespace std::placeholders; + socket_->lowest_layer().async_connect(endpoint, + [=] (const boost::system::error_code &ec) { + handle_connected(ec, callback); + }); + } + + virtual void async_write(boost::asio::streambuf &command_streambuf, + write_callback callback) { + boost::asio::async_write(*socket_, command_streambuf, callback); + } + + virtual void async_read_until(boost::asio::streambuf &command_streambuf, + const std::string &delim, + read_callback callback) { + boost::asio::async_read_until(*socket_, command_streambuf, delim, callback); + } + + virtual void async_read(boost::asio::streambuf &command_streambuf, + read_callback callback) { + boost::asio::async_read(*socket_, command_streambuf, + boost::asio::transfer_at_least(1), callback); + } + + virtual void disconnect() { + if (socket_ && socket_->lowest_layer().is_open()) { + boost::system::error_code ec; + socket_->lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + if (!ec) { + socket_->lowest_layer().close(ec); + } + } + } + + virtual void cancel() { + socket_->lowest_layer().cancel(); + } + + private: + + void handle_connected(const boost::system::error_code &ec, connect_callback callback) { + if (!ec) { + auto existing_session = SSL_get1_session(socket_->native_handle()); + if (existing_session) { + socket_->async_handshake(boost::asio::ssl::stream_base::client, callback); + } + else { + SSL_set_session(socket_->native_handle(), existing_session); + SSL_connect(socket_->native_handle()); + callback(ec); + } + } + else { + callback(ec); + } + } + + boost::asio::io_service &io_service_; + client_options options_; + std::unique_ptr context_; + std::unique_ptr< + boost::asio::ssl::stream> socket_; + + }; + } // namespace client_connection + } // namespace v2 + } // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_SSL_CONNECTION_INC diff --git a/http/src/network/http/v2/client/connection/tcp_resolver.hpp b/http/src/network/http/v2/client/connection/tcp_resolver.hpp new file mode 100644 index 000000000..8092c6eeb --- /dev/null +++ b/http/src/network/http/v2/client/connection/tcp_resolver.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2013 by Glyn Matthews +// 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_HTTP_V2_CLIENT_CONNECTION_TCP_RESOLVER_INC +#define NETWORK_HTTP_V2_CLIENT_CONNECTION_TCP_RESOLVER_INC + +/** + * \file + * \brief + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +namespace client_connection { +/** + * \class tcp_resolver network/http/v2/client/connection/tcp_resolver.hpp + * \brief Resolves and maintains a cache of hosts. + */ +class tcp_resolver : public async_resolver { + + tcp_resolver(const tcp_resolver &) = delete; + tcp_resolver &operator = (const tcp_resolver &) = delete; + +public: + + using async_resolver::resolver; + using async_resolver::resolver_iterator; + using async_resolver::resolve_callback; + + /** + * \brief Constructor. + */ + tcp_resolver(boost::asio::io_service &service, bool cache_resolved = false) + : resolver_(service) + , cache_resolved_(cache_resolved) { + + } + + /** + * \brief Destructor. + */ + virtual ~tcp_resolver() noexcept { + + } + + virtual void async_resolve(const std::string &host, std::uint16_t port, + resolve_callback handler) { + if (cache_resolved_) { + auto it = endpoint_cache_.find(host); + if (it != endpoint_cache_.end()) { + boost::system::error_code ec; + handler(ec, it->second); + return; + } + } + + resolver::query query(host, std::to_string(port)); + resolver_.async_resolve(query, + [host, handler, this](const boost::system::error_code &ec, + resolver_iterator endpoint_iterator) { + if (ec) { + handler(ec, resolver_iterator()); + } + else { + if (cache_resolved_) { + endpoint_cache_.insert(host, endpoint_iterator); + } + handler(ec, endpoint_iterator); + } + }); + } + + virtual void clear_resolved_cache() { + endpoint_cache_.clear(); + } + +private: + + resolver resolver_; + bool cache_resolved_; + endpoint_cache endpoint_cache_; + +}; +} // namespace client_connection +} // namespace v2 +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_CONNECTION_TCP_RESOLVER_INC diff --git a/http/src/network/http/v2/client/request.hpp b/http/src/network/http/v2/client/request.hpp new file mode 100644 index 000000000..f82ab528a --- /dev/null +++ b/http/src/network/http/v2/client/request.hpp @@ -0,0 +1,579 @@ +// Copyright (C) 2013 by Glyn Matthews +// 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_HTTP_V2_CLIENT_REQUEST_INC +#define NETWORK_HTTP_V2_CLIENT_REQUEST_INC + +/** + * \file + * \brief Contains classes for handling creating and handling HTTP + * requests. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +namespace client_message { +enum class transfer_direction { + bytes_written, bytes_read, +}; + +/** + * \ingroup http_client + * \class request_options network/http/v2/client/request.hpp network/http/v2/client.hpp + * \brief A class used to configure an HTTP request. + */ +class request_options { + +public: + + /** + * \brief Constructor. + */ + request_options() + : resolve_timeout_(30000) + , read_timeout_(30000) + , total_timeout_(30000) + , max_redirects_(10) { } + + /** + * \brief Copy constructor. + */ + request_options(request_options const &other) = default; + + /** + * \brief Move constructor. + */ + request_options(request_options &&other) = default; + + /** + * \brief Assignment operator. + */ + request_options &operator = (request_options other) { + other.swap(*this); + return *this; + } + + /** + * \brief Destructor. + */ + ~request_options() = default; + + /** + * \brief + * \param other + */ + void swap(request_options &other) noexcept { + using std::swap; + swap(resolve_timeout_, other.resolve_timeout_); + swap(read_timeout_, other.read_timeout_); + swap(total_timeout_, other.total_timeout_); + } + + /** + * \brief + * \returns + */ + request_options &resolve_timeout(std::uint64_t resolve_timeout) { + resolve_timeout_ = resolve_timeout; + return *this; + } + + /** + * \brief + * \returns + */ + std::uint64_t resolve_timeout() const { + return resolve_timeout_; + } + + /** + * \brief + * \returns + */ + request_options &read_timeout(std::uint64_t read_timeout) { + read_timeout_ = read_timeout; + return *this; + } + + /** + * \brief + * \returns + */ + std::uint64_t read_timeout() const { + return read_timeout_; + } + + /** + * \brief + * \returns + */ + request_options &total_timeout(std::uint64_t total_timeout) { + total_timeout_ = total_timeout; + return *this; + } + + /** + * \brief + * \returns + */ + std::uint64_t total_timeout() const { + return total_timeout_; + } + + /** + * \brief + * \returns + */ + request_options &max_redirects(int max_redirects) { + max_redirects_ = max_redirects; + return *this; + } + + /** + * \brief + * \returns + */ + int max_redirects() const { + return max_redirects_; + } + + /** + * \brief + * \returns + */ + request_options &progress(std::function handler) { + progress_handler_ = handler; + return *this; + } + + /** + * \brief + * \returns + */ + std::function progress() const { + return progress_handler_; + } + +private: + + std::uint64_t resolve_timeout_; + std::uint64_t read_timeout_; + std::uint64_t total_timeout_; + int max_redirects_; + std::function progress_handler_; + +}; + +/** + * \brief + * \param lhs + * \param rhs + */ +inline +void swap(request_options &lhs, request_options &rhs) noexcept { + lhs.swap(rhs); +} + +/** + * \ingroup http_client + * \class byte_source network/http/v2/client/request.hpp network/http/v2/client.hpp + * \brief An abstract class that allows a request object to read + * data from any source. + */ +class byte_source { + +public: + + /** + * \typedef string_type + * \brief The byte_source string type. + */ + typedef std::string string_type; + + /** + * \typedef size_type + * \brief The byte_source size type. + */ + typedef std::size_t size_type; + + /** + * \brief Destructor. + */ + virtual ~byte_source() {} + + /** + * \brief Allows the request to read the data into a local + * copy of its source string. + */ + virtual size_type read(string_type &source, size_type length) = 0; + +}; + +/** + * \ingroup http_client + * \class string_byte_source network/http/v2/client/request.hpp network/http/v2/client.hpp + * \brief A class that wraps a string as a byte source. + */ +class string_byte_source : public byte_source { + +public: + + /** + * \brief Constructor. + */ + explicit string_byte_source(string_type source); + + /** + * \brief Destructor. + */ + virtual ~string_byte_source() {} + + virtual size_type read(string_type &source, size_type length); + +private: + + string_type source_; + +}; + +/** + * \ingroup http_client + * \class request network/http/v2/client/request.hpp network/http/v2/client.hpp + * \brief A class that models an HTTP request. + */ +class request { + +public: + + /** + * \typedef string_type + * \brief The request string type. + */ + typedef byte_source::string_type string_type; + + /** + * \typedef size_type + * \brief The request size type. + */ + typedef byte_source::size_type size_type; + + /** + * \typedef headers_type + * \brief The request headers type. + */ + typedef std::vector> headers_type; + + /** + * \typedef headers_iterator + * \brief The request headers iterator. + */ + typedef headers_type::iterator headers_iterator; + + /** + * \typedef const_headers_iterator + * \brief The request headers const_iterator. + */ + typedef headers_type::const_iterator const_headers_iterator; + + /** + * \brief Constructor. + */ + request() = default; + + /** + * \brief Constructor. + */ + explicit request(uri url) { + this->https://github.com/url(url); + } + + /** + * \brief Copy constructor. + */ + request(const request &other) = default; + + /** + * \brief Move constructor. + */ + request(request &&other) noexcept = default; + + /** + * \brief Destructor. + */ + ~request() = default; + + /** + * \brief Swaps one request object with another. + * \param other The other request object. + */ + void swap(request &other) noexcept { + using std::swap; + swap(url_, other.url_); + swap(method_, other.method_); + swap(path_, other.path_); + swap(version_, other.version_); + swap(headers_, other.headers_); + swap(byte_source_, other.byte_source_); + } + + /** + * \brief + * \returns + */ + request &url(https://github.com/const%20uri%20&url) { + if (auto scheme = url.scheme()) { + if ((!boost::equal(*scheme, boost::as_literal("http"))) && + (!boost::equal(*scheme, boost::as_literal("https")))) { + throw invalid_url(); + } + + if (auto path = url.path()) { + std::copy(std::begin(*path), std::end(*path), + std::back_inserter(path_)); + } + + if (auto query = url.query()) { + path_.push_back('?'); + std::copy(std::begin(*query), std::end(*query), + std::back_inserter(path_)); + } + + if (auto fragment = url.fragment()) { + path_.push_back('#'); + std::copy(std::begin(*fragment), std::end(*fragment), + std::back_inserter(path_)); + } + + std::ostringstream oss; + std::copy(std::begin(*url.host()), std::end(*url.host()), + std::ostream_iterator(oss)); + if (url.port()) { + oss << ":"; + std::copy(std::begin(*url.port()), std::end(*url.port()), + std::ostream_iterator(oss)); + } + append_header("Host", oss.str()); + } + else { + throw invalid_url(); + } + url_ = url; + return *this; + } + + /** + * \brief + * \returns + */ + uri url() const { + return url_; + } + + /** + * \brief Checks whether this is an HTTPS request. + * \returns \c true if it is HTTPS, \c false otherwise. + */ + bool is_https() const { + return url_.scheme() && boost::equal(*url_.scheme(), boost::as_literal("https")); + } + + /** + * \brief Sets the HTTP request method. + * \param method The HTTP request method. + * \returns *this + */ + request &method(network::http::v2::method method) { + method_ = method; + return *this; + } + + /** + * \brief Gets the HTTP request method. + * \returns The HTTP request method. + */ + network::http::v2::method method() const { + return method_; + } + + /** + * \brief Sets the HTTP path. + * \param path The HTTP path. + * \returns *this + */ + request &path(string_type path) { + path_ = path; + return *this; + } + + /** + * \brief Gets the HTTP path. + * \returns The HTTP path. + */ + string_type path() const { + return path_; + } + + /** + * \brief Sets the HTTP request version. + * \param version 1.0 or 1.1. + */ + request &version(string_type version) { + version_ = std::move(version); + return *this; + } + + /** + * \brief Gets the HTTP request version. + * \returns The HTTP request version. + */ + string_type version() const { + return version_; + } + + /** + * \brief + * \returns + */ + request &body(std::shared_ptr byte_source) { + byte_source_ = byte_source; + return *this; + } + + /** + * \brief + * \returns + */ + template + void body(size_type length, Handler &&handler) { + string_type body; + byte_source_->read(body, length); + handler(body); + } + + /** + * \brief Appends a header to the request. + * \param name The header name. + * \param value The header value. + * + * Duplicates are allowed. + */ + request &append_header(string_type name, string_type value) { + headers_.emplace_back(name, value); + return *this; + } + + /** + * \brief + * \returns + */ + boost::optional header(const string_type &name) { + for (auto header : headers_) { + if (boost::iequals(header.first, name)) { + return header.second; + } + } + return boost::optional(); + } + + /** + * \brief + * \returns + */ + const_headers_iterator headers_begin() const { + return std::begin(headers_); + } + + /** + * \brief + * \returns + */ + const_headers_iterator headers_end() const { + return std::end(headers_); + } + + /** + * \brief Returns the headers range. + * \returns An iterator range covering all headers. + */ + boost::iterator_range headers() const { + return boost::make_iterator_range(headers_begin(), headers_end()); + } + + /** + * \brief Removes a header from the request. + * \param name The name of the header to be removed. + * + * If the header name can not be found, nothing happens. If + * the header is duplicated, then both entries are removed. + */ + void remove_header(const string_type &name) { + auto it = std::remove_if(std::begin(headers_), std::end(headers_), + [&name] (const std::pair &header) { + return boost::iequals(header.first, name); + }); + headers_.erase(it, std::end(headers_)); + } + + /** + * \brief Clears all HTTP request headers. + */ + void clear_headers() { + headers_type().swap(headers_); + } + +private: + + network::uri url_; + network::http::v2::method method_; + string_type path_; + string_type version_; + headers_type headers_; + std::shared_ptr byte_source_; + + friend std::ostream &operator << (std::ostream &os, const request &req) { + os << req.method_ << " " << req.path_ << " HTTP/" << req.version_ << "\r\n"; + for (auto header : req.headers_) { + os << header.first << ": " << header.second << "\r\n"; + } + return os << "\r\n"; + } +}; + +/** + * \brief + * \returns + */ +inline +void swap(request &lhs, request &rhs) noexcept { + lhs.swap(rhs); +} +} // namespace client_message +} // namespace v2 +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_REQUEST_INC diff --git a/http/src/network/http/v2/client/response.hpp b/http/src/network/http/v2/client/response.hpp new file mode 100644 index 000000000..21cf37c0c --- /dev/null +++ b/http/src/network/http/v2/client/response.hpp @@ -0,0 +1,210 @@ +// Copyright (C) 2013 by Glyn Matthews +// 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_HTTP_V2_CLIENT_RESPONSE_INC +#define NETWORK_HTTP_V2_CLIENT_RESPONSE_INC + +/** + * \file + * \brief Defines the HTTP response. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +namespace client_message { +/** + * \ingroup http_client + * \class response network/http/v2/client/response.hpp + * \brief A class that encapsulates an HTTP response. + */ +class response { + +public: + + /** + * \typedef string_type + * \brief The response string_type. + */ + typedef std::string string_type; + + /** + * \typedef headers_type + * \brief The response headers type. + */ + typedef std::vector> headers_type; + + /** + * \typedef headers_iterator + * \brief The response headers iterator. + */ + typedef headers_type::iterator headers_iterator; + + /** + * \typedef const_headers_iterator + * \brief The response headers const_iterator. + */ + typedef headers_type::const_iterator const_headers_iterator; + + /** + * \brief Constructor. + */ + response() = default; + + /** + * \brief Copy constructor. + * \param other The other response object. + */ + response(const response &other) = default; + + /** + * \brief Move constructor. + * \param other The other response object. + */ + response(response &&other) noexcept = default; + + /** + * \brief Swap function. + * \param other The other response object. + */ + void swap(response &other) noexcept { + using std::swap; + swap(version_, other.version_); + swap(status_, other.status_); + swap(status_message_, other.status_message_); + swap(headers_, other.headers_); + swap(body_, other.body_); + } + + /** + * \brief Sets the HTTP version. + * \param version The HTTP version (1.0 or 1.1). + */ + void set_version(string_type version) { + version_ = version; + } + + /** + * \brief Returns the HTTP version. + * \returns The HTTP version. + */ + string_type version() const { + return version_; + } + + /** + * \brief Sets the HTTP response status code. + * \param status The HTTP response status code. + */ + void set_status(network::http::v2::status::code status) { + status_ = status; + } + + /** + * \brief Returns the HTTP response status. + * \returns The status code. + */ + network::http::v2::status::code status() const { + return status_; + } + + /** + * \brief Sets the HTTP response status message. + * \param status The HTTP response status message. + */ + void set_status_message(string_type status_message) { + status_message_ = status_message; + } + + /** + * \brief Returns the HTTP response status message. + * \returns The status message. + */ + string_type status_message() const { + return status_message_; + } + + /** + * \brief Adds a header to the HTTP response. + * \param name The header name. + * \param value The header value. + */ + void add_header(string_type name, string_type value) { + headers_.emplace_back(name, value); + } + + /** + * \brief + * \returns + */ + const_headers_iterator headers_begin() const { + return std::begin(headers_); + } + + /** + * \brief + * \returns + */ + const_headers_iterator headers_end() const { + return std::end(headers_); + } + + /** + * \brief Returns the full range of headers. + * \returns An iterator range covering the HTTP response + * headers. + */ + boost::iterator_range headers() const { + return boost::make_iterator_range(headers_begin(), headers_end()); + } + + /** + * \brief + * \param body + */ + void append_body(string_type body) { + body_.append(body); + } + + /** + * \brief + * \returns + */ + string_type body() const { + return body_; + } + +private: + + string_type version_; + network::http::v2::status::code status_; + string_type status_message_; + headers_type headers_; + string_type body_; + +}; + +inline +void swap(response &lhs, response &rhs) noexcept { + lhs.swap(rhs); +} +} // namespace client_message +} // namespace v2 +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_V2_CLIENT_RESPONSE_INC diff --git a/http/src/network/http/v2/method.hpp b/http/src/network/http/v2/method.hpp new file mode 100644 index 000000000..0f20bcf46 --- /dev/null +++ b/http/src/network/http/v2/method.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_METHOD_INC +#define NETWORK_HTTP_V2_METHOD_INC + +/** + * \file + * \brief HTTP request methods. + */ + +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +enum class method { get, post, put, delete_, head, options, trace, connect, merge, patch, }; + +inline +std::ostream &operator << (std::ostream &os, method m) { + switch (m) { + case method::get: + return os << "GET"; + case method::post: + return os << "POST"; + case method::put: + return os << "PUT"; + case method::delete_: + return os << "DELETE"; + case method::head: + return os << "HEAD"; + case method::options: + return os << "OPTIONS"; + case method::trace: + return os << "TRACE"; + case method::connect: + return os << "CONNECT"; + case method::merge: + return os << "MERGE"; + case method::patch: + return os << "PATCH"; + } + return os; +} +} // namespace v2 +} // namespace http +} // namespace network + + +#endif // NETWORK_HTTP_V2_METHOD_INC diff --git a/http/src/network/http/v2/status.hpp b/http/src/network/http/v2/status.hpp new file mode 100644 index 000000000..b93ae91cc --- /dev/null +++ b/http/src/network/http/v2/status.hpp @@ -0,0 +1,174 @@ +// Copyright (C) 2013 by 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 NETWORK_HTTP_V2_STATUS_INC +#define NETWORK_HTTP_V2_STATUS_INC + +/** + * \file + * \brief Constants for the HTTP error status. + * + * http://tools.ietf.org/html/rfc6585 + * http://httpstatus.es/ + */ + +#include +#include +#include + +namespace network { +namespace http { +inline namespace v2 { +namespace status { +/** + * \ingroup http + * \enum code + * \brief Provides the full set of HTTP status codes. + */ +enum class code { + // informational + continue_ = 100, + switch_protocols = 101, + + // successful + ok = 200, + created = 201, + accepted = 202, + non_auth_info = 203, + no_content = 204, + reset_content = 205, + partial_content = 206, + + // redirection + multiple_choices = 300, + moved_permanently = 301, + found = 302, + see_other = 303, + not_modified = 304, + use_proxy = 305, + temporary_redirect = 307, + + // client error + bad_request = 400, + unauthorized = 401, + payment_required = 402, + forbidden = 403, + not_found = 404, + method_not_allowed = 405, + not_acceptable = 406, + proxy_auth_required = 407, + request_timeout = 408, + conflict = 409, + gone = 410, + length_required = 411, + precondition_failed = 412, + request_entity_too_large = 413, + request_uri_too_long = 414, + unsupported_media_type = 415, + request_range_not_satisfiable = 416, + expectation_failed = 417, + precondition_required = 428, + too_many_requests = 429, + request_header_fields_too_large = 431, + + // server error + internal_error = 500, + not_implemented = 501, + bad_gateway = 502, + service_unavailable = 503, + gateway_timeout = 504, + http_version_not_supported = 505, + network_authentication_required = 511, + }; +} // namespace status +} // namespace v2 +} // namespace http +} // namespace network + +#if !defined(DOXYGEN_SHOULD_SKIP_THIS) +namespace std { +template <> +struct hash { + std::size_t operator()(network::http::v2::status::code status_code) const { + hash hasher; + return hasher(static_cast(status_code)); + } +}; +} // namespace std +#endif // !defined(DOXYGEN_SHOULD_SKIP_THIS) + +namespace network { +namespace http { +inline namespace v2 { +namespace status { +/** + * \ingroup http_client + * \fn + * \brief Returns a message based on the status code provided. + * \param code The status code. + * \returns The corresponding status message. + */ +inline +std::string message(code status_code) { + static std::unordered_map status_messages{ + {code::continue_, "Continue"}, + {code::switch_protocols, "Switching Protocols"}, + {code::ok, "OK"}, + {code::created, "Created"}, + {code::accepted, "Accepted"}, + {code::non_auth_info, "Non-Authoritative Information"}, + {code::no_content, "No Content"}, + {code::reset_content, "Reset Content"}, + {code::partial_content, "Partial Content"}, + {code::multiple_choices, "Multiple Choices"}, + {code::moved_permanently, "Moved Permanently"}, + {code::found, "Found"}, + {code::see_other, "See Other"}, + {code::not_modified, "Not Modified"}, + {code::use_proxy, "Use Proxy"}, + {code::temporary_redirect, "Temporary Redirect"}, + {code::bad_request, "Bad Request"}, + {code::unauthorized, "Unauthorized"}, + {code::payment_required, "Payment Required"}, + {code::forbidden, "Forbidden"}, + {code::not_found, "Not Found"}, + {code::method_not_allowed, "Method Not Allowed"}, + {code::not_acceptable, "Not Acceptable"}, + {code::proxy_auth_required, "Proxy Authentication Required"}, + {code::request_timeout, "Request Timeout"}, + {code::conflict, "Conflict"}, + {code::gone, "Gone"}, + {code::length_required, "Length Required"}, + {code::precondition_failed, "Precondition Failed"}, + {code::request_entity_too_large, "Request Entity Too Large"}, + {code::request_uri_too_long, "Request Uri Too Long"}, + {code::unsupported_media_type, "Unsupported Media Type"}, + {code::request_range_not_satisfiable, "Request Range Not Satisfiable"}, + {code::expectation_failed, "Expectation Failed"}, + {code::precondition_required, "Precondition Required"}, + {code::too_many_requests, "Too Many Requests"}, + {code::request_header_fields_too_large, "Request Header Fields Too Large"}, + {code::internal_error, "Internal Error"}, + {code::not_implemented, "Not Implemented"}, + {code::bad_gateway, "Bad Gateway"}, + {code::service_unavailable, "Service Unavailable"}, + {code::gateway_timeout, "Gateway Timeout"}, + {code::http_version_not_supported, "HTTP Version Not Supported"}, + {code::network_authentication_required, "Network Authentication Required"}, + }; + + auto it = status_messages.find(status_code); + if (it != status_messages.end()) { + return it->second; + } + return "Invalid Status Code"; +} +} // namespace status +} // namespace v2 +} // namespace http +} // namespace network + + +#endif // NETWORK_HTTP_V2_CONSTANTS_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..98032f255 --- /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..8a2cce346 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..28ca1b3af --- /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..1571a4b35 --- /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..3eb0d222d --- /dev/null +++ b/http/src/network/protocol/http/algorithms/linearize.hpp @@ -0,0 +1,159 @@ +// 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..1198819f1 --- /dev/null +++ b/http/src/network/protocol/http/client.hpp @@ -0,0 +1,45 @@ +// 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..c478a85f6 --- /dev/null +++ b/http/src/network/protocol/http/client.ipp @@ -0,0 +1,26 @@ +// 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..414db745d --- /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< + void(boost::iterator_range 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..51138bc80 --- /dev/null +++ b/http/src/network/protocol/http/client/base.ipp @@ -0,0 +1,136 @@ +// 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< + void(boost::iterator_range 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..df9eb3758 --- /dev/null +++ b/http/src/network/protocol/http/client/client_connection.hpp @@ -0,0 +1,39 @@ +// 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 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..be6afceaa --- /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..f828667f1 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_normal.hpp @@ -0,0 +1,57 @@ +// 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..f615aab29 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_normal.ipp @@ -0,0 +1,849 @@ +// 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(...)"); +#ifdef NETWORK_ENABLE_HTTPS + // 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. + constexpr static long short_read_error = 335544539; + bool is_short_read_error = + (ec.category() == boost::asio::error::ssl_category) && + (ec.value() == short_read_error); +#else + constexpr bool is_short_read_error = 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 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 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 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/http/src/network/protocol/http/client/connection/async_protocol_handler.hpp b/http/src/network/protocol/http/client/connection/async_protocol_handler.hpp new file mode 100644 index 000000000..d68d84941 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -0,0 +1,321 @@ +// Copyright 2010 (C) Dean Michael Berris +// 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_PROTOCOL_HANDLER_HPP_ +#define NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ + +#include +#include + +namespace network { +namespace http { +namespace impl { + +struct http_async_protocol_handler { + protected: + +#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 (!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 + + void init_response(response& response_) { + boost::shared_future source_future( + source_promise.get_future()); + source(response_, source_future); + boost::shared_future destination_future( + destination_promise.get_future()); + destination(response_, destination_future); + boost::shared_future< + std::multimap> headers_future( + headers_promise.get_future()); + headers(response_, headers_future); + boost::shared_future body_future(body_promise.get_future()); + body(response_, body_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( + status_message_promise.get_future()); + status_message(response_, status_message_future); + } + + 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(); + } + }; + + template + logic::tribool parse_version(Delegate& delegate_, + Callback callback, + size_t bytes) { + 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); + 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)); + 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(); + delegate_->read_some(asio::mutable_buffers_1(part.c_array(), part.size()), + callback); + } + return parsed_ok; + } + + template + logic::tribool parse_status(Delegate& delegate_, + Callback callback, + size_t bytes) { + 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); + 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)); + trim(status); + boost::uint16_t status_int = 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(); + delegate_->read_some(asio::mutable_buffers_1(part.c_array(), part.size()), + callback); + } + return parsed_ok; + } + + template + logic::tribool parse_status_message(Delegate& delegate_, + Callback callback, + size_t bytes) { + 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); + 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)); + 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(); + delegate_->read_some(asio::mutable_buffers_1(part.c_array(), part.size()), + callback); + } + return parsed_ok; + } + + void parse_headers_real(std::string& headers_part) { + boost::iterator_range input_range = + boost::make_iterator_range(headers_part), result_range; + 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)) { + 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)); + 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)); + + trim(header_pair.first); + if (header_pair.first.size() > 1) { + header_pair.first.erase(header_pair.first.size() - 1); + } + trim(header_pair.second); + headers.insert(header_pair); + } + headers_promise.set_value(headers); + } + + template + fusion::tuple parse_headers(Delegate& delegate_, + Callback callback, + size_t bytes) { + 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); + 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(); + delegate_->read_some(asio::mutable_buffers_1(part.c_array(), part.size()), + callback); + } + return fusion::make_tuple(parsed_ok, + std::distance(boost::end(result_range), + part_end)); + } + + template + void parse_body(Delegate& delegate_, Callback 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(); + delegate_->read_some(asio::mutable_buffers_1(part.c_array(), part.size()), + callback); + } + + 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; + buffer_type::const_iterator part_begin; + std::string partial_parsed; +}; + +} // namespace impl +} // namespace http +} // namespace network + +#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..a64890419 --- /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..55385627c --- /dev/null +++ b/http/src/network/protocol/http/client/connection/async_resolver.ipp @@ -0,0 +1,141 @@ +// 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< + std::string, + std::pair> 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..e0fd3cb0a --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate.hpp @@ -0,0 +1,34 @@ +// 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..72f88e370 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate_factory.hpp @@ -0,0 +1,40 @@ +// 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..4bab38350 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_delegate_factory.ipp @@ -0,0 +1,57 @@ +// 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"); + std::shared_ptr delegate_ptr(new ssl_delegate(service, options)); + delegate = std::move(delegate_ptr); +#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..e86716a42 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_factory.hpp @@ -0,0 +1,36 @@ +// 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..62639fbc4 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/connection_factory.ipp @@ -0,0 +1,20 @@ +// 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..d5ea40392 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/normal_delegate.hpp @@ -0,0 +1,51 @@ +// 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..1a5682951 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/normal_delegate.ipp @@ -0,0 +1,49 @@ +// 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..afa4e56ab --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate.hpp @@ -0,0 +1,32 @@ +// 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..504874b6a --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.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_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..b470c4336 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/resolver_delegate_factory.ipp @@ -0,0 +1,36 @@ +// 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> 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..9e915e2bd --- /dev/null +++ b/http/src/network/protocol/http/client/connection/simple_connection_factory.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_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..94c508996 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/simple_connection_factory.ipp @@ -0,0 +1,101 @@ +// 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..dec0e80f1 --- /dev/null +++ b/http/src/network/protocol/http/client/connection/ssl_delegate.hpp @@ -0,0 +1,58 @@ +// 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 + +namespace boost { +namespace asio { +class io_service; +} // namespace asio +} // namespace boost + +namespace network { +namespace http { + +struct ssl_delegate : connection_delegate, + std::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< + boost::asio::ssl::stream> 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..fb930164d --- /dev/null +++ b/http/src/network/protocol/http/client/connection/ssl_delegate.ipp @@ -0,0 +1,107 @@ +// 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 + +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_none); + } + socket_.reset(new boost::asio::ssl::stream< + boost::asio::ip::tcp::socket>(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/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..90b621e8d --- /dev/null +++ b/http/src/network/protocol/http/client/connection_manager.hpp @@ -0,0 +1,38 @@ +// 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..a57398709 --- /dev/null +++ b/http/src/network/protocol/http/client/connection_manager.ipp @@ -0,0 +1,24 @@ +// 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..15f658ddd --- /dev/null +++ b/http/src/network/protocol/http/client/facade.hpp @@ -0,0 +1,57 @@ +// 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< + std::string>(), + 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< + std::string>(), + 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..9dc2d8f48 --- /dev/null +++ b/http/src/network/protocol/http/client/facade.ipp @@ -0,0 +1,123 @@ +// 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..df91f9ef0 --- /dev/null +++ b/http/src/network/protocol/http/client/macros.hpp @@ -0,0 +1,20 @@ +// 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..8f4ba5ff1 --- /dev/null +++ b/http/src/network/protocol/http/client/options.hpp @@ -0,0 +1,152 @@ +// 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..3771e3a5f --- /dev/null +++ b/http/src/network/protocol/http/client/options.ipp @@ -0,0 +1,258 @@ +// 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< + std::string> 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< + http::connection_manager> 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< + http::connection_factory> 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..f210bcfba --- /dev/null +++ b/http/src/network/protocol/http/client/parameters.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_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..69358999c --- /dev/null +++ b/http/src/network/protocol/http/client/pimpl.hpp @@ -0,0 +1,100 @@ +// 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_, 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..d7aff4c52 --- /dev/null +++ b/http/src/network/protocol/http/client/simple_connection_manager.hpp @@ -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_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..c6864de9b --- /dev/null +++ b/http/src/network/protocol/http/client/simple_connection_manager.ipp @@ -0,0 +1,91 @@ +// 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/errors.hpp b/http/src/network/protocol/http/errors.hpp new file mode 100644 index 000000000..fd5b4536e --- /dev/null +++ b/http/src/network/protocol/http/errors.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_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..e1cff2b2a --- /dev/null +++ b/http/src/network/protocol/http/impl/access.hpp @@ -0,0 +1,39 @@ +// 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..258bc30ff --- /dev/null +++ b/http/src/network/protocol/http/impl/access.ipp @@ -0,0 +1,51 @@ +// 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/request_parser.ipp b/http/src/network/protocol/http/impl/request_parser.ipp new file mode 100644 index 000000000..1b823918e --- /dev/null +++ b/http/src/network/protocol/http/impl/request_parser.ipp @@ -0,0 +1,256 @@ +// +// request_parser.ipp +// ~~~~~~~~~~~~~~~~~~ +// +// 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 (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_HTTP_REQUEST_PARSER_IPP +#define NETWORK_HTTP_REQUEST_PARSER_IPP + +#include + +namespace network { +namespace http { + +template +boost::tribool basic_request_parser::consume(basic_request& req, + char input) { + switch (state_) { + case method_start: + if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + } else { + state_ = method; + req.method.push_back(input); + return boost::indeterminate; + } + case method: + if (input == ' ') { + state_ = uri; + return boost::indeterminate; + } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + } else { + req.method.push_back(input); + return boost::indeterminate; + } + case uri_start: + if (is_ctl(input)) { + return false; + } else { + state_ = uri; + req.destination.push_back(input); + return boost::indeterminate; + } + case uri: + if (input == ' ') { + state_ = http_version_h; + return boost::indeterminate; + } else if (is_ctl(input)) { + return false; + } else { + req.destination.push_back(input); + return boost::indeterminate; + } + case http_version_h: + if (input == 'H') { + state_ = http_version_t_1; + return boost::indeterminate; + } else { + return false; + } + case http_version_t_1: + if (input == 'T') { + state_ = http_version_t_2; + return boost::indeterminate; + } else { + return false; + } + case http_version_t_2: + if (input == 'T') { + state_ = http_version_p; + return boost::indeterminate; + } else { + return false; + } + case http_version_p: + if (input == 'P') { + state_ = http_version_slash; + return boost::indeterminate; + } else { + return false; + } + case http_version_slash: + if (input == '/') { + req.http_version_major = 0; + req.http_version_minor = 0; + state_ = http_version_major_start; + return boost::indeterminate; + } else { + return false; + } + case http_version_major_start: + if (is_digit(input)) { + req.http_version_major = req.http_version_major * 10 + input - '0'; + state_ = http_version_major; + return boost::indeterminate; + } else { + return false; + } + case http_version_major: + if (input == '.') { + state_ = http_version_minor_start; + return boost::indeterminate; + } else if (is_digit(input)) { + req.http_version_major = req.http_version_major * 10 + input - '0'; + return boost::indeterminate; + } else { + return false; + } + case http_version_minor_start: + if (is_digit(input)) { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + state_ = http_version_minor; + return boost::indeterminate; + } else { + return false; + } + case http_version_minor: + if (input == '\r') { + state_ = expecting_newline_1; + return boost::indeterminate; + } else if (is_digit(input)) { + req.http_version_minor = req.http_version_minor * 10 + input - '0'; + return boost::indeterminate; + } else { + return false; + } + case expecting_newline_1: + if (input == '\n') { + state_ = header_line_start; + return boost::indeterminate; + } else { + return false; + } + case header_line_start: + if (input == '\r') { + state_ = expecting_newline_3; + return boost::indeterminate; + } else if (!req.headers.empty() && (input == ' ' || input == '\t')) { + state_ = header_lws; + return boost::indeterminate; + } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + } else { + req.headers.push_back(typename request_header::type()); + req.headers.back().name.push_back(input); + state_ = header_name; + return boost::indeterminate; + } + case header_lws: + if (input == '\r') { + state_ = expecting_newline_2; + return boost::indeterminate; + } else if (input == ' ' || input == '\t') { + return boost::indeterminate; + } else if (is_ctl(input)) { + return false; + } else { + state_ = header_value; + req.headers.back().value.push_back(input); + return boost::indeterminate; + } + case header_name: + if (input == ':') { + state_ = space_before_header_value; + return boost::indeterminate; + } else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) { + return false; + } else { + req.headers.back().name.push_back(input); + return boost::indeterminate; + } + case space_before_header_value: + if (input == ' ') { + state_ = header_value; + return boost::indeterminate; + } else { + return false; + } + case header_value: + if (input == '\r') { + state_ = expecting_newline_2; + return boost::indeterminate; + } else if (is_ctl(input)) { + return false; + } else { + req.headers.back().value.push_back(input); + return boost::indeterminate; + } + case expecting_newline_2: + if (input == '\n') { + state_ = header_line_start; + return boost::indeterminate; + } else { + return false; + } + case expecting_newline_3: + return (input == '\n'); + default: + return false; + } +} + +template bool basic_request_parser::is_char(int c) { + return c >= 0 && c <= 127; +} + +template bool basic_request_parser::is_ctl(int c) { + return (c >= 0 && c <= 31) || (c == 127); +} + +template bool basic_request_parser::is_tspecial(int c) { + switch (c) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '"': + case '/': + case '[': + case ']': + case '?': + case '=': + case '{': + case '}': + case ' ': + case '\t': + return true; + default: + return false; + } +} + +template bool basic_request_parser::is_digit(int c) { + return c >= '0' && c <= '9'; +} + +} // namespace http +} // namespace network + +#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..4727eb317 --- /dev/null +++ b/http/src/network/protocol/http/impl/response.ipp @@ -0,0 +1,301 @@ +// 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..ff2b34056 --- /dev/null +++ b/http/src/network/protocol/http/message/async_message.hpp @@ -0,0 +1,151 @@ +// 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..9aad7e047 --- /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..e2c49df75 --- /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..f5c1ada3e --- /dev/null +++ b/http/src/network/protocol/http/message/directives/minor_version.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_DIRECTIVES_MINOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 + +#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..09484a860 --- /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..961ded756 --- /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..e9f2c263f --- /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..c64071256 --- /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..2d33c5865 --- /dev/null +++ b/http/src/network/protocol/http/message/header.hpp @@ -0,0 +1,54 @@ +// +// 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..6aaea7d5d --- /dev/null +++ b/http/src/network/protocol/http/message/header/name.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_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..fcc2b5fd9 --- /dev/null +++ b/http/src/network/protocol/http/message/header/value.hpp @@ -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) + +#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..e6028f84e --- /dev/null +++ b/http/src/network/protocol/http/message/header_concept.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_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..08044e7d3 --- /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..daded1840 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/method.hpp @@ -0,0 +1,22 @@ +// 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..0e2819ce8 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/minor_version.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_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..46a9b040a --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/status.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_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..de78c164f --- /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..f127c4e29 --- /dev/null +++ b/http/src/network/protocol/http/message/modifiers/uri.hpp @@ -0,0 +1,27 @@ +// 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..66bcf47ea --- /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..8f225c94e --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/anchor.hpp @@ -0,0 +1,30 @@ +// 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..e85c91bce --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/anchor.ipp @@ -0,0 +1,30 @@ +// Copyright 2011 Dean Michael Berris . +// Copyright 2011 Google, 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/http/src/network/protocol/http/message/wrappers/helper.hpp b/http/src/network/protocol/http/message/wrappers/helper.hpp new file mode 100644 index 000000000..946faf9e0 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/helper.hpp @@ -0,0 +1,62 @@ +// 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 NETWORK_DEFINE_HTTP_WRAPPER +#define NETWORK_DEFINE_HTTP_WRAPPER(name, accessor, pod_field)\ + struct name##_pod_accessor {\ + protected:\ + template \ + typename Message::string_type const& get_value(\ + Message const& message) const {\ + return message.pod_field;\ + }\ + };\ + struct name##_member_accessor {\ + protected:\ + template \ + typename Message::string_type get_value(Message const& message) const {\ + return message.accessor();\ + }\ + }\ + ;\ +\ + template \ + struct name##_wrapper_impl : mpl::if_,\ + name##_pod_accessor,\ + name##_member_accessor> {}\ + ;\ +\ + template \ + struct name##_wrapper : name##_wrapper_impl::type {\ + typedef typename string::type string_type;\ + Message const& message_;\ + name##_wrapper(Message const& message) : message_(message) {}\ + name##_wrapper(name##_wrapper const& other) : message_(other.message_) {}\ + operator string_type() const { return this->get_value(message_); }\ + }\ + ;\ +\ + template \ + inline name##_wrapper> const name(\ + basic_response const& message) {\ + return name##_wrapper>(message);\ + }\ +\ + template \ + inline name##_wrapper> const name(\ + basic_request const& message) {\ + return name##_wrapper>(message);\ + } + +#endif /* NETWORK_DEFINE_HTTP_WRAPPER */ + +#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..de61f6b9e --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/host.hpp @@ -0,0 +1,30 @@ +// 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..924092112 --- /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..d484a5463 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/major_version.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_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..08a3b9c4f --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/method.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_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/http/src/network/protocol/http/message/wrappers/minor_version.hpp b/http/src/network/protocol/http/message/wrappers/minor_version.hpp new file mode 100644 index 000000000..b5377db6c --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/minor_version.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_WRAPPERS_MINOR_VERSION_HPP_20101120 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 + +#include +#include +#include + +namespace network { +namespace http { + +template struct basic_request; + +template struct minor_version_wrapper { + basic_request const& request; + explicit minor_version_wrapper(basic_request const& request) + : request(request) {} + operator boost:: uint8_t() { return request.http_version_minor; } +}; + +template +inline typename enable_if, + minor_version_wrapper>::type minor_version( + basic_request const& request) { + return minor_version_wrapper(request); +} + +} // namespace http +} // namespace network + +#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..808856ba9 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/path.hpp @@ -0,0 +1,30 @@ +// 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..6cb03f079 --- /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..0a93a4f77 --- /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< boost:: uint16_t>() 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..81322d605 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/port.ipp @@ -0,0 +1,47 @@ +// 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_->compare("http") == 0) { + return 80u; + } else if (scheme_->compare("https") == 0) { + return 443u; + } + } + return std::stoul(std::string(*optional_port)); +} + +port_wrapper::operator boost:: optional< boost:: uint16_t>() 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..2336b6e6c --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/protocol.hpp @@ -0,0 +1,30 @@ +// 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..7f895a58e --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/query.hpp @@ -0,0 +1,30 @@ +// 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..b1f9b1215 --- /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/http/src/network/protocol/http/message/wrappers/ready.hpp b/http/src/network/protocol/http/message/wrappers/ready.hpp new file mode 100644 index 000000000..461568679 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/ready.hpp @@ -0,0 +1,43 @@ +// 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_READY_HPP_20100618 +#define NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_READY_HPP_20100618 + +#include + +namespace network { +namespace http { + +template struct async_message; + +namespace impl { +template +struct ready_wrapper + : network::detail::wrapper_base_const> { + typedef network::detail::wrapper_base_const< + Tag, + async_message> wrapper_base; + explicit ready_wrapper(async_message const& message) + : wrapper_base(message) {} + operator bool() { + return wrapper_base::_message.version_.is_ready() && + wrapper_base::_message.status_.is_ready() && + wrapper_base::_message.status_message_.is_ready() && + wrapper_base::_message.headers_.is_ready() && + wrapper_base::_message.body_.is_ready(); + } +}; +} // namespace impl + +template inline bool ready(async_message const& message) { + return impl::ready_wrapper(message); +} + +} // namespace http +} // namespace network + +#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..4bf92275a --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status.hpp @@ -0,0 +1,30 @@ +// 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..af436c75f --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status.ipp @@ -0,0 +1,26 @@ +// 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..0a8985e9f --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status_message.hpp @@ -0,0 +1,38 @@ +// 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..d45aa4e8c --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/status_message.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_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..3a5936156 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/uri.hpp @@ -0,0 +1,32 @@ +// 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..16548b728 --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/uri.ipp @@ -0,0 +1,34 @@ +// 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..ffd2fb77f --- /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..b8cca3d0b --- /dev/null +++ b/http/src/network/protocol/http/message/wrappers/version.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_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/http/src/network/protocol/http/parser.hpp b/http/src/network/protocol/http/parser.hpp new file mode 100644 index 000000000..16f278974 --- /dev/null +++ b/http/src/network/protocol/http/parser.hpp @@ -0,0 +1,341 @@ +// 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_HPP +#define NETWORK_PROTOCOL_HTTP_PARSER_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +// forward declarations used to finish HTTP requests +template class basic_request; + +// forward declarations used to finish HTTP requests +template class basic_response; + +/// an incremental HTTP 1.0/1.1 protocol parser +template > +class basic_parser : private boost::noncopyable { + public: + + // import types from ParserTraits template + typedef ParserTraits traits_type; + typedef typename string::type string_type; + + // default destructor + virtual ~basic_parser() {} + + /** + * creates a new HTTP protocol parser + * + * @param is_request if true, the message is parsed as an HTTP request; + * if false, the message is parsed as an HTTP response + */ + basic_parser(const bool is_request) + : m_is_request(is_request), + m_read_ptr(NULL), + m_read_end_ptr(NULL), + m_headers_parse_state(is_request ? PARSE_METHOD_START : + PARSE_HTTP_VERSION_H), + m_chunked_content_parse_state(PARSE_CHUNK_SIZE_START), + m_status_code(0), + m_bytes_last_read(0), + m_bytes_total_read(0) {} + + /** + * parses an HTTP message up to the end of the headers using bytes + * available in the read buffer + * + * @param http_msg the HTTP message object to populate from parsing + * + * @return boost::tribool result of parsing: + * false = message has an error, + * true = finished parsing HTTP headers, + * indeterminate = not yet finished parsing HTTP headers + */ + boost::tribool parse_http_headers(basic_message& http_msg); + + /** + * parses a chunked HTTP message-body using bytes available in the read buffer + * + * @param chunk_buffers buffers to be populated from parsing chunked content + * + * @return boost::tribool result of parsing: + * false = message has an error, + * true = finished parsing message, + * indeterminate = message is not yet finished + */ + boost::tribool parse_chunks(types::chunk_cache_t& chunk_buffers); + + /** + * prepares the payload content buffer and consumes any content remaining + * in the parser's read buffer + * + * @param http_msg the HTTP message object to consume content for + * @return unsigned long number of content bytes consumed, if any + */ + std::size_t consume_content(basic_message& http_msg); + + /** + * consume the bytes available in the read buffer, converting them into + * the next chunk for the HTTP message + * + * @param chunk_buffers buffers to be populated from parsing chunked content + * @return unsigned long number of content bytes consumed, if any + */ + std::size_t consume_content_as_next_chunk( + types::chunk_cache_t& chunk_buffers); + + /** + * finishes parsing an HTTP request message (copies over request-only data) + * + * @param http_request the HTTP request object to finish + */ + void finish(basic_request& http_request); + + /** + * finishes an HTTP response message (copies over response-only data) + * + * @param http_request the HTTP response object to finish + */ + void finish(basic_response& http_response); + + /** + * resets the location and size of the read buffer + * + * @param ptr pointer to the first bytes available to be read + * @param len number of bytes available to be read + */ + inline void set_read_buffer(const char* ptr, std::size_t len) { + m_read_ptr = ptr; + m_read_end_ptr = ptr + len; + } + + /** + * saves the current read position bookmark + * + * @param read_ptr points to the next character to be consumed in the read_buffer + * @param read_end_ptr points to the end of the read_buffer (last byte + 1) + */ + inline void save_read_position(const char*& read_ptr, + const char*& read_end_ptr) const { + read_ptr = m_read_ptr; + read_end_ptr = m_read_end_ptr; + } + + /// resets the parser to its initial state + inline void reset(void); + + /// returns true if there are no more bytes available in the read buffer + inline bool eof(void) const { + return m_read_ptr == NULL || m_read_ptr >= m_read_end_ptr; + } + + /// returns the number of bytes read during the last parse operation + inline std::size_t gcount(void) const { return m_bytes_last_read; } + + /// returns the total number of bytes read while parsing the HTTP message + inline std::size_t bytes_read(void) const { return m_bytes_total_read; } + + /// returns the number of bytes available in the read buffer + inline std::size_t bytes_available(void) const { + return (eof() ? 0 : (m_read_end_ptr - m_read_ptr)); + } + + protected: + + /** + * parse key-value pairs out of a url-encoded string + * (i.e. this=that&a=value) + * + * @param params container for key-values string pairs + * @param ptr points to the start of the encoded string + * @param len length of the encoded string, in bytes + * + * @return bool true if successful + */ + static bool parse_url_encoded(types::query_params& params, + const char* ptr, + const std::size_t len); + + /** + * parse key-value pairs out of a "Cookie" request header + * (i.e. this=that; a=value) + * + * @param params container for key-values string pairs + * @param cookie_header header string to be parsed + * + * @return bool true if successful + */ + static bool parse_cookie_header(types::cookie_params& params, + const string_type& cookie_header); + + /// true if the message is an HTTP request; false if it is an HTTP response + const bool m_is_request; + + /// points to the next character to be consumed in the read_buffer + const char* m_read_ptr; + + /// points to the end of the read_buffer (last byte + 1) + const char* m_read_end_ptr; + + private: + + // returns true if the argument is a special character + inline static bool is_special(int c) { + switch (c) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '"': + case '/': + case '[': + case ']': + case '?': + case '=': + case '{': + case '}': + case ' ': + case '\t': + return true; + default: + return false; + } + } + + // returns true if the argument is a character + inline static bool is_char(int c) { return (c >= 0 && c <= 127); } + + // returns true if the argument is a control character + inline static bool is_control(int c) { + return ((c >= 0 && c <= 31) || c == 127); + } + + // returns true if the argument is a digit + inline static bool is_digit(int c) { return (c >= '0' && c <= '9'); } + + // returns true if the argument is a hexadecimal digit + inline static bool is_hex_digit(int c) { + return ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F')); + } + + /// state used to keep track of where we are in parsing the HTTP headers + enum headers_parse_state_t { + PARSE_METHOD_START, + PARSE_METHOD, + PARSE_URI_STEM, + PARSE_URI_QUERY, + PARSE_HTTP_VERSION_H, + PARSE_HTTP_VERSION_T_1, + PARSE_HTTP_VERSION_T_2, + PARSE_HTTP_VERSION_P, + PARSE_HTTP_VERSION_SLASH, + PARSE_HTTP_VERSION_MAJOR_START, + PARSE_HTTP_VERSION_MAJOR, + PARSE_HTTP_VERSION_MINOR_START, + PARSE_HTTP_VERSION_MINOR, + PARSE_STATUS_CODE_START, + PARSE_STATUS_CODE, + PARSE_STATUS_MESSAGE, + PARSE_EXPECTING_NEWLINE, + PARSE_EXPECTING_CR, + PARSE_HEADER_WHITESPACE, + PARSE_HEADER_START, + PARSE_HEADER_NAME, + PARSE_SPACE_BEFORE_HEADER_VALUE, + PARSE_HEADER_VALUE, + PARSE_EXPECTING_FINAL_NEWLINE, + PARSE_EXPECTING_FINAL_CR + }; + + /// state used to keep track of where we are in parsing chunked content + enum chunked_content_parse_state_t { + PARSE_CHUNK_SIZE_START, + PARSE_CHUNK_SIZE, + PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE, + PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE, + PARSE_CHUNK, + PARSE_EXPECTING_CR_AFTER_CHUNK, + PARSE_EXPECTING_LF_AFTER_CHUNK, + PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK, + PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK + }; + + /// the current state of parsing HTTP headers + headers_parse_state_t m_headers_parse_state; + + /// the current state of parsing chunked content + chunked_content_parse_state_t m_chunked_content_parse_state; + + /// Used for parsing the HTTP response status code + boost::uint16_t m_status_code; + + /// Used for parsing the HTTP response status message + string_type m_status_message; + + /// Used for parsing the request method + string_type m_method; + + /// Used for parsing the name of resource requested + string_type m_resource; + + /// Used for parsing the query string portion of a URI + string_type m_query_string; + + /// Used for parsing the name of HTTP headers + string_type m_header_name; + + /// Used for parsing the value of HTTP headers + string_type m_header_value; + + /// Used for parsing the chunk size + string_type m_chunk_size_str; + + /// Used for parsing the current chunk + std::vector m_current_chunk; + + /// number of bytes in the chunk currently being parsed + std::size_t m_size_of_current_chunk; + + /// number of bytes read so far in the chunk currently being parsed + std::size_t m_bytes_read_in_current_chunk; + + /// number of bytes read during last parse operation + std::size_t m_bytes_last_read; + + /// total number of bytes read while parsing the HTTP message + std::size_t m_bytes_total_read; +}; + +/// typedef for the default HTTP protocol parser implementation +typedef basic_parser parser; + +} // namespace http +} // namespace network + +// import implementation file +#include + +#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..a7a7fdb82 --- /dev/null +++ b/http/src/network/protocol/http/parser/incremental.hpp @@ -0,0 +1,290 @@ +// 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< + boost::logic::tribool, + boost::iterator_range> 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..4c4394b1f --- /dev/null +++ b/http/src/network/protocol/http/policies/async_connection.hpp @@ -0,0 +1,79 @@ +// 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, + std::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..5c5e02e07 --- /dev/null +++ b/http/src/network/protocol/http/policies/async_connection.ipp @@ -0,0 +1,174 @@ +// 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::client_connection> 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..8e5f335e2 --- /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..6f7f492dd --- /dev/null +++ b/http/src/network/protocol/http/request/request.hpp @@ -0,0 +1,117 @@ +// 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); + + virtual void swap(request& other); + virtual bool equals(request const& other) 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< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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< + void(std::string::const_iterator, size_t)> 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..6abc1ecfc --- /dev/null +++ b/http/src/network/protocol/http/request/request.ipp @@ -0,0 +1,290 @@ +// 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< + void(std::string const&, std::string const&)> 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< + void(std::string const&, std::string const&)> 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; +} + +void request::swap(request& other ) { + using std::swap; + swap(pimpl_, other.pimpl_); + request_storage_base::swap(other); +} + +bool request::equals(request const& other) const { + return pimpl_->equals(*other.pimpl_) && request_storage_base::equals(other); +} + +// 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< + void(std::string const&, std::string const&)> inserter) const { + pimpl_->get_headers(inserter); +} + +void request::get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const { + pimpl_->get_headers(name, inserter); +} + +void request::get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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< + void(std::string::const_iterator, size_t)> 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..60947ed9f --- /dev/null +++ b/http/src/network/protocol/http/request/request_base.hpp @@ -0,0 +1,70 @@ +// 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..7befd11c4 --- /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 +#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/http/src/network/protocol/http/request/request_concept.hpp b/http/src/network/protocol/http/request/request_concept.hpp new file mode 100644 index 000000000..c96231c02 --- /dev/null +++ b/http/src/network/protocol/http/request/request_concept.hpp @@ -0,0 +1,104 @@ +// 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 + +namespace network { +namespace http { + +template struct ServerRequest { + BOOST_CONCEPT_USAGE(ServerRequest) { + std::string source_, method_, destination_; + boost::uint8_t major_version_, minor_version_; + std::multimap headers_; + std::string body_; + + source_ = source(request); + method_ = method(request); + destination_ = destination(request); + major_version_ = major_version(request); + minor_version_ = minor_version(request); + headers_ = headers(request); + body_ = body(request); + + source(request, source_); + method(request, method_); + destination(request, destination_); + major_version(request, major_version_); + minor_version(request, minor_version_); + headers(request, headers_); + add_header(request, std::string(), std::string()); + remove_header(request, std::string()); + clear_headers(request); + body(request, body_); + + std::string name, value; + + 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_; + (void) body_; + (void) name; + (void) value; + } + + private: + R request; +}; + +template struct ClientRequest : network::Message { + BOOST_CONCEPT_USAGE(ClientRequest) { + std::string tmp; + R request_(tmp); + swap(request, request_); // swappable via ADL + + 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(std::string()); + + network::http::uri(request, std::string()); + + (void) host_; + (void) port_; + (void) path_; + (void) query_; + (void) anchor_; + (void) protocol_; + } + + private: + R request; +}; + +} // namespace http + +} // namespace network + +#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 67% rename from boost/network/protocol/http/request_parser.hpp rename to http/src/network/protocol/http/request_parser.hpp index 13818cbf2..579a12b7a 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,18 @@ #include #include -#include +#include -namespace boost { namespace network { namespace http { +namespace network { +namespace http { -namespace tag { - struct default_; -} +namespace tag { struct default_; } /// Parser for incoming requests. -template -class basic_request_parser -{ -public: +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,11 +39,10 @@ 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, - InputIterator begin, InputIterator end) - { - while (begin != end) - { + boost::tuple parse_headers(request& req, + InputIterator begin, + InputIterator end) { + while (begin != end) { boost::tribool result = consume(req, *begin++); if (result || !result) return boost::make_tuple(result, begin); @@ -54,9 +51,9 @@ class basic_request_parser return boost::make_tuple(result, begin); } -private: + 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); @@ -71,8 +68,7 @@ class basic_request_parser static bool is_digit(int c); /// The current state of the parser. - enum state - { + enum state { method_start, method, uri_start, @@ -97,12 +93,9 @@ class basic_request_parser } state_; }; -} // namespace http +} // namespace http +} // namespace network -} // namespace network +#include -} // namespace boost - -#include - -#endif // HTTP_SERVER3_REQUEST_PARSER_HPP +#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..8fe46608c --- /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..908b8b4b3 --- /dev/null +++ b/http/src/network/protocol/http/response/response.hpp @@ -0,0 +1,97 @@ +// 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< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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..382562fa2 --- /dev/null +++ b/http/src/network/protocol/http/response/response.ipp @@ -0,0 +1,483 @@ +// 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 + +#include +#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) { + if (removed_headers_.find(name) != removed_headers_.end()) + return; + + std::pair::const_iterator, + std::multimap::const_iterator> + range; + if (!headers_future_.valid()) { + range = added_headers_.equal_range(name); + } else { + std::multimap const& headers_ = + headers_future_.get(); + range = headers_.equal_range(name); + } + + for (auto it = range.first; it != range.second; ++it) { + inserter(it->first, it->second); + } + } + 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 { + std::string partial_parsed = body_future_.get(); + bool chunked = false; + auto check = [&](std::string const& key, std::string const& value) { + chunked = chunked || boost::iequals(value, "chunked"); + }; + get_headers(std::string("Transfer-Encoding"), check); + if (chunked) { + auto begin = partial_parsed.begin(); + std::string crlf = "\r\n"; + for (auto iter = std::search(begin,partial_parsed.end(), crlf.begin(), crlf.end()); + iter != partial_parsed.end(); + iter = std::search(begin,partial_parsed.end(), crlf.begin(), crlf.end())) { + std::string line(begin, iter); + if (line.empty()) break; + std::stringstream stream(line); + int len; + stream >> std::hex >> len; + iter += 2; + if (!len) break; + if (len <= partial_parsed.end() - iter) { + body.insert(body.end(), iter, iter + len); + iter += len; + } + begin = iter; + } + } else { + std::swap(body, partial_parsed); + } + } + } + + 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< + std::multimap> 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< + void(std::string const&, std::string const&)> inserter) const { + pimpl_->get_headers(inserter); +} + +void response::get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const { + pimpl_->get_headers(name, inserter); +} + +void response::get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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..9ab70903b --- /dev/null +++ b/http/src/network/protocol/http/response/response_base.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_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..2a7994f52 --- /dev/null +++ b/http/src/network/protocol/http/response/response_base.ipp @@ -0,0 +1,22 @@ +// 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/http/src/network/protocol/http/response/response_concept.hpp b/http/src/network/protocol/http/response/response_concept.hpp new file mode 100644 index 000000000..0b6200e52 --- /dev/null +++ b/http/src/network/protocol/http/response/response_concept.hpp @@ -0,0 +1,55 @@ +// 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 + +namespace network { +namespace http { + +template struct Response : network::Message { + typedef typename R::string_type string_type; + + BOOST_CONCEPT_USAGE(Response) { + R response_; + swap(response, response_); // swappable via ADL + + 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 + << status_message(status_message_type()) // status_message directive + ; + + version(response, version_type()); + status(response, status_type()); + status_message(response, status_message_type()); + + string_type version_ = version(response); + boost::uint16_t status_ = status(response); + string_type status_message_ = status_message(response); + + (void) version_; + (void) status_; + (void) status_message_; + } + + private: + R response; +}; + +} // namespace http +} // namespace network + +#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..60cd7b6c9 --- /dev/null +++ b/http/src/network/protocol/http/server.hpp @@ -0,0 +1,77 @@ +// 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..3082cf894 --- /dev/null +++ b/http/src/network/protocol/http/server/async_impl.hpp @@ -0,0 +1,60 @@ +// 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..7004d1345 --- /dev/null +++ b/http/src/network/protocol/http/server/async_impl.ipp @@ -0,0 +1,159 @@ +// 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/http/src/network/protocol/http/server/async_server.hpp b/http/src/network/protocol/http/server/async_server.hpp new file mode 100644 index 000000000..31a9c30e7 --- /dev/null +++ b/http/src/network/protocol/http/server/async_server.hpp @@ -0,0 +1,174 @@ +// 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_ASYNC_SERVER_HPP_20101025 +#define NETWORK_PROTOCOL_HTTP_SERVER_ASYNC_SERVER_HPP_20101025 + +#include +#include +#include +#include +#include +#include + +namespace network { +namespace http { + +template +struct async_server_base : server_storage_base, socket_options_base { + typedef basic_request request; + typedef basic_response response; + typedef typename string::type string_type; + typedef typename boost::network::http::response_header< + Tag>::type response_header; + typedef async_connection connection; + typedef shared_ptr connection_ptr; + typedef boost::unique_lock scoped_mutex_lock; + + template + async_server_base(ArgPack const& args) + : server_storage_base( + args, + typename mpl::if_< + is_same::type, + void>, + server_storage_base::no_io_service, + server_storage_base::has_io_service>::type()), + socket_options_base(args), + handler(args[_handler]), + address_(args[_address]), + port_(args[_port]), + thread_pool(args[_thread_pool]), + acceptor(server_storage_base::service_), + stopping(false), + new_connection(), + listening_mutex_(), + stopping_mutex_(), + listening(false) {} + + void run() { + listen(); + service_.run(); + } + ; + + void stop() { + // stop accepting new requests and let all the existing + // handlers finish. + scoped_mutex_lock listening_lock(listening_mutex_); + if (listening) { // we dont bother stopping if we arent currently listening + scoped_mutex_lock stopping_lock(stopping_mutex_); + stopping = true; + system::error_code ignored; + acceptor.close(ignored); + listening = false; + service_.post(std::bind(&async_server_base::handle_stop, this)); + } + } + + void listen() { + scoped_mutex_lock listening_lock(listening_mutex_); + NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); + if (!listening) + start_listening(); // we only initialize our acceptor/sockets if we arent already listening + if (!listening) { + NETWORK_MESSAGE("Error listening on " << address_ << ':' << port_); + boost::throw_exception( + std::runtime_error("Error listening on provided port.")); + } + } + + private: + Handler& handler; + string_type address_, port_; + utils::thread_pool& thread_pool; + asio::ip::tcp::acceptor acceptor; + bool stopping; + connection_ptr new_connection; + boost::mutex listening_mutex_; + boost::mutex stopping_mutex_; + bool listening; + + void handle_stop() { + scoped_mutex_lock stopping_lock(stopping_mutex_); + if (stopping) + service_ + .stop(); // a user may have started listening again before the stop command is reached + } + + 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 + } + if (!ec) { + socket_options_base::socket_options(new_connection->socket()); + new_connection->start(); + new_connection.reset(new connection(service_, handler, thread_pool)); + acceptor.async_accept( + new_connection->socket(), + std::bind(&async_server_base::handle_accept, + this, + asio::placeholders::error)); + } else { + NETWORK_MESSAGE("Error accepting connection, reason: " << ec); + } + } + + void start_listening() { + using asio::ip::tcp; + + system::error_code error; + + service_.reset(); // this 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_); + return; + } + tcp::endpoint endpoint = *endpoint_iterator; + acceptor.open(endpoint.protocol(), error); + if (error) { + NETWORK_MESSAGE("Error opening socket: " << address_ << ":" << port_); + return; + } + socket_options_base::acceptor_options(acceptor); + acceptor.bind(endpoint, error); + if (error) { + NETWORK_MESSAGE("Error binding socket: " << address_ << ":" << port_); + return; + } + acceptor.listen(asio::socket_base::max_connections, error); + if (error) { + 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(), + std::bind(&async_server_base::handle_accept, + this, + 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 + NETWORK_MESSAGE("Now listening on socket: '" << address_ << ":" << port_ + << "'"); + } +}; + +} // namespace http +} // namespace network + +#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..18d06f36f --- /dev/null +++ b/http/src/network/protocol/http/server/connection/async.hpp @@ -0,0 +1,660 @@ +// 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 +#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( + std::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< + !std::is_base_of::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< + std::is_base_of::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(std::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(std::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(std::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< + std::vector> 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(std::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< + std::pair>::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(std::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(std::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(std::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(std::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< + std::vector>(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 = + std::bind( + &async_server_connection::template write_vec_impl< + ConstBufferSeq, + std::function>, + 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, + std::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..6bc3365e0 --- /dev/null +++ b/http/src/network/protocol/http/server/connection/sync.hpp @@ -0,0 +1,334 @@ +// 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 std::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(std::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< + std::pair>::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( + std::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( + std::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(std::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/http/src/network/protocol/http/server/impl/parsers.ipp b/http/src/network/protocol/http/server/impl/parsers.ipp new file mode 100644 index 000000000..e56c3e8a4 --- /dev/null +++ b/http/src/network/protocol/http/server/impl/parsers.ipp @@ -0,0 +1,53 @@ +// 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 SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 +#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 + +#include + +#include +#include +#include + +#ifdef NETWORK_NO_LIB +#ifndef NETWORK_INLINE +#define NETWORK_INLINE inline +#endif +#else +#define NETWORK_INLINE +#endif +#include + +namespace network { +namespace http { + +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(), + (lit("HTTP/") >> ushort_ >> '.' >> ushort_), + version_pair); +} + +NETWORK_INLINE void parse_headers( + std::string const& input, + std::vector>& container) { + using namespace boost::spirit::qi; + parse(input.begin(), + input.end(), + *(+(alnum | (punct - ':')) >> lit(": ") >> + +((alnum | space | punct) - '\r' - '\n') >> lit("\r\n")) >> + lit("\r\n"), + container); +} + +} // namespace http +} // namespace network + +#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..7c58bcb64 --- /dev/null +++ b/http/src/network/protocol/http/server/impl/socket_options_setter.hpp @@ -0,0 +1,28 @@ +// 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..a1c222509 --- /dev/null +++ b/http/src/network/protocol/http/server/impl/socket_options_setter.ipp @@ -0,0 +1,61 @@ +// 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..953030dd7 --- /dev/null +++ b/http/src/network/protocol/http/server/options.hpp @@ -0,0 +1,84 @@ +// 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..bb51d27ec --- /dev/null +++ b/http/src/network/protocol/http/server/options.ipp @@ -0,0 +1,234 @@ +// 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/http/src/network/protocol/http/server/parameters.hpp b/http/src/network/protocol/http/server/parameters.hpp new file mode 100644 index 000000000..3c8527fe7 --- /dev/null +++ b/http/src/network/protocol/http/server/parameters.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_SERVER_PARAMETERS_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 + +#include + +namespace network { +namespace http { + +BOOST_PARAMETER_NAME(address) BOOST_PARAMETER_NAME(port) + BOOST_PARAMETER_NAME(handler) BOOST_PARAMETER_NAME(thread_pool) + BOOST_PARAMETER_NAME(reuse_address) BOOST_PARAMETER_NAME(report_aborted) + BOOST_PARAMETER_NAME(receive_buffer_size) + BOOST_PARAMETER_NAME(send_buffer_size) + BOOST_PARAMETER_NAME(receive_low_watermark) + BOOST_PARAMETER_NAME(send_low_watermark) + BOOST_PARAMETER_NAME(non_blocking_io) BOOST_PARAMETER_NAME(linger) + BOOST_PARAMETER_NAME(linger_timeout) + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 */ diff --git a/http/src/network/protocol/http/server/request.hpp b/http/src/network/protocol/http/server/request.hpp new file mode 100644 index 000000000..ace15da0d --- /dev/null +++ b/http/src/network/protocol/http/server/request.hpp @@ -0,0 +1,49 @@ +// +// request.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot 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 NETWORK_HTTP_REQUEST_HPP +#define NETWORK_HTTP_REQUEST_HPP + +#include +#include +#include +#include "header.hpp" + +namespace network { +namespace http { + +/// A request received from a client. +struct request { + std::string method; + std::string uri; + int http_version_major; + int http_version_minor; + std::vector
headers; + std::string body; +}; + +inline void swap(request& l, request& r) { + using std::swap; + swap(l.method, r.method); + swap(l.uri, r.uri); + swap(l.http_version_major, r.http_version_major); + swap(l.http_version_minor, r.http_version_minor); + swap(l.headers, r.headers); + swap(l.body, r.body); +} + +} // namespace http +} // namespace network + +#endif // NETWORK_HTTP_REQUEST_HPP + diff --git a/http/src/network/protocol/http/server/request_parser.hpp b/http/src/network/protocol/http/server/request_parser.hpp new file mode 100644 index 000000000..3b3f679f6 --- /dev/null +++ b/http/src/network/protocol/http/server/request_parser.hpp @@ -0,0 +1,233 @@ +// 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 network { +namespace http { + +struct request_parser { + + enum state_t { + method_start, + method_char, + method_done, + uri_char, + uri_done, + version_h, + version_t1, + version_t2, + version_p, + version_slash, + version_d1, + version_dot, + version_d2, + version_cr, + version_done, + header_name, + header_colon, + header_value, + header_cr, + header_line_done, + headers_cr, + headers_done + }; + + explicit request_parser(state_t start_state = method_start) + : internal_state(start_state) {} + + void reset(state_t start_state = method_start) { + internal_state = method_start; + } + + state_t state() const { return internal_state; } + + template + boost::fusion::tuple< + boost::logic::tribool, + boost::iterator_range> parse_until( + state_t stop_state, + Range& range) { + 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; + boost::iterator_range local_range = + boost::make_iterator_range(start, end); + while (!boost::empty(local_range) && stop_state != internal_state && + indeterminate(parsed_ok)) { + current_iterator = boost::begin(local_range); + switch (internal_state) { + case method_start: + if (boost::algorithm::is_upper()(*current_iterator)) + internal_state = method_char; + else + parsed_ok = false; + break; + case method_char: + 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 (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 (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; + else + parsed_ok = false; + break; + case version_h: + if (*current_iterator == 'T') + internal_state = version_t1; + else + parsed_ok = false; + break; + case version_t1: + if (*current_iterator == 'T') + internal_state = version_t2; + else + parsed_ok = false; + break; + case version_t2: + if (*current_iterator == 'P') + internal_state = version_p; + else + parsed_ok = false; + break; + case version_p: + if (*current_iterator == '/') + internal_state = version_slash; + else + parsed_ok = false; + break; + case version_slash: + if (boost::algorithm::is_digit()(*current_iterator)) + internal_state = version_d1; + else + parsed_ok = false; + break; + case version_d1: + if (*current_iterator == '.') + internal_state = version_dot; + else + parsed_ok = false; + break; + case version_dot: + if (boost::algorithm::is_digit()(*current_iterator)) + internal_state = version_d2; + else + parsed_ok = false; + break; + case version_d2: + if (*current_iterator == '\r') + internal_state = version_cr; + else + parsed_ok = false; + break; + case version_cr: + if (*current_iterator == '\n') + internal_state = version_done; + else + parsed_ok = false; + break; + case version_done: + 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 (boost::algorithm::is_alnum()(*current_iterator) || + boost::algorithm::is_punct()(*current_iterator)) + break; + else + parsed_ok = false; + break; + case header_colon: + if (*current_iterator == ' ') + internal_state = header_value; + else + parsed_ok = false; + break; + case header_value: + if (*current_iterator == '\r') + internal_state = header_cr; + else if (boost::algorithm::is_cntrl()(*current_iterator)) + parsed_ok = false; + break; + case header_cr: + if (*current_iterator == '\n') + internal_state = header_line_done; + else + parsed_ok = false; + break; + case header_line_done: + if (*current_iterator == '\r') + internal_state = headers_cr; + else if (boost::algorithm::is_alnum()(*current_iterator)) + internal_state = header_name; + else + parsed_ok = false; + break; + case headers_cr: + if (*current_iterator == '\n') + internal_state = headers_done; + else + parsed_ok = false; + break; + case headers_done: + // anything that follows after headers_done is allowed. + break; + default: + parsed_ok = false; + } + ; + if (internal_state == stop_state) + parsed_ok = true; + local_range = boost::make_iterator_range(++current_iterator, end); + } + return boost::fusion::make_tuple( + parsed_ok, + boost::make_iterator_range(start, current_iterator)); + } + + private: + state_t internal_state; + +}; + +} // namespace http +} // namespace network + +#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..81e05e9bf --- /dev/null +++ b/http/src/network/protocol/http/server/server.ipp @@ -0,0 +1,64 @@ +// 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/http/src/network/protocol/http/server/socket_options_base.hpp b/http/src/network/protocol/http/server/socket_options_base.hpp new file mode 100644 index 000000000..5afa28a13 --- /dev/null +++ b/http/src/network/protocol/http/server/socket_options_base.hpp @@ -0,0 +1,87 @@ +// 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_SOCKET_OPTIONS_BASE_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 + +#include +#include +#include + +namespace network { +namespace http { + +struct socket_options_base { + protected: + asio::socket_base::reuse_address acceptor_reuse_address; + asio::socket_base::enable_connection_aborted acceptor_report_aborted; + boost::optional receive_buffer_size; + boost::optional send_buffer_size; + boost::optional< + asio::socket_base::receive_low_watermark> receive_low_watermark; + boost::optional send_low_watermark; + asio::socket_base::non_blocking_io non_blocking_io; + asio::socket_base::linger linger; + + template + socket_options_base(ArgPack const& args) + : acceptor_reuse_address(args[_reuse_address | false]), + acceptor_report_aborted(args[_report_aborted | false]), + non_blocking_io(args[_non_blocking_io | true]), + linger(args[_linger | true], args[_linger_timeout | 0]) { + set_optional(receive_buffer_size, args, _receive_buffer_size); + set_optional(send_buffer_size, args, _send_buffer_size); + set_optional(receive_low_watermark, args, _receive_low_watermark); + set_optional(send_low_watermark, args, _send_low_watermark); + } + + void acceptor_options(asio::ip::tcp::acceptor& acceptor) { + acceptor.set_option(acceptor_reuse_address); + acceptor.set_option(acceptor_report_aborted); + } + + 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); + if (receive_low_watermark) + socket.set_option(*receive_low_watermark, ignored); + if (send_buffer_size) + socket.set_option(*send_buffer_size, ignored); + if (send_low_watermark) + socket.set_option(*send_low_watermark, ignored); + } + + private: + + template + typename boost::enable_if::type, + void>>, + void>::type set_optional(Optional& option, + Args const& args, + Keyword const& keyword) { + option = in_place(args[keyword]); + } + + template + typename boost::enable_if< + boost::is_same< + typename boost::parameter::value_type::type, + void>, + void>::type set_optional(Optional&, Args const&, Keyword const&) { + // do nothing + } + +}; + +} // namespace http + +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 */ diff --git a/http/src/network/protocol/http/server/storage_base.hpp b/http/src/network/protocol/http/server/storage_base.hpp new file mode 100644 index 000000000..60eb73173 --- /dev/null +++ b/http/src/network/protocol/http/server/storage_base.hpp @@ -0,0 +1,42 @@ +// 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_STORAGE_BASE_HPP_20101210 +#define NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 + +#include + +namespace network { +namespace http { + +struct server_storage_base { + struct no_io_service {}; + struct has_io_service {}; + protected: + template + server_storage_base(ArgPack const& /* args */, no_io_service) + : self_service_(new asio::io_service()), + service_(*self_service_) {} + + template + server_storage_base(ArgPack const& args, has_io_service) + : self_service_(0), + service_(args[_io_service]) {} + + ~server_storage_base() { + delete self_service_; + self_service_ = 0; + } + + asio::io_service* self_service_; + asio::io_service& service_; +}; + +} // namespace http + +} // namespace network + +#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..b8d18725b --- /dev/null +++ b/http/src/network/protocol/http/server/sync_impl.hpp @@ -0,0 +1,50 @@ +// 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..fcded30fe --- /dev/null +++ b/http/src/network/protocol/http/server/sync_impl.ipp @@ -0,0 +1,121 @@ +// 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/http/src/network/protocol/http/server/sync_server.hpp b/http/src/network/protocol/http/server/sync_server.hpp new file mode 100644 index 000000000..19029bf52 --- /dev/null +++ b/http/src/network/protocol/http/server/sync_server.hpp @@ -0,0 +1,142 @@ +// 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 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 + +namespace network { +namespace http { + +template +struct sync_server_base : server_storage_base, socket_options_base { + typedef typename string::type string_type; + typedef basic_request request; + typedef basic_response response; + typedef typename boost::network::http::response_header< + Tag>::type response_header; + + template + sync_server_base(ArgPack const& args) + : server_storage_base( + args, + typename mpl::if_< + is_same::type, + void>, + server_storage_base::no_io_service, + server_storage_base::has_io_service>::type()), + socket_options_base(args), + handler_(args[_handler]), + address_(args[_address]), + port_(args[_port]), + acceptor_(server_storage_base::service_), + new_connection(), + listening_mutex_(), + listening_(false) {} + + void run() { + listen(); + service_.run(); + } + + void stop() { + // stop accepting new connections and let all the existing handlers finish. + system::error_code ignored; + acceptor_.close(ignored); + service_.stop(); + } + + void listen() { + boost::unique_lock listening_lock(listening_mutex_); + if (!listening_) + start_listening(); + } + + private: + + Handler& handler_; + string_type address_, port_; + asio::ip::tcp::acceptor acceptor_; + boost::shared_ptr> new_connection; + boost::mutex listening_mutex_; + bool listening_; + + 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(), + std::bind(&sync_server_base::handle_accept, + this, + asio::placeholders::error)); + } + } + + void start_listening() { + 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) { + NETWORK_MESSAGE("Error resolving address: " << address_ << ':' << port_); + return; + } + tcp::endpoint endpoint = *endpoint_iterator; + acceptor_.open(endpoint.protocol(), error); + if (error) { + NETWORK_MESSAGE("Error opening socket: " << address_ << ':' << port_ + << " -- reason: '" << error + << '\''); + return; + } + socket_options_base::acceptor_options(acceptor_); + acceptor_.bind(endpoint, error); + if (error) { + NETWORK_MESSAGE("Error binding to socket: " << address_ << ':' << port_ + << " -- reason: '" << error + << '\''); + return; + } + acceptor_.listen(tcp::socket::max_connections, error); + if (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(), + std::bind(&sync_server_base::handle_accept, + this, + asio::placeholders::error)); + listening_ = true; + } +}; + +} // namespace http +} // namespace network + +#endif /* NETWORK_PROTOCOL_HTTP_SERVER_SYNC_SERVER_HPP_20101025 */ 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..d90e7ab59 --- /dev/null +++ b/http/src/network/protocol/http/support/is_server.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_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< + Tag, + typename boost::enable_if< + typename Tag::is_server>::type> : boost::mpl::true_ {} +; + +} // namespace http + +} // namespace network + +#endif /* NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 */ diff --git a/http/src/network/version.hpp b/http/src/network/version.hpp new file mode 100644 index 000000000..cbfb75eea --- /dev/null +++ b/http/src/network/version.hpp @@ -0,0 +1,22 @@ +// Copyright Dean Michael Berris 2009. +// Copyright Glyn Matthews 2010, 2013. +// 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..19878d607 --- /dev/null +++ b/http/test/CMakeLists.txt @@ -0,0 +1,99 @@ +# Copyright 2013 Google, Inc. +# Copyright 2010, 2013 Dean Michael Berris +# Copyright (c) Glyn Matthews 2013. +# Distributed under the 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}/config/src + ${CPP-NETLIB_SOURCE_DIR}/message/src + ${CPP-NETLIB_SOURCE_DIR}/uri/src + ${CPP-NETLIB_SOURCE_DIR}/logging/src + ${CPP-NETLIB_SOURCE_DIR}/http/src + ${GTEST_INCLUDE_DIRS} + #${GMOCK_INCLUDE_DIRS} + ${IGLOO_INCLUDE_DIR} + ${CPP-NETLIB_SOURCE_DIR}) + +add_subdirectory(v2) + +if (OPENSSL_FOUND) + include_directories( ${OPENSSL_INCLUDE_DIR} ) + add_definitions(-DNETWORK_ENABLE_HTTPS) +endif() + + +set( CPPNETLIB_LIBRARIES cppnetlib ) +#set( CPPNETLIB_CLIENT_LIBRARIES ${CPPNETLIB_LIBRARIES} ) +set( CPPNETLIB_SERVER_LIBRARIES ${CPPNETLIB_LIBRARIES} ) +if(NOT CPP-NETLIB_BUILD_SINGLE_LIB) + set( CPPNETLIB_LIBRARIES + network-message + network-message-wrappers + network-http-message + network-http-message-wrappers + network-uri + network-constants ) + +# set( CPPNETLIB_CLIENT_LIBRARIES +# ${CPPNETLIB_LIBRARIES} +# network-http-client +# network-http-client-connections ) + + set( CPPNETLIB_SERVER_LIBRARIES + network-http-server ) +endif() + + +if (CPP-NETLIB_BUILD_TESTS) + # These are the internal (simple) tests. + set (MESSAGE_TESTS request_base_test request_test response_test + response_incremental_parser_test) + foreach ( test ${MESSAGE_TESTS} ) + add_executable(cpp-netlib-http-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-${test} + ${Boost_LIBRARIES} + ${GTEST_BOTH_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${CPPNETLIB_LIBRARIES} ) + 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) + +# # HTTP Client tests. +# add_executable(cpp-netlib-http-client_test client_test.cpp) +# target_link_libraries(cpp-netlib-http-client_test +# ${Boost_LIBRARIES} +# ${GTEST_BOTH_LIBRARIES} +# ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} +# ${CMAKE_THREAD_LIBS_INIT} +# ${CPP-NETLIB_LOGGING_LIB} +# ${CPPNETLIB_CLIENT_LIBRARIES} ) +# if (OPENSSL_FOUND) +# target_link_libraries(cpp-netlib-http-client_test ${OPENSSL_LIBRARIES}) +# endif() +# set_target_properties(cpp-netlib-http-client_test +# PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) +# add_test(cpp-netlib-http-client_test +# ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-client_test) +# + # HTTP Server tests + set (SERVER_TESTS server_simple_sessions_test server_dynamic_dispatcher_test + server_default_connection_manager_test server_test) + foreach (test ${SERVER_TESTS}) + add_executable(cpp-netlib-http-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-${test} + ${Boost_LIBRARIES} + ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${CPPNETLIB_SERVER_LIBRARIES} ) + 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/client_test.cpp b/http/test/client_test.cpp new file mode 100644 index 000000000..26a2b611b --- /dev/null +++ b/http/test/client_test.cpp @@ -0,0 +1,125 @@ +// Copyright 2012 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 = network::http; +namespace net = network; + +TEST(client_test, constructor) { + // 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); +} + +TEST(client_test, get_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_); + ASSERT_TRUE(!headers_.empty()); + ASSERT_GT(body(response_).size(), 0); +} + +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; +}; + +TEST(client_test, 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_; + ASSERT_NO_THROW(response = client_.get(request, handler_instance)); + net::headers_wrapper::container_type const& headers_ = headers(response); + ASSERT_TRUE(!boost::empty(headers_)); + ASSERT_EQ(body(response).size(), 0u); + std::string version_, status_message_; + boost::uint16_t status_; + version_ = version(response); + status_ = status(response); + status_message_ = status_message(response); + ASSERT_EQ(version_.substr(0, 7), std::string("HTTP/1.")); + ASSERT_EQ(status_, 200u); + ASSERT_EQ(status_message_, std::string("OK")); + dummy_body = body(response); + } + ASSERT_TRUE(dummy_body == std::string()); +} + +TEST(client_test, http_get_test) { + http::client::request request("http://www.google.com/"); + request << net::header("Connection", "close"); + http::client client_; + http::client::response response; + ASSERT_NO_THROW(response = client_.get(request)); + std::multimap headers_ = net::headers(response); + ASSERT_TRUE(!boost::empty(headers_)); + ASSERT_NO_THROW(ASSERT_TRUE(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_); + ASSERT_EQ(version_.substr(0, 7), "HTTP/1."); + ASSERT_TRUE(status_ == 302u || status_ == 200u); + ASSERT_TRUE(status_message_ == std::string("Found") || + status_message_ == std::string("OK")); +} + +#ifdef NETWORK_ENABLE_HTTPS + +TEST(client_test, https_get_test) { + http::client::request request("https://www.google.com/"); + request << net::header("Connection", "close"); + http::client client_; + http::client::response response; + ASSERT_NO_THROW(response = client_.get(request)); + std::multimap headers_ = net::headers(response); + ASSERT_TRUE(!boost::empty(headers_)); + ASSERT_NO_THROW(ASSERT_TRUE(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_); + ASSERT_EQ(version_.substr(0, 7), "HTTP/1."); + ASSERT_TRUE(status_ == 302u || status_ == 200u); + ASSERT_TRUE(status_message_ == std::string("Found") || + status_message_ == std::string("OK")); +} + +#endif + +TEST(client_test, 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); + std::string temp; + ASSERT_EQ(12121, port_); + ASSERT_THROW(response_ = client_.get(request); temp = body(response_);, + std::exception); +} + diff --git a/http/test/request_base_test.cpp b/http/test/request_base_test.cpp new file mode 100644 index 000000000..fced4c39d --- /dev/null +++ b/http/test/request_base_test.cpp @@ -0,0 +1,67 @@ +// 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 + +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. + } +}; + +TEST(request_test, 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)); + ASSERT_EQ(bytes_read, sizeof(data)); + std::string flattened; + simple.flatten(flattened); + ASSERT_EQ(flattened, output); + ASSERT_EQ(std::string(data, sizeof(data)), output); + simple.clear(); +} + +TEST(request_test, 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)); + ASSERT_EQ(bytes_read, sizeof(quick_brown)); + std::string flattened; + copy.flatten(flattened); + ASSERT_EQ(flattened, output); + ASSERT_EQ(std::string(quick_brown, sizeof(quick_brown)), output); + copy.clear(); + flattened.clear(); + original.flatten(flattened); + ASSERT_EQ(flattened, std::string(quick_brown, sizeof(quick_brown))); +} diff --git a/http/test/request_incremental_parser_test.cpp b/http/test/request_incremental_parser_test.cpp new file mode 100644 index 000000000..d22fa774b --- /dev/null +++ b/http/test/request_incremental_parser_test.cpp @@ -0,0 +1,141 @@ +// 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 +#include +#include + +/** Synopsis + * + * Test for the HTTP Request Incremental Parser + * -------------------------------------------- + * + * In this test we fully intend to specify how an incremental HTTP request + * parser should be used. This follows the HTTP Response Incremental Parser + * example, and models the Incremental Parser Concept. + * + */ + +namespace tags = boost::network::tags; +namespace logic = boost::logic; +namespace fusion = boost::fusion; +using namespace boost::network::http; + +TEST(request_test, incremental_parser_constructor) { + request_parser p; // default constructible +} + +TEST(request_test, incremental_parser_parse_http_method) { + request_parser p; + logic::tribool parsed_ok = false; + typedef request_parser request_parser_type; + typedef boost::iterator_range range_type; + range_type result_range; + + std::string valid_http_method = "GET "; + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::method_done, valid_http_method); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + std::string parsed(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; + + std::string invalid_http_method = "get "; + p.reset(); + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::method_done, invalid_http_method); + ASSERT_EQ(parsed_ok, false); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; +} + +TEST(request_test, incremental_parser_parse_http_uri) { + request_parser p; + logic::tribool parsed_ok = false; + typedef request_parser request_parser_type; + typedef boost::iterator_range range_type; + range_type result_range; + + std::string valid_http_request = "GET / HTTP/1.1\r\n"; + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::uri_done, valid_http_request); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + std::string parsed(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; + + std::string invalid_http_request = "GET /\t HTTP/1.1\r\n"; + p.reset(); + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::uri_done, invalid_http_request); + ASSERT_EQ(parsed_ok, false); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; +} + +TEST(request_test, incremental_parser_parse_http_version) { + request_parser p; + logic::tribool parsed_ok = false; + typedef request_parser request_parser_type; + typedef boost::iterator_range range_type; + range_type result_range; + + std::string valid_http_request = "GET / HTTP/1.1\r\n"; + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::version_done, valid_http_request); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + std::string parsed(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; + + std::string invalid_http_request = "GET / HTTP 1.1\r\n"; + p.reset(); + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::version_done, invalid_http_request); + ASSERT_EQ(parsed_ok, false); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; +} + +TEST(request_test, incremental_parser_parse_http_headers) { + request_parser p; + logic::tribool parsed_ok = false; + typedef request_parser request_parser_type; + typedef boost::iterator_range range_type; + range_type result_range; + + std::string valid_http_request = + "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\n\r\n"; + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::headers_done, valid_http_request); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + std::string parsed(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; + + valid_http_request = + "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\nConnection: close\r\n\r\n"; + p.reset(); + fusion::tie(parsed_ok, result_range) = + p.parse_until(request_parser_type::headers_done, valid_http_request); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " + << std::endl; +} + diff --git a/http/test/request_test.cpp b/http/test/request_test.cpp new file mode 100644 index 000000000..280fef86b --- /dev/null +++ b/http/test/request_test.cpp @@ -0,0 +1,126 @@ +// 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 + +namespace http = network::http; +namespace net = network; + +TEST(message_test, request_construction) { + http::request request; + http::request other(request); +} + +TEST(message_test, request_swap) { + network::uri tmp_uri; + network::uri request_uri("http://www.google.com/"); + network::uri other_uri("http://www.google.it/"); + http::request request(request_uri); + http::request other(other_uri); + + request.swap(other); + + request.get_uri(tmp_uri); + ASSERT_EQ(tmp_uri, other_uri); + other.get_uri(tmp_uri); + ASSERT_EQ(tmp_uri, request_uri); +} + +TEST(message_test, 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. + ASSERT_TRUE(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!"); + ASSERT_TRUE(original != assigned); + // Next we swap the assigned and copy. + std::swap(assigned, copy); + ASSERT_TRUE(copy != assigned); + ASSERT_TRUE(copy != original); + ASSERT_TRUE(original == assigned); +} + +TEST(message_test, request_uri) { + 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); + ASSERT_EQ(std::string("http://www.google.com/"), original); + ASSERT_EQ(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); + ASSERT_EQ(std::string("www.google.com"), host_); + std::string gotten_host(*uri_.host()); + ASSERT_EQ(gotten_host, host_); + ASSERT_EQ(std::string("www.google.com"), gotten_host); +} + +TEST(message_test, request_url_constructor) { + 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); + ASSERT_EQ(original, other_uri); + + // Now test the directives.. + network::uri directive_original = http::uri(request); + ASSERT_EQ(original, directive_original); +} + +TEST(message_test, request_basics) { + 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_); + + ASSERT_EQ(uri_.string(), std::string("http://www.google.com/")); + ASSERT_EQ(source_, std::string("127.0.0.1")); + ASSERT_EQ(destination_, std::string("destination!")); + ASSERT_EQ(body_, std::string("The quick brown fox jumps over the lazy dog!")); + ASSERT_TRUE(!boost::empty(headers_)); +} + +TEST(message_test, linearize_request) { + http::request request("http://www.boost.org/"); + // TODO: Actually specify the expected output. + linearize(request, "GET", 1, 0, std::ostream_iterator(std::cout)); + linearize(request, "GET", 2, 1, std::ostream_iterator(std::cout)); +} diff --git a/http/test/response_incremental_parser_test.cpp b/http/test/response_incremental_parser_test.cpp new file mode 100644 index 000000000..d0fc96be8 --- /dev/null +++ b/http/test/response_incremental_parser_test.cpp @@ -0,0 +1,213 @@ + +// 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) + +#include +#include +#include +#include +#include +#include + +/** Synopsis + * + * Test for HTTP Response Incremental Parser + * ----------------------------------------- + * + * In this test we fully intend to specify how an incremental + * HTTP Response parser should be used. This defines the bare + * minimum implementation for an Incremental Parser concept, + * and shall follow an interface that puts a premium on simplicity. + * + * The motivation for coming up with a re-startable stateful + * incremental parser comes from the requirement in the asynchronous + * HTTP client implementation that allows for parsing an HTTP + * response as the data comes in. By being able to process some + * parts of the message ahead of others, we are allowed to set + * the promise values bound to futures that the users of the client + * would be waiting on. + * + * The basic interface that we're looking for is a means of providing: + * - a range of input + * - a means of resetting the parser's state + * - a means of initializing the parser to a given state + * - a parse_until function that takes a state as parameter and + * a range from which the parser will operate on, returns + * a tuple of a boost::logic::tribool and a resulting range + * + * One of the possible implementations can use the Boost.MSM library + * to create the state machine. The test however does not specify what + * implementation should be used, but rather that the interface and the + * semantics are according to expectations. + * + * Date: September 9, 2010 + * Author: Dean Michael Berris + */ + +namespace logic = boost::logic; +namespace fusion = boost::fusion; +using namespace network::http; + +TEST(response_test, incremental_parser_constructor) { + response_parser p; // default constructible +} + +/** In this test we want to be able to parse incrementally a + * range passed in as input, and specify to the parser that + * it should stop when we reach a certain state. In this case + * we want it to parse until it either finds the HTTP version + * or there is an error encountered. + */ +TEST(response_test, incremental_parser_parse_http_version) { + response_parser p; // default constructible + logic::tribool parsed_ok = false; + typedef response_parser response_parser_type; + typedef boost::iterator_range range_type; + range_type result_range; + + std::string valid_http_version = "HTTP/1.0 "; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_version_done, + valid_http_version); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + std::string parsed(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + p.reset(); + valid_http_version = "HTTP/1.1 "; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_version_done, + valid_http_version); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(!boost::empty(result_range)); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + + p.reset(); + std::string invalid_http_version = "HTTP 1.0"; + parsed_ok = logic::indeterminate; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_version_done, + invalid_http_version); + ASSERT_EQ(parsed_ok, false); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + + p.reset(); + valid_http_version = "HTTP/0.9 "; + parsed_ok = logic::indeterminate; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_version_done, + valid_http_version); + ASSERT_EQ(parsed_ok, true); + parsed.assign(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; +} + +/** In this test we then want to check that we can parse a status + * string right after the version string. We should expect that + * the parser doesn't do any conversions from string to integer + * and outsource that part to the user of the parser. + */ +TEST(response_test, incremental_parser_parse_status) { + typedef response_parser response_parser_type; + typedef boost::iterator_range range_type; + // We want to create a parser that has been initialized to a specific + // state. In this case we assume that the parser has already parsed + // the version part of the HTTP Response. + response_parser_type p(response_parser_type::http_version_done); + + std::string valid_status = "200 "; + logic::tribool parsed_ok; + range_type result_range; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_status_done, valid_status); + ASSERT_EQ(parsed_ok, true); + std::string parsed = std::string(boost::begin(result_range), + boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + + p.reset(response_parser_type::http_version_done); + std::string invalid_status = "200x "; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_status_done, invalid_status); + ASSERT_EQ(parsed_ok, false); + parsed = std::string(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; +} + +/** In this test then we get the rest of the first line of the HTTP + * Response, and treat it as the status message. + */ +TEST(response_test, incremental_parser_parse_status_message) { + typedef response_parser response_parser_type; + typedef boost::iterator_range range_type; + response_parser_type p(response_parser_type::http_status_done); + + std::string valid_status_message = "OK\r\nServer: Foo"; + logic::tribool parsed_ok; + range_type result_range; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_status_message_done, + valid_status_message); + ASSERT_EQ(parsed_ok, true); + std::string parsed = std::string(boost::begin(result_range), + boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + + p.reset(response_parser_type::http_status_done); + valid_status_message = "OK\r\n"; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_status_message_done, + valid_status_message); + ASSERT_EQ(parsed_ok, true); + parsed = std::string(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; + + p.reset(response_parser_type::http_status_done); + valid_status_message = "Internal Server Error\r\n"; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_status_message_done, + valid_status_message); + ASSERT_EQ(parsed_ok, true); + parsed = std::string(boost::begin(result_range), boost::end(result_range)); + std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; +} + +/** This test specifices how one-line-per-header parsing happens incrementally. + */ +TEST(response_test, incremental_parser_parse_header_lines) { + typedef response_parser response_parser_type; + typedef boost::iterator_range range_type; + response_parser_type p(response_parser_type::http_status_message_done); + + std::string valid_headers = + "Server: Foo\r\nContent-Type: application/json\r\n\r\n"; + logic::tribool parsed_ok; + range_type result_range; + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_header_line_done, valid_headers); + ASSERT_EQ(parsed_ok, true); + std::string parsed1 = std::string(boost::begin(result_range), + boost::end(result_range)); + std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; + p.reset(response_parser_type::http_status_message_done); + std::string::const_iterator end = valid_headers.end(); + valid_headers.assign(boost::end(result_range), end); + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_header_line_done, valid_headers); + ASSERT_EQ(parsed_ok, true); + std::string parsed2 = std::string(boost::begin(result_range), + boost::end(result_range)); + std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; + valid_headers.assign(boost::end(result_range), end); + p.reset(response_parser_type::http_status_message_done); + fusion::tie(parsed_ok, result_range) = + p.parse_until(response_parser_type::http_headers_done, valid_headers); + ASSERT_EQ(parsed_ok, true); + ASSERT_TRUE(parsed1 != parsed2); +} + diff --git a/http/test/response_test.cpp b/http/test/response_test.cpp new file mode 100644 index 000000000..d26aec48a --- /dev/null +++ b/http/test/response_test.cpp @@ -0,0 +1,67 @@ +// 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 + +namespace http = network::http; + +TEST(response_test, response_constructor) { http::response created; } + +TEST(response_test, response_value_semantics) { + http::response original; + http::response copy(original); + http::response assigned; + assigned = original; + ASSERT_TRUE(original == assigned); + assigned.set_source("http://www.google.com/"); + ASSERT_TRUE(original != assigned); + std::swap(assigned, copy); + ASSERT_TRUE(assigned == original); + ASSERT_TRUE(copy != original); + ASSERT_TRUE(assigned != copy); + original = copy; + ASSERT_TRUE(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_; +}; + +TEST(response_test, response_setters_and_getters) { + 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); + ASSERT_EQ(source, std::string("http://www.google.com/")); + ASSERT_EQ(destination, std::string("127.0.0.1")); + ASSERT_EQ(body, std::string("Hello, World!")); + ASSERT_EQ(status, 200u); + ASSERT_EQ(version, std::string("HTTP/1.1")); + ASSERT_TRUE(expected_headers == headers); +} diff --git a/http/test/server_default_connection_manager_test.cpp b/http/test/server_default_connection_manager_test.cpp new file mode 100644 index 000000000..3afc57fe8 --- /dev/null +++ b/http/test/server_default_connection_manager_test.cpp @@ -0,0 +1,19 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 http = network::http; + +namespace { + +TEST(default_connection_manager_test, constructor_test) { + http::default_connection_manager manager; + (void)manager; +} + +} // namespace diff --git a/http/test/server_dynamic_dispatcher_test.cpp b/http/test/server_dynamic_dispatcher_test.cpp new file mode 100644 index 000000000..0b358221b --- /dev/null +++ b/http/test/server_dynamic_dispatcher_test.cpp @@ -0,0 +1,27 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 http = ::network::http; + +TEST(server_dynamic_dispatcher, constructor) { + http::dynamic_dispatcher dispatcher; + (void)dispatcher; +} + +TEST(server_dynamic_dispatcher, register_handler) { + http::dynamic_dispatcher dispatcher; + bool called = false; + dispatcher.register_handler("/", [&called](http::session& s, std::shared_ptr c){ called = true; }); + http::session s; + std::shared_ptr c; + dispatcher.dispatch("/", s, c); + EXPECT_EQ(true, called); +} diff --git a/http/test/server_simple_sessions_test.cpp b/http/test/server_simple_sessions_test.cpp new file mode 100644 index 000000000..c0f036e97 --- /dev/null +++ b/http/test/server_simple_sessions_test.cpp @@ -0,0 +1,59 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 http = network::http; +namespace net = network; + +namespace { + +TEST(simple_sessions_test, constructor) { + http::simple_sessions simple_sessions; + (void) simple_sessions; +} + +TEST(simple_sessions_test, lookup) { + http::simple_sessions simple_sessions; + http::session session = simple_sessions.lookup("sessionid"); + (void) session; +} + +TEST(simple_sessions_test, update) { + http::simple_sessions simple_sessions; + { + http::session session = simple_sessions.lookup("sessionid"); + session.set("user", "some-user"); + simple_sessions.update("sessionid", std::move(session)); + } + { + http::session session = simple_sessions.lookup("sessionid"); + EXPECT_EQ("some-user", session["user"]); + } +} + +TEST(simple_sessions_test, threaded_sessions) { + http::simple_sessions simple_sessions; + // Run many asynchronous functions (hoping that there will be many threads + // created) so that we may be able to exercise the atomics and the + // concurrency of the simple session manager. + std::vector> futures; + constexpr size_t max_sessions = 1000; + for (size_t counter = 0; counter < max_sessions; ++counter) { + futures.emplace_back(std::async(std::launch::async, [&]() { + return simple_sessions.lookup("")["id"]; + })); + } + std::set ids; + for (auto &future : futures) + ids.emplace(future.get()); + EXPECT_EQ(max_sessions, ids.size()); +} + +} // namespace diff --git a/http/test/server_test.cpp b/http/test/server_test.cpp new file mode 100644 index 000000000..265e3e347 --- /dev/null +++ b/http/test/server_test.cpp @@ -0,0 +1,20 @@ +// Copyright 2013 (c) Google, Inc. +// Copyright 2013 (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 http = network::http; +namespace net = network; + +namespace { + +TEST(server_test, default_constructor) { + http::server server; + (void) server; +} + +} // namespace diff --git a/http/test/v2/CMakeLists.txt b/http/test/v2/CMakeLists.txt new file mode 100644 index 000000000..68203fd50 --- /dev/null +++ b/http/test/v2/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (C) 2013 by 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) + +add_subdirectory(client) diff --git a/http/test/v2/client/CMakeLists.txt b/http/test/v2/client/CMakeLists.txt new file mode 100644 index 000000000..b2fecb17c --- /dev/null +++ b/http/test/v2/client/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (C) 2013 by 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) + +add_subdirectory(units) +if(NOT CPP-NETLIB_DISABLE_FEATURE_TESTS) + add_subdirectory(features) +endif() diff --git a/http/test/v2/client/features/CMakeLists.txt b/http/test/v2/client/features/CMakeLists.txt new file mode 100644 index 000000000..6c3de153f --- /dev/null +++ b/http/test/v2/client/features/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (C) 2013 by 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) + +set(CPP-NETLIB_CLIENT_TESTS + async_resolver_test + normal_connection_test + http_client_test + ) + +if (OPENSSL_FOUND) + list(APPEND CPP-NETLIB_CLIENT_TESTS ssl_connection_test) +endif() + +foreach(test ${CPP-NETLIB_CLIENT_TESTS}) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + + add_executable(cpp-netlib-http-v2-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-v2-${test} + network-uri + network-http-v2-client + ${Boost_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + set_target_properties(cpp-netlib-http-v2-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-v2-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-v2-${test}) + +endforeach(test) + +if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-http-v2-ssl_connection_test ${OPENSSL_LIBRARIES}) +endif() diff --git a/http/test/v2/client/features/async_resolver_test.cpp b/http/test/v2/client/features/async_resolver_test.cpp new file mode 100644 index 000000000..5824e8885 --- /dev/null +++ b/http/test/v2/client/features/async_resolver_test.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/connection/tcp_resolver.hpp" + +using namespace igloo; +using boost::asio::ip::tcp; +namespace http = network::http::v2; + +Describe(async_resolver) { + + void SetUp() { + // An HTTP server must be running on 127.0.0.1:80 + // maybe execute a script + + io_service_.reset(new boost::asio::io_service); + resolver_.reset(new http::client_connection::tcp_resolver(*io_service_)); + } + + It(resolves_localhost) { + resolver_->async_resolve("127.0.0.1", 80, + [&] (const boost::system::error_code &ec, + http::client_connection::async_resolver::resolver_iterator endpoint_iterator) { + Assert::That(ec, Equals(boost::system::error_code())); + if (endpoint_iterator != + http::client_connection::async_resolver::resolver_iterator()) { + tcp::endpoint endpoint = *endpoint_iterator; + Assert::That(endpoint.address().to_string(), Equals("127.0.0.1")); + Assert::That(endpoint.port(), Equals(80)); + } + }); + io_service_->run_one(); + } + + std::unique_ptr io_service_; + std::unique_ptr resolver_; + +}; + +int +main(int argc, char *argv[]) { + return TestRunner::RunAllTests(argc, const_cast(argv)); +} diff --git a/http/test/v2/client/features/http_client_test.cpp b/http/test/v2/client/features/http_client_test.cpp new file mode 100644 index 000000000..137232956 --- /dev/null +++ b/http/test/v2/client/features/http_client_test.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client.hpp" + +using namespace igloo; +namespace http = network::http::v2; + +Describe(http_client) { + + void SetUp() { + client_.reset(new http::client{}); + } + + void TearDown() { + + } + + It(gets_a_header_response) { + http::request request{network::uri{"http://www.boost.org/"}}; + request + .method(http::method::get) + .path("/LICENSE_1_0.txt") + .version("1.1") + .append_header("Host", "www.boost.org") + .append_header("User-Agent", "cpp-netlib client_test") + .append_header("Connection", "close"); + auto future_response = client_->head(request); + auto response = future_response.get(); + + Assert::That(response.version(), Equals("HTTP/1.1")); + Assert::That(response.status(), Equals(http::status::code::ok)); + Assert::That(response.status_message(), Equals("OK")); + + auto headers = response.headers(); + Assert::That(std::begin(headers)->first, Equals("Date")); + } + + std::unique_ptr client_; + +}; + +int +main(int argc, char *argv[]) { + return TestRunner::RunAllTests(argc, const_cast(argv)); +} diff --git a/http/test/v2/client/features/normal_connection_test.cpp b/http/test/v2/client/features/normal_connection_test.cpp new file mode 100644 index 000000000..644372086 --- /dev/null +++ b/http/test/v2/client/features/normal_connection_test.cpp @@ -0,0 +1,126 @@ +// Copyright (C) 2013 by 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 +#include "network/http/v2/client/connection/normal_connection.hpp" +#include "network/http/v2/client/request.hpp" + +using namespace igloo; +using boost::asio::ip::tcp; +namespace http = network::http::v2; +namespace http_cm = network::http::v2::client_message; + +Describe(normal_http_connection) { + + void SetUp() { + io_service_.reset(new boost::asio::io_service{}); + resolver_.reset(new tcp::resolver(*io_service_)); + connection_.reset(new http::client_connection::normal_connection(*io_service_)); + } + + void TearDown() { + + } + + void ConnectToBoost(boost::system::error_code &ec) { + // Resolve the host. + tcp::resolver::query query("www.boost.org", "80"); + auto it = resolver_->resolve(query, ec); + Assert::That(ec, Equals(boost::system::error_code())); + + // Make sure that the connection is successful. + tcp::endpoint endpoint(it->endpoint()); + connection_->async_connect(endpoint, + "www.boost.org", + [&ec] (const boost::system::error_code &ec_) { + ec = ec_; + }); + } + + void WriteToBoost(boost::system::error_code &ec, + std::size_t &bytes_written) { + // Create an HTTP request. + http_cm::request request; + request + .method(http::method::get) + .path("/LICENSE_1_0.txt") + .version("1.0") + .append_header("Host", "www.boost.org") + .append_header("User-Agent", "cpp-netlib normal_connection_test") + .append_header("Connection", "close"); + + // Write the HTTP request to the socket, sending it to the server. + std::ostream request_stream(&request_); + request_stream << request; + connection_->async_write(request_, + [&bytes_written] (const boost::system::error_code &ec_, + std::size_t bytes_written_) { + Assert::That(ec_, Equals(boost::system::error_code())); + bytes_written = bytes_written_; + }); + } + + void ReadFromBoost(boost::system::error_code &ec, + std::size_t &bytes_read) { + // Read the HTTP response on the socket from the server. + connection_->async_read_until(response_, + "\r\n", + [] (const boost::system::error_code &ec_, std::size_t) { + Assert::That(ec_, Equals(boost::system::error_code())); + }); + } + + It(connects_to_boost) { + boost::system::error_code ec; + + ConnectToBoost(ec); + + io_service_->run_one(); + Assert::That(ec, Equals(boost::system::error_code())); + } + + It(writes_to_boost) { + boost::system::error_code ec; + std::size_t bytes_written = 0; + + ConnectToBoost(ec); + WriteToBoost(ec, bytes_written); + + io_service_->run(); + Assert::That(bytes_written, IsGreaterThan(0)); + } + + It(reads_from_boost) { + boost::system::error_code ec; + std::size_t bytes_written = 0, bytes_read = 0; + + ConnectToBoost(ec); + WriteToBoost(ec, bytes_written); + ReadFromBoost(ec, bytes_read); + + io_service_->run(); + std::istream is(&response_); + std::string status; + std::getline(is, status); + // getline delimits the new line, but not the carriage return + Assert::That(status, Equals("HTTP/1.1 200 OK\r")); + } + + std::unique_ptr io_service_; + std::unique_ptr resolver_; + std::unique_ptr connection_; + + boost::asio::streambuf request_; + boost::asio::streambuf response_; + +}; + +int +main(int argc, char *argv[]) { + return TestRunner::RunAllTests(argc, const_cast(argv)); +} diff --git a/http/test/v2/client/features/ssl_connection_test.cpp b/http/test/v2/client/features/ssl_connection_test.cpp new file mode 100644 index 000000000..231bc8ec5 --- /dev/null +++ b/http/test/v2/client/features/ssl_connection_test.cpp @@ -0,0 +1,40 @@ +// Copyright (C) 2013 by 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 +#include "network/http/v2/client/connection/ssl_connection.hpp" +#include "network/http/v2/client/request.hpp" + +using namespace igloo; +using boost::asio::ip::tcp; +namespace http = network::http::v2; + +Describe(https_connection) { + + void SetUp() { + io_service_.reset(new boost::asio::io_service); + resolver_.reset(new tcp::resolver(*io_service_)); + options_.reset(new http::client_options); + connection_.reset(new http::client_connection::ssl_connection(*io_service_, *options_)); + } + + void TearDown() { + + } + + std::unique_ptr io_service_; + std::unique_ptr resolver_; + std::unique_ptr options_; + std::unique_ptr connection_; + +}; + +int +main(int argc, char *argv[]) { + return TestRunner::RunAllTests(argc, const_cast(argv)); +} diff --git a/http/test/v2/client/units/CMakeLists.txt b/http/test/v2/client/units/CMakeLists.txt new file mode 100644 index 000000000..88acb8ad0 --- /dev/null +++ b/http/test/v2/client/units/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2013 by 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) + +set(CPP-NETLIB_CLIENT_TESTS + client_options_test + client_test + client_resolution_test + request_options_test + byte_source_test + request_test + response_test + ) + +foreach(test ${CPP-NETLIB_CLIENT_TESTS}) + #if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + # set_source_files_properties(${test}.cpp + # PROPERTIES COMPILE_FLAGS "-Wall") + #endif() + + add_executable(cpp-netlib-http-v2-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-v2-${test} + network-uri + network-http-v2-client + ${Boost_LIBRARIES} + #${GMOCK_BOTH_LIBRARIES} + ${GTEST_BOTH_LIBRARIES} + ${ICU_LIBRARIES} ${ICU_I18N_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ) + set_target_properties(cpp-netlib-http-v2-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-v2-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-v2-${test}) + +endforeach(test) diff --git a/boost/network/uri.hpp b/http/test/v2/client/units/byte_source_test.cpp similarity index 52% rename from boost/network/uri.hpp rename to http/test/v2/client/units/byte_source_test.cpp index e9ad1ffea..3c0860ac7 100644 --- a/boost/network/uri.hpp +++ b/http/test/v2/client/units/byte_source_test.cpp @@ -1,12 +1,9 @@ -#ifndef BOOST_NETWORK_URL_HPP_ -#define BOOST_NETWORK_URL_HPP_ - -// Copyright 2009 Dean Michael Berris. +// Copyright (C) 2013 by 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 "network/http/v2/client/request.hpp" -#endif diff --git a/http/test/v2/client/units/client_options_test.cpp b/http/test/v2/client/units/client_options_test.cpp new file mode 100644 index 000000000..9ac2908a9 --- /dev/null +++ b/http/test/v2/client/units/client_options_test.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/client.hpp" + +TEST(client_options_test, default_options_follow_redirects) { + network::http::v2::client_options opts; + ASSERT_FALSE(opts.follow_redirects()); +} + +TEST(client_options_test, default_options_cache_resolved) { + network::http::v2::client_options opts; + ASSERT_FALSE(opts.cache_resolved()); +} + +TEST(client_options_test, default_options_use_proxy) { + network::http::v2::client_options opts; + ASSERT_FALSE(opts.use_proxy()); +} + +TEST(client_options_test, default_options_openssl_certificate_paths) { + network::http::v2::client_options opts; + ASSERT_TRUE(opts.openssl_certificate_paths().empty()); +} + +TEST(client_options_test, default_options_openssl_verify_paths) { + network::http::v2::client_options opts; + ASSERT_TRUE(opts.openssl_verify_paths().empty()); +} + +TEST(client_options_test, always_verify_peer) { + network::http::v2::client_options opts; + ASSERT_FALSE(opts.always_verify_peer()); +} + +TEST(client_options_test, user_agent) { + network::http::v2::client_options opts; + ASSERT_EQ("cpp-netlib/1.0.0a", opts.user_agent()); +} + +TEST(client_options_test, set_option_follow_redirects) { + network::http::v2::client_options opts; + opts.follow_redirects(true); + ASSERT_TRUE(opts.follow_redirects()); +} + +TEST(client_options_test, set_option_cache_resolved) { + network::http::v2::client_options opts; + opts.cache_resolved(true); + ASSERT_TRUE(opts.cache_resolved()); +} + +TEST(client_options_test, set_option_use_proxy) { + network::http::v2::client_options opts; + opts.use_proxy(true); + ASSERT_TRUE(opts.use_proxy()); +} + +TEST(client_options_test, set_option_openssl_certificate_path) { + network::http::v2::client_options opts; + opts.openssl_certificate_path("openssl_certificate"); + ASSERT_EQ(std::vector{"openssl_certificate"}, opts.openssl_certificate_paths()); +} + +TEST(client_options_test, set_option_openssl_verify_path) { + network::http::v2::client_options opts; + opts.openssl_verify_path("openssl_verify"); + ASSERT_EQ(std::vector{"openssl_verify"}, opts.openssl_verify_paths()); +} + +TEST(client_options_test, set_always_verify_peer) { + network::http::v2::client_options opts; + opts.always_verify_peer(true); + ASSERT_TRUE(opts.always_verify_peer()); +} diff --git a/http/test/v2/client/units/client_resolution_test.cpp b/http/test/v2/client/units/client_resolution_test.cpp new file mode 100644 index 000000000..689d0f9e7 --- /dev/null +++ b/http/test/v2/client/units/client_resolution_test.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/connection/async_resolver.hpp" +#include "network/http/v2/client/connection/async_connection.hpp" +#include "network/http/v2/client.hpp" + +namespace http = network::http::v2; +namespace http_cc = http::client_connection; + +class mock_async_resolver : public http_cc::async_resolver { +public: + + mock_async_resolver() { } + + virtual ~mock_async_resolver() noexcept { } + + virtual void async_resolve(const std::string &, std::uint16_t, + resolve_callback callback) { + // arbitrary error code, I just want this to fail + boost::system::error_code ec(boost::asio::error::host_not_found, + boost::asio::error::get_netdb_category()); + callback(ec, resolver_iterator()); + } + + virtual void clear_resolved_cache() { } + +}; + +class fake_async_connection : public http_cc::async_connection { +public: + + fake_async_connection() { } + + virtual ~fake_async_connection() noexcept { } + + virtual void async_connect(const boost::asio::ip::tcp::endpoint &, + const std::string &, + connect_callback) { } + + virtual void async_write(boost::asio::streambuf &, + write_callback) { } + + virtual void async_read_until(boost::asio::streambuf &, + const std::string &, + read_callback) { } + + virtual void async_read(boost::asio::streambuf &, + read_callback) { } + + virtual void disconnect() { } + + virtual void cancel() { } + +}; + +class client_resolution_test : public ::testing::Test { + +protected: + + void SetUp() { + resolver_.reset(new mock_async_resolver{}); + connection_.reset(new fake_async_connection{}); + client_.reset(new http::client{std::move(resolver_), std::move(connection_)}); + } + + void TearDown() { + + } + + std::unique_ptr resolver_; + std::unique_ptr connection_; + std::unique_ptr client_; + +}; + +TEST_F(client_resolution_test, host_not_found) { + http::request request; + request + .method(http::method::get) + .path("/LICENSE_1_0.txt") + .version("1.1") + .append_header("Host", "www.boost.org") + .append_header("User-Agent", "cpp-netlib client_test") + .append_header("Connection", "close"); + auto future_response = client_->head(request); + ASSERT_THROW(future_response.get(), std::system_error); +} diff --git a/http/test/v2/client/units/client_test.cpp b/http/test/v2/client/units/client_test.cpp new file mode 100644 index 000000000..2417fe8ab --- /dev/null +++ b/http/test/v2/client/units/client_test.cpp @@ -0,0 +1,7 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/client.hpp" diff --git a/http/test/v2/client/units/request_options_test.cpp b/http/test/v2/client/units/request_options_test.cpp new file mode 100644 index 000000000..9fb0d9aab --- /dev/null +++ b/http/test/v2/client/units/request_options_test.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2013, 2014 by 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 "network/http/v2/client/request.hpp" + +namespace http_cm = network::http::v2::client_message; + +TEST(request_options_test, default_options_resolve_timeout) { + http_cm::request_options opts; + ASSERT_EQ(30000, opts.resolve_timeout()); +} + +TEST(request_options_test, default_options_read_timeout) { + http_cm::request_options opts; + ASSERT_EQ(30000, opts.read_timeout()); +} + +TEST(request_options_test, default_options_total_timeout) { + http_cm::request_options opts; + ASSERT_EQ(30000, opts.total_timeout()); +} + +TEST(request_options_test, set_resolve_timeout) { + http_cm::request_options opts; + opts.resolve_timeout(10000); + ASSERT_EQ(10000, opts.resolve_timeout()); +} + +TEST(request_options_test, set_max_redirects) { + http_cm::request_options opts; + opts.max_redirects(5); + ASSERT_EQ(5, opts.max_redirects()); +} + +TEST(request_options_test, set_progress_handler) { + std::uint64_t bytes = 0; + http_cm::request_options opts; + opts.progress([&bytes] (http_cm::transfer_direction direction, std::uint64_t bytes_) { + bytes = bytes_; + }); + opts.progress()(http_cm::transfer_direction::bytes_written, 42); + ASSERT_EQ(42, bytes); +} diff --git a/http/test/v2/client/units/request_test.cpp b/http/test/v2/client/units/request_test.cpp new file mode 100644 index 000000000..573305459 --- /dev/null +++ b/http/test/v2/client/units/request_test.cpp @@ -0,0 +1,221 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/request.hpp" + +namespace http = network::http::v2; +namespace http_cm = http::client_message; + + +TEST(request_test, constructor_url) { + ASSERT_NO_THROW(http_cm::request{network::uri{"http://www.example.com/"}}); +} + +TEST(request_test, constructor_https_url) { + ASSERT_NO_THROW(http_cm::request{network::uri{"https://www.example.com/"}}); +} + +TEST(request_test, constructor_invalid_url) { + ASSERT_THROW(http_cm::request{network::uri{"mailto:john.doe@example.com"}}, + http::invalid_url); +} + +TEST(request_test, get_url) { + http_cm::request instance{network::uri{"http://www.example.com/"}}; + ASSERT_EQ("http://www.example.com/", instance.url()); +} + +TEST(request_test, constructor_empty_uri) { + ASSERT_THROW(http_cm::request{network::uri{}}, + http::invalid_url); +} + +TEST(request_test, constructor_uri_no_scheme) { + network::uri_builder builder; + builder.host("www.example.com").path("/"); + ASSERT_THROW(http_cm::request{builder.uri()}, + http::invalid_url); +} + +TEST(request_test, stream) { + http_cm::request instance{network::uri{"http://www.example.com/"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + std::ostringstream oss; + oss << instance; + ASSERT_EQ("GET / HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: close\r\n" + "User-Agent: request_test\r\n\r\n", oss.str()); +} + +TEST(request_test, stream_2) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + std::ostringstream oss; + oss << instance; + ASSERT_EQ("GET /path/to/resource/index.html HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Connection: close\r\n" + "User-Agent: request_test\r\n\r\n", oss.str()); +} + +TEST(request_test, read_path) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + ASSERT_EQ("/path/to/resource/index.html", instance.path()); +} + +TEST(request_test, read_full_request) { + http_cm::request instance; + instance + .method(http::method::get) + .path("/path/to/resource/index.html") + .version("1.1") + .append_header("Host", "www.example.com") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + + ASSERT_EQ(http::method::get, instance.method()); + ASSERT_EQ("/path/to/resource/index.html", instance.path()); + ASSERT_EQ("1.1", instance.version()); + + auto headers = instance.headers(); + auto headers_it = std::begin(headers); + ASSERT_EQ("Host", headers_it->first); + ASSERT_EQ("www.example.com", headers_it->second); + ++headers_it; + ASSERT_EQ("Connection", headers_it->first); + ASSERT_EQ("close", headers_it->second); + ++headers_it; + ASSERT_EQ("User-Agent", headers_it->first); + ASSERT_EQ("request_test", headers_it->second); +} + +TEST(request_test, read_headers) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + + auto headers = instance.headers(); + auto headers_it = std::begin(headers); + ASSERT_EQ("Host", headers_it->first); + ASSERT_EQ("www.example.com", headers_it->second); + ++headers_it; + ASSERT_EQ("Connection", headers_it->first); + ASSERT_EQ("close", headers_it->second); + ++headers_it; + ASSERT_EQ("User-Agent", headers_it->first); + ASSERT_EQ("request_test", headers_it->second); +} + +TEST(request_test, clear_headers) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + instance.clear_headers(); + auto headers = instance.headers(); + ASSERT_TRUE(std::begin(headers) == std::end(headers)); +} + +TEST(request_test, remove_headers) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test"); + instance.remove_header("User-Agent"); + + auto headers = instance.headers(); + auto headers_it = std::begin(headers); + + ASSERT_EQ("Host", headers_it->first); + ASSERT_EQ("www.example.com", headers_it->second); + ++headers_it; + ASSERT_EQ("Connection", headers_it->first); + ASSERT_EQ("close", headers_it->second); + ++headers_it; + ASSERT_TRUE(headers_it == std::end(headers)); +} + +TEST(request_test, remove_duplicate_headers) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test") + .append_header("User-Agent", "request_test_2") + .remove_header("User-Agent"); + + auto headers = instance.headers(); + auto headers_it = std::begin(headers); + + ASSERT_EQ("Host", headers_it->first); + ASSERT_EQ("www.example.com", headers_it->second); + ++headers_it; + ASSERT_EQ("Connection", headers_it->first); + ASSERT_EQ("close", headers_it->second); + ++headers_it; + ASSERT_TRUE(headers_it == std::end(headers)); +} + +TEST(request_test, get_header) { + http_cm::request instance{network::uri{"http://www.example.com/path/to/resource/index.html"}}; + instance + .method(http::method::get) + .version("1.1") + .append_header("Connection", "close") + .append_header("User-Agent", "request_test") + ; + + auto header = instance.header("User-Agent"); + ASSERT_TRUE(static_cast(header)); + ASSERT_EQ("request_test", *header); +} + +TEST(request_test, is_not_https) { + http_cm::request instance{network::uri{"http://www.example.com/"}}; + ASSERT_FALSE(instance.is_https()); +} + +TEST(request_test, is_https) { + http_cm::request instance{network::uri{"https://www.example.com/"}}; + ASSERT_TRUE(instance.is_https()); +} + +TEST(request_test, path) { + http_cm::request instance{network::uri{"http://www.example.com/path/"}}; + ASSERT_EQ("/path/", instance.path()); +} + +TEST(request_test, path_with_query) { + http_cm::request instance{network::uri{"http://www.example.com/path/?foo=bar"}}; + ASSERT_EQ("/path/?foo=bar", instance.path()); +} + +TEST(request_test, path_with_fragment) { + http_cm::request instance{network::uri{"http://www.example.com/path/#fragment"}}; + ASSERT_EQ("/path/#fragment", instance.path()); +} + +TEST(request_test, path_with_query_and_fragment) { + http_cm::request instance{network::uri{"http://www.example.com/path/?foo=bar#fragment"}}; + ASSERT_EQ("/path/?foo=bar#fragment", instance.path()); +} diff --git a/http/test/v2/client/units/response_test.cpp b/http/test/v2/client/units/response_test.cpp new file mode 100644 index 000000000..fd50aa0e9 --- /dev/null +++ b/http/test/v2/client/units/response_test.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2013 by 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 "network/http/v2/client/response.hpp" + +namespace http = network::http::v2; +namespace http_cm = network::http::v2::client_message; + +TEST(response_test, constructor) { + ASSERT_NO_THROW(http_cm::response{}); +} 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/Jamfile.v2 b/libs/network/example/Jamfile.v2 deleted file mode 100644 index 5bca45589..000000000 --- a/libs/network/example/Jamfile.v2 +++ /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) - -project network_test : - requirements - ../../../ - /boost//system - /boost//date_time - /boost//regex - /boost//thread - /boost//program_options - gcc:-lpthread - gcc:-lssl - msvc:BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN - msvc:WIN32_LEAN_AND_MEAN - static - 256 - debug:BOOST_NETWORK_DEBUG - ; - -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 ; - -exe atom_reader : atom/main.cpp atom/atom.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; - -exe rss_reader : rss/main.cpp rss/rss.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; - -exe twitter_search : twitter/search.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; - -exe hello_world_server : http/hello_world_server.cpp /cpp-netlib//cppnetlib-server-parsers ; - -exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri ; - -exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri ; - -exe fileserver : http/fileserver.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/example/atom/atom.cpp b/libs/network/example/atom/atom.cpp deleted file mode 100644 index 7555956b6..000000000 --- a/libs/network/example/atom/atom.cpp +++ /dev/null @@ -1,97 +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 "atom.hpp" -#include "../rapidxml/rapidxml.hpp" -#include -#include - - -namespace boost { -namespace network { -namespace atom { -feed::feed(const http::client::response &response) { - std::string response_body = body(response); - rapidxml::xml_document<> doc; - doc.parse<0>(const_cast(response_body.c_str())); - - rapidxml::xml_node<> *feed = doc.first_node("feed"); - if (!feed) { - throw std::runtime_error("Invalid atom feed."); - } - - rapidxml::xml_node<> *title = feed->first_node("title"); - if (title) { - title_ = title->first_node()->value(); - } - - rapidxml::xml_node<> *subtitle = feed->first_node("subtitle"); - if (subtitle) { - subtitle_ = subtitle->first_node()->value(); - } - - rapidxml::xml_node<> *id = feed->first_node("id"); - if (id) { - id_ = id->first_node()->value(); - } - - rapidxml::xml_node<> *updated = feed->first_node("updated"); - if (updated) { - updated_ = updated->first_node()->value(); - } - - rapidxml::xml_node<> *author = feed->first_node("author"); - if (author) { - rapidxml::xml_node<> *name = author->first_node("name"); - rapidxml::xml_node<> *email = author->first_node("email"); - if (name && email) { - author_ = atom::author(name->first_node()->value(), email->first_node()->value()); - } - else if (name) { - author_ = atom::author(name->first_node()->value()); - } - } - - rapidxml::xml_node<> *entry = feed->first_node("entry"); - while (entry) { - entries_.push_back(atom::entry()); - - rapidxml::xml_node<> *title = entry->first_node("title"); - if (title) { - entries_.back().set_title(title->first_node()->value()); - } - - rapidxml::xml_node<> *id = entry->first_node("id"); - if (id) { - entries_.back().set_id(id->first_node()->value()); - } - - rapidxml::xml_node<> *published = entry->first_node("published"); - if (published) { - entries_.back().set_published(published->first_node()->value()); - } - - rapidxml::xml_node<> *updated = entry->first_node("updated"); - if (updated) { - entries_.back().set_updated(updated->first_node()->value()); - } - - rapidxml::xml_node<> *summary = entry->first_node("summary"); - if (summary) { - entries_.back().set_summary(summary->first_node()->value()); - } - - rapidxml::xml_node<> *content = entry->first_node("content"); - if (content) { - entries_.back().set_content(content->first_node()->value()); - } - - entry = entry->next_sibling(); - } -} -} // namespace atom -} // namespace network -} // namespace boost diff --git a/libs/network/example/atom/atom.hpp b/libs/network/example/atom/atom.hpp deleted file mode 100644 index b19e4146a..000000000 --- a/libs/network/example/atom/atom.hpp +++ /dev/null @@ -1,177 +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 ___ATOM_INC__ -# define ___ATOM_INC__ - - -# include -# include -# include - - -namespace boost { -namespace network { -namespace atom { -class entry { - -public: - - void set_title(const std::string &title) { - title_ = title; - } - - std::string title() const { - return title_; - } - - void set_id(const std::string &id) { - id_ = id; - } - - std::string id() const { - return id_; - } - - void set_published(const std::string &published) { - published_ = published; - } - - std::string published() const { - return published_; - } - - void set_updated(const std::string &updated) { - updated_ = updated; - } - - std::string updated() const { - return updated_; - } - - void set_summary(const std::string &summary) { - summary_ = summary; - } - - std::string summary() const { - return summary_; - } - - void set_content(const std::string &content) { - content_ = content; - } - - std::string content() const { - return content_; - } - -private: - - std::string title_; - std::string id_; - std::string published_; - std::string updated_; - std::string summary_; - std::string content_; - -}; - -class author { - -public: - - author() { - - } - - author(const std::string &name) - : name_(name) { - - } - - author(const std::string &name, const std::string &email) - : name_(name), email_(email) { - - } - - std::string name() const { - return name_; - } - - std::string email() const { - return email_; - } - -private: - - std::string name_; - std::string email_; - -}; - -class feed { - -public: - typedef entry value_type; - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - - feed(const http::client::response &response); - - std::string title() const { - return title_; - } - - std::string subtitle() const { - return subtitle_; - } - - std::string id() const { - return id_; - } - - std::string updated() const { - return updated_; - } - - atom::author author() const { - return author_; - } - - unsigned int entry_count() const { - return entries_.size(); - } - - iterator begin() { - return entries_.begin(); - } - - iterator end() { - return entries_.end(); - } - - const_iterator begin() const { - return entries_.begin(); - } - - const_iterator end() const { - return entries_.end(); - } - -private: - - std::string title_; - std::string subtitle_; - std::string id_; - std::string updated_; - atom::author author_; - std::vector entries_; - -}; -} // namespace atom -} // namespace network -} // namespace boost - -#endif // ___ATOM_INC__ diff --git a/libs/network/example/atom/main.cpp b/libs/network/example/atom/main.cpp deleted file mode 100644 index b419db720..000000000 --- a/libs/network/example/atom/main.cpp +++ /dev/null @@ -1,37 +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 "atom.hpp" -#include -#include -#include - -int main(int argc, char * argv[]) { - using namespace boost::network; - - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - - try { - http::client client; - http::client::request request(argv[1]); - request << header("Connection", "close"); - http::client::response response = client.get(request); - atom::feed feed(response); - - std::cout << "Feed: " << feed.title() << " (" << feed.subtitle() << ")" << std::endl; - BOOST_FOREACH(const atom::entry &entry, feed) { - std::cout << entry.title() << " (" << entry.published() << ")" << std::endl; - } - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/libs/network/example/http/fileserver.cpp b/libs/network/example/http/fileserver.cpp deleted file mode 100644 index 076680385..000000000 --- a/libs/network/example/http/fileserver.cpp +++ /dev/null @@ -1,185 +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 -#include -#include -#include -#include -#include -#include -#include -#include - -namespace http = boost::network::http; -namespace utils = boost::network::utils; - -struct file_server; -typedef http::async_server server; - -struct file_cache { - - typedef std::map > region_map; - typedef std::map > meta_map; - - std::string doc_root_; - region_map regions; - meta_map file_headers; - boost::shared_mutex cache_mutex; - - explicit file_cache(std::string const & doc_root) - : doc_root_(doc_root) {} - - ~file_cache() throw () { - BOOST_FOREACH(region_map::value_type const & region, regions) { - munmap(region.second.first, region.second.second); - } - } - - bool has(std::string const & path) { - boost::shared_lock lock(cache_mutex); - return regions.find(doc_root_ + path) != regions.end(); - } - - bool add(std::string const & path) { - boost::upgrade_lock lock(cache_mutex); - std::string real_filename = doc_root_+path; - if (regions.find(real_filename) != regions.end()) return true; -#ifdef O_NOATIME - int fd = open(real_filename.c_str(), O_RDONLY|O_NOATIME|O_NONBLOCK); -#else - int fd = open(real_filename.c_str(), O_RDONLY|O_NONBLOCK); -#endif - if (fd == -1) return false; - std::size_t size = lseek(fd, 0, SEEK_END); - void * region = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (region == MAP_FAILED) { close(fd); return false; } - - boost::upgrade_to_unique_lock unique_lock(lock); - regions.insert(std::make_pair(real_filename, std::make_pair(region, size))); - static server::response_header common_headers[] = { - {"Connection","close"} - ,{"Content-Type", "x-application/octet-stream"} - ,{"Content-Length", "0"} - }; - std::vector headers(common_headers, common_headers+3); - headers[2].value = boost::lexical_cast(size); - file_headers.insert(std::make_pair(real_filename, headers)); - return true; - } - - std::pair get(std::string const & path) { - boost::shared_lock lock(cache_mutex); - region_map::const_iterator region = regions.find(doc_root_+path); - if (region != regions.end()) return region->second; - else return std::pair(0,0); - } - - boost::iterator_range::iterator> meta(std::string const & path) { - boost::shared_lock lock(cache_mutex); - static std::vector empty_vector; - meta_map::iterator headers = file_headers.find(doc_root_+path); - if (headers != file_headers.end()) { - std::vector::iterator begin = headers->second.begin() - , end = headers->second.end(); - return boost::make_iterator_range(begin,end); - } else return boost::make_iterator_range(empty_vector); - } - -}; - -struct connection_handler : boost::enable_shared_from_this { - explicit connection_handler(file_cache & cache) - : file_cache_(cache) {} - - void operator()(std::string const & path, server::connection_ptr connection, bool serve_body) { - bool ok = file_cache_.has(path); - if (!ok) ok = file_cache_.add(path); - if (ok) { - send_headers(file_cache_.meta(path), connection); - if (serve_body) send_file(file_cache_.get(path), 0, connection); - } else { - not_found(path, connection); - } - } - - void not_found(std::string const & path, server::connection_ptr connection) { - static server::response_header headers[] = { - {"Connection","close"} - ,{"Content-Type", "text/plain"} - }; - connection->set_status(server::connection::not_found); - connection->set_headers(boost::make_iterator_range(headers, headers+2)); - connection->write("File Not Found!"); - } - - template - void send_headers(Range const & headers, server::connection_ptr connection) { - connection->set_status(server::connection::ok); - connection->set_headers(headers); - } - - void send_file(std::pair mmaped_region, off_t offset, server::connection_ptr connection) { - // chunk it up page by page - std::size_t adjusted_offset = offset+4096; - off_t rightmost_bound = std::min(mmaped_region.second, adjusted_offset); - connection->write( - boost::asio::const_buffers_1( - static_cast(mmaped_region.first) + offset, - rightmost_bound - ) - , boost::bind( - &connection_handler::handle_chunk, - connection_handler::shared_from_this(), - mmaped_region, - rightmost_bound, - connection, - _1 - ) - ); - } - - void handle_chunk(std::pair mmaped_region, off_t offset, server::connection_ptr connection, boost::system::error_code const & ec) { - if (!ec && offset < mmaped_region.second) send_file(mmaped_region, offset, connection); - } - - file_cache & file_cache_; -}; - -struct file_server { - explicit file_server(file_cache & cache) - : cache_(cache) {} - - void operator()( - server::request const & request, - server::connection_ptr connection - ) { - if (request.method == "HEAD") { - boost::shared_ptr h(new connection_handler(cache_)); - (*h)(request.destination, connection, false); - } else if (request.method == "GET") { - boost::shared_ptr h(new connection_handler(cache_)); - (*h)(request.destination, connection, true); - } else { - static server::response_header error_headers[] = { - { "Connection", "close" } - }; - connection->set_status(server::connection::not_supported); - connection->set_headers(boost::make_iterator_range(error_headers, error_headers+1)); - connection->write("Method not supported."); - } - } - - file_cache & cache_; -}; - -int main(int argc, char * argv[]) { - file_cache cache("."); - file_server handler(cache); - utils::thread_pool thread_pool(4); - server instance("0.0.0.0", "8000", handler, thread_pool); - instance.run(); - return 0; -} diff --git a/libs/network/example/http/hello_world_client.cpp b/libs/network/example/http/hello_world_client.cpp deleted file mode 100644 index 333c389d9..000000000 --- a/libs/network/example/http/hello_world_client.cpp +++ /dev/null @@ -1,47 +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) - - -//[ hello_world_client_main -/*` - This is a part of the 'Hello World' example. We create a client - object and make a single HTTP request. If we use make this request - to the `hello_world_server`, then the output is simply "Hello, - World!". - */ -#include -#include - - -namespace http = boost::network::http; - - -int -main(int argc, char *argv[]) { - - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " url" << std::endl; - return 1; - } - - try { - /*<< Creates the client. >>*/ - http::client client; - /*<< Creates a request using a URI supplied on the command - line. >>*/ - http::client::request request(argv[1]); - /*<< Gets a response from the HTTP server. >>*/ - http::client::response response = client.get(request); - /*<< Prints the response body to the console. >>*/ - std::cout << body(response) << std::endl; - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - return 1; - } - - return 0; -} -//] diff --git a/libs/network/example/http/hello_world_server.cpp b/libs/network/example/http/hello_world_server.cpp deleted file mode 100644 index e6ec08bcf..000000000 --- a/libs/network/example/http/hello_world_server.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2009 (c) Tarro, Inc. -// Copyright 2009 (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) -// - -//[ hello_world_server_main -/*` - This is a part of the 'Hello World' example. It's used to - 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 - - -namespace http = boost::network::http; - - -/*<< Defines the server. >>*/ -struct hello_world; -typedef http::server server; - -/*<< Defines the request handler. It's a class that defines two - functions, `operator()` and `log()` >>*/ -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()); - } - /*<< It's necessary to define a log function, but it's ignored in - this example. >>*/ - void log(...) { - // do nothing - } -}; - - -int main(int argc, char * argv[]) { - - if (argc != 3) { - std::cerr << "Usage: " << argv[0] << " address port" << std::endl; - return 1; - } - - try { - /*<< Creates the request handler. >>*/ - hello_world handler; - /*<< Creates the server. >>*/ - server server_(argv[1], argv[2], handler); - /*<< Runs the server. >>*/ - server_.run(); - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - return 1; - } - - return 0; -} -//] diff --git a/libs/network/example/http/one_liner.cpp b/libs/network/example/http/one_liner.cpp deleted file mode 100644 index 86a98d763..000000000 --- a/libs/network/example/http/one_liner.cpp +++ /dev/null @@ -1,25 +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) - - -//[ http_one_liner_main -/*` - - */ -#include - - -using namespace std; -using namespace boost::network; -using namespace boost::network::http; - - -int main(int argc, const char *argv[]) { - /*<< The client sends an HTTP request to the server, and the output - is printed to the console. >>*/ - cout << body(client().get(client::request("http://www.boost.org/"))); - return 0; -} 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/rapidxml/license.txt b/libs/network/example/rapidxml/license.txt deleted file mode 100644 index 140983180..000000000 --- a/libs/network/example/rapidxml/license.txt +++ /dev/null @@ -1,52 +0,0 @@ -Use of this software is granted under one of the following two licenses, -to be chosen freely by the user. - -1. Boost Software License - Version 1.0 - August 17th, 2003 -=============================================================================== - -Copyright (c) 2006, 2007 Marcin Kalicinski - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - -2. The MIT License -=============================================================================== - -Copyright (c) 2006, 2007 Marcin Kalicinski - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/libs/network/example/rapidxml/manual.html b/libs/network/example/rapidxml/manual.html deleted file mode 100644 index 2c422703f..000000000 --- a/libs/network/example/rapidxml/manual.html +++ /dev/null @@ -1,406 +0,0 @@ -

RAPIDXML Manual

Version 1.13

Copyright (C) 2006, 2009 Marcin Kalicinski
See accompanying file license.txt for license information.

Table of Contents

1. What is RapidXml?
1.1 Dependencies And Compatibility
1.2 Character Types And Encodings
1.3 Error Handling
1.4 Memory Allocation
1.5 W3C Compliance
1.6 API Design
1.7 Reliability
1.8 Acknowledgements
2. Two Minute Tutorial
2.1 Parsing
2.2 Accessing The DOM Tree
2.3 Modifying The DOM Tree
2.4 Printing XML
3. Differences From Regular XML Parsers
3.1 Lifetime Of Source Text
3.2 Ownership Of Strings
3.3 Destructive Vs Non-Destructive Mode
4. Performance
4.1 Comparison With Other Parsers
5. Reference

1. What is RapidXml?

RapidXml is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of strlen() function executed on the same data.

- Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy rapidxml.hpp file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header rapidxml_print.hpp.

1.1 Dependencies And Compatibility

RapidXml has no dependencies other than a very small subset of standard C++ library (<cassert>, <cstdlib>, <new> and <exception>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.

1.2 Character Types And Encodings

RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse wchar_t strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag).

- Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: &apos; &amp; &quot; &lt; &gt; &#...; Other character references are not expanded.

1.3 Error Handling

By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See parse_error class and parse_error_handler() function for more information.

1.4 Memory Allocation

RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using new operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of memory_pool::set_allocator() function. See class memory_pool for more information.

1.5 W3C Compliance

RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.

1.6 API Design

RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: rapidxml_utils.hpp and rapidxml_print.hpp. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).

1.7 Reliability

RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely.

- Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents.

- Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.

1.8 Acknowledgements

I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

2. Two Minute Tutorial

2.1 Parsing

The following code causes RapidXml to parse a zero-terminated string named text:
using namespace rapidxml;
-xml_document<> doc;    // character type defaults to char
-doc.parse<0>(text);    // 0 means default parse flags
-
doc object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace rapidxml, users must either bring contents of this namespace into scope, or fully qualify all the names. Class xml_document represents a root of the DOM hierarchy. By means of public inheritance, it is also an xml_node and a memory_pool. Template parameter of xml_document::parse() function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.

2.2 Accessing The DOM Tree

To access the DOM tree, use methods of xml_node and xml_attribute classes:
cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
-xml_node<> *node = doc.first_node("foobar");
-cout << "Node foobar has value " << node->value() << "\n";
-for (xml_attribute<> *attr = node->first_attribute();
-     attr; attr = attr->next_attribute())
-{
-    cout << "Node foobar has attribute " << attr->name() << " ";
-    cout << "with value " << attr->value() << "\n";
-}
-

2.3 Modifying The DOM Tree

DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website:
xml_document<> doc;
-xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
-doc.append_node(node);
-xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
-node->append_attribute(attr);
-
One quirk is that nodes and attributes do not own the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the xml_document memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses memory_pool::allocate_string() function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node:
xml_document<> doc;
-char *node_name = doc.allocate_string(name);        // Allocate string and copy name into it
-xml_node<> *node = doc.allocate_node(node_element, node_name);  // Set node name to node_name
-
Check Reference section for description of the entire interface.

2.4 Printing XML

You can print xml_document and xml_node objects into an XML string. Use print() function or operator <<, which are defined in rapidxml_print.hpp header.
using namespace rapidxml;
-xml_document<> doc;    // character type defaults to char
-// ... some code to fill the document
-
-// Print to stream using operator <<
-std::cout << doc;   
-
-// Print to stream using print function, specifying printing flags
-print(std::cout, doc, 0);   // 0 means default printing flags
-
-// Print to string using output iterator
-std::string s;
-print(std::back_inserter(s), doc, 0);
-
-// Print to memory buffer using output iterator
-char buffer[4096];                      // You are responsible for making the buffer large enough!
-char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
-*end = 0;                               // Add string terminator after XML
-

3. Differences From Regular XML Parsers

RapidXml is an in-situ parser, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the source text in the DOM hierarchy.

3.1 Lifetime Of Source Text

In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml.

- In many cases however, these are not serious issues.

3.2 Ownership Of Strings

Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using xml_base::name(const Ch *) or xml_base::value(const Ch *) functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from memory_pool owned by the document. Use memory_pool::allocate_string() function for this purpose.

3.3 Destructive Vs Non-Destructive Mode

By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.

- In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:

4. Performance

RapidXml achieves its speed through use of several techniques:
  • In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.
  • Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.
  • Extensive use of lookup tables for parsing.
  • Hand-tuned C++ with profiling done on several most popular CPUs.
This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.

4.1 Comparison With Other Parsers

The table below compares speed of RapidXml to some other parsers, and to strlen() function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.
  • The test file is a real-world, 50kB large, moderately dense XML file.
  • All timing is done by using RDTSC instruction present in Pentium-compatible CPUs.
  • No profile-guided optimizations are used.
  • All parsers are running in their fastest modes.
  • The results are given in CPU cycles per character, so frequency of CPUs is irrelevant.
  • The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc.
  • A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results.
Platform
Compiler
strlen() RapidXml pugixml 0.3 pugxml TinyXml
Pentium 4
MSVC 8.0
2.5
5.4
7.0
61.7
298.8
Pentium 4
gcc 4.1.1
0.8
6.1
9.5
67.0
413.2
Core 2
MSVC 8.0
1.0
4.5
5.0
24.6
154.8
Core 2
gcc 4.1.1
0.6
4.6
5.4
28.3
229.3
Athlon XP
MSVC 8.0
3.1
7.7
8.0
25.5
182.6
Athlon XP
gcc 4.1.1
0.9
8.2
9.2
33.7
265.2
Pentium 3
MSVC 8.0
2.0
6.3
7.0
30.9
211.9
Pentium 3
gcc 4.1.1
1.0
6.7
8.9
35.3
316.0
(*) All results are in CPU cycles per character of source text

5. Reference

This section lists all classes, functions, constants etc. and describes them in detail.
class - template - rapidxml::memory_pool
- constructor - memory_pool()
- destructor - ~memory_pool()
function allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
function allocate_string(const Ch *source=0, std::size_t size=0)
function clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)
function clear()
function set_allocator(alloc_func *af, free_func *ff)

class rapidxml::parse_error
- constructor - parse_error(const char *what, void *where)
function what() const
function where() const

class - template - rapidxml::xml_attribute
- constructor - xml_attribute()
function document() const
function previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const

class - template - rapidxml::xml_base
- constructor - xml_base()
function name() const
function name_size() const
function value() const
function value_size() const
function name(const Ch *name, std::size_t size)
function name(const Ch *name)
function value(const Ch *value, std::size_t size)
function value(const Ch *value)
function parent() const

class - template - rapidxml::xml_document
- constructor - xml_document()
function parse(Ch *text)
function clear()

class - template - rapidxml::xml_node
- constructor - xml_node(node_type type)
function type() const
function document() const
function first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
function type(node_type type)
function prepend_node(xml_node< Ch > *child)
function append_node(xml_node< Ch > *child)
function insert_node(xml_node< Ch > *where, xml_node< Ch > *child)
function remove_first_node()
function remove_last_node()
function remove_node(xml_node< Ch > *where)
function remove_all_nodes()
function prepend_attribute(xml_attribute< Ch > *attribute)
function append_attribute(xml_attribute< Ch > *attribute)
function insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)
function remove_first_attribute()
function remove_last_attribute()
function remove_attribute(xml_attribute< Ch > *where)
function remove_all_attributes()

namespace rapidxml
enum node_type
function parse_error_handler(const char *what, void *where)
function print(OutIt out, const xml_node< Ch > &node, int flags=0)
function print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0)
function operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
- constant - parse_no_data_nodes
- constant - parse_no_element_values
- constant - parse_no_string_terminators
- constant - parse_no_entity_translation
- constant - parse_no_utf8
- constant - parse_declaration_node
- constant - parse_comment_nodes
- constant - parse_doctype_node
- constant - parse_pi_nodes
- constant - parse_validate_closing_tags
- constant - parse_trim_whitespace
- constant - parse_normalize_whitespace
- constant - parse_default
- constant - parse_non_destructive
- constant - parse_fastest
- constant - parse_full
- constant - print_no_indenting


class - template - rapidxml::memory_pool

- - Defined in rapidxml.hpp
- Base class for - xml_document

Description

This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use memory_pool of relevant xml_document to allocate the memory. Not only is this faster than allocating them by using new operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management.

- Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. You can also call allocate_string() function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no free() function -- all allocations are freed at once when clear() function is called, or when the pool is destroyed.

- It is also possible to create a standalone memory_pool, and use it to allocate nodes, whose lifetime will not be tied to any document.

- Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, by using global new[] and delete[] operators. This behaviour can be changed by setting custom allocation routines. Use set_allocator() function to set them.

- Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. This value defaults to the size of pointer on target architecture.

- To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT to obtain best wasted memory to performance compromise. To do it, define their values before rapidxml.hpp file is included.

Parameters

Ch
Character type of created nodes.

- constructor - memory_pool::memory_pool

Synopsis

memory_pool(); -

Description

Constructs empty pool with default allocator functions.

- destructor - memory_pool::~memory_pool

Synopsis

~memory_pool(); -

Description

Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid.

function memory_pool::allocate_node

Synopsis

xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); -

Description

Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

type
Type of node to create.
name
Name to assign to the node, or 0 to assign no name.
value
Value to assign to the node, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated node. This pointer will never be NULL.

function memory_pool::allocate_attribute

Synopsis

xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); -

Description

Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

name
Name to assign to the attribute, or 0 to assign no name.
value
Value to assign to the attribute, or 0 to assign no value.
name_size
Size of name to assign, or 0 to automatically calculate size from name string.
value_size
Size of value to assign, or 0 to automatically calculate size from value string.

Returns

Pointer to allocated attribute. This pointer will never be NULL.

function memory_pool::allocate_string

Synopsis

Ch* allocate_string(const Ch *source=0, std::size_t size=0); -

Description

Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

Parameters

source
String to initialize the allocated memory with, or 0 to not initialize it.
size
Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.

Returns

Pointer to allocated char array. This pointer will never be NULL.

function memory_pool::clone_node

Synopsis

xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0); -

Description

Clones an xml_node and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document.

Parameters

source
Node to clone.
result
Node to put results in, or 0 to automatically allocate result node

Returns

Pointer to cloned node. This pointer will never be NULL.

function memory_pool::clear

Synopsis

void clear(); -

Description

Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid.

function memory_pool::set_allocator

Synopsis

void set_allocator(alloc_func *af, free_func *ff); -

Description

Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use longjmp() function to pass control to other place of program. If it returns invalid pointer, results are undefined.

- User defined allocation functions must have the following forms:

-void *allocate(std::size_t size);
-void free(void *pointer);

Parameters

af
Allocation function, or 0 to restore default function
ff
Free function, or 0 to restore default function

class rapidxml::parse_error

- - Defined in rapidxml.hpp

Description

Parse error exception. This exception is thrown by the parser when an error occurs. Use what() function to get human-readable error message. Use where() function to get a pointer to position within source text where error was detected.

- If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. This function must be defined by the user.

- This class derives from std::exception class.

- constructor - parse_error::parse_error

Synopsis

parse_error(const char *what, void *where); -

Description

Constructs parse error.

function parse_error::what

Synopsis

virtual const char* what() const; -

Description

Gets human readable description of error.

Returns

Pointer to null terminated description of the error.

function parse_error::where

Synopsis

Ch* where() const; -

Description

Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.

Returns

Pointer to location within the parsed string where error occured.

class - template - rapidxml::xml_attribute

- - Defined in rapidxml.hpp
- Inherits from - xml_base

Description

Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.

Parameters

Ch
Character type to use.

- constructor - xml_attribute::xml_attribute

Synopsis

xml_attribute(); -

Description

Constructs an empty attribute with the specified type. Consider using memory_pool of appropriate xml_document if allocating attributes manually.

function xml_attribute::document

Synopsis

xml_document<Ch>* document() const; -

Description

Gets document of which attribute is a child.

Returns

Pointer to document that contains this attribute, or 0 if there is no parent document.

function xml_attribute::previous_attribute

Synopsis

xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets previous attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_attribute::next_attribute

Synopsis

xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets next attribute, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

class - template - rapidxml::xml_base

- - Defined in rapidxml.hpp
- Base class for - xml_attribute xml_node

Description

Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().

Parameters

Ch
Character type to use

- constructor - xml_base::xml_base

Synopsis

xml_base(); -

function xml_base::name

Synopsis

Ch* name() const; -

Description

Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

- Use name_size() function to determine length of the name.

Returns

Name of node, or empty string if node has no name.

function xml_base::name_size

Synopsis

std::size_t name_size() const; -

Description

Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated.

Returns

Size of node name, in characters.

function xml_base::value

Synopsis

Ch* value() const; -

Description

Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

- Use value_size() function to determine length of the value.

Returns

Value of node, or empty string if node has no value.

function xml_base::value_size

Synopsis

std::size_t value_size() const; -

Description

Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated.

Returns

Size of node value, in characters.

function xml_base::name

Synopsis

void name(const Ch *name, std::size_t size); -

Description

Sets name of node to a non zero-terminated string. See Ownership Of Strings .

- Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

- Size of name must be specified separately, because name does not have to be zero terminated. Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

Parameters

name
Name of node to set. Does not have to be zero terminated.
size
Size of name, in characters. This does not include zero terminator, if one is present.

function xml_base::name

Synopsis

void name(const Ch *name); -

Description

Sets name of node to a zero-terminated string. See also Ownership Of Strings and xml_node::name(const Ch *, std::size_t).

Parameters

name
Name of node to set. Must be zero terminated.

function xml_base::value

Synopsis

void value(const Ch *value, std::size_t size); -

Description

Sets value of node to a non zero-terminated string. See Ownership Of Strings .

- Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

- Size of value must be specified separately, because it does not have to be zero terminated. Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

- If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.

Parameters

value
value of node to set. Does not have to be zero terminated.
size
Size of value, in characters. This does not include zero terminator, if one is present.

function xml_base::value

Synopsis

void value(const Ch *value); -

Description

Sets value of node to a zero-terminated string. See also Ownership Of Strings and xml_node::value(const Ch *, std::size_t).

Parameters

value
Vame of node to set. Must be zero terminated.

function xml_base::parent

Synopsis

xml_node<Ch>* parent() const; -

Description

Gets node parent.

Returns

Pointer to parent node, or 0 if there is no parent.

class - template - rapidxml::xml_document

- - Defined in rapidxml.hpp
- Inherits from - xml_node memory_pool

Description

This class represents root of the DOM hierarchy. It is also an xml_node and a memory_pool through public inheritance. Use parse() function to build a DOM tree from a zero-terminated XML text string. parse() function allocates memory for nodes and attributes by using functions of xml_document, which are inherited from memory_pool. To access root node of the document, use the document itself, as if it was an xml_node.

Parameters

Ch
Character type to use.

- constructor - xml_document::xml_document

Synopsis

xml_document(); -

Description

Constructs empty XML document.

function xml_document::parse

Synopsis

void parse(Ch *text); -

Description

Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. The string must persist for the lifetime of the document. In case of error, rapidxml::parse_error exception will be thrown.

- If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated.

- Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

Parameters

text
XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

function xml_document::clear

Synopsis

void clear(); -

Description

Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed.

class - template - rapidxml::xml_node

- - Defined in rapidxml.hpp
- Inherits from - xml_base
- Base class for - xml_document

Description

Class representing a node of XML document. Each node may have associated name and value strings, which are available through name() and value() functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using type() function.

- Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node.

Parameters

Ch
Character type to use.

- constructor - xml_node::xml_node

Synopsis

xml_node(node_type type); -

Description

Constructs an empty node with the specified type. Consider using memory_pool of appropriate document to allocate nodes manually.

Parameters

type
Type of node to construct.

function xml_node::type

Synopsis

node_type type() const; -

Description

Gets type of node.

Returns

Type of node.

function xml_node::document

Synopsis

xml_document<Ch>* document() const; -

Description

Gets document of which node is a child.

Returns

Pointer to document that contains this node, or 0 if there is no parent document.

function xml_node::first_node

Synopsis

xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets first child node, optionally matching node name.

Parameters

name
Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::last_node

Synopsis

xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use first_node() to test if node has children.

Parameters

name
Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found child, or 0 if not found.

function xml_node::previous_sibling

Synopsis

xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::next_sibling

Synopsis

xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

Parameters

name
Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found sibling, or 0 if not found.

function xml_node::first_attribute

Synopsis

xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets first attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::last_attribute

Synopsis

xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; -

Description

Gets last attribute of node, optionally matching attribute name.

Parameters

name
Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
name_size
Size of name, in characters, or 0 to have size calculated automatically from string
case_sensitive
Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

Returns

Pointer to found attribute, or 0 if not found.

function xml_node::type

Synopsis

void type(node_type type); -

Description

Sets type of node.

Parameters

type
Type of node to set.

function xml_node::prepend_node

Synopsis

void prepend_node(xml_node< Ch > *child); -

Description

Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back.

Parameters

child
Node to prepend.

function xml_node::append_node

Synopsis

void append_node(xml_node< Ch > *child); -

Description

Appends a new child node. The appended child becomes the last child.

Parameters

child
Node to append.

function xml_node::insert_node

Synopsis

void insert_node(xml_node< Ch > *where, xml_node< Ch > *child); -

Description

Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back.

Parameters

where
Place where to insert the child, or 0 to insert at the back.
child
Node to insert.

function xml_node::remove_first_node

Synopsis

void remove_first_node(); -

Description

Removes first child node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_last_node

Synopsis

void remove_last_node(); -

Description

Removes last child of the node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

function xml_node::remove_node

Synopsis

void remove_node(xml_node< Ch > *where); -

Description

Removes specified child from the node.

function xml_node::remove_all_nodes

Synopsis

void remove_all_nodes(); -

Description

Removes all child nodes (but not attributes).

function xml_node::prepend_attribute

Synopsis

void prepend_attribute(xml_attribute< Ch > *attribute); -

Description

Prepends a new attribute to the node.

Parameters

attribute
Attribute to prepend.

function xml_node::append_attribute

Synopsis

void append_attribute(xml_attribute< Ch > *attribute); -

Description

Appends a new attribute to the node.

Parameters

attribute
Attribute to append.

function xml_node::insert_attribute

Synopsis

void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute); -

Description

Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.

Parameters

where
Place where to insert the attribute, or 0 to insert at the back.
attribute
Attribute to insert.

function xml_node::remove_first_attribute

Synopsis

void remove_first_attribute(); -

Description

Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_last_attribute

Synopsis

void remove_last_attribute(); -

Description

Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

function xml_node::remove_attribute

Synopsis

void remove_attribute(xml_attribute< Ch > *where); -

Description

Removes specified attribute from node.

Parameters

where
Pointer to attribute to be removed.

function xml_node::remove_all_attributes

Synopsis

void remove_all_attributes(); -

Description

Removes all attributes of node.

enum node_type

Description

Enumeration listing all node types produced by the parser. Use xml_node::type() function to query node type.

Values

node_document
A document node. Name and value are empty.
node_element
An element node. Name contains element name. Value contains text of first data node.
node_data
A data node. Name is empty. Value contains data text.
node_cdata
A CDATA node. Name is empty. Value contains data text.
node_comment
A comment node. Name is empty. Value contains comment text.
node_declaration
A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
node_doctype
A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
node_pi
A PI node. Name contains target. Value contains instructions.

function parse_error_handler

Synopsis

void rapidxml::parse_error_handler(const char *what, void *where); -

Description

When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user.

- This function cannot return. If it does, the results are undefined.

- A very simple definition might look like that: - void rapidxml::parse_error_handler(const char *what, void *where) - { - std::cout << "Parse error: " << what << "\n"; - std::abort(); - } -

Parameters

what
Human readable description of the error.
where
Pointer to character data where error was detected.

function print

Synopsis

OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0); -

Description

Prints XML to given output iterator.

Parameters

out
Output iterator to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output iterator pointing to position immediately after last character of printed text.

function print

Synopsis

std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0); -

Description

Prints XML to given output stream.

Parameters

out
Output stream to print to.
node
Node to be printed. Pass xml_document to print entire document.
flags
Flags controlling how XML is printed.

Returns

Output stream.

function operator<<

Synopsis

std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node); -

Description

Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.

Parameters

out
Output stream to print to.
node
Node to be printed.

Returns

Output stream.

- constant - parse_no_data_nodes

Synopsis

const int parse_no_data_nodes - = 0x1; -

Description

Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_no_element_values

Synopsis

const int parse_no_element_values - = 0x2; -

Description

Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes and a value, the value will be ignored. Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

- See xml_document::parse() function.

- constant - parse_no_string_terminators

Synopsis

const int parse_no_string_terminators - = 0x4; -

Description

Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_no_entity_translation

Synopsis

const int parse_no_entity_translation - = 0x8; -

Description

Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_no_utf8

Synopsis

const int parse_no_utf8 - = 0x10; -

Description

Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_declaration_node

Synopsis

const int parse_declaration_node - = 0x20; -

Description

Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_comment_nodes

Synopsis

const int parse_comment_nodes - = 0x40; -

Description

Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_doctype_node

Synopsis

const int parse_doctype_node - = 0x80; -

Description

Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_pi_nodes

Synopsis

const int parse_pi_nodes - = 0x100; -

Description

Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_validate_closing_tags

Synopsis

const int parse_validate_closing_tags - = 0x200; -

Description

Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_trim_whitespace

Synopsis

const int parse_trim_whitespace - = 0x400; -

Description

Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_normalize_whitespace

Synopsis

const int parse_normalize_whitespace - = 0x800; -

Description

Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator.

- See xml_document::parse() function.

- constant - parse_default

Synopsis

const int parse_default - = 0; -

Description

Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a negation of the default setting. For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, and using the flag will disable it.

- See xml_document::parse() function.

- constant - parse_non_destructive

Synopsis

const int parse_non_destructive - = parse_no_string_terminators | parse_no_entity_translation; -

Description

A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur:
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • entities will not be translated
  • whitespace will not be normalized
-See xml_document::parse() function.

- constant - parse_fastest

Synopsis

const int parse_fastest - = parse_non_destructive | parse_no_data_nodes; -

Description

A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

- See xml_document::parse() function.

- constant - parse_full

Synopsis

const int parse_full - = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; -

Description

A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing.

- See xml_document::parse() function.

- constant - print_no_indenting

Synopsis

const int print_no_indenting - = 0x1; -

Description

Printer flag instructing the printer to suppress indenting of XML. See print() function.

\ No newline at end of file diff --git a/libs/network/example/rapidxml/rapidxml.hpp b/libs/network/example/rapidxml/rapidxml.hpp deleted file mode 100644 index ae91e081d..000000000 --- a/libs/network/example/rapidxml/rapidxml.hpp +++ /dev/null @@ -1,2596 +0,0 @@ -#ifndef RAPIDXML_HPP_INCLUDED -#define RAPIDXML_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation - -// If standard library is disabled, user must provide implementations of required functions and typedefs -#if !defined(RAPIDXML_NO_STDLIB) - #include // For std::size_t - #include // For assert - #include // For placement new -#endif - -// On MSVC, disable "conditional expression is constant" warning (level 4). -// This warning is almost impossible to avoid with certain types of templated code -#ifdef _MSC_VER - #pragma warning(push) - #pragma warning(disable:4127) // Conditional expression is constant -#endif - -/////////////////////////////////////////////////////////////////////////// -// RAPIDXML_PARSE_ERROR - -#if defined(RAPIDXML_NO_EXCEPTIONS) - -#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } - -namespace rapidxml -{ - //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, - //! this function is called to notify user about the error. - //! It must be defined by the user. - //!

- //! This function cannot return. If it does, the results are undefined. - //!

- //! A very simple definition might look like that: - //!

-    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
-    //! {
-    //!     std::cout << "Parse error: " << what << "\n";
-    //!     std::abort();
-    //! }
-    //! 
- //! \param what Human readable description of the error. - //! \param where Pointer to character data where error was detected. - void parse_error_handler(const char *what, void *where); -} - -#else - -#include // For std::exception - -#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) - -namespace rapidxml -{ - - //! Parse error exception. - //! This exception is thrown by the parser when an error occurs. - //! Use what() function to get human-readable error message. - //! Use where() function to get a pointer to position within source text where error was detected. - //!

- //! If throwing exceptions by the parser is undesirable, - //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. - //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. - //! This function must be defined by the user. - //!

- //! This class derives from std::exception class. - class parse_error: public std::exception - { - - public: - - //! Constructs parse error - parse_error(const char *what, void *where) - : m_what(what) - , m_where(where) - { - } - - //! Gets human readable description of error. - //! \return Pointer to null terminated description of the error. - virtual const char *what() const throw() - { - return m_what; - } - - //! Gets pointer to character data where error happened. - //! Ch should be the same as char type of xml_document that produced the error. - //! \return Pointer to location within the parsed string where error occured. - template - Ch *where() const - { - return reinterpret_cast(m_where); - } - - private: - - const char *m_what; - void *m_where; - - }; -} - -#endif - -/////////////////////////////////////////////////////////////////////////// -// Pool sizes - -#ifndef RAPIDXML_STATIC_POOL_SIZE - // Size of static memory block of memory_pool. - // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. - // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. - #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_DYNAMIC_POOL_SIZE - // Size of dynamic memory block of memory_pool. - // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. - // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. - #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) -#endif - -#ifndef RAPIDXML_ALIGNMENT - // Memory allocation alignment. - // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. - // All memory allocations for nodes, attributes and strings will be aligned to this value. - // This must be a power of 2 and at least 1, otherwise memory_pool will not work. - #define RAPIDXML_ALIGNMENT sizeof(void *) -#endif - -namespace rapidxml -{ - // Forward declarations - template class xml_node; - template class xml_attribute; - template class xml_document; - - //! Enumeration listing all node types produced by the parser. - //! Use xml_node::type() function to query node type. - enum node_type - { - node_document, //!< A document node. Name and value are empty. - node_element, //!< An element node. Name contains element name. Value contains text of first data node. - node_data, //!< A data node. Name is empty. Value contains data text. - node_cdata, //!< A CDATA node. Name is empty. Value contains data text. - node_comment, //!< A comment node. Name is empty. Value contains comment text. - node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. - node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. - node_pi //!< A PI node. Name contains target. Value contains instructions. - }; - - /////////////////////////////////////////////////////////////////////// - // Parsing flags - - //! Parse flag instructing the parser to not create data nodes. - //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_no_data_nodes = 0x1; - - //! Parse flag instructing the parser to not use text of first data node as a value of parent element. - //! Can be combined with other flags by use of | operator. - //! Note that child data nodes of element node take precendence over its value when printing. - //! That is, if element has one or more child data nodes and a value, the value will be ignored. - //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. - //!

- //! See xml_document::parse() function. - const int parse_no_element_values = 0x2; - - //! Parse flag instructing the parser to not place zero terminators after strings in the source text. - //! By default zero terminators are placed, modifying source text. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_no_string_terminators = 0x4; - - //! Parse flag instructing the parser to not translate entities in the source text. - //! By default entities are translated, modifying source text. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_no_entity_translation = 0x8; - - //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. - //! By default, UTF-8 handling is enabled. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_no_utf8 = 0x10; - - //! Parse flag instructing the parser to create XML declaration node. - //! By default, declaration node is not created. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_declaration_node = 0x20; - - //! Parse flag instructing the parser to create comments nodes. - //! By default, comment nodes are not created. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_comment_nodes = 0x40; - - //! Parse flag instructing the parser to create DOCTYPE node. - //! By default, doctype node is not created. - //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_doctype_node = 0x80; - - //! Parse flag instructing the parser to create PI nodes. - //! By default, PI nodes are not created. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_pi_nodes = 0x100; - - //! Parse flag instructing the parser to validate closing tag names. - //! If not set, name inside closing tag is irrelevant to the parser. - //! By default, closing tags are not validated. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_validate_closing_tags = 0x200; - - //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. - //! By default, whitespace is not trimmed. - //! This flag does not cause the parser to modify source text. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_trim_whitespace = 0x400; - - //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. - //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. - //! By default, whitespace is not normalized. - //! If this flag is specified, source text will be modified. - //! Can be combined with other flags by use of | operator. - //!

- //! See xml_document::parse() function. - const int parse_normalize_whitespace = 0x800; - - // Compound flags - - //! Parse flags which represent default behaviour of the parser. - //! This is always equal to 0, so that all other flags can be simply ored together. - //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. - //! This also means that meaning of each flag is a negation of the default setting. - //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, - //! and using the flag will disable it. - //!

- //! See xml_document::parse() function. - const int parse_default = 0; - - //! A combination of parse flags that forbids any modifications of the source text. - //! This also results in faster parsing. However, note that the following will occur: - //!
    - //!
  • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
  • - //!
  • entities will not be translated
  • - //!
  • whitespace will not be normalized
  • - //!
- //! See xml_document::parse() function. - const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; - - //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. - //!

- //! See xml_document::parse() function. - const int parse_fastest = parse_non_destructive | parse_no_data_nodes; - - //! A combination of parse flags resulting in largest amount of data being extracted. - //! This usually results in slowest parsing. - //!

- //! See xml_document::parse() function. - const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; - - /////////////////////////////////////////////////////////////////////// - // Internals - - //! \cond internal - namespace internal - { - - // Struct that contains lookup tables for the parser - // It must be a template to allow correct linking (because it has static data members, which are defined in a header file). - template - struct lookup_tables - { - static const unsigned char lookup_whitespace[256]; // Whitespace table - static const unsigned char lookup_node_name[256]; // Node name table - static const unsigned char lookup_text[256]; // Text table - static const unsigned char lookup_text_pure_no_ws[256]; // Text table - static const unsigned char lookup_text_pure_with_ws[256]; // Text table - static const unsigned char lookup_attribute_name[256]; // Attribute name table - static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote - static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes - static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes - static const unsigned char lookup_digits[256]; // Digits - static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters - }; - - // Find length of the string - template - inline std::size_t measure(const Ch *p) - { - const Ch *tmp = p; - while (*tmp) - ++tmp; - return tmp - p; - } - - // Compare strings for equality - template - inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) - { - if (size1 != size2) - return false; - if (case_sensitive) - { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (*p1 != *p2) - return false; - } - else - { - for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) - if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) - return false; - } - return true; - } - } - //! \endcond - - /////////////////////////////////////////////////////////////////////// - // Memory pool - - //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. - //! In most cases, you will not need to use this class directly. - //! However, if you need to create nodes manually or modify names/values of nodes, - //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. - //! Not only is this faster than allocating them by using new operator, - //! but also their lifetime will be tied to the lifetime of document, - //! possibly simplyfing memory management. - //!

- //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. - //! You can also call allocate_string() function to allocate strings. - //! Such strings can then be used as names or values of nodes without worrying about their lifetime. - //! Note that there is no free() function -- all allocations are freed at once when clear() function is called, - //! or when the pool is destroyed. - //!

- //! It is also possible to create a standalone memory_pool, and use it - //! to allocate nodes, whose lifetime will not be tied to any document. - //!

- //! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. - //! Until static memory is exhausted, no dynamic memory allocations are done. - //! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, - //! by using global new[] and delete[] operators. - //! This behaviour can be changed by setting custom allocation routines. - //! Use set_allocator() function to set them. - //!

- //! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. - //! This value defaults to the size of pointer on target architecture. - //!

- //! To obtain absolutely top performance from the parser, - //! it is important that all nodes are allocated from a single, contiguous block of memory. - //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. - //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT - //! to obtain best wasted memory to performance compromise. - //! To do it, define their values before rapidxml.hpp file is included. - //! \param Ch Character type of created nodes. - template - class memory_pool - { - - public: - - //! \cond internal - typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory - typedef void (free_func)(void *); // Type of user-defined function used to free memory - //! \endcond - - //! Constructs empty pool with default allocator functions. - memory_pool() - : m_alloc_func(0) - , m_free_func(0) - { - init(); - } - - //! Destroys pool and frees all the memory. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Nodes allocated from the pool are no longer valid. - ~memory_pool() - { - clear(); - } - - //! Allocates a new node from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param type Type of node to create. - //! \param name Name to assign to the node, or 0 to assign no name. - //! \param value Value to assign to the node, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated node. This pointer will never be NULL. - xml_node *allocate_node(node_type type, - const Ch *name = 0, const Ch *value = 0, - std::size_t name_size = 0, std::size_t value_size = 0) - { - void *memory = allocate_aligned(sizeof(xml_node)); - xml_node *node = new(memory) xml_node(type); - if (name) - { - if (name_size > 0) - node->name(name, name_size); - else - node->name(name); - } - if (value) - { - if (value_size > 0) - node->value(value, value_size); - else - node->value(value); - } - return node; - } - - //! Allocates a new attribute from the pool, and optionally assigns name and value to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param name Name to assign to the attribute, or 0 to assign no name. - //! \param value Value to assign to the attribute, or 0 to assign no value. - //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. - //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. - //! \return Pointer to allocated attribute. This pointer will never be NULL. - xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, - std::size_t name_size = 0, std::size_t value_size = 0) - { - void *memory = allocate_aligned(sizeof(xml_attribute)); - xml_attribute *attribute = new(memory) xml_attribute; - if (name) - { - if (name_size > 0) - attribute->name(name, name_size); - else - attribute->name(name); - } - if (value) - { - if (value_size > 0) - attribute->value(value, value_size); - else - attribute->value(value); - } - return attribute; - } - - //! Allocates a char array of given size from the pool, and optionally copies a given string to it. - //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. - //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function - //! will call rapidxml::parse_error_handler() function. - //! \param source String to initialize the allocated memory with, or 0 to not initialize it. - //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. - //! \return Pointer to allocated char array. This pointer will never be NULL. - Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) - { - assert(source || size); // Either source or size (or both) must be specified - if (size == 0) - size = internal::measure(source) + 1; - Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); - if (source) - for (std::size_t i = 0; i < size; ++i) - result[i] = source[i]; - return result; - } - - //! Clones an xml_node and its hierarchy of child nodes and attributes. - //! Nodes and attributes are allocated from this memory pool. - //! Names and values are not cloned, they are shared between the clone and the source. - //! Result node can be optionally specified as a second parameter, - //! in which case its contents will be replaced with cloned source node. - //! This is useful when you want to clone entire document. - //! \param source Node to clone. - //! \param result Node to put results in, or 0 to automatically allocate result node - //! \return Pointer to cloned node. This pointer will never be NULL. - xml_node *clone_node(const xml_node *source, xml_node *result = 0) - { - // Prepare result node - if (result) - { - result->remove_all_attributes(); - result->remove_all_nodes(); - result->type(source->type()); - } - else - result = allocate_node(source->type()); - - // Clone name and value - result->name(source->name(), source->name_size()); - result->value(source->value(), source->value_size()); - - // Clone child nodes and attributes - for (xml_node *child = source->first_node(); child; child = child->next_sibling()) - result->append_node(clone_node(child)); - for (xml_attribute *attr = source->first_attribute(); attr; attr = attr->next_attribute()) - result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size())); - - return result; - } - - //! Clears the pool. - //! This causes memory occupied by nodes allocated by the pool to be freed. - //! Any nodes or strings allocated from the pool will no longer be valid. - void clear() - { - while (m_begin != m_static_memory) - { - char *previous_begin = reinterpret_cast
(align(m_begin))->previous_begin; - if (m_free_func) - m_free_func(m_begin); - else - delete[] m_begin; - m_begin = previous_begin; - } - init(); - } - - //! Sets or resets the user-defined memory allocation functions for the pool. - //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. - //! Allocation function must not return invalid pointer on failure. It should either throw, - //! stop the program, or use longjmp() function to pass control to other place of program. - //! If it returns invalid pointer, results are undefined. - //!

- //! User defined allocation functions must have the following forms: - //!
- //!
void *allocate(std::size_t size); - //!
void free(void *pointer); - //!

- //! \param af Allocation function, or 0 to restore default function - //! \param ff Free function, or 0 to restore default function - void set_allocator(alloc_func *af, free_func *ff) - { - assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet - m_alloc_func = af; - m_free_func = ff; - } - - private: - - struct header - { - char *previous_begin; - }; - - void init() - { - m_begin = m_static_memory; - m_ptr = align(m_begin); - m_end = m_static_memory + sizeof(m_static_memory); - } - - char *align(char *ptr) - { - std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); - return ptr + alignment; - } - - char *allocate_raw(std::size_t size) - { - // Allocate - void *memory; - if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] - { - memory = m_alloc_func(size); - assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp - } - else - { - memory = new char[size]; -#ifdef RAPIDXML_NO_EXCEPTIONS - if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc - RAPIDXML_PARSE_ERROR("out of memory", 0); -#endif - } - return static_cast(memory); - } - - void *allocate_aligned(std::size_t size) - { - // Calculate aligned pointer - char *result = align(m_ptr); - - // If not enough memory left in current pool, allocate a new pool - if (result + size > m_end) - { - // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) - std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; - if (pool_size < size) - pool_size = size; - - // Allocate - std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation - char *raw_memory = allocate_raw(alloc_size); - - // Setup new pool in allocated memory - char *pool = align(raw_memory); - header *new_header = reinterpret_cast
(pool); - new_header->previous_begin = m_begin; - m_begin = raw_memory; - m_ptr = pool + sizeof(header); - m_end = raw_memory + alloc_size; - - // Calculate aligned pointer again using new pool - result = align(m_ptr); - } - - // Update pool and return aligned pointer - m_ptr = result + size; - return result; - } - - char *m_begin; // Start of raw memory making up current pool - char *m_ptr; // First free byte in current pool - char *m_end; // One past last available byte in current pool - char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory - alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used - free_func *m_free_func; // Free function, or 0 if default is to be used - }; - - /////////////////////////////////////////////////////////////////////////// - // XML base - - //! Base class for xml_node and xml_attribute implementing common functions: - //! name(), name_size(), value(), value_size() and parent(). - //! \param Ch Character type to use - template - class xml_base - { - - public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - // Construct a base with empty name, value and parent - xml_base() - : m_name(0) - , m_value(0) - , m_parent(0) - { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets name of the node. - //! Interpretation of name depends on type of node. - //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use name_size() function to determine length of the name. - //! \return Name of node, or empty string if node has no name. - Ch *name() const - { - return m_name ? m_name : nullstr(); - } - - //! Gets size of node name, not including terminator character. - //! This function works correctly irrespective of whether name is or is not zero terminated. - //! \return Size of node name, in characters. - std::size_t name_size() const - { - return m_name ? m_name_size : 0; - } - - //! Gets value of node. - //! Interpretation of value depends on type of node. - //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. - //!

- //! Use value_size() function to determine length of the value. - //! \return Value of node, or empty string if node has no value. - Ch *value() const - { - return m_value ? m_value : nullstr(); - } - - //! Gets size of node value, not including terminator character. - //! This function works correctly irrespective of whether value is or is not zero terminated. - //! \return Size of node value, in characters. - std::size_t value_size() const - { - return m_value ? m_value_size : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets name of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of name must be specified separately, because name does not have to be zero terminated. - //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //! \param name Name of node to set. Does not have to be zero terminated. - //! \param size Size of name, in characters. This does not include zero terminator, if one is present. - void name(const Ch *name, std::size_t size) - { - m_name = const_cast(name); - m_name_size = size; - } - - //! Sets name of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). - //! \param name Name of node to set. Must be zero terminated. - void name(const Ch *name) - { - this->name(name, internal::measure(name)); - } - - //! Sets value of node to a non zero-terminated string. - //! See \ref ownership_of_strings. - //!

- //! Note that node does not own its name or value, it only stores a pointer to it. - //! It will not delete or otherwise free the pointer on destruction. - //! It is reponsibility of the user to properly manage lifetime of the string. - //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - - //! on destruction of the document the string will be automatically freed. - //!

- //! Size of value must be specified separately, because it does not have to be zero terminated. - //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). - //!

- //! If an element has a child node of type node_data, it will take precedence over element value when printing. - //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. - //! \param value value of node to set. Does not have to be zero terminated. - //! \param size Size of value, in characters. This does not include zero terminator, if one is present. - void value(const Ch *value, std::size_t size) - { - m_value = const_cast(value); - m_value_size = size; - } - - //! Sets value of node to a zero-terminated string. - //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). - //! \param value Vame of node to set. Must be zero terminated. - void value(const Ch *value) - { - this->value(value, internal::measure(value)); - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets node parent. - //! \return Pointer to parent node, or 0 if there is no parent. - xml_node *parent() const - { - return m_parent; - } - - protected: - - // Return empty string - static Ch *nullstr() - { - static Ch zero = Ch('\0'); - return &zero; - } - - Ch *m_name; // Name of node, or 0 if no name - Ch *m_value; // Value of node, or 0 if no value - std::size_t m_name_size; // Length of node name, or undefined of no name - std::size_t m_value_size; // Length of node value, or undefined if no value - xml_node *m_parent; // Pointer to parent node, or 0 if none - - }; - - //! Class representing attribute node of XML document. - //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). - //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. - //! Thus, this text must persist in memory for the lifetime of attribute. - //! \param Ch Character type to use. - template - class xml_attribute: public xml_base - { - - friend class xml_node; - - public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty attribute with the specified type. - //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. - xml_attribute() - { - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which attribute is a child. - //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. - xml_document *document() const - { - if (xml_node *node = this->parent()) - { - while (node->parent()) - node = node->parent(); - return node->type() == node_document ? static_cast *>(node) : 0; - } - else - return 0; - } - - //! Gets previous attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) - return attribute; - return 0; - } - else - return this->m_parent ? m_prev_attribute : 0; - } - - //! Gets next attribute, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) - return attribute; - return 0; - } - else - return this->m_parent ? m_next_attribute : 0; - } - - private: - - xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero - xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero - - }; - - /////////////////////////////////////////////////////////////////////////// - // XML node - - //! Class representing a node of XML document. - //! Each node may have associated name and value strings, which are available through name() and value() functions. - //! Interpretation of name and value depends on type of the node. - //! Type of node can be determined by using type() function. - //!

- //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. - //! Thus, this text must persist in the memory for the lifetime of node. - //! \param Ch Character type to use. - template - class xml_node: public xml_base - { - - public: - - /////////////////////////////////////////////////////////////////////////// - // Construction & destruction - - //! Constructs an empty node with the specified type. - //! Consider using memory_pool of appropriate document to allocate nodes manually. - //! \param type Type of node to construct. - xml_node(node_type type) - : m_type(type) - , m_first_node(0) - , m_first_attribute(0) - { - } - - /////////////////////////////////////////////////////////////////////////// - // Node data access - - //! Gets type of node. - //! \return Type of node. - node_type type() const - { - return m_type; - } - - /////////////////////////////////////////////////////////////////////////// - // Related nodes access - - //! Gets document of which node is a child. - //! \return Pointer to document that contains this node, or 0 if there is no parent document. - xml_document *document() const - { - xml_node *node = const_cast *>(this); - while (node->parent()) - node = node->parent(); - return node->type() == node_document ? static_cast *>(node) : 0; - } - - //! Gets first child node, optionally matching node name. - //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_node *child = m_first_node; child; child = child->next_sibling()) - if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) - return child; - return 0; - } - else - return m_first_node; - } - - //! Gets last child node, optionally matching node name. - //! Behaviour is undefined if node has no children. - //! Use first_node() to test if node has children. - //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found child, or 0 if not found. - xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - assert(m_first_node); // Cannot query for last child if node has no children - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_node *child = m_last_node; child; child = child->previous_sibling()) - if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) - return child; - return 0; - } - else - return m_last_node; - } - - //! Gets previous sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) - return sibling; - return 0; - } - else - return m_prev_sibling; - } - - //! Gets next sibling node, optionally matching node name. - //! Behaviour is undefined if node has no parent. - //! Use parent() to test if node has a parent. - //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found sibling, or 0 if not found. - xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - assert(this->m_parent); // Cannot query for siblings if node has no parent - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) - if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) - return sibling; - return 0; - } - else - return m_next_sibling; - } - - //! Gets first attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) - return attribute; - return 0; - } - else - return m_first_attribute; - } - - //! Gets last attribute of node, optionally matching attribute name. - //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero - //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string - //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters - //! \return Pointer to found attribute, or 0 if not found. - xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const - { - if (name) - { - if (name_size == 0) - name_size = internal::measure(name); - for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) - if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) - return attribute; - return 0; - } - else - return m_first_attribute ? m_last_attribute : 0; - } - - /////////////////////////////////////////////////////////////////////////// - // Node modification - - //! Sets type of node. - //! \param type Type of node to set. - void type(node_type type) - { - m_type = type; - } - - /////////////////////////////////////////////////////////////////////////// - // Node manipulation - - //! Prepends a new child node. - //! The prepended child becomes the first child, and all existing children are moved one position back. - //! \param child Node to prepend. - void prepend_node(xml_node *child) - { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) - { - child->m_next_sibling = m_first_node; - m_first_node->m_prev_sibling = child; - } - else - { - child->m_next_sibling = 0; - m_last_node = child; - } - m_first_node = child; - child->m_parent = this; - child->m_prev_sibling = 0; - } - - //! Appends a new child node. - //! The appended child becomes the last child. - //! \param child Node to append. - void append_node(xml_node *child) - { - assert(child && !child->parent() && child->type() != node_document); - if (first_node()) - { - child->m_prev_sibling = m_last_node; - m_last_node->m_next_sibling = child; - } - else - { - child->m_prev_sibling = 0; - m_first_node = child; - } - m_last_node = child; - child->m_parent = this; - child->m_next_sibling = 0; - } - - //! Inserts a new child node at specified place inside the node. - //! All children after and including the specified node are moved one position back. - //! \param where Place where to insert the child, or 0 to insert at the back. - //! \param child Node to insert. - void insert_node(xml_node *where, xml_node *child) - { - assert(!where || where->parent() == this); - assert(child && !child->parent() && child->type() != node_document); - if (where == m_first_node) - prepend_node(child); - else if (where == 0) - append_node(child); - else - { - child->m_prev_sibling = where->m_prev_sibling; - child->m_next_sibling = where; - where->m_prev_sibling->m_next_sibling = child; - where->m_prev_sibling = child; - child->m_parent = this; - } - } - - //! Removes first child node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_first_node() - { - assert(first_node()); - xml_node *child = m_first_node; - m_first_node = child->m_next_sibling; - if (child->m_next_sibling) - child->m_next_sibling->m_prev_sibling = 0; - else - m_last_node = 0; - child->m_parent = 0; - } - - //! Removes last child of the node. - //! If node has no children, behaviour is undefined. - //! Use first_node() to test if node has children. - void remove_last_node() - { - assert(first_node()); - xml_node *child = m_last_node; - if (child->m_prev_sibling) - { - m_last_node = child->m_prev_sibling; - child->m_prev_sibling->m_next_sibling = 0; - } - else - m_first_node = 0; - child->m_parent = 0; - } - - //! Removes specified child from the node - // \param where Pointer to child to be removed. - void remove_node(xml_node *where) - { - assert(where && where->parent() == this); - assert(first_node()); - if (where == m_first_node) - remove_first_node(); - else if (where == m_last_node) - remove_last_node(); - else - { - where->m_prev_sibling->m_next_sibling = where->m_next_sibling; - where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; - where->m_parent = 0; - } - } - - //! Removes all child nodes (but not attributes). - void remove_all_nodes() - { - for (xml_node *node = first_node(); node; node = node->m_next_sibling) - node->m_parent = 0; - m_first_node = 0; - } - - //! Prepends a new attribute to the node. - //! \param attribute Attribute to prepend. - void prepend_attribute(xml_attribute *attribute) - { - assert(attribute && !attribute->parent()); - if (first_attribute()) - { - attribute->m_next_attribute = m_first_attribute; - m_first_attribute->m_prev_attribute = attribute; - } - else - { - attribute->m_next_attribute = 0; - m_last_attribute = attribute; - } - m_first_attribute = attribute; - attribute->m_parent = this; - attribute->m_prev_attribute = 0; - } - - //! Appends a new attribute to the node. - //! \param attribute Attribute to append. - void append_attribute(xml_attribute *attribute) - { - assert(attribute && !attribute->parent()); - if (first_attribute()) - { - attribute->m_prev_attribute = m_last_attribute; - m_last_attribute->m_next_attribute = attribute; - } - else - { - attribute->m_prev_attribute = 0; - m_first_attribute = attribute; - } - m_last_attribute = attribute; - attribute->m_parent = this; - attribute->m_next_attribute = 0; - } - - //! Inserts a new attribute at specified place inside the node. - //! All attributes after and including the specified attribute are moved one position back. - //! \param where Place where to insert the attribute, or 0 to insert at the back. - //! \param attribute Attribute to insert. - void insert_attribute(xml_attribute *where, xml_attribute *attribute) - { - assert(!where || where->parent() == this); - assert(attribute && !attribute->parent()); - if (where == m_first_attribute) - prepend_attribute(attribute); - else if (where == 0) - append_attribute(attribute); - else - { - attribute->m_prev_attribute = where->m_prev_attribute; - attribute->m_next_attribute = where; - where->m_prev_attribute->m_next_attribute = attribute; - where->m_prev_attribute = attribute; - attribute->m_parent = this; - } - } - - //! Removes first attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_first_attribute() - { - assert(first_attribute()); - xml_attribute *attribute = m_first_attribute; - if (attribute->m_next_attribute) - { - attribute->m_next_attribute->m_prev_attribute = 0; - } - else - m_last_attribute = 0; - attribute->m_parent = 0; - m_first_attribute = attribute->m_next_attribute; - } - - //! Removes last attribute of the node. - //! If node has no attributes, behaviour is undefined. - //! Use first_attribute() to test if node has attributes. - void remove_last_attribute() - { - assert(first_attribute()); - xml_attribute *attribute = m_last_attribute; - if (attribute->m_prev_attribute) - { - attribute->m_prev_attribute->m_next_attribute = 0; - m_last_attribute = attribute->m_prev_attribute; - } - else - m_first_attribute = 0; - attribute->m_parent = 0; - } - - //! Removes specified attribute from node. - //! \param where Pointer to attribute to be removed. - void remove_attribute(xml_attribute *where) - { - assert(first_attribute() && where->parent() == this); - if (where == m_first_attribute) - remove_first_attribute(); - else if (where == m_last_attribute) - remove_last_attribute(); - else - { - where->m_prev_attribute->m_next_attribute = where->m_next_attribute; - where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; - where->m_parent = 0; - } - } - - //! Removes all attributes of node. - void remove_all_attributes() - { - for (xml_attribute *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) - attribute->m_parent = 0; - m_first_attribute = 0; - } - - private: - - /////////////////////////////////////////////////////////////////////////// - // Restrictions - - // No copying - xml_node(const xml_node &); - void operator =(const xml_node &); - - /////////////////////////////////////////////////////////////////////////// - // Data members - - // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. - // This is required for maximum performance, as it allows the parser to omit initialization of - // unneded/redundant values. - // - // The rules are as follows: - // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively - // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage - // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage - - node_type m_type; // Type of node; always valid - xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid - xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero - xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid - xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero - xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero - - }; - - /////////////////////////////////////////////////////////////////////////// - // XML document - - //! This class represents root of the DOM hierarchy. - //! It is also an xml_node and a memory_pool through public inheritance. - //! Use parse() function to build a DOM tree from a zero-terminated XML text string. - //! parse() function allocates memory for nodes and attributes by using functions of xml_document, - //! which are inherited from memory_pool. - //! To access root node of the document, use the document itself, as if it was an xml_node. - //! \param Ch Character type to use. - template - class xml_document: public xml_node, public memory_pool - { - - public: - - //! Constructs empty XML document - xml_document() - : xml_node(node_document) - { - } - - //! Parses zero-terminated XML string according to given flags. - //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. - //! The string must persist for the lifetime of the document. - //! In case of error, rapidxml::parse_error exception will be thrown. - //!

- //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. - //! Make sure that data is zero-terminated. - //!

- //! Document can be parsed into multiple times. - //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. - //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. - template - void parse(Ch *text) - { - assert(text); - - // Remove current contents - this->remove_all_nodes(); - this->remove_all_attributes(); - - // Parse BOM, if any - parse_bom(text); - - // Parse children - while (1) - { - // Skip whitespace before node - skip(text); - if (*text == 0) - break; - - // Parse and append new child - if (*text == Ch('<')) - { - ++text; // Skip '<' - if (xml_node *node = parse_node(text)) - this->append_node(node); - } - else - RAPIDXML_PARSE_ERROR("expected <", text); - } - - } - - //! Clears the document by deleting all nodes and clearing the memory pool. - //! All nodes owned by document pool are destroyed. - void clear() - { - this->remove_all_nodes(); - this->remove_all_attributes(); - memory_pool::clear(); - } - - private: - - /////////////////////////////////////////////////////////////////////// - // Internal character utility functions - - // Detect whitespace character - struct whitespace_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; - } - }; - - // Detect node name character - struct node_name_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; - } - }; - - // Detect attribute name character - struct attribute_name_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) - struct text_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_no_ws_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; - } - }; - - // Detect text character (PCDATA) that does not require processing - struct text_pure_with_ws_pred - { - static unsigned char test(Ch ch) - { - return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; - } - }; - - // Detect attribute value character - template - struct attribute_value_pred - { - static unsigned char test(Ch ch) - { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Detect attribute value character - template - struct attribute_value_pure_pred - { - static unsigned char test(Ch ch) - { - if (Quote == Ch('\'')) - return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; - if (Quote == Ch('\"')) - return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; - return 0; // Should never be executed, to avoid warnings on Comeau - } - }; - - // Insert coded character, using UTF8 or 8-bit ASCII - template - static void insert_coded_character(Ch *&text, unsigned long code) - { - if (Flags & parse_no_utf8) - { - // Insert 8-bit ASCII character - // Todo: possibly verify that code is less than 256 and use replacement char otherwise? - text[0] = static_cast(code); - text += 1; - } - else - { - // Insert UTF8 sequence - if (code < 0x80) // 1 byte sequence - { - text[0] = static_cast(code); - text += 1; - } - else if (code < 0x800) // 2 byte sequence - { - text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[0] = static_cast(code | 0xC0); - text += 2; - } - else if (code < 0x10000) // 3 byte sequence - { - text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[0] = static_cast(code | 0xE0); - text += 3; - } - else if (code < 0x110000) // 4 byte sequence - { - text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; - text[0] = static_cast(code | 0xF0); - text += 4; - } - else // Invalid, only codes up to 0x10FFFF are allowed in Unicode - { - RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); - } - } - } - - // Skip characters until predicate evaluates to true - template - static void skip(Ch *&text) - { - Ch *tmp = text; - while (StopPred::test(*tmp)) - ++tmp; - text = tmp; - } - - // Skip characters until predicate evaluates to true while doing the following: - // - replacing XML character entity references with proper characters (' & " < > &#...;) - // - condensing whitespace sequences to single space character - template - static Ch *skip_and_expand_character_refs(Ch *&text) - { - // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip - if (Flags & parse_no_entity_translation && - !(Flags & parse_normalize_whitespace) && - !(Flags & parse_trim_whitespace)) - { - skip(text); - return text; - } - - // Use simple skip until first modification is detected - skip(text); - - // Use translation skip - Ch *src = text; - Ch *dest = src; - while (StopPred::test(*src)) - { - // If entity translation is enabled - if (!(Flags & parse_no_entity_translation)) - { - // Test if replacement is needed - if (src[0] == Ch('&')) - { - switch (src[1]) - { - - // & ' - case Ch('a'): - if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) - { - *dest = Ch('&'); - ++dest; - src += 5; - continue; - } - if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) - { - *dest = Ch('\''); - ++dest; - src += 6; - continue; - } - break; - - // " - case Ch('q'): - if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) - { - *dest = Ch('"'); - ++dest; - src += 6; - continue; - } - break; - - // > - case Ch('g'): - if (src[2] == Ch('t') && src[3] == Ch(';')) - { - *dest = Ch('>'); - ++dest; - src += 4; - continue; - } - break; - - // < - case Ch('l'): - if (src[2] == Ch('t') && src[3] == Ch(';')) - { - *dest = Ch('<'); - ++dest; - src += 4; - continue; - } - break; - - // &#...; - assumes ASCII - case Ch('#'): - if (src[2] == Ch('x')) - { - unsigned long code = 0; - src += 3; // Skip &#x - while (1) - { - unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) - break; - code = code * 16 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } - else - { - unsigned long code = 0; - src += 2; // Skip &# - while (1) - { - unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; - if (digit == 0xFF) - break; - code = code * 10 + digit; - ++src; - } - insert_coded_character(dest, code); // Put character in output - } - if (*src == Ch(';')) - ++src; - else - RAPIDXML_PARSE_ERROR("expected ;", src); - continue; - - // Something else - default: - // Ignore, just copy '&' verbatim - break; - - } - } - } - - // If whitespace condensing is enabled - if (Flags & parse_normalize_whitespace) - { - // Test if condensing is needed - if (whitespace_pred::test(*src)) - { - *dest = Ch(' '); ++dest; // Put single space in dest - ++src; // Skip first whitespace char - // Skip remaining whitespace chars - while (whitespace_pred::test(*src)) - ++src; - continue; - } - } - - // No replacement, only copy character - *dest++ = *src++; - - } - - // Return new end - text = src; - return dest; - - } - - /////////////////////////////////////////////////////////////////////// - // Internal parsing functions - - // Parse BOM, if any - template - void parse_bom(Ch *&text) - { - // UTF-8? - if (static_cast(text[0]) == 0xEF && - static_cast(text[1]) == 0xBB && - static_cast(text[2]) == 0xBF) - { - text += 3; // Skup utf-8 bom - } - } - - // Parse XML declaration ( - xml_node *parse_xml_declaration(Ch *&text) - { - // If parsing of declaration is disabled - if (!(Flags & parse_declaration_node)) - { - // Skip until end of declaration - while (text[0] != Ch('?') || text[1] != Ch('>')) - { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - - // Create declaration - xml_node *declaration = this->allocate_node(node_declaration); - - // Skip whitespace before attributes or ?> - skip(text); - - // Parse declaration attributes - parse_node_attributes(text, declaration); - - // Skip ?> - if (text[0] != Ch('?') || text[1] != Ch('>')) - RAPIDXML_PARSE_ERROR("expected ?>", text); - text += 2; - - return declaration; - } - - // Parse XML comment (' - return 0; // Do not produce comment node - } - - // Remember value start - Ch *value = text; - - // Skip until end of comment - while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) - { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create comment node - xml_node *comment = this->allocate_node(node_comment); - comment->value(value, text - value); - - // Place zero terminator after comment value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip '-->' - return comment; - } - - // Parse DOCTYPE - template - xml_node *parse_doctype(Ch *&text) - { - // Remember value start - Ch *value = text; - - // Skip to > - while (*text != Ch('>')) - { - // Determine character type - switch (*text) - { - - // If '[' encountered, scan for matching ending ']' using naive algorithm with depth - // This works for all W3C test files except for 2 most wicked - case Ch('['): - { - ++text; // Skip '[' - int depth = 1; - while (depth > 0) - { - switch (*text) - { - case Ch('['): ++depth; break; - case Ch(']'): --depth; break; - case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); - } - ++text; - } - break; - } - - // Error on end of text - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Other character, skip it - default: - ++text; - - } - } - - // If DOCTYPE nodes enabled - if (Flags & parse_doctype_node) - { - // Create a new doctype node - xml_node *doctype = this->allocate_node(node_doctype); - doctype->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 1; // skip '>' - return doctype; - } - else - { - text += 1; // skip '>' - return 0; - } - - } - - // Parse PI - template - xml_node *parse_pi(Ch *&text) - { - // If creation of PI nodes is enabled - if (Flags & parse_pi_nodes) - { - // Create pi node - xml_node *pi = this->allocate_node(node_pi); - - // Extract PI target name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected PI target", text); - pi->name(name, text - name); - - // Skip whitespace between pi target and pi - skip(text); - - // Remember start of pi - Ch *value = text; - - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) - { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Set pi value (verbatim, no entity expansion or whitespace normalization) - pi->value(value, text - value); - - // Place zero terminator after name and value - if (!(Flags & parse_no_string_terminators)) - { - pi->name()[pi->name_size()] = Ch('\0'); - pi->value()[pi->value_size()] = Ch('\0'); - } - - text += 2; // Skip '?>' - return pi; - } - else - { - // Skip to '?>' - while (text[0] != Ch('?') || text[1] != Ch('>')) - { - if (*text == Ch('\0')) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 2; // Skip '?>' - return 0; - } - } - - // Parse and append data - // Return character that ends data. - // This is necessary because this character might have been overwritten by a terminating 0 - template - Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) - { - // Backup to contents start if whitespace trimming is disabled - if (!(Flags & parse_trim_whitespace)) - text = contents_start; - - // Skip until end of data - Ch *value = text, *end; - if (Flags & parse_normalize_whitespace) - end = skip_and_expand_character_refs(text); - else - end = skip_and_expand_character_refs(text); - - // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > - if (Flags & parse_trim_whitespace) - { - if (Flags & parse_normalize_whitespace) - { - // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end - if (*(end - 1) == Ch(' ')) - --end; - } - else - { - // Backup until non-whitespace character is found - while (whitespace_pred::test(*(end - 1))) - --end; - } - } - - // If characters are still left between end and value (this test is only necessary if normalization is enabled) - // Create new data node - if (!(Flags & parse_no_data_nodes)) - { - xml_node *data = this->allocate_node(node_data); - data->value(value, end - value); - node->append_node(data); - } - - // Add data to parent node if no data exists yet - if (!(Flags & parse_no_element_values)) - if (*node->value() == Ch('\0')) - node->value(value, end - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - { - Ch ch = *text; - *end = Ch('\0'); - return ch; // Return character that ends data; this is required because zero terminator overwritten it - } - - // Return character that ends data - return *text; - } - - // Parse CDATA - template - xml_node *parse_cdata(Ch *&text) - { - // If CDATA is disabled - if (Flags & parse_no_data_nodes) - { - // Skip until end of cdata - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) - { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - text += 3; // Skip ]]> - return 0; // Do not produce CDATA node - } - - // Skip until end of cdata - Ch *value = text; - while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) - { - if (!text[0]) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - - // Create new cdata node - xml_node *cdata = this->allocate_node(node_cdata); - cdata->value(value, text - value); - - // Place zero terminator after value - if (!(Flags & parse_no_string_terminators)) - *text = Ch('\0'); - - text += 3; // Skip ]]> - return cdata; - } - - // Parse element node - template - xml_node *parse_element(Ch *&text) - { - // Create element node - xml_node *element = this->allocate_node(node_element); - - // Extract element name - Ch *name = text; - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected element name", text); - element->name(name, text - name); - - // Skip whitespace between element name and attributes or > - skip(text); - - // Parse attributes, if any - parse_node_attributes(text, element); - - // Determine ending type - if (*text == Ch('>')) - { - ++text; - parse_node_contents(text, element); - } - else if (*text == Ch('/')) - { - ++text; - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; - } - else - RAPIDXML_PARSE_ERROR("expected >", text); - - // Place zero terminator after name - if (!(Flags & parse_no_string_terminators)) - element->name()[element->name_size()] = Ch('\0'); - - // Return parsed element - return element; - } - - // Determine node type, and parse it - template - xml_node *parse_node(Ch *&text) - { - // Parse proper node type - switch (text[0]) - { - - // <... - default: - // Parse and append element node - return parse_element(text); - - // (text); - } - else - { - // Parse PI - return parse_pi(text); - } - - // (text); - } - break; - - // (text); - } - break; - - // (text); - } - - } // switch - - // Attempt to skip other, unrecognized node types starting with ')) - { - if (*text == 0) - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - ++text; - } - ++text; // Skip '>' - return 0; // No node recognized - - } - } - - // Parse contents of the node - children, data etc. - template - void parse_node_contents(Ch *&text, xml_node *node) - { - // For all children and text - while (1) - { - // Skip whitespace between > and node contents - Ch *contents_start = text; // Store start of node contents before whitespace is skipped - skip(text); - Ch next_char = *text; - - // After data nodes, instead of continuing the loop, control jumps here. - // This is because zero termination inside parse_and_append_data() function - // would wreak havoc with the above code. - // Also, skipping whitespace after data nodes is unnecessary. - after_data_node: - - // Determine what comes next: node closing, child node, data node, or 0? - switch (next_char) - { - - // Node closing or child node - case Ch('<'): - if (text[1] == Ch('/')) - { - // Node closing - text += 2; // Skip '(text); - if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) - RAPIDXML_PARSE_ERROR("invalid closing tag name", text); - } - else - { - // No validation, just skip name - skip(text); - } - // Skip remaining whitespace after node name - skip(text); - if (*text != Ch('>')) - RAPIDXML_PARSE_ERROR("expected >", text); - ++text; // Skip '>' - return; // Node closed, finished parsing contents - } - else - { - // Child node - ++text; // Skip '<' - if (xml_node *child = parse_node(text)) - node->append_node(child); - } - break; - - // End of data - error - case Ch('\0'): - RAPIDXML_PARSE_ERROR("unexpected end of data", text); - - // Data node - default: - next_char = parse_and_append_data(node, text, contents_start); - goto after_data_node; // Bypass regular processing after data nodes - - } - } - } - - // Parse XML attributes of the node - template - void parse_node_attributes(Ch *&text, xml_node *node) - { - // For all attributes - while (attribute_name_pred::test(*text)) - { - // Extract attribute name - Ch *name = text; - ++text; // Skip first character of attribute name - skip(text); - if (text == name) - RAPIDXML_PARSE_ERROR("expected attribute name", name); - - // Create new attribute - xml_attribute *attribute = this->allocate_attribute(); - attribute->name(name, text - name); - node->append_attribute(attribute); - - // Skip whitespace after attribute name - skip(text); - - // Skip = - if (*text != Ch('=')) - RAPIDXML_PARSE_ERROR("expected =", text); - ++text; - - // Add terminating zero after name - if (!(Flags & parse_no_string_terminators)) - attribute->name()[attribute->name_size()] = 0; - - // Skip whitespace after = - skip(text); - - // Skip quote and remember if it was ' or " - Ch quote = *text; - if (quote != Ch('\'') && quote != Ch('"')) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; - - // Extract attribute value and expand char refs in it - Ch *value = text, *end; - const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes - if (quote == Ch('\'')) - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); - else - end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); - - // Set attribute value - attribute->value(value, end - value); - - // Make sure that end quote is present - if (*text != quote) - RAPIDXML_PARSE_ERROR("expected ' or \"", text); - ++text; // Skip quote - - // Add terminating zero after value - if (!(Flags & parse_no_string_terminators)) - attribute->value()[attribute->value_size()] = 0; - - // Skip whitespace after attribute value - skip(text); - } - } - - }; - - //! \cond internal - namespace internal - { - - // Whitespace (space \n \r \t) - template - const unsigned char lookup_tables::lookup_whitespace[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F - }; - - // Node name (anything but space \n \r \t / > ? \0) - template - const unsigned char lookup_tables::lookup_node_name[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) (anything but < \0) - template - const unsigned char lookup_tables::lookup_text[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled - // (anything but < \0 &) - template - const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled - // (anything but < \0 & space \n \r \t) - template - const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute name (anything but space \n \r \t / < > = ? ! \0) - template - const unsigned char lookup_tables::lookup_attribute_name[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with single quote (anything but ' \0) - template - const unsigned char lookup_tables::lookup_attribute_data_1[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with single quote that does not require processing (anything but ' \0 &) - template - const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with double quote (anything but " \0) - template - const unsigned char lookup_tables::lookup_attribute_data_2[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Attribute data with double quote that does not require processing (anything but " \0 &) - template - const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 - 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F - }; - - // Digits (dec and hex, 255 denotes end of numeric character reference) - template - const unsigned char lookup_tables::lookup_digits[256] = - { - // 0 1 2 3 4 5 6 7 8 9 A B C D E F - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 - 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 - 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E - 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F - }; - - // Upper case conversion - template - const unsigned char lookup_tables::lookup_upcase[256] = - { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 - 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 - 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 - 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 - 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A - 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B - 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C - 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D - 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E - 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F - }; - } - //! \endcond - -} - -// Undefine internal macros -#undef RAPIDXML_PARSE_ERROR - -// On MSVC, restore warnings state -#ifdef _MSC_VER - #pragma warning(pop) -#endif - -#endif diff --git a/libs/network/example/rapidxml/rapidxml_iterators.hpp b/libs/network/example/rapidxml/rapidxml_iterators.hpp deleted file mode 100644 index 52ebc298a..000000000 --- a/libs/network/example/rapidxml/rapidxml_iterators.hpp +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED -#define RAPIDXML_ITERATORS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_iterators.hpp This file contains rapidxml iterators - -#include "rapidxml.hpp" - -namespace rapidxml -{ - - //! Iterator of child nodes of xml_node - template - class node_iterator - { - - public: - - typedef typename xml_node value_type; - typedef typename xml_node &reference; - typedef typename xml_node *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - node_iterator() - : m_node(0) - { - } - - node_iterator(xml_node *node) - : m_node(node->first_node()) - { - } - - reference operator *() const - { - assert(m_node); - return *m_node; - } - - pointer operator->() const - { - assert(m_node); - return m_node; - } - - node_iterator& operator++() - { - assert(m_node); - m_node = m_node->next_sibling(); - return *this; - } - - node_iterator operator++(int) - { - node_iterator tmp = *this; - ++this; - return tmp; - } - - node_iterator& operator--() - { - assert(m_node && m_node->previous_sibling()); - m_node = m_node->previous_sibling(); - return *this; - } - - node_iterator operator--(int) - { - node_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const node_iterator &rhs) - { - return m_node == rhs.m_node; - } - - bool operator !=(const node_iterator &rhs) - { - return m_node != rhs.m_node; - } - - private: - - xml_node *m_node; - - }; - - //! Iterator of child attributes of xml_node - template - class attribute_iterator - { - - public: - - typedef typename xml_attribute value_type; - typedef typename xml_attribute &reference; - typedef typename xml_attribute *pointer; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - attribute_iterator() - : m_attribute(0) - { - } - - attribute_iterator(xml_node *node) - : m_attribute(node->first_attribute()) - { - } - - reference operator *() const - { - assert(m_attribute); - return *m_attribute; - } - - pointer operator->() const - { - assert(m_attribute); - return m_attribute; - } - - attribute_iterator& operator++() - { - assert(m_attribute); - m_attribute = m_attribute->next_attribute(); - return *this; - } - - attribute_iterator operator++(int) - { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - attribute_iterator& operator--() - { - assert(m_attribute && m_attribute->previous_attribute()); - m_attribute = m_attribute->previous_attribute(); - return *this; - } - - attribute_iterator operator--(int) - { - attribute_iterator tmp = *this; - ++this; - return tmp; - } - - bool operator ==(const attribute_iterator &rhs) - { - return m_attribute == rhs.m_attribute; - } - - bool operator !=(const attribute_iterator &rhs) - { - return m_attribute != rhs.m_attribute; - } - - private: - - xml_attribute *m_attribute; - - }; - -} - -#endif diff --git a/libs/network/example/rapidxml/rapidxml_print.hpp b/libs/network/example/rapidxml/rapidxml_print.hpp deleted file mode 100644 index 0ae2b14fa..000000000 --- a/libs/network/example/rapidxml/rapidxml_print.hpp +++ /dev/null @@ -1,421 +0,0 @@ -#ifndef RAPIDXML_PRINT_HPP_INCLUDED -#define RAPIDXML_PRINT_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_print.hpp This file contains rapidxml printer implementation - -#include "rapidxml.hpp" - -// Only include streams if not disabled -#ifndef RAPIDXML_NO_STREAMS - #include - #include -#endif - -namespace rapidxml -{ - - /////////////////////////////////////////////////////////////////////// - // Printing flags - - const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. - - /////////////////////////////////////////////////////////////////////// - // Internal - - //! \cond internal - namespace internal - { - - /////////////////////////////////////////////////////////////////////////// - // Internal character operations - - // Copy characters from given range to given output iterator - template - inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) - { - while (begin != end) - *out++ = *begin++; - return out; - } - - // Copy characters from given range to given output iterator and expand - // characters into references (< > ' " &) - template - inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) - { - while (begin != end) - { - if (*begin == noexpand) - { - *out++ = *begin; // No expansion, copy character - } - else - { - switch (*begin) - { - case Ch('<'): - *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('>'): - *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('\''): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); - break; - case Ch('"'): - *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); - break; - case Ch('&'): - *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); - break; - default: - *out++ = *begin; // No expansion, copy character - } - } - ++begin; // Step to next character - } - return out; - } - - // Fill given output iterator with repetitions of the same character - template - inline OutIt fill_chars(OutIt out, int n, Ch ch) - { - for (int i = 0; i < n; ++i) - *out++ = ch; - return out; - } - - // Find character - template - inline bool find_char(const Ch *begin, const Ch *end) - { - while (begin != end) - if (*begin++ == ch) - return true; - return false; - } - - /////////////////////////////////////////////////////////////////////////// - // Internal printing operations - - // Print node - template - inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) - { - // Print proper node type - switch (node->type()) - { - - // Document - case node_document: - out = print_children(out, node, flags, indent); - break; - - // Element - case node_element: - out = print_element_node(out, node, flags, indent); - break; - - // Data - case node_data: - out = print_data_node(out, node, flags, indent); - break; - - // CDATA - case node_cdata: - out = print_cdata_node(out, node, flags, indent); - break; - - // Declaration - case node_declaration: - out = print_declaration_node(out, node, flags, indent); - break; - - // Comment - case node_comment: - out = print_comment_node(out, node, flags, indent); - break; - - // Doctype - case node_doctype: - out = print_doctype_node(out, node, flags, indent); - break; - - // Pi - case node_pi: - out = print_pi_node(out, node, flags, indent); - break; - - // Unknown - default: - assert(0); - break; - } - - // If indenting not disabled, add line break after node - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - - // Return modified iterator - return out; - } - - // Print children of the node - template - inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) - { - for (xml_node *child = node->first_node(); child; child = child->next_sibling()) - out = print_node(out, child, flags, indent); - return out; - } - - // Print attributes of the node - template - inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) - { - for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) - { - if (attribute->name() && attribute->value()) - { - // Print attribute name - *out = Ch(' '), ++out; - out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); - *out = Ch('='), ++out; - // Print attribute value using appropriate quote type - if (find_char(attribute->value(), attribute->value() + attribute->value_size())) - { - *out = Ch('\''), ++out; - out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); - *out = Ch('\''), ++out; - } - else - { - *out = Ch('"'), ++out; - out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); - *out = Ch('"'), ++out; - } - } - } - return out; - } - - // Print data node - template - inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_data); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); - return out; - } - - // Print data node - template - inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_cdata); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'); ++out; - *out = Ch('!'); ++out; - *out = Ch('['); ++out; - *out = Ch('C'); ++out; - *out = Ch('D'); ++out; - *out = Ch('A'); ++out; - *out = Ch('T'); ++out; - *out = Ch('A'); ++out; - *out = Ch('['); ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch(']'); ++out; - *out = Ch(']'); ++out; - *out = Ch('>'); ++out; - return out; - } - - // Print element node - template - inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_element); - - // Print element name and attributes, if any - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - out = print_attributes(out, node, flags); - - // If node is childless - if (node->value_size() == 0 && !node->first_node()) - { - // Print childless node tag ending - *out = Ch('/'), ++out; - *out = Ch('>'), ++out; - } - else - { - // Print normal node tag ending - *out = Ch('>'), ++out; - - // Test if node contains a single data node only (and no other nodes) - xml_node *child = node->first_node(); - if (!child) - { - // If node has no children, only print its value without indenting - out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); - } - else if (child->next_sibling() == 0 && child->type() == node_data) - { - // If node has a sole data child, only print its value without indenting - out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); - } - else - { - // Print all children with full indenting - if (!(flags & print_no_indenting)) - *out = Ch('\n'), ++out; - out = print_children(out, node, flags, indent + 1); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - } - - // Print node end - *out = Ch('<'), ++out; - *out = Ch('/'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch('>'), ++out; - } - return out; - } - - // Print declaration node - template - inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) - { - // Print declaration start - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - *out = Ch('x'), ++out; - *out = Ch('m'), ++out; - *out = Ch('l'), ++out; - - // Print attributes - out = print_attributes(out, node, flags); - - // Print declaration end - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - - return out; - } - - // Print comment node - template - inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_comment); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('-'), ++out; - *out = Ch('-'), ++out; - *out = Ch('>'), ++out; - return out; - } - - // Print doctype node - template - inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_doctype); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('!'), ++out; - *out = Ch('D'), ++out; - *out = Ch('O'), ++out; - *out = Ch('C'), ++out; - *out = Ch('T'), ++out; - *out = Ch('Y'), ++out; - *out = Ch('P'), ++out; - *out = Ch('E'), ++out; - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('>'), ++out; - return out; - } - - // Print pi node - template - inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) - { - assert(node->type() == node_pi); - if (!(flags & print_no_indenting)) - out = fill_chars(out, indent, Ch('\t')); - *out = Ch('<'), ++out; - *out = Ch('?'), ++out; - out = copy_chars(node->name(), node->name() + node->name_size(), out); - *out = Ch(' '), ++out; - out = copy_chars(node->value(), node->value() + node->value_size(), out); - *out = Ch('?'), ++out; - *out = Ch('>'), ++out; - return out; - } - - } - //! \endcond - - /////////////////////////////////////////////////////////////////////////// - // Printing - - //! Prints XML to given output iterator. - //! \param out Output iterator to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output iterator pointing to position immediately after last character of printed text. - template - inline OutIt print(OutIt out, const xml_node &node, int flags = 0) - { - return internal::print_node(out, &node, flags, 0); - } - -#ifndef RAPIDXML_NO_STREAMS - - //! Prints XML to given output stream. - //! \param out Output stream to print to. - //! \param node Node to be printed. Pass xml_document to print entire document. - //! \param flags Flags controlling how XML is printed. - //! \return Output stream. - template - inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) - { - print(std::ostream_iterator(out), node, flags); - return out; - } - - //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. - //! \param out Output stream to print to. - //! \param node Node to be printed. - //! \return Output stream. - template - inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) - { - return print(out, node); - } - -#endif - -} - -#endif diff --git a/libs/network/example/rapidxml/rapidxml_utils.hpp b/libs/network/example/rapidxml/rapidxml_utils.hpp deleted file mode 100644 index 37c29535f..000000000 --- a/libs/network/example/rapidxml/rapidxml_utils.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef RAPIDXML_UTILS_HPP_INCLUDED -#define RAPIDXML_UTILS_HPP_INCLUDED - -// Copyright (C) 2006, 2009 Marcin Kalicinski -// Version 1.13 -// Revision $DateTime: 2009/05/13 01:46:17 $ -//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful -//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. - -#include "rapidxml.hpp" -#include -#include -#include -#include - -namespace rapidxml -{ - - //! Represents data loaded from a file - template - class file - { - - public: - - //! Loads file into the memory. Data will be automatically destroyed by the destructor. - //! \param filename Filename to load. - file(const char *filename) - { - using namespace std; - - // Open stream - basic_ifstream stream(filename, ios::binary); - if (!stream) - throw runtime_error(string("cannot open file ") + filename); - stream.unsetf(ios::skipws); - - // Determine stream size - stream.seekg(0, ios::end); - size_t size = stream.tellg(); - stream.seekg(0); - - // Load data and add terminating 0 - m_data.resize(size + 1); - stream.read(&m_data.front(), static_cast(size)); - m_data[size] = 0; - } - - //! Loads file into the memory. Data will be automatically destroyed by the destructor - //! \param stream Stream to load from - file(std::basic_istream &stream) - { - using namespace std; - - // Load data and add terminating 0 - stream.unsetf(ios::skipws); - m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); - if (stream.fail() || stream.bad()) - throw runtime_error("error reading stream"); - m_data.push_back(0); - } - - //! Gets file data. - //! \return Pointer to data of file. - Ch *data() - { - return &m_data.front(); - } - - //! Gets file data. - //! \return Pointer to data of file. - const Ch *data() const - { - return &m_data.front(); - } - - //! Gets file data size. - //! \return Size of file data, in characters. - std::size_t size() const - { - return m_data.size(); - } - - private: - - std::vector m_data; // File data - - }; - - //! Counts children of node. Time complexity is O(n). - //! \return Number of children of node - template - inline std::size_t count_children(xml_node *node) - { - xml_node *child = node->first_node(); - std::size_t count = 0; - while (child) - { - ++count; - child = child->next_sibling(); - } - return count; - } - - //! Counts attributes of node. Time complexity is O(n). - //! \return Number of attributes of node - template - inline std::size_t count_attributes(xml_node *node) - { - xml_attribute *attr = node->first_attribute(); - std::size_t count = 0; - while (attr) - { - ++count; - attr = attr->next_attribute(); - } - return count; - } - -} - -#endif diff --git a/libs/network/example/rss/main.cpp b/libs/network/example/rss/main.cpp deleted file mode 100644 index 141f7c335..000000000 --- a/libs/network/example/rss/main.cpp +++ /dev/null @@ -1,37 +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 "rss.hpp" -#include -#include -#include - -int main(int argc, char * argv[]) { - using namespace boost::network; - - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - - try { - http::client client; - http::client::request request(argv[1]); - request << header("Connection", "close"); - http::client::response response = client.get(request); - rss::channel channel(response); - - std::cout << "Channel: " << channel.title() << " (" << channel.description() << ")" << std::endl; - BOOST_FOREACH(const rss::item &item, channel) { - std::cout << item.title() << " (" << item.author() << ")" << std::endl; - } - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - } - - return 0; -} diff --git a/libs/network/example/rss/rss.cpp b/libs/network/example/rss/rss.cpp deleted file mode 100644 index f4864c1ef..000000000 --- a/libs/network/example/rss/rss.cpp +++ /dev/null @@ -1,75 +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 "rss.hpp" -#include "../rapidxml/rapidxml.hpp" -#include -#include - - -namespace boost { -namespace network { -namespace rss { -channel::channel(const http::client::response &response) { - std::string response_body = body(response); - rapidxml::xml_document<> doc; - doc.parse<0>(const_cast(response_body.c_str())); - - rapidxml::xml_node<> *rss = doc.first_node("rss"); - if (!rss) { - throw std::runtime_error("Invalid RSS feed."); - } - - rapidxml::xml_node<> *channel = rss->first_node("channel"); - if (!channel) { - throw std::runtime_error("Invalid RSS channel."); - } - - rapidxml::xml_node<> *title = channel->first_node("title"); - if (title) { - title_ = title->first_node()->value(); - } - - rapidxml::xml_node<> *description = channel->first_node("description"); - if (description) { - description_ = description->first_node()->value(); - } - - rapidxml::xml_node<> *link = channel->first_node("link"); - if (link) { - link_ = link->first_node()->value(); - } - - rapidxml::xml_node<> *author = channel->first_node("author"); - if (author) { - author_ = author->first_node()->value(); - } - - rapidxml::xml_node<> *item = channel->first_node("item"); - while (item) { - items_.push_back(rss::item()); - - rapidxml::xml_node<> *title = item->first_node("title"); - if (title) { - items_.back().set_title(title->first_node()->value()); - } - - rapidxml::xml_node<> *author = item->first_node("author"); - if (author) { - items_.back().set_author(author->first_node()->value()); - } - - rapidxml::xml_node<> *description = item->first_node("description"); - if (description) { - items_.back().set_description(description->first_node()->value()); - } - - item = item->next_sibling(); - } -} -} // namespace rss -} // namespace network -} // namespace boost diff --git a/libs/network/example/rss/rss.hpp b/libs/network/example/rss/rss.hpp deleted file mode 100644 index 12acd4ad0..000000000 --- a/libs/network/example/rss/rss.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 ___RSS_INC__ -# define ___RSS_INC__ - - -# include -# include -# include - - -namespace boost { -namespace network { -namespace rss { -class item { - -public: - - void set_title(const std::string &title) { - title_ = title; - } - - std::string title() const { - return title_; - } - - void set_author(const std::string &author) { - author_ = author; - } - - std::string author() const { - return author_; - } - - void set_description(const std::string &description) { - description_ = description; - } - - std::string description() const { - return description_; - } - -private: - - std::string title_; - std::string author_; - std::string description_; - -}; - -class channel { - -public: - typedef item value_type; - typedef std::vector::iterator iterator; - typedef std::vector::const_iterator const_iterator; - - channel(const http::client::response &response); - - std::string title() const { - return title_; - } - - std::string description() const { - return description_; - } - - std::string link() const { - return link_; - } - - std::string author() const { - return author_; - } - - unsigned int item_count() const { - return items_.size(); - } - - iterator begin() { - return items_.begin(); - } - - iterator end() { - return items_.end(); - } - - const_iterator begin() const { - return items_.begin(); - } - - const_iterator end() const { - return items_.end(); - } - -private: - - std::string title_; - std::string description_; - std::string link_; - std::string author_; - std::vector items_; - -}; -} // namespace rss -} // namespace network -} // namespace boost - -#endif // ___RSS_INC__ 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/twitter/rapidjson/document.h b/libs/network/example/twitter/rapidjson/document.h deleted file mode 100644 index f956ea97d..000000000 --- a/libs/network/example/twitter/rapidjson/document.h +++ /dev/null @@ -1,806 +0,0 @@ -#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_ diff --git a/libs/network/example/twitter/rapidjson/filestream.h b/libs/network/example/twitter/rapidjson/filestream.h deleted file mode 100644 index 24573aa48..000000000 --- a/libs/network/example/twitter/rapidjson/filestream.h +++ /dev/null @@ -1,46 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/internal/pow10.h deleted file mode 100644 index 0852539e7..000000000 --- a/libs/network/example/twitter/rapidjson/internal/pow10.h +++ /dev/null @@ -1,54 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/internal/stack.h deleted file mode 100644 index 6faefdee7..000000000 --- a/libs/network/example/twitter/rapidjson/internal/stack.h +++ /dev/null @@ -1,82 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/internal/strfunc.h deleted file mode 100644 index 47b8ac075..000000000 --- a/libs/network/example/twitter/rapidjson/internal/strfunc.h +++ /dev/null @@ -1,24 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/prettywriter.h deleted file mode 100644 index 6f282933d..000000000 --- a/libs/network/example/twitter/rapidjson/prettywriter.h +++ /dev/null @@ -1,152 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/rapidjson.h deleted file mode 100644 index 14b0c3a3c..000000000 --- a/libs/network/example/twitter/rapidjson/rapidjson.h +++ /dev/null @@ -1,512 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/reader.h deleted file mode 100644 index a01649781..000000000 --- a/libs/network/example/twitter/rapidjson/reader.h +++ /dev/null @@ -1,664 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/stringbuffer.h deleted file mode 100644 index d69e3d1cc..000000000 --- a/libs/network/example/twitter/rapidjson/stringbuffer.h +++ /dev/null @@ -1,49 +0,0 @@ -#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/libs/network/example/twitter/rapidjson/writer.h deleted file mode 100644 index 1d028cc69..000000000 --- a/libs/network/example/twitter/rapidjson/writer.h +++ /dev/null @@ -1,224 +0,0 @@ -#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/libs/network/example/twitter/search.cpp deleted file mode 100644 index 1d0f2fafa..000000000 --- a/libs/network/example/twitter/search.cpp +++ /dev/null @@ -1,54 +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) - - -#include -#include "rapidjson/rapidjson.h" -#include "rapidjson/document.h" -#include - -// This example uses the Twitter Search API. -// -// https://dev.twitter.com/docs/using-search - -int main(int argc, char *argv[]) { - using namespace boost::network; - using namespace rapidjson; - - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - - try { - http::client client; - - uri::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); - http::client::response response = client.get(request); - - Document d; - if (!d.Parse<0>(response.body().c_str()).HasParseError()) { - const Value &results = d["results"]; - for (SizeType i = 0; i < results.Size(); ++i) - { - const Value &user = results[i]["from_user_name"]; - const Value &text = results[i]["text"]; - std::cout << "From: " << user.GetString() << std::endl - << " " << text.GetString() << std::endl - << std::endl; - } - } - } - catch (std::exception &e) { - std::cerr << e.what() << std::endl; - } - - 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_get_timeout_test.cpp b/libs/network/test/http/client_get_timeout_test.cpp deleted file mode 100644 index 4f8aa5e1b..000000000 --- a/libs/network/test/http/client_get_timeout_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 Timeout Test -#include -#include -#include "client_types.hpp" - -namespace http = boost::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::uint16_t port_ = port(request); - typename client::response::string_type 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/libs/network/test/http/client_include_inlined.cpp deleted file mode 100644 index a83664800..000000000 --- a/libs/network/test/http/client_include_inlined.cpp +++ /dev/null @@ -1,22 +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_NETWORK_NO_LIB -#include - -int main(int argc, char * argv[]) { - using namespace boost; - using namespace boost::network; - http::client c; - http::client::request req("http://www.boost.org/"); - try { - http::client::response res = c.get(req); - } catch (...) { - // ignore the error, we just want to make sure - // the interface works inlined. - } - return 0; -} - diff --git a/libs/network/test/http/client_localhost_normal_test.cpp b/libs/network/test/http/client_localhost_normal_test.cpp deleted file mode 100644 index 3a3711c1c..000000000 --- a/libs/network/test/http/client_localhost_normal_test.cpp +++ /dev/null @@ -1,354 +0,0 @@ -// -// 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) -// -// Changes by Kim Grasman 2008 -// Changes by Dean Michael Berris 2008, 2010 - -#define BOOST_TEST_MODULE http 1.0 localhost tests - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "http_test_server.hpp" - -using std::cout; -using std::endl; - -namespace { - const std::string base_url = "http://localhost:8000/"; - const std::string cgi_url = base_url + "/cgi-bin/requestinfo.py"; - - struct running_server_fixture - { - // NOTE: Can't use BOOST_REQUIRE_MESSAGE here, as Boost.Test data structures - // are not fully set up when the global fixture runs. - running_server_fixture() { - if( !server.start() ) - cout << "Failed to start HTTP server for test!" << endl; - } - - ~running_server_fixture() { - if( !server.stop() ) - cout << "Failed to stop HTTP server for test!" << endl; - } - - http_test_server server; - }; - - std::size_t readfile(std::ifstream& file, std::vector& buffer) { - using std::ios; - - std::istreambuf_iterator src(file); - std::istreambuf_iterator eof; - std::copy(src, eof, std::back_inserter(buffer)); - - return buffer.size(); - } - - std::map parse_headers(std::string const& body) { - std::map headers; - - std::istringstream stream(body); - while (stream.good()) - { - std::string line; - std::getline(stream, line); - if (!stream.eof()) - { - std::size_t colon = line.find(':'); - if (colon != std::string::npos) - { - std::string header = line.substr(0, colon); - std::string value = line.substr(colon + 2); - headers[header] = value; - } - } - } - - return headers; - } - - std::string get_content_length(std::string const& content) { - return boost::lexical_cast(content.length()); - } - -} - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - // Uncomment the below if you're running Python pre-2.6. There was a bug - // in the Python HTTP server for earlier versions that causes this test - // case to fail. - //BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(text_query_preserves_crlf, 2); -#endif - -BOOST_GLOBAL_FIXTURE( running_server_fixture ); - -BOOST_AUTO_TEST_CASE(body_test) { - // Tests presence of body in http responses - using namespace boost::network; - http::client::request request_(base_url); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); - BOOST_CHECK(body(response_).size() != 0); -} - -BOOST_AUTO_TEST_CASE(text_content_type_test) { - // Tests correct parsing of the content-type header sent by the server - using namespace boost::network; - http::client::request request_(base_url); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); - BOOST_REQUIRE(headers(response_).count("Content-type") != 0); - headers_range::type range = headers(response_)["Content-type"]; - BOOST_CHECK(boost::begin(range)->first == "Content-type"); - BOOST_CHECK(boost::begin(range)->second == "text/html"); -} - -BOOST_AUTO_TEST_CASE(binary_content_type_test) { - // Tests correct parsing of content-type for binary files such as .zip files - using namespace boost::network; - http::client::request request_(base_url + "/boost.jpg"); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); - BOOST_REQUIRE(headers(response_).count("Content-type") != 0); - headers_range::type range = headers(response_)["Content-type"]; - BOOST_CHECK(boost::begin(range)->first == "Content-type"); - BOOST_CHECK(boost::begin(range)->second == "image/jpeg"); -} - -BOOST_AUTO_TEST_CASE(content_length_header_test) { - // Uses the test.xml file to ensure that the file was received at the correct length for a text encoding - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); - BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); - headers_range::type range = headers(response_)["Content-Length"]; - BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); - BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).size() != 0); -} - -BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { - // Tests proper transfer of a text file - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); - - http::client::response::string_type body_ = body(response_); - BOOST_CHECK(body(response_).size() != 0); - - using std::ios; - - std::ifstream file("libs/network/test/server/test.xml", ios::in | ios::binary); - if( ! file ) { - file.clear(); - file.open("server/test.xml", ios::in | ios::binary); - } - - BOOST_REQUIRE_MESSAGE( file, "Could not open local test.xml"); - - std::vector memblock; - std::size_t size = readfile(file, memblock); - - BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body_.size(), size); - - if (body(response_).size() == size) { - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); - BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); - } -} - -BOOST_AUTO_TEST_CASE(binary_file_query) { - // Tests proper transfer of a binary image - using namespace boost::network; - http::client::request request_(base_url + "/boost.jpg"); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); - - http::client::response::string_type body_ = body(response_); - BOOST_CHECK(body_.size() != 0); - - using std::ios; - - std::ifstream file("libs/network/test/server/boost.jpg", ios::in | ios::binary); - if( ! file ) { - file.clear(); - file.open("server/boost.jpg", ios::in | ios::binary); - } - - BOOST_REQUIRE_MESSAGE( file, "Could not open boost.jpg locally"); - - std::vector memblock; - std::size_t size = readfile(file, memblock); - - BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body_.size(), size); - - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); - BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); -} - -BOOST_AUTO_TEST_CASE(cgi_query) { - // Get a dynamic request with no Content-Length header - // Ensure that we have a body - using namespace boost::network; - - http::client::request req(cgi_url + "?query=1"); - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.get(req)); - BOOST_CHECK(body(r).size() != 0); - BOOST_CHECK(boost::empty(headers(r)["Content-Length"])); -} - -BOOST_AUTO_TEST_CASE(cgi_multi_line_headers) { - using namespace boost::network; - - http::client::request req(base_url + "/cgi-bin/multiline-header.py?query=1"); - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.get(req)); - BOOST_CHECK(body(r).size() != 0); - BOOST_CHECK(boost::empty(headers(r)["Content-Type"])); - headers_range::type range=headers(r)["X-CppNetlib-Test"]; - BOOST_REQUIRE(boost::begin(range) != boost::end(range)); - BOOST_REQUIRE(distance(range) == 2); - BOOST_CHECK_EQUAL(boost::begin(range)->second, std::string("multi-line-header")); - BOOST_CHECK_EQUAL((++boost::begin(range))->second, std::string("that-should-concatenate")); -} - -BOOST_AUTO_TEST_CASE(file_not_found) { - // Request for a non existing file. - // Ensure that we have a body even in the presence of an error response - using namespace boost::network; - - http::client::request req(base_url + "/file_not_found"); - http::client c; - http::client::response r = c.get(req); - - BOOST_CHECK(body(r).size() != 0); -} - -BOOST_AUTO_TEST_CASE(head_test) { - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_; - BOOST_REQUIRE_NO_THROW( response_ = client_.head(request_) ); - BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); - headers_range::type range = headers(response_)["Content-Length"]; - BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); - BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).size() == 0); -} - -BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { - // This test checks that the headers echoed through echo_headers.py - // are in fact the same as what are sent through the POST request - using namespace boost::network; - - const std::string postdata = "empty"; - const std::string content_length = get_content_length(postdata); - const std::string content_type = "application/x-www-form-urlencoded"; - - http::client::request req(base_url + "/cgi-bin/echo_headers.py"); - req << header("Content-Length", content_length); - req << header("Content-Type", content_type); - req << body(postdata); - - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.post(req)); - - std::map headers = parse_headers(body(r)); - BOOST_CHECK_EQUAL(headers["content-length"], content_length); - BOOST_CHECK_EQUAL(headers["content-type"], content_type); -} - -BOOST_AUTO_TEST_CASE(post_with_implicit_headers) { - // This test checks that post(request, body) derives Content-Length - // and Content-Type - using namespace boost::network; - - const std::string postdata = "empty"; - - http::client::request req(base_url + "/cgi-bin/echo_headers.py"); - - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); - - std::map headers = parse_headers(body(r)); - BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); - BOOST_CHECK_EQUAL(headers["content-type"], "x-application/octet-stream"); -} - -BOOST_AUTO_TEST_CASE(post_with_explicit_content_type) { - // This test checks that post(request, content_type, body) derives Content-Length, - // and keeps Content-Type - using namespace boost::network; - - const std::string postdata = "empty"; - const std::string content_type = "application/x-my-content-type"; - - http::client::request req(base_url + "/cgi-bin/echo_headers.py"); - - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.post(req, content_type, postdata)); - - std::map headers = parse_headers(body(r)); - BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); - BOOST_CHECK_EQUAL(headers["content-type"], content_type); -} - -BOOST_AUTO_TEST_CASE(post_body_default_content_type) { - // This test checks that post(request, body) gets the post data - // through to the server - using namespace boost::network; - - const std::string postdata = "firstname=bill&lastname=badger"; - - http::client::request req(base_url + "/cgi-bin/echo_body.py"); - - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); - http::client::response::string_type body_ = body(r); - BOOST_CHECK_EQUAL(postdata, body_); -} - -BOOST_AUTO_TEST_CASE(post_with_custom_headers) { - // This test checks that custom headers pass through to the server - // when posting - using namespace boost::network; - - http::client::request req(base_url + "/cgi-bin/echo_headers.py"); - req << header("X-Cpp-Netlib", "rocks!"); - - http::client c; - http::client::response r; - BOOST_REQUIRE_NO_THROW(r = c.post(req, std::string())); - - std::map headers = parse_headers(body(r)); - BOOST_CHECK_EQUAL(headers["x-cpp-netlib"], "rocks!"); -} diff --git a/libs/network/test/http/client_localhost_ssl_test.cpp b/libs/network/test/http/client_localhost_ssl_test.cpp deleted file mode 100644 index 5bbf20390..000000000 --- a/libs/network/test/http/client_localhost_ssl_test.cpp +++ /dev/null @@ -1,321 +0,0 @@ -// -// Copyright Divye Kapoor 2008. -// 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) -// -// Changes by Kim Grasman 2008 -// Changes by Dean Michael Berris 2008, 2009 - -#define BOOST_TEST_MODULE https 1.0 localhost tests - -#include -#include -#include -#include -#include -#include -#include -#include - -#define HTTPS_SERVER_TEST -#include "http_test_server.hpp" - -using std::cout; -using std::endl; - -namespace { - const std::string base_url = "https://localhost:8443/"; - const std::string cgi_url = base_url + "/cgi-bin/requestinfo.py"; - - struct running_server_fixture - { - // NOTE: Can't use BOOST_REQUIRE_MESSAGE here, as Boost.Test data structures - // are not fully set up when the global fixture runs. - running_server_fixture() { - if( !server.start() ) - cout << "Failed to start HTTP server for test!" << endl; - } - - ~running_server_fixture() { - if( !server.stop() ) - cout << "Failed to stop HTTP server for test!" << endl; - } - - http_test_server server; - }; - - std::size_t readfile(std::ifstream& file, std::vector& buffer) { - using std::ios; - - std::istreambuf_iterator src(file); - std::istreambuf_iterator eof; - std::copy(src, eof, std::back_inserter(buffer)); - - return buffer.size(); - } - -} - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - // Uncomment the below if you're running Python pre-2.6. There was a bug - // in the Python HTTP server for earlier versions that causes this test - // case to fail. - //BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(text_query_preserves_crlf, 2); -#endif - -BOOST_GLOBAL_FIXTURE( running_server_fixture ); - -BOOST_AUTO_TEST_CASE(body_test) { - // Tests presence of body in http responses - using namespace boost::network; - http::client::request request_(base_url); - http::client client_; - http::client::response response_ = client_.get(request_); - BOOST_CHECK(body(response_).size() != 0); -} - -BOOST_AUTO_TEST_CASE(text_content_type_test) { - // Tests correct parsing of the content-type header sent by the server - using namespace boost::network; - http::client::request request_(base_url); - http::client client_; - http::client::response response_ = client_.get(request_); - BOOST_REQUIRE(headers(response_).count("Content-type") != 0); - headers_range::type range = headers(response_)["Content-type"]; - BOOST_CHECK(boost::begin(range)->first == "Content-type"); - BOOST_CHECK(boost::begin(range)->second == "text/html"); -} - -BOOST_AUTO_TEST_CASE(binary_content_type_test) { - // Tests correct parsing of content-type for binary files such as .zip files - using namespace boost::network; - http::client::request request_(base_url + "/boost.jpg"); - http::client client_; - http::client::response response_ = client_.get(request_); - BOOST_REQUIRE(headers(response_).count("Content-type") != 0); - headers_range::type range = headers(response_)["Content-type"]; - BOOST_CHECK(boost::begin(range)->first == "Content-type"); - BOOST_CHECK(boost::begin(range)->second == "image/jpeg"); -} - -BOOST_AUTO_TEST_CASE(content_length_header_test) { - // Uses the test.xml file to ensure that the file was received at the correct length for a text encoding - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_ = client_.get(request_); - BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); - headers_range::type range = headers(response_)["Content-Length"]; - BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); - BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).size() != 0); -} - -BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { - // Tests proper transfer of a text file - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_ = client_.get(request_); - - http::client::response::string_type body_ = body(response_); - BOOST_CHECK(body_.size() != 0); - - using std::ios; - - std::ifstream file("libs/network/test/server/test.xml", ios::in | ios::binary); - if( ! file ) { - file.clear(); - file.open("server/test.xml", ios::in | ios::binary); - } - - BOOST_REQUIRE_MESSAGE( file, "Could not open local test.xml"); - - std::vector memblock; - std::size_t size = readfile(file, memblock); - - BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).size(), size); - - if (body(response_).size() == size) { - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); - BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); - } -} - -BOOST_AUTO_TEST_CASE(binary_file_query) { - // Tests proper transfer of a binary image - using namespace boost::network; - http::client::request request_(base_url + "/boost.jpg"); - http::client client_; - http::client::response response_; - BOOST_CHECK_NO_THROW(response_ = client_.get(request_)); - - http::client::response::string_type body_ = body(response_); - BOOST_CHECK(body_.size() != 0); - - using std::ios; - - std::ifstream file("libs/network/test/server/boost.jpg", ios::in | ios::binary); - if( ! file ) { - file.clear(); - file.open("server/boost.jpg", ios::in | ios::binary); - } - - BOOST_REQUIRE_MESSAGE( file, "Could not open boost.jpg locally"); - - std::vector memblock; - std::size_t size = readfile(file, memblock); - - BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).size(), size); - - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); - BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); -} - -//BOOST_AUTO_TEST_CASE(cgi_query) { -// // Get a dynamic request with no Content-Length header -// // Ensure that we have a body -// using namespace boost::network; -// -// http::client::request req(cgi_url + "?query=1"); -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.get(req)); -// BOOST_CHECK(body(r).size() != 0); -// BOOST_CHECK(headers(r)["Content-Type"].begin() != headers(r)["Content-Type"].end()); -//} -// -//BOOST_AUTO_TEST_CASE(cgi_multi_line_headers) { -// using namespace boost::network; -// -// http::client::request req(base_url + "/cgi-bin/multiline-header.py?query=1"); -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.get(req)); -// BOOST_CHECK(body(r).size() != 0); -// BOOST_CHECK(headers(r)["Content-Type"].begin() != headers(r)["Content-Type"].end()); -// headers_range::type range=headers(r)["X-CppNetlib-Test"]; -// BOOST_REQUIRE(boost::begin(range) != boost::end(range)); -// BOOST_REQUIRE(distance(range) == 2); -// BOOST_CHECK_EQUAL(boost::begin(range)->second, std::string("multi-line-header")); -// BOOST_CHECK_EQUAL((++boost::begin(range))->second, std::string("that-should-concatenate")); -//} - -BOOST_AUTO_TEST_CASE(file_not_found) { - // Request for a non existing file. - // Ensure that we have a body even in the presence of an error response - using namespace boost::network; - - http::client::request req(base_url + "/file_not_found"); - http::client c; - http::client::response r = c.get(req); - - BOOST_CHECK(body(r).size() != 0); -} - -BOOST_AUTO_TEST_CASE(head_test) { - using namespace boost::network; - http::client::request request_(base_url + "/test.xml"); - http::client client_; - http::client::response response_ = client_.head(request_); - BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); - headers_range::type range = headers(response_)["Content-Length"]; - BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); - BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).size() == 0); -} - -//BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { -// // This test checks that the headers echoed through echo_headers.py -// // are in fact the same as what are sent through the POST request -// using namespace boost::network; -// -// const std::string postdata = "empty"; -// const std::string content_length = get_content_length(postdata); -// const std::string content_type = "application/x-www-form-urlencoded"; -// -// http::client::request req(base_url + "/cgi-bin/echo_headers.py"); -// req << header("Content-Length", content_length); -// req << header("Content-Type", content_type); -// req << body(postdata); -// -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.post(req)); -// -// std::map headers = parse_headers(body(r)); -// BOOST_CHECK_EQUAL(headers["content-length"], content_length); -// BOOST_CHECK_EQUAL(headers["content-type"], content_type); -//} -// -//BOOST_AUTO_TEST_CASE(post_with_implicit_headers) { -// // This test checks that post(request, body) derives Content-Length -// // and Content-Type -// using namespace boost::network; -// -// const std::string postdata = "empty"; -// -// http::client::request req(base_url + "/cgi-bin/echo_headers.py"); -// -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); -// -// std::map headers = parse_headers(body(r)); -// BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); -// BOOST_CHECK_EQUAL(headers["content-type"], "x-application/octet-stream"); -//} -// -//BOOST_AUTO_TEST_CASE(post_with_explicit_content_type) { -// // This test checks that post(request, content_type, body) derives Content-Length, -// // and keeps Content-Type -// using namespace boost::network; -// -// const std::string postdata = "empty"; -// const std::string content_type = "application/x-my-content-type"; -// -// http::client::request req(base_url + "/cgi-bin/echo_headers.py"); -// -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.post(req, content_type, postdata)); -// -// std::map headers = parse_headers(body(r)); -// BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); -// BOOST_CHECK_EQUAL(headers["content-type"], content_type); -//} -// -//BOOST_AUTO_TEST_CASE(post_body_default_content_type) { -// // This test checks that post(request, body) gets the post data -// // through to the server -// using namespace boost::network; -// -// const std::string postdata = "firstname=bill&lastname=badger"; -// -// http::client::request req(base_url + "/cgi-bin/echo_body.py"); -// -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); -// -// BOOST_CHECK_EQUAL(postdata, body(r)); -//} -// -//BOOST_AUTO_TEST_CASE(post_with_custom_headers) { -// // This test checks that custom headers pass through to the server -// // when posting -// using namespace boost::network; -// -// http::client::request req(base_url + "/cgi-bin/echo_headers.py"); -// req << header("X-Cpp-Netlib", "rocks!"); -// -// http::client c; -// http::client::response r; -// BOOST_REQUIRE_NO_THROW(r = c.post(req, std::string())); -// -// std::map headers = parse_headers(body(r)); -// BOOST_CHECK_EQUAL(headers["x-cpp-netlib"], "rocks!"); -//} 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/http_test_server.hpp b/libs/network/test/http/http_test_server.hpp deleted file mode 100644 index 293c9d9d8..000000000 --- a/libs/network/test/http/http_test_server.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// 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) -// -// Changes by Allister Levi Sanchez 2008 -// Changes by Dean Michael Berris 2010 -#ifndef __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ -#define __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ - -#define BOOST_FILESYSTEM_VERSION 3 -#include - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(MIN) - #include - - // ShellExecuteEx - #include - #pragma comment( lib, "shell32" ) -#else - #include // fork, execlp etc. - #include - #include // for waitpid - #include // for chmod - #include // for kill -#endif - -struct http_test_server -{ - bool start() { - using namespace boost::filesystem; - - path script_path = get_server_path(current_path()); - if (script_path.empty()) - return false; - - path cgibin_path = script_path.parent_path() / "cgi-bin"; - if (!set_cgibin_permissions(cgibin_path)) - return false; - - server_child = launch_python_script(script_path); - if (server_child == 0) - return false; - - return true; - } - - bool stop() { - kill_script(server_child); - return true; - } - -private: -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - typedef HANDLE script_handle_t; -#else - typedef pid_t script_handle_t; -#endif - - boost::filesystem::path get_server_path(const boost::filesystem::path& base_path) { - using namespace boost::filesystem; - - const path script_name = -#if defined(HTTPS_SERVER_TEST) - "https_test_server.py" -#else - "http_test_server.py" -#endif - ; - - // if executed from $CPP_NETLIB_HOME - path server_path = base_path / "libs/network/test/server" / script_name; - if (!exists(server_path)) { - // if executed from $CPP_NETLIB_HOME/libs/network/test - server_path = base_path / "server" / script_name; - if (!exists(server_path)) - return path(); - } - - return server_path; - } - - script_handle_t launch_python_script(const boost::filesystem::path& python_script_path) { - using namespace boost::filesystem; - - path::string_type script_name = python_script_path.filename().native(); - path::string_type script_dir = python_script_path.parent_path().native(); - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - SHELLEXECUTEINFOA sei = {0}; - sei.cbSize = sizeof(sei); - sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; - sei.lpVerb = "open"; - sei.lpFile = "python.exe"; - sei.lpParameters = reinterpret_cast(script_name.c_str()); - sei.lpDirectory = reinterpret_cast(script_dir.c_str()); - sei.nShow = SW_SHOWNOACTIVATE; - - if (!ShellExecuteExA(&sei)) - return 0; - - return sei.hProcess; -#else - // Try general Unix code - pid_t child_process = fork(); - if (child_process < 0) - return false; - - if (child_process == 0) { - // child process - - // cd into script dir and launch python script - current_path(script_dir); - - if (execlp("python", "python", script_name.c_str(), (char*)NULL) == -1) - return 0; - } - else { - // parent - sleep(1); - } - - return child_process; -#endif - } - - void kill_script(script_handle_t h) { -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - TerminateProcess(h, 0U); - CloseHandle(h); -#else - kill(h, SIGTERM); -#endif - } - - bool set_cgibin_permissions(const boost::filesystem::path& cgibin_path) { - using namespace boost::filesystem; - -#if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32) - // set the CGI script execute permission - for (directory_iterator i(cgibin_path); i != directory_iterator(); ++i) { - if (is_regular_file(i->status())) { - path::string_type file_path = i->path().string(); - if (chmod(file_path.c_str(), S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH) != 0) - return false; - } - } -#endif - return true; - } - - script_handle_t server_child; -}; - -#endif // __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ - diff --git a/libs/network/test/http/message_async_ready_test.cpp b/libs/network/test/http/message_async_ready_test.cpp deleted file mode 100644 index 60b3502cc..000000000 --- a/libs/network/test/http/message_async_ready_test.cpp +++ /dev/null @@ -1,18 +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 Async Response Test -#include -#include - -namespace http = boost::network::http; - -BOOST_AUTO_TEST_CASE(unready_state_response) { - typedef http::basic_response response; - response r; - BOOST_CHECK(!ready(r)); -} - diff --git a/libs/network/test/http/message_test.cpp b/libs/network/test/http/message_test.cpp deleted file mode 100644 index dde3a9303..000000000 --- a/libs/network/test/http/message_test.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -// 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) - -#define BOOST_TEST_MODULE HTTP message test -#include -#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 -> tag_types; - -struct fixtures { -}; - -BOOST_FIXTURE_TEST_SUITE(http_message_test_suite, fixtures) - -BOOST_AUTO_TEST_CASE_TEMPLATE (request_constructor_test, T, tag_types) { - http::basic_request request("http://boost.org/"); - typedef typename http::basic_request::string_type string_type; - string_type host = http::host(request); - boost::uint16_t port = http::port(request); - string_type path = http::path(request); - string_type query = http::query(request); - string_type anchor = http::anchor(request); - string_type protocol = http::protocol(request); - BOOST_CHECK_EQUAL ( host , "boost.org" ); - BOOST_CHECK_EQUAL ( port , 80u ); - BOOST_CHECK_EQUAL ( path, "/" ); - BOOST_CHECK_EQUAL ( query, "" ); - BOOST_CHECK_EQUAL ( anchor, "" ); - BOOST_CHECK_EQUAL ( protocol, "http"); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (request_copy_constructor_test, T, tag_types) { - http::basic_request request("http://boost.org/handler.php"); - request << header("Content-Type", "text/plain") - << body("Hello, World!") - ; - http::basic_request copy(request); - typedef typename http::basic_request::string_type string_type; - string_type orig_host = http::host(request), - copy_host = http::host(copy); - boost::uint16_t orig_port = http::port(request), - copy_port = http::port(copy); - string_type orig_path = http::path(request), - copy_path = http::path(copy); - string_type orig_body = body(request), - copy_body = body(copy); - BOOST_CHECK_EQUAL ( orig_host, copy_host ); - BOOST_CHECK_EQUAL ( orig_port, copy_port ); - BOOST_CHECK_EQUAL ( orig_path, copy_path ); - BOOST_CHECK_EQUAL ( orig_body, copy_body ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (request_assignment_test, T, tag_types) { - http::basic_request request("http://boost.org/handler.php"); - request << header("Content-Type", "text/plain") - << body("Hello, World!") - ; - http::basic_request copy; - copy = request; - typedef typename http::basic_request::string_type string_type; - string_type orig_host = http::host(request), - copy_host = http::host(copy); - boost::uint16_t orig_port = http::port(request), - copy_port = http::port(copy); - string_type orig_path = http::path(request), - copy_path = http::path(copy); - string_type orig_body = body(request), - copy_body = body(copy); - BOOST_CHECK_EQUAL ( orig_host, copy_host ); - BOOST_CHECK_EQUAL ( orig_port, copy_port ); - BOOST_CHECK_EQUAL ( orig_path, copy_path ); - BOOST_CHECK_EQUAL ( orig_body, copy_body ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (request_swap_test, T, tag_types) { - boost::network::http::basic_request request("http://boost.org/"); - boost::network::http::basic_request other; - swap(other, request); // ADL - typedef typename http::basic_request::string_type string_type; - string_type orig_host = http::host(request), - orig_path = http::path(request), - copy_host = http::host(other), - copy_path = http::path(other); - boost::uint16_t orig_port = http::port(request), - copy_port = http::port(request); - BOOST_CHECK_EQUAL ( orig_host, "" ); - BOOST_CHECK_EQUAL ( orig_port, 80u ); - BOOST_CHECK_EQUAL ( orig_path, "/" ); - BOOST_CHECK_EQUAL ( copy_host, "boost.org" ); - BOOST_CHECK_EQUAL ( copy_port, 80u ); - BOOST_CHECK_EQUAL ( copy_path, "/" ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (request_uri_directive_test, T, tag_types) { - http::basic_request request; - request << http::uri("http://boost.org/"); - typename http::basic_request::string_type uri_ = http::uri(request); - BOOST_CHECK_EQUAL(uri_, "http://boost.org/"); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (response_constructor_test, T, tag_types) { - http::basic_response response; - typename http::basic_response::string_type body_ = body(response); - BOOST_CHECK_EQUAL ( body_, std::string() ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (response_copy_construct_test, T, tag_types) { - using namespace http; - http::basic_response response; - response << http::version("HTTP/1.1") - << http::status(200u) - << body("The quick brown fox jumps over the lazy dog") - << http::status_message("OK") - ; - http::basic_response copy(response); - - typename http::basic_response::string_type - version_orig = version(response) - , version_copy = version(copy); - BOOST_CHECK_EQUAL ( version_orig, version_copy ); - boost::uint16_t status_orig = status(response) - , status_copy = status(copy); - BOOST_CHECK_EQUAL ( status_orig, status_copy ); - typename http::basic_response::string_type - status_message_orig = status_message(response) - , status_message_copy = status_message(copy) - , body_orig = body(response) - , body_copy = body(copy); - BOOST_CHECK_EQUAL ( status_message_orig, status_message_copy ); - BOOST_CHECK_EQUAL ( body_orig, body_copy ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (response_assignment_construct_test, T, tag_types) { - http::basic_response response; - response << http::version("HTTP/1.1") - << http::status(200) - << http::status_message("OK") - << body("The quick brown fox jumps over the lazy dog"); - http::basic_response copy; - copy = response; - typedef typename http::basic_response::string_type string_type; - string_type version_orig = version(response) - , version_copy = version(copy); - BOOST_CHECK_EQUAL ( version_orig, version_copy ); - boost::uint16_t status_orig = status(response) - , status_copy = status(copy); - BOOST_CHECK_EQUAL ( status_orig, status_copy ); - string_type status_message_orig = status_message(response) - , status_message_copy = status_message(copy); - BOOST_CHECK_EQUAL ( status_message_orig, status_message_copy ); - string_type body_orig = body(response) - , body_copy = body(copy); - BOOST_CHECK_EQUAL ( body_orig, body_copy ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE (response_swap_test, T, tag_types) { - using namespace boost::network::http; - http::basic_response response; - response << version("HTTP/1.1") - << status(200) - << status_message("OK") - << body("RESPONSE"); - boost::network::http::basic_response swapped; - BOOST_REQUIRE_NO_THROW(swap(response, swapped)); - BOOST_CHECK_EQUAL ( response.version(), std::string() ); - BOOST_CHECK_EQUAL ( response.status(), 0u ); - BOOST_CHECK_EQUAL ( response.status_message(), std::string() ); - typename http::basic_response::string_type - orig_body = body(response) - , swapped_body = body(swapped); - BOOST_CHECK_EQUAL ( orig_body, std::string() ); - BOOST_CHECK_EQUAL ( swapped.version(), std::string("HTTP/1.1") ); - BOOST_CHECK_EQUAL ( swapped.status(), 200u ); - BOOST_CHECK_EQUAL ( swapped.status_message(), std::string("OK") ); - BOOST_CHECK_EQUAL ( swapped_body, std::string("RESPONSE") ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/libs/network/test/http/request_incremental_parser_test.cpp b/libs/network/test/http/request_incremental_parser_test.cpp deleted file mode 100644 index 00f1657f2..000000000 --- a/libs/network/test/http/request_incremental_parser_test.cpp +++ /dev/null @@ -1,134 +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 Incremental Request Parser Test -#include -#include -#include -#include -#include -#include -#include -#include - -/** Synopsis - * - * Test for the HTTP Request Incremental Parser - * -------------------------------------------- - * - * In this test we fully intend to specify how an incremental HTTP request - * parser should be used. This follows the HTTP Response Incremental Parser - * example, and models the Incremental Parser Concept. - * - */ - -namespace tags = boost::network::tags; -namespace logic = boost::logic; -namespace fusion = boost::fusion; -using namespace boost::network::http; - -BOOST_AUTO_TEST_CASE(incremental_parser_constructor) { - request_parser p; // default constructible -} - -BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_method) { - request_parser p; - logic::tribool parsed_ok = false; - typedef request_parser request_parser_type; - typedef boost::iterator_range range_type; - range_type result_range; - - std::string valid_http_method = "GET "; - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::method_done - , valid_http_method); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - std::string parsed(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; - - std::string invalid_http_method = "get "; - p.reset(); - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::method_done - , invalid_http_method); - BOOST_CHECK_EQUAL(parsed_ok, false); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; -} - -BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_uri) { - request_parser p; - logic::tribool parsed_ok = false; - typedef request_parser request_parser_type; - typedef boost::iterator_range range_type; - range_type result_range; - - std::string valid_http_request = "GET / HTTP/1.1\r\n"; - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::uri_done, valid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - std::string parsed(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; - - std::string invalid_http_request = "GET /\t HTTP/1.1\r\n"; - p.reset(); - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::uri_done, invalid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, false); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; -} - -BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) { - request_parser p; - logic::tribool parsed_ok = false; - typedef request_parser request_parser_type; - typedef boost::iterator_range range_type; - range_type result_range; - - std::string valid_http_request = "GET / HTTP/1.1\r\n"; - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::version_done, valid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - std::string parsed(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; - - std::string invalid_http_request = "GET / HTTP 1.1\r\n"; - p.reset(); - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::version_done, invalid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, false); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; -} - -BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_headers) { - request_parser p; - logic::tribool parsed_ok = false; - typedef request_parser request_parser_type; - typedef boost::iterator_range range_type; - range_type result_range; - - std::string valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\n\r\n"; - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::headers_done, valid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - std::string parsed(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; - - valid_http_request = "GET / HTTP/1.1\r\nHost: cpp-netlib.org\r\nConnection: close\r\n\r\n"; - p.reset(); - fusion::tie(parsed_ok, result_range) = p.parse_until( - request_parser_type::headers_done, valid_http_request); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " [state:" << p.state() << "] " << std::endl; -} - 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/response_incremental_parser_test.cpp b/libs/network/test/http/response_incremental_parser_test.cpp deleted file mode 100644 index 9026ec0bc..000000000 --- a/libs/network/test/http/response_incremental_parser_test.cpp +++ /dev/null @@ -1,215 +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) - -#define BOOST_TEST_MODULE HTTP Incremental Parser Test -#include -#include -#include -#include -#include -#include -#include - -/** Synopsis - * - * Test for HTTP Response Incremental Parser - * ----------------------------------------- - * - * In this test we fully intend to specify how an incremental - * HTTP Response parser should be used. This defines the bare - * minimum implementation for an Incremental Parser concept, - * and shall follow an interface that puts a premium on simplicity. - * - * The motivation for coming up with a re-startable stateful - * incremental parser comes from the requirement in the asynchronous - * HTTP client implementation that allows for parsing an HTTP - * response as the data comes in. By being able to process some - * parts of the message ahead of others, we are allowed to set - * the promise values bound to futures that the users of the client - * would be waiting on. - * - * The basic interface that we're looking for is a means of providing: - * - a range of input - * - a means of resetting the parser's state - * - a means of initializing the parser to a given state - * - a parse_until function that takes a state as parameter and - * a range from which the parser will operate on, returns - * a tuple of a boost::logic::tribool and a resulting range - * - * One of the possible implementations can use the Boost.MSM library - * to create the state machine. The test however does not specify what - * implementation should be used, but rather that the interface and the - * semantics are according to expectations. - * - * Date: September 9, 2010 - * Author: Dean Michael Berris - */ - -namespace tags = boost::network::tags; -namespace logic = boost::logic; -namespace fusion = boost::fusion; -using namespace boost::network::http; - -BOOST_AUTO_TEST_CASE(incremental_parser_constructor) { - response_parser p; // default constructible -} - -/** In this test we want to be able to parse incrementally a - * range passed in as input, and specify to the parser that - * it should stop when we reach a certain state. In this case - * we want it to parse until it either finds the HTTP version - * or there is an error encountered. - */ -BOOST_AUTO_TEST_CASE(incremental_parser_parse_http_version) { - response_parser p; // default constructible - logic::tribool parsed_ok = false; - typedef response_parser response_parser_type; - typedef boost::iterator_range range_type; - range_type result_range; - - std::string valid_http_version = "HTTP/1.0 "; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_version_done, - valid_http_version); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - std::string parsed(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - p.reset(); - valid_http_version = "HTTP/1.1 "; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_version_done, - valid_http_version); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(!boost::empty(result_range)); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - - p.reset(); - std::string invalid_http_version = "HTTP 1.0"; - parsed_ok = logic::indeterminate; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_version_done, - invalid_http_version); - BOOST_CHECK_EQUAL(parsed_ok, false); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - - p.reset(); - valid_http_version = "HTTP/0.9 "; - parsed_ok = logic::indeterminate; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_version_done, - valid_http_version); - BOOST_CHECK_EQUAL(parsed_ok, true); - parsed.assign(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; -} - -/** In this test we then want to check that we can parse a status - * string right after the version string. We should expect that - * the parser doesn't do any conversions from string to integer - * and outsource that part to the user of the parser. - */ -BOOST_AUTO_TEST_CASE(incremental_parser_parse_status) { - typedef response_parser response_parser_type; - typedef boost::iterator_range range_type; - // We want to create a parser that has been initialized to a specific - // state. In this case we assume that the parser has already parsed - // the version part of the HTTP Response. - response_parser_type p(response_parser_type::http_version_done); - - std::string valid_status = "200 "; - logic::tribool parsed_ok; - range_type result_range; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_status_done, - valid_status); - BOOST_CHECK_EQUAL(parsed_ok, true); - std::string parsed = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - - p.reset(response_parser_type::http_version_done); - std::string invalid_status = "200x "; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_status_done, - invalid_status); - BOOST_CHECK_EQUAL(parsed_ok, false); - parsed = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; -} - -/** In this test then we get the rest of the first line of the HTTP - * Response, and treat it as the status message. - */ -BOOST_AUTO_TEST_CASE(incremental_parser_parse_status_message) { - typedef response_parser response_parser_type; - typedef boost::iterator_range range_type; - response_parser_type p(response_parser_type::http_status_done); - - std::string valid_status_message = "OK\r\nServer: Foo"; - logic::tribool parsed_ok; - range_type result_range; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_status_message_done, - valid_status_message); - BOOST_CHECK_EQUAL(parsed_ok, true); - std::string parsed = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - - p.reset(response_parser_type::http_status_done); - valid_status_message = "OK\r\n"; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_status_message_done, - valid_status_message); - BOOST_CHECK_EQUAL(parsed_ok, true); - parsed = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; - - p.reset(response_parser_type::http_status_done); - valid_status_message = "Internal Server Error\r\n"; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_status_message_done, - valid_status_message); - BOOST_CHECK_EQUAL(parsed_ok, true); - parsed = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed << " state=" << p.state() << std::endl; -} - -/** This test specifices how one-line-per-header parsing happens incrementally. - */ -BOOST_AUTO_TEST_CASE(incremental_parser_parse_header_lines) { - typedef response_parser response_parser_type; - typedef boost::iterator_range range_type; - response_parser_type p(response_parser_type::http_status_message_done); - - std::string valid_headers = "Server: Foo\r\nContent-Type: application/json\r\n\r\n"; - logic::tribool parsed_ok; - range_type result_range; - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_header_line_done, - valid_headers); - BOOST_CHECK_EQUAL(parsed_ok, true); - std::string parsed1 = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed1 << " state=" << p.state() << std::endl; - p.reset(response_parser_type::http_status_message_done); - std::string::const_iterator end = valid_headers.end(); - valid_headers.assign(boost::end(result_range), end); - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_header_line_done, - valid_headers); - BOOST_CHECK_EQUAL(parsed_ok, true); - std::string parsed2 = std::string(boost::begin(result_range), boost::end(result_range)); - std::cout << "PARSED: " << parsed2 << " state=" << p.state() << std::endl; - valid_headers.assign(boost::end(result_range), end); - p.reset(response_parser_type::http_status_message_done); - fusion::tie(parsed_ok, result_range) = p.parse_until( - response_parser_type::http_headers_done, - valid_headers); - BOOST_CHECK_EQUAL(parsed_ok, true); - BOOST_CHECK(parsed1 != parsed2); -} - diff --git a/libs/network/test/http/server_async.cpp b/libs/network/test/http/server_async.cpp deleted file mode 100644 index 95f8646dd..000000000 --- a/libs/network/test/http/server_async.cpp +++ /dev/null @@ -1,53 +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 - -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(name(header), "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"} - , {"Content-Length", "13"} - }; - static std::string hello_world("Hello, World!"); - connection->set_status(server::connection::ok); - connection->set_headers(boost::make_iterator_range(headers, headers+4)); - connection->write(hello_world); - } -}; - -int main(int argc, char * argv[]) { - utils::thread_pool thread_pool(2); - 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); - instance.run(); - return 0; -} - 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 c1ca4786b..000000000 --- a/libs/network/test/http/server_async_less_copy.cpp +++ /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) - -#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests - -#include - -#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(name(header), "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"} - , {"Content-Length", "13"} - }; - static char const * hello_world = "Hello, World!"; - connection->set_status(server::connection::ok); - connection->set_headers(boost::make_iterator_range(headers, headers+4)); - 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; - std::string port = "8000"; - if (argc > 1) port = argv[1]; - server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true); - instance.run(); - return 0; -} - diff --git a/libs/network/test/http/server_async_run_stop_concurrency.cpp b/libs/network/test/http/server_async_run_stop_concurrency.cpp deleted file mode 100644 index e9a4e25ac..000000000 --- a/libs/network/test/http/server_async_run_stop_concurrency.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests - -#include -#include -#include - -namespace http = boost::network::http; -namespace util = boost::network::utils; - -struct dummy_async_handler; -typedef http::async_server async_server; - -struct dummy_async_handler { - void operator()(async_server::request const & req, - async_server::connection_ptr conn) { - // Really, this is just for testing purposes - } -}; - -// In this batch of tests we ensure that calling run and stop on an async_server, in any sequence, is thread safe. - -int main(int argc, char * argv[]) { - dummy_async_handler async_handler; - -#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 - -#define ASYNC_SERVER_SLEEP_TIME \ - boost::posix_time::milliseconds(100) - - // stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop without running"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - server_instance.stop(); - } - - // run-stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - server_instance.stop(); - running_thread.join(); - } - - // run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - } - - // run-stop-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_stopping_thread.join(); - second_running_thread.join(); - } - - // run-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_running_thread.join(); - } - - // run-stop-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - second_stopping_thread.join(); - running_thread.join(); - } - -#undef ASYNC_SERVER_TEST_CONFIG - - return 0; -} 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/server_hello_world.cpp b/libs/network/test/http/server_hello_world.cpp deleted file mode 100644 index 86857a9f2..000000000 --- a/libs/network/test/http/server_hello_world.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2009 (c) Tarro, Inc. -// Copyright 2009-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 -#include - -namespace http = boost::network::http; -using boost::assign::list_of; -using boost::lexical_cast; -using std::string; -using std::cerr; -using std::endl; - -struct hello_world; -typedef http::server server; - -struct hello_world { - - void operator()(server::request const & request, server::response & response) { - static server::response::header_type header = {"Connection", "close"}; - response = server::response::stock_reply(server::response::ok, "Hello, World!"); - response.headers.push_back(header); - assert(response.status == server::response::ok); - assert(response.headers.size() == 3); - assert(response.content == "Hello, World!"); - } - - void log(string const & data) { - cerr << data << endl; - abort(); - } - -}; - -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); - server_.run(); - return EXIT_SUCCESS; -} - diff --git a/libs/network/test/http/server_include_inlined.cpp b/libs/network/test/http/server_include_inlined.cpp deleted file mode 100644 index 1f286bba6..000000000 --- a/libs/network/test/http/server_include_inlined.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2009 (c) Tarro, Inc. -// Copyright 2009-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 -#define BOOST_NETWORK_NO_LIB -#include -#include -#include -#include -#include -#include - -namespace http = boost::network::http; -using boost::assign::list_of; -using boost::lexical_cast; -using std::string; -using std::cerr; -using std::endl; - -struct hello_world; -typedef http::server server; - -struct hello_world { - - void operator()(server::request const & request, server::response & response) { - static server::response::header_type header = {"Connection", "close"}; - response = server::response::stock_reply(server::response::ok, "Hello, World!"); - response.headers.push_back(header); - assert(response.status == server::response::ok); - assert(response.headers.size() == 3); - assert(response.content == "Hello, World!"); - } - - void log(string const & data) { - cerr << data << endl; - abort(); - } - -}; - -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); - boost::thread runner(boost::bind(&server::run, &server_)); - try { - server_.stop(); - runner.join(); - } catch (...) { - /* ignore all errors */ - } - return EXIT_SUCCESS; -} - 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/libs/network/test/utils_thread_pool.cpp b/libs/network/test/utils_thread_pool.cpp deleted file mode 100644 index d075efafa..000000000 --- a/libs/network/test/utils_thread_pool.cpp +++ /dev/null @@ -1,49 +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 utils thread pool test -#include -#include -#include -#include - -using namespace boost::network; - -// 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 -// tests that this unit test requires of thread pools. Ultimately the -// requirements will show up in the Concept documentation, but this test is the -// canonical definition of what a thread pool should look like at least -// syntactically. -// - -BOOST_AUTO_TEST_CASE( default_constructor ) { - utils::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_; - } -protected: - 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); -} diff --git a/logging/CMakeLists.txt b/logging/CMakeLists.txt new file mode 100644 index 000000000..7a4273175 --- /dev/null +++ b/logging/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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( -DNETWORK_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 network-logging ) + add_definitions(-DNETWORK_ENABLE_LOGGING) + + if(CPP-NETLIB_BUILD_TESTS) + enable_testing() + add_subdirectory(test) + endif(CPP-NETLIB_BUILD_TESTS) + +endif() + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_LOGGING_SRCS ${CPP-NETLIB_LOGGING_SRCS} PARENT_SCOPE) diff --git a/logging/src/CMakeLists.txt b/logging/src/CMakeLists.txt new file mode 100644 index 000000000..a55f49b45 --- /dev/null +++ b/logging/src/CMakeLists.txt @@ -0,0 +1,18 @@ +# 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}/logging/src ${CPP-NETLIB_SOURCE_DIR}) + +set(CPP-NETLIB_LOGGING_SRCS + logging.cpp) + +add_library(network-logging ${CPP-NETLIB_LOGGING_SRCS}) + +# prepend current directory to make paths absolute +prependToElements( "${CMAKE_CURRENT_SOURCE_DIR}/" + CPP-NETLIB_LOGGING_SRCS ) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_LOGGING_SRCS ${CPP-NETLIB_LOGGING_SRCS} PARENT_SCOPE) diff --git a/logging/src/logging.cpp b/logging/src/logging.cpp new file mode 100644 index 000000000..4ab195db1 --- /dev/null +++ b/logging/src/logging.cpp @@ -0,0 +1,50 @@ +// 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..44d56531f --- /dev/null +++ b/logging/src/network/logging/logging.hpp @@ -0,0 +1,77 @@ +// 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 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 + 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 + log_record& write(TypeOfSomething && something) { + m_text_stream << std::forward(something); + return *this; + } + + template + 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..e49b55b13 --- /dev/null +++ b/logging/test/CMakeLists.txt @@ -0,0 +1,36 @@ +# 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(${GTEST_INCLUDE_DIRS}) +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 (CPP-NETLIB_BUILD_TESTS) + set( + TESTS + logging_log_record + logging_custom_handler + ) + if(CPP-NETLIB_BUILD_SINGLE_LIB) + set(link_cppnetlib_lib cppnetlib) + else() + set(link_cppnetlib_lib network-logging) + endif() + 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) + target_link_libraries(cpp-netlib-${test} + ${Boost_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${link_cppnetlib_lib}) + 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 (CPP-NETLIB_BUILD_TESTS) diff --git a/logging/test/logging_custom_handler.cpp b/logging/test/logging_custom_handler.cpp new file mode 100644 index 000000000..3651df217 --- /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 + +#include + +#include + +using namespace network::logging; + +TEST(logging_custom_handler, 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(); + + ASSERT_TRUE(!result_output.empty()); + ASSERT_TRUE(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..002a65d42 --- /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 + +#include + +#include +#ifndef NETWORK_ENABLE_LOGGING +# define NETWORK_ENABLE_LOGGING +#endif +#include + +using namespace network::logging; + +TEST(logging_log_record, default_constructor) { + log_record record; + ASSERT_TRUE(record.message() == ""); + ASSERT_TRUE(record.filename() == log_record::UNKNOWN_FILE_NAME); + ASSERT_TRUE(record.line() == 0); +} + +TEST(logging_log_record, cstring_constructor) { + const auto message = "This is a test."; + log_record record(message); + ASSERT_TRUE(record.message() == message); + ASSERT_TRUE(record.filename() == log_record::UNKNOWN_FILE_NAME); + ASSERT_TRUE(record.line() == 0); +} + +TEST(logging_log_record, string_constructor) { + const std::string message("This is a test."); + log_record record(message); + ASSERT_TRUE(record.message() == message); + ASSERT_TRUE(record.filename() == log_record::UNKNOWN_FILE_NAME); + ASSERT_TRUE(record.line() == 0); +} + +TEST(logging_log_record, int_constructor) { + const auto num = 42; + log_record record(num); + ASSERT_TRUE(record.message() == std::to_string(num)); + ASSERT_TRUE(record.filename() == log_record::UNKNOWN_FILE_NAME); + ASSERT_TRUE(record.line() == 0); +} + +TEST(logging_log_record, info_constructor) { + const auto line_num = 42; + const auto file_name = "somewhere.cpp"; + log_record record(file_name, line_num); + ASSERT_TRUE(record.message() == ""); + ASSERT_TRUE(record.filename() == file_name); + ASSERT_TRUE(record.line() == line_num); +} + +TEST(logging_log_record, 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."; + + ASSERT_TRUE(record.message() == message); + ASSERT_TRUE(record.filename() == file_name); + ASSERT_TRUE(record.line() == line_num); +} + +TEST(logging_log_record, raw_log) { log("This is a raw log."); } + +TEST(logging_log_record, 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!"); +} diff --git a/message/CMakeLists.txt b/message/CMakeLists.txt new file mode 100644 index 000000000..6b7d20585 --- /dev/null +++ b/message/CMakeLists.txt @@ -0,0 +1,16 @@ +# 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) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_MESSAGE_SRCS ${CPP-NETLIB_MESSAGE_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_MESSAGE_WRAPPERS_SRCS ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS} PARENT_SCOPE) diff --git a/message/src/CMakeLists.txt b/message/src/CMakeLists.txt new file mode 100644 index 000000000..54d2b49c0 --- /dev/null +++ b/message/src/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (c) Glyn Matthews 2012. +# Copyright 2013, Dean Michael Berris 2013 +# Copyright 2013, Google, Inc. +# Distributed under the 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) + +set(CPP-NETLIB_MESSAGE_SRCS + message.cpp) + +add_library(network-message ${CPP-NETLIB_MESSAGE_SRCS}) +target_link_libraries(network-message network-uri) + +set(CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS + directives.cpp) + +add_library(network-message-directives ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS}) + +set(CPP-NETLIB_MESSAGE_WRAPPERS_SRCS + wrappers.cpp) + +add_library(network-message-wrappers ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS}) + +# prepend current directory to make paths absolute +prependToElements( "${CMAKE_CURRENT_SOURCE_DIR}/" + CPP-NETLIB_MESSAGE_SRCS + CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS + CPP-NETLIB_MESSAGE_WRAPPERS_SRCS ) + +# propagate sources to parent directory for one-lib-build +set(CPP-NETLIB_MESSAGE_SRCS ${CPP-NETLIB_MESSAGE_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS ${CPP-NETLIB_MESSAGE_DIRECTIVES_SRCS} PARENT_SCOPE) +set(CPP-NETLIB_MESSAGE_WRAPPERS_SRCS ${CPP-NETLIB_MESSAGE_WRAPPERS_SRCS} PARENT_SCOPE) 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..c228e06e6 --- /dev/null +++ b/message/src/network/detail/debug.hpp @@ -0,0 +1,41 @@ +#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..bb8d8bd10 --- /dev/null +++ b/message/src/network/detail/directive_base.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_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..d97d3d535 --- /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..f33721716 --- /dev/null +++ b/message/src/network/message.hpp @@ -0,0 +1,30 @@ +// 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 + +#ifdef NETWORK_DEBUG +#include +#endif + +#endif // NETWORK_MESSAGE_HPP_20111021 diff --git a/message/src/network/message/directives.hpp b/message/src/network/message/directives.hpp new file mode 100644 index 000000000..a7cf737b0 --- /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..f268c8067 --- /dev/null +++ b/message/src/network/message/directives/detail/string_directive.hpp @@ -0,0 +1,46 @@ +// 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..a66781ace --- /dev/null +++ b/message/src/network/message/directives/detail/string_value.hpp @@ -0,0 +1,34 @@ +// 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_, + boost::shared_future::type>, + typename mpl::if_, + 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..da4764e0f --- /dev/null +++ b/message/src/network/message/directives/header.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_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..5b2ef7c1a --- /dev/null +++ b/message/src/network/message/directives/header.ipp @@ -0,0 +1,28 @@ +// 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..787d7374a --- /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..f6c8f2573 --- /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..1396d6f16 --- /dev/null +++ b/message/src/network/message/message.hpp @@ -0,0 +1,82 @@ +// 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< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const; + virtual void get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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..ef9a7ab23 --- /dev/null +++ b/message/src/network/message/message.ipp @@ -0,0 +1,196 @@ +// 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< + void(std::string const&, std::string const&)> 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< + void(std::string const&, std::string const&)> 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< + void(std::string const&, std::string const&)> inserter) const { + pimpl->get_headers(inserter); +} + +void message::get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const { + pimpl->get_headers(name, inserter); +} + +void message::get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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..b3867a820 --- /dev/null +++ b/message/src/network/message/message_base.hpp @@ -0,0 +1,50 @@ +// 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< + void(std::string const&, std::string const&)> inserter) const = 0; + virtual void get_headers( + std::string const& name, + std::function< + void(std::string const&, std::string const&)> inserter) const = 0; + virtual void get_headers( + std::function predicate, + std::function< + void(std::string const&, std::string const&)> 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..244469fc8 --- /dev/null +++ b/message/src/network/message/message_concept.hpp @@ -0,0 +1,62 @@ +// 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..35ea709d2 --- /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..6f8c05e9c --- /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..c8af55914 --- /dev/null +++ b/message/src/network/message/modifiers/clear_headers.hpp @@ -0,0 +1,18 @@ +#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..4775bf769 --- /dev/null +++ b/message/src/network/message/modifiers/destination.hpp @@ -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_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..68ab1abc0 --- /dev/null +++ b/message/src/network/message/modifiers/remove_header.hpp @@ -0,0 +1,21 @@ +// 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..9ba4fcc7e --- /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..66e0d9247 --- /dev/null +++ b/message/src/network/message/transformers.hpp @@ -0,0 +1,53 @@ +// 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..9c6717769 --- /dev/null +++ b/message/src/network/message/transformers/selectors.hpp @@ -0,0 +1,57 @@ +// 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..5c9b0f101 --- /dev/null +++ b/message/src/network/message/transformers/to_lower.hpp @@ -0,0 +1,88 @@ + +// 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..dfbf5388f --- /dev/null +++ b/message/src/network/message/transformers/to_upper.hpp @@ -0,0 +1,90 @@ + +// 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..4fde3dd72 --- /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..c508a9b83 --- /dev/null +++ b/message/src/network/message/wrappers/body.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_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< std:: string:: const_iterator>() 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..42213aaa8 --- /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< std:: string:: const_iterator> + () 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..17c4a618b --- /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..966c5b405 --- /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..610a9ce38 --- /dev/null +++ b/message/src/network/message/wrappers/headers.hpp @@ -0,0 +1,31 @@ +// 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..357b3b64d --- /dev/null +++ b/message/src/network/message/wrappers/headers.ipp @@ -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_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..1582f1023 --- /dev/null +++ b/message/src/network/message/wrappers/source.hpp @@ -0,0 +1,32 @@ +// 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..7a1473283 --- /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/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..12dc09d7b --- /dev/null +++ b/message/test/CMakeLists.txt @@ -0,0 +1,34 @@ +# 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(${GTEST_INCLUDE_DIRS}) +include_directories(${CPP-NETLIB_SOURCE_DIR}/uri/src) +include_directories(${CPP-NETLIB_SOURCE_DIR}/message/src) + +if (CPP-NETLIB_BUILD_TESTS) + set(TESTS message_test message_transform_test) + if(CPP-NETLIB_BUILD_SINGLE_LIB) + set(link_cppnetlib_lib cppnetlib) + else() + set(link_cppnetlib_lib network-message + network-message-directives + network-message-wrappers) + endif() + foreach (test ${TESTS}) + add_executable(cpp-netlib-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-${test} + ${Boost_SYSTEM_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${GTEST_BOTH_LIBRARIES} + ${link_cppnetlib_lib}) + 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 (CPP-NETLIB_BUILD_TESTS) diff --git a/message/test/message_test.cpp b/message/test/message_test.cpp new file mode 100644 index 000000000..2349342a1 --- /dev/null +++ b/message/test/message_test.cpp @@ -0,0 +1,71 @@ + +// Copyright 2007, 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 + +using namespace network; + +TEST(message_test, copy_constructor) { + message instance; + instance << header("name", "value"); + message copy(instance); + headers_wrapper::container_type const& headers_ = headers(copy); + ASSERT_EQ(headers_.count("name"), static_cast(1)); + message::headers_range range = headers_.equal_range("name"); + ASSERT_TRUE(!boost::empty(range)); +} + +TEST(message_test, swap) { + 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); + ASSERT_EQ(instance_headers.count("name"), static_cast(0)); + ASSERT_EQ(other_headers.count("name"), static_cast(1)); +} + +TEST(message_test, headers_directive) { + message instance; + instance << header("name", "value"); + headers_wrapper::container_type const& instance_headers = headers(instance); + ASSERT_EQ(instance_headers.count("name"), static_cast(1)); + message::headers_range range = instance_headers.equal_range("name"); + ASSERT_TRUE(boost::begin(range) != boost::end(range)); +} + +TEST(message_test, body_directive) { + message instance; + instance << ::network::body("body"); + std::string body_string = body(instance); + ASSERT_TRUE(body_string == "body"); +} + +TEST(message_test, source_directive) { + message instance; + instance << ::network::source("source"); + std::string source_string = source(instance); + ASSERT_TRUE(source_string == "source"); +} + +TEST(message_test, destination_directive) { + message instance; + instance << destination("destination"); + std::string const& destination_ = destination(instance); + ASSERT_TRUE(destination_ == "destination"); +} + +TEST(message_test, remove_header_directive) { + 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"); + ASSERT_TRUE(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..3e558a52e --- /dev/null +++ b/message/test/message_transform_test.cpp @@ -0,0 +1,47 @@ + +// Copyright 2007, 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 + +TEST(message_test, message_transform_toupper) { + using namespace network; + + message msg; + msg << source("me"); + std::string const& source_orig = source(msg); + ASSERT_EQ(source_orig, "me"); + msg << transform(to_upper_, source_); + std::string const& source_upper = source(msg); + ASSERT_EQ(source_upper, "ME"); + msg << destination("you"); + std::string const& destination_orig = destination(msg); + ASSERT_EQ(destination_orig, "you"); + msg << transform(to_upper_, destination_); + std::string const& destination_upper = destination(msg); + ASSERT_EQ(destination_upper, "YOU"); +} + +TEST(message_test, message_transform_tolower) { + using namespace network; + + message msg; + msg << source("ME"); + std::string const& source_orig = source(msg); + ASSERT_EQ(source_orig, "ME"); + msg << transform(to_lower_, source_); + std::string const& source_lower = source(msg); + ASSERT_EQ(source_lower, "me"); + msg << destination("YOU"); + std::string const& destination_orig = destination(msg); + ASSERT_EQ(destination_orig, "YOU"); + msg << transform(to_lower_, destination_); + std::string const& destination_lower = destination(msg); + ASSERT_EQ(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..89871225f --- /dev/null +++ b/mime/test/CMakeLists.txt @@ -0,0 +1,20 @@ +# 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) + +add_executable ( mime-roundtrip mime-roundtrip.cpp ) +target_link_libraries ( mime-roundtrip ) +set_target_properties(mime-roundtrip + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) +add_test ( mime-roundtrip mime-roundtrip ) 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 75% rename from libs/mime/test/mime-roundtrip.cpp rename to mime/test/mime-roundtrip.cpp index d09166076..fc516b510 100644 --- a/libs/mime/test/mime-roundtrip.cpp +++ b/mime/test/mime-roundtrip.cpp @@ -10,7 +10,8 @@ */ #include -#include +// #include +#include #include @@ -83,15 +84,15 @@ using namespace boost::unit_test; test_suite* init_unit_test_suite( int argc, char* argv[] ) { - framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000001" ))); - framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000019" ))); - framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000431" ))); - framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000975" ))); + framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/00000001" ))); + framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/00000019" ))); + framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/00000431" ))); + framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/00000975" ))); // Following test is removed because the file it used often tripped false-positives when scanned by virus checkers. -// framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00001136" ))); +// framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/00001136" ))); // test cases that fail -// framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/0019-NoBoundary" ))); +// framework::master_test_suite().add ( BOOST_TEST_CASE( std::bind ( test_roundtrip, "TestMessages/0019-NoBoundary" ))); return 0; } 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..9567e16a5 --- /dev/null +++ b/uri @@ -0,0 +1 @@ +Subproject commit 9567e16a5936bf0ebcea8b33d56863251dc94e9b