Inboarding cpp-netlib
This commit is contained in:
parent
fcafa5c414
commit
f4ec16c2c5
529 changed files with 57236 additions and 10 deletions
|
@ -46,9 +46,6 @@ include_directories (${Boost_INCLUDE_DIR})
|
|||
find_package (Qt5 REQUIRED COMPONENTS Core Gui Widgets Test ${PLATFORM_QT_PACKAGES})
|
||||
include_directories (${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Test_INCLUDE_DIRS})
|
||||
|
||||
find_package (cppnetlib)
|
||||
include_directories (${CPPNETLIB_INCLUDE_DIRS})
|
||||
|
||||
include_directories (${OPENCL_INCLUDE_DIRS})
|
||||
|
||||
add_library (ed25519
|
||||
|
@ -72,6 +69,9 @@ endif ()
|
|||
add_subdirectory (gtest)
|
||||
include_directories ("gtest/include")
|
||||
|
||||
add_subdirectory (cpp-netlib)
|
||||
include_directories ("cpp-netlib")
|
||||
|
||||
add_library (cryptopp
|
||||
cryptopp/3way.cpp
|
||||
cryptopp/adler32.cpp
|
||||
|
@ -344,19 +344,19 @@ else (WIN32)
|
|||
set (PLATFORM_WALLET_LIBS)
|
||||
endif (WIN32)
|
||||
|
||||
target_link_libraries (core_test node secure lmdb xxhash ed25519 argon2 blake2 cryptopp gtest_main gtest ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} ${PLATFORM_LIBS})
|
||||
target_link_libraries (core_test node secure lmdb xxhash ed25519 argon2 blake2 cryptopp gtest_main gtest cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
target_link_libraries (slow_test node secure lmdb xxhash ed25519 argon2 blake2 cryptopp gtest_main gtest ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} ${PLATFORM_LIBS})
|
||||
target_link_libraries (slow_test node secure lmdb xxhash ed25519 argon2 blake2 cryptopp gtest_main gtest cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
target_link_libraries (rai_node node secure lmdb xxhash ed25519 argon2 blake2 cryptopp ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} ${PLATFORM_LIBS})
|
||||
target_link_libraries (rai_node node secure lmdb xxhash ed25519 argon2 blake2 cryptopp cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
target_link_libraries (rai_landing node secure lmdb xxhash ed25519 argon2 blake2 cryptopp ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} ${PLATFORM_LIBS})
|
||||
target_link_libraries (rai_landing node secure lmdb xxhash ed25519 argon2 blake2 cryptopp cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
target_link_libraries (qt_test node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp gtest ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Test ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS})
|
||||
target_link_libraries (qt_test node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp gtest cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Test ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
target_link_libraries (rai_wallet node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} Qt5::Core Qt5::Gui Qt5::Widgets ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS} ${PLATFORM_WALLET_LIBS})
|
||||
target_link_libraries (rai_wallet node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} Qt5::Core Qt5::Gui Qt5::Widgets ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS} ${PLATFORM_WALLET_LIBS})
|
||||
|
||||
target_link_libraries (qt_system node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp gtest ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} ${CPPNETLIB_LIBRARIES} Qt5::Core Qt5::Gui Qt5::Widgets ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS})
|
||||
target_link_libraries (qt_system node secure lmdb xxhash ed25519 qt argon2 blake2 cryptopp gtest cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_LOG_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_LOG_SETUP_LIBRARY} ${Boost_THREAD_LIBRARY} Qt5::Core Qt5::Gui Qt5::Widgets ${QT_QTGUI_LIBRARY} ${PLATFORM_LIBS})
|
||||
|
||||
set (CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE)
|
||||
if (APPLE)
|
||||
|
|
38
cpp-netlib/.clang-format
Normal file
38
cpp-netlib/.clang-format
Normal file
|
@ -0,0 +1,38 @@
|
|||
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
|
||||
ObjCSpaceBeforeProtocolList: false
|
||||
PenaltyBreakComment: 60
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerBindsToType: true
|
||||
SpacesBeforeTrailingComments: 2
|
||||
Cpp11BracedListStyle: true
|
||||
Standard: Auto
|
||||
IndentWidth: 2
|
||||
TabWidth: 4
|
||||
UseTab: false
|
||||
BreakBeforeBraces: Attach
|
||||
IndentFunctionDeclarationAfterType: true
|
||||
SpacesInParentheses: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpaceAfterControlStatementKeyword: true
|
11
cpp-netlib/.gitignore
vendored
Normal file
11
cpp-netlib/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
*.cmake
|
||||
*.swp
|
||||
*.pyc
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Makefile
|
||||
Testing
|
||||
*.gch
|
||||
libs/mime/test/mime-roundtrip
|
||||
*.a
|
||||
_build
|
55
cpp-netlib/.travis.yml
Normal file
55
cpp-netlib/.travis.yml
Normal file
|
@ -0,0 +1,55 @@
|
|||
language:
|
||||
- cpp
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
env:
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="ON"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.54.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Release" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="ON" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF"
|
||||
- BOOST_VER=1.55.0 BUILD_SHARED_LIBS="OFF" CMAKE_BUILD_TYPE="Debug" ENABLE_HTTPS="OFF"
|
||||
|
||||
before_install:
|
||||
- if [ "${CXX}" == "g++" ] || [ ${BUILD_SHARED_LIBS} = "OFF" ]; then
|
||||
sudo add-apt-repository ppa:boost-latest/ppa --yes;
|
||||
sudo apt-get update;
|
||||
fi
|
||||
- if [ "${CXX}" == "clang++" ] && [ ${BUILD_SHARED_LIBS} = "ON" ]; then
|
||||
svn export http://svn.boost.org/svn/boost/tags/release/Boost_${BOOST_VER//./_} ../boost_${BOOST_VER//./_};
|
||||
export BOOST_ROOT=$TRAVIS_BUILD_DIR/../boost_${BOOST_VER//./_};
|
||||
fi
|
||||
|
||||
install:
|
||||
- if [ "${CXX}" == "g++" ] || [ ${BUILD_SHARED_LIBS} = "OFF" ]; then
|
||||
sudo apt-get install libboost${BOOST_VER/%.0/}-all-dev;
|
||||
fi
|
||||
- if [ "${CXX}" == "clang++" ] && [ ${BUILD_SHARED_LIBS} = "ON" ]; then
|
||||
cd $BOOST_ROOT;
|
||||
./bootstrap.sh --with-toolset=$CC;
|
||||
./b2 -j4 --stagedir=.;
|
||||
cd -;
|
||||
fi
|
||||
|
||||
script:
|
||||
- cmake -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
-DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS}
|
||||
-DCPP-NETLIB_ENABLE_HTTPS=${ENABLE_HTTPS}
|
||||
- make
|
||||
- make test
|
||||
|
||||
after_failure:
|
||||
- cat Testing/Temporary/LastTest.log
|
72
cpp-netlib/.ycm_extra_conf.py
Normal file
72
cpp-netlib/.ycm_extra_conf.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Copyright 2013 Google, Inc.
|
||||
# Copyright 2013 Dean Michael Berris <dberris@google.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)
|
||||
#
|
||||
# Project-wide configuration for YouCompleteMe Vim plugin.
|
||||
#
|
||||
# Based off of Valloric's .ycm_conf_extra.py for YouCompleteMe:
|
||||
# https://github.com/Valloric/YouCompleteMe/blob/master/cpp/ycm/.ycm_extra_conf.py
|
||||
#
|
||||
|
||||
import os
|
||||
import ycm_core
|
||||
|
||||
flags = [
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
'-std=c++03',
|
||||
'-isystem',
|
||||
'.',
|
||||
'-isystem',
|
||||
'/usr/include',
|
||||
'-isystem',
|
||||
'/usr/include/c++/4.6',
|
||||
'-isystem',
|
||||
'/usr/include/clang/3.0/include',
|
||||
'-isystem',
|
||||
'/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/c++/v1',
|
||||
'-I',
|
||||
os.environ['BOOST_ROOT'],
|
||||
# Always enable debugging for the project when building for semantic
|
||||
# completion.
|
||||
'-DBOOST_NETWORK_DEBUG',
|
||||
]
|
||||
|
||||
def DirectoryOfThisScript():
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
|
||||
if not working_directory:
|
||||
return list(flags)
|
||||
new_flags = []
|
||||
make_next_absolute = False
|
||||
path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
|
||||
for flag in flags:
|
||||
new_flag = flag
|
||||
if make_next_absolute:
|
||||
make_next_absolute = False
|
||||
if not flag.startswith('/'):
|
||||
new_flag = os.path.join(working_directory, flag)
|
||||
|
||||
for path_flag in path_flags:
|
||||
if flag == path_flag:
|
||||
make_next_absolute = True
|
||||
break
|
||||
if flag.startswith(path_flag):
|
||||
path = flag[len(path_flag):]
|
||||
new_flag = path_flag + os.path.join(working_directory, path)
|
||||
break
|
||||
|
||||
if new_flag:
|
||||
new_flags.append(new_flag)
|
||||
return new_flags
|
||||
|
||||
|
||||
def FlagsForFile(filename):
|
||||
relative_to = DirectoryOfThisScript()
|
||||
final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
|
||||
return {'flags': final_flags, 'do_cache': True }
|
150
cpp-netlib/CMakeLists.txt
Normal file
150
cpp-netlib/CMakeLists.txt
Normal file
|
@ -0,0 +1,150 @@
|
|||
# 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)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(CPP-NETLIB)
|
||||
|
||||
option( CPP-NETLIB_BUILD_SHARED_LIBS "Build cpp-netlib as shared libraries." OFF )
|
||||
option( CPP-NETLIB_BUILD_TESTS "Build the cpp-netlib project tests." OFF)
|
||||
option( CPP-NETLIB_BUILD_EXPERIMENTS "Build the cpp-netlib project experiments." OFF)
|
||||
option( CPP-NETLIB_BUILD_EXAMPLES "Build the cpp-netlib project examples." OFF)
|
||||
option( CPP-NETLIB_ENABLE_HTTPS "Build cpp-netlib with support for https if OpenSSL is found." OFF)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# determine install path for CMake config files
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set(DEF_INSTALL_CMAKE_DIR CMake)
|
||||
else()
|
||||
set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/cppnetlib)
|
||||
endif()
|
||||
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
|
||||
|
||||
# Make relative cmake install path absolute (needed later on)
|
||||
if(NOT IS_ABSOLUTE "${INSTALL_CMAKE_DIR}")
|
||||
set(INSTALL_CMAKE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}")
|
||||
endif()
|
||||
|
||||
|
||||
if(CPP-NETLIB_BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)
|
||||
message (STATUS "Linking boost testing libs dynamically...")
|
||||
set(Boost_USE_STATIC_LIBS OFF)
|
||||
set(CPP-NETLIB_BUILD_SHARED_LIBS ON)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK)
|
||||
else()
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(CPP-NETLIB_BUILD_SHARED_LIBS OFF)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
endif()
|
||||
|
||||
set(Boost_USE_MULTI_THREADED ON)
|
||||
find_package( Boost 1.54.0
|
||||
REQUIRED unit_test_framework system regex date_time thread filesystem
|
||||
program_options chrono atomic )
|
||||
|
||||
if (CPP-NETLIB_ENABLE_HTTPS)
|
||||
find_package( OpenSSL )
|
||||
endif()
|
||||
|
||||
find_package( Threads )
|
||||
set(CMAKE_VERBOSE_MAKEFILE true)
|
||||
|
||||
set(CPPNETLIB_VERSION_MAJOR 0) # MUST bump this whenever we make ABI-incompatible changes
|
||||
set(CPPNETLIB_VERSION_MINOR 11)
|
||||
set(CPPNETLIB_VERSION_PATCH 1)
|
||||
set(CPPNETLIB_VERSION_STRING ${CPPNETLIB_VERSION_MAJOR}.${CPPNETLIB_VERSION_MINOR}.${CPPNETLIB_VERSION_PATCH})
|
||||
|
||||
if (CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
add_definitions(-DBOOST_NETWORK_DEBUG)
|
||||
endif()
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS)
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
elseif (${CMAKE_CXX_COMPILER_ID} MATCHES Clang)
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# We want to link in C++11 mode if we're using Clang and on OS X.
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256 -std=c++11 -stdlib=libc++")
|
||||
else()
|
||||
# We just add the -Wall and a high enough template depth
|
||||
# flag for Clang in other systems.
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -ftemplate-depth=256")
|
||||
endif()
|
||||
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)
|
||||
if (CPP-NETLIB_BUILD_TESTS)
|
||||
add_subdirectory(libs/network/test)
|
||||
endif (CPP-NETLIB_BUILD_TESTS)
|
||||
if (CPP-NETLIB_BUILD_EXPERIMENTS)
|
||||
add_subdirectory(libs/network/experiment)
|
||||
endif (CPP-NETLIB_BUILD_EXPERIMENTS)
|
||||
if (NOT MSVC AND CPP-NETLIB_BUILD_TESTS)
|
||||
add_subdirectory(libs/mime/test)
|
||||
endif(NOT MSVC AND CPP-NETLIB_BUILD_TESTS)
|
||||
if (CPP-NETLIB_BUILD_EXAMPLES)
|
||||
add_subdirectory(libs/network/example)
|
||||
endif (CPP-NETLIB_BUILD_EXAMPLES)
|
||||
endif(Boost_FOUND)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
|
||||
install(DIRECTORY boost DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
###
|
||||
## Export Targets
|
||||
# (so cpp-netlib can be easily used by other CMake projects)
|
||||
# [see http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file]
|
||||
|
||||
# Add all targets to the build-tree export set
|
||||
export(TARGETS cppnetlib-client-connections cppnetlib-server-parsers cppnetlib-uri
|
||||
FILE "${PROJECT_BINARY_DIR}/cppnetlibTargets.cmake")
|
||||
# Export the package for use from the build-tree
|
||||
# (this registers the build-tree with a global CMake-registry)
|
||||
export(PACKAGE cppnetlib)
|
||||
# Create the cppnetlibConfig.cmake and cppnetlibConfigVersion files
|
||||
file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}"
|
||||
"${CMAKE_INSTALL_FULL_INCLUDEDIR}")
|
||||
# ... for the build tree
|
||||
set(CONF_INCLUDE_DIRS "${PROJECT_SOURCE_DIR}" ${Boost_INCLUDE_DIRS})
|
||||
configure_file(cppnetlibConfig.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/cppnetlibConfig.cmake" @ONLY)
|
||||
# ... for the install tree
|
||||
set(CONF_INCLUDE_DIRS "\${CPPNETLIB_CMAKE_DIR}/${REL_INCLUDE_DIR}")
|
||||
set(CONF_INCLUDE_DIRS ${CONF_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
|
||||
configure_file(cppnetlibConfig.cmake.in
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cppnetlibConfig.cmake" @ONLY)
|
||||
# ... for both
|
||||
configure_file(cppnetlibConfigVersion.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/cppnetlibConfigVersion.cmake" @ONLY)
|
||||
# Install the cppnetlibConfig.cmake and cppnetlibConfigVersion.cmake
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cppnetlibConfig.cmake"
|
||||
"${PROJECT_BINARY_DIR}/cppnetlibConfigVersion.cmake"
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}"
|
||||
COMPONENT dev)
|
||||
# Install the export set for use with the install-tree
|
||||
install(EXPORT cppnetlibTargets
|
||||
DESTINATION "${INSTALL_CMAKE_DIR}"
|
||||
COMPONENT dev)
|
23
cpp-netlib/LICENSE_1_0.txt
Normal file
23
cpp-netlib/LICENSE_1_0.txt
Normal file
|
@ -0,0 +1,23 @@
|
|||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
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.
|
64
cpp-netlib/RATIONALE.txt
Normal file
64
cpp-netlib/RATIONALE.txt
Normal file
|
@ -0,0 +1,64 @@
|
|||
C++ Networking Library
|
||||
Goals and Scope
|
||||
|
||||
|
||||
Objectives
|
||||
----------
|
||||
|
||||
o Develop a high quality, portable, easy to use C++ networking library
|
||||
|
||||
o Enable users to easily extend the library
|
||||
|
||||
o Lower the barrier to entry for cross-platform network-aware C++
|
||||
applications
|
||||
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
* Implement a simple message implementation which can be used in
|
||||
network protocol-specific routines for inter-operability and
|
||||
to provide a generic interface to manipulating network-oriented
|
||||
messages.
|
||||
|
||||
* Implement easy to use protocol client libraries such as (but not
|
||||
limited to):
|
||||
|
||||
- HTTP 1.0/1.1
|
||||
- (E)SMTP
|
||||
- SNMP
|
||||
- ICMP
|
||||
|
||||
* Implement an easy to embed HTTP server container type that supports
|
||||
most modern HTTP 1.1 features.
|
||||
|
||||
* Implement an efficient easy to use URI class/parser.
|
||||
|
||||
* Implement a fully compliant cross-platform asynchronous DNS resolver
|
||||
either as a wrapper to external (C) libraries, or as hand-rolled
|
||||
implementation.
|
||||
|
||||
* Implement a MIME handler which builds message objects from either
|
||||
data retrieved from the network or other sources and create
|
||||
text/binary representations from existing message objects intended
|
||||
for transport over the network.
|
||||
|
||||
|
||||
Scope
|
||||
-----
|
||||
|
||||
* The library will provide a generic message class which is intended
|
||||
to be the common message type used by the protocol libraries.
|
||||
|
||||
* The library will only contain client implementations for the various
|
||||
supported protocols.
|
||||
|
||||
* The library will use only STL and Boost C++ library components,
|
||||
utilities, and libraries throughout the implementation.
|
||||
|
||||
* The library will strive to use C++ templates and template
|
||||
metaprogramming techniques in order to not require the building of
|
||||
external shared/static libraries. In other words, the library will be
|
||||
header-only and compliant with the C++ standard.
|
||||
|
||||
|
160
cpp-netlib/README.rst
Normal file
160
cpp-netlib/README.rst
Normal file
|
@ -0,0 +1,160 @@
|
|||
C++ Network Library
|
||||
===================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
cpp-netlib is a collection of network related routines/implementations
|
||||
geared towards providing a robust cross-platform networking library.
|
||||
cpp-netlib offers the following implementations:
|
||||
|
||||
* Common Message Type -- A generic message type which can be used
|
||||
to encapsulate and store message related information, used by all
|
||||
network implementations as the primary means of data exchange.
|
||||
* Network protocol message parsers -- A collection of parsers which
|
||||
generate message objects from strings.
|
||||
* Adapters and Wrappers -- A collection of Adapters and wrappers aimed
|
||||
towards making the message type STL friendly.
|
||||
* Network protocol client and server implementations -- A collection
|
||||
of network protocol implementations that include embeddable client
|
||||
and server types.
|
||||
|
||||
This library is released under the Boost Software License (please see
|
||||
http://boost.org/LICENSE_1_0.txt or the accompanying LICENSE_1_0.txt file
|
||||
for the full text.
|
||||
|
||||
Downloading cpp-netlib
|
||||
----------------------
|
||||
|
||||
You can find official release packages of the library at::
|
||||
|
||||
http://github.com/cpp-netlib/cpp-netlib/downloads
|
||||
|
||||
Building and Installing
|
||||
-----------------------
|
||||
|
||||
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
|
||||
system.
|
||||
|
||||
::
|
||||
|
||||
$ cmake --version
|
||||
cmake version 2.8.1
|
||||
|
||||
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 \
|
||||
> -DCMAKE_C_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
|
||||
$ make
|
||||
$ make test
|
||||
|
||||
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
|
||||
|
||||
Building with Boost.Build
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you don't already have Boost.Build set up on your system, follow the steps
|
||||
indicated in the Boost Getting Started Guide [#]_ -- you will particularly want
|
||||
to copy the ``bjam`` executable to a directory that is already in your ``PATH``
|
||||
so that you don't have to go hunting for it all the time. A good place to put it
|
||||
is in ``/usr/local/bin``.
|
||||
|
||||
.. [#] http://www.boost.org/doc/libs/release/more/getting_started/
|
||||
|
||||
Building and running the tests can be as simple as doing the following::
|
||||
|
||||
$ cd ~/cpp-netlib
|
||||
$ bjam
|
||||
|
||||
Doing this will already build all the tests and run them as they are built. In
|
||||
case you encounter any problems and would like to report it to the developers,
|
||||
please do the following::
|
||||
|
||||
$ cd ~/cpp-netlib
|
||||
$ bjam 2>&1 >build-test.log
|
||||
|
||||
And then attach the ``build-test.log`` file to the email you will send to the
|
||||
cpp-netlib `developers mailing list`_.
|
||||
|
||||
.. _`developers mailing list`: cpp-netlib@googlegroups.com
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
|
||||
If you want to run the tests that come with cpp-netlib, there are a few things
|
||||
you will need. These are:
|
||||
|
||||
* A compiler (GCC 4.x, Clang 2.8, MSVC 2008)
|
||||
* A build tool (CMake [#]_ recommended, Boost.Build also an option)
|
||||
* OpenSSL headers (optional)
|
||||
|
||||
.. note:: This assumes that you have cpp-netlib at the top-level of
|
||||
your home directory.
|
||||
[#] http://www.cmake.org/
|
||||
|
||||
Hacking on cpp-netlib
|
||||
---------------------
|
||||
|
||||
cpp-netlib is being developed with the git_ distributed SCM system.
|
||||
cpp-netlib is hosted on GitHub_ following the GitHub recommended practice of
|
||||
forking the repository and submitting pull requests to the source repository.
|
||||
You can read more about the forking_ process and submitting `pull requests`_ if
|
||||
you're not familiar with either process yet.
|
||||
|
||||
.. _git: http://git-scm.com/
|
||||
.. _GitHub: http://github.com/
|
||||
.. _forking: http://help.github.com/forking/
|
||||
.. _`pull requests`: http://help.github.com/pull-requests/
|
||||
|
||||
Because cpp-netlib is released under the `Boost Software License`_ it is
|
||||
recommended that any file you make changes to bear your copyright notice
|
||||
alongside the original authors' copyright notices on the file. Typically the
|
||||
copyright notices are at the top of each file in the project.
|
||||
|
||||
.. _`Boost Software License`: http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
At the time of writing, there are no coding conventions being followed but if
|
||||
you write in the general style that is already existing in the project that
|
||||
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.
|
||||
|
||||
Contact and Support
|
||||
-------------------
|
||||
|
||||
In case you have any questions or would like to make feature requests, you can
|
||||
contact the development team through the `developers mailing list`_
|
||||
or by filing issues at http://github.com/cpp-netlib/cpp-netlib/issues.
|
||||
|
||||
.. _`developers mailing list`: cpp-netlib@googlegroups.com
|
||||
|
||||
You can reach the maintainers of the project through::
|
||||
|
||||
Dean Michael Berris (dberris@google.com)
|
||||
|
||||
Glyn Matthews (glyn.matthews@gmail.com)
|
832
cpp-netlib/boost/mime.hpp
Normal file
832
cpp-netlib/boost/mime.hpp
Normal file
|
@ -0,0 +1,832 @@
|
|||
//
|
||||
// Copyright Marshall Clow 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_MIME_HPP
|
||||
#define _BOOST_MIME_HPP
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iosfwd>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/fusion/include/std_pair.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp> // pulls in all of Phoenix
|
||||
#include <boost/spirit/include/support_istream_iterator.hpp>
|
||||
#include <boost/fusion/adapted/struct.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
// #define DUMP_MIME_DATA 1
|
||||
|
||||
namespace boost {
|
||||
namespace mime {
|
||||
|
||||
// Errors are reported using this exception class
|
||||
class mime_parsing_error : public std::runtime_error {
|
||||
public:
|
||||
explicit mime_parsing_error(const std::string &msg)
|
||||
: std::runtime_error(msg) {}
|
||||
};
|
||||
|
||||
template <class traits>
|
||||
class basic_mime;
|
||||
|
||||
namespace detail {
|
||||
|
||||
static const char *k_crlf = "\015\012";
|
||||
static const char *k_package_name = "Proposed.Boost.Mime";
|
||||
static const char *k_package_version = "0.1";
|
||||
static const char *k_content_type_header = "Content-Type";
|
||||
static const char *k_mime_version_header = "Mime-Version";
|
||||
|
||||
struct default_types {
|
||||
typedef std::string string_type;
|
||||
// typedef std::pair < std::string, string_type > header_type;
|
||||
typedef std::vector<char> body_type;
|
||||
};
|
||||
|
||||
template <typename string_type>
|
||||
struct find_mime_header {
|
||||
find_mime_header(const char *str) : searchFor(str) {}
|
||||
bool operator()(const std::pair<std::string, string_type> &val) const {
|
||||
return boost::iequals(val.first, searchFor);
|
||||
}
|
||||
|
||||
private:
|
||||
const char *searchFor;
|
||||
};
|
||||
|
||||
#ifdef DUMP_MIME_DATA
|
||||
struct tracer {
|
||||
tracer(const char *fn) : fn_(fn) { std::cout << "->" << fn_ << std::endl; }
|
||||
~tracer() { std::cout << "<-" << fn_ << std::endl; }
|
||||
const char *fn_;
|
||||
};
|
||||
#else
|
||||
struct tracer {
|
||||
tracer(const char *) {}
|
||||
~tracer() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Parsing a Content-Type header
|
||||
typedef std::pair<std::string, std::string> phrase_t;
|
||||
typedef std::vector<phrase_t> phrase_container_t;
|
||||
struct mime_content_type {
|
||||
std::string type;
|
||||
std::string sub_type;
|
||||
phrase_container_t phrases;
|
||||
};
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phx = boost::phoenix;
|
||||
using boost::spirit::_val;
|
||||
using boost::spirit::_1;
|
||||
|
||||
template <typename Iterator, typename Container>
|
||||
struct mime_header_parser : qi::grammar<Iterator, Container()> {
|
||||
mime_header_parser() : mime_header_parser::base_type(mime_headerList) {
|
||||
mime_headerList = *(mime_header) >> crlf;
|
||||
mime_header = token >> qi::lit(':') >> value >> crlf;
|
||||
token = qi::char_("a-zA-Z") >> *qi::char_("a-zA-Z_0-9\\-");
|
||||
|
||||
// In Classifieds/000001, a header begins with a CRLF
|
||||
value = (valuePart[_val = _1] | qi::eps) >>
|
||||
*(valueCont[_val += "\015\012" + _1]);
|
||||
valueCont = crlf >> contWS[_val += _1] >> valuePart[_val += _1];
|
||||
valuePart = +qi::char_("\t -~");
|
||||
|
||||
contWS = +qi::char_(" \t");
|
||||
crlf = qi::lit(k_crlf);
|
||||
|
||||
/* mime_headerList.name("mime-header-list");
|
||||
mime_header.name ("mime-header");
|
||||
token.name ("mime-token");
|
||||
valuePart.name ("mime-value-part");
|
||||
value.name ("mime-value");
|
||||
|
||||
qi::on_error<qi::fail> ( mime_headerList,
|
||||
std::cout
|
||||
<< phoenix::val("Error! Expecting ")
|
||||
<< qi::labels::_4
|
||||
<< phoenix::val(" here: \"")
|
||||
<< phoenix::construct<std::string>(qi::labels::_3,
|
||||
qi::labels::_2)
|
||||
<< phoenix::val("\"")
|
||||
<< std::endl
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
qi::rule<Iterator, Container()> mime_headerList;
|
||||
qi::rule<Iterator, typename Container::value_type()> mime_header;
|
||||
qi::rule<Iterator, std::string()> token, value, valueCont, valuePart, contWS;
|
||||
qi::rule<Iterator> crlf;
|
||||
};
|
||||
|
||||
template <typename Container, typename Iterator>
|
||||
static Container read_headers(Iterator &begin, Iterator end) {
|
||||
tracer t(__func__);
|
||||
Container retVal;
|
||||
|
||||
mime_header_parser<Iterator, Container> mh_parser;
|
||||
bool b = qi::parse(begin, end, mh_parser, retVal);
|
||||
if (!b) throw mime_parsing_error("Failed to parse headers");
|
||||
|
||||
#ifdef DUMP_MIME_DATA
|
||||
std::cout << "******Headers*******" << std::endl;
|
||||
for (typename Container::const_iterator iter = retVal.begin();
|
||||
iter != retVal.end(); ++iter) {
|
||||
std::string val = iter->second;
|
||||
size_t idx;
|
||||
while (std::string::npos != (idx = val.find(k_crlf)))
|
||||
val.replace(idx, std::strlen(k_crlf), "\n");
|
||||
std::cout << iter->first << ": " << val << std::endl;
|
||||
}
|
||||
std::cout << std::endl << "******Headers*******" << std::endl;
|
||||
#endif
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// The structure of a Content-Type mime header is taken from RFC 2045
|
||||
// http://www.ietf.org/rfc/rfc2045.txt, section 5.1
|
||||
|
||||
template <typename Iterator>
|
||||
struct mime_content_type_parser : qi::grammar<Iterator, mime_content_type()> {
|
||||
mime_content_type_parser()
|
||||
: mime_content_type_parser::base_type(content_type_header) {
|
||||
content_type_header = *qi::lit(' ') >> part >> '/' >> sub_part >> *phrase;
|
||||
|
||||
part = token | extension_token;
|
||||
sub_part = token | extension_token;
|
||||
|
||||
phrase = qi::lit(';') >> +ws >> attribute >> '=' >> value >> *ws;
|
||||
ws = qi::char_(" \t") | line_sep | comment;
|
||||
line_sep = qi::lexeme[qi::lit(k_crlf)];
|
||||
|
||||
attribute = token.alias();
|
||||
value = token | quoted_string;
|
||||
|
||||
token = +(qi::char_(" -~") - qi::char_(" ()<>@,;:\\\"/[]?="));
|
||||
comment = qi::lit('(') >> +(qi::char_(" -~") - ')') >> qi::lit(')');
|
||||
quoted_string = qi::lit('"') >> +(qi::char_(" -~") - '"') >> qi::lit('"');
|
||||
extension_token = qi::char_("Xx") >> qi::lit('-') >> token;
|
||||
}
|
||||
|
||||
qi::rule<Iterator, mime_content_type()> content_type_header;
|
||||
qi::rule<Iterator, phrase_t()> phrase;
|
||||
qi::rule<Iterator, std::string()> part, sub_part, token, attribute, value,
|
||||
quoted_string, extension_token;
|
||||
qi::rule<Iterator> ws, line_sep, comment;
|
||||
};
|
||||
|
||||
template <typename string_type>
|
||||
mime_content_type parse_content_type(const string_type &theHeader) {
|
||||
tracer t(__func__);
|
||||
mime_content_type retVal;
|
||||
typename string_type::const_iterator first = theHeader.begin();
|
||||
mime_content_type_parser<typename string_type::const_iterator> ct_parser;
|
||||
bool b = qi::parse(first, theHeader.end(), ct_parser, retVal);
|
||||
if (!b) throw mime_parsing_error("Failed to parse the 'Content-Type' header");
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
template <typename string_type>
|
||||
static string_type get_ct_value(const string_type &ctString, const char *key) {
|
||||
tracer t(__func__);
|
||||
mime_content_type mc = parse_content_type(ctString);
|
||||
for (phrase_container_t::const_iterator iter = mc.phrases.begin();
|
||||
iter != mc.phrases.end(); ++iter)
|
||||
if (boost::iequals(iter->first, key)) return iter->second;
|
||||
|
||||
throw std::runtime_error(
|
||||
str(boost::format("Couldn't find Content-Type phrase (%s)") % key));
|
||||
}
|
||||
|
||||
// Replace this with a spirit thing later.
|
||||
// we're looking for '; boundary="<somevalue>".*'
|
||||
std::string get_boundary(const std::string &ctString) {
|
||||
tracer t(__func__);
|
||||
return get_ct_value(ctString, "boundary");
|
||||
}
|
||||
|
||||
// Read the body of a multipart
|
||||
// Return a Container of containers, where the first is the actual
|
||||
// body,
|
||||
// and the rest are the sub-parts.
|
||||
// Note that the body of the multipart can be empty.
|
||||
// If this is the case, then the first separator need not have a crlf
|
||||
|
||||
// if the marker is "abcde", we could have:
|
||||
// Note that the separators are really CRLF--abcdeCRLF and
|
||||
// CRLF--abcde--CRLF
|
||||
//
|
||||
// multipart body
|
||||
// --abcde
|
||||
// sub part #1
|
||||
// --abcde
|
||||
// sub part #2
|
||||
// --abcde--
|
||||
//
|
||||
// ** or **
|
||||
// In this case, the first separator is --abcdeCRLF
|
||||
//
|
||||
// --abcde (no multipart body!)
|
||||
// sub part #1
|
||||
// --abcde
|
||||
// sub part #2
|
||||
// --abcde--
|
||||
|
||||
typedef std::vector<char> sub_part_t;
|
||||
typedef std::vector<sub_part_t> sub_parts_t;
|
||||
|
||||
template <typename bodyContainer>
|
||||
struct multipart_body_type {
|
||||
bool prolog_is_missing;
|
||||
bodyContainer body_prolog;
|
||||
sub_parts_t sub_parts;
|
||||
bodyContainer body_epilog;
|
||||
};
|
||||
|
||||
// Parse a mulitpart body.
|
||||
// Either "--boundaryCRLF" -- in which case the body is empty
|
||||
// or <some sequence of chars> "CRLF--boundaryCRLF" -- in which
|
||||
// case we return the sequence
|
||||
//
|
||||
// I am deliberately not checking for a termination separator here
|
||||
template <typename Iterator, typename Container>
|
||||
struct multipart_body_parser : qi::grammar<Iterator, Container()> {
|
||||
multipart_body_parser(const std::string &boundary, bool &isMissing)
|
||||
: multipart_body_parser::base_type(mimeBody), m_is_missing(isMissing) {
|
||||
m_is_missing = false;
|
||||
// Thanks to Michael Caisse for the hint to get this working
|
||||
mimeBody %=
|
||||
bareSep[phx::ref(m_is_missing) = true] | (+(qi::char_ - sep) >> sep);
|
||||
bareSep = qi::lit("--") >> boundary >> crlf;
|
||||
sep = crlf >> bareSep;
|
||||
crlf = qi::lit(k_crlf);
|
||||
}
|
||||
|
||||
bool &m_is_missing;
|
||||
qi::rule<Iterator, Container()> mimeBody;
|
||||
qi::rule<Iterator> bareSep, sep, crlf;
|
||||
};
|
||||
|
||||
// Break up a multi-part into its' constituent sub parts.
|
||||
template <typename Iterator, typename Container>
|
||||
struct multipart_part_parser : qi::grammar<Iterator, Container()> {
|
||||
multipart_part_parser(const std::string &boundary)
|
||||
: multipart_part_parser::base_type(mimeParts) {
|
||||
mimeParts = (+(qi::char_ - sep) % (sep >> crlf)) > terminator;
|
||||
sep = crlf >> qi::lit("--") >> boundary;
|
||||
terminator = sep >> qi::lit("--") >> crlf;
|
||||
crlf = qi::lit(k_crlf);
|
||||
}
|
||||
qi::rule<Iterator, Container()> mimeParts;
|
||||
qi::rule<Iterator> sep, terminator, crlf;
|
||||
};
|
||||
|
||||
template <typename Iterator, typename bodyContainer>
|
||||
static void read_multipart_body(Iterator &begin, Iterator end,
|
||||
multipart_body_type<bodyContainer> &mp_body,
|
||||
const std::string &separator) {
|
||||
tracer t(__func__);
|
||||
typedef bodyContainer innerC;
|
||||
innerC mpBody;
|
||||
multipart_body_parser<Iterator, innerC> mb_parser(separator,
|
||||
mp_body.prolog_is_missing);
|
||||
if (!qi::parse(begin, end, mb_parser, mp_body.body_prolog))
|
||||
throw mime_parsing_error("Failed to parse mime body(1)");
|
||||
|
||||
multipart_part_parser<Iterator, sub_parts_t> mp_parser(separator);
|
||||
if (!qi::parse(begin, end, mp_parser, mp_body.sub_parts))
|
||||
throw mime_parsing_error("Failed to parse mime body(2)");
|
||||
std::copy(begin, end, std::back_inserter(mp_body.body_epilog));
|
||||
|
||||
#ifdef DUMP_MIME_DATA
|
||||
std::cout << std::endl << ">>****Multipart Body*******" << std::endl;
|
||||
std::cout << str(boost::format(
|
||||
"Body size %d, sub part count = %d, trailer size "
|
||||
"= %d %s") %
|
||||
mp_body.body_prolog.size() % mp_body.sub_parts.size() %
|
||||
mp_body.body_epilog.size() %
|
||||
(mp_body.prolog_is_missing ? "(missing)" : "")) << std::endl;
|
||||
std::cout << std::endl << "****** Multipart Body Prolog *******" << std::endl;
|
||||
std::copy(mp_body.body_prolog.begin(), mp_body.body_prolog.end(),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl << "****** Multipart Body Epilog *******" << std::endl;
|
||||
std::copy(mp_body.body_epilog.begin(), mp_body.body_epilog.end(),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl << "<<****Multipart Body*******" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Container, typename Iterator>
|
||||
static Container read_simplepart_body(Iterator &begin, Iterator end) {
|
||||
tracer t(__func__);
|
||||
Container retVal;
|
||||
std::copy(begin, end, std::back_inserter(retVal));
|
||||
|
||||
#ifdef DUMP_MIME_DATA
|
||||
std::cout << std::endl << ">>****SinglePart Body*******" << std::endl;
|
||||
std::cout << str(boost::format("Body size %d") % retVal.size()) << std::endl;
|
||||
std::copy(retVal.begin(), retVal.end(),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl << "<<****SinglePart Body*******" << std::endl;
|
||||
#endif
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// FIXME: Need to break the headers at 80 chars...
|
||||
template <typename headerList>
|
||||
void write_headers(std::ostream &out, const headerList &headers) {
|
||||
if (headers.size() > 0) {
|
||||
for (typename headerList::const_iterator iter = headers.begin();
|
||||
iter != headers.end(); ++iter)
|
||||
out << iter->first << ':' << iter->second << detail::k_crlf;
|
||||
}
|
||||
out << detail::k_crlf;
|
||||
}
|
||||
|
||||
template <typename bodyContainer>
|
||||
void write_body(std::ostream &out, const bodyContainer &body) {
|
||||
std::copy(body.begin(), body.end(), std::ostream_iterator<char>(out));
|
||||
}
|
||||
|
||||
inline void write_boundary(std::ostream &out, std::string boundary, bool isLast,
|
||||
bool leadingCR = true) {
|
||||
if (leadingCR) out << detail::k_crlf;
|
||||
out << "--" << boundary;
|
||||
if (isLast) out << "--";
|
||||
out << detail::k_crlf;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename traits>
|
||||
static boost::shared_ptr<basic_mime<traits> > parse_mime(
|
||||
Iterator &begin, Iterator end,
|
||||
const char *default_content_type = "text/plain");
|
||||
}
|
||||
|
||||
template <class traits = detail::default_types>
|
||||
class basic_mime {
|
||||
public:
|
||||
typedef enum {
|
||||
simple_part,
|
||||
multi_part,
|
||||
message_part
|
||||
} part_kind;
|
||||
// Types for headers
|
||||
typedef typename traits::string_type string_type;
|
||||
typedef std::pair<std::string, string_type> headerEntry;
|
||||
typedef std::list<headerEntry> headerList;
|
||||
typedef typename headerList::iterator headerIter;
|
||||
typedef typename headerList::const_iterator constHeaderIter;
|
||||
|
||||
// Types for the parts
|
||||
typedef boost::shared_ptr<basic_mime> mimePtr;
|
||||
typedef std::vector<mimePtr> partList;
|
||||
typedef typename partList::iterator partIter;
|
||||
typedef typename partList::const_iterator constPartIter;
|
||||
|
||||
// Type for the body
|
||||
typedef typename traits::body_type bodyContainer;
|
||||
typedef boost::shared_ptr<bodyContainer> mimeBody;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Constructors, destructor, assignment, and swap
|
||||
// -----------------------------------------------------------
|
||||
|
||||
basic_mime(const char *type, const char *subtype)
|
||||
: m_body_prolog_is_missing(false),
|
||||
m_body(new bodyContainer),
|
||||
m_body_epilog(new bodyContainer) {
|
||||
if (NULL == type || NULL == subtype || 0 == std::strlen(type) ||
|
||||
0 == std::strlen(subtype))
|
||||
throw std::runtime_error(
|
||||
"Can't create a mime part w/o a type or subtype");
|
||||
|
||||
// We start with just two headers, "Content-Type:" and "Mime-Version"
|
||||
// Everything else is optional.
|
||||
m_part_kind = part_kind_from_string_pair(type, subtype);
|
||||
std::string ctString = str(boost::format("%s/%s") % type % subtype);
|
||||
set_header_value(detail::k_content_type_header, ctString);
|
||||
set_header_value(detail::k_mime_version_header,
|
||||
str(boost::format("1.0 (%s %s)") % detail::k_package_name %
|
||||
detail::k_package_version));
|
||||
}
|
||||
|
||||
basic_mime(const headerList &theHeaders,
|
||||
const string_type &default_content_type)
|
||||
: m_body_prolog_is_missing(false),
|
||||
m_body(new bodyContainer),
|
||||
m_body_epilog(new bodyContainer),
|
||||
m_default_content_type(default_content_type) {
|
||||
string_type ct = m_default_content_type;
|
||||
|
||||
constHeaderIter found = std::find_if(
|
||||
theHeaders.begin(), theHeaders.end(),
|
||||
detail::find_mime_header<string_type>(detail::k_content_type_header));
|
||||
if (found != theHeaders.end()) ct = found->second;
|
||||
|
||||
detail::mime_content_type mct = detail::parse_content_type(ct);
|
||||
m_part_kind = part_kind_from_string_pair(mct.type, mct.sub_type);
|
||||
m_headers = theHeaders;
|
||||
}
|
||||
|
||||
basic_mime(const basic_mime &rhs)
|
||||
: m_part_kind(rhs.m_part_kind),
|
||||
m_headers(rhs.m_headers),
|
||||
m_body_prolog_is_missing(rhs.m_body_prolog_is_missing),
|
||||
m_body(new bodyContainer(*rhs.m_body)),
|
||||
m_body_epilog(new bodyContainer(*rhs.m_body_epilog)),
|
||||
/* m_subparts ( rhs.m_subparts ), */ m_default_content_type(
|
||||
rhs.m_default_content_type) {
|
||||
// Copy the parts -- not just the shared pointers
|
||||
for (typename partList::const_iterator iter = rhs.subpart_begin();
|
||||
iter != rhs.subpart_end(); ++iter)
|
||||
m_subparts.push_back(mimePtr(new basic_mime(**iter)));
|
||||
}
|
||||
|
||||
// Simple, copy constructor-based assignment
|
||||
// If this is not efficient enough, then I can optimize it later
|
||||
basic_mime &operator=(const basic_mime &rhs) {
|
||||
basic_mime temp(rhs);
|
||||
this->swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(basic_mime &rhs) throw() {
|
||||
std::swap(m_part_kind, rhs.m_part_kind);
|
||||
std::swap(m_headers, rhs.m_headers);
|
||||
std::swap(m_body_prolog_is_missing, rhs.m_body_prolog_is_missing);
|
||||
std::swap(m_body, rhs.m_body);
|
||||
std::swap(m_body_epilog, rhs.m_body_epilog);
|
||||
std::swap(m_subparts, rhs.m_subparts);
|
||||
std::swap(m_default_content_type, rhs.m_default_content_type);
|
||||
}
|
||||
|
||||
~basic_mime() {}
|
||||
|
||||
// What kind of part is this (simple, multi, message)
|
||||
part_kind get_part_kind() const { return m_part_kind; }
|
||||
|
||||
// Sub-part information
|
||||
// FIXME: Need some error checking here
|
||||
// No sub-parts for simple parts, for example.
|
||||
size_t part_count() const { return m_subparts.size(); }
|
||||
|
||||
boost::shared_ptr<basic_mime> operator[](std::size_t idx) const {
|
||||
check_subpart_index(idx);
|
||||
return m_subparts[idx];
|
||||
}
|
||||
|
||||
void append_part(boost::shared_ptr<basic_mime> newPart) {
|
||||
check_subpart_append();
|
||||
m_subparts.push_back(newPart);
|
||||
}
|
||||
|
||||
partIter subpart_begin() { return m_subparts.begin(); }
|
||||
partIter subpart_end() { return m_subparts.end(); }
|
||||
constPartIter subpart_begin() const { return m_subparts.begin(); }
|
||||
constPartIter subpart_end() const { return m_subparts.end(); }
|
||||
|
||||
// Reading the raw headers
|
||||
headerIter header_begin() { return m_headers.begin(); }
|
||||
headerIter header_end() { return m_headers.end(); }
|
||||
constHeaderIter header_begin() const { return m_headers.begin(); }
|
||||
constHeaderIter header_end() const { return m_headers.end(); }
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Header manipulation
|
||||
// -----------------------------------------------------------
|
||||
|
||||
// The 'tag' part of the header is still a std::string
|
||||
bool header_exists(const char *key) const {
|
||||
return header_end() != find_header(key);
|
||||
}
|
||||
|
||||
string_type header_value(const char *key) const {
|
||||
constHeaderIter found = find_header(key);
|
||||
if (found == header_end())
|
||||
throw std::runtime_error("'header_value' not found");
|
||||
return found->second;
|
||||
}
|
||||
|
||||
void set_header_value(const char *key, const string_type &value,
|
||||
bool replace = false) {
|
||||
if (!replace)
|
||||
m_headers.push_back(std::make_pair(std::string(key), value));
|
||||
else {
|
||||
headerIter found = find_header(key);
|
||||
if (found == m_headers.end())
|
||||
throw std::runtime_error("'header_value' not found - can't replace");
|
||||
found->second = value;
|
||||
}
|
||||
}
|
||||
|
||||
string_type get_content_type_header() const {
|
||||
constHeaderIter found = find_header(detail::k_content_type_header);
|
||||
return found != header_end() ? found->second : m_default_content_type;
|
||||
}
|
||||
|
||||
string_type get_content_type() const {
|
||||
detail::mime_content_type mct =
|
||||
detail::parse_content_type(get_content_type_header());
|
||||
return string_type(mct.type) + '/' + mct.sub_type;
|
||||
}
|
||||
|
||||
// Special purpose helper routine
|
||||
void append_phrase_to_content_type(const char *key,
|
||||
const string_type &value) {
|
||||
headerIter found = find_header(detail::k_content_type_header);
|
||||
|
||||
// Create a Content-Type header if there isn't one
|
||||
if (m_headers.end() == found) {
|
||||
m_headers.push_back(std::make_pair(
|
||||
std::string(detail::k_content_type_header), m_default_content_type));
|
||||
found = find_header(detail::k_content_type_header);
|
||||
}
|
||||
|
||||
detail::mime_content_type mct = detail::parse_content_type(found->second);
|
||||
detail::phrase_container_t::const_iterator p_found =
|
||||
std::find_if(mct.phrases.begin(), mct.phrases.end(),
|
||||
detail::find_mime_header<std::string>(key));
|
||||
if (p_found != mct.phrases.end())
|
||||
throw std::runtime_error("phrase already exists");
|
||||
found->second += str(boost::format("; %s=\"%s\"") % key % value);
|
||||
}
|
||||
|
||||
// Body get/set methods
|
||||
mimeBody body() const { return m_body; }
|
||||
mimeBody body_prolog() const { return m_body; }
|
||||
mimeBody body_epilog() const { return m_body_epilog; }
|
||||
|
||||
std::size_t body_size() const { return m_body->size(); }
|
||||
|
||||
template <typename Iterator>
|
||||
void set_body(Iterator begin, Iterator end) {
|
||||
bodyContainer temp;
|
||||
std::copy(begin, end, std::back_inserter(temp));
|
||||
m_body->swap(temp);
|
||||
}
|
||||
|
||||
void set_body(const char *contents, size_t sz) {
|
||||
set_body(contents, contents + sz);
|
||||
}
|
||||
void set_body(std::istream &in) {
|
||||
set_body(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
}
|
||||
void set_body(const bodyContainer &new_body) { *m_body = new_body; }
|
||||
|
||||
void set_multipart_prolog_is_missing(bool isMissing) {
|
||||
m_body_prolog_is_missing = isMissing;
|
||||
}
|
||||
void set_body_prolog(const bodyContainer &new_body_prolog) {
|
||||
*m_body = new_body_prolog;
|
||||
}
|
||||
void set_body_epilog(const bodyContainer &new_body_epilog) {
|
||||
*m_body_epilog = new_body_epilog;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Output
|
||||
// -----------------------------------------------------------
|
||||
void stream_out(std::ostream &out) { // called by operator <<
|
||||
if (m_part_kind == simple_part) {
|
||||
detail::write_headers(out, m_headers);
|
||||
detail::write_body(out, *m_body);
|
||||
} else if (m_part_kind == message_part) {
|
||||
if (m_subparts.size() != 1)
|
||||
throw std::runtime_error(
|
||||
"message part w/wrong number of sub-parts - should be 1");
|
||||
|
||||
detail::write_headers(out, m_headers);
|
||||
m_subparts[0]->stream_out(out);
|
||||
} else { // multi-part
|
||||
// Find or invent a boundary string
|
||||
std::string boundary;
|
||||
try {
|
||||
boundary = detail::get_boundary(get_content_type_header());
|
||||
}
|
||||
catch (std::runtime_error &) {
|
||||
// FIXME: Make boundary strings (more?) unique
|
||||
boundary = str(boost::format("------=_NextPart-%s.%08ld") %
|
||||
detail::k_package_name % std::clock());
|
||||
append_phrase_to_content_type("boundary", boundary);
|
||||
}
|
||||
|
||||
// If the body prolog is missing, we don't want a CRLF on the front
|
||||
// of the first sub-part.
|
||||
// Note that there's a (subtle) difference between an zero length
|
||||
// body and a missing one.
|
||||
// See the comments in the parser code for more information.
|
||||
detail::write_headers(out, m_headers);
|
||||
bool writeCR = body_prolog()->size() > 0 || !m_body_prolog_is_missing;
|
||||
detail::write_body(out, *body_prolog());
|
||||
for (typename partList::const_iterator iter = m_subparts.begin();
|
||||
iter != m_subparts.end(); ++iter) {
|
||||
detail::write_boundary(out, boundary, false, writeCR);
|
||||
(*iter)->stream_out(out);
|
||||
writeCR = true;
|
||||
}
|
||||
detail::write_boundary(out, boundary, true);
|
||||
detail::write_body(out, *body_epilog());
|
||||
}
|
||||
// out << detail::k_crlf;
|
||||
}
|
||||
|
||||
// Build a simple mime part
|
||||
template <typename Iterator>
|
||||
static basic_mime make_simple_part(const char *type, const char *subtype,
|
||||
Iterator begin, Iterator end) {
|
||||
basic_mime retval(type, subtype);
|
||||
retval.set_body(begin, end);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Build a mime part from a pair of iterators
|
||||
template <typename Iterator>
|
||||
static boost::shared_ptr<basic_mime<traits> > parse_mime(Iterator &begin,
|
||||
Iterator end) {
|
||||
return detail::parse_mime<Iterator, traits>(begin, end);
|
||||
}
|
||||
|
||||
// Build a mime part from a stream
|
||||
static boost::shared_ptr<basic_mime> parse_mime(std::istream &in) {
|
||||
boost::spirit::istream_iterator first(in);
|
||||
boost::spirit::istream_iterator last;
|
||||
return parse_mime(first, last);
|
||||
}
|
||||
|
||||
private:
|
||||
basic_mime(); // Can't create a part w/o a type
|
||||
|
||||
headerIter find_header(const char *key) {
|
||||
return std::find_if(header_begin(), header_end(),
|
||||
detail::find_mime_header<string_type>(key));
|
||||
}
|
||||
|
||||
constHeaderIter find_header(const char *key) const {
|
||||
return std::find_if(header_begin(), header_end(),
|
||||
detail::find_mime_header<string_type>(key));
|
||||
}
|
||||
|
||||
static part_kind part_kind_from_string_pair(const std::string &type,
|
||||
const std::string &sub_type) {
|
||||
if (boost::iequals(type, "multipart")) return multi_part;
|
||||
|
||||
part_kind retVal = simple_part;
|
||||
// I expect that this will get more complicated as time goes on....
|
||||
//
|
||||
// message/delivery-status is a simple type.
|
||||
// RFC 3464 defines message/delivery-status
|
||||
//<http://www.faqs.org/rfcs/rfc3464.html>
|
||||
// The body of a message/delivery-status consists of one or more
|
||||
// "fields" formatted according to the ABNF of RFC 822 header
|
||||
//"fields"
|
||||
// (see [RFC822]).
|
||||
if (boost::iequals(type, "message"))
|
||||
if (!boost::iequals(sub_type, "delivery-status")) retVal = message_part;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void check_subpart_index(size_t idx) const {
|
||||
if (get_part_kind() == simple_part)
|
||||
throw std::runtime_error("Simple Mime parts don't have sub-parts");
|
||||
else if (get_part_kind() == multi_part) {
|
||||
if (idx >= m_subparts.size())
|
||||
throw std::runtime_error(
|
||||
str(boost::format(
|
||||
"Trying to access part %d (of %d) sub-part to a "
|
||||
"multipart/xxx mime part") %
|
||||
idx % m_subparts.size()));
|
||||
} else { // message-part
|
||||
if (get_part_kind() == message_part)
|
||||
if (m_subparts.size() > 1)
|
||||
throw std::runtime_error(
|
||||
"How did a message/xxx mime parts get more than one "
|
||||
"sub-part?");
|
||||
|
||||
if (idx >= m_subparts.size())
|
||||
throw std::runtime_error(
|
||||
str(boost::format(
|
||||
"Trying to access part %d (of %d) sub-part to a "
|
||||
"message/xxx mime part") %
|
||||
idx % m_subparts.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void check_subpart_append() const {
|
||||
if (get_part_kind() == simple_part)
|
||||
throw std::runtime_error("Simple Mime parts don't have sub-parts");
|
||||
else if (get_part_kind() == message_part) {
|
||||
if (m_subparts.size() > 0)
|
||||
throw std::runtime_error(
|
||||
"Can't add a second sub-part to a message/xxx mime part");
|
||||
}
|
||||
// else { /* Multi-part */ } // We can always add to a multi-part
|
||||
}
|
||||
|
||||
part_kind m_part_kind;
|
||||
headerList m_headers;
|
||||
bool m_body_prolog_is_missing; // only for multiparts
|
||||
mimeBody m_body;
|
||||
mimeBody m_body_epilog; // only for multiparts
|
||||
partList m_subparts; // only for multiparts or message
|
||||
string_type m_default_content_type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Iterator, typename traits>
|
||||
static boost::shared_ptr<basic_mime<traits> > parse_mime(
|
||||
Iterator &begin, Iterator end, const char *default_content_type) {
|
||||
tracer t(__func__);
|
||||
typedef typename boost::mime::basic_mime<traits> mime_part;
|
||||
|
||||
shared_ptr<mime_part> retVal(new mime_part(
|
||||
detail::read_headers<typename mime_part::headerList>(begin, end),
|
||||
default_content_type));
|
||||
|
||||
std::string content_type = retVal->get_content_type();
|
||||
|
||||
#ifdef DUMP_MIME_DATA
|
||||
std::cout << "Content-Type: " << content_type << std::endl;
|
||||
std::cout << str(boost::format("retVal->get_part_kind () = %d") %
|
||||
((int)retVal->get_part_kind())) << std::endl;
|
||||
#endif
|
||||
|
||||
if (retVal->get_part_kind() == mime_part::simple_part)
|
||||
retVal->set_body(detail::read_simplepart_body<
|
||||
typename mime_part::bodyContainer, Iterator>(begin, end));
|
||||
else if (retVal->get_part_kind() == mime_part::message_part) {
|
||||
// If we've got a message/xxxx, then there is no body, and we have
|
||||
// a single
|
||||
// embedded mime_part (which, of course, could be a multipart)
|
||||
retVal->append_part(parse_mime<Iterator, traits>(begin, end));
|
||||
} else /* multi_part */ {
|
||||
// Find or invent a boundary string
|
||||
std::string part_separator =
|
||||
detail::get_boundary(retVal->get_content_type_header());
|
||||
const char *cont_type = boost::iequals(content_type, "multipart/digest")
|
||||
? "message/rfc822"
|
||||
: "text/plain";
|
||||
|
||||
detail::multipart_body_type<typename traits::body_type> body_and_subParts;
|
||||
detail::read_multipart_body(begin, end, body_and_subParts, part_separator);
|
||||
|
||||
retVal->set_body_prolog(body_and_subParts.body_prolog);
|
||||
retVal->set_multipart_prolog_is_missing(
|
||||
body_and_subParts.prolog_is_missing);
|
||||
for (typename sub_parts_t::const_iterator iter =
|
||||
body_and_subParts.sub_parts.begin();
|
||||
iter != body_and_subParts.sub_parts.end(); ++iter) {
|
||||
typedef typename sub_part_t::const_iterator iter_type;
|
||||
iter_type b = iter->begin();
|
||||
iter_type e = iter->end();
|
||||
retVal->append_part(parse_mime<iter_type, traits>(b, e, cont_type));
|
||||
}
|
||||
retVal->set_body_epilog(body_and_subParts.body_epilog);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
//
|
||||
// Streaming
|
||||
//
|
||||
// -----------------------------------------------------------
|
||||
|
||||
template <typename traits>
|
||||
inline std::ostream &operator<<(std::ostream &stream,
|
||||
basic_mime<traits> &part) {
|
||||
part.stream_out(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
template <typename traits>
|
||||
inline std::ostream &operator<<(std::ostream &stream,
|
||||
boost::shared_ptr<basic_mime<traits> > part) {
|
||||
return stream << *part;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FUSION_ADAPT_STRUCT(boost::mime::detail::mime_content_type,
|
||||
(std::string, type)(std::string, sub_type)(
|
||||
boost::mime::detail::phrase_container_t, phrases))
|
||||
|
||||
#endif // _BOOST_MIME_HPP
|
17
cpp-netlib/boost/network.hpp
Normal file
17
cpp-netlib/boost/network.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
// 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 <boost/network/message.hpp> // message type implementation
|
||||
#include <boost/network/protocol.hpp> // protocols implementation
|
||||
|
||||
#endif // __NETWORK_HPP__
|
140
cpp-netlib/boost/network/constants.hpp
Normal file
140
cpp-netlib/boost/network/constants.hpp
Normal file
|
@ -0,0 +1,140 @@
|
|||
#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 <boost/network/support/is_default_string.hpp>
|
||||
#include <boost/network/support/is_default_wstring.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
template <class Tag>
|
||||
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 <class Tag>
|
||||
struct constants_wide {
|
||||
|
||||
static wchar_t const* https() {
|
||||
static wchar_t https_[] = L"https";
|
||||
return https_;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
struct constants
|
||||
: mpl::if_<
|
||||
is_default_string<Tag>, impl::constants_narrow<Tag>,
|
||||
typename mpl::if_<is_default_wstring<Tag>, impl::constants_wide<Tag>,
|
||||
unsupported_tag<Tag> >::type>::type {};
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_CONSTANTS_HPP_20100808
|
27
cpp-netlib/boost/network/detail/debug.hpp
Normal file
27
cpp-netlib/boost/network/detail/debug.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#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 <iostream>
|
||||
#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 */
|
34
cpp-netlib/boost/network/detail/directive_base.hpp
Normal file
34
cpp-netlib/boost/network/detail/directive_base.hpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
// 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 <class Tag>
|
||||
struct directive_base {
|
||||
typedef Tag tag;
|
||||
// explicit directive_base(basic_message<tag> & message_)
|
||||
// : _message(message_)
|
||||
protected:
|
||||
~directive_base() {}; // can only be extended
|
||||
|
||||
// mutable basic_message<tag> & _message;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_DETAIL_DIRECTIVE_BASE_HPP__
|
41
cpp-netlib/boost/network/detail/wrapper_base.hpp
Normal file
41
cpp-netlib/boost/network/detail/wrapper_base.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
// 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 <class Tag, class Message>
|
||||
struct wrapper_base {
|
||||
explicit wrapper_base(Message& message_) : _message(message_) {};
|
||||
|
||||
protected:
|
||||
~wrapper_base() {}; // for extending only
|
||||
|
||||
Message& _message;
|
||||
};
|
||||
|
||||
template <class Tag, class Message>
|
||||
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__
|
13
cpp-netlib/boost/network/include/http/client.hpp
Normal file
13
cpp-netlib/boost/network/include/http/client.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#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 <boost/network/protocol/http/client.hpp>
|
||||
|
||||
#endif // BOOST_NETWORK_INCLUDE_HTTP_CLIENT_HPP_
|
13
cpp-netlib/boost/network/include/http/server.hpp
Normal file
13
cpp-netlib/boost/network/include/http/server.hpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#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 <boost/network/protocol/http/server.hpp>
|
||||
|
||||
#endif
|
14
cpp-netlib/boost/network/include/message.hpp
Normal file
14
cpp-netlib/boost/network/include/message.hpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef BOOST_NETWORK_INCLUDE_MESSAGE_HPP_
|
||||
#define BOOST_NETWORK_INCLUDE_MESSAGE_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 basic message type
|
||||
|
||||
#include <boost/network/tags.hpp>
|
||||
#include <boost/network/message.hpp>
|
||||
|
||||
#endif // BOOST_NETWORK_INCLUDE_MESSAGE_HPP_
|
135
cpp-netlib/boost/network/message.hpp
Normal file
135
cpp-netlib/boost/network/message.hpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
// 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 <boost/network/message_fwd.hpp>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/traits/ostringstream.hpp>
|
||||
#include <boost/network/traits/headers_container.hpp>
|
||||
#include <boost/network/detail/directive_base.hpp>
|
||||
#include <boost/network/detail/wrapper_base.hpp>
|
||||
#include <boost/network/message/directives.hpp>
|
||||
#include <boost/network/message/wrappers.hpp>
|
||||
#include <boost/network/message/transformers.hpp>
|
||||
|
||||
#include <boost/network/message/modifiers/add_header.hpp>
|
||||
#include <boost/network/message/modifiers/remove_header.hpp>
|
||||
#include <boost/network/message/modifiers/clear_headers.hpp>
|
||||
#include <boost/network/message/modifiers/source.hpp>
|
||||
#include <boost/network/message/modifiers/destination.hpp>
|
||||
#include <boost/network/message/modifiers/body.hpp>
|
||||
|
||||
#include <boost/network/message/message_concept.hpp>
|
||||
|
||||
/** 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 <class Tag>
|
||||
struct basic_message {
|
||||
public:
|
||||
typedef Tag tag;
|
||||
|
||||
typedef typename headers_container<Tag>::type headers_container_type;
|
||||
typedef typename headers_container_type::value_type header_type;
|
||||
typedef typename string<Tag>::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<Tag> rhs) {
|
||||
rhs.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(basic_message<Tag>& 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<Tag>;
|
||||
friend struct detail::wrapper_base<Tag, basic_message<Tag> >;
|
||||
|
||||
mutable headers_container_type _headers;
|
||||
mutable string_type _body;
|
||||
mutable string_type _source;
|
||||
mutable string_type _destination;
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
inline void swap(basic_message<Tag>& left, basic_message<Tag>& right) {
|
||||
// swap for ADL
|
||||
left.swap(right);
|
||||
}
|
||||
|
||||
// Commenting this out as we don't need to do this anymore.
|
||||
// BOOST_CONCEPT_ASSERT((Message<basic_message<boost::network::tags::default_string>
|
||||
// >));
|
||||
// BOOST_CONCEPT_ASSERT((Message<basic_message<boost::network::tags::default_wstring>
|
||||
// >));
|
||||
typedef basic_message<tags::default_string> message;
|
||||
typedef basic_message<tags::default_wstring> wmessage;
|
||||
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_HPP__
|
36
cpp-netlib/boost/network/message/directives.hpp
Normal file
36
cpp-netlib/boost/network/message/directives.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
|
||||
// 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 <boost/network/message/directives/detail/string_directive.hpp>
|
||||
#include <boost/network/message/directives/header.hpp>
|
||||
#include <boost/network/message/directives/remove_header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
template <class Tag, class Directive>
|
||||
inline basic_message<Tag>& operator<<(basic_message<Tag>& 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__
|
|
@ -0,0 +1,59 @@
|
|||
#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 <boost/network/traits/string.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/network/support/is_pod.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
/**
|
||||
*
|
||||
* 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 <class ValueType> \
|
||||
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 Tag, template <class> class Message> \
|
||||
typename enable_if<is_pod<Tag>, void>::type operator()( \
|
||||
Message<Tag>& message) const { \
|
||||
pod_body; \
|
||||
} \
|
||||
template <class Tag, template <class> class Message> \
|
||||
typename enable_if<mpl::not_<is_pod<Tag> >, void>::type operator()( \
|
||||
Message<Tag>& message) const { \
|
||||
body; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template <class T> \
|
||||
inline name##_directive<T> name(T const& input) { \
|
||||
return name##_directive<T>(input); \
|
||||
}
|
||||
#endif /* BOOST_NETWORK_STRING_DIRECTIVE */
|
||||
|
||||
#endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 \
|
||||
*/
|
|
@ -0,0 +1,33 @@
|
|||
#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 <boost/network/traits/string.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace detail {
|
||||
|
||||
template <class Tag>
|
||||
struct string_value
|
||||
: mpl::if_<is_async<Tag>, boost::shared_future<typename string<Tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<Tag>, is_same<Tag, tags::default_string>,
|
||||
is_same<Tag, tags::default_wstring> >,
|
||||
typename string<Tag>::type, unsupported_tag<Tag> >::type> {};
|
||||
|
||||
} /* detail */
|
||||
} /* network */
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_VALUE_HPP_20100915 */
|
76
cpp-netlib/boost/network/message/directives/header.hpp
Normal file
76
cpp-netlib/boost/network/message/directives/header.hpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class KeyType, class ValueType>
|
||||
struct header_directive {
|
||||
|
||||
explicit header_directive(KeyType const& header_name,
|
||||
ValueType const& header_value)
|
||||
: _header_name(header_name), _header_value(header_value) {};
|
||||
|
||||
template <class Message>
|
||||
struct pod_directive {
|
||||
template <class T1, class T2>
|
||||
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 <class Message>
|
||||
struct normal_directive {
|
||||
template <class T1, class T2>
|
||||
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 <class Message>
|
||||
struct directive_impl
|
||||
: mpl::if_<is_base_of<tags::pod, typename Message::tag>,
|
||||
pod_directive<Message>, normal_directive<Message> >::type {};
|
||||
|
||||
template <class Message>
|
||||
void operator()(Message const& msg) const {
|
||||
directive_impl<Message>::eval(msg, _header_name, _header_value);
|
||||
}
|
||||
|
||||
private:
|
||||
KeyType const& _header_name;
|
||||
ValueType const& _header_value;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class T1, class T2>
|
||||
inline impl::header_directive<T1, T2> header(T1 const& header_name,
|
||||
T2 const& header_value) {
|
||||
return impl::header_directive<T1, T2>(header_name, header_value);
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_DIRECTIVES_HEADER_HPP__
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_message;
|
||||
|
||||
namespace impl {
|
||||
template <class T>
|
||||
struct remove_header_directive {
|
||||
|
||||
explicit remove_header_directive(T header_name)
|
||||
: header_name_(header_name) {};
|
||||
|
||||
template <class MessageTag>
|
||||
void operator()(basic_message<MessageTag>& msg) const {
|
||||
msg.headers().erase(header_name_);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable T header_name_;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
inline impl::remove_header_directive<std::string> remove_header(
|
||||
std::string header_name) {
|
||||
return impl::remove_header_directive<std::string>(header_name);
|
||||
}
|
||||
|
||||
inline impl::remove_header_directive<std::wstring> remove_header(
|
||||
std::wstring header_name) {
|
||||
return impl::remove_header_directive<std::wstring>(header_name);
|
||||
}
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // NETWORK_MESSAGE_DIRECTIVES_REMOVE_HEADER_HPP
|
66
cpp-netlib/boost/network/message/message_concept.hpp
Normal file
66
cpp-netlib/boost/network/message/message_concept.hpp
Normal file
|
@ -0,0 +1,66 @@
|
|||
|
||||
#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 <boost/concept_check.hpp>
|
||||
#include <boost/network/message/traits/body.hpp>
|
||||
#include <boost/network/message/traits/source.hpp>
|
||||
#include <boost/network/message/traits/destination.hpp>
|
||||
#include <boost/network/message/traits/headers.hpp>
|
||||
#include <boost/network/message/wrappers.hpp>
|
||||
#include <boost/network/message/transformers.hpp>
|
||||
#include <boost/network/message/directives.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
template <class M>
|
||||
struct Message : DefaultConstructible<M>, CopyConstructible<M>, Assignable<M> {
|
||||
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<M>::type body_type;
|
||||
typedef typename traits::source<M>::type source_type;
|
||||
typedef typename traits::destination<M>::type destination_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
|
54
cpp-netlib/boost/network/message/modifiers/add_header.hpp
Normal file
54
cpp-netlib/boost/network/message/modifiers/add_header.hpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_pod.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
template <class Message, class KeyType, class ValueType, class Tag>
|
||||
inline typename enable_if<
|
||||
mpl::and_<mpl::not_<is_pod<Tag> >, mpl::not_<is_async<Tag> > >, void>::type
|
||||
add_header(Message& message, KeyType const& key, ValueType const& value, Tag) {
|
||||
message.headers().insert(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
template <class Message, class KeyType, class ValueType, class Tag>
|
||||
inline typename enable_if<mpl::and_<mpl::not_<is_pod<Tag> >, is_async<Tag> >,
|
||||
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 <class Message, class KeyType, class ValueType, class Tag>
|
||||
inline typename enable_if<is_pod<Tag>, 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 Tag, template <class> class Message, class KeyType,
|
||||
class ValueType>
|
||||
inline void add_header(Message<Tag>& 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
|
35
cpp-netlib/boost/network/message/modifiers/body.hpp
Normal file
35
cpp-netlib/boost/network/message/modifiers/body.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#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 <boost/network/support/pod_or_normal.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
template <class Tag, template <class> class Message, class ValueType>
|
||||
inline void body_impl(Message<Tag>& message, ValueType const& body, tags::pod) {
|
||||
message.body = body;
|
||||
}
|
||||
|
||||
template <class Tag, template <class> class Message, class ValueType>
|
||||
inline void body_impl(Message<Tag>& message, ValueType const& body,
|
||||
tags::normal) {
|
||||
message.body(body);
|
||||
}
|
||||
|
||||
template <class Tag, template <class> class Message, class ValueType>
|
||||
inline void body(Message<Tag>& message, ValueType const& body_) {
|
||||
body_impl(message, body_, typename pod_or_normal<Tag>::type());
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_MODIFIERS_BODY_HPP_20100824
|
55
cpp-netlib/boost/network/message/modifiers/clear_headers.hpp
Normal file
55
cpp-netlib/boost/network/message/modifiers/clear_headers.hpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_pod.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
template <class Message, class Tag>
|
||||
inline typename enable_if<
|
||||
mpl::and_<mpl::not_<is_pod<Tag> >, mpl::not_<is_async<Tag> > >, void>::type
|
||||
clear_headers(Message const &message, Tag const &) {
|
||||
(typename Message::headers_container_type()).swap(message.headers());
|
||||
}
|
||||
|
||||
template <class Message, class Tag>
|
||||
inline typename enable_if<is_pod<Tag>, void>::type clear_headers(
|
||||
Message const &message, Tag const &) {
|
||||
(typename Message::headers_container_type()).swap(message.headers);
|
||||
}
|
||||
|
||||
template <class Message, class Tag>
|
||||
inline typename enable_if<mpl::and_<mpl::not_<is_pod<Tag> >, is_async<Tag> >,
|
||||
void>::type
|
||||
clear_headers(Message const &message, Tag const &) {
|
||||
boost::promise<typename Message::headers_container_type> header_promise;
|
||||
boost::shared_future<typename Message::headers_container_type> headers_future(
|
||||
header_promise.get_future());
|
||||
message.headers(headers_future);
|
||||
header_promise.set_value(typename Message::headers_container_type());
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, template <class> class Message>
|
||||
inline void clear_headers(Message<Tag> const &message) {
|
||||
impl::clear_headers(message, Tag());
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_MODIFIER_CLEAR_HEADERS_HPP_20100824
|
41
cpp-netlib/boost/network/message/modifiers/destination.hpp
Normal file
41
cpp-netlib/boost/network/message/modifiers/destination.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class ValueType, class Tag>
|
||||
inline void destination(Message const &message, ValueType const &destination_,
|
||||
Tag const &, mpl::false_ const &) {
|
||||
message.destination(destination_);
|
||||
}
|
||||
|
||||
template <class Message, class ValueType, class Tag>
|
||||
inline void destination(Message const &message, ValueType const &destination_,
|
||||
Tag const &, mpl::true_ const &) {
|
||||
message.destination(destination_);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, template <class> class Message, class ValueType>
|
||||
inline void destination(Message<Tag> const &message,
|
||||
ValueType const &destination_) {
|
||||
impl::destination(message, destination_, Tag(), is_async<Tag>());
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_MODIFIER_DESTINATION_HPP_20100824
|
65
cpp-netlib/boost/network/message/modifiers/remove_header.hpp
Normal file
65
cpp-netlib/boost/network/message/modifiers/remove_header.hpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_pod.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/range/algorithm/remove_if.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class KeyType, class Tag>
|
||||
inline typename enable_if<
|
||||
mpl::and_<mpl::not_<is_pod<Tag> >, mpl::not_<is_async<Tag> > >, void>::type
|
||||
remove_header(Message& message, KeyType const& key, Tag) {
|
||||
message.headers().erase(key);
|
||||
}
|
||||
|
||||
template <class Message, class KeyType, class Tag>
|
||||
inline typename enable_if<mpl::and_<mpl::not_<is_pod<Tag> >, is_async<Tag> >,
|
||||
void>::type
|
||||
remove_header(Message& message, KeyType const& key, Tag) {
|
||||
message.remove_header(key);
|
||||
}
|
||||
|
||||
template <class KeyType>
|
||||
struct iequals_pred {
|
||||
KeyType const& key;
|
||||
iequals_pred(KeyType const& key) : key(key) {}
|
||||
template <class Header>
|
||||
bool operator()(Header& other) const {
|
||||
return boost::iequals(key, name(other));
|
||||
}
|
||||
};
|
||||
|
||||
template <class Message, class KeyType, class Tag>
|
||||
inline typename enable_if<is_pod<Tag>, void>::type remove_header(
|
||||
Message& message, KeyType const& key, Tag) {
|
||||
message.headers.erase(
|
||||
boost::remove_if(message.headers, iequals_pred<KeyType>(key)),
|
||||
message.headers.end());
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, template <class> class Message, class KeyType>
|
||||
inline void remove_header(Message<Tag>& message, KeyType const& key) {
|
||||
impl::remove_header(message, key, Tag());
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824
|
40
cpp-netlib/boost/network/message/modifiers/source.hpp
Normal file
40
cpp-netlib/boost/network/message/modifiers/source.hpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class ValueType, class Tag>
|
||||
inline void source(Message const &message, ValueType const &source_,
|
||||
Tag const &, mpl::false_ const &) {
|
||||
message.source(source_);
|
||||
}
|
||||
|
||||
template <class Message, class ValueType, class Tag>
|
||||
inline void source(Message const &message, ValueType const &source_,
|
||||
Tag const &, mpl::true_ const &) {
|
||||
message.source(source_);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, template <class> class Message, class ValueType>
|
||||
inline void source(Message<Tag> const &message, ValueType const &source_) {
|
||||
impl::source(message, source_, Tag(), is_async<Tag>());
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_MODIFIER_SOURCE_HPP_20100824
|
43
cpp-netlib/boost/network/message/traits/body.hpp
Normal file
43
cpp-netlib/boost/network/message/traits/body.hpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace traits {
|
||||
|
||||
template <class Tag>
|
||||
struct unsupported_tag;
|
||||
|
||||
template <class Message>
|
||||
struct body
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<typename string<typename Message::tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<typename Message::tag>,
|
||||
is_same<typename Message::tag, tags::default_string>,
|
||||
is_same<typename Message::tag, tags::default_wstring> >,
|
||||
typename string<typename Message::tag>::type,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_TRAITS_BODY_HPP_20100903
|
42
cpp-netlib/boost/network/message/traits/destination.hpp
Normal file
42
cpp-netlib/boost/network/message/traits/destination.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace traits {
|
||||
|
||||
template <class Tag>
|
||||
struct unsupported_tag;
|
||||
|
||||
template <class Message>
|
||||
struct destination
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<typename string<typename Message::tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<typename Message::tag>,
|
||||
is_same<typename Message::tag, tags::default_string>,
|
||||
is_same<typename Message::tag, tags::default_wstring> >,
|
||||
typename string<typename Message::tag>::type,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_TRAITS_DESTINATION_HPP_20100903
|
56
cpp-netlib/boost/network/message/traits/headers.hpp
Normal file
56
cpp-netlib/boost/network/message/traits/headers.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
|
||||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace traits {
|
||||
|
||||
template <class Tag>
|
||||
struct unsupported_tag;
|
||||
|
||||
template <class Message>
|
||||
struct header_key
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<typename string<typename Message::tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<typename Message::tag>,
|
||||
is_same<typename Message::tag, tags::default_string>,
|
||||
is_same<typename Message::tag, tags::default_wstring> >,
|
||||
typename string<typename Message::tag>::type,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
template <class Message>
|
||||
struct header_value
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<typename string<typename Message::tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<typename Message::tag>,
|
||||
is_same<typename Message::tag, tags::default_string>,
|
||||
is_same<typename Message::tag, tags::default_wstring> >,
|
||||
typename string<typename Message::tag>::type,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_TRAITS_HEADERS_HPP_20100903
|
41
cpp-netlib/boost/network/message/traits/source.hpp
Normal file
41
cpp-netlib/boost/network/message/traits/source.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace traits {
|
||||
|
||||
template <class Tag>
|
||||
struct unsupported_tag;
|
||||
|
||||
template <class Message>
|
||||
struct source
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<typename string<typename Message::tag>::type>,
|
||||
typename mpl::if_<
|
||||
mpl::or_<is_sync<typename Message::tag>,
|
||||
is_same<typename Message::tag, tags::default_string>,
|
||||
is_same<typename Message::tag, tags::default_wstring> >,
|
||||
typename string<typename Message::tag>::type,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
} // namespace traits
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif // BOOST_NETWORK_MESSAGE_TRAITS_SOURCE_HPP_20100903
|
53
cpp-netlib/boost/network/message/transformers.hpp
Normal file
53
cpp-netlib/boost/network/message/transformers.hpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
// 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 <boost/network/message/transformers/selectors.hpp>
|
||||
#include <boost/network/message/transformers/to_upper.hpp>
|
||||
#include <boost/network/message/transformers/to_lower.hpp>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace impl {
|
||||
template <class Algorithm, class Selector>
|
||||
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 <class Algorithm, class Selector>
|
||||
struct transform_impl : public get_real_algorithm<Algorithm, Selector>::type {};
|
||||
} // namspace impl
|
||||
|
||||
template <class Algorithm, class Selector>
|
||||
inline impl::transform_impl<Algorithm, Selector> transform(Algorithm,
|
||||
Selector) {
|
||||
return impl::transform_impl<Algorithm, Selector>();
|
||||
}
|
||||
|
||||
template <class Tag, class Algorithm, class Selector>
|
||||
inline basic_message<Tag>& operator<<(
|
||||
basic_message<Tag>& msg_,
|
||||
impl::transform_impl<Algorithm, Selector> const& transformer) {
|
||||
transformer(msg_);
|
||||
return msg_;
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_TRANSFORMERS_HPP__
|
55
cpp-netlib/boost/network/message/transformers/selectors.hpp
Normal file
55
cpp-netlib/boost/network/message/transformers/selectors.hpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
|
||||
// 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__
|
86
cpp-netlib/boost/network/message/transformers/to_lower.hpp
Normal file
86
cpp-netlib/boost/network/message/transformers/to_lower.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
// 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 <boost/algorithm/string.hpp>
|
||||
|
||||
/** 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 <class Selector>
|
||||
struct to_lower_transformer {};
|
||||
|
||||
template <>
|
||||
struct to_lower_transformer<selectors::source_selector> {
|
||||
template <class Tag>
|
||||
void operator()(basic_message<Tag> &message_) const {
|
||||
boost::to_lower(message_.source());
|
||||
}
|
||||
|
||||
protected:
|
||||
~to_lower_transformer() {}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct to_lower_transformer<selectors::destination_selector> {
|
||||
template <class Tag>
|
||||
void operator()(basic_message<Tag> &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 <class Selector>
|
||||
struct type : public impl::to_lower_transformer<Selector> {};
|
||||
|
||||
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__
|
86
cpp-netlib/boost/network/message/transformers/to_upper.hpp
Normal file
86
cpp-netlib/boost/network/message/transformers/to_upper.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
|
||||
// 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 <boost/algorithm/string.hpp>
|
||||
|
||||
/** 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 <class Selector>
|
||||
struct to_upper_transformer {};
|
||||
|
||||
template <>
|
||||
struct to_upper_transformer<selectors::source_selector> {
|
||||
template <class Tag>
|
||||
void operator()(basic_message<Tag> &message_) const {
|
||||
boost::to_upper(message_.source());
|
||||
}
|
||||
|
||||
protected:
|
||||
~to_upper_transformer() {};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct to_upper_transformer<selectors::destination_selector> {
|
||||
template <class Tag>
|
||||
void operator()(basic_message<Tag> &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 <class Selector>
|
||||
struct type : public impl::to_upper_transformer<Selector> {};
|
||||
|
||||
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__
|
19
cpp-netlib/boost/network/message/wrappers.hpp
Normal file
19
cpp-netlib/boost/network/message/wrappers.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
// 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 <boost/network/message/wrappers/headers.hpp>
|
||||
#include <boost/network/message/wrappers/body.hpp>
|
||||
#include <boost/network/message/wrappers/source.hpp>
|
||||
#include <boost/network/message/wrappers/destination.hpp>
|
||||
|
||||
#endif // __NETWORK_MESSAGE_WRAPPERS_HPP__
|
105
cpp-netlib/boost/network/message/wrappers/body.hpp
Normal file
105
cpp-netlib/boost/network/message/wrappers/body.hpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
#include <boost/network/detail/wrapper_base.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
template <class Message>
|
||||
struct body_range {
|
||||
typedef typename boost::iterator_range<
|
||||
typename Message::string_type::const_iterator> type;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
template <class Tag>
|
||||
struct body_wrapper : public detail::wrapper_base<Tag, basic_message<Tag> > {
|
||||
typedef basic_message<Tag> message_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef detail::wrapper_base<Tag, basic_message<Tag> > wrapper_base;
|
||||
|
||||
explicit body_wrapper(basic_message<Tag>& 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<string_type>::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 <class Tag>
|
||||
struct body_wrapper_const
|
||||
: public detail::wrapper_base_const<Tag, basic_message<Tag> > {
|
||||
typedef basic_message<Tag> message_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef detail::wrapper_base_const<Tag, basic_message<Tag> > wrapper_base;
|
||||
|
||||
explicit body_wrapper_const(basic_message<Tag> 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<string_type>() const {
|
||||
return boost::make_iterator_range(wrapper_base::_message.body());
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
body_wrapper<Tag> const& body) {
|
||||
os << static_cast<typename body_wrapper<Tag>::string_type>(body);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
body_wrapper_const<Tag> const& body) {
|
||||
os << static_cast<typename body_wrapper_const<Tag>::string_type>(body);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag>
|
||||
inline impl::body_wrapper<Tag> const body(basic_message<Tag>& message_) {
|
||||
return impl::body_wrapper<Tag>(message_);
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline impl::body_wrapper_const<Tag> const body(
|
||||
basic_message<Tag> const& message_) {
|
||||
return impl::body_wrapper_const<Tag>(message_);
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_WRAPPERS_BODY_HPP__
|
42
cpp-netlib/boost/network/message/wrappers/destination.hpp
Normal file
42
cpp-netlib/boost/network/message/wrappers/destination.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
template <class Tag>
|
||||
struct destination_wrapper
|
||||
: public detail::wrapper_base<Tag, basic_message<Tag> > {
|
||||
typedef Tag tag;
|
||||
typedef basic_message<tag> message_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef detail::wrapper_base<Tag, basic_message<Tag> > 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 <class Tag>
|
||||
inline typename string<Tag>::type destination(basic_message<Tag>& message_) {
|
||||
return impl::destination_wrapper<Tag>(message_);
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_WRAPPERS_DESTINATION_HPP__
|
101
cpp-netlib/boost/network/message/wrappers/headers.hpp
Normal file
101
cpp-netlib/boost/network/message/wrappers/headers.hpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
#include <boost/network/traits/headers_container.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/range/functions.hpp>
|
||||
#include <boost/network/detail/wrapper_base.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
/// Template metaprogram to get the range type for a message
|
||||
template <class Message>
|
||||
struct headers_range {
|
||||
typedef typename headers_container<typename Message::tag>::type
|
||||
headers_container_type;
|
||||
typedef typename boost::iterator_range<
|
||||
typename headers_container_type::const_iterator> type;
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
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<iterator, iterator>)
|
||||
* whose keys are all equal to the index string.
|
||||
*
|
||||
* This type is also convertible to a
|
||||
* headers_range<basic_message<tag> >::type
|
||||
* Which allows for full range support.
|
||||
*
|
||||
* The type is also convertible to a
|
||||
* headers_container<Tag>::type
|
||||
* Which copies the headers from the wrapped message.
|
||||
*
|
||||
*/
|
||||
namespace impl {
|
||||
template <class Tag>
|
||||
struct headers_wrapper
|
||||
: public detail::wrapper_base_const<Tag, basic_message<Tag> > {
|
||||
typedef Tag tag;
|
||||
typedef basic_message<Tag> message_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef typename headers_range<message_type>::type range_type;
|
||||
typedef typename headers_container<Tag>::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<Tag, basic_message<Tag> > wrapper_base;
|
||||
|
||||
explicit headers_wrapper(basic_message<Tag> const& message_)
|
||||
: wrapper_base(message_) {};
|
||||
|
||||
range_type operator[](string_type const& key) const {
|
||||
return headers_wrapper<Tag>::_message.headers().equal_range(key);
|
||||
};
|
||||
|
||||
typename message_type::headers_container_type::size_type count(
|
||||
string_type const& key) const {
|
||||
return headers_wrapper<Tag>::_message.headers().count(key);
|
||||
};
|
||||
|
||||
const_iterator begin() const {
|
||||
return headers_wrapper<Tag>::_message.headers().begin();
|
||||
};
|
||||
|
||||
const_iterator end() const {
|
||||
return headers_wrapper<Tag>::_message.headers().end();
|
||||
};
|
||||
|
||||
operator range_type() {
|
||||
return make_iterator_range(headers_wrapper<Tag>::_message.headers().begin(),
|
||||
headers_wrapper<Tag>::_message.headers().end());
|
||||
};
|
||||
|
||||
operator headers_container_type() {
|
||||
return headers_wrapper<Tag>::_message.headers();
|
||||
}
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
/// Factory method to create the right wrapper object
|
||||
template <class Tag>
|
||||
inline impl::headers_wrapper<Tag> headers(basic_message<Tag> const& message_) {
|
||||
return impl::headers_wrapper<Tag>(message_);
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_WRAPPERS_HEADERS_HPP__
|
41
cpp-netlib/boost/network/message/wrappers/source.hpp
Normal file
41
cpp-netlib/boost/network/message/wrappers/source.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
namespace impl {
|
||||
template <class Tag>
|
||||
struct source_wrapper : public detail::wrapper_base<Tag, basic_message<Tag> > {
|
||||
typedef Tag tag;
|
||||
typedef basic_message<tag> message_type;
|
||||
typedef typename string<tag>::type string_type;
|
||||
typedef detail::wrapper_base<Tag, basic_message<Tag> > wrapper_base;
|
||||
|
||||
explicit source_wrapper(basic_message<tag>& message_)
|
||||
: wrapper_base(message_) {};
|
||||
|
||||
operator string_type() const {
|
||||
return string_type(wrapper_base::_message.source());
|
||||
};
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag>
|
||||
inline typename string<Tag>::type source(basic_message<Tag>& message_) {
|
||||
return impl::source_wrapper<Tag>(message_);
|
||||
}
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // __NETWORK_MESSAGE_WRAPPERS_SOURCE_HPP__
|
18
cpp-netlib/boost/network/message_fwd.hpp
Normal file
18
cpp-netlib/boost/network/message_fwd.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
// 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 <class Tag>
|
||||
struct basic_message;
|
||||
|
||||
} // namespace boost
|
||||
} // namespace network
|
||||
|
||||
#endif // __2008817MESSAGE_FWD_INC__
|
16
cpp-netlib/boost/network/protocol.hpp
Normal file
16
cpp-netlib/boost/network/protocol.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
// 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 <boost/network/protocol/http.hpp> // include HTTP implementation
|
||||
|
||||
#endif // __NETWORK_PROTOCOLS_20070908-1_HPP__
|
19
cpp-netlib/boost/network/protocol/http.hpp
Normal file
19
cpp-netlib/boost/network/protocol/http.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
// 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 <boost/network/protocol/http/response.hpp>
|
||||
#include <boost/network/protocol/http/request.hpp>
|
||||
#include <boost/network/protocol/http/client.hpp>
|
||||
#include <boost/network/protocol/http/errors.hpp>
|
||||
|
||||
#endif // __NETWORK_PROTOCOL_HTTP_20070908-1_HPP__
|
192
cpp-netlib/boost/network/protocol/http/algorithms/linearize.hpp
Normal file
192
cpp-netlib/boost/network/protocol/http/algorithms/linearize.hpp
Normal file
|
@ -0,0 +1,192 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028
|
||||
|
||||
// Copyright 2010 Dean Michael Berris.
|
||||
// Copyright 2014 Jussi Lyytinen
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/protocol/http/message/header/name.hpp>
|
||||
#include <boost/network/protocol/http/message/header/value.hpp>
|
||||
#include <boost/network/protocol/http/message/header_concept.hpp>
|
||||
#include <boost/network/protocol/http/request_concept.hpp>
|
||||
#include <boost/network/constants.hpp>
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/range/algorithm/copy.hpp>
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct linearize_header {
|
||||
typedef typename string<Tag>::type string_type;
|
||||
|
||||
template <class Arguments>
|
||||
struct result;
|
||||
|
||||
template <class This, class Arg>
|
||||
struct result<This(Arg)> {
|
||||
typedef string_type type;
|
||||
};
|
||||
|
||||
template <class ValueType>
|
||||
BOOST_CONCEPT_REQUIRES(((Header<typename boost::remove_cv<ValueType>::type>)),
|
||||
(string_type))
|
||||
operator()(ValueType& header) {
|
||||
typedef typename ostringstream<Tag>::type output_stream;
|
||||
typedef constants<Tag> consts;
|
||||
output_stream header_line;
|
||||
header_line << name(header) << consts::colon() << consts::space()
|
||||
<< value(header) << consts::crlf();
|
||||
return header_line.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Request, class OutputIterator>
|
||||
BOOST_CONCEPT_REQUIRES(((ClientRequest<Request>)), (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<Tag> consts;
|
||||
typedef typename string<Tag>::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<string_type>(version_major),
|
||||
version_minor_str =
|
||||
boost::lexical_cast<string_type>(version_minor);
|
||||
boost::copy(version_major_str, oi);
|
||||
*oi = consts::dot_char();
|
||||
boost::copy(version_minor_str, oi);
|
||||
boost::copy(crlf, oi);
|
||||
|
||||
// We need to determine whether we've seen any of the following headers
|
||||
// before setting the defaults. We use a bitset to keep track of the
|
||||
// defaulted headers.
|
||||
enum {
|
||||
ACCEPT,
|
||||
ACCEPT_ENCODING,
|
||||
HOST,
|
||||
CONNECTION,
|
||||
MAX
|
||||
};
|
||||
std::bitset<MAX> found_headers;
|
||||
static char const* defaulted_headers[][2] = {
|
||||
{consts::accept(), consts::accept() + std::strlen(consts::accept())},
|
||||
{consts::accept_encoding(),
|
||||
consts::accept_encoding() + std::strlen(consts::accept_encoding())},
|
||||
{consts::host(), consts::host() + std::strlen(consts::host())},
|
||||
{consts::connection(),
|
||||
consts::connection() + std::strlen(consts::connection())}};
|
||||
|
||||
typedef typename headers_range<Request>::type headers_range;
|
||||
typedef typename range_value<headers_range>::type headers_value;
|
||||
BOOST_FOREACH(const headers_value & header, headers(request)) {
|
||||
string_type header_name = name(header), header_value = value(header);
|
||||
// Here we check that we have not seen an override to the defaulted
|
||||
// headers.
|
||||
for (int header_index = 0; header_index < MAX; ++header_index)
|
||||
if (std::distance(header_name.begin(), header_name.end()) ==
|
||||
std::distance(defaulted_headers[header_index][0],
|
||||
defaulted_headers[header_index][1]) &&
|
||||
std::equal(header_name.begin(), header_name.end(),
|
||||
defaulted_headers[header_index][0],
|
||||
algorithm::is_iequal()))
|
||||
found_headers.set(header_index, true);
|
||||
|
||||
// We ignore empty headers.
|
||||
if (header_value.empty()) continue;
|
||||
boost::copy(header_name, oi);
|
||||
*oi = consts::colon_char();
|
||||
*oi = consts::space_char();
|
||||
boost::copy(header_value, oi);
|
||||
boost::copy(crlf, oi);
|
||||
}
|
||||
|
||||
if (!found_headers[HOST]) {
|
||||
boost::copy(host, oi);
|
||||
*oi = consts::colon_char();
|
||||
*oi = consts::space_char();
|
||||
boost::copy(request.host(), oi);
|
||||
boost::optional<boost::uint16_t> port_ =
|
||||
#if (_MSC_VER >= 1600 && BOOST_VERSION > 105500)
|
||||
port(request).as_optional();
|
||||
#else
|
||||
port(request);
|
||||
#endif
|
||||
if (port_) {
|
||||
string_type port_str = boost::lexical_cast<string_type>(*port_);
|
||||
*oi = consts::colon_char();
|
||||
boost::copy(port_str, oi);
|
||||
}
|
||||
boost::copy(crlf, oi);
|
||||
}
|
||||
|
||||
if (!found_headers[ACCEPT]) {
|
||||
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 &&
|
||||
!found_headers[ACCEPT_ENCODING]) {
|
||||
boost::copy(accept_encoding, oi);
|
||||
*oi = consts::colon_char();
|
||||
*oi = consts::space_char();
|
||||
boost::copy(default_accept_encoding, oi);
|
||||
boost::copy(crlf, oi);
|
||||
}
|
||||
|
||||
if (!connection_keepalive<Tag>::value && !found_headers[CONNECTION]) {
|
||||
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<Request>::type body_data = body(request).range();
|
||||
return boost::copy(body_data, oi);
|
||||
}
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* net */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */
|
72
cpp-netlib/boost/network/protocol/http/client.hpp
Normal file
72
cpp-netlib/boost/network/protocol/http/client.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#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 <boost/network/version.hpp>
|
||||
#include <boost/network/traits/ostringstream.hpp>
|
||||
#include <boost/network/protocol/http/message.hpp>
|
||||
#include <boost/network/protocol/http/response.hpp>
|
||||
#include <boost/network/protocol/http/request.hpp>
|
||||
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
|
||||
#include <boost/network/protocol/http/client/facade.hpp>
|
||||
#include <boost/network/protocol/http/client/macros.hpp>
|
||||
#include <boost/network/protocol/http/client/options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client : basic_client_facade<Tag, version_major, version_minor> {
|
||||
private:
|
||||
typedef basic_client_facade<Tag, version_major, version_minor>
|
||||
base_facade_type;
|
||||
|
||||
public:
|
||||
typedef basic_request<Tag> request;
|
||||
typedef basic_response<Tag> response;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef Tag tag_type;
|
||||
typedef client_options<Tag> options;
|
||||
|
||||
// Constructors
|
||||
// =================================================================
|
||||
// This constructor takes a single options argument of type
|
||||
// client_options. See boost/network/protocol/http/client/options.hpp
|
||||
// for more details.
|
||||
explicit basic_client(options const& options) : base_facade_type(options) {}
|
||||
|
||||
// This default constructor sets up the default options.
|
||||
basic_client() : base_facade_type(options()) {}
|
||||
//
|
||||
// =================================================================
|
||||
};
|
||||
|
||||
#ifndef BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG
|
||||
#define BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG tags::http_async_8bit_udp_resolve
|
||||
#endif
|
||||
|
||||
typedef basic_client<BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG, 1, 1> client;
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_20091215
|
109
cpp-netlib/boost/network/protocol/http/client/async_impl.hpp
Normal file
109
cpp-netlib/boost/network/protocol/http/client/async_impl.hpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
#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 <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client_impl;
|
||||
|
||||
namespace impl {
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct async_client
|
||||
: connection_policy<Tag, version_major, version_minor>::type {
|
||||
typedef typename connection_policy<Tag, version_major, version_minor>::type
|
||||
connection_base;
|
||||
typedef typename resolver<Tag>::type resolver_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
|
||||
typedef function<void(boost::iterator_range<char const*> const&,
|
||||
system::error_code const&)> body_callback_function_type;
|
||||
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
|
||||
async_client(bool cache_resolved, bool follow_redirect,
|
||||
bool always_verify_peer, int timeout,
|
||||
boost::shared_ptr<boost::asio::io_service> service,
|
||||
optional<string_type> const& certificate_filename,
|
||||
optional<string_type> const& verify_path,
|
||||
optional<string_type> const& certificate_file,
|
||||
optional<string_type> const& private_key_file,
|
||||
optional<string_type> const& ciphers, long ssl_options)
|
||||
: connection_base(cache_resolved, follow_redirect, timeout),
|
||||
service_ptr(service.get()
|
||||
? service
|
||||
: boost::make_shared<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),
|
||||
certificate_file_(certificate_file),
|
||||
private_key_file_(private_key_file),
|
||||
ciphers_(ciphers),
|
||||
ssl_options_(ssl_options),
|
||||
always_verify_peer_(always_verify_peer) {
|
||||
connection_base::resolver_strand_.reset(
|
||||
new boost::asio::io_service::strand(service_));
|
||||
if (!service)
|
||||
lifetime_thread_.reset(new boost::thread(
|
||||
boost::bind(&boost::asio::io_service::run, &service_)));
|
||||
}
|
||||
|
||||
~async_client() throw() { sentinel_.reset(); }
|
||||
|
||||
void wait_complete() {
|
||||
sentinel_.reset();
|
||||
if (lifetime_thread_.get()) {
|
||||
lifetime_thread_->join();
|
||||
lifetime_thread_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
basic_response<Tag> const request_skeleton(
|
||||
basic_request<Tag> const& request_, string_type const& method,
|
||||
bool get_body, body_callback_function_type callback,
|
||||
body_generator_function_type generator) {
|
||||
typename connection_base::connection_ptr connection_;
|
||||
connection_ = connection_base::get_connection(
|
||||
resolver_, request_, always_verify_peer_, certificate_filename_,
|
||||
verify_path_, certificate_file_, private_key_file_, ciphers_,
|
||||
ssl_options_);
|
||||
return connection_->send_request(method, request_, get_body, callback,
|
||||
generator);
|
||||
}
|
||||
|
||||
boost::shared_ptr<boost::asio::io_service> service_ptr;
|
||||
boost::asio::io_service& service_;
|
||||
resolver_type resolver_;
|
||||
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
|
||||
boost::shared_ptr<boost::thread> lifetime_thread_;
|
||||
optional<string_type> certificate_filename_;
|
||||
optional<string_type> verify_path_;
|
||||
optional<string_type> certificate_file_;
|
||||
optional<string_type> private_key_file_;
|
||||
optional<string_type> ciphers_;
|
||||
long ssl_options_;
|
||||
bool always_verify_peer_;
|
||||
};
|
||||
} // namespace impl
|
||||
} // namespace http
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529
|
||||
|
||||
// Copryight 2013 Google, Inc.
|
||||
// Copyright 2010 Dean Michael Berris <dberris@google.com>
|
||||
// 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 <boost/network/protocol/http/response.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/connection_delegate_factory.hpp>
|
||||
#include <boost/network/protocol/http/traits/delegate_factory.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/async_normal.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct async_connection_base {
|
||||
typedef async_connection_base<Tag, version_major, version_minor> this_type;
|
||||
typedef typename resolver_policy<Tag>::type resolver_base;
|
||||
typedef typename resolver_base::resolver_type resolver_type;
|
||||
typedef typename resolver_base::resolve_function resolve_function;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef basic_request<Tag> request;
|
||||
typedef basic_response<Tag> response;
|
||||
typedef iterator_range<char const *> char_const_range;
|
||||
typedef function<void(char_const_range const &, system::error_code const &)>
|
||||
body_callback_function_type;
|
||||
typedef function<bool(string_type &)> body_generator_function_type;
|
||||
typedef shared_ptr<this_type> 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 always_verify_peer, bool https, int timeout,
|
||||
optional<string_type> certificate_filename = optional<string_type>(),
|
||||
optional<string_type> const &verify_path = optional<string_type>(),
|
||||
optional<string_type> certificate_file = optional<string_type>(),
|
||||
optional<string_type> private_key_file = optional<string_type>(),
|
||||
optional<string_type> ciphers = optional<string_type>(),
|
||||
long ssl_options = 0) {
|
||||
typedef http_async_connection<Tag, version_major, version_minor>
|
||||
async_connection;
|
||||
typedef typename delegate_factory<Tag>::type delegate_factory_type;
|
||||
connection_ptr temp;
|
||||
temp.reset(new async_connection(
|
||||
resolver, resolve, follow_redirect, timeout,
|
||||
delegate_factory_type::new_connection_delegate(
|
||||
resolver.get_io_service(), https, always_verify_peer,
|
||||
certificate_filename, verify_path, certificate_file,
|
||||
private_key_file, ciphers, ssl_options)));
|
||||
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,
|
||||
body_generator_function_type generator) = 0;
|
||||
|
||||
virtual ~async_connection_base() {}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529
|
|
@ -0,0 +1,509 @@
|
|||
#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 <boost/network/version.hpp>
|
||||
#include <boost/network/detail/debug.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/range/algorithm/transform.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/network/constants.hpp>
|
||||
#include <boost/network/traits/ostream_iterator.hpp>
|
||||
#include <boost/network/traits/istream.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/network/protocol/http/parser/incremental.hpp>
|
||||
#include <boost/network/protocol/http/message/wrappers/uri.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/async_protocol_handler.hpp>
|
||||
#include <boost/network/protocol/http/algorithms/linearize.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind/protect.hpp>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/network/protocol/http/traits/delegate_factory.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct async_connection_base;
|
||||
|
||||
namespace placeholders = boost::asio::placeholders;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct http_async_connection
|
||||
: async_connection_base<Tag, version_major, version_minor>,
|
||||
protected http_async_protocol_handler<Tag, version_major, version_minor>,
|
||||
boost::enable_shared_from_this<
|
||||
http_async_connection<Tag, version_major, version_minor> > {
|
||||
typedef async_connection_base<Tag, version_major, version_minor> base;
|
||||
typedef http_async_protocol_handler<Tag, version_major, version_minor>
|
||||
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 typename base::body_generator_function_type
|
||||
body_generator_function_type;
|
||||
typedef http_async_connection<Tag, version_major, version_minor> this_type;
|
||||
typedef typename delegate_factory<Tag>::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, int timeout,
|
||||
connection_delegate_ptr delegate)
|
||||
: timeout_(timeout),
|
||||
timer_(resolver.get_io_service()),
|
||||
is_timedout_(false),
|
||||
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,
|
||||
body_generator_function_type generator) {
|
||||
response response_;
|
||||
this->init_response(response_, get_body);
|
||||
linearize(request, method, version_major, version_minor,
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(
|
||||
&command_streambuf));
|
||||
this->method = method;
|
||||
boost::uint16_t port_ = port(request);
|
||||
string_type host_ = host(request);
|
||||
boost::uint16_t source_port = request.source_port();
|
||||
|
||||
resolve_(resolver_, host_, port_,
|
||||
request_strand_.wrap(boost::bind(
|
||||
&this_type::handle_resolved, this_type::shared_from_this(),
|
||||
host_, port_, source_port, get_body, callback,
|
||||
generator, boost::arg<1>(), boost::arg<2>())));
|
||||
if (timeout_ > 0) {
|
||||
timer_.expires_from_now(boost::posix_time::seconds(timeout_));
|
||||
timer_.async_wait(request_strand_.wrap(
|
||||
boost::bind(&this_type::handle_timeout, this_type::shared_from_this(),
|
||||
boost::arg<1>())));
|
||||
}
|
||||
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));
|
||||
this->timer_.cancel();
|
||||
}
|
||||
|
||||
void handle_timeout(boost::system::error_code const& ec) {
|
||||
if (!ec) delegate_->disconnect();
|
||||
is_timedout_ = true;
|
||||
}
|
||||
|
||||
void handle_resolved(string_type host, boost::uint16_t port, boost::uint16_t source_port, bool get_body,
|
||||
body_callback_function_type callback,
|
||||
body_generator_function_type generator,
|
||||
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, host, source_port,
|
||||
request_strand_.wrap(boost::bind(
|
||||
&this_type::handle_connected, this_type::shared_from_this(), host,
|
||||
port, source_port, get_body, callback, generator,
|
||||
std::make_pair(++iter, resolver_iterator()),
|
||||
placeholders::error)));
|
||||
} else {
|
||||
set_errors(ec ? ec : boost::asio::error::host_not_found);
|
||||
boost::iterator_range<const char*> range;
|
||||
if (callback) callback(range, ec);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_connected(string_type host, boost::uint16_t port, boost::uint16_t source_port, bool get_body,
|
||||
body_callback_function_type callback,
|
||||
body_generator_function_type generator,
|
||||
resolver_iterator_pair endpoint_range,
|
||||
boost::system::error_code const& ec) {
|
||||
if (is_timedout_) {
|
||||
set_errors(asio::error::timed_out);
|
||||
} else 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, generator, 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, host, source_port,
|
||||
request_strand_.wrap(boost::bind(
|
||||
&this_type::handle_connected, this_type::shared_from_this(),
|
||||
host, port, source_port, get_body, callback, generator,
|
||||
std::make_pair(++iter, resolver_iterator()),
|
||||
placeholders::error)));
|
||||
} else {
|
||||
set_errors(ec ? ec : boost::asio::error::host_not_found);
|
||||
boost::iterator_range<const char*> range;
|
||||
if (callback) callback(range, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum state_t {
|
||||
version,
|
||||
status,
|
||||
status_message,
|
||||
headers,
|
||||
body
|
||||
};
|
||||
|
||||
void handle_sent_request(bool get_body, body_callback_function_type callback,
|
||||
body_generator_function_type generator,
|
||||
boost::system::error_code const& ec,
|
||||
std::size_t bytes_transferred) {
|
||||
// TODO(dberris): review parameter necessity.
|
||||
(void)bytes_transferred;
|
||||
|
||||
if (!is_timedout_ && !ec) {
|
||||
if (generator) {
|
||||
// Here we write some more data that the generator provides,
|
||||
// before
|
||||
// we wait for data from the server.
|
||||
string_type chunk;
|
||||
if (generator(chunk)) {
|
||||
// At this point this means we have more data to write, so we
|
||||
// write
|
||||
// it out.
|
||||
std::copy(chunk.begin(), chunk.end(),
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(
|
||||
&command_streambuf));
|
||||
delegate_->write(
|
||||
command_streambuf,
|
||||
request_strand_.wrap(boost::bind(
|
||||
&this_type::handle_sent_request,
|
||||
this_type::shared_from_this(), get_body, callback, generator,
|
||||
placeholders::error, placeholders::bytes_transferred)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
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(is_timedout_ ? asio::error::timed_out : 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 const 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 && short_read_error;
|
||||
#endif
|
||||
if (!is_timedout_ &&
|
||||
(!ec || ec == boost::asio::error::eof || is_ssl_short_read_error)) {
|
||||
logic::tribool parsed_ok;
|
||||
size_t remainder;
|
||||
switch (state) {
|
||||
case version:
|
||||
if (ec == boost::asio::error::eof) return;
|
||||
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:
|
||||
if (ec == boost::asio::error::eof) return;
|
||||
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:
|
||||
if (ec == boost::asio::error::eof) return;
|
||||
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:
|
||||
if (ec == boost::asio::error::eof) return;
|
||||
// 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);
|
||||
if (this->is_chunk_encoding)
|
||||
this->body_promise.set_value(parse_chunk_encoding(body_string));
|
||||
else
|
||||
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();
|
||||
this->timer_.cancel();
|
||||
} 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(is_timedout_ ? asio::error::timed_out
|
||||
: 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:
|
||||
if (!callback) {
|
||||
// N.B. if callback is non-null, then body_promise has
|
||||
// already been set to value "" to indicate body is
|
||||
// handled by streaming handler so no exception should be set
|
||||
this->body_promise.set_exception(boost::copy_exception(error));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BOOST_ASSERT(false && "Bug, report this to the developers!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_type parse_chunk_encoding(string_type& body_string) {
|
||||
string_type body;
|
||||
string_type crlf = "\r\n";
|
||||
|
||||
typename string_type::iterator begin = body_string.begin();
|
||||
for (typename string_type::iterator iter =
|
||||
std::search(begin, body_string.end(), crlf.begin(), crlf.end());
|
||||
iter != body_string.end();
|
||||
iter =
|
||||
std::search(begin, body_string.end(), crlf.begin(), crlf.end())) {
|
||||
string_type line(begin, iter);
|
||||
if (line.empty()) break;
|
||||
std::stringstream stream(line);
|
||||
int len;
|
||||
stream >> std::hex >> len;
|
||||
std::advance(iter, 2);
|
||||
if (!len) break;
|
||||
if (len <= body_string.end() - iter) {
|
||||
body.insert(body.end(), iter, iter + len);
|
||||
std::advance(iter, len + 2);
|
||||
}
|
||||
begin = iter;
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
int timeout_;
|
||||
boost::asio::deadline_timer timer_;
|
||||
bool is_timedout_;
|
||||
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
|
|
@ -0,0 +1,356 @@
|
|||
#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 <boost/network/detail/debug.hpp>
|
||||
#include <boost/network/protocol/http/algorithms/linearize.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct http_async_protocol_handler {
|
||||
protected:
|
||||
typedef typename string<Tag>::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<Tag>::type escaped_stream;
|
||||
if (input == '\r') {
|
||||
string.append("\\r");
|
||||
} else if (input == '\n') {
|
||||
string.append("\\n");
|
||||
} else {
|
||||
escaped_stream << "\\x" << static_cast<int>(input);
|
||||
string.append(escaped_stream.str());
|
||||
}
|
||||
} else {
|
||||
string.push_back(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class ResponseType>
|
||||
void init_response(ResponseType& response_, bool get_body) {
|
||||
// TODO(dberris): review parameter necessity.
|
||||
(void)get_body;
|
||||
|
||||
boost::shared_future<string_type> source_future(
|
||||
source_promise.get_future());
|
||||
source(response_, source_future);
|
||||
|
||||
boost::shared_future<string_type> destination_future(
|
||||
destination_promise.get_future());
|
||||
destination(response_, destination_future);
|
||||
|
||||
boost::shared_future<typename headers_container<Tag>::type> headers_future(
|
||||
headers_promise.get_future());
|
||||
headers(response_, headers_future);
|
||||
|
||||
boost::shared_future<string_type> body_future(body_promise.get_future());
|
||||
body(response_, body_future);
|
||||
|
||||
boost::shared_future<string_type> version_future(
|
||||
version_promise.get_future());
|
||||
version(response_, version_future);
|
||||
|
||||
boost::shared_future<boost::uint16_t> status_future(
|
||||
status_promise.get_future());
|
||||
status(response_, status_future);
|
||||
|
||||
boost::shared_future<string_type> status_message_future(
|
||||
status_message_promise.get_future());
|
||||
status_message(response_, status_message_future);
|
||||
}
|
||||
|
||||
struct to_http_headers {
|
||||
typedef typename string<Tag>::type string_type;
|
||||
template <class U>
|
||||
string_type const operator()(U const& pair) const {
|
||||
typedef typename ostringstream<Tag>::type ostringstream_type;
|
||||
typedef constants<Tag> constants;
|
||||
ostringstream_type header_line;
|
||||
header_line << pair.first << constants::colon() << constants::space()
|
||||
<< pair.second << constants::crlf();
|
||||
return header_line.str();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Delegate, class Callback>
|
||||
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<typename buffer_type::const_iterator>
|
||||
result_range,
|
||||
input_range = boost::make_iterator_range(part_begin, part_end);
|
||||
fusion::tie(parsed_ok, result_range) = response_parser_.parse_until(
|
||||
response_parser_type::http_version_done, 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 <class Delegate, class Callback>
|
||||
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<typename buffer_type::const_iterator>
|
||||
result_range,
|
||||
input_range = boost::make_iterator_range(part_begin, part_end);
|
||||
fusion::tie(parsed_ok, result_range) = response_parser_.parse_until(
|
||||
response_parser_type::http_status_done, 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<boost::uint16_t>(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 <class Delegate, class Callback>
|
||||
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<typename buffer_type::const_iterator>
|
||||
result_range,
|
||||
input_range = boost::make_iterator_range(part_begin, part_end);
|
||||
fusion::tie(parsed_ok, result_range) = response_parser_.parse_until(
|
||||
response_parser_type::http_status_message_done, 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<typename string_type::const_iterator>
|
||||
input_range = boost::make_iterator_range(headers_part),
|
||||
result_range;
|
||||
logic::tribool parsed_ok;
|
||||
response_parser_type headers_parser(
|
||||
response_parser_type::http_header_line_done);
|
||||
typename headers_container<Tag>::type headers;
|
||||
std::pair<string_type, string_type> 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);
|
||||
}
|
||||
// determine if the body parser will need to handle chunked encoding
|
||||
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
|
||||
headers.equal_range("Transfer-Encoding");
|
||||
is_chunk_encoding =
|
||||
!boost::empty(transfer_encoding_range) &&
|
||||
boost::iequals(boost::begin(transfer_encoding_range)->second,
|
||||
"chunked");
|
||||
headers_promise.set_value(headers);
|
||||
}
|
||||
|
||||
template <class Delegate, class Callback>
|
||||
fusion::tuple<logic::tribool, size_t> 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<typename buffer_type::const_iterator>
|
||||
result_range,
|
||||
input_range = boost::make_iterator_range(part_begin, part_end);
|
||||
fusion::tie(parsed_ok, result_range) = response_parser_.parse_until(
|
||||
response_parser_type::http_headers_done, 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 <class Delegate, class Callback>
|
||||
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<Tag> response_parser_type;
|
||||
// TODO: make 1024 go away and become a configurable value.
|
||||
typedef boost::array<typename char_<Tag>::type, 1024> buffer_type;
|
||||
|
||||
response_parser_type response_parser_;
|
||||
boost::promise<string_type> version_promise;
|
||||
boost::promise<boost::uint16_t> status_promise;
|
||||
boost::promise<string_type> status_message_promise;
|
||||
boost::promise<typename headers_container<Tag>::type> headers_promise;
|
||||
boost::promise<string_type> source_promise;
|
||||
boost::promise<string_type> destination_promise;
|
||||
boost::promise<string_type> body_promise;
|
||||
buffer_type part;
|
||||
typename buffer_type::const_iterator part_begin;
|
||||
string_type partial_parsed;
|
||||
bool is_chunk_encoding;
|
||||
};
|
||||
|
||||
} /* impl */
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 \
|
||||
*/
|
|
@ -0,0 +1,37 @@
|
|||
#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, std::string host, boost::uint16_t source_port,
|
||||
function<void(system::error_code const &)> handler) = 0;
|
||||
virtual void write(
|
||||
asio::streambuf &command_streambuf,
|
||||
function<void(system::error_code const &, size_t)> handler) = 0;
|
||||
virtual void read_some(
|
||||
asio::mutable_buffers_1 const &read_buffer,
|
||||
function<void(system::error_code const &, size_t)> handler) = 0;
|
||||
virtual void disconnect() = 0;
|
||||
virtual ~connection_delegate() {}
|
||||
};
|
||||
|
||||
} /* impl */
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ \
|
||||
*/
|
|
@ -0,0 +1,62 @@
|
|||
#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 <boost/throw_exception.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/connection_delegate.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/normal_delegate.hpp>
|
||||
#ifdef BOOST_NETWORK_ENABLE_HTTPS
|
||||
#include <boost/network/protocol/http/client/connection/ssl_delegate.hpp>
|
||||
#endif /* BOOST_NETWORK_ENABLE_HTTPS */
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
struct ssl_delegate;
|
||||
|
||||
struct normal_delegate;
|
||||
|
||||
template <class Tag>
|
||||
struct connection_delegate_factory {
|
||||
typedef shared_ptr<connection_delegate> connection_delegate_ptr;
|
||||
typedef typename string<Tag>::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, bool always_verify_peer,
|
||||
optional<string_type> certificate_filename,
|
||||
optional<string_type> verify_path, optional<string_type> certificate_file,
|
||||
optional<string_type> private_key_file, optional<string_type> ciphers,
|
||||
long ssl_options) {
|
||||
connection_delegate_ptr delegate;
|
||||
if (https) {
|
||||
#ifdef BOOST_NETWORK_ENABLE_HTTPS
|
||||
delegate.reset(new ssl_delegate(
|
||||
service, always_verify_peer, certificate_filename, verify_path,
|
||||
certificate_file, private_key_file, ciphers, ssl_options));
|
||||
#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 \
|
||||
*/
|
|
@ -0,0 +1,54 @@
|
|||
#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 <boost/network/protocol/http/client/connection/connection_delegate.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/asio/placeholders.hpp>
|
||||
|
||||
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, std::string host, boost::uint16_t source_port,
|
||||
function<void(system::error_code const &)> handler);
|
||||
virtual void write(
|
||||
asio::streambuf &command_streambuf,
|
||||
function<void(system::error_code const &, size_t)> handler);
|
||||
virtual void read_some(
|
||||
asio::mutable_buffers_1 const &read_buffer,
|
||||
function<void(system::error_code const &, size_t)> handler);
|
||||
virtual void disconnect();
|
||||
~normal_delegate();
|
||||
|
||||
private:
|
||||
asio::io_service &service_;
|
||||
scoped_ptr<asio::ip::tcp::socket> socket_;
|
||||
|
||||
normal_delegate(normal_delegate const &); // = delete
|
||||
normal_delegate &operator=(normal_delegate); // = delete
|
||||
};
|
||||
|
||||
} /* impl */
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#ifdef BOOST_NETWORK_NO_LIB
|
||||
#include <boost/network/protocol/http/client/connection/normal_delegate.ipp>
|
||||
#endif /* BOOST_NETWORK_NO_LIB */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 \
|
||||
*/
|
|
@ -0,0 +1,57 @@
|
|||
#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 <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/normal_delegate.hpp>
|
||||
|
||||
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, std::string host, boost::uint16_t source_port,
|
||||
function<void(system::error_code const &)> handler) {
|
||||
|
||||
// TODO(dberris): review parameter necessity.
|
||||
(void)host;
|
||||
|
||||
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<void(system::error_code const &, size_t)> 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<void(system::error_code const &, size_t)> handler) {
|
||||
socket_->async_read_some(read_buffer, handler);
|
||||
}
|
||||
|
||||
void boost::network::http::impl::normal_delegate::disconnect() {
|
||||
if (socket_.get() && socket_->is_open()) {
|
||||
boost::system::error_code ignored;
|
||||
socket_->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored);
|
||||
if (!ignored) {
|
||||
socket_->close(ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::network::http::impl::normal_delegate::~normal_delegate() {}
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 \
|
||||
*/
|
|
@ -0,0 +1,76 @@
|
|||
#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 <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/network/protocol/http/client/connection/connection_delegate.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/network/support/is_default_string.hpp>
|
||||
#include <boost/network/support/is_default_wstring.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
struct ssl_delegate : connection_delegate,
|
||||
enable_shared_from_this<ssl_delegate> {
|
||||
ssl_delegate(asio::io_service &service, bool always_verify_peer,
|
||||
optional<std::string> certificate_filename,
|
||||
optional<std::string> verify_path,
|
||||
optional<std::string> certificate_file,
|
||||
optional<std::string> private_key_file,
|
||||
optional<std::string> ciphers, long ssl_options);
|
||||
|
||||
virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port,
|
||||
function<void(system::error_code const &)> handler);
|
||||
virtual void write(
|
||||
asio::streambuf &command_streambuf,
|
||||
function<void(system::error_code const &, size_t)> handler);
|
||||
virtual void read_some(
|
||||
asio::mutable_buffers_1 const &read_buffer,
|
||||
function<void(system::error_code const &, size_t)> handler);
|
||||
virtual void disconnect();
|
||||
~ssl_delegate();
|
||||
|
||||
private:
|
||||
asio::io_service &service_;
|
||||
optional<std::string> certificate_filename_;
|
||||
optional<std::string> verify_path_;
|
||||
optional<std::string> certificate_file_;
|
||||
optional<std::string> private_key_file_;
|
||||
optional<std::string> ciphers_;
|
||||
long ssl_options_;
|
||||
scoped_ptr<asio::ssl::context> context_;
|
||||
scoped_ptr<asio::ip::tcp::socket> tcp_socket_;
|
||||
scoped_ptr<asio::ssl::stream<asio::ip::tcp::socket&> > socket_;
|
||||
bool always_verify_peer_;
|
||||
|
||||
ssl_delegate(ssl_delegate const &); // = delete
|
||||
ssl_delegate &operator=(ssl_delegate); // = delete
|
||||
|
||||
void handle_connected(system::error_code const &ec,
|
||||
function<void(system::error_code const &)> handler);
|
||||
};
|
||||
|
||||
} /* impl */
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#ifdef BOOST_NETWORK_NO_LIB
|
||||
#include <boost/network/protocol/http/client/connection/ssl_delegate.ipp>
|
||||
#endif /* BOOST_NETWORK_NO_LIB */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 \
|
||||
*/
|
|
@ -0,0 +1,113 @@
|
|||
#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 <boost/network/protocol/http/client/connection/ssl_delegate.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
boost::network::http::impl::ssl_delegate::ssl_delegate(
|
||||
asio::io_service &service, bool always_verify_peer,
|
||||
optional<std::string> certificate_filename,
|
||||
optional<std::string> verify_path,
|
||||
optional<std::string> certificate_file,
|
||||
optional<std::string> private_key_file,
|
||||
optional<std::string> ciphers,
|
||||
long ssl_options)
|
||||
: service_(service),
|
||||
certificate_filename_(certificate_filename),
|
||||
verify_path_(verify_path),
|
||||
certificate_file_(certificate_file),
|
||||
private_key_file_(private_key_file),
|
||||
ciphers_(ciphers),
|
||||
ssl_options_(ssl_options),
|
||||
always_verify_peer_(always_verify_peer) {}
|
||||
|
||||
void boost::network::http::impl::ssl_delegate::connect(
|
||||
asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port,
|
||||
function<void(system::error_code const &)> handler) {
|
||||
context_.reset(
|
||||
new asio::ssl::context(service_, asio::ssl::context::sslv23_client));
|
||||
if (ciphers_) {
|
||||
::SSL_CTX_set_cipher_list(context_->native_handle(), ciphers_->c_str());
|
||||
}
|
||||
if (ssl_options_ != 0) {
|
||||
context_->set_options(ssl_options_);
|
||||
}
|
||||
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 {
|
||||
if (always_verify_peer_) {
|
||||
context_->set_verify_mode(asio::ssl::context::verify_peer);
|
||||
// use openssl default verify paths. uses openssl environment variables
|
||||
// SSL_CERT_DIR, SSL_CERT_FILE
|
||||
context_->set_default_verify_paths();
|
||||
} else
|
||||
context_->set_verify_mode(asio::ssl::context::verify_none);
|
||||
}
|
||||
if (certificate_file_)
|
||||
context_->use_certificate_file(*certificate_file_,
|
||||
boost::asio::ssl::context::pem);
|
||||
if (private_key_file_)
|
||||
context_->use_private_key_file(*private_key_file_,
|
||||
boost::asio::ssl::context::pem);
|
||||
|
||||
tcp_socket_.reset(new asio::ip::tcp::socket(service_, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), source_port)));
|
||||
socket_.reset(
|
||||
new asio::ssl::stream<asio::ip::tcp::socket&>(*(tcp_socket_.get()), *context_));
|
||||
|
||||
if (always_verify_peer_)
|
||||
socket_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
|
||||
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<void(system::error_code const &)> 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<void(system::error_code const &, size_t)> 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<void(system::error_code const &, size_t)> handler) {
|
||||
socket_->async_read_some(read_buffer, handler);
|
||||
}
|
||||
|
||||
void boost::network::http::impl::ssl_delegate::disconnect() {
|
||||
if (socket_.get() && socket_->lowest_layer().is_open()) {
|
||||
boost::system::error_code ignored;
|
||||
socket_->lowest_layer().shutdown(
|
||||
boost::asio::ip::tcp::socket::shutdown_both, ignored);
|
||||
if (!ignored) {
|
||||
socket_->lowest_layer().close(ignored);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::network::http::impl::ssl_delegate::~ssl_delegate() {}
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 \
|
||||
*/
|
|
@ -0,0 +1,302 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_SYNC_CONNECTION_BASE_20091217
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// Copyright 2009 Dean Michael Berris <dberris@google.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)
|
||||
|
||||
#include <boost/network/protocol/http/traits/resolver_policy.hpp>
|
||||
#include <boost/network/traits/ostringstream.hpp>
|
||||
#include <boost/network/traits/istringstream.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/asio/read_until.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/network/protocol/http/response.hpp>
|
||||
|
||||
#include <boost/network/protocol/http/client/connection/sync_normal.hpp>
|
||||
#ifdef BOOST_NETWORK_ENABLE_HTTPS
|
||||
#include <boost/network/protocol/http/client/connection/sync_ssl.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base_impl {
|
||||
protected:
|
||||
typedef typename resolver_policy<Tag>::type resolver_base;
|
||||
typedef typename resolver_base::resolver_type resolver_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef function<typename resolver_base::resolver_iterator_pair(
|
||||
resolver_type&, string_type const&, string_type const&)>
|
||||
resolver_function_type;
|
||||
|
||||
template <class Socket>
|
||||
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 <class Socket>
|
||||
void read_status(Socket& socket_, basic_response<Tag>& 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 <class Socket>
|
||||
void read_headers(Socket& socket_, basic_response<Tag>& 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 <class Socket>
|
||||
void send_request_impl(Socket& socket_, string_type const& method,
|
||||
boost::asio::streambuf& request_buffer) {
|
||||
// TODO(dberris): review parameter necessity.
|
||||
(void)method;
|
||||
|
||||
write(socket_, request_buffer);
|
||||
}
|
||||
|
||||
template <class Socket>
|
||||
void read_body_normal(Socket& socket_, basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer,
|
||||
typename ostringstream<Tag>::type& body_stream) {
|
||||
// TODO(dberris): review parameter necessity.
|
||||
(void)response_;
|
||||
|
||||
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 <class Socket>
|
||||
void read_body_transfer_chunk_encoding(
|
||||
Socket& socket_, basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer,
|
||||
typename ostringstream<Tag>::type& body_stream) {
|
||||
boost::system::error_code error;
|
||||
// look for the content-length header
|
||||
typename headers_range<basic_response<Tag> >::type content_length_range =
|
||||
headers(response_)["Content-Length"];
|
||||
if (boost::empty(content_length_range)) {
|
||||
typename headers_range<basic_response<Tag> >::type
|
||||
transfer_encoding_range = headers(response_)["Transfer-Encoding"];
|
||||
if (boost::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<Tag>::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 {
|
||||
if (response_buffer.size() < (chunk_size + 2)) {
|
||||
std::size_t bytes_to_read =
|
||||
(chunk_size + 2) - response_buffer.size();
|
||||
std::size_t chunk_bytes_read =
|
||||
read(socket_, response_buffer,
|
||||
boost::asio::transfer_at_least(bytes_to_read), error);
|
||||
if (chunk_bytes_read == 0) {
|
||||
if (error != boost::asio::error::eof)
|
||||
throw boost::system::system_error(error);
|
||||
stopping_inner = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::istreambuf_iterator<char> eos;
|
||||
std::istreambuf_iterator<char> 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<size_t>(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 <class Socket>
|
||||
void read_body(Socket& socket_, basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
typename ostringstream<Tag>::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 <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base {
|
||||
typedef typename resolver_policy<Tag>::type resolver_base;
|
||||
typedef typename resolver_base::resolver_type resolver_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef function<typename resolver_base::resolver_iterator_pair(
|
||||
resolver_type&, string_type const&, string_type const&)>
|
||||
resolver_function_type;
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
|
||||
// FIXME make the certificate filename and verify path parameters be
|
||||
// optional
|
||||
// ranges
|
||||
static sync_connection_base<Tag, version_major, version_minor>*
|
||||
new_connection(
|
||||
resolver_type& resolver, resolver_function_type resolve, bool https,
|
||||
bool always_verify_peer, int timeout,
|
||||
optional<string_type> const& certificate_filename =
|
||||
optional<string_type>(),
|
||||
optional<string_type> const& verify_path = optional<string_type>(),
|
||||
optional<string_type> const& certificate_file =
|
||||
optional<string_type>(),
|
||||
optional<string_type> const& private_key_file =
|
||||
optional<string_type>(),
|
||||
optional<string_type> const& ciphers = optional<string_type>(),
|
||||
long ssl_options = 0) {
|
||||
if (https) {
|
||||
#ifdef BOOST_NETWORK_ENABLE_HTTPS
|
||||
return dynamic_cast<
|
||||
sync_connection_base<Tag, version_major, version_minor>*>(
|
||||
new https_sync_connection<Tag, version_major, version_minor>(
|
||||
resolver, resolve, always_verify_peer, timeout,
|
||||
certificate_filename, verify_path, certificate_file,
|
||||
private_key_file, ciphers, ssl_options));
|
||||
#else
|
||||
throw std::runtime_error("HTTPS not supported.");
|
||||
#endif
|
||||
}
|
||||
return dynamic_cast<
|
||||
sync_connection_base<Tag, version_major, version_minor>*>(
|
||||
new http_sync_connection<Tag, version_major, version_minor>(
|
||||
resolver, resolve, timeout));
|
||||
}
|
||||
|
||||
virtual void init_socket(string_type const& hostname,
|
||||
string_type const& port) = 0;
|
||||
virtual void send_request_impl(string_type const& method,
|
||||
basic_request<Tag> const& request_,
|
||||
body_generator_function_type generator) = 0;
|
||||
virtual void read_status(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) = 0;
|
||||
virtual void read_headers(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) = 0;
|
||||
virtual void read_body(basic_response<Tag>& 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
|
|
@ -0,0 +1,134 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// 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 <boost/network/protocol/http/algorithms/linearize.hpp>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base_impl;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct http_sync_connection
|
||||
: public virtual sync_connection_base<Tag, version_major, version_minor>,
|
||||
sync_connection_base_impl<Tag, version_major, version_minor>,
|
||||
boost::enable_shared_from_this<
|
||||
http_sync_connection<Tag, version_major, version_minor> > {
|
||||
typedef typename resolver_policy<Tag>::type resolver_base;
|
||||
typedef typename resolver_base::resolver_type resolver_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef function<typename resolver_base::resolver_iterator_pair(
|
||||
resolver_type&, string_type const&, string_type const&)>
|
||||
resolver_function_type;
|
||||
typedef http_sync_connection<Tag, version_major, version_minor> this_type;
|
||||
typedef sync_connection_base_impl<Tag, version_major, version_minor>
|
||||
connection_base;
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
|
||||
http_sync_connection(resolver_type& resolver, resolver_function_type resolve,
|
||||
int timeout)
|
||||
: connection_base(),
|
||||
timeout_(timeout),
|
||||
timer_(resolver.get_io_service()),
|
||||
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<Tag> const& request_,
|
||||
body_generator_function_type generator) {
|
||||
boost::asio::streambuf request_buffer;
|
||||
linearize(
|
||||
request_, method, version_major, version_minor,
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(&request_buffer));
|
||||
connection_base::send_request_impl(socket_, method, request_buffer);
|
||||
if (generator) {
|
||||
string_type chunk;
|
||||
while (generator(chunk)) {
|
||||
std::copy(chunk.begin(), chunk.end(),
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(
|
||||
&request_buffer));
|
||||
chunk.clear();
|
||||
connection_base::send_request_impl(socket_, method, request_buffer);
|
||||
}
|
||||
}
|
||||
if (timeout_ > 0) {
|
||||
timer_.expires_from_now(boost::posix_time::seconds(timeout_));
|
||||
timer_.async_wait(boost::bind(&this_type::handle_timeout,
|
||||
this_type::shared_from_this(),
|
||||
boost::arg<1>()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_status(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_status(socket_, response_, response_buffer);
|
||||
}
|
||||
|
||||
void read_headers(basic_response<Tag>& response,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_headers(socket_, response, response_buffer);
|
||||
}
|
||||
|
||||
void read_body(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_body(socket_, response_, response_buffer);
|
||||
typename headers_range<basic_response<Tag> >::type connection_range =
|
||||
headers(response_)["Connection"];
|
||||
if (version_major == 1 && version_minor == 1 && !boost::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() {
|
||||
timer_.cancel();
|
||||
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:
|
||||
void handle_timeout(boost::system::error_code const& ec) {
|
||||
if (!ec) close_socket();
|
||||
}
|
||||
|
||||
int timeout_;
|
||||
boost::asio::deadline_timer timer_;
|
||||
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
|
|
@ -0,0 +1,184 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// Copyright 2010 (C) Dean Michael Berris <dberris@google.com>
|
||||
// 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 <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <boost/asio/ssl/context_base.hpp>
|
||||
#include <boost/asio/streambuf.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/protocol/http/request.hpp>
|
||||
#include <boost/network/protocol/http/traits/resolver_policy.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base_impl;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_connection_base;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct https_sync_connection
|
||||
: public virtual sync_connection_base<Tag, version_major, version_minor>,
|
||||
sync_connection_base_impl<Tag, version_major, version_minor>,
|
||||
boost::enable_shared_from_this<
|
||||
https_sync_connection<Tag, version_major, version_minor> > {
|
||||
typedef typename resolver_policy<Tag>::type resolver_base;
|
||||
typedef typename resolver_base::resolver_type resolver_type;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef function<typename resolver_base::resolver_iterator_pair(
|
||||
resolver_type&, string_type const&, string_type const&)>
|
||||
resolver_function_type;
|
||||
typedef https_sync_connection<Tag, version_major, version_minor> this_type;
|
||||
typedef sync_connection_base_impl<Tag, version_major, version_minor>
|
||||
connection_base;
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
|
||||
// FIXME make the certificate filename and verify path parameters be
|
||||
// optional ranges
|
||||
https_sync_connection(
|
||||
resolver_type& resolver, resolver_function_type resolve,
|
||||
bool always_verify_peer, int timeout,
|
||||
optional<string_type> const& certificate_filename =
|
||||
optional<string_type>(),
|
||||
optional<string_type> const& verify_path = optional<string_type>(),
|
||||
optional<string_type> const& certificate_file = optional<string_type>(),
|
||||
optional<string_type> const& private_key_file = optional<string_type>(),
|
||||
optional<string_type> const& ciphers = optional<string_type>(),
|
||||
long ssl_options = 0)
|
||||
: connection_base(),
|
||||
timeout_(timeout),
|
||||
timer_(resolver.get_io_service()),
|
||||
resolver_(resolver),
|
||||
resolve_(resolve),
|
||||
context_(resolver.get_io_service(),
|
||||
boost::asio::ssl::context::sslv23_client),
|
||||
socket_(resolver.get_io_service(), context_) {
|
||||
if (ciphers) {
|
||||
::SSL_CTX_set_cipher_list(context_.native_handle(), ciphers->c_str());
|
||||
}
|
||||
if (ssl_options != 0) {
|
||||
context_.set_options(ssl_options);
|
||||
}
|
||||
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 {
|
||||
if (always_verify_peer)
|
||||
context_.set_verify_mode(boost::asio::ssl::context_base::verify_peer);
|
||||
else
|
||||
context_.set_verify_mode(boost::asio::ssl::context_base::verify_none);
|
||||
}
|
||||
if (certificate_file)
|
||||
context_.use_certificate_file(*certificate_file,
|
||||
boost::asio::ssl::context::pem);
|
||||
if (private_key_file)
|
||||
context_.use_private_key_file(*private_key_file,
|
||||
boost::asio::ssl::context::pem);
|
||||
}
|
||||
|
||||
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<Tag> const& request_,
|
||||
body_generator_function_type generator) {
|
||||
boost::asio::streambuf request_buffer;
|
||||
linearize(
|
||||
request_, method, version_major, version_minor,
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(&request_buffer));
|
||||
connection_base::send_request_impl(socket_, method, request_buffer);
|
||||
if (generator) {
|
||||
string_type chunk;
|
||||
while (generator(chunk)) {
|
||||
std::copy(chunk.begin(), chunk.end(),
|
||||
std::ostreambuf_iterator<typename char_<Tag>::type>(
|
||||
&request_buffer));
|
||||
chunk.clear();
|
||||
connection_base::send_request_impl(socket_, method, request_buffer);
|
||||
}
|
||||
}
|
||||
if (timeout_ > 0) {
|
||||
timer_.expires_from_now(boost::posix_time::seconds(timeout_));
|
||||
timer_.async_wait(boost::bind(&this_type::handle_timeout,
|
||||
this_type::shared_from_this(),
|
||||
boost::arg<1>()));
|
||||
}
|
||||
}
|
||||
|
||||
void read_status(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_status(socket_, response_, response_buffer);
|
||||
}
|
||||
|
||||
void read_headers(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_headers(socket_, response_, response_buffer);
|
||||
}
|
||||
|
||||
void read_body(basic_response<Tag>& response_,
|
||||
boost::asio::streambuf& response_buffer) {
|
||||
connection_base::read_body(socket_, response_, response_buffer);
|
||||
typename headers_range<basic_response<Tag> >::type connection_range =
|
||||
headers(response_)["Connection"];
|
||||
if (version_major == 1 && version_minor == 1 && !boost::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() {
|
||||
timer_.cancel();
|
||||
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:
|
||||
void handle_timeout(boost::system::error_code const& ec) {
|
||||
if (!ec) close_socket();
|
||||
}
|
||||
|
||||
int timeout_;
|
||||
boost::asio::deadline_timer timer_;
|
||||
resolver_type& resolver_;
|
||||
resolver_function_type resolve_;
|
||||
boost::asio::ssl::context context_;
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
} // namespace http
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601
|
174
cpp-netlib/boost/network/protocol/http/client/facade.hpp
Normal file
174
cpp-netlib/boost/network/protocol/http/client/facade.hpp
Normal file
|
@ -0,0 +1,174 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// Copyright 2010 Dean Michael Berris <dberris@google.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)
|
||||
|
||||
#include <boost/network/protocol/http/request.hpp>
|
||||
#include <boost/network/protocol/http/response.hpp>
|
||||
#include <boost/network/protocol/http/client/pimpl.hpp>
|
||||
#include <boost/network/protocol/http/client/options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client_facade {
|
||||
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef basic_request<Tag> request;
|
||||
typedef basic_response<Tag> response;
|
||||
typedef basic_client_impl<Tag, version_major, version_minor> pimpl_type;
|
||||
typedef function<void(iterator_range<char const*> const&,
|
||||
system::error_code const&)> body_callback_function_type;
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
|
||||
explicit basic_client_facade(client_options<Tag> const& options) {
|
||||
init_pimpl(options);
|
||||
}
|
||||
|
||||
~basic_client_facade() { pimpl->wait_complete(); }
|
||||
|
||||
response head(request const& request) {
|
||||
return pimpl->request_skeleton(request, "HEAD", false,
|
||||
body_callback_function_type(),
|
||||
body_generator_function_type());
|
||||
}
|
||||
|
||||
response get(request const& request,
|
||||
body_callback_function_type body_handler =
|
||||
body_callback_function_type()) {
|
||||
return pimpl->request_skeleton(request, "GET", true, body_handler,
|
||||
body_generator_function_type());
|
||||
}
|
||||
|
||||
response post(request request, string_type const& body = string_type(),
|
||||
string_type const& content_type = string_type(),
|
||||
body_callback_function_type body_handler =
|
||||
body_callback_function_type(),
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
if (body != string_type()) {
|
||||
request << remove_header("Content-Length")
|
||||
<< header("Content-Length",
|
||||
boost::lexical_cast<string_type>(body.size()))
|
||||
<< boost::network::body(body);
|
||||
}
|
||||
typename headers_range<basic_request<Tag> >::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_<Tag>::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,
|
||||
body_generator);
|
||||
}
|
||||
|
||||
response post(request const& request,
|
||||
body_generator_function_type body_generator,
|
||||
body_callback_function_type callback =
|
||||
body_generator_function_type()) {
|
||||
return pimpl->request_skeleton(request, "POST", true, callback,
|
||||
body_generator);
|
||||
}
|
||||
|
||||
response post(request const& request, body_callback_function_type callback,
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
return post(request, string_type(), string_type(), callback,
|
||||
body_generator);
|
||||
}
|
||||
|
||||
response post(request const& request, string_type const& body,
|
||||
body_callback_function_type callback,
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
return post(request, body, string_type(), callback, body_generator);
|
||||
}
|
||||
|
||||
response put(request request, string_type const& body = string_type(),
|
||||
string_type const& content_type = string_type(),
|
||||
body_callback_function_type body_handler =
|
||||
body_callback_function_type(),
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
if (body != string_type()) {
|
||||
request << remove_header("Content-Length")
|
||||
<< header("Content-Length",
|
||||
boost::lexical_cast<string_type>(body.size()))
|
||||
<< boost::network::body(body);
|
||||
}
|
||||
typename headers_range<basic_request<Tag> >::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_<Tag>::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,
|
||||
body_generator);
|
||||
}
|
||||
|
||||
response put(request const& request, body_callback_function_type callback,
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
return put(request, string_type(), string_type(), callback, body_generator);
|
||||
}
|
||||
|
||||
response put(request const& request, string_type body,
|
||||
body_callback_function_type callback,
|
||||
body_generator_function_type body_generator =
|
||||
body_generator_function_type()) {
|
||||
return put(request, body, string_type(), callback, body_generator);
|
||||
}
|
||||
|
||||
response delete_(request const& request,
|
||||
body_callback_function_type body_handler =
|
||||
body_callback_function_type()) {
|
||||
return pimpl->request_skeleton(request, "DELETE", true, body_handler,
|
||||
body_generator_function_type());
|
||||
}
|
||||
|
||||
void clear_resolved_cache() { pimpl->clear_resolved_cache(); }
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<pimpl_type> pimpl;
|
||||
|
||||
void init_pimpl(client_options<Tag> const& options) {
|
||||
pimpl.reset(new pimpl_type(
|
||||
options.cache_resolved(), options.follow_redirects(),
|
||||
options.always_verify_peer(), options.openssl_certificate(),
|
||||
options.openssl_verify_path(), options.openssl_certificate_file(),
|
||||
options.openssl_private_key_file(), options.openssl_ciphers(),
|
||||
options.openssl_options(), options.io_service(), options.timeout()));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
|
19
cpp-netlib/boost/network/protocol/http/client/macros.hpp
Normal file
19
cpp-netlib/boost/network/protocol/http/client/macros.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430
|
||||
|
||||
// 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)
|
||||
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#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 char*> const& range_name, \
|
||||
boost::system::error_code const& error_name)
|
||||
#endif
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */
|
181
cpp-netlib/boost/network/protocol/http/client/options.hpp
Normal file
181
cpp-netlib/boost/network/protocol/http/client/options.hpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128
|
||||
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// Copyright 2013 Dean Michael Berris <dberris@google.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)
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct client_options {
|
||||
typedef typename string<Tag>::type string_type;
|
||||
|
||||
client_options()
|
||||
: cache_resolved_(false),
|
||||
follow_redirects_(false),
|
||||
openssl_certificate_(),
|
||||
openssl_verify_path_(),
|
||||
openssl_certificate_file_(),
|
||||
openssl_private_key_file_(),
|
||||
openssl_ciphers_(),
|
||||
openssl_options_(0),
|
||||
io_service_(),
|
||||
always_verify_peer_(false),
|
||||
timeout_(0) {}
|
||||
|
||||
client_options(client_options const& other)
|
||||
: cache_resolved_(other.cache_resolved_),
|
||||
follow_redirects_(other.follow_redirects_),
|
||||
openssl_certificate_(other.openssl_certificate_),
|
||||
openssl_verify_path_(other.openssl_verify_path_),
|
||||
openssl_certificate_file_(other.openssl_certificate_file_),
|
||||
openssl_private_key_file_(other.openssl_private_key_file_),
|
||||
openssl_ciphers_(other.openssl_ciphers_),
|
||||
openssl_options_(other.openssl_options_),
|
||||
io_service_(other.io_service_),
|
||||
always_verify_peer_(other.always_verify_peer_),
|
||||
timeout_(other.timeout_) {}
|
||||
|
||||
client_options& operator=(client_options other) {
|
||||
other.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(client_options& other) {
|
||||
using std::swap;
|
||||
swap(cache_resolved_, other.cache_resolved_);
|
||||
swap(follow_redirects_, other.follow_redirects_);
|
||||
swap(openssl_certificate_, other.openssl_certificate_);
|
||||
swap(openssl_verify_path_, other.openssl_verify_path_);
|
||||
swap(openssl_certificate_file_, other.openssl_certificate_file_);
|
||||
swap(openssl_private_key_file_, other.openssl_private_key_file_);
|
||||
swap(openssl_ciphers_, other.openssl_ciphers_);
|
||||
swap(openssl_options_, other.openssl_options_);
|
||||
swap(io_service_, other.io_service_);
|
||||
swap(always_verify_peer_, other.always_verify_peer_);
|
||||
swap(timeout_, other.timeout_);
|
||||
}
|
||||
|
||||
client_options& cache_resolved(bool v) {
|
||||
cache_resolved_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& follow_redirects(bool v) {
|
||||
follow_redirects_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_certificate(string_type const& v) {
|
||||
openssl_certificate_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_verify_path(string_type const& v) {
|
||||
openssl_verify_path_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_certificate_file(string_type const& v) {
|
||||
openssl_certificate_file_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_private_key_file(string_type const& v) {
|
||||
openssl_private_key_file_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_ciphers(string_type const& v) {
|
||||
openssl_ciphers_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& openssl_options(long o) {
|
||||
openssl_options_ = o;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& io_service(boost::shared_ptr<boost::asio::io_service> v) {
|
||||
io_service_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& always_verify_peer(bool v) {
|
||||
always_verify_peer_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
client_options& timeout(int v) {
|
||||
timeout_ = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool cache_resolved() const { return cache_resolved_; }
|
||||
|
||||
bool follow_redirects() const { return follow_redirects_; }
|
||||
|
||||
boost::optional<string_type> openssl_certificate() const {
|
||||
return openssl_certificate_;
|
||||
}
|
||||
|
||||
boost::optional<string_type> openssl_verify_path() const {
|
||||
return openssl_verify_path_;
|
||||
}
|
||||
|
||||
boost::optional<string_type> openssl_certificate_file() const {
|
||||
return openssl_certificate_file_;
|
||||
}
|
||||
|
||||
boost::optional<string_type> openssl_private_key_file() const {
|
||||
return openssl_private_key_file_;
|
||||
}
|
||||
|
||||
boost::optional<string_type> openssl_ciphers() const {
|
||||
return openssl_ciphers_;
|
||||
}
|
||||
|
||||
long openssl_options() const { return openssl_options_; }
|
||||
|
||||
boost::shared_ptr<boost::asio::io_service> io_service() const {
|
||||
return io_service_;
|
||||
}
|
||||
|
||||
bool always_verify_peer() const { return always_verify_peer_; }
|
||||
|
||||
int timeout() const { return timeout_; }
|
||||
|
||||
private:
|
||||
bool cache_resolved_;
|
||||
bool follow_redirects_;
|
||||
boost::optional<string_type> openssl_certificate_;
|
||||
boost::optional<string_type> openssl_verify_path_;
|
||||
boost::optional<string_type> openssl_certificate_file_;
|
||||
boost::optional<string_type> openssl_private_key_file_;
|
||||
boost::optional<string_type> openssl_ciphers_;
|
||||
long openssl_options_;
|
||||
boost::shared_ptr<boost::asio::io_service> io_service_;
|
||||
bool always_verify_peer_;
|
||||
int timeout_;
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
inline void swap(client_options<Tag>& a, client_options<Tag>& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} /* http */
|
||||
} /* network */
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_OPTIONS_HPP_20130128 */
|
90
cpp-netlib/boost/network/protocol/http/client/pimpl.hpp
Normal file
90
cpp-netlib/boost/network/protocol/http/client/pimpl.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/network/protocol/http/traits/connection_policy.hpp>
|
||||
#include <boost/network/protocol/http/client/async_impl.hpp>
|
||||
#include <boost/network/protocol/http/client/sync_impl.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client_impl;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct async_client;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_client;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor,
|
||||
class Enable = void>
|
||||
struct client_base {
|
||||
typedef unsupported_tag<Tag> type;
|
||||
};
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct client_base<Tag, version_major, version_minor,
|
||||
typename enable_if<is_async<Tag> >::type> {
|
||||
typedef async_client<Tag, version_major, version_minor> type;
|
||||
};
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct client_base<Tag, version_major, version_minor,
|
||||
typename enable_if<is_sync<Tag> >::type> {
|
||||
typedef sync_client<Tag, version_major, version_minor> type;
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client;
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client_impl
|
||||
: impl::client_base<Tag, version_major, version_minor>::type {
|
||||
BOOST_STATIC_ASSERT(
|
||||
(mpl::not_<mpl::and_<is_async<Tag>, is_sync<Tag> > >::value));
|
||||
|
||||
typedef typename impl::client_base<Tag, version_major, version_minor>::type
|
||||
base_type;
|
||||
typedef typename base_type::string_type string_type;
|
||||
|
||||
basic_client_impl(bool cache_resolved, bool follow_redirect,
|
||||
bool always_verify_peer,
|
||||
optional<string_type> const& certificate_filename,
|
||||
optional<string_type> const& verify_path,
|
||||
optional<string_type> const& certificate_file,
|
||||
optional<string_type> const& private_key_file,
|
||||
optional<string_type> const& ciphers, long ssl_options,
|
||||
boost::shared_ptr<boost::asio::io_service> service,
|
||||
int timeout)
|
||||
: base_type(cache_resolved, follow_redirect, always_verify_peer, timeout,
|
||||
service, certificate_filename, verify_path, certificate_file,
|
||||
private_key_file, ciphers, ssl_options) {}
|
||||
|
||||
~basic_client_impl() {}
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623
|
99
cpp-netlib/boost/network/protocol/http/client/sync_impl.hpp
Normal file
99
cpp-netlib/boost/network/protocol/http/client/sync_impl.hpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623
|
||||
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/protocol/http/tags.hpp>
|
||||
#include <boost/network/protocol/http/traits/vector.hpp>
|
||||
#include <boost/network/protocol/http/request.hpp>
|
||||
#include <boost/network/protocol/http/traits/connection_policy.hpp>
|
||||
|
||||
// Copyright 2013 Google, Inc.
|
||||
// Copyright 2010 Dean Michael Berris <dberris@google.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)
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct basic_client_impl;
|
||||
|
||||
namespace impl {
|
||||
template <class Tag, unsigned version_major, unsigned version_minor>
|
||||
struct sync_client
|
||||
: connection_policy<Tag, version_major, version_minor>::type {
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef typename connection_policy<Tag, version_major, version_minor>::type
|
||||
connection_base;
|
||||
typedef typename resolver<Tag>::type resolver_type;
|
||||
typedef function<void(iterator_range<char const*> const&,
|
||||
system::error_code const&)> body_callback_function_type;
|
||||
typedef function<bool(string_type&)> body_generator_function_type;
|
||||
friend struct basic_client_impl<Tag, version_major, version_minor>;
|
||||
|
||||
boost::shared_ptr<boost::asio::io_service> service_ptr;
|
||||
boost::asio::io_service& service_;
|
||||
resolver_type resolver_;
|
||||
optional<string_type> certificate_filename_;
|
||||
optional<string_type> verify_path_;
|
||||
optional<string_type> certificate_file_;
|
||||
optional<string_type> private_key_file_;
|
||||
optional<string_type> ciphers_;
|
||||
long ssl_options_;
|
||||
bool always_verify_peer_;
|
||||
|
||||
sync_client(
|
||||
bool cache_resolved, bool follow_redirect, bool always_verify_peer,
|
||||
int timeout, boost::shared_ptr<boost::asio::io_service> service,
|
||||
optional<string_type> const& certificate_filename =
|
||||
optional<string_type>(),
|
||||
optional<string_type> const& verify_path = optional<string_type>(),
|
||||
optional<string_type> const& certificate_file = optional<string_type>(),
|
||||
optional<string_type> const& private_key_file = optional<string_type>(),
|
||||
optional<string_type> const& ciphers = optional<string_type>(),
|
||||
long ssl_options = 0)
|
||||
: connection_base(cache_resolved, follow_redirect, timeout),
|
||||
service_ptr(service.get() ? service
|
||||
: make_shared<boost::asio::io_service>()),
|
||||
service_(*service_ptr),
|
||||
resolver_(service_),
|
||||
certificate_filename_(certificate_filename),
|
||||
verify_path_(verify_path),
|
||||
certificate_file_(certificate_file),
|
||||
private_key_file_(private_key_file),
|
||||
ciphers_(ciphers),
|
||||
ssl_options_(ssl_options),
|
||||
always_verify_peer_(always_verify_peer) {}
|
||||
|
||||
~sync_client() {
|
||||
connection_base::cleanup();
|
||||
service_ptr.reset();
|
||||
}
|
||||
|
||||
void wait_complete() {}
|
||||
|
||||
basic_response<Tag> request_skeleton(basic_request<Tag> const& request_,
|
||||
string_type method, bool get_body,
|
||||
body_callback_function_type callback,
|
||||
body_generator_function_type generator) {
|
||||
typename connection_base::connection_ptr connection_;
|
||||
connection_ = connection_base::get_connection(
|
||||
resolver_, request_, always_verify_peer_, certificate_filename_,
|
||||
verify_path_, certificate_file_, private_key_file_, ciphers_);
|
||||
return connection_->send_request(method, request_, get_body, callback,
|
||||
generator);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
} // namespace http
|
||||
} // namespace network
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_SYNC_IMPL_HPP_20100623
|
31
cpp-netlib/boost/network/protocol/http/errors.hpp
Normal file
31
cpp-netlib/boost/network/protocol/http/errors.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
|
||||
// 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 <boost/network/protocol/http/message.hpp>
|
||||
#include <exception>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
namespace errors {
|
||||
|
||||
template <class Tag = tags::http_default_8bit_tcp_resolve>
|
||||
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__
|
299
cpp-netlib/boost/network/protocol/http/impl/message.ipp
Normal file
299
cpp-netlib/boost/network/protocol/http/impl/message.ipp
Normal file
|
@ -0,0 +1,299 @@
|
|||
// 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 <boost/network/protocol/http/message.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
// static member functions of boost::network::http::message
|
||||
|
||||
template <typename Tag>
|
||||
typename message_impl<Tag>::string_type const message_impl<Tag>::url_decode(
|
||||
typename message_impl<Tag>::string_type const &str) {
|
||||
char decode_buf[3];
|
||||
typename message_impl<Tag>::string_type result;
|
||||
result.reserve(str.size());
|
||||
|
||||
for (typename message_impl<Tag>::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<char>(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 Tag>
|
||||
typename message_impl<Tag>::string_type const message_impl<Tag>::url_encode(
|
||||
typename message_impl<Tag>::string_type const &str) {
|
||||
char encode_buf[4];
|
||||
typename message_impl<Tag>::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<Tag>::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 Tag>
|
||||
typename message_impl<Tag>::string_type const
|
||||
message_impl<Tag>::make_query_string(
|
||||
typename query_container<Tag>::type const &query_params) {
|
||||
typename message_impl<Tag>::string_type query_string;
|
||||
for (typename query_container<Tag>::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 Tag>
|
||||
typename message_impl<Tag>::string_type const
|
||||
message_impl<Tag>::make_set_cookie_header(
|
||||
typename message_impl<Tag>::string_type const &name,
|
||||
typename message_impl<Tag>::string_type const &value,
|
||||
typename message_impl<Tag>::string_type const &path, bool const has_max_age,
|
||||
unsigned long const max_age) {
|
||||
typename message_impl<Tag>::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<message_impl<Tag>::string_type>(max_age);
|
||||
set_cookie_header += '\"';
|
||||
}
|
||||
return set_cookie_header;
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
bool message_impl<Tag>::base64_decode(
|
||||
const typename message_impl<Tag>::string_type &input,
|
||||
typename message_impl<Tag>::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_length; i++) {
|
||||
char base64code0;
|
||||
char base64code1;
|
||||
char base64code2 = 0; // initialized to 0 to suppress warnings
|
||||
char base64code3;
|
||||
|
||||
base64code0 = decoding_data[static_cast<int>(input_ptr[i])];
|
||||
if (base64code0 == nop) // non base64 character
|
||||
return false;
|
||||
if (!(++i < input_length)) // we need at least two input bytes for
|
||||
// first byte output
|
||||
return false;
|
||||
base64code1 = decoding_data[static_cast<int>(input_ptr[i])];
|
||||
if (base64code1 == nop) // non base64 character
|
||||
return false;
|
||||
|
||||
output += ((base64code0 << 2) | ((base64code1 >> 4) & 0x3));
|
||||
|
||||
if (++i < input_length) {
|
||||
char c = input_ptr[i];
|
||||
if (c == '=') { // padding , end of input
|
||||
BOOST_ASSERT((base64code1 & 0x0f) == 0);
|
||||
return true;
|
||||
}
|
||||
base64code2 = decoding_data[static_cast<int>(input_ptr[i])];
|
||||
if (base64code2 == nop) // non base64 character
|
||||
return false;
|
||||
|
||||
output += ((base64code1 << 4) & 0xf0) | ((base64code2 >> 2) & 0x0f);
|
||||
}
|
||||
|
||||
if (++i < input_length) {
|
||||
char c = input_ptr[i];
|
||||
if (c == '=') { // padding , end of input
|
||||
BOOST_ASSERT((base64code2 & 0x03) == 0);
|
||||
return true;
|
||||
}
|
||||
base64code3 = decoding_data[static_cast<int>(input_ptr[i])];
|
||||
if (base64code3 == nop) // non base64 character
|
||||
return false;
|
||||
|
||||
output += (((base64code2 << 6) & 0xc0) | base64code3);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
bool message_impl<Tag>::base64_encode(
|
||||
typename message_impl<Tag>::string_type const &input,
|
||||
typename message_impl<Tag>::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 < input_length; i++) {
|
||||
int base64code0 = 0;
|
||||
int base64code1 = 0;
|
||||
int base64code2 = 0;
|
||||
int base64code3 = 0;
|
||||
|
||||
base64code0 = (input_ptr[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
|
807
cpp-netlib/boost/network/protocol/http/impl/parser.ipp
Normal file
807
cpp-netlib/boost/network/protocol/http/impl/parser.ipp
Normal file
|
@ -0,0 +1,807 @@
|
|||
// 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 <boost/network/protocol/http/parser.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
// member functions for class basic_parser<Tag,Traits>
|
||||
|
||||
template <typename Tag, typename ParserTraits>
|
||||
boost::tribool basic_parser<Tag, Traits>::parse_http_headers(
|
||||
basic_message<Tag>& 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 <typename Tag, typename ParserTraits>
|
||||
boost::tribool basic_parser<Tag, Traits>::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 <typename Tag, typename ParserTraits>
|
||||
std::size_t basic_parser<Tag, Traits>::consume_content(
|
||||
basic_message<Tag>& 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 <typename Tag, typename ParserTraits>
|
||||
std::size_t basic_parser<Tag, Traits>::consume_content_as_next_chunk(
|
||||
types::chunk_cache_t& chunk_buffers) {
|
||||
if (bytes_available() == 0) {
|
||||
m_bytes_last_read = 0;
|
||||
} else {
|
||||
std::vector<char> 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 <typename Tag, typename ParserTraits>
|
||||
void basic_parser<Tag, Traits>::finish(basic_request<Tag>& 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<types::headers::const_iterator, types::headers::const_iterator>
|
||||
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 <typename Tag, typename ParserTraits>
|
||||
void basic_parser<Tag, Traits>::finish(basic_response<Tag>& http_response) {
|
||||
http_response.setIsValid(true);
|
||||
http_response.setStatusCode(m_status_code);
|
||||
http_response.setStatusMessage(m_status_message);
|
||||
}
|
||||
|
||||
template <typename Tag, typename ParserTraits>
|
||||
inline void basic_parser<Tag, Traits>::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 <typename Tag, typename ParserTraits>
|
||||
static bool basic_parser<Tag, Traits>::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 <typename Tag, typename ParserTraits>
|
||||
static bool basic_parser<Tag, Traits>::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
|
231
cpp-netlib/boost/network/protocol/http/impl/request.hpp
Normal file
231
cpp-netlib/boost/network/protocol/http/impl/request.hpp
Normal file
|
@ -0,0 +1,231 @@
|
|||
|
||||
// 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 <boost/network/protocol/http/message.hpp>
|
||||
#include <boost/network/protocol/http/message/header.hpp>
|
||||
|
||||
#include <boost/fusion/container/map.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/at_key.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic/value_at_key.hpp>
|
||||
|
||||
#include <boost/network/uri/uri.hpp>
|
||||
#include <boost/network/traits/vector.hpp>
|
||||
#include <boost/network/constants.hpp>
|
||||
|
||||
#include <boost/network/protocol/http/message/async_message.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/protocol/http/support/sync_only.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
|
||||
/** Specialize the traits for the http_server tag. */
|
||||
template <>
|
||||
struct headers_container<
|
||||
http::tags::http_server> : vector<http::tags::http_server>::
|
||||
apply<http::request_header<
|
||||
http::tags::http_server>::type> {};
|
||||
|
||||
template <>
|
||||
struct headers_container<
|
||||
http::tags::
|
||||
http_async_server> : vector<http::tags::http_async_server>::
|
||||
apply<http::request_header<
|
||||
http::tags::http_async_server>::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 <class Tag>
|
||||
struct basic_request : public basic_message<Tag> {
|
||||
|
||||
mutable boost::network::uri::uri uri_;
|
||||
boost::uint16_t source_port_;
|
||||
typedef basic_message<Tag> base_type;
|
||||
|
||||
public:
|
||||
typedef typename sync_only<Tag>::type tag;
|
||||
typedef typename string<tag>::type string_type;
|
||||
typedef boost::uint16_t port_type;
|
||||
|
||||
explicit basic_request(string_type const& uri_) : uri_(uri_), source_port_(0) {}
|
||||
|
||||
explicit basic_request(boost::network::uri::uri const& uri_) : uri_(uri_), source_port_(0) {}
|
||||
|
||||
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(), source_port_(0) {}
|
||||
|
||||
basic_request(basic_request const& other)
|
||||
: base_type(other), uri_(other.uri_), source_port_(other.source_port_) {}
|
||||
|
||||
basic_request& operator=(basic_request rhs) {
|
||||
rhs.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(basic_request& other) {
|
||||
base_type& base_ref(other);
|
||||
basic_request<Tag>& this_ref(*this);
|
||||
base_ref.swap(this_ref);
|
||||
boost::swap(other.uri_, this->uri_);
|
||||
boost::swap(other.source_port_, this->source_port_);
|
||||
}
|
||||
|
||||
string_type const host() const { return uri_.host(); }
|
||||
|
||||
port_type port() const {
|
||||
boost::optional<port_type> port = uri::port_us(uri_);
|
||||
if (!port) {
|
||||
typedef constants<Tag> 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_; }
|
||||
|
||||
void source_port(const boost::uint16_t port) { source_port_ = port; }
|
||||
|
||||
boost::uint16_t source_port() const { return source_port_; }
|
||||
};
|
||||
|
||||
/** 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 <class Tag>
|
||||
struct not_quite_pod_request_base {
|
||||
typedef Tag tag;
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef typename request_header<Tag>::type header_type;
|
||||
typedef typename vector<Tag>::template apply<header_type>::type vector_type;
|
||||
typedef vector_type headers_container_type;
|
||||
typedef boost::uint16_t port_type;
|
||||
mutable string_type source;
|
||||
mutable port_type source_port;
|
||||
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(source_port, r.source_port);
|
||||
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<tags::http_async_server> : not_quite_pod_request_base<
|
||||
tags::http_async_server> {};
|
||||
|
||||
template <>
|
||||
struct basic_request<tags::http_server> : not_quite_pod_request_base<
|
||||
tags::http_server> {};
|
||||
|
||||
template <class R>
|
||||
struct ServerRequest;
|
||||
|
||||
BOOST_CONCEPT_ASSERT((ServerRequest<basic_request<tags::http_async_server> >));
|
||||
BOOST_CONCEPT_ASSERT((ServerRequest<basic_request<tags::http_server> >));
|
||||
|
||||
template <class Tag>
|
||||
inline void swap(basic_request<Tag>& lhs, basic_request<Tag>& rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
namespace http {
|
||||
namespace impl {
|
||||
|
||||
template <>
|
||||
struct request_headers_wrapper<tags::http_server> {
|
||||
basic_request<tags::http_server> const& request_;
|
||||
request_headers_wrapper(basic_request<tags::http_server> const& request_)
|
||||
: request_(request_) {}
|
||||
typedef headers_container<tags::http_server>::type headers_container_type;
|
||||
operator headers_container_type() { return request_.headers; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct body_wrapper<basic_request<tags::http_server> > {
|
||||
typedef string<tags::http_server>::type string_type;
|
||||
basic_request<tags::http_server> const& request_;
|
||||
body_wrapper(basic_request<tags::http_server> const& request_)
|
||||
: request_(request_) {}
|
||||
operator string_type() { return request_.body; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct request_headers_wrapper<tags::http_async_server> {
|
||||
basic_request<tags::http_async_server> const& request_;
|
||||
request_headers_wrapper(
|
||||
basic_request<tags::http_async_server> const& request_)
|
||||
: request_(request_) {}
|
||||
typedef headers_container<tags::http_async_server>::type
|
||||
headers_container_type;
|
||||
operator headers_container_type() { return request_.headers; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct body_wrapper<basic_request<tags::http_async_server> > {
|
||||
typedef string<tags::http_async_server>::type string_type;
|
||||
basic_request<tags::http_async_server> const& request_;
|
||||
body_wrapper(basic_request<tags::http_async_server> 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__
|
262
cpp-netlib/boost/network/protocol/http/impl/request_parser.ipp
Normal file
262
cpp-netlib/boost/network/protocol/http/impl/request_parser.ipp
Normal file
|
@ -0,0 +1,262 @@
|
|||
//
|
||||
// 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 <boost/network/protocol/http/request.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
boost::tribool basic_request_parser<Tag>::consume(basic_request<Tag>& 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<Tag>::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 <class Tag>
|
||||
bool basic_request_parser<Tag>::is_char(int c) {
|
||||
return c >= 0 && c <= 127;
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
bool basic_request_parser<Tag>::is_ctl(int c) {
|
||||
return (c >= 0 && c <= 31) || (c == 127);
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
bool basic_request_parser<Tag>::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 <class Tag>
|
||||
bool basic_request_parser<Tag>::is_digit(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_HTTP_REQUEST_PARSER_IPP
|
522
cpp-netlib/boost/network/protocol/http/impl/response.ipp
Normal file
522
cpp-netlib/boost/network/protocol/http/impl/response.ipp
Normal file
|
@ -0,0 +1,522 @@
|
|||
//
|
||||
// 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.
|
||||
// Copyright (c) 2014 Jussi Lyytinen (jussi@lyytinen.org)
|
||||
//
|
||||
// Distributed under the 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 <boost/asio/buffer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/network/protocol/http/tags.hpp>
|
||||
#include <boost/network/traits/string.hpp>
|
||||
#include <boost/network/protocol/http/traits/vector.hpp>
|
||||
#include <boost/network/protocol/http/message/header.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
/// A reply to be sent to a client.
|
||||
template <>
|
||||
struct basic_response<tags::http_server> {
|
||||
typedef tags::http_server tag;
|
||||
typedef response_header<tags::http_server>::type header_type;
|
||||
|
||||
/*! The status of the reply. Represent all the status codes of HTTP v1.1
|
||||
* from http://tools.ietf.org/html/rfc2616#page-39 and
|
||||
* http://tools.ietf.org/html/rfc6585
|
||||
*/
|
||||
enum status_type {
|
||||
continue_http = 100,
|
||||
switching_protocols = 101,
|
||||
ok = 200,
|
||||
created = 201,
|
||||
accepted = 202,
|
||||
non_authoritative_information = 203,
|
||||
no_content = 204,
|
||||
reset_content = 205,
|
||||
partial_content = 206,
|
||||
multiple_choices = 300,
|
||||
moved_permanently = 301,
|
||||
moved_temporarily = 302, ///< \deprecated Not HTTP standard
|
||||
found = 302,
|
||||
see_other = 303,
|
||||
not_modified = 304,
|
||||
use_proxy = 305,
|
||||
temporary_redirect = 307,
|
||||
bad_request = 400,
|
||||
unauthorized = 401,
|
||||
payment_required = 402,
|
||||
forbidden = 403,
|
||||
not_found = 404,
|
||||
not_supported = 405, ///< \deprecated Not HTTP standard
|
||||
method_not_allowed = 405,
|
||||
not_acceptable = 406,
|
||||
proxy_authentication_required = 407,
|
||||
request_timeout = 408,
|
||||
conflict = 409,
|
||||
gone = 410,
|
||||
length_required = 411,
|
||||
precondition_failed = 412,
|
||||
request_entity_too_large = 413,
|
||||
request_uri_too_large = 414,
|
||||
unsupported_media_type = 415,
|
||||
unsatisfiable_range = 416, ///< \deprecated Not HTTP standard
|
||||
requested_range_not_satisfiable = 416,
|
||||
expectation_failed = 417,
|
||||
precondition_required = 428,
|
||||
too_many_requests = 429,
|
||||
request_header_fields_too_large = 431,
|
||||
internal_server_error = 500,
|
||||
not_implemented = 501,
|
||||
bad_gateway = 502,
|
||||
service_unavailable = 503,
|
||||
gateway_timeout = 504,
|
||||
http_version_not_supported = 505,
|
||||
space_unavailable = 507,
|
||||
network_authentication_required = 511
|
||||
} status;
|
||||
|
||||
/// The headers to be included in the reply.
|
||||
typedef vector<tags::http_server>::apply<header_type>::type headers_vector;
|
||||
headers_vector headers;
|
||||
|
||||
/// The content to be sent in the reply.
|
||||
typedef string<tags::http_server>::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<boost::asio::const_buffer> 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<const_buffer> 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<tags::http_server> stock_reply(status_type status) {
|
||||
return stock_reply(status, to_string(status));
|
||||
}
|
||||
|
||||
/// Get a stock reply with custom plain text data.
|
||||
static basic_response<tags::http_server> stock_reply(status_type status,
|
||||
string_type content) {
|
||||
using boost::lexical_cast;
|
||||
basic_response<tags::http_server> rep;
|
||||
rep.status = status;
|
||||
rep.content = content;
|
||||
rep.headers.resize(2);
|
||||
rep.headers[0].name = "Content-Length";
|
||||
rep.headers[0].value = lexical_cast<string_type>(rep.content.size());
|
||||
rep.headers[1].name = "Content-Type";
|
||||
rep.headers[1].value = "text/html";
|
||||
return rep;
|
||||
}
|
||||
|
||||
/// Swap response objects
|
||||
void swap(basic_response<tags::http_server> &r) {
|
||||
using std::swap;
|
||||
swap(headers, r.headers);
|
||||
swap(content, r.content);
|
||||
}
|
||||
|
||||
private:
|
||||
static string_type to_string(status_type status) {
|
||||
switch (status) {
|
||||
// 2xx Success
|
||||
case basic_response<tags::http_server>::ok:
|
||||
return "";
|
||||
case basic_response<tags::http_server>::created:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Created</title></head>"
|
||||
"<body><h1>201 Created</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::accepted:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Accepted</title></head>"
|
||||
"<body><h1>202 Accepted</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::non_authoritative_information:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Non-Authoritative Information</title></head>"
|
||||
"<body><h1>203 Non-Authoritative Information</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::no_content:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>No Content</title></head>"
|
||||
"<body><h1>204 Content</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::reset_content:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Reset Content</title></head>"
|
||||
"<body><h1>205 Reset Content</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::partial_content:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Partial Content</title></head>"
|
||||
"<body><h1>206 Partial Content</h1></body>"
|
||||
"</html>";
|
||||
|
||||
// 3xx Redirection
|
||||
case basic_response<tags::http_server>::multiple_choices:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Multiple Choices</title></head>"
|
||||
"<body><h1>300 Multiple Choices</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::moved_permanently:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Moved Permanently</title></head>"
|
||||
"<body><h1>301 Moved Permanently</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::moved_temporarily:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Moved Temporarily</title></head>"
|
||||
"<body><h1>302 Moved Temporarily</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::see_other:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>See Other</title></head>"
|
||||
"<body><h1>303 See Other</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::not_modified:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Not Modified</title></head>"
|
||||
"<body><h1>304 Not Modified</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::use_proxy:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Use Proxy</title></head>"
|
||||
"<body><h1>305 Use Proxy</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::temporary_redirect:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Temporary Redirect</title></head>"
|
||||
"<body><h1>307 Temporary Redirect</h1></body>"
|
||||
"</html>";
|
||||
|
||||
// 4xx Client Error
|
||||
case basic_response<tags::http_server>::bad_request:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Bad Request</title></head>"
|
||||
"<body><h1>400 Bad Request</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::unauthorized:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Unauthorized</title></head>"
|
||||
"<body><h1>401 Unauthorized</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::forbidden:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Forbidden</title></head>"
|
||||
"<body><h1>403 Forbidden</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::not_found:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Not Found</title></head>"
|
||||
"<body><h1>404 Not Found</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::not_supported:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Method Not Supported</title></head>"
|
||||
"<body><h1>405 Method Not Supported</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::not_acceptable:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Not Acceptable\r\n</title></head>"
|
||||
"<body><h1>406 Not Acceptable</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::proxy_authentication_required:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Proxy Authentication Required</title></head>"
|
||||
"<body><h1>407 Proxy Authentication Required</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::request_timeout:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Request Timeout</title></head>"
|
||||
"<body><h1>408 Request Timeout</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::conflict:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Conflict</title></head>"
|
||||
"<body><h1>409 Conflict</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::gone:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Gone</title></head>"
|
||||
"<body><h1>410 Gone</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::length_required:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Length Required</title></head>"
|
||||
"<body><h1>411 Length Required</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::precondition_failed:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Precondition Failed</title></head>"
|
||||
"<body><h1>412 Precondition Failed</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::request_entity_too_large:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Request Entity Too Large</title></head>"
|
||||
"<body><h1>413 Request Entity Too Large</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::request_uri_too_large:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Request-URI Too Large</title></head>"
|
||||
"<body><h1>414 Request-URI Too Large</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::unsupported_media_type:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Unsupported Media Type</title></head>"
|
||||
"<body><h1>415 Unsupported Media Type</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::unsatisfiable_range:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Unsatisfiable Range</title></head>"
|
||||
"<body><h1>416 Requested Range Not "
|
||||
"Satisfiable</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::expectation_failed:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Expectation Failed</title></head>"
|
||||
"<body><h1>417 Expectation Failed</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::precondition_required:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Precondition Required</title></head>"
|
||||
"<body><h1>428 Precondition Required</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::too_many_requests:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Too Many Requests</title></head>"
|
||||
"<body><h1>429 Too Many Requests</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::request_header_fields_too_large:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Request Header Fields Too Large</title></head>"
|
||||
"<body><h1>431 Request Header Fields Too Large</h1></body>"
|
||||
"</html>";
|
||||
|
||||
// 5xx Server Error
|
||||
case basic_response<tags::http_server>::internal_server_error:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Internal Server Error</title></head>"
|
||||
"<body><h1>500 Internal Server Error</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::not_implemented:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Not Implemented</title></head>"
|
||||
"<body><h1>501 Not Implemented</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::bad_gateway:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Bad Gateway</title></head>"
|
||||
"<body><h1>502 Bad Gateway</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::service_unavailable:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Service Unavailable</title></head>"
|
||||
"<body><h1>503 Service Unavailable</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::gateway_timeout:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Gateway Timeout</title></head>"
|
||||
"<body><h1>504 Gateway Timeout</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::http_version_not_supported:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>HTTP Version Not Supported</title></head>"
|
||||
"<body><h1>505 HTTP Version Not Supported</h1></body>"
|
||||
"</html>";
|
||||
case basic_response<tags::http_server>::space_unavailable:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Space Unavailable</title></head>"
|
||||
"<body><h1>507 Insufficient Space to Store "
|
||||
"Resource</h1></body>"
|
||||
"</html>";
|
||||
|
||||
default:
|
||||
return
|
||||
"<html>"
|
||||
"<head><title>Internal Server Error</title></head>"
|
||||
"<body><h1>500 Internal Server Error</h1></body>"
|
||||
"</html>";
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::const_buffer trim_null(boost::asio::const_buffer buffer) {
|
||||
std::size_t size = boost::asio::buffer_size(buffer);
|
||||
return boost::asio::buffer(buffer, size - 1);
|
||||
}
|
||||
|
||||
boost::asio::const_buffer to_buffer(status_type status) {
|
||||
using boost::asio::buffer;
|
||||
switch (status) {
|
||||
// 2xx Success
|
||||
case basic_response<tags::http_server>::ok:
|
||||
return trim_null(buffer("HTTP/1.1 200 OK\r\n"));
|
||||
case basic_response<tags::http_server>::created:
|
||||
return trim_null(buffer("HTTP/1.1 201 Created\r\n"));
|
||||
case basic_response<tags::http_server>::accepted:
|
||||
return trim_null(buffer("HTTP/1.1 202 Accepted\r\n"));
|
||||
case basic_response<tags::http_server>::non_authoritative_information:
|
||||
return trim_null(buffer("HTTP/1.1 203 Non-Authoritative Information\r\n"));
|
||||
case basic_response<tags::http_server>::no_content:
|
||||
return trim_null(buffer("HTTP/1.1 204 No Content\r\n"));
|
||||
case basic_response<tags::http_server>::reset_content:
|
||||
return trim_null(buffer("HTTP/1.1 205 Reset Content\r\n"));
|
||||
case basic_response<tags::http_server>::partial_content:
|
||||
return trim_null(buffer("HTTP/1.1 206 Partial Content\r\n"));
|
||||
|
||||
// 3xx Redirection
|
||||
case basic_response<tags::http_server>::multiple_choices:
|
||||
return trim_null(buffer("HTTP/1.1 300 Multiple Choices\r\n"));
|
||||
case basic_response<tags::http_server>::moved_permanently:
|
||||
return trim_null(buffer("HTTP/1.1 301 Moved Permanently\r\n"));
|
||||
case basic_response<tags::http_server>::moved_temporarily:
|
||||
return trim_null(buffer("HTTP/1.1 302 Moved Temporarily\r\n"));
|
||||
case basic_response<tags::http_server>::see_other:
|
||||
return trim_null(buffer("HTTP/1.1 303 See Other\r\n"));
|
||||
case basic_response<tags::http_server>::not_modified:
|
||||
return trim_null(buffer("HTTP/1.1 304 Not Modified\r\n"));
|
||||
case basic_response<tags::http_server>::use_proxy:
|
||||
return trim_null(buffer("HTTP/1.1 305 Use Proxy\r\n"));
|
||||
case basic_response<tags::http_server>::temporary_redirect:
|
||||
return trim_null(buffer("HTTP/1.1 307 Temporary Redirect\r\n"));
|
||||
|
||||
// 4xx Client Error
|
||||
case basic_response<tags::http_server>::bad_request:
|
||||
return trim_null(buffer("HTTP/1.1 400 Bad Request\r\n"));
|
||||
case basic_response<tags::http_server>::unauthorized:
|
||||
return trim_null(buffer("HTTP/1.1 401 Unauthorized\r\n"));
|
||||
case basic_response<tags::http_server>::forbidden:
|
||||
return trim_null(buffer("HTTP/1.1 403 Forbidden\r\n"));
|
||||
case basic_response<tags::http_server>::not_found:
|
||||
return trim_null(buffer("HTTP/1.1 404 Not Found\r\n"));
|
||||
case basic_response<tags::http_server>::not_supported:
|
||||
return trim_null(buffer("HTTP/1.1 405 Method Not Supported\r\n"));
|
||||
case basic_response<tags::http_server>::not_acceptable:
|
||||
return trim_null(buffer("HTTP/1.1 406 Method Not Acceptable\r\n"));
|
||||
case basic_response<tags::http_server>::proxy_authentication_required:
|
||||
return trim_null(buffer("HTTP/1.1 407 Proxy Authentication Required\r\n"));
|
||||
case basic_response<tags::http_server>::request_timeout:
|
||||
return trim_null(buffer("HTTP/1.1 408 Request Timeout\r\n"));
|
||||
case basic_response<tags::http_server>::conflict:
|
||||
return trim_null(buffer("HTTP/1.1 409 Conflict\r\n"));
|
||||
case basic_response<tags::http_server>::gone:
|
||||
return trim_null(buffer("HTTP/1.1 410 Gone\r\n"));
|
||||
case basic_response<tags::http_server>::length_required:
|
||||
return trim_null(buffer("HTTP/1.1 411 Length Required\r\n"));
|
||||
case basic_response<tags::http_server>::precondition_failed:
|
||||
return trim_null(buffer("HTTP/1.1 412 Precondition Failed\r\n"));
|
||||
case basic_response<tags::http_server>::request_entity_too_large:
|
||||
return trim_null(buffer("HTTP/1.1 413 Request Entity Too Large\r\n"));
|
||||
case basic_response<tags::http_server>::request_uri_too_large:
|
||||
return trim_null(buffer("HTTP/1.1 414 Request-URI Too Large\r\n"));
|
||||
case basic_response<tags::http_server>::unsupported_media_type:
|
||||
return trim_null(buffer("HTTP/1.1 415 Unsupported Media Type\r\n"));
|
||||
case basic_response<tags::http_server>::unsatisfiable_range:
|
||||
return trim_null(buffer("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
|
||||
case basic_response<tags::http_server>::precondition_required:
|
||||
return trim_null(buffer("HTTP/1.1 428 Precondition Required\r\n"));
|
||||
case basic_response<tags::http_server>::too_many_requests:
|
||||
return trim_null(buffer("HTTP/1.1 429 Too Many Requests\r\n"));
|
||||
case basic_response<tags::http_server>::request_header_fields_too_large:
|
||||
return trim_null(buffer("HTTP/1.1 431 Request Header Fields Too Large\r\n"));
|
||||
|
||||
// 5xx Server Error
|
||||
case basic_response<tags::http_server>::internal_server_error:
|
||||
return trim_null(buffer("HTTP/1.1 500 Internal Server Error\r\n"));
|
||||
case basic_response<tags::http_server>::not_implemented:
|
||||
return trim_null(buffer("HTTP/1.1 501 Not Implemented\r\n"));
|
||||
case basic_response<tags::http_server>::bad_gateway:
|
||||
return trim_null(buffer("HTTP/1.1 502 Bad Gateway\r\n"));
|
||||
case basic_response<tags::http_server>::service_unavailable:
|
||||
return trim_null(buffer("HTTP/1.1 503 Service Unavailable\r\n"));
|
||||
case basic_response<tags::http_server>::gateway_timeout:
|
||||
return trim_null(buffer("HTTP/1.1 504 Gateway Timeout\r\n"));
|
||||
case basic_response<tags::http_server>::http_version_not_supported:
|
||||
return trim_null(buffer("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
|
||||
case basic_response<tags::http_server>::space_unavailable:
|
||||
return trim_null(buffer("HTTP/1.1 507 Insufficient Space to Store Resource\r\n"));
|
||||
|
||||
default:
|
||||
return trim_null(buffer("HTTP/1.1 500 Internal Server Error\r\n"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_RESPONSE_RESPONSE_IPP
|
137
cpp-netlib/boost/network/protocol/http/message.hpp
Normal file
137
cpp-netlib/boost/network/protocol/http/message.hpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
// 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 <boost/network/protocol/http/traits.hpp>
|
||||
#include <boost/network/protocol/http/message/header/name.hpp>
|
||||
#include <boost/network/protocol/http/message/header/value.hpp>
|
||||
#include <boost/network/protocol/http/message/header_concept.hpp>
|
||||
#include <boost/network/message.hpp>
|
||||
#include <boost/network/tags.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
/// base class for HTTP messages (requests and responses)
|
||||
template <typename Tag>
|
||||
struct message_impl : public basic_message<Tag> {
|
||||
|
||||
typedef typename string<Tag>::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<Tag>::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<Tag> 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 <class Tag>
|
||||
inline void swap(message_impl<Tag> &lhs, message_impl<Tag> &rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
typedef message_impl<tags::http_default_8bit_tcp_resolve> message;
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// import implementation file
|
||||
#include <boost/network/protocol/http/impl/message.ipp>
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP
|
158
cpp-netlib/boost/network/protocol/http/message/async_message.hpp
Normal file
158
cpp-netlib/boost/network/protocol/http/message/async_message.hpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
#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 <boost/thread/future.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
// FIXME move this out to a trait
|
||||
#include <set>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/network/detail/wrapper_base.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag>
|
||||
struct ready_wrapper;
|
||||
|
||||
} /* impl */
|
||||
|
||||
template <class Tag>
|
||||
struct async_message {
|
||||
|
||||
typedef typename string<Tag>::type string_type;
|
||||
typedef typename headers_container<Tag>::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<string_type> const& future) const {
|
||||
status_message_ = future;
|
||||
}
|
||||
|
||||
string_type const version() const { return version_.get(); }
|
||||
|
||||
void version(boost::shared_future<string_type> const& future) const {
|
||||
version_ = future;
|
||||
}
|
||||
|
||||
boost::uint16_t status() const { return status_.get(); }
|
||||
|
||||
void status(boost::shared_future<uint16_t> const& future) const {
|
||||
status_ = future;
|
||||
}
|
||||
|
||||
string_type const source() const { return source_.get(); }
|
||||
|
||||
void source(boost::shared_future<string_type> const& future) const {
|
||||
source_ = future;
|
||||
}
|
||||
|
||||
string_type const destination() const { return destination_.get(); }
|
||||
|
||||
void destination(boost::shared_future<string_type> 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<headers_container_type> 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<string_type> 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<string_type> status_message_, version_, source_,
|
||||
destination_;
|
||||
mutable boost::shared_future<boost::uint16_t> status_;
|
||||
mutable boost::shared_future<headers_container_type> headers_;
|
||||
mutable headers_container_type added_headers;
|
||||
mutable std::set<string_type> removed_headers;
|
||||
mutable boost::shared_future<string_type> body_;
|
||||
mutable boost::optional<headers_container_type> retrieved_headers_;
|
||||
|
||||
friend struct boost::network::http::impl::ready_wrapper<Tag>;
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
inline void swap(async_message<Tag>& lhs, async_message<Tag>& rhs) {
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_ASYNC_MESSAGE_HPP_20100622
|
|
@ -0,0 +1,41 @@
|
|||
#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 <boost/network/protocol/http/support/is_server.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
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 <class Tag>
|
||||
void operator()(basic_request<Tag>& 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 \
|
||||
*/
|
|
@ -0,0 +1,23 @@
|
|||
#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 \
|
||||
*/
|
|
@ -0,0 +1,41 @@
|
|||
#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 <boost/network/protocol/http/support/is_server.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
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 <class Tag>
|
||||
void operator()(basic_request<Tag>& 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 \
|
||||
*/
|
|
@ -0,0 +1,76 @@
|
|||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
struct status_directive {
|
||||
|
||||
boost::variant<boost::uint16_t, boost::shared_future<boost::uint16_t> >
|
||||
status_;
|
||||
|
||||
explicit status_directive(boost::uint16_t status) : status_(status) {}
|
||||
|
||||
explicit status_directive(boost::shared_future<boost::uint16_t> const &status)
|
||||
: status_(status) {}
|
||||
|
||||
status_directive(status_directive const &other) : status_(other.status_) {}
|
||||
|
||||
template <class Tag>
|
||||
struct value : mpl::if_<is_async<Tag>, boost::shared_future<boost::uint16_t>,
|
||||
boost::uint16_t> {};
|
||||
|
||||
template <class Tag>
|
||||
struct status_visitor : boost::static_visitor<> {
|
||||
basic_response<Tag> const &response;
|
||||
status_visitor(basic_response<Tag> const &response) : response(response) {}
|
||||
|
||||
void operator()(typename value<Tag>::type const &status_) const {
|
||||
response.status(status_);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void operator()(T const &) const {
|
||||
// FIXME fail here!
|
||||
}
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
basic_response<Tag> const &operator()(basic_response<Tag> const &response)
|
||||
const {
|
||||
apply_visitor(status_visitor<Tag>(response), status_);
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
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
|
|
@ -0,0 +1,27 @@
|
|||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/message/directives/detail/string_directive.hpp>
|
||||
|
||||
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
|
|
@ -0,0 +1,26 @@
|
|||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/message/directives/detail/string_directive.hpp>
|
||||
|
||||
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
|
|
@ -0,0 +1,26 @@
|
|||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/message/directives/detail/string_directive.hpp>
|
||||
|
||||
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
|
99
cpp-netlib/boost/network/protocol/http/message/header.hpp
Normal file
99
cpp-netlib/boost/network/protocol/http/message/header.hpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// 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 <boost/network/traits/string.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/network/support/is_default_wstring.hpp>
|
||||
#include <boost/network/support/is_default_wstring.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
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 <class Tag>
|
||||
struct request_header
|
||||
: mpl::if_<is_default_string<Tag>, request_header_narrow,
|
||||
typename mpl::if_<is_default_wstring<Tag>, request_header_wide,
|
||||
unsupported_tag<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 <class Tag>
|
||||
struct response_header
|
||||
: mpl::if_<is_default_string<Tag>, response_header_narrow,
|
||||
typename mpl::if_<is_default_wstring<Tag>, response_header_wide,
|
||||
unsupported_tag<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
|
|
@ -0,0 +1,41 @@
|
|||
#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 <boost/network/protocol/http/message/header.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class T1, class T2>
|
||||
T1 &name(std::pair<T1, T2> 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 */
|
|
@ -0,0 +1,51 @@
|
|||
#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 <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
struct request_header_narrow;
|
||||
struct request_header_wide;
|
||||
struct response_header_narrow;
|
||||
struct response_header_wide;
|
||||
|
||||
template <class T1, class T2>
|
||||
T1& value(std::pair<T1, T2> 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 */
|
|
@ -0,0 +1,38 @@
|
|||
#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 <boost/network/traits/string.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class H>
|
||||
struct Header : DefaultConstructible<H>, Assignable<H>, CopyConstructible<H> {
|
||||
|
||||
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 */
|
|
@ -0,0 +1,33 @@
|
|||
#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 <boost/network/tags.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct async_message;
|
||||
|
||||
template <class Tag>
|
||||
struct message_impl;
|
||||
|
||||
template <class Tag>
|
||||
struct message_base
|
||||
: mpl::if_<is_async<Tag>, async_message<Tag>, message_impl<Tag> > {};
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_BASE_HPP_20100603
|
|
@ -0,0 +1,77 @@
|
|||
#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 <boost/network/protocol/http/tags.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/protocol/http/support/client_or_server.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/network/message/directives.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void body(basic_response<Tag> &response, T const &value, mpl::false_ const &) {
|
||||
response << ::boost::network::body(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void body(basic_response<Tag> &response, T const &future, mpl::true_ const &) {
|
||||
response.body(future);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void body(basic_response<Tag> &response, T const &value) {
|
||||
impl::body(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void body_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::server) {
|
||||
request.body = value;
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void body_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::client) {
|
||||
request << ::boost::network::body(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void body(basic_request<Tag> &request, T const &value) {
|
||||
body_impl(request, value, typename client_or_server<Tag>::type());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class ValueType, class Async>
|
||||
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
|
|
@ -0,0 +1,52 @@
|
|||
#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 <boost/network/protocol/http/support/client_or_server.hpp>
|
||||
#include <boost/network/support/pod_or_normal.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
inline void clear_headers_impl(basic_request<Tag>& request, tags::pod) {
|
||||
typedef typename basic_request<Tag>::headers_container_type headers_container;
|
||||
headers_container().swap(request.headers);
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline void clear_headers_impl(basic_request<Tag>& request, tags::normal) {
|
||||
request.headers(typename basic_request<Tag>::headers_container_type());
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline void clear_headers_impl(basic_request<Tag>& request, tags::client) {
|
||||
clear_headers_impl(request, typename pod_or_normal<Tag>::type());
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline void clear_headers_impl(basic_request<Tag>& request, tags::server) {
|
||||
typedef typename basic_request<Tag>::headers_container_type headers_container;
|
||||
headers_container().swap(request.headers);
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
inline void clear_headers(basic_request<Tag>& request) {
|
||||
clear_headers_impl(request, typename client_or_server<Tag>::type());
|
||||
}
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 \
|
||||
*/
|
|
@ -0,0 +1,95 @@
|
|||
#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 <boost/network/protocol/http/support/client_or_server.hpp>
|
||||
#include <boost/network/support/pod_or_normal.hpp>
|
||||
#include <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/concept/requires.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void destination(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << ::boost::network::destination(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void destination(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.destination(future);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination(basic_response<Tag> &response, T const &value) {
|
||||
impl::destination(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
template <class R>
|
||||
struct ServerRequest;
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::server) {
|
||||
request.destination = value;
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::pod) {
|
||||
request.destination = value;
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::normal) {
|
||||
request.destination(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::client) {
|
||||
destination_impl(request, value, typename pod_or_normal<Tag>::type());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void destination(basic_request<Tag> &request, T const &value) {
|
||||
destination_impl(request, value, typename client_or_server<Tag>::type());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class ValueType, class Async>
|
||||
inline void destination(Message const &message, ValueType const &destination_,
|
||||
http::tags::http_server, Async) {
|
||||
message.destination = destination_;
|
||||
}
|
||||
|
||||
} /* impl */
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/network/message/modifiers/destination.hpp>
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_DESTINATION_HPP_20100624
|
|
@ -0,0 +1,60 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/concept/requires.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void headers(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << headers(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void headers(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.headers(future);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void headers(basic_request<Tag> &request, T const &value,
|
||||
tags::server const &) {
|
||||
request.headers = value;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void headers(basic_response<Tag> &response, T const &value) {
|
||||
impl::headers(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void headers(basic_request<Tag> &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
|
|
@ -0,0 +1,33 @@
|
|||
#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 <boost/network/protocol/http/support/is_server.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
template <class Tag>
|
||||
inline typename enable_if<is_server<Tag>, void>::type major_version(
|
||||
basic_request<Tag>& 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 \
|
||||
*/
|
|
@ -0,0 +1,31 @@
|
|||
#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 <boost/network/traits/string.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
template <class Tag>
|
||||
inline typename enable_if<is_server<Tag>, void>::type method(
|
||||
basic_request<Tag>& request, typename string<Tag>::type const& method_) {
|
||||
request.method = method_;
|
||||
}
|
||||
|
||||
} /* http */
|
||||
|
||||
} /* network */
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 */
|
|
@ -0,0 +1,33 @@
|
|||
#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 <boost/network/protocol/http/support/is_server.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
template <class Tag>
|
||||
inline typename enable_if<is_server<Tag>, void>::type minor_version(
|
||||
basic_request<Tag>& 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 \
|
||||
*/
|
|
@ -0,0 +1,87 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/protocol/http/support/client_or_server.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/concept/requires.hpp>
|
||||
#include <boost/network/protocol/http/tags.hpp>
|
||||
#include <boost/network/message/directives.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void source(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << ::boost::network::source(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void source(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.source(future);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void source(basic_request<Tag> &request, T const &value, tags::server const &) {
|
||||
request.source = value;
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void source(basic_request<Tag> &request, T const &value, tags::client const &) {
|
||||
request << ::boost::network::source(value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void source(basic_response<Tag> &response, T const &value) {
|
||||
impl::source(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void source_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::server) {
|
||||
impl::source(request, value, Tag());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void source_impl(basic_request<Tag> &request, T const &value,
|
||||
tags::client) {
|
||||
impl::source(request, value, Tag());
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
inline void source(basic_request<Tag> &request, T const &value) {
|
||||
source_impl(request, value, typename client_or_server<Tag>::type());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Message, class ValueType, class Async>
|
||||
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 <boost/network/message/modifiers/source.hpp>
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIER_SOURCE_HPP_20100624
|
|
@ -0,0 +1,47 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void status(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << boost::network::http::status(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void status(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.status(future);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, class T>
|
||||
void status(basic_response<Tag> &response, T const &value) {
|
||||
impl::status(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_HPP_20100608
|
|
@ -0,0 +1,47 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void status_message(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << boost::network::http::status_message(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void status_message(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.status_message(future);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, class T>
|
||||
void status_message(basic_response<Tag> &response, T const &value) {
|
||||
impl::status_message(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_STATUS_MESSAGE_HPP_20100608
|
|
@ -0,0 +1,31 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_request;
|
||||
|
||||
template <class Tag, class T>
|
||||
void uri(basic_request<Tag>& request, T const& value) {
|
||||
request.uri(value);
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_URI_HPP_20100621
|
|
@ -0,0 +1,49 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/network/support/is_sync.hpp>
|
||||
#include <boost/thread/future.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
template <class Tag>
|
||||
struct basic_response;
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class Tag, class T>
|
||||
void version(basic_response<Tag> &response, T const &value,
|
||||
mpl::false_ const &) {
|
||||
response << boost::network::http::version(value);
|
||||
}
|
||||
|
||||
template <class Tag, class T>
|
||||
void version(basic_response<Tag> &response, T const &future,
|
||||
mpl::true_ const &) {
|
||||
response.version(future);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Tag, class T>
|
||||
void version(basic_response<Tag> &response, T const &value) {
|
||||
impl::version(response, value, is_async<Tag>());
|
||||
}
|
||||
|
||||
} // namespace http
|
||||
|
||||
} // namespace network
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_VERSION_HPP_20100608
|
|
@ -0,0 +1,36 @@
|
|||
#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 <boost/network/support/is_async.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/network/tags.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace network {
|
||||
namespace http {
|
||||
|
||||
namespace traits {
|
||||
|
||||
template <class Tag>
|
||||
struct unsupported_tag;
|
||||
|
||||
template <class Message>
|
||||
struct status
|
||||
: mpl::if_<
|
||||
is_async<typename Message::tag>,
|
||||
boost::shared_future<boost::uint16_t>,
|
||||
typename mpl::if_<is_sync<typename Message::tag>, boost::uint16_t,
|
||||
unsupported_tag<typename Message::tag> >::type> {};
|
||||
|
||||
} /* traits */
|
||||
|
||||
} /* http */
|
||||
} /* network */
|
||||
} /* boost */
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue