diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 42cf923..8f529ee --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,4 @@ fc_automoc.cpp git_revision.cpp GitSHA3.cpp -ntp_test task_cancel_test -udt_client -udt_server diff --git a/.gitmodules b/.gitmodules old mode 100644 new mode 100755 index c49f87b..0e539dc --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "vendor/secp256k1-zkp"] - path = vendor/secp256k1-zkp - url = https://github.com/cryptonomex/secp256k1-zkp.git -[submodule "vendor/websocketpp"] - path = vendor/websocketpp - url = https://github.com/zaphoyd/websocketpp.git + path = vendor/secp256k1-zkp + url = https://github.com/bitshares/secp256k1-zkp.git diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 08862ab..bd52180 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ endif() SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) SET(BOOST_COMPONENTS) -LIST(APPEND BOOST_COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context locale iostreams) +LIST(APPEND BOOST_COMPONENTS thread date_time filesystem system program_options signals serialization chrono unit_test_framework context locale iostreams) SET( Boost_USE_STATIC_LIBS ON CACHE STRING "ON or OFF" ) IF( ECC_IMPL STREQUAL openssl ) @@ -55,7 +55,7 @@ ELSE( ECC_IMPL STREQUAL openssl ) ENDIF( ECC_IMPL STREQUAL openssl ) # Configure secp256k1-zkp -if ( WIN32 ) +if ( MSVC ) # autoconf won't work here, hard code the defines set( SECP256K1_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp" ) @@ -71,8 +71,18 @@ if ( WIN32 ) USE_SCALAR_8X32 USE_SCALAR_INV_BUILTIN ) set_target_properties( secp256k1 PROPERTIES COMPILE_DEFINITIONS "${SECP256K1_BUILD_DEFINES}" LINKER_LANGUAGE C ) -else ( WIN32 ) +else ( MSVC ) include(ExternalProject) + if ( MINGW ) + ExternalProject_Add( project_secp256k1 + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp + CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp --with-bignum=no --host=x86_64-w64-mingw32 + BUILD_COMMAND make + INSTALL_COMMAND true + BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a + ) + else ( MINGW ) ExternalProject_Add( project_secp256k1 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp @@ -81,6 +91,7 @@ else ( WIN32 ) INSTALL_COMMAND true BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/secp256k1-zkp/src/project_secp256k1-build/.libs/libsecp256k1.a ) + endif ( MINGW ) ExternalProject_Add_Step(project_secp256k1 autogen WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/autogen.sh @@ -93,13 +104,14 @@ else ( WIN32 ) set_property(TARGET secp256k1 PROPERTY IMPORTED_LOCATION ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX}) set_property(TARGET secp256k1 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp/include) add_dependencies(secp256k1 project_secp256k1) -endif ( WIN32 ) + install( FILES ${binary_dir}/.libs/libsecp256k1${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib/cryptonomex ) +endif ( MSVC ) # End configure secp256k1-zkp IF( WIN32 ) MESSAGE(STATUS "Configuring fc to build on Win32") - set( RPCRT4 Rpcrt4 ) + set( RPCRT4 rpcrt4 ) #boost SET(BOOST_ROOT $ENV{BOOST_ROOT}) @@ -116,7 +128,7 @@ IF( WIN32 ) SET(Boost_LIBRARIES ${BOOST_LIBRARIES_TEMP} ${Boost_LIBRARIES}) ENDIF() - set( PLATFORM_SPECIFIC_LIBS WS2_32.lib Userenv.lib) + set( PLATFORM_SPECIFIC_LIBS wsock32.lib ws2_32.lib userenv.lib) # iphlpapi.lib ELSE(WIN32) @@ -178,14 +190,15 @@ set( fc_sources src/io/varint.cpp src/io/console.cpp src/filesystem.cpp - src/interprocess/process.cpp src/interprocess/signals.cpp src/interprocess/file_mapping.cpp src/interprocess/mmap_struct.cpp + src/interprocess/file_mutex.cpp src/rpc/cli.cpp src/rpc/http_api.cpp src/rpc/json_connection.cpp src/rpc/state.cpp + src/rpc/bstate.cpp src/rpc/websocket_api.cpp src/log/log_message.cpp src/log/logger.cpp @@ -199,7 +212,6 @@ set( fc_sources src/crypto/aes.cpp src/crypto/crc.cpp src/crypto/city.cpp - src/crypto/base32.cpp src/crypto/base36.cpp src/crypto/base58.cpp src/crypto/base64.cpp @@ -219,20 +231,16 @@ set( fc_sources src/crypto/rand.cpp src/network/tcp_socket.cpp src/network/udp_socket.cpp - src/network/udt_socket.cpp src/network/http/http_connection.cpp src/network/http/http_server.cpp src/network/http/websocket.cpp - src/network/ntp.cpp src/network/ip.cpp + src/network/ntp.cpp src/network/rate_limiting.cpp src/network/resolve.cpp src/network/url.cpp - src/network/gntp.cpp src/compress/smaz.cpp src/compress/zlib.cpp - vendor/cyoencode-1.0.2/src/CyoDecode.c - vendor/cyoencode-1.0.2/src/CyoEncode.c ) file( GLOB_RECURSE fc_headers ${CMAKE_CURRENT_SOURCE_DIR} *.hpp *.h ) @@ -245,10 +253,10 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/git_revision.cpp.in" "${CMAKE_CU list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp") list(APPEND sources ${fc_headers}) -add_subdirectory( vendor/websocketpp ) -add_subdirectory( vendor/udt4 ) +add_subdirectory( vendor/websocketpp EXCLUDE_FROM_ALL ) -setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC DONT_INSTALL_LIBRARY ) +setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC ) +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include ) # begin readline stuff find_package(Curses) @@ -269,6 +277,10 @@ if(WIN32) endif(WIN32) # end readline stuff +if( NOT CPP_STANDARD ) + set( CPP_STANDARD, "-std=c++11" ) +endif() + IF(WIN32) target_compile_definitions(fc PUBLIC WIN32 NOMINMAX _WIN32_WINNT=0x0501 _CRT_SECURE_NO_WARNINGS _SCL_SERCURE_NO_WARNINGS @@ -279,47 +291,86 @@ IF(WIN32) # autodetecting code to do the right thing. _WEBSOCKETPP_CPP11_CHRONO_ ) - # Activate C++ exception handling, assume extern C calls don't throw - # Add /U options to be sure settings specific to dynamic boost link are ineffective - target_compile_options(fc PUBLIC /EHsc /UBOOST_ALL_DYN_LINK /UBOOST_LINKING_PYTHON /UBOOST_DEBUG_PYTHON) + if( MSVC ) + # Activate C++ exception handling, assume extern C calls don't throw + # Add /U options to be sure settings specific to dynamic boost link are ineffective + target_compile_options(fc PUBLIC /EHsc /UBOOST_ALL_DYN_LINK /UBOOST_LINKING_PYTHON /UBOOST_DEBUG_PYTHON) + elseif( MINGW ) + # Put MinGW specific compiler settings here + endif() ELSE() SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall") IF(APPLE) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CPP_STANDARD} -stdlib=libc++ -Wall") ELSE() if( NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) - target_compile_options(fc PUBLIC -std=c++11 -Wall -fnon-call-exceptions) + target_compile_options(fc PUBLIC ${CPP_STANDARD} -Wall -fnon-call-exceptions) + endif() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CPP_STANDARD} -Wall -fnon-call-exceptions") + + if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) + if( CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.0.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0.0 ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-partial-specialization" ) + endif() endif() - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fnon-call-exceptions") ENDIF() ENDIF() +IF(APPLE) + # As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency + # on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib + # option or not when it was built, but that's difficult to do in practice, so we + # just always try to link it in on mac. + find_package( ZLIB REQUIRED ) +ELSE(APPLE) + find_package( ZLIB ) +ENDIF(APPLE) + +if( ZLIB_FOUND ) + MESSAGE( STATUS "zlib found" ) + add_definitions( -DHAS_ZLIB ) +else() + MESSAGE( STATUS "zlib not found" ) + set( ZLIB_LIBRARIES "" ) +endif( ZLIB_FOUND ) + # This will become unnecessary once we update to websocketpp which fixes upstream issue #395 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBSOCKETPP_STRICT_MASKING") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBOOST_ASIO_HAS_STD_CHRONO") +OPTION( LOG_LONG_API "Log long API calls over websocket (ON OR OFF)" ON ) +MESSAGE( STATUS "LOG_LONG_API: ${LOG_LONG_API}" ) +if( LOG_LONG_API ) + SET( LOG_LONG_API_MAX_MS 1000 CACHE STRING "Max API execution time in ms" ) + SET( LOG_LONG_API_WARN_MS 750 CACHE STRING "API execution time in ms at which to warn" ) + MESSAGE( STATUS " " ) + MESSAGE( STATUS " LOGGING LONG API CALLS" ) + MESSAGE( STATUS " MAX MS: ${LOG_LONG_API_MAX_MS}" ) + MESSAGE( STATUS " WARN MS: ${LOG_LONG_API_WARN_MS}" ) + MESSAGE( STATUS " " ) + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLOG_LONG_API -DLOG_LONG_API_MAX_MS=${LOG_LONG_API_MAX_MS} -DLOG_LONG_API_WARN_MS=${LOG_LONG_API_WARN_MS}" ) + SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLOG_LONG_API -DLOG_LONG_API_MAX_MS=${LOG_LONG_API_MAX_MS} -DLOG_LONG_API_WARN_MS=${LOG_LONG_API_WARN_MS}" ) +endif() + target_include_directories(fc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} + "vendor/diff-match-patch-cpp-stl" + ${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp "${readline_includes}" PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include - ${CMAKE_CURRENT_SOURCE_DIR}/vendor/cyoencode-1.0.2/src - ${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src - ${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp ${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp - ${ZLIB_INCLUDE_DIRS} ) -#target_link_libraries( fc PUBLIC udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} ) +#target_link_libraries( fc PUBLIC ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${ECC_LIB} ) IF(NOT WIN32) set(LINK_USR_LOCAL_LIB -L/usr/local/lib) ENDIF() -target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} ) +target_link_libraries( fc PUBLIC ${LINK_USR_LOCAL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library} ${readline_libraries} ${ECC_LIB} ) if(MSVC) set_source_files_properties( src/network/http/websocket.cpp PROPERTIES COMPILE_FLAGS "/bigobj" ) @@ -327,77 +378,16 @@ endif(MSVC) IF(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY MATCHES "\\.(a|lib)$") -IF(WIN32) +IF(MSVC) add_definitions(/DBOOST_TEST_DYN_LINK) -ELSE(WIN32) +ELSE(MSVC) add_definitions(-DBOOST_TEST_DYN_LINK) -ENDIF(WIN32) +ENDIF(MSVC) ENDIF() -add_executable( api tests/api.cpp ) -target_link_libraries( api fc ) - -if( ECC_IMPL STREQUAL secp256k1 ) - add_executable( blind tests/all_tests.cpp tests/crypto/blind.cpp ) - target_link_libraries( blind fc ) -endif() - include_directories( vendor/websocketpp ) -add_executable( ntp_test tests/all_tests.cpp tests/network/ntp_test.cpp ) -target_link_libraries( ntp_test fc ) - -add_executable( task_cancel_test tests/all_tests.cpp tests/thread/task_cancel.cpp ) -target_link_libraries( task_cancel_test fc ) - - -add_executable( bloom_test tests/all_tests.cpp tests/bloom_test.cpp ) -target_link_libraries( bloom_test fc ) - -add_executable( real128_test tests/all_tests.cpp tests/real128_test.cpp ) -target_link_libraries( real128_test fc ) - -add_executable( hmac_test tests/hmac_test.cpp ) -target_link_libraries( hmac_test fc ) - -add_executable( blinding_test tests/blinding_test.cpp ) -target_link_libraries( blinding_test fc ) - - -add_executable( udt_server tests/udts.cpp ) -target_link_libraries( udt_server fc udt ) - -add_executable( udt_client tests/udtc.cpp ) -target_link_libraries( udt_client fc udt ) - -add_executable( ecc_test tests/crypto/ecc_test.cpp ) -target_link_libraries( ecc_test fc ) - -#add_executable( test_aes tests/aes_test.cpp ) -#target_link_libraries( test_aes fc ${rt_library} ${pthread_library} ) -#add_executable( test_sleep tests/sleep.cpp ) -#target_link_libraries( test_sleep fc ) -#add_executable( test_rate_limiting tests/rate_limiting.cpp ) -#target_link_libraries( test_rate_limiting fc ) - -add_executable( all_tests tests/all_tests.cpp - tests/compress/compress.cpp - tests/crypto/aes_test.cpp - tests/crypto/base_n_tests.cpp - tests/crypto/bigint_test.cpp - tests/crypto/blind.cpp - tests/crypto/blowfish_test.cpp - tests/crypto/dh_test.cpp - tests/crypto/rand_test.cpp - tests/crypto/sha_tests.cpp - tests/network/ntp_test.cpp - tests/network/http/websocket_test.cpp - tests/thread/task_cancel.cpp - tests/bloom_test.cpp - tests/real128_test.cpp - tests/utf8_test.cpp - ) -target_link_libraries( all_tests fc ) +add_subdirectory(tests) if(WIN32) # add addtional import library on windows platform @@ -481,14 +471,6 @@ if(WIN32) endif(WIN32) -IF(APPLE) - # As of 10.10 yosemite, the OpenSSL static libraries shipped with os x have a dependency - # on zlib, so any time you link in openssl you also need to link zlib. . We really want to detect whether openssl was configured with the --no-zlib - # option or not when it was built, but that's difficult to do in practice, so we - # just always try to link it in on mac. - find_package( ZLIB REQUIRED ) -ENDIF(APPLE) - SET(OPENSSL_CONF_TARGET ) IF(DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) SET (OPENSSL_CONF_TARGET ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) @@ -497,8 +479,15 @@ ELSE() ENDIF() IF(WIN32) -SET(POST_BUILD_STEP_COMMANDS ${POST_BUILD_STEP_COMMANDS} - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf" "${OPENSSL_CONF_TARGET}/openssl.cnf") + IF("${OPENSSL_ROOT_DIR}" STREQUAL "") + get_filename_component(OPENSSL_ROOT_DIR "${OPENSSL_INCLUDE_DIR}/.." REALPATH) + ENDIF() + SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/ssl/openssl.cnf") + IF(MINGW) + SET(OPENSSL_CONF_SOURCE "${OPENSSL_ROOT_DIR}/openssl.cnf") + ENDIF(MINGW) + SET(POST_BUILD_STEP_COMMANDS ${POST_BUILD_STEP_COMMANDS} + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${OPENSSL_CONF_SOURCE}" "${OPENSSL_CONF_TARGET}/openssl.cnf") ENDIF(WIN32) ADD_CUSTOM_COMMAND(TARGET fc POST_BUILD ${POST_BUILD_STEP_COMMANDS} diff --git a/CMakeModules/ArgumentParser.cmake b/CMakeModules/ArgumentParser.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/FindBoost.cmake b/CMakeModules/FindBoost.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/FindReadline.cmake b/CMakeModules/FindReadline.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/FindVLD.cmake b/CMakeModules/FindVLD.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/FindWt.cmake b/CMakeModules/FindWt.cmake deleted file mode 100755 index 094e378..0000000 --- a/CMakeModules/FindWt.cmake +++ /dev/null @@ -1,127 +0,0 @@ -# Find Wt includes and libraries -# -# This script sets the following variables: -# -# Wt_INCLUDE_DIR -# Wt_LIBRARIES - Release libraries -# Wt_FOUND - True if release libraries found -# Wt_DEBUG_LIBRARIES - Debug libraries -# Wt_DEBUG_FOUND - True if debug libraries found -# -# To direct the script to a particular Wt installation, use the -# standard cmake variables CMAKE_INCLUDE_PATH and CMAKE_LIBRARY_PATH -# -# To use this script to find Wt, when using the new style for include files: -# #include -# #include -# #include -# -# include the following CMake snippet in your project: -# -# FIND_PACKAGE( Wt REQUIRED ) -# INCLUDE_DIRECTORIES( ${Wt_INCLUDE_DIR} ) -# TARGET_LINK_LIBRARIES( yourexe -# ${Wt_DEBUG_LIBRARY} # or {Wt_LIBRARY} -# ${Wt_HTTP_DEBUG_LIBRARY} # or {Wt_HTTP_LIBRARY} -# ${Wt_EXT_DEBUG_LIBRARY} # or {Wt_EXT_LIBRARY} -# ) -# -# To use this script to find Wt, when using the old include style: -# #include -# #include -# #include -# style of include files, change the INCLUDE_DIRECTORIES statement to: -# INCLUDE_DIRECTORIES( ${Wt_INCLUDE_DIR} ${Wt_INCLUDE_DIR}/Wt ) -# -# -# -# -# Copyright (c) 2007, Pau Garcia i Quiles, -# -# Redistribution and use is allowed according to the terms of the BSD license. -# For details see the accompanying COPYING-CMAKE-SCRIPTS file. - -FIND_PATH( Wt_INCLUDE_DIR NAMES Wt/WObject PATHS ENV PATH PATH_SUFFIXES include wt ) - -SET( Wt_FIND_COMPONENTS Release Debug ) - -IF( Wt_INCLUDE_DIR ) - FIND_LIBRARY( Wt_LIBRARY NAMES wt PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_EXT_LIBRARY NAMES wtext PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_HTTP_LIBRARY NAMES wthttp PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_FCGI_LIBRARY NAMES wtfcgi PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_DBO_LIBRARY NAMES wtdbo PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_DBOSQLITE3_LIBRARY NAMES wtdbosqlite3 PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - FIND_LIBRARY( Wt_DBOPOSTGRES_LIBRARY NAMES wtdbopostgres PATHS PATH PATH_SUFFIXES lib lib-release lib_release ) - - FIND_LIBRARY( Wt_DEBUG_LIBRARY NAMES wtd wt PATHS PATH PATH_SUFFIXES lib libd lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_EXT_DEBUG_LIBRARY NAMES wtextd wtext PATHS PATH PATH_SUFFIXES lib libd lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_HTTP_DEBUG_LIBRARY NAMES wthttpd wthttp PATHS PATH PATH_SUFFIXES lib libd lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_FCGI_DEBUG_LIBRARY NAMES wtfcgid wtfcgi PATHS PATH PATH_SUFFIXES lib libd lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_DBO_DEBUG_LIBRARY NAMES wtdbod wtdbo PATHS PATH PATH_SUFFIXES lib lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_DBOSQLITE3_DEBUG_LIBRARY NAMES wtdbosqlite3d wtdbosqlite3 PATHS PATH PATH_SUFFIXES lib lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - FIND_LIBRARY( Wt_DBOPOSTGRES_DEBUG_LIBRARY NAMES wtdbopostgresd wtdbopostgres PATHS PATH PATH_SUFFIXES lib lib-debug lib_debug HINTS /usr/lib/debug/usr/lib) - - IF( Wt_LIBRARY AND Wt_EXT_LIBRARY AND Wt_HTTP_LIBRARY) - SET( Wt_FOUND TRUE ) - SET( Wt_FIND_REQUIRED_Release TRUE ) - SET( Wt_LIBRARIES ${Wt_HTTP_LIBRARY} ${Wt_EXT_LIBRARY} ${Wt_LIBRARY} ) - ENDIF( Wt_LIBRARY AND Wt_EXT_LIBRARY AND Wt_HTTP_LIBRARY) - - IF( Wt_DBO_LIBRARY ) - SET( Wt_LIBRARIES ${Wt_LIBRARIES} ${Wt_DBO_LIBRARY} ) - IF( Wt_DBOSQLITE3_LIBRARY ) - SET( Wt_LIBRARIES ${Wt_LIBRARIES} ${Wt_DBOSQLITE3_LIBRARY} ) - ENDIF( Wt_DBOSQLITE3_LIBRARY ) - IF( Wt_DBOPOSTGRES_LIBRARY ) - SET( Wt_LIBRARIES ${Wt_LIBRARIES} ${Wt_DBOPOSTGRES_LIBRARY} ) - ENDIF( Wt_DBOPOSTGRES_LIBRARY ) - ENDIF( Wt_DBO_LIBRARY ) - - IF( Wt_FCGI_LIBRARY ) - SET( Wt_LIBRARIES ${Wt_LIBRARIES} ${Wt_FCGI_LIBRARY} ) - ENDIF( Wt_FCGI_LIBRARY ) - - IF( Wt_DEBUG_LIBRARY AND Wt_EXT_DEBUG_LIBRARY AND Wt_HTTP_DEBUG_LIBRARY) - SET( Wt_DEBUG_FOUND TRUE ) - SET( Wt_FIND_REQUIRED_Debug TRUE ) - SET( Wt_DEBUG_LIBRARIES ${Wt_HTTP_DEBUG_LIBRARY} ${Wt_EXT_DEBUG_LIBRARY} ${Wt_DEBUG_LIBRARY} ) - ENDIF( Wt_DEBUG_LIBRARY AND Wt_EXT_DEBUG_LIBRARY AND Wt_HTTP_DEBUG_LIBRARY) - - IF( Wt_DBO_DEBUG_LIBRARY ) - SET( Wt_DEBUG_LIBRARIES ${Wt_DEBUG_LIBRARIES} ${Wt_DBO_DEBUG_LIBRARY} ) - IF( Wt_DBOSQLITE3_DEBUG_LIBRARY ) - SET( Wt_DEBUG_LIBRARIES ${Wt_DEBUG_LIBRARIES} ${Wt_DBOSQLITE3_DEBUG_LIBRARY} ) - ENDIF( Wt_DBOSQLITE3_DEBUG_LIBRARY ) - IF( Wt_DBOPOSTGRES_DEBUG_LIBRARY ) - SET( Wt_DEBUG_LIBRARIES ${Wt_DEBUG_LIBRARIES} ${Wt_DBOPOSTGRES_DEBUG_LIBRARY} ) - ENDIF( Wt_DBOPOSTGRES_DEBUG_LIBRARY ) - ENDIF( Wt_DBO_DEBUG_LIBRARY ) - - IF( Wt_FCGI_DEBUG_LIBRARY ) - SET( Wt_DEBUG_LIBRARIES ${Wt_DEBUG_LIBRARIES} ${Wt_FCGI_DEBUG_LIBRARY} ) - ENDIF( Wt_FCGI_DEBUG_LIBRARY ) - - IF(Wt_FOUND) - IF (NOT Wt_FIND_QUIETLY) - MESSAGE(STATUS "Found the Wt libraries at ${Wt_LIBRARIES}") - MESSAGE(STATUS "Found the Wt headers at ${Wt_INCLUDE_DIR}") - ENDIF (NOT Wt_FIND_QUIETLY) - ELSE(Wt_FOUND) - IF(Wt_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could NOT find Wt") - ENDIF(Wt_FIND_REQUIRED) - ENDIF(Wt_FOUND) - - IF(Wt_DEBUG_FOUND) - IF (NOT Wt_FIND_QUIETLY) - MESSAGE(STATUS "Found the Wt debug libraries at ${Wt_DEBUG_LIBRARIES}") - MESSAGE(STATUS "Found the Wt debug headers at ${Wt_INCLUDE_DIR}") - ENDIF (NOT Wt_FIND_QUIETLY) - ELSE(Wt_DEBUG_FOUND) - IF(Wt_FIND_REQUIRED_Debug) - MESSAGE(FATAL_ERROR "Could NOT find Wt debug libraries") - ENDIF(Wt_FIND_REQUIRED_Debug) - ENDIF(Wt_DEBUG_FOUND) - -ENDIF( Wt_INCLUDE_DIR ) diff --git a/CMakeModules/ParseLibraryList.cmake b/CMakeModules/ParseLibraryList.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/SetupTargetMacros.cmake b/CMakeModules/SetupTargetMacros.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/UseLibraryMacros.cmake b/CMakeModules/UseLibraryMacros.cmake old mode 100644 new mode 100755 diff --git a/CMakeModules/VersionMacros.cmake b/CMakeModules/VersionMacros.cmake old mode 100644 new mode 100755 diff --git a/GitVersionGen/GetGitRevisionDescription.cmake b/GitVersionGen/GetGitRevisionDescription.cmake old mode 100644 new mode 100755 index 00f8727..2b4a479 --- a/GitVersionGen/GetGitRevisionDescription.cmake +++ b/GitVersionGen/GetGitRevisionDescription.cmake @@ -58,7 +58,7 @@ function(get_git_head_revision _refspecvar _hashvar) file(READ ${GIT_DIR} submodule) string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + get_filename_component(GIT_DIR ${GIT_DIR_RELATIVE} ABSOLUTE BASE_DIR ${SUBMODULE_DIR}) endif() set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") if(NOT EXISTS "${GIT_DATA}") diff --git a/GitVersionGen/GetGitRevisionDescription.cmake.in b/GitVersionGen/GetGitRevisionDescription.cmake.in old mode 100644 new mode 100755 diff --git a/README-ecc.md b/README-ecc.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 31b0e44..5e7feef --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ fc == +**NOTE:** This fork reverts upstream commit a421e280488385cab26a42153f7ce3c8d5b6281f to avoid changing the BitShares API. + FC stands for fast-compiling c++ library and provides a set of utility libraries useful for the development of asynchronous libraries. Some of the highlights include: diff --git a/fc.natvis b/fc.natvis old mode 100644 new mode 100755 diff --git a/include/fc/actor.hpp b/include/fc/actor.hpp old mode 100644 new mode 100755 diff --git a/include/fc/aligned.hpp b/include/fc/aligned.hpp old mode 100644 new mode 100755 diff --git a/include/fc/any.hpp b/include/fc/any.hpp old mode 100644 new mode 100755 diff --git a/include/fc/api.hpp b/include/fc/api.hpp old mode 100644 new mode 100755 index e84f50b..06414b1 --- a/include/fc/api.hpp +++ b/include/fc/api.hpp @@ -38,8 +38,33 @@ namespace fc { OtherType& _source; }; + template + class api; + + class api_connection; + + typedef uint32_t api_id_type; + + class api_base + { + public: + api_base() {} + virtual ~api_base() {} + + virtual uint64_t get_handle()const = 0; + + virtual api_id_type register_api( api_connection& conn )const = 0; + + // defined in api_connection.hpp + template< typename T > + api as(); + }; + typedef std::shared_ptr< api_base > api_ptr; + + class api_connection; + template - class api { + class api : public api_base { public: typedef vtable vtable_type; @@ -58,10 +83,12 @@ namespace fc { } api( const api& cpy ):_vtable(cpy._vtable),_data(cpy._data) {} + virtual ~api() {} friend bool operator == ( const api& a, const api& b ) { return a._data == b._data && a._vtable == b._vtable; } friend bool operator != ( const api& a, const api& b ) { return !(a._data == b._data && a._vtable == b._vtable); } - uint64_t get_handle()const { return uint64_t(_data.get()); } + virtual uint64_t get_handle()const override { return uint64_t(_data.get()); } + virtual api_id_type register_api( api_connection& conn )const override; // defined in api_connection.hpp vtable_type& operator*()const { FC_ASSERT( _vtable ); return *_vtable; } vtable_type* operator->()const { FC_ASSERT( _vtable ); return _vtable.get(); } diff --git a/include/fc/array.hpp b/include/fc/array.hpp old mode 100644 new mode 100755 index 6a2053c..8453447 --- a/include/fc/array.hpp +++ b/include/fc/array.hpp @@ -20,11 +20,17 @@ namespace fc { T& at( size_t pos ) { assert( pos < N); return data[pos]; } const T& at( size_t pos )const { assert( pos < N); return data[pos]; } ///@} + + T& operator[]( size_t pos ) { assert( pos < N); return data[pos]; } + const T& operator[]( size_t pos )const { assert( pos < N); return data[pos]; } + - T* begin() { return &data[0]; } const T* begin()const { return &data[0]; } const T* end()const { return &data[N]; } + T* begin() { return &data[0]; } + T* end() { return &data[N]; } + size_t size()const { return N; } T data[N]; diff --git a/include/fc/asio.hpp b/include/fc/asio.hpp old mode 100644 new mode 100755 diff --git a/include/fc/bitutil.hpp b/include/fc/bitutil.hpp old mode 100644 new mode 100755 diff --git a/include/fc/bloom_filter.hpp b/include/fc/bloom_filter.hpp old mode 100644 new mode 100755 diff --git a/include/fc/compress/smaz.hpp b/include/fc/compress/smaz.hpp old mode 100644 new mode 100755 diff --git a/include/fc/compress/zlib.hpp b/include/fc/compress/zlib.hpp old mode 100644 new mode 100755 diff --git a/include/fc/container/deque.hpp b/include/fc/container/deque.hpp old mode 100644 new mode 100755 diff --git a/include/fc/container/deque_fwd.hpp b/include/fc/container/deque_fwd.hpp old mode 100644 new mode 100755 diff --git a/include/fc/container/flat.hpp b/include/fc/container/flat.hpp old mode 100644 new mode 100755 index 8fe606a..48fdf75 --- a/include/fc/container/flat.hpp +++ b/include/fc/container/flat.hpp @@ -30,8 +30,8 @@ namespace fc { value.insert( std::move(tmp) ); } } - template - inline void pack( Stream& s, const flat_map& value ) { + template + inline void pack( Stream& s, const flat_map& value ) { pack( s, unsigned_int((uint32_t)value.size()) ); auto itr = value.begin(); auto end = value.end(); @@ -40,8 +40,8 @@ namespace fc { ++itr; } } - template - inline void unpack( Stream& s, flat_map& value ) + template + inline void unpack( Stream& s, flat_map& value ) { unsigned_int size; unpack( s, size ); value.clear(); @@ -54,6 +54,35 @@ namespace fc { value.insert( std::move(tmp) ); } } + + template + void pack( Stream& s, const bip::vector& value ) { + pack( s, unsigned_int((uint32_t)value.size()) ); + if( !std::is_fundamental::value ) { + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr ); + ++itr; + } + } else { + s.write( (const char*)value.data(), value.size() ); + } + } + + template + void unpack( Stream& s, bip::vector& value ) { + unsigned_int size; + unpack( s, size ); + value.resize( size ); + if( !std::is_fundamental::value ) { + for( auto& item : value ) + unpack( s, item ); + } else { + s.read( (char*)value.data(), value.size() ); + } + } + } // namespace raw @@ -76,8 +105,8 @@ namespace fc { vo.insert( itr->as() ); } - template - void to_variant( const flat_map& var, variant& vo ) + template + void to_variant( const flat_map& var, variant& vo ) { std::vector< variant > vars(var.size()); size_t i = 0; @@ -85,8 +114,8 @@ namespace fc { vars[i] = fc::variant(*itr); vo = vars; } - template - void from_variant( const variant& var, flat_map& vo ) + template + void from_variant( const variant& var, flat_map& vo ) { const variants& vars = var.get_array(); vo.clear(); diff --git a/include/fc/container/flat_fwd.hpp b/include/fc/container/flat_fwd.hpp old mode 100644 new mode 100755 index 999a976..d56323a --- a/include/fc/container/flat_fwd.hpp +++ b/include/fc/container/flat_fwd.hpp @@ -1,21 +1,29 @@ #pragma once #include #include +#include namespace fc { using boost::container::flat_map; using boost::container::flat_set; + namespace bip = boost::interprocess; namespace raw { template void pack( Stream& s, const flat_set& value ); template void unpack( Stream& s, flat_set& value ); - template - void pack( Stream& s, const flat_map& value ); - template - void unpack( Stream& s, flat_map& value ) ; + template + void pack( Stream& s, const flat_map& value ); + template + void unpack(Stream& s, flat_map& value); + + + template + void pack( Stream& s, const bip::vector& value ); + template + void unpack( Stream& s, bip::vector& value ); } // namespace raw } // fc diff --git a/include/fc/crypto/aes.hpp b/include/fc/crypto/aes.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/base32.hpp b/include/fc/crypto/base32.hpp deleted file mode 100644 index 15bf169..0000000 --- a/include/fc/crypto/base32.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -#include - -namespace fc -{ - std::vector from_base32( const fc::string& b32 ); - fc::string to_base32( const std::vector& vec ); - fc::string to_base32( const char* data, size_t len ); -} diff --git a/include/fc/crypto/base36.hpp b/include/fc/crypto/base36.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/base58.hpp b/include/fc/crypto/base58.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/base64.hpp b/include/fc/crypto/base64.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/bigint.hpp b/include/fc/crypto/bigint.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/blowfish.hpp b/include/fc/crypto/blowfish.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/city.hpp b/include/fc/crypto/city.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/dh.hpp b/include/fc/crypto/dh.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/digest.hpp b/include/fc/crypto/digest.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/elliptic.hpp b/include/fc/crypto/elliptic.hpp old mode 100644 new mode 100755 index 99cd68a..bc1eae9 --- a/include/fc/crypto/elliptic.hpp +++ b/include/fc/crypto/elliptic.hpp @@ -25,9 +25,7 @@ namespace fc { typedef fc::array compact_signature; typedef std::vector range_proof_type; typedef fc::array extended_key_data; - typedef fc::sha256 blinded_hash; - typedef fc::sha256 blind_signature; - + /** * @class public_key * @brief contains only the public point of an elliptic curve key. @@ -38,7 +36,6 @@ namespace fc { public_key(); public_key(const public_key& k); ~public_key(); -// bool verify( const fc::sha256& digest, const signature& sig ); public_key_data serialize()const; public_key_point_data serialize_ecc_point()const; @@ -52,8 +49,6 @@ namespace fc { public_key child( const fc::sha256& offset )const; bool valid()const; - /** Computes new pubkey = generator * offset + old pubkey ?! */ -// public_key mult( const fc::sha256& offset )const; /** Computes new pubkey = regenerate(offset).pubkey + old pubkey * = offset * G + 1 * old pubkey ?! */ public_key add( const fc::sha256& offset )const; @@ -123,7 +118,7 @@ namespace fc { fc::sha512 get_shared_secret( const public_key& pub )const; // signature sign( const fc::sha256& digest )const; - compact_signature sign_compact( const fc::sha256& digest )const; + compact_signature sign_compact( const fc::sha256& digest, bool require_canonical = true )const; // bool verify( const fc::sha256& digest, const signature& sig ); public_key get_public_key()const; @@ -164,8 +159,6 @@ namespace fc { fc::string to_base58() const { return str(); } static extended_public_key from_base58( const fc::string& base58 ); - public_key generate_p( int i ) const; - public_key generate_q( int i ) const; private: sha256 c; int child_num, parent_fp; @@ -192,25 +185,10 @@ namespace fc { static extended_private_key generate_master( const fc::string& seed ); static extended_private_key generate_master( const char* seed, uint32_t seed_len ); - // Oleg Andreev's blind signature scheme, - // see http://blog.oleganza.com/post/77474860538/blind-signatures - public_key blind_public_key( const extended_public_key& bob, int i ) const; - blinded_hash blind_hash( const fc::sha256& hash, int i ) const; - blind_signature blind_sign( const blinded_hash& hash, int i ) const; - // WARNING! This may produce non-canonical signatures! - compact_signature unblind_signature( const extended_public_key& bob, - const blind_signature& sig, - const fc::sha256& hash, int i ) const; - private: extended_private_key private_derive_rest( const fc::sha512& hash, int num ) const; - private_key generate_a( int i ) const; - private_key generate_b( int i ) const; - private_key generate_c( int i ) const; - private_key generate_d( int i ) const; - private_key_secret compute_p( int i ) const; - private_key_secret compute_q( int i, const private_key_secret& p ) const; + sha256 c; int child_num, parent_fp; uint8_t depth; @@ -218,8 +196,8 @@ namespace fc { struct range_proof_info { - int exp; - int mantissa; + int64_t exp; + int64_t mantissa; uint64_t min_value; uint64_t max_value; }; diff --git a/include/fc/crypto/hash_ctr_rng.hpp b/include/fc/crypto/hash_ctr_rng.hpp new file mode 100755 index 0000000..878cf77 --- /dev/null +++ b/include/fc/crypto/hash_ctr_rng.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include + +namespace fc { + +/** + * Always returns 0. Useful for testing. + */ +class nullary_rng +{ + public: + nullary_rng() {} + virtual ~nullary_rng() {} + + template< typename T > T operator()( T max ) + { return T(0); } +} ; + +/** + * The hash_ctr_rng generates bits using a hash function in counter (CTR) + * mode. + */ +template +class hash_ctr_rng +{ + public: + hash_ctr_rng( const char* seed, uint64_t counter = 0 ) + : _counter( counter ), _current_offset( 0 ) + { + memcpy( _seed, seed, SeedLength ); + _reset_current_value(); + return; + } + + virtual ~hash_ctr_rng() {} + + uint64_t get_bits( uint8_t count ) + { + uint64_t result = 0; + uint64_t mask = 1; + // grab the requested number of bits + while( count > 0 ) + { + result |= + ( + ( + ( + _current_value.data()[ (_current_offset >> 3) & 0x1F ] + & ( 1 << (_current_offset & 0x07) ) + ) + != 0 + ) ? mask : 0 + ); + mask += mask; + --count; + ++_current_offset; + if( _current_offset == (_current_value.data_size() << 3) ) + { + _counter++; + _current_offset = 0; + _reset_current_value(); + } + } + return result; + } + + uint64_t operator()( uint64_t bound ) + { + if( bound <= 1 ) + return 0; + uint8_t bitcount = boost::multiprecision::detail::find_msb( bound ) + 1; + + // probability of loop exiting is >= 1/2, so probability of + // running N times is bounded above by (1/2)^N + while( true ) + { + uint64_t result = get_bits( bitcount ); + if( result < bound ) + return result; + } + } + + // convenience method which does casting for types other than uint64_t + template< typename T > T operator()( T bound ) + { return (T) ( (*this)(uint64_t( bound )) ); } + + void _reset_current_value() + { + // internal implementation detail, called to update + // _current_value when _counter changes + typename HashClass::encoder enc; + enc.write( _seed , SeedLength ); + enc.write( (char *) &_counter, 8 ); + _current_value = enc.result(); + return; + } + + uint64_t _counter; + char _seed[ SeedLength ]; + HashClass _current_value; + uint16_t _current_offset; + + static const int seed_length = SeedLength; +}; + +} // end namespace fc diff --git a/include/fc/crypto/hex.hpp b/include/fc/crypto/hex.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/hmac.hpp b/include/fc/crypto/hmac.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/md5.hpp b/include/fc/crypto/md5.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/openssl.hpp b/include/fc/crypto/openssl.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/pke.hpp b/include/fc/crypto/pke.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/rand.hpp b/include/fc/crypto/rand.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/ripemd160.hpp b/include/fc/crypto/ripemd160.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/sha1.hpp b/include/fc/crypto/sha1.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/sha224.hpp b/include/fc/crypto/sha224.hpp old mode 100644 new mode 100755 diff --git a/include/fc/crypto/sha256.hpp b/include/fc/crypto/sha256.hpp old mode 100644 new mode 100755 index 87fffa2..39b436b --- a/include/fc/crypto/sha256.hpp +++ b/include/fc/crypto/sha256.hpp @@ -68,15 +68,34 @@ class sha256 friend bool operator > ( const sha256& h1, const sha256& h2 ); friend bool operator < ( const sha256& h1, const sha256& h2 ); - uint32_t pop_count() + uint32_t pop_count()const { return (uint32_t)(__builtin_popcountll(_hash[0]) + __builtin_popcountll(_hash[1]) + __builtin_popcountll(_hash[2]) + __builtin_popcountll(_hash[3])); } - - uint64_t _hash[4]; + + /** + * Count leading zero bits + */ + uint16_t clz()const; + + /** + * Approximate (log_2(x) + 1) * 2**24. + * + * Detailed specs: + * - Return 0 when x == 0. + * - High 8 bits of result simply counts nonzero bits. + * - Low 24 bits of result are the 24 bits of input immediately after the most significant 1 in the input. + * - If above would require reading beyond the end of the input, zeros are used instead. + */ + uint32_t approx_log_32()const; + + void set_to_inverse_approx_log_32( uint32_t x ); + static double inverse_approx_log_32_double( uint32_t x ); + + uint64_t _hash[4]; }; typedef sha256 uint256; @@ -99,5 +118,7 @@ namespace std } }; } + + #include FC_REFLECT_TYPENAME( fc::sha256 ) diff --git a/include/fc/crypto/sha512.hpp b/include/fc/crypto/sha512.hpp old mode 100644 new mode 100755 diff --git a/include/fc/exception/exception.hpp b/include/fc/exception/exception.hpp old mode 100644 new mode 100755 index 35d9f27..6fb66fa --- a/include/fc/exception/exception.hpp +++ b/include/fc/exception/exception.hpp @@ -32,7 +32,6 @@ namespace fc invalid_operation_exception_code = 14, unknown_host_exception_code = 15, null_optional_code = 16, - udt_error_code = 17, aes_error_code = 18, overflow_code = 19, underflow_code = 20, @@ -76,7 +75,7 @@ namespace fc const std::string& what_value = "unspecified"); exception( const exception& e ); exception( exception&& e ); - ~exception(); + virtual ~exception(); const char* name()const throw(); int64_t code()const throw(); @@ -294,7 +293,6 @@ namespace fc FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" ); FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" ); FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" ); - FC_DECLARE_EXCEPTION( udt_exception, udt_error_code, "UDT error" ); FC_DECLARE_EXCEPTION( aes_exception, aes_error_code, "AES error" ); FC_DECLARE_EXCEPTION( overflow_exception, overflow_code, "Integer Overflow" ); FC_DECLARE_EXCEPTION( underflow_exception, underflow_code, "Integer Underflow" ); diff --git a/include/fc/filesystem.hpp b/include/fc/filesystem.hpp old mode 100644 new mode 100755 index 1a16926..7484f2a --- a/include/fc/filesystem.hpp +++ b/include/fc/filesystem.hpp @@ -31,7 +31,7 @@ namespace fc { path(); ~path(); path( const boost::filesystem::path& ); - path( const fc::string& p ); + path( const std::string& p ); /// Constructor to build path using unicode native characters. path(const std::wstring& p); path( const char* ); @@ -54,12 +54,12 @@ namespace fc { fc::path extension()const; fc::path filename()const; fc::path parent_path()const; - fc::string string()const; - fc::string generic_string()const; + std::string string()const; + std::string generic_string()const; /** On windows, returns a path where all path separators are '\' suitable for displaying * to users. On other platforms, it does the same as generic_string() */ - fc::string preferred_string() const; + std::string preferred_string() const; std::wstring wstring() const; std::wstring generic_wstring() const; @@ -77,7 +77,7 @@ namespace fc { * * @note not part of boost::filesystem::path */ - fc::string windows_string()const; + std::string windows_string()const; bool is_relative()const; bool is_absolute()const; diff --git a/include/fc/fixed_string.hpp b/include/fc/fixed_string.hpp new file mode 100755 index 0000000..ca6ea1f --- /dev/null +++ b/include/fc/fixed_string.hpp @@ -0,0 +1,161 @@ +#pragma once +#include + + +namespace fc { + + + /** + * This class is designed to offer in-place memory allocation of a string up to Length equal to + * sizeof(Storage). + * + * The string will serialize the same way as std::string for variant and raw formats + * The string will sort according to the comparison operators defined for Storage, this enables effecient + * sorting. + */ + template > + class fixed_string { + public: + fixed_string(){} + fixed_string( const fixed_string& c ):data(c.data){} + + fixed_string( const std::string& str ) { + if( str.size() <= sizeof(data) ) + memcpy( (char*)&data, str.c_str(), str.size() ); + else { + memcpy( (char*)&data, str.c_str(), sizeof(data) ); + } + } + fixed_string( const char* str ) { + auto l = strlen(str); + if( l <= sizeof(data) ) + memcpy( (char*)&data, str, l ); + else { + memcpy( (char*)&data, str, sizeof(data) ); + } + } + + operator std::string()const { + const char* self = (const char*)&data; + return std::string( self, self + size() ); + } + + uint32_t size()const { + if( *(((const char*)&data)+sizeof(data) - 1) ) + return sizeof(data); + return strnlen( (const char*)&data, sizeof(data) ); + } + uint32_t length()const { return size(); } + + fixed_string& operator=( const fixed_string& str ) { + data = str.data; + return *this; + } + fixed_string& operator=( const char* str ) { + return *this = fixed_string(str); + } + + fixed_string& operator=( const std::string& str ) { + if( str.size() <= sizeof(data) ) { + data = Storage(); + memcpy( (char*)&data, str.c_str(), str.size() ); + } + else { + memcpy( (char*)&data, str.c_str(), sizeof(data) ); + } + return *this; + } + + friend std::string operator + ( const fixed_string& a, const std::string& b ) { + return std::string(a) + b; + } + friend std::string operator + ( const std::string& a, const fixed_string& b ) { + return a + std::string(b); + } + + friend bool operator < ( const fixed_string& a, const fixed_string& b ) { + return a.data < b.data; + } + friend bool operator <= ( const fixed_string& a, const fixed_string& b ) { + return a.data <= b.data; + } + friend bool operator > ( const fixed_string& a, const fixed_string& b ) { + return a.data > b.data; + } + friend bool operator >= ( const fixed_string& a, const fixed_string& b ) { + return a.data >= b.data; + } + friend bool operator == ( const fixed_string& a, const fixed_string& b ) { + return a.data == b.data; + } + friend bool operator != ( const fixed_string& a, const fixed_string& b ) { + return a.data != b.data; + } + //private: + Storage data; + }; + + namespace raw + { + template + inline void pack( Stream& s, const fc::fixed_string& u ) { + unsigned_int size = u.size(); + pack( s, size ); + s.write( (const char*)&u.data, size ); + } + + template + inline void unpack( Stream& s, fc::fixed_string& u ) { + unsigned_int size; + fc::raw::unpack( s, size ); + if( size.value > 0 ) { + if( size.value > sizeof(Storage) ) { + s.read( (char*)&u.data, sizeof(Storage) ); + char buf[1024]; + size_t left = size.value - sizeof(Storage); + while( left >= 1024 ) + { + s.read( buf, 1024 ); + left -= 1024; + } + s.read( buf, left ); + + /* + s.seekp( s.tellp() + (size.value - sizeof(Storage)) ); + char tmp; + size.value -= sizeof(storage); + while( size.value ){ s.read( &tmp, 1 ); --size.value; } + */ + // s.skip( size.value - sizeof(Storage) ); + } else { + s.read( (char*)&u.data, size.value ); + } + } + } + + /* + template + inline void pack( Stream& s, const boost::multiprecision::number& d ) { + s.write( (const char*)&d, sizeof(d) ); + } + + template + inline void unpack( Stream& s, boost::multiprecision::number& u ) { + s.read( (const char*)&u, sizeof(u) ); + } + */ + } +} + +#include +namespace fc { + template + void to_variant( const fixed_string& s, variant& v ) { + v = std::string(s); + } + + template + void from_variant( const variant& v, fixed_string& s ) { + s = v.as_string(); + } +} diff --git a/include/fc/fwd.hpp b/include/fc/fwd.hpp old mode 100644 new mode 100755 diff --git a/include/fc/fwd_impl.hpp b/include/fc/fwd_impl.hpp old mode 100644 new mode 100755 diff --git a/include/fc/git_revision.hpp b/include/fc/git_revision.hpp old mode 100644 new mode 100755 diff --git a/include/fc/interprocess/container.hpp b/include/fc/interprocess/container.hpp new file mode 100755 index 0000000..ed761b8 --- /dev/null +++ b/include/fc/interprocess/container.hpp @@ -0,0 +1,143 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fc { + + namespace bip = boost::interprocess; + + template + void to_variant( const bip::deque< T... >& t, fc::variant& v ) { + std::vector vars(t.size()); + for( size_t i = 0; i < t.size(); ++i ) { + vars[i] = t[i]; + } + v = std::move(vars); + } + + template + void from_variant( const fc::variant& v, bip::deque< T, A... >& d ) { + const variants& vars = v.get_array(); + d.clear(); + d.resize( vars.size() ); + for( uint32_t i = 0; i < vars.size(); ++i ) { + from_variant( vars[i], d[i] ); + } + } + + //bip::map == boost::map + template + void to_variant( const bip::map< K, V, T... >& var, fc::variant& vo ) { + std::vector< variant > vars(var.size()); + size_t i = 0; + for( auto itr = var.begin(); itr != var.end(); ++itr, ++i ) + vars[i] = fc::variant(*itr); + vo = vars; + } +/* + template + void from_variant( const variant& var, bip::map& vo ) + { + const variants& vars = var.get_array(); + vo.clear(); + for( auto itr = vars.begin(); itr != vars.end(); ++itr ) + vo.insert( itr->as< std::pair >() ); Not safe for interprocess. Needs allocator + } +*/ + + template + void to_variant( const bip::vector< T... >& t, fc::variant& v ) { + std::vector vars(t.size()); + for( size_t i = 0; i < t.size(); ++i ) { + vars[i] = t[i]; + } + v = std::move(vars); + } + + template + void from_variant( const fc::variant& v, bip::vector< T, A... >& d ) { + const variants& vars = v.get_array(); + d.clear(); + d.resize( vars.size() ); + for( uint32_t i = 0; i < vars.size(); ++i ) { + from_variant( vars[i], d[i] ); + } + } + + template + void to_variant( const bip::set< T... >& t, fc::variant& v ) { + std::vector vars; + vars.reserve(t.size()); + for( const auto& item : t ) { + vars.emplace_back( item ); + } + v = std::move(vars); + } + +/* + template + void from_variant( const fc::variant& v, bip::set< T, A... >& d ) { + const variants& vars = v.get_array(); + d.clear(); + d.reserve( vars.size() ); + for( uint32_t i = 0; i < vars.size(); ++i ) { + from_variant( vars[i], d[i] ); Not safe for interprocess. Needs allocator + } + } +*/ + + template + void to_variant( const bip::vector& t, fc::variant& v ) + { + if( t.size() ) + v = variant(fc::to_hex(t.data(), t.size())); + else + v = ""; + } + + template + void from_variant( const fc::variant& v, bip::vector& d ) + { + auto str = v.as_string(); + d.resize( str.size() / 2 ); + if( d.size() ) + { + size_t r = fc::from_hex( str, d.data(), d.size() ); + FC_ASSERT( r == d.size() ); + } + // std::string b64 = base64_decode( var.as_string() ); + // vo = std::vector( b64.c_str(), b64.c_str() + b64.size() ); + } + + namespace raw { + namespace bip = boost::interprocess; + + template + inline void pack( Stream& s, const bip::vector& value ) { + pack( s, unsigned_int((uint32_t)value.size()) ); + auto itr = value.begin(); + auto end = value.end(); + while( itr != end ) { + fc::raw::pack( s, *itr ); + ++itr; + } + } + template + inline void unpack( Stream& s, bip::vector& value ) { + unsigned_int size; + unpack( s, size ); + value.clear(); value.resize(size); + for( auto& item : value ) + fc::raw::unpack( s, item ); + } + } +} diff --git a/include/fc/interprocess/file_mapping.hpp b/include/fc/interprocess/file_mapping.hpp old mode 100644 new mode 100755 diff --git a/include/fc/interprocess/file_mutex.hpp b/include/fc/interprocess/file_mutex.hpp new file mode 100755 index 0000000..6041824 --- /dev/null +++ b/include/fc/interprocess/file_mutex.hpp @@ -0,0 +1,44 @@ +#pragma once +#include +#include + +#include + +namespace fc { + class microseconds; + class time_point; + class path; + struct context; + + namespace detail { class file_mutex_impl; } + + /** + * The purpose of this class is to support synchronization of + * processes, threads, and coop-threads. + * + * Before grabbing the lock for a thread or coop, a file_mutex will first + * grab a process-level lock. After grabbing the process level lock, it will + * synchronize in the same way as a local process lock. + */ + class file_mutex { + public: + file_mutex( const fc::path& filename ); + ~file_mutex(); + + bool try_lock(); + bool try_lock_for( const microseconds& rel_time ); + bool try_lock_until( const time_point& abs_time ); + void lock(); + void unlock(); + + void lock_shared(); + void unlock_shared(); + bool try_lock_shared(); + + int readers()const; + + private: + std::unique_ptr my; + }; + +} // namespace fc diff --git a/include/fc/interprocess/iprocess.hpp b/include/fc/interprocess/iprocess.hpp old mode 100644 new mode 100755 diff --git a/include/fc/interprocess/mmap_struct.hpp b/include/fc/interprocess/mmap_struct.hpp old mode 100644 new mode 100755 diff --git a/include/fc/interprocess/process.hpp b/include/fc/interprocess/process.hpp old mode 100644 new mode 100755 diff --git a/include/fc/interprocess/signals.hpp b/include/fc/interprocess/signals.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/buffered_iostream.hpp b/include/fc/io/buffered_iostream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/console.hpp b/include/fc/io/console.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/datastream.hpp b/include/fc/io/datastream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/datastream_back.hpp b/include/fc/io/datastream_back.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/enum_type.hpp b/include/fc/io/enum_type.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/fstream.hpp b/include/fc/io/fstream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/iobuffer.hpp b/include/fc/io/iobuffer.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/iostream.hpp b/include/fc/io/iostream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/json.hpp b/include/fc/io/json.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/json_relaxed.hpp b/include/fc/io/json_relaxed.hpp old mode 100644 new mode 100755 index a3793a4..e4876f2 --- a/include/fc/io/json_relaxed.hpp +++ b/include/fc/io/json_relaxed.hpp @@ -123,6 +123,7 @@ namespace fc { namespace json_relaxed char c2 = in.peek(); if( c2 == q ) { + in.get(); char c3 = in.peek(); if( c3 == q ) { diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp old mode 100644 new mode 100755 index bc5cd22..4e81b30 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -17,6 +17,13 @@ namespace fc { namespace raw { + + template + inline void pack( Stream& s, const Arg0& a0, Args... args ) { + pack( s, a0 ); + pack( s, args... ); + } + template inline void pack( Stream& s, const fc::exception& e ) { @@ -324,13 +331,13 @@ namespace fc { struct if_enum { template static inline void pack( Stream& s, const T& v ) { - fc::raw::pack(s, (int64_t)v); + fc::raw::pack(s, signed_int((int32_t)v)); } template static inline void unpack( Stream& s, T& v ) { - int64_t temp; + signed_int temp; fc::raw::unpack(s, temp); - v = (T)temp; + v = (T)temp.value; } }; @@ -547,6 +554,20 @@ namespace fc { return vec; } + template + inline std::vector pack( const T& v, Next... next ) { + datastream ps; + fc::raw::pack(ps,v,next...); + std::vector vec(ps.tellp()); + + if( vec.size() ) { + datastream ds( vec.data(), size_t(vec.size()) ); + fc::raw::pack(ds,v,next...); + } + return vec; + } + + template inline T unpack( const std::vector& s ) { try { diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp old mode 100644 new mode 100755 index 9192ca3..f397202 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -25,12 +25,22 @@ namespace fc { namespace ip { class endpoint; } namespace ecc { class public_key; class private_key; } + template class fixed_string; + namespace raw { + template + inline size_t pack_size( const T& v ); + + template inline void pack( Stream& s, const fc::fixed_string& u ); + template inline void unpack( Stream& s, fc::fixed_string& u ); + template inline void pack( Stream& s, const fc::enum_type& tp ); template inline void unpack( Stream& s, fc::enum_type& tp ); + + template inline void pack( Stream& s, const std::set& value ); template inline void unpack( Stream& s, std::set& value ); template inline void pack( Stream& s, const std::unordered_set& value ); @@ -51,8 +61,8 @@ namespace fc { template inline void pack( Stream& s, const std::map& value ); template inline void unpack( Stream& s, std::map& value ); - template inline void pack( Stream& s, const flat_map& value ); - template inline void unpack( Stream& s, flat_map& value ); + template inline void pack( Stream& s, const flat_map& value ); + template inline void unpack( Stream& s, flat_map& value ); template inline void pack( Stream& s, const std::pair& value ); template inline void unpack( Stream& s, std::pair& value ); diff --git a/include/fc/io/raw_unpack_file.hpp b/include/fc/io/raw_unpack_file.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/raw_variant.hpp b/include/fc/io/raw_variant.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/sstream.hpp b/include/fc/io/sstream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/stdio.hpp b/include/fc/io/stdio.hpp old mode 100644 new mode 100755 diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/appender.hpp b/include/fc/log/appender.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/console_appender.hpp b/include/fc/log/console_appender.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/file_appender.hpp b/include/fc/log/file_appender.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/gelf_appender.hpp b/include/fc/log/gelf_appender.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/log_message.hpp b/include/fc/log/log_message.hpp old mode 100644 new mode 100755 diff --git a/include/fc/log/logger.hpp b/include/fc/log/logger.hpp old mode 100644 new mode 100755 index 8c1020d..a0e85b3 --- a/include/fc/log/logger.hpp +++ b/include/fc/log/logger.hpp @@ -155,6 +155,15 @@ namespace fc #define FC_FORMAT_ARG_PARAMS( ... )\ BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, __VA_ARGS__ ) +#define fc_ddump( LOGGER, SEQ ) \ + fc_dlog( LOGGER, FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) +#define fc_idump( LOGGER, SEQ ) \ + fc_ilog( LOGGER, FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) +#define fc_wdump( LOGGER, SEQ ) \ + fc_wlog( LOGGER, FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) +#define fc_edump( LOGGER, SEQ ) \ + fc_elog( LOGGER, FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) + #define ddump( SEQ ) \ dlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ) #define idump( SEQ ) \ diff --git a/include/fc/log/logger_config.hpp b/include/fc/log/logger_config.hpp old mode 100644 new mode 100755 diff --git a/include/fc/make_fused.hpp b/include/fc/make_fused.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/gntp.hpp b/include/fc/network/gntp.hpp deleted file mode 100644 index fcfa656..0000000 --- a/include/fc/network/gntp.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include -#include - -namespace fc -{ - namespace detail { - class gntp_icon_impl; - } - class gntp_notifier; - - class gntp_icon { - public: - gntp_icon(const char* buffer, size_t length); - ~gntp_icon(); - private: - std::unique_ptr my; - friend class gntp_notifier; - }; - typedef std::shared_ptr gntp_icon_ptr; - - class gntp_notification_type { - public: - std::string name; - std::string display_name; - bool enabled; - gntp_icon_ptr icon; - }; - typedef std::vector gntp_notification_type_list; - - namespace detail { - class gntp_notifier_impl; - } - - typedef uint160_t gntp_guid; - - class gntp_notifier { - public: - gntp_notifier(const std::string& host_to_notify = "127.0.0.1", uint16_t port = 23053, - const optional& password = optional()); - ~gntp_notifier(); - void set_application_name(std::string application_name); - void set_application_icon(const gntp_icon_ptr& icon); - void register_notifications(); - gntp_guid send_notification(std::string name, std::string title, std::string text, const gntp_icon_ptr& icon = gntp_icon_ptr(), optional coalescingId = optional()); - void add_notification_type(const gntp_notification_type& notificationType); - private: - std::unique_ptr my; - }; - - -} // namespace fc diff --git a/include/fc/network/http/connection.hpp b/include/fc/network/http/connection.hpp old mode 100644 new mode 100755 index 153a47e..7f0707c --- a/include/fc/network/http/connection.hpp +++ b/include/fc/network/http/connection.hpp @@ -40,11 +40,12 @@ namespace fc { struct request { fc::string get_header( const fc::string& key )const; + fc::string remote_endpoint; fc::string method; fc::string domain; fc::string path; - std::vector
headers; - std::vector body; + std::vector
headers; + std::vector body; }; std::vector
parse_urlencoded_params( const fc::string& f ); diff --git a/include/fc/network/http/server.hpp b/include/fc/network/http/server.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/http/websocket.hpp b/include/fc/network/http/websocket.hpp old mode 100644 new mode 100755 index c0c7266..f56b4be --- a/include/fc/network/http/websocket.hpp +++ b/include/fc/network/http/websocket.hpp @@ -29,6 +29,8 @@ namespace fc { namespace http { void set_session_data( fc::any d ){ _session_data = std::move(d); } fc::any& get_session_data() { return _session_data; } + virtual std::string get_request_header(const std::string& key) = 0; + fc::signal closed; private: fc::any _session_data; @@ -76,7 +78,7 @@ namespace fc { namespace http { class websocket_client { public: - websocket_client(); + websocket_client( const std::string& ca_filename = "_default" ); ~websocket_client(); websocket_connection_ptr connect( const std::string& uri ); @@ -88,7 +90,7 @@ namespace fc { namespace http { class websocket_tls_client { public: - websocket_tls_client(); + websocket_tls_client( const std::string& ca_filename = "_default" ); ~websocket_tls_client(); websocket_connection_ptr connect( const std::string& uri ); diff --git a/include/fc/network/ip.hpp b/include/fc/network/ip.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/ntp.hpp b/include/fc/network/ntp.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/rate_limiting.hpp b/include/fc/network/rate_limiting.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/resolve.hpp b/include/fc/network/resolve.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/tcp_socket.hpp b/include/fc/network/tcp_socket.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/tcp_socket_io_hooks.hpp b/include/fc/network/tcp_socket_io_hooks.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/udp_socket.hpp b/include/fc/network/udp_socket.hpp old mode 100644 new mode 100755 diff --git a/include/fc/network/udt_socket.hpp b/include/fc/network/udt_socket.hpp deleted file mode 100644 index 1210427..0000000 --- a/include/fc/network/udt_socket.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -namespace fc { - namespace ip { class endpoint; } - - class udt_socket : public virtual iostream, public noncopyable - { - public: - udt_socket(); - ~udt_socket(); - - void bind( const fc::ip::endpoint& local_endpoint ); - void connect_to( const fc::ip::endpoint& remote_endpoint ); - - fc::ip::endpoint remote_endpoint() const; - fc::ip::endpoint local_endpoint() const; - - using istream::get; - void get( char& c ) - { - read( &c, 1 ); - } - - - /// istream interface - /// @{ - virtual size_t readsome( char* buffer, size_t max ); - virtual size_t readsome( const std::shared_ptr& buf, size_t len, size_t offset ); - virtual bool eof()const; - /// @} - - /// ostream interface - /// @{ - virtual size_t writesome( const char* buffer, size_t len ); - virtual size_t writesome( const std::shared_ptr& buf, size_t len, size_t offset ); - virtual void flush(); - virtual void close(); - /// @} - - void open(); - bool is_open()const; - - private: - friend class udt_server; - int _udt_socket_id; - }; - typedef std::shared_ptr udt_socket_ptr; - - class udt_server : public noncopyable - { - public: - udt_server(); - ~udt_server(); - - void close(); - void accept( udt_socket& s ); - - void listen( const fc::ip::endpoint& ep ); - fc::ip::endpoint local_endpoint() const; - - private: - int _udt_socket_id; - }; - -} // fc diff --git a/include/fc/network/url.hpp b/include/fc/network/url.hpp old mode 100644 new mode 100755 diff --git a/include/fc/noncopyable.hpp b/include/fc/noncopyable.hpp old mode 100644 new mode 100755 diff --git a/include/fc/optional.hpp b/include/fc/optional.hpp old mode 100644 new mode 100755 index dfb725d..bb760a5 --- a/include/fc/optional.hpp +++ b/include/fc/optional.hpp @@ -18,9 +18,11 @@ namespace fc { * fc::optional adds less than 400. */ template - class optional + class optional { public: + typedef T value_type; + optional():_valid(false){} ~optional(){ reset(); } diff --git a/include/fc/platform_independence.hpp b/include/fc/platform_independence.hpp old mode 100644 new mode 100755 diff --git a/include/fc/real128.hpp b/include/fc/real128.hpp old mode 100644 new mode 100755 diff --git a/include/fc/reflect/reflect.hpp b/include/fc/reflect/reflect.hpp old mode 100644 new mode 100755 index 4deea27..45efbe0 --- a/include/fc/reflect/reflect.hpp +++ b/include/fc/reflect/reflect.hpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -111,7 +112,7 @@ void fc::reflector::visit( const Visitor& v ) { \ #define FC_REFLECT_VISIT_ENUM( r, enum_type, elem ) \ - v.TEMPLATE operator()(BOOST_PP_STRINGIZE(elem)); + v.operator()(BOOST_PP_STRINGIZE(elem), int64_t(enum_type::elem) ); #define FC_REFLECT_ENUM_TO_STRING( r, enum_type, elem ) \ case enum_type::elem: return BOOST_PP_STRINGIZE(elem); #define FC_REFLECT_ENUM_TO_FC_STRING( r, enum_type, elem ) \ @@ -119,7 +120,8 @@ void fc::reflector::visit( const Visitor& v ) { \ #define FC_REFLECT_ENUM_FROM_STRING( r, enum_type, elem ) \ if( strcmp( s, BOOST_PP_STRINGIZE(elem) ) == 0 ) return enum_type::elem; - +#define FC_REFLECT_ENUM_FROM_STRING_CASE( r, enum_type, elem ) \ + case enum_type::elem: #define FC_REFLECT_ENUM( ENUM, FIELDS ) \ namespace fc { \ @@ -146,11 +148,37 @@ template<> struct reflector { \ static fc::string to_fc_string(int64_t i) { \ return to_fc_string(ENUM(i)); \ } \ + static ENUM from_int(int64_t i) { \ + ENUM e = ENUM(i); \ + switch( e ) \ + { \ + BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING_CASE, ENUM, FIELDS ) \ + break; \ + default: \ + fc::throw_bad_enum_cast( i, BOOST_PP_STRINGIZE(ENUM) ); \ + } \ + return e;\ + } \ static ENUM from_string( const char* s ) { \ BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_ENUM_FROM_STRING, ENUM, FIELDS ) \ - return ENUM(atoi(s));\ + int64_t i = 0; \ + try \ + { \ + i = boost::lexical_cast(s); \ + } \ + catch( const boost::bad_lexical_cast& e ) \ + { \ + fc::throw_bad_enum_cast( s, BOOST_PP_STRINGIZE(ENUM) ); \ + } \ + return from_int(i); \ + } \ + template< typename Visitor > \ + static void visit( Visitor& v ) \ + { \ + BOOST_PP_SEQ_FOR_EACH( FC_REFLECT_VISIT_ENUM, ENUM, FIELDS ) \ } \ }; \ +template<> struct get_typename { static const char* name() { return BOOST_PP_STRINGIZE(ENUM); } }; \ } /* Note: FC_REFLECT_ENUM previously defined this function, but I don't think it ever diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp old mode 100644 new mode 100755 index 312c927..5cd55c9 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -15,7 +15,7 @@ namespace fc { class exception; namespace ip { class address; } - template class get_typename{}; + template struct get_typename; template<> struct get_typename { static const char* name() { return "int32_t"; } }; template<> struct get_typename { static const char* name() { return "int64_t"; } }; template<> struct get_typename { static const char* name() { return "int16_t"; } }; diff --git a/include/fc/reflect/variant.hpp b/include/fc/reflect/variant.hpp old mode 100644 new mode 100755 index f48fe9a..31bbbdf --- a/include/fc/reflect/variant.hpp +++ b/include/fc/reflect/variant.hpp @@ -88,8 +88,8 @@ namespace fc { if( v.is_string() ) o = fc::reflector::from_string( v.get_string().c_str() ); - else - o = static_cast(v.as_int64()); + else + o = fc::reflector::from_int( v.as_int64() ); } }; diff --git a/include/fc/rpc/api_connection.hpp b/include/fc/rpc/api_connection.hpp old mode 100644 new mode 100755 index c06d2d0..1cd5561 --- a/include/fc/rpc/api_connection.hpp +++ b/include/fc/rpc/api_connection.hpp @@ -12,8 +12,6 @@ namespace fc { class api_connection; - - typedef uint32_t api_id_type; namespace detail { template @@ -68,6 +66,33 @@ namespace fc { }; } + /** + * If api is returned from a remote method, the API is eagerly bound to api of + * the correct type in api_visitor::from_variant(). This binding [1] needs a reference + * to the api_connection, which is made available to from_variant() as a parameter. + * + * However, in the case of a remote method which returns api_base which can subsequently + * be cast by the caller with as, we need to keep track of the connection because + * the binding is done later (when the client code actually calls as). + * + * [1] The binding actually happens in get_remote_api(). + */ + class any_api : public api_base + { + public: + any_api( api_id_type api_id, const std::shared_ptr& con ) + : _api_id(api_id), _api_connection(con) {} + + virtual uint64_t get_handle()const override + { return _api_id; } + + virtual api_id_type register_api( api_connection& conn )const override + { FC_ASSERT( false ); return api_id_type(); } + + api_id_type _api_id; + std::weak_ptr _api_connection; + }; + } // namespace detail class generic_api @@ -143,7 +168,7 @@ namespace fc { struct api_visitor { - api_visitor( generic_api& a, const std::weak_ptr& s ):api(a),_api_con(s){ } + api_visitor( generic_api& a, const std::weak_ptr& s ):_api(a),_api_con(s){ } template std::function to_generic( const std::function(Args...)>& f )const; @@ -151,6 +176,9 @@ namespace fc { template std::function to_generic( const std::function>(Args...)>& f )const; + template + std::function to_generic( const std::function& f )const; + template std::function to_generic( const std::function& f )const; @@ -159,11 +187,11 @@ namespace fc { template void operator()( const char* name, std::function& memb )const { - api._methods.emplace_back( to_generic( memb ) ); - api._by_name[name] = api._methods.size() - 1; + _api._methods.emplace_back( to_generic( memb ) ); + _api._by_name[name] = _api._methods.size() - 1; } - generic_api& api; + generic_api& _api; const std::weak_ptr& _api_con; }; @@ -267,6 +295,17 @@ namespace fc { return con->get_remote_api( v.as_uint64() ); } + static fc::api_ptr from_variant( + const variant& v, + fc::api_ptr* /* used for template deduction */, + const std::shared_ptr& con + ) + { + if( v.is_null() ) + return fc::api_ptr(); + return fc::api_ptr( new detail::any_api( v.as_uint64(), con ) ); + } + template static fc::variant convert_callbacks( const std::shared_ptr&, const T& v ) { @@ -345,7 +384,7 @@ namespace fc { const std::function(Args...)>& f )const { auto api_con = _api_con; - auto gapi = &api; + auto gapi = &_api; return [=]( const variants& args ) { auto con = api_con.lock(); FC_ASSERT( con, "not connected" ); @@ -359,7 +398,7 @@ namespace fc { const std::function>(Args...)>& f )const { auto api_con = _api_con; - auto gapi = &api; + auto gapi = &_api; return [=]( const variants& args )-> fc::variant { auto con = api_con.lock(); FC_ASSERT( con, "not connected" ); @@ -370,10 +409,28 @@ namespace fc { return variant(); }; } + + template + std::function generic_api::api_visitor::to_generic( + const std::function& f )const + { + auto api_con = _api_con; + auto gapi = &_api; + return [=]( const variants& args ) -> fc::variant { + auto con = api_con.lock(); + FC_ASSERT( con, "not connected" ); + + auto api_result = gapi->call_generic( f, args.begin(), args.end() ); + if( !api_result ) + return variant(); + return api_result->register_api( *con ); + }; + } + template std::function generic_api::api_visitor::to_generic( const std::function& f )const { - generic_api* gapi = &api; + generic_api* gapi = &_api; return [f,gapi]( const variants& args ) { return variant( gapi->call_generic( f, args.begin(), args.end() ) ); }; @@ -382,13 +439,47 @@ namespace fc { template std::function generic_api::api_visitor::to_generic( const std::function& f )const { - generic_api* gapi = &api; + generic_api* gapi = &_api; return [f,gapi]( const variants& args ) { gapi->call_generic( f, args.begin(), args.end() ); return variant(); }; } + /** + * It is slightly unclean tight coupling to have this method in the api class. + * It breaks encapsulation by requiring an api class method to have a pointer + * to an api_connection. The reason this is necessary is we have a goal of being + * able to call register_api() on an api through its base class api_base. But + * register_api() must know the template parameters! + * + * The only reasonable way to achieve the goal is to implement register_api() + * as a method in api (which obviously knows the template parameter T), + * then make the implementation accessible through the base class (by making + * it a pure virtual method in the base class which is overridden by the subclass's + * implementation). + */ + template< typename Interface, typename Transform > + api_id_type api< Interface, Transform >::register_api( api_connection& conn )const + { + return conn.register_api( *this ); + } + + template< typename T > + api api_base::as() + { + // TODO: this method should probably be const (if it is not too hard) + api* maybe_requested_type = dynamic_cast< api* >(this); + if( maybe_requested_type != nullptr ) + return *maybe_requested_type; + + detail::any_api* maybe_any = dynamic_cast< detail::any_api* >(this); + FC_ASSERT( maybe_any != nullptr ); + std::shared_ptr< api_connection > api_conn = maybe_any->_api_connection.lock(); + FC_ASSERT( api_conn ); + return api_conn->get_remote_api( maybe_any->_api_id ); + } + namespace detail { template template diff --git a/include/fc/rpc/binary_api_connection.hpp b/include/fc/rpc/binary_api_connection.hpp new file mode 100755 index 0000000..9c9ce2f --- /dev/null +++ b/include/fc/rpc/binary_api_connection.hpp @@ -0,0 +1,532 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +namespace fc { + class binary_api_connection; + + namespace detail { + template + class callback_functor + { + public: + typedef typename std::function::result_type result_type; + + callback_functor( std::weak_ptr< fc::binary_api_connection > con, uint64_t id ) + :_callback_id(id),_binary_api_connection(con){} + + template + result_type operator()( Args... args )const; + + private: + uint64_t _callback_id; + std::weak_ptr< fc::binary_api_connection > _binary_api_connection; + }; + + template + std::function bind_first_arg( const std::function& f, Arg0 a0 ) + { + return [=]( Args... args ) { return f( a0, args... ); }; + } + template + R call_generic( const std::function& f, variants::const_iterator a0, variants::const_iterator e ) + { + return f(); + } + + template + R call_generic( const std::function& f, variants::const_iterator a0, variants::const_iterator e ) + { + FC_ASSERT( a0 != e ); + return call_generic( bind_first_arg( f, a0->as< typename std::decay::type >() ), a0+1, e ); + } + + template + std::function to_generic( const std::function& f ) + { + return [=]( const variants& args ) { + return variant( call_generic( f, args.begin(), args.end() ) ); + }; + } + + template + std::function to_generic( const std::function& f ) + { + return [=]( const variants& args ) { + call_generic( f, args.begin(), args.end() ); + return variant(); + }; + } + + /** + * If api is returned from a remote method, the API is eagerly bound to api of + * the correct type in api_visitor::from_variant(). This binding [1] needs a reference + * to the binary_api_connection, which is made available to from_variant() as a parameter. + * + * However, in the case of a remote method which returns api_base which can subsequently + * be cast by the caller with as, we need to keep track of the connection because + * the binding is done later (when the client code actually calls as). + * + * [1] The binding actually happens in get_remote_api(). + */ + class any_api : public api_base + { + public: + any_api( api_id_type api_id, const std::shared_ptr& con ) + : _api_id(api_id), _binary_api_connection(con) {} + + virtual uint64_t get_handle()const override + { return _api_id; } + + virtual api_id_type register_api( binary_api_connection& conn )const override + { FC_ASSERT( false ); return api_id_type(); } + + api_id_type _api_id; + std::weak_ptr _binary_api_connection; + }; + + } // namespace detail + + class generic_api + { + public: + template + generic_api( const Api& a, const std::shared_ptr& c ); + + generic_api( const generic_api& cpy ) = delete; + + vector call( const string& name, const vector& args ) + { + auto itr = _by_name.find(name); + FC_ASSERT( itr != _by_name.end(), "no method with name '${name}'", ("name",name)("api",_by_name) ); + return call( itr->second, args ); + } + + vector call( uint32_t method_id, const vector& args ) + { + FC_ASSERT( method_id < _methods.size() ); + return _methods[method_id](args); + } + + std::weak_ptr< fc::binary_api_connection > get_connection() + { + return _binary_api_connection; + } + + std::vector get_method_names()const + { + std::vector result; + result.reserve( _by_name.size() ); + for( auto& m : _by_name ) result.push_back(m.first); + return result; + } + + private: + friend struct api_visitor; + + template + std::function bind_first_arg( const std::function& f, Arg0 a0 )const + { + return [=]( Args... args ) { return f( a0, args... ); }; + } + + template + R call_generic( const std::function& f, datastream& ds )const + { + return f(); + } + + template + R call_generic( const std::function,Args...)>& f, datastream& ds ) + { + uint64_t callback_id = 0; + fc::raw::unpack( ds, callback_id ); + detail::callback_functor arg0( get_connection(), callback_id ); + return call_generic( this->bind_first_arg,Args...>( f, std::function(arg0) ), ds ); + } + template + R call_generic( const std::function&,Args...)>& f, fc::datastream& ds ) + { + uint64_t callback_id = 0; + fc::raw::unpack( ds, callback_id ); + detail::callback_functor arg0( get_connection(), callback_id ); + return call_generic( this->bind_first_arg&,Args...>( f, arg0 ), ds ); + } + + template + R call_generic( const std::function& f, fc::datastream& ds ) + { + std::decay::type a0; + fc::raw::unpack( ds, a0 ); + return call_generic( this->bind_first_arg( f, a0 ), ds ); + } + + struct api_visitor + { + api_visitor( generic_api& a, const std::weak_ptr& s ):api(a),_api_con(s){ } + + template + std::function to_generic( const std::function(Args...)>& f )const; + + template + std::function to_generic( const std::function>(Args...)>& f )const; + + template + std::function to_generic( const std::function& f )const; + + template + std::function to_generic( const std::function& f )const; + + template + std::function to_generic( const std::function& f )const; + + template + void operator()( const char* name, std::function& memb )const { + api._methods.emplace_back( to_generic( memb ) ); + api._by_name[name] = api._methods.size() - 1; + } + + generic_api& api; + const std::weak_ptr& _api_con; + }; + + + std::weak_ptr _binary_api_connection; + fc::any _api; + std::map< std::string, uint32_t > _by_name; + std::vector< std::function(const vector&)> > _methods; + }; // class generic_api + + + + class binary_api_connection : public std::enable_shared_from_this + { + public: + typedef std::vector params_type; + typedef std::vector result_type; + + binary_api_connection(){} + virtual ~binary_api_connection(){}; + + + template + api get_remote_api( api_id_type api_id = 0 ) + { + api result; + result->visit( api_visitor( api_id, this->shared_from_this() ) ); + return result; + } + + /** makes calls to the remote server */ + virtual result_type send_call( api_id_type api_id, string method_name, params_type args = params_type() ) = 0; + virtual result_type send_callback( uint64_t callback_id, params_type args = params_type() ) = 0; + virtual void send_notice( uint64_t callback_id, params_type args = params_type() ) = 0; + + result_type receive_call( api_id_type api_id, const string& method_name, const params_type& args = params_type() )const + { + FC_ASSERT( _local_apis.size() > api_id ); + return _local_apis[api_id]->call( method_name, args ); + } + result_type receive_callback( uint64_t callback_id, const params_type& args = params_type() )const + { + FC_ASSERT( _local_callbacks.size() > callback_id ); + return _local_callbacks[callback_id]( args ); + } + void receive_notice( uint64_t callback_id, const params_type& args = params_type() )const + { + FC_ASSERT( _local_callbacks.size() > callback_id ); + _local_callbacks[callback_id]( args ); + } + + template + api_id_type register_api( const Interface& a ) + { + auto handle = a.get_handle(); + auto itr = _handle_to_id.find(handle); + if( itr != _handle_to_id.end() ) return itr->second; + + _local_apis.push_back( std::unique_ptr( new generic_api(a, shared_from_this() ) ) ); + _handle_to_id[handle] = _local_apis.size() - 1; + return _local_apis.size() - 1; + } + + template + uint64_t register_callback( const std::function& cb ) + { + _local_callbacks.push_back( detail::to_generic( cb ) ); + return _local_callbacks.size() - 1; + } + + std::vector get_method_names( api_id_type local_api_id = 0 )const { return _local_apis[local_api_id]->get_method_names(); } + + fc::signal closed; + private: + std::vector< std::unique_ptr > _local_apis; + std::map< uint64_t, api_id_type > _handle_to_id; + std::vector< std::function > _local_callbacks; + + + struct api_visitor + { + uint32_t _api_id; + std::shared_ptr _connection; + + api_visitor( uint32_t api_id, std::shared_ptr con ) + :_api_id(api_id),_connection(std::move(con)) + { + } + + api_visitor() = delete; + + template + static Result from_vector( const vector& v, Result*, const std::shared_ptr& ) + { + return fc::raw::unpack( v ); + } + + template + static fc::api from_vector( const vector& v, + fc::api* /*used for template deduction*/, + const std::shared_ptr& con + ) + { + return con->get_remote_api( fc::raw::unpack( v ) ); + } + + static fc::api_ptr from_vector( + const vector& v, + fc::api_ptr* /* used for template deduction */, + const std::shared_ptr& con + ) + { + return fc::api_ptr( new detail::any_api( fc::raw::unpack(v), con ) ); + } + + template + static result_type convert_callbacks( const std::shared_ptr&, const T& v ) + { + return fc::raw::pack(v); + } + + template + static result_type convert_callbacks( const std::shared_ptr& con, const std::function& v ) + { + return con->register_callback( v ); + } + + template + void operator()( const char* name, std::function& memb )const + { + auto con = _connection; + auto api_id = _api_id; + memb = [con,api_id,name]( Args... args ) { + auto var_result = con->send_call( api_id, name, { convert_callbacks(con,args)...} ); + return from_vector( var_result, (Result*)nullptr, con ); + }; + } + template + void operator()( const char* name, std::function& memb )const + { + auto con = _connection; + auto api_id = _api_id; + memb = [con,api_id,name]( Args... args ) { + con->send_call( api_id, name, { convert_callbacks(con,args)...} ); + }; + } + }; + }; + + class local_binary_api_connection : public binary_api_connection + { + public: + /** makes calls to the remote server */ + virtual result_type send_call( api_id_type api_id, string method_name, params_type args = params_type() ) override + { + FC_ASSERT( _remote_connection ); + return _remote_connection->receive_call( api_id, method_name, std::move(args) ); + } + virtual result_type send_callback( uint64_t callback_id, params_type args = params_type() ) override + { + FC_ASSERT( _remote_connection ); + return _remote_connection->receive_callback( callback_id, args ); + } + virtual void send_notice( uint64_t callback_id, params_type args = params_type() ) override + { + FC_ASSERT( _remote_connection ); + _remote_connection->receive_notice( callback_id, args ); + } + + + void set_remote_connection( const std::shared_ptr& rc ) + { + FC_ASSERT( !_remote_connection ); + FC_ASSERT( rc != this->shared_from_this() ); + _remote_connection = rc; + } + const std::shared_ptr& remote_connection()const { return _remote_connection; } + + std::shared_ptr _remote_connection; + }; + + template + generic_api::generic_api( const Api& a, const std::shared_ptr& c ) + :_binary_api_connection(c),_api(a) + { + boost::any_cast(a)->visit( api_visitor( *this, c ) ); + } + + template + std::function generic_api::api_visitor::to_generic( + const std::function(Args...)>& f )const + { + auto api_con = _api_con; + auto gapi = &api; + return [=]( const params_type& args ) { + auto con = api_con.lock(); + FC_ASSERT( con, "not connected" ); + + fc::raw::datastream ds( args.data(), args.size() ); + auto api_result = gapi->call_generic( f, args ); + return con->register_api( api_result ); + }; + } + template + std::function generic_api::api_visitor::to_generic( + const std::function>(Args...)>& f )const + { + auto api_con = _api_con; + auto gapi = &api; + return [=]( const params_type& args )-> fc::variant { + auto con = api_con.lock(); + FC_ASSERT( con, "not connected" ); + + fc::raw::datastream ds( args.data(), args.size() ); + auto api_result = gapi->call_generic( f, ds ); + if( api_result ) + return con->register_api( *api_result ); + return result_type(); + }; + } + + template + std::function generic_api::api_visitor::to_generic( + const std::function& f )const + { + auto api_con = _api_con; + auto gapi = &api; + return [=]( const variants& args ) -> fc::variant { + auto con = api_con.lock(); + FC_ASSERT( con, "not connected" ); + + fc::raw::datastream ds( args.data(), args.size() ); + auto api_result = gapi->call_generic( f, ds ); + if( !api_result ) + return result_type(); + return api_result->register_api( *con ); + }; + } + + template + std::function generic_api::api_visitor::to_generic( const std::function& f )const + { + generic_api* gapi = &api; + return [f,gapi]( const params_type& args ) { + fc::raw::datastream ds( args.data(), args.size() ); + return fc::raw::pack(gapi->call_generic( f, ds )); + }; + } + + template + std::function generic_api::api_visitor::to_generic( const std::function& f )const + { + generic_api* gapi = &api; + return [f,gapi]( const params_type& args ) { + fc::raw::datastream ds( args.data(), args.size() ); + gapi->call_generic( f, ds ); + return result_type(); + }; + } + + /** + * It is slightly unclean tight coupling to have this method in the api class. + * It breaks encapsulation by requiring an api class method to have a pointer + * to an binary_api_connection. The reason this is necessary is we have a goal of being + * able to call register_api() on an api through its base class api_base. But + * register_api() must know the template parameters! + * + * The only reasonable way to achieve the goal is to implement register_api() + * as a method in api (which obviously knows the template parameter T), + * then make the implementation accessible through the base class (by making + * it a pure virtual method in the base class which is overridden by the subclass's + * implementation). + */ + template< typename Interface, typename Transform > + api_id_type api< Interface, Transform >::register_api( binary_api_connection& conn )const + { + return conn.register_api( *this ); + } + + template< typename T > + api api_base::as() + { + // TODO: this method should probably be const (if it is not too hard) + api* maybe_requested_type = dynamic_cast< api* >(this); + if( maybe_requested_type != nullptr ) + return *maybe_requested_type; + + detail::any_api* maybe_any = dynamic_cast< detail::any_api* >(this); + FC_ASSERT( maybe_any != nullptr ); + std::shared_ptr< binary_api_connection > api_conn = maybe_any->_binary_api_connection.lock(); + FC_ASSERT( api_conn ); + return api_conn->get_remote_api( maybe_any->_api_id ); + } + + namespace detail { + template + template + typename callback_functor::result_type callback_functor::operator()( Args... args )const + { + std::shared_ptr< fc::binary_api_connection > locked = _binary_api_connection.lock(); + // TODO: make new exception type for this instead of recycling eof_exception + if( !locked ) + throw fc::eof_exception(); + + /// TODO------------->>> pack args... + locked->send_callback( _callback_id, fc::raw::pack( args... ) ).template as< result_type >(); + } + + + template + class callback_functor + { + public: + typedef void result_type; + + callback_functor( std::weak_ptr< fc::binary_api_connection > con, uint64_t id ) + :_callback_id(id),_binary_api_connection(con){} + + void operator()( Args... args )const + { + std::shared_ptr< fc::binary_api_connection > locked = _binary_api_connection.lock(); + // TODO: make new exception type for this instead of recycling eof_exception + if( !locked ) + throw fc::eof_exception(); + locked->send_notice( _callback_id, fc::variants{ args... } ); + } + + private: + uint64_t _callback_id; + std::weak_ptr< fc::binary_api_connection > _binary_api_connection; + }; + } // namespace detail + +} // fc diff --git a/include/fc/rpc/bstate.hpp b/include/fc/rpc/bstate.hpp new file mode 100755 index 0000000..b7c74b7 --- /dev/null +++ b/include/fc/rpc/bstate.hpp @@ -0,0 +1,58 @@ +#pragma once +#include +#include +#include +#include + +namespace fc { namespace rpc { + typedef std::vector params_type; + typedef std::vector result_type; + + struct brequest + { + optional id; + std::string method; + params_type params; + }; + + struct bresponse + { + bresponse(){} + bresponse( int64_t i, result_type r ):id(i),result(r){} + bresponse( int64_t i, error_object r ):id(i),error(r){} + int64_t id = 0; + optional result; + optional error; + }; + + /** binary RPC state */ + class bstate + { + public: + typedef std::function method; + ~bstate(); + + void add_method( const fc::string& name, method m ); + void remove_method( const fc::string& name ); + + result_type local_call( const string& method_name, const params_type& args ); + void handle_reply( const bresponse& response ); + + brequest start_remote_call( const string& method_name, params_type args ); + result_type wait_for_response( uint64_t request_id ); + + void close(); + + void on_unhandled( const std::function& unhandled ); + + private: + uint64_t _next_id = 1; + std::unordered_map::ptr> _awaiting; + std::unordered_map _methods; + std::function _unhandled; + }; +} } // namespace fc::rpc + +FC_REFLECT( fc::rpc::brequest, (id)(method)(params) ); +FC_REFLECT( fc::rpc::bresponse, (id)(result)(error) ) + diff --git a/include/fc/rpc/cli.hpp b/include/fc/rpc/cli.hpp old mode 100644 new mode 100755 diff --git a/include/fc/rpc/http_api.hpp b/include/fc/rpc/http_api.hpp old mode 100644 new mode 100755 diff --git a/include/fc/rpc/json_connection.hpp b/include/fc/rpc/json_connection.hpp old mode 100644 new mode 100755 diff --git a/include/fc/rpc/state.hpp b/include/fc/rpc/state.hpp old mode 100644 new mode 100755 index 3c36bcf..e031530 --- a/include/fc/rpc/state.hpp +++ b/include/fc/rpc/state.hpp @@ -23,7 +23,10 @@ namespace fc { namespace rpc { response(){} response( int64_t i, fc::variant r ):id(i),result(r){} response( int64_t i, error_object r ):id(i),error(r){} + response( int64_t i, fc::variant r, string j ):id(i),jsonrpc(j),result(r){} + response( int64_t i, error_object r, string j ):id(i),jsonrpc(j),error(r){} int64_t id = 0; + optional jsonrpc; optional result; optional error; }; @@ -57,4 +60,4 @@ namespace fc { namespace rpc { FC_REFLECT( fc::rpc::request, (id)(method)(params) ); FC_REFLECT( fc::rpc::error_object, (code)(message)(data) ) -FC_REFLECT( fc::rpc::response, (id)(result)(error) ) +FC_REFLECT( fc::rpc::response, (id)(jsonrpc)(result)(error) ) diff --git a/include/fc/rpc/variant_connection.hpp b/include/fc/rpc/variant_connection.hpp old mode 100644 new mode 100755 diff --git a/include/fc/rpc/variant_stream.hpp b/include/fc/rpc/variant_stream.hpp old mode 100644 new mode 100755 diff --git a/include/fc/rpc/websocket_api.hpp b/include/fc/rpc/websocket_api.hpp old mode 100644 new mode 100755 diff --git a/include/fc/safe.hpp b/include/fc/safe.hpp old mode 100644 new mode 100755 diff --git a/include/fc/scoped_exit.hpp b/include/fc/scoped_exit.hpp new file mode 100755 index 0000000..98ec16d --- /dev/null +++ b/include/fc/scoped_exit.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace fc { + + template + class scoped_exit { + public: + template + scoped_exit( C&& c ):callback( std::forward(c) ){} + scoped_exit( scoped_exit&& mv ):callback( std::move( mv.callback ) ){} + + ~scoped_exit() { + try { callback(); } catch( ... ) {} + } + + scoped_exit& operator = ( scoped_exit&& mv ) { + callback = std::move(mv); + return *this; + } + private: + scoped_exit( const scoped_exit& ); + scoped_exit& operator=( const scoped_exit& ); + + Callback callback; + }; + + template + scoped_exit make_scoped_exit( Callback&& c ) { + return scoped_exit( std::forward(c) ); + } + +} diff --git a/include/fc/shared_ptr.hpp b/include/fc/shared_ptr.hpp old mode 100644 new mode 100755 diff --git a/include/fc/signal.hpp b/include/fc/signal.hpp old mode 100644 new mode 100755 diff --git a/include/fc/signals.hpp b/include/fc/signals.hpp old mode 100644 new mode 100755 diff --git a/include/fc/smart_ref_fwd.hpp b/include/fc/smart_ref_fwd.hpp old mode 100644 new mode 100755 diff --git a/include/fc/smart_ref_impl.hpp b/include/fc/smart_ref_impl.hpp old mode 100644 new mode 100755 diff --git a/include/fc/ssh/client.hpp b/include/fc/ssh/client.hpp deleted file mode 100644 index eb24a8e..0000000 --- a/include/fc/ssh/client.hpp +++ /dev/null @@ -1,193 +0,0 @@ -#pragma once -#include -#include -#include - -namespace fc { - class path; - class logger; - namespace ssh { - namespace detail { - class client_impl; - class process_impl; - }; - - enum sftp_file_type { - named_pipe = 0010000, - directory = 0040000, - regular = 0100000, - symlink = 0120000 - }; - - - enum sftp_file_mode { - owner_mask = 0000700, /* RWX mask for owner */ - owner_read = 0000400, /* R for owner */ - owner_write = 0000200, /* W for owner */ - owner_exec = 0000100, /* X for owner */ - group_mask = 0000070, /* RWX mask for group */ - group_read = 0000040, /* R for group */ - group_write = 0000020, /* W for group */ - group_exec = 0000010, /* X for group */ - other_mask = 0000007, /* RWX mask for other */ - other_read = 0000004, /* R for other */ - other_write = 0000002, /* W for other */ - other_exec = 0000001 /* X for other */ - }; - - struct file_attrib { - file_attrib(); - - uint64_t size; - uint32_t uid; - uint32_t gid; - uint32_t permissions; - uint32_t atime; - uint32_t mtime; - - bool exists(); - bool is_file(); - bool is_directory(); - }; - - - /** - * @brief Enables communication over ssh using libssh2. - * - * Because the client creates other resources that depend upon - * it, it can only be created as a std::shared_ptr (aka client::ptr) - * via client::create(); - * - */ - class client - { - public: - enum trace_level { - TRACE_NONE = 0, - TRACE_TRANS = (1<<1), - TRACE_KEX = (1<<2), - TRACE_AUTH = (1<<3), - TRACE_CONN = (1<<4), - TRACE_SCP = (1<<5), - TRACE_SFTP = (1<<6), - TRACE_ERROR = (1<<7), - TRACE_PUBLICKEY = (1<<8), - TRACE_SOCKET = (1<<9) - }; - /** - * Everything but TRACE_ERROR will be logged at fc::log_level::debug, while - * TRACE_ERROR will be logged at fc::log_level::error - * - * @param bitmask comprised of values from trace_level - **/ - void set_trace_level( int bitmask ); - int get_trace_level()const; - - /** - * Override the default logger used by fc::ssh::client - */ - void set_logger( const logger& lgr ); - const logger& get_logger()const; - - /** - * Connect, with no password specified. Authentication will try public key, - * (via agent or explicitly-set key), empty password, then keyboard-interactive - */ - void connect( const fc::string& user, const fc::string& host, uint16_t port = 22); - - /** - * Connect, specifying a password to be used for password authentication - */ - void connect( const fc::string& user, const fc::string& pass, const fc::string& host, uint16_t port = 22); - - /** - * @note THIS METHOD IS DEPRECATED and should be replace with: - * - * ssh::client_ptr sshc = std::make_shared(); - * sshc->connect( ... ) - * ssh::process_ptr proc = std::make_shared( sshc ); - * proc->exec( ... ) - * - * - * @brief execute command on remote machine - * @param pty_type - whether or not to request a PTY when executing this process, this is necessary - * for interactive (non-buffered) IO with the remote process, if left empty no pty will be - * requested - * - * @note Processes launched in this manner will fully buffer stdin and stdout regardless of whether - * the process calls flush(). If you need unbuffered (streaming, realtime) access to standard - * out then you must launch the process via a shell. - ssh::process exec( const fc::string& cmd, const fc::string& pty_type = "" ); - */ - - - /** - * @brief upload a file to remote host - * @param progress a callback to report / cancel upload. - * The callback takes two parameters, bytes sent and file size. To continue the - * transfer, the callback should return true. To cancel the callback should return false. - */ - void scp_send( const fc::path& local_path, const fc::path& remote_path, - std::function progress = [](uint64_t,uint64_t){return true;} ); - - /** - * @brief recursively sends the contents of local_dir to the remote_path - * - * If remote_path ends in '/' then a new directory at remote_path/local_dir.filename() will - * be created, otherwise local_dir / * will be copied to remote_path / * - * - * Progress will be reported as total bytes transferred for all files. - */ - void scp_send_dir( const fc::path& local_dir, const fc::path& remote_path, - std::function progress = [](uint64_t,uint64_t){return true;} ); - - /** - * @pre remote_path is not a directory - * @post remote file is removed from the remote filesystem - */ - void rm( const fc::path& remote_path ); - - /** - * @pre remote_path is a directory - * @post remote directory is removed from the remote filesystem - */ - void rmdir( const fc::path& remote_path ); - - void rmdir_recursive( const fc::path& remote_path ); - - file_attrib stat( const fc::path& remote_path ); - - /** - * @pre all parent directories already exist. - * @pre remote_dir is not exist or is already a directory - * @post remote_dir exists. - */ - void mkdir( const fc::path& remote_dir, int mode = owner_read|owner_write|owner_exec ); - - /** - * Create all parent directories for remote_dir if they do not exist. - * - * @post remote_dir exists. - */ - void create_directories( const fc::path& remote_dir, int mode = owner_read|owner_write|owner_exec ); - - /** - * Sets whether the remote system is believed to be a Windows box (by default, it's - * assumed to be running UNIX. This alters how command-line arguments are quoted - * and possibly how filenames are altered when copying files - */ - void set_remote_system_is_windows(bool is_windows = true); - - void close(); - - client(); - ~client(); - - private: - friend class process; - friend class detail::process_impl; - std::unique_ptr my; - }; - typedef std::shared_ptr client_ptr; - -} } // namespace fc::ssh diff --git a/include/fc/ssh/error.hpp b/include/fc/ssh/error.hpp deleted file mode 100644 index 55eba7c..0000000 --- a/include/fc/ssh/error.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MACE_SSH_ERROR_HPP -#define MACE_SSH_ERROR_HPP -#include -#include - -namespace mace { namespace ssh { -typedef boost::error_info err_msg; - -struct exception : public virtual boost::exception, public virtual std::exception { - const char* what()const throw() { return "exception"; } - virtual void rethrow()const { BOOST_THROW_EXCEPTION(*this); } - const std::string& message()const { return *boost::get_error_info(*this); } -}; - -} } // mace::ssh - -/** - * Helper macro for throwing exceptions with a message: THROW( "Hello World %1%, %2%", %"Hello" %"World" ) - */ -#define MACE_SSH_THROW( MSG, ... ) \ - do { \ - BOOST_THROW_EXCEPTION( mace::ssh::exception() << mace::ssh::err_msg( (boost::format( MSG ) __VA_ARGS__ ).str() ) );\ - } while(0) - -#endif diff --git a/include/fc/ssh/process.hpp b/include/fc/ssh/process.hpp deleted file mode 100644 index 08eb089..0000000 --- a/include/fc/ssh/process.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include - -namespace fc { namespace ssh -{ - - class client; - - namespace detail { - class process_impl; - }; - - /** - * Enables communication with a process executed via - * client::exec(). - * - * Process can only be created by mace::ssh::client. - */ - class process : public iprocess - { - public: - virtual iprocess& exec( const fc::path& exe, std::vector args, - const fc::path& work_dir = fc::path(), exec_opts opts = open_all ); - - /** - * Blocks until the result code of the process has been returned. - */ - virtual int result(); - - - /** - * Not supported. libssh2 does not support sending signals to remote processes. - * closing in_stream() is the best you can do - */ - virtual void kill(); - - - /** - * @brief returns a stream that writes to the process' stdin - */ - virtual fc::buffered_ostream_ptr in_stream(); - - /** - * @brief returns a stream that reads from the process' stdout - */ - virtual fc::buffered_istream_ptr out_stream(); - /** - * @brief returns a stream that reads from the process' stderr - */ - virtual fc::buffered_istream_ptr err_stream(); - - process( fc::ssh::client_ptr c ); - ~process(); - private: - std::unique_ptr my; - }; - -} } // fc::ssh diff --git a/include/fc/static_variant.hpp b/include/fc/static_variant.hpp old mode 100644 new mode 100755 index 9aab790..d6206c2 --- a/include/fc/static_variant.hpp +++ b/include/fc/static_variant.hpp @@ -382,5 +382,5 @@ struct visitor { s.visit( to_static_variant(ar[1]) ); } - template struct get_typename { static const char* name() { return typeid(static_variant).name(); } }; + template struct get_typename { static const char* name() { return typeid(static_variant).name(); } }; } // namespace fc diff --git a/include/fc/string.hpp b/include/fc/string.hpp old mode 100644 new mode 100755 index 0ae999b..dc942b9 --- a/include/fc/string.hpp +++ b/include/fc/string.hpp @@ -29,6 +29,8 @@ namespace fc fc::string trim( const fc::string& ); fc::string to_lower( const fc::string& ); string trim_and_normalize_spaces( const string& s ); + + uint64_t parse_size( const string& s ); } #else diff --git a/include/fc/thread/future.hpp b/include/fc/thread/future.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/mutex.hpp b/include/fc/thread/mutex.hpp old mode 100644 new mode 100755 index 544253e..59f8941 --- a/include/fc/thread/mutex.hpp +++ b/include/fc/thread/mutex.hpp @@ -61,7 +61,7 @@ namespace fc { * * @code * void write_message() { - * boost::unique_lock lock(sock->write_lock); + * boost::unique_lock lock(sock->write_lock); * sock->write(part1); // may yield * sock->write(part2); // may yield * sock->write(part3); // may yield diff --git a/include/fc/thread/non_preemptable_scope_check.hpp b/include/fc/thread/non_preemptable_scope_check.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/priority.hpp b/include/fc/thread/priority.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/scoped_lock.hpp b/include/fc/thread/scoped_lock.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/spin_lock.hpp b/include/fc/thread/spin_lock.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/spin_yield_lock.hpp b/include/fc/thread/spin_yield_lock.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/thread_specific.hpp b/include/fc/thread/thread_specific.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/unique_lock.hpp b/include/fc/thread/unique_lock.hpp old mode 100644 new mode 100755 diff --git a/include/fc/thread/wait_condition.hpp b/include/fc/thread/wait_condition.hpp old mode 100644 new mode 100755 diff --git a/include/fc/time.hpp b/include/fc/time.hpp old mode 100644 new mode 100755 diff --git a/include/fc/tuple.hpp b/include/fc/tuple.hpp old mode 100644 new mode 100755 diff --git a/include/fc/uint128.hpp b/include/fc/uint128.hpp old mode 100644 new mode 100755 diff --git a/include/fc/unique_ptr.hpp b/include/fc/unique_ptr.hpp old mode 100644 new mode 100755 diff --git a/include/fc/utf8.hpp b/include/fc/utf8.hpp old mode 100644 new mode 100755 index 3af2abe..c573029 --- a/include/fc/utf8.hpp +++ b/include/fc/utf8.hpp @@ -8,19 +8,21 @@ namespace fc { -bool is_utf8( const std::string& str ); + std::string prune_invalid_utf8( const std::string& str ); -/** Decodes utf 8 std::string into unicode string. - @param input - input string to be decoded and stored in 'storage' - @param storage - buffer for converted text. Cannot be nullptr. -*/ -void decodeUtf8(const std::string& input, std::wstring* storage); - -/** Encodes given wide (unicode) string into UTF-8 representation. - @param input - input string to be encoded and stored in 'storage' - @param storage - buffer for converted text. Cannot be nullptr. -*/ -void encodeUtf8(const std::wstring& input, std::string* storage); + bool is_utf8( const std::string& str ); + + /** Decodes utf 8 std::string into unicode string. + @param input - input string to be decoded and stored in 'storage' + @param storage - buffer for converted text. Cannot be nullptr. + */ + void decodeUtf8(const std::string& input, std::wstring* storage); + + /** Encodes given wide (unicode) string into UTF-8 representation. + @param input - input string to be encoded and stored in 'storage' + @param storage - buffer for converted text. Cannot be nullptr. + */ + void encodeUtf8(const std::wstring& input, std::string* storage); } /// namespace fc diff --git a/include/fc/utility.hpp b/include/fc/utility.hpp old mode 100644 new mode 100755 diff --git a/include/fc/variant.hpp b/include/fc/variant.hpp old mode 100644 new mode 100755 index 3b86fcb..4b3821c --- a/include/fc/variant.hpp +++ b/include/fc/variant.hpp @@ -88,10 +88,10 @@ namespace fc template void from_variant( const variant& var, std::unordered_map& vo ); - template - void to_variant( const fc::flat_map& var, variant& vo ); - template - void from_variant( const variant& var, fc::flat_map& vo ); + template + void to_variant( const fc::flat_map& var, variant& vo ); + template + void from_variant(const variant& var, flat_map& vo); template void to_variant( const std::map& var, variant& vo ); @@ -307,6 +307,12 @@ namespace fc return tmp; } + template + void as( T& v )const + { + from_variant( *this, v ); + } + variant& operator=( variant&& v ); variant& operator=( const variant& v ); diff --git a/include/fc/variant_object.hpp b/include/fc/variant_object.hpp old mode 100644 new mode 100755 diff --git a/include/fc/vector.hpp b/include/fc/vector.hpp old mode 100644 new mode 100755 diff --git a/include/fc/vector_fwd.hpp b/include/fc/vector_fwd.hpp old mode 100644 new mode 100755 diff --git a/include/fc/wait_any.hpp b/include/fc/wait_any.hpp old mode 100644 new mode 100755 diff --git a/src/asio.cpp b/src/asio.cpp old mode 100644 new mode 100755 index 7843336..870c60a --- a/src/asio.cpp +++ b/src/asio.cpp @@ -92,45 +92,51 @@ namespace fc { struct default_io_service_scope { boost::asio::io_service* io; - boost::thread* asio_thread; + std::vector asio_threads; boost::asio::io_service::work* the_work; default_io_service_scope() { io = new boost::asio::io_service(); the_work = new boost::asio::io_service::work(*io); - asio_thread = new boost::thread( [=]() - { - fc::thread::current().set_name("asio"); - while (!io->stopped()) - { - try - { - io->run(); - } - catch (const fc::exception& e) - { - elog("Caught unhandled exception in asio service loop: ${e}", ("e", e)); - } - catch (const std::exception& e) - { - elog("Caught unhandled exception in asio service loop: ${e}", ("e", e.what())); - } - catch (...) - { - elog("Caught unhandled exception in asio service loop"); - } - } - }); + for( int i = 0; i < 8; ++i ) { + asio_threads.push_back( new boost::thread( [=]() + { + fc::thread::current().set_name("asio"); + while (!io->stopped()) + { + try + { + io->run(); + } + catch (const fc::exception& e) + { + elog("Caught unhandled exception in asio service loop: ${e}", ("e", e)); + } + catch (const std::exception& e) + { + elog("Caught unhandled exception in asio service loop: ${e}", ("e", e.what())); + } + catch (...) + { + elog("Caught unhandled exception in asio service loop"); + } + } + }) ); + } } void cleanup() { delete the_work; io->stop(); - asio_thread->join(); + for( auto asio_thread : asio_threads ) { + asio_thread->join(); + } delete io; - delete asio_thread; + for( auto asio_thread : asio_threads ) { + delete asio_thread; + } } ~default_io_service_scope() @@ -139,10 +145,12 @@ namespace fc { /// If cleanup is true, do not use the return value; it is a null reference boost::asio::io_service& default_io_service(bool cleanup) { - static default_io_service_scope fc_asio_service; - if (cleanup) - fc_asio_service.cleanup(); - return *fc_asio_service.io; + static default_io_service_scope fc_asio_service[1]; + if (cleanup) { + for( int i = 0; i < 1; ++i ) + fc_asio_service[i].cleanup(); + } + return *fc_asio_service[0].io; } namespace tcp { diff --git a/src/byteswap.hpp b/src/byteswap.hpp old mode 100644 new mode 100755 index 1a0e534..e75b8e3 --- a/src/byteswap.hpp +++ b/src/byteswap.hpp @@ -1,6 +1,6 @@ #pragma once -#ifdef _MSC_VER +#ifdef _WIN32 # include # define bswap_64(x) _byteswap_uint64(x) #elif defined(__APPLE__) diff --git a/src/compress/miniz.c b/src/compress/miniz.c old mode 100644 new mode 100755 index 358143a..7123d62 --- a/src/compress/miniz.c +++ b/src/compress/miniz.c @@ -2848,7 +2848,7 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, #include #include - #if defined(_MSC_VER) || defined(__MINGW64__) + #if defined(_MSC_VER) static FILE *mz_fopen(const char *pFilename, const char *pMode) { FILE* pFile = NULL; diff --git a/src/compress/smaz.cpp b/src/compress/smaz.cpp old mode 100644 new mode 100755 diff --git a/src/compress/zlib.cpp b/src/compress/zlib.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/_digest_common.cpp b/src/crypto/_digest_common.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/_digest_common.hpp b/src/crypto/_digest_common.hpp old mode 100644 new mode 100755 diff --git a/src/crypto/_elliptic_impl_priv.hpp b/src/crypto/_elliptic_impl_priv.hpp old mode 100644 new mode 100755 diff --git a/src/crypto/_elliptic_impl_pub.hpp b/src/crypto/_elliptic_impl_pub.hpp old mode 100644 new mode 100755 diff --git a/src/crypto/aes.cpp b/src/crypto/aes.cpp old mode 100644 new mode 100755 index 0704b7b..7564816 --- a/src/crypto/aes.cpp +++ b/src/crypto/aes.cpp @@ -16,8 +16,8 @@ #endif #include -#if defined(_MSC_VER) -# include +#if defined(_WIN32) +# include #endif namespace fc { @@ -396,7 +396,7 @@ boost::mutex* openssl_thread_config::openssl_mutexes = nullptr; unsigned long openssl_thread_config::get_thread_id() { -#ifdef _MSC_VER +#ifdef _WIN32 return (unsigned long)::GetCurrentThreadId(); #else return (unsigned long)(&fc::thread::current()); // TODO: should expose boost thread id diff --git a/src/crypto/base32.cpp b/src/crypto/base32.cpp deleted file mode 100644 index bb5354d..0000000 --- a/src/crypto/base32.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include -namespace fc -{ - std::vector from_base32( const std::string& b32 ) - { - auto len = cyoBase32DecodeGetLength( b32.size() ); - std::vector v(len); - len = cyoBase32Decode( v.data(), b32.c_str(), b32.size() ); - v.resize( len ); - return v; - } - - std::string to_base32( const char* data, size_t len ) - { - auto s = cyoBase32EncodeGetLength(len); - std::vector b32; - b32.resize(s); - cyoBase32Encode( b32.data(), data, len ); - b32.resize( b32.size()-1); // strip the nullterm - return std::string(b32.begin(),b32.end()); - } - - std::string to_base32( const std::vector& vec ) - { - return to_base32( vec.data(), vec.size() ); - } -} diff --git a/src/crypto/base36.cpp b/src/crypto/base36.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/base58.cpp b/src/crypto/base58.cpp old mode 100644 new mode 100755 index e1d5d33..ad1b7de --- a/src/crypto/base58.cpp +++ b/src/crypto/base58.cpp @@ -66,74 +66,72 @@ public: /** C++ wrapper for BIGNUM (OpenSSL bignum) */ -class CBigNum : public BIGNUM +class CBigNum { + BIGNUM* bn; public: CBigNum() - { - BN_init(this); - } + : bn(BN_new()) {} CBigNum(const CBigNum& b) + : CBigNum() { - BN_init(this); - if (!BN_copy(this, &b)) + if (!BN_copy(bn, b.bn)) { - BN_clear_free(this); + BN_clear_free(bn); throw bignum_error("CBigNum::CBigNum(const CBigNum&) : BN_copy failed"); } } CBigNum& operator=(const CBigNum& b) { - if (!BN_copy(this, &b)) + if (!BN_copy(bn, b.bn)) throw bignum_error("CBigNum::operator= : BN_copy failed"); return (*this); } ~CBigNum() { - BN_clear_free(this); + BN_clear_free(bn); } //CBigNum(char n) is not portable. Use 'signed char' or 'unsigned char'. - CBigNum(signed char n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(short n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - //CBigNum(long n) { BN_init(this); if (n >= 0) setulong(n); else setint64(n); } - CBigNum(int64_t n) { BN_init(this); setint64(n); } - CBigNum(unsigned char n) { BN_init(this); setulong(n); } - CBigNum(unsigned short n) { BN_init(this); setulong(n); } - CBigNum(unsigned int n) { BN_init(this); setulong(n); } - //CBigNum(unsigned long n) { BN_init(this); setulong(n); } - CBigNum(uint64_t n) { BN_init(this); setuint64(n); } + CBigNum(signed char n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); } + CBigNum(short n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); } + CBigNum(int n) :CBigNum() { if (n >= 0) setulong(n); else setint64(n); } + CBigNum(int64_t n) :CBigNum() { setint64(n); } + CBigNum(unsigned char n) :CBigNum() { setulong(n); } + CBigNum(unsigned short n) :CBigNum() { setulong(n); } + CBigNum(unsigned int n) :CBigNum() { setulong(n); } + CBigNum(uint64_t n) :CBigNum() { setuint64(n); } + explicit CBigNum(const std::vector& vch) + : CBigNum() { - BN_init(this); setvch(vch); } void setulong(unsigned long n) { - if (!BN_set_word(this, n)) + if (!BN_set_word(bn, n)) throw bignum_error("CBigNum conversion from unsigned long : BN_set_word failed"); } unsigned long getulong() const { - return BN_get_word(this); + return BN_get_word(bn); } unsigned int getuint() const { - return BN_get_word(this); + return BN_get_word(bn); } int getint() const { - unsigned long n = BN_get_word(this); - if (!BN_is_negative(this)) + unsigned long n = BN_get_word(bn); + if (!BN_is_negative(bn)) return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::max() : n); else return (n > (unsigned long)std::numeric_limits::max() ? std::numeric_limits::min() : -(int)n); @@ -171,7 +169,7 @@ public: pch[1] = (nSize >> 16) & 0xff; pch[2] = (nSize >> 8) & 0xff; pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); + BN_mpi2bn(pch, p - pch, bn); } void setuint64(uint64_t n) @@ -198,7 +196,7 @@ public: pch[1] = (nSize >> 16) & 0xff; pch[2] = (nSize >> 8) & 0xff; pch[3] = (nSize) & 0xff; - BN_mpi2bn(pch, p - pch, this); + BN_mpi2bn(pch, p - pch, bn); } @@ -214,16 +212,16 @@ public: vch2[3] = (nSize >> 0) & 0xff; // swap data to big endian reverse_copy(vch.begin(), vch.end(), vch2.begin() + 4); - BN_mpi2bn(&vch2[0], vch2.size(), this); + BN_mpi2bn(&vch2[0], vch2.size(), bn); } std::vector getvch() const { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(bn, NULL); if (nSize <= 4) return std::vector(); std::vector vch(nSize); - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(bn, &vch[0]); vch.erase(vch.begin(), vch.begin() + 4); reverse(vch.begin(), vch.end()); return vch; @@ -237,16 +235,16 @@ public: if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff; if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff; if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff; - BN_mpi2bn(&vch[0], vch.size(), this); + BN_mpi2bn(&vch[0], vch.size(), bn); return *this; } unsigned int GetCompact() const { - unsigned int nSize = BN_bn2mpi(this, NULL); + unsigned int nSize = BN_bn2mpi(bn, NULL); std::vector vch(nSize); nSize -= 4; - BN_bn2mpi(this, &vch[0]); + BN_bn2mpi(bn, &vch[0]); unsigned int nCompact = nSize << 24; if (nSize >= 1) nCompact |= (vch[4] << 16); if (nSize >= 2) nCompact |= (vch[5] << 8); @@ -281,7 +279,7 @@ public: *this += n; } if (fNegative) - *this = 0 - *this; + BN_set_negative(bn, 1); } std::string ToString(int nBase=10) const @@ -291,20 +289,20 @@ public: CBigNum bn0 = 0; std::string str; CBigNum bn = *this; - BN_set_negative(&bn, false); + BN_set_negative(bn.bn, false); CBigNum dv; CBigNum rem; - if (BN_cmp(&bn, &bn0) == 0) + if (BN_cmp(bn.bn, bn0.bn) == 0) return "0"; - while (BN_cmp(&bn, &bn0) > 0) + while (BN_cmp(bn.bn, bn0.bn) > 0) { - if (!BN_div(&dv, &rem, &bn, &bnBase, pctx)) + if (!BN_div(dv.bn, rem.bn, bn.bn, bnBase.bn, pctx)) throw bignum_error("CBigNum::ToString() : BN_div failed"); bn = dv; unsigned int c = rem.getulong(); str += "0123456789abcdef"[c]; } - if (BN_is_negative(this)) + if (BN_is_negative(this->bn)) str += "-"; reverse(str.begin(), str.end()); return str; @@ -319,45 +317,50 @@ public: bool operator!() const { - return BN_is_zero(this); + return BN_is_zero(bn); } CBigNum& operator+=(const CBigNum& b) { - if (!BN_add(this, this, &b)) + if (!BN_add(bn, bn, b.bn)) throw bignum_error("CBigNum::operator+= : BN_add failed"); return *this; } CBigNum& operator-=(const CBigNum& b) { - *this = *this - b; + if (!BN_sub(bn, bn, b.bn)) + throw bignum_error("CBigNum::operator-= : BN_sub failed"); return *this; } CBigNum& operator*=(const CBigNum& b) { CAutoBN_CTX pctx; - if (!BN_mul(this, this, &b, pctx)) + if (!BN_mul(bn, bn, b.bn, pctx)) throw bignum_error("CBigNum::operator*= : BN_mul failed"); return *this; } CBigNum& operator/=(const CBigNum& b) { - *this = *this / b; + CAutoBN_CTX pctx; + if (!BN_div(bn, NULL, bn, b.bn, pctx)) + throw bignum_error("CBigNum::operator/= : BN_div failed"); return *this; } CBigNum& operator%=(const CBigNum& b) { - *this = *this % b; + CAutoBN_CTX pctx; + if (!BN_div(NULL, bn, bn, b.bn, pctx)) + throw bignum_error("CBigNum::operator%= : BN_div failed"); return *this; } CBigNum& operator<<=(unsigned int shift) { - if (!BN_lshift(this, this, shift)) + if (!BN_lshift(bn, bn, shift)) throw bignum_error("CBigNum:operator<<= : BN_lshift failed"); return *this; } @@ -368,13 +371,13 @@ public: // if built on ubuntu 9.04 or 9.10, probably depends on version of openssl CBigNum a = 1; a <<= shift; - if (BN_cmp(&a, this) > 0) + if (BN_cmp(a.bn, bn) > 0) { *this = 0; return *this; } - if (!BN_rshift(this, this, shift)) + if (!BN_rshift(bn, bn, shift)) throw bignum_error("CBigNum:operator>>= : BN_rshift failed"); return *this; } @@ -383,7 +386,7 @@ public: CBigNum& operator++() { // prefix operator - if (!BN_add(this, this, BN_value_one())) + if (!BN_add(bn, bn, BN_value_one())) throw bignum_error("CBigNum::operator++ : BN_add failed"); return *this; } @@ -400,7 +403,7 @@ public: { // prefix operator CBigNum r; - if (!BN_sub(&r, this, BN_value_one())) + if (!BN_sub(r.bn, bn, BN_value_one())) throw bignum_error("CBigNum::operator-- : BN_sub failed"); *this = r; return *this; @@ -414,10 +417,12 @@ public: return ret; } - - friend inline const CBigNum operator-(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator/(const CBigNum& a, const CBigNum& b); - friend inline const CBigNum operator%(const CBigNum& a, const CBigNum& b); + const BIGNUM* to_bignum() const { + return bn; + } + BIGNUM* to_bignum() { + return bn; + } }; @@ -425,7 +430,7 @@ public: inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) { CBigNum r; - if (!BN_add(&r, &a, &b)) + if (!BN_add(r.to_bignum(), a.to_bignum(), b.to_bignum())) throw bignum_error("CBigNum::operator+ : BN_add failed"); return r; } @@ -433,7 +438,7 @@ inline const CBigNum operator+(const CBigNum& a, const CBigNum& b) inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) { CBigNum r; - if (!BN_sub(&r, &a, &b)) + if (!BN_sub(r.to_bignum(), a.to_bignum(), b.to_bignum())) throw bignum_error("CBigNum::operator- : BN_sub failed"); return r; } @@ -441,7 +446,7 @@ inline const CBigNum operator-(const CBigNum& a, const CBigNum& b) inline const CBigNum operator-(const CBigNum& a) { CBigNum r(a); - BN_set_negative(&r, !BN_is_negative(&r)); + BN_set_negative(r.to_bignum(), !BN_is_negative(r.to_bignum())); return r; } @@ -449,7 +454,7 @@ inline const CBigNum operator*(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_mul(&r, &a, &b, pctx)) + if (!BN_mul(r.to_bignum(), a.to_bignum(), b.to_bignum(), pctx)) throw bignum_error("CBigNum::operator* : BN_mul failed"); return r; } @@ -458,7 +463,7 @@ inline const CBigNum operator/(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_div(&r, NULL, &a, &b, pctx)) + if (!BN_div(r.to_bignum(), NULL, a.to_bignum(), b.to_bignum(), pctx)) throw bignum_error("CBigNum::operator/ : BN_div failed"); return r; } @@ -467,7 +472,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) { CAutoBN_CTX pctx; CBigNum r; - if (!BN_mod(&r, &a, &b, pctx)) + if (!BN_mod(r.to_bignum(), a.to_bignum(), b.to_bignum(), pctx)) throw bignum_error("CBigNum::operator% : BN_div failed"); return r; } @@ -475,7 +480,7 @@ inline const CBigNum operator%(const CBigNum& a, const CBigNum& b) inline const CBigNum operator<<(const CBigNum& a, unsigned int shift) { CBigNum r; - if (!BN_lshift(&r, &a, shift)) + if (!BN_lshift(r.to_bignum(), a.to_bignum(), shift)) throw bignum_error("CBigNum:operator<< : BN_lshift failed"); return r; } @@ -487,12 +492,12 @@ inline const CBigNum operator>>(const CBigNum& a, unsigned int shift) return r; } -inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) == 0); } -inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) != 0); } -inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) <= 0); } -inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) >= 0); } -inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) < 0); } -inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(&a, &b) > 0); } +inline bool operator==(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) == 0); } +inline bool operator!=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) != 0); } +inline bool operator<=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) <= 0); } +inline bool operator>=(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) >= 0); } +inline bool operator<(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) < 0); } +inline bool operator>(const CBigNum& a, const CBigNum& b) { return (BN_cmp(a.to_bignum(), b.to_bignum()) > 0); } static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; @@ -522,7 +527,7 @@ inline std::string EncodeBase58(const unsigned char* pbegin, const unsigned char CBigNum rem; while (bn > bn0) { - if (!BN_div(&dv, &rem, &bn, &bn58, pctx)) + if (!BN_div(dv.to_bignum(), rem.to_bignum(), bn.to_bignum(), bn58.to_bignum(), pctx)) throw bignum_error("EncodeBase58 : BN_div failed"); bn = dv; unsigned int c = rem.getulong(); @@ -572,7 +577,7 @@ inline bool DecodeBase58(const char* psz, std::vector& vchRet) break; } bnChar.setulong(p1 - pszBase58); - if (!BN_mul(&bn, &bn, &bn58, pctx)) + if (!BN_mul(bn.to_bignum(), bn.to_bignum(), bn58.to_bignum(), pctx)) throw bignum_error("DecodeBase58 : BN_mul failed"); bn += bnChar; } diff --git a/src/crypto/base64.cpp b/src/crypto/base64.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/bigint.cpp b/src/crypto/bigint.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/blowfish.cpp b/src/crypto/blowfish.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/city.cpp b/src/crypto/city.cpp old mode 100644 new mode 100755 index 18367fb..971b7bd --- a/src/crypto/city.cpp +++ b/src/crypto/city.cpp @@ -75,7 +75,7 @@ static uint32_t UNALIGNED_LOAD32(const char *p) { return result; } -#ifdef _MSC_VER +#ifdef _WIN32 #include #define bswap_32(x) _byteswap_ulong(x) diff --git a/src/crypto/crc.cpp b/src/crypto/crc.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/dh.cpp b/src/crypto/dh.cpp old mode 100644 new mode 100755 index cbd7dcc..7e87437 --- a/src/crypto/dh.cpp +++ b/src/crypto/dh.cpp @@ -12,10 +12,19 @@ namespace fc { bool diffie_hellman::generate_params( int s, uint8_t g ) { - ssl_dh dh = DH_generate_parameters( s, g, NULL, NULL ); + ssl_dh dh(DH_new()); + DH_generate_parameters_ex(dh.obj, s, g, NULL); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const BIGNUM* bn_p; // must not be free'd! + DH_get0_pqg(dh.obj, &bn_p, NULL, NULL); + p.resize( BN_num_bytes( bn_p ) ); + if( p.size() ) + BN_bn2bin( bn_p, (unsigned char*)&p.front() ); +#else p.resize( BN_num_bytes( dh->p ) ); if( p.size() ) BN_bn2bin( dh->p, (unsigned char*)&p.front() ); +#endif this->g = g; return fc::validate( dh, valid ); } @@ -25,8 +34,14 @@ namespace fc { if( !p.size() ) return valid = false; ssl_dh dh = DH_new(); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); + const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); + DH_set0_pqg(dh.obj, bn_p, NULL, bn_g); +#else dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); +#endif return fc::validate( dh, valid ); } @@ -35,8 +50,14 @@ namespace fc { if( !p.size() ) return valid = false; ssl_dh dh = DH_new(); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); + const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); + DH_set0_pqg(dh.obj, bn_p, NULL, bn_g); +#else dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); +#endif if( !fc::validate( dh, valid ) ) { @@ -44,21 +65,42 @@ namespace fc { } DH_generate_key(dh); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + const BIGNUM* bn_pub_key; // must not be free'd! + const BIGNUM* bn_priv_key; // must not be free'd! + DH_get0_key(dh.obj, &bn_pub_key, &bn_priv_key); + pub_key.resize( BN_num_bytes( bn_pub_key ) ); + priv_key.resize( BN_num_bytes( bn_priv_key ) ); + if( pub_key.size() ) + BN_bn2bin( bn_pub_key, (unsigned char*)&pub_key.front() ); + if( priv_key.size() ) + BN_bn2bin( bn_priv_key, (unsigned char*)&priv_key.front() ); +#else pub_key.resize( BN_num_bytes( dh->pub_key ) ); priv_key.resize( BN_num_bytes( dh->priv_key ) ); if( pub_key.size() ) BN_bn2bin( dh->pub_key, (unsigned char*)&pub_key.front() ); if( priv_key.size() ) BN_bn2bin( dh->priv_key, (unsigned char*)&priv_key.front() ); +#endif return true; } bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) { ssl_dh dh = DH_new(); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); + auto bn_pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL ); + auto bn_priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL ); + auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); + DH_set0_pqg(dh.obj, bn_p, NULL, bn_g); + DH_set0_key(dh.obj, bn_pub_key, bn_priv_key); +#else dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL ); dh->pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL ); dh->priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL ); dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL ); +#endif int check; DH_check(dh,&check); diff --git a/src/crypto/elliptic_common.cpp b/src/crypto/elliptic_common.cpp old mode 100644 new mode 100755 index 88228b0..16a57cb --- a/src/crypto/elliptic_common.cpp +++ b/src/crypto/elliptic_common.cpp @@ -5,7 +5,7 @@ #include #include -#ifdef _MSC_VER +#ifdef _WIN32 # include #else # include @@ -231,11 +231,12 @@ namespace fc { namespace ecc { static fc::string _to_base58( const extended_key_data& key ) { - char *buffer = (char*)alloca(key.size() + 4); + size_t buf_len = key.size() + 4; + char *buffer = (char*)alloca(buf_len); memcpy( buffer, key.begin(), key.size() ); fc::sha256 double_hash = fc::sha256::hash( fc::sha256::hash( key.begin(), key.size() )); memcpy( buffer + key.size(), double_hash.data(), 4 ); - return fc::to_base58( buffer, sizeof(buffer) ); + return fc::to_base58( buffer, buf_len ); } static void _parse_extended_data( unsigned char* buffer, fc::string base58 ) @@ -301,9 +302,6 @@ namespace fc { namespace ecc { return extended_public_key( get_public_key(), c, child_num, parent_fp, depth ); } - public_key extended_public_key::generate_p(int i) const { return derive_normal_child(2*i + 0); } - public_key extended_public_key::generate_q(int i) const { return derive_normal_child(2*i + 1); } - extended_private_key extended_private_key::derive_child(int i) const { return i < 0 ? derive_hardened_child(i) : derive_normal_child(i); @@ -346,11 +344,6 @@ namespace fc { namespace ecc { return from_base58( _to_base58( data ) ); } - private_key extended_private_key::generate_a(int i) const { return derive_hardened_child(4*i + 0); } - private_key extended_private_key::generate_b(int i) const { return derive_hardened_child(4*i + 1); } - private_key extended_private_key::generate_c(int i) const { return derive_hardened_child(4*i + 2); } - private_key extended_private_key::generate_d(int i) const { return derive_hardened_child(4*i + 3); } - fc::string extended_private_key::str() const { return _to_base58( serialize_extended() ); diff --git a/src/crypto/elliptic_impl_priv.cpp b/src/crypto/elliptic_impl_priv.cpp old mode 100644 new mode 100755 index ad79ebe..585ffde --- a/src/crypto/elliptic_impl_priv.cpp +++ b/src/crypto/elliptic_impl_priv.cpp @@ -85,7 +85,7 @@ namespace fc { namespace ecc { return secp256k1_nonce_function_default( nonce32, msg32, key32, *extra, nullptr ); } - compact_signature private_key::sign_compact( const fc::sha256& digest )const + compact_signature private_key::sign_compact( const fc::sha256& digest, bool require_canonical )const { FC_ASSERT( my->_key != empty_priv ); compact_signature result; @@ -94,7 +94,7 @@ namespace fc { namespace ecc { do { FC_ASSERT( secp256k1_ecdsa_sign_compact( detail::_get_context(), (unsigned char*) digest.data(), (unsigned char*) result.begin() + 1, (unsigned char*) my->_key.data(), extended_nonce_function, &counter, &recid )); - } while( !public_key::is_canonical( result ) ); + } while( require_canonical && !public_key::is_canonical( result ) ); result.begin()[0] = 27 + 4 + recid; return result; } diff --git a/src/crypto/elliptic_impl_pub.cpp b/src/crypto/elliptic_impl_pub.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/elliptic_mixed.cpp b/src/crypto/elliptic_mixed.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/elliptic_openssl.cpp b/src/crypto/elliptic_openssl.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/elliptic_secp256k1.cpp b/src/crypto/elliptic_secp256k1.cpp old mode 100644 new mode 100755 index f4175d0..515d086 --- a/src/crypto/elliptic_secp256k1.cpp +++ b/src/crypto/elliptic_secp256k1.cpp @@ -12,7 +12,7 @@ #include #include -#ifdef _MSC_VER +#if _WIN32 # include #else # include @@ -185,164 +185,6 @@ namespace fc { namespace ecc { return result; } - static void to_bignum( const unsigned char* in, ssl_bignum& out, unsigned int len ) - { - if ( *in & 0x80 ) - { - unsigned char *buffer = (unsigned char*)alloca(len + 1); - *buffer = 0; - memcpy( buffer + 1, in, len ); - BN_bin2bn( buffer, sizeof(buffer), out ); - } - else - { - BN_bin2bn( in, len, out ); - } - } - - static void to_bignum( const private_key_secret& in, ssl_bignum& out ) - { - to_bignum( (unsigned char*) in.data(), out, in.data_size() ); - } - - static void from_bignum( const ssl_bignum& in, unsigned char* out, unsigned int len ) - { - unsigned int l = BN_num_bytes( in ); - if ( l > len ) - { - unsigned char *buffer = (unsigned char*)alloca(l); - BN_bn2bin( in, buffer ); - memcpy( out, buffer + l - len, len ); - } - else - { - memset( out, 0, len - l ); - BN_bn2bin( in, out + len - l ); - } - } - - static void from_bignum( const ssl_bignum& in, private_key_secret& out ) - { - from_bignum( in, (unsigned char*) out.data(), out.data_size() ); - } - - static void invert( const private_key_secret& in, private_key_secret& out ) - { - ssl_bignum bn_in; - to_bignum( in, bn_in ); - ssl_bignum bn_n; - to_bignum( detail::get_curve_order(), bn_n ); - ssl_bignum bn_inv; - bn_ctx ctx( BN_CTX_new() ); - FC_ASSERT( BN_mod_inverse( bn_inv, bn_in, bn_n, ctx ) ); - from_bignum( bn_inv, out ); - } - - static void to_point( const public_key_data& in, ec_point& out ) - { - bn_ctx ctx( BN_CTX_new() ); - const ec_group& curve = detail::get_curve(); - private_key_secret x; - memcpy( x.data(), in.begin() + 1, x.data_size() ); - ssl_bignum bn_x; - to_bignum( x, bn_x ); - FC_ASSERT( EC_POINT_set_compressed_coordinates_GFp( curve, out, bn_x, *in.begin() & 1, ctx ) > 0 ); - } - - static void from_point( const ec_point& in, public_key_data& out ) - { - bn_ctx ctx( BN_CTX_new() ); - const ec_group& curve = detail::get_curve(); - ssl_bignum bn_x; - ssl_bignum bn_y; - FC_ASSERT( EC_POINT_get_affine_coordinates_GFp( curve, in, bn_x, bn_y, ctx ) > 0 ); - private_key_secret x; - from_bignum( bn_x, x ); - memcpy( out.begin() + 1, x.data(), out.size() - 1 ); - *out.begin() = BN_is_bit_set( bn_y, 0 ) ? 3 : 2; - } - -// static void print(const unsigned char* data) { -// for (int i = 0; i < 32; i++) { -// printf("%02x", *data++); -// } -// } -// -// static void print(private_key_secret key) { -// print((unsigned char*) key.data()); -// } -// -// static void print(public_key_data key) { -// print((unsigned char*) key.begin() + 1); -// } - - static void canonicalize( unsigned char *int256 ) - { - fc::sha256 biggi( (char*) int256, 32 ); - if ( detail::get_half_curve_order() >= biggi ) - { - return; // nothing to do - } - ssl_bignum bn_k; - to_bignum( int256, bn_k, 32 ); - ssl_bignum bn_n; - to_bignum( detail::get_curve_order(), bn_n ); - FC_ASSERT( BN_sub( bn_k, bn_n, bn_k ) ); - from_bignum( bn_k, int256, 32 ); - } - - static public_key compute_k( const private_key_secret& a, const private_key_secret& c, - const public_key& p ) - { - private_key_secret prod = a; - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) c.data() ) > 0 ); - invert( prod, prod ); - public_key_data P = p.serialize(); - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) P.begin(), P.size(), (unsigned char*) prod.data() ) ); -// printf("K: "); print(P); printf("\n"); - return public_key( P ); - } - - static public_key compute_t( const private_key_secret& a, const private_key_secret& b, - const private_key_secret& c, const private_key_secret& d, - const public_key_data& p, const public_key_data& q ) - { - private_key_secret prod; - invert( c, prod ); // prod == c^-1 - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) d.data() ) > 0 ); - // prod == c^-1 * d - - public_key_data accu = p; - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) ); - // accu == prod * P == c^-1 * d * P - - ec_point point_accu( EC_POINT_new( detail::get_curve() ) ); - to_point( accu, point_accu ); - ec_point point_q( EC_POINT_new( detail::get_curve() ) ); - to_point( q, point_q ); - bn_ctx ctx(BN_CTX_new()); - FC_ASSERT( EC_POINT_add( detail::get_curve(), point_accu, point_accu, point_q, ctx ) > 0 ); - from_point( point_accu, accu ); - // accu == c^-1 * a * P + Q - - FC_ASSERT( secp256k1_ec_pubkey_tweak_add( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) b.data() ) ); - // accu == c^-1 * a * P + Q + b*G - - public_key_data k = compute_k( a, c, p ).serialize(); - memcpy( prod.data(), k.begin() + 1, prod.data_size() ); - // prod == Kx - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) prod.data(), (unsigned char*) a.data() ) > 0 ); - // prod == Kx * a - invert( prod, prod ); - // prod == (Kx * a)^-1 - - FC_ASSERT( secp256k1_ec_pubkey_tweak_mul( detail::_get_context(), (unsigned char*) accu.begin(), accu.size(), (unsigned char*) prod.data() ) ); - // accu == (c^-1 * a * P + Q + b*G) * (Kx * a)^-1 - -// printf("T: "); print(accu); printf("\n"); - return public_key( accu ); - } - extended_private_key::extended_private_key( const private_key& k, const sha256& c, int child, int parent, uint8_t depth ) : private_key(k), c(c), child_num(child), parent_fp(parent), depth(depth) { } @@ -358,102 +200,6 @@ namespace fc { namespace ecc { return result; } - public_key extended_private_key::blind_public_key( const extended_public_key& bob, int i ) const - { - private_key_secret a = generate_a(i).get_secret(); - private_key_secret b = generate_b(i).get_secret(); - private_key_secret c = generate_c(i).get_secret(); - private_key_secret d = generate_d(i).get_secret(); - public_key_data p = bob.generate_p(i).serialize(); - public_key_data q = bob.generate_q(i).serialize(); -// printf("a: "); print(a); printf("\n"); -// printf("b: "); print(b); printf("\n"); -// printf("c: "); print(c); printf("\n"); -// printf("d: "); print(d); printf("\n"); -// printf("P: "); print(p); printf("\n"); -// printf("Q: "); print(q); printf("\n"); - return compute_t( a, b, c, d, p, q ); - } - - blinded_hash extended_private_key::blind_hash( const fc::sha256& hash, int i ) const - { - private_key_secret a = generate_a(i).get_secret(); - private_key_secret b = generate_b(i).get_secret(); - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) hash.data() ) > 0 ); - FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) a.data(), (unsigned char*) b.data() ) > 0 ); -// printf("hash: "); print(hash); printf("\n"); -// printf("blinded: "); print(a); printf("\n"); - return a; - } - - private_key_secret extended_private_key::compute_p( int i ) const - { - private_key_secret p_inv = derive_normal_child( 2*i ).get_secret(); - invert( p_inv, p_inv ); -// printf("p: "); print(p_inv); printf("\n"); - return p_inv; - } - - private_key_secret extended_private_key::compute_q( int i, const private_key_secret& p ) const - { - private_key_secret q = derive_normal_child( 2*i + 1 ).get_secret(); - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) q.data(), (unsigned char*) p.data() ) > 0 ); -// printf("q: "); print(q); printf("\n"); - return q; - } - - blind_signature extended_private_key::blind_sign( const blinded_hash& hash, int i ) const - { - private_key_secret p = compute_p( i ); - private_key_secret q = compute_q( i, p ); - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) hash.data() ) > 0 ); - FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) p.data(), (unsigned char*) q.data() ) > 0 ); -// printf("blind_sig: "); print(p); printf("\n"); - return p; - } - - compact_signature extended_private_key::unblind_signature( const extended_public_key& bob, - const blind_signature& sig, - const fc::sha256& hash, - int i ) const - { - private_key_secret a = generate_a(i).get_secret(); - private_key_secret b = generate_b(i).get_secret(); - private_key_secret c = generate_c(i).get_secret(); - private_key_secret d = generate_d(i).get_secret(); - public_key p = bob.generate_p(i); - public_key q = bob.generate_q(i); - public_key_data k = compute_k( a, c, p ); - public_key_data t = compute_t( a, b, c, d, p, q ).serialize(); - - FC_ASSERT( secp256k1_ec_privkey_tweak_mul( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) sig.data() ) > 0 ); - FC_ASSERT( secp256k1_ec_privkey_tweak_add( detail::_get_context(), (unsigned char*) c.data(), (unsigned char*) d.data() ) > 0 ); - - compact_signature result; - memcpy( result.begin() + 1, k.begin() + 1, 32 ); - memcpy( result.begin() + 33, c.data(), 32 ); - canonicalize( result.begin() + 33 ); -// printf("unblinded: "); print(result.begin() + 33); printf("\n"); - for ( int i = 0; i < 4; i++ ) - { - unsigned char pubkey[33]; - int pklen = 33; - if ( secp256k1_ecdsa_recover_compact( detail::_get_context(), (unsigned char*) hash.data(), - (unsigned char*) result.begin() + 1, - pubkey, &pklen, 1, i ) ) - { - if ( !memcmp( t.begin(), pubkey, sizeof(pubkey) ) ) - { - *result.begin() = 27 + 4 + i; - return result; -// } else { -// printf("Candidate: "); print( pubkey ); printf("\n"); - } - } - } - FC_ASSERT( 0, "Failed to unblind - use different i" ); - } - commitment_type blind( const blind_factor_type& blind, uint64_t value ) { commitment_type result; diff --git a/src/crypto/hex.cpp b/src/crypto/hex.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/md5.cpp b/src/crypto/md5.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/openssl.cpp b/src/crypto/openssl.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/pke.cpp b/src/crypto/pke.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/rand.cpp b/src/crypto/rand.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/ripemd160.cpp b/src/crypto/ripemd160.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha1.cpp b/src/crypto/sha1.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha224.cpp b/src/crypto/sha224.cpp old mode 100644 new mode 100755 diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp old mode 100644 new mode 100755 index 9c3b9e6..c1b8235 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -97,7 +98,102 @@ namespace fc { bool operator == ( const sha256& h1, const sha256& h2 ) { return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) == 0; } - + + uint32_t sha256::approx_log_32()const + { + uint16_t lzbits = clz(); + if( lzbits >= 0x100 ) + return 0; + uint8_t nzbits = 0xFF-lzbits; + size_t offset = (size_t) (lzbits >> 3); + uint8_t* my_bytes = (uint8_t*) data(); + size_t n = data_size(); + uint32_t y = (uint32_t( my_bytes[offset ] ) << 0x18) + | (uint32_t(offset+1 < n ? my_bytes[offset+1] : 0) << 0x10) + | (uint32_t(offset+2 < n ? my_bytes[offset+2] : 0) << 0x08) + | (uint32_t(offset+3 < n ? my_bytes[offset+3] : 0) ) + ; + // + // lzbits&7 == 7 : 00000001 iff nzbits&7 == 0 + // lzbits&7 == 6 : 0000001x iff nzbits&7 == 1 + // lzbits&7 == 5 : 000001xx iff nzbits&7 == 2 + // + y >>= (nzbits & 7); + y ^= 1 << 0x18; + y |= uint32_t( nzbits ) << 0x18; + return y; + } + + void sha256::set_to_inverse_approx_log_32( uint32_t x ) + { + uint8_t nzbits = uint8_t( x >> 0x18 ); + _hash[0] = 0; + _hash[1] = 0; + _hash[2] = 0; + _hash[3] = 0; + if( nzbits == 0 ) + return; + uint8_t x0 = uint8_t((x ) & 0xFF); + uint8_t x1 = uint8_t((x >> 0x08) & 0xFF); + uint8_t x2 = uint8_t((x >> 0x10) & 0xFF); + uint8_t* my_bytes = (uint8_t*) data(); + my_bytes[0x1F] = x0; + my_bytes[0x1E] = x1; + my_bytes[0x1D] = x2; + my_bytes[0x1C] = 1; + + if( nzbits <= 0x18 ) + { + (*this) = (*this) >> (0x18 - nzbits); + } + else + (*this) = (*this) << (nzbits - 0x18); + return; + } + + double sha256::inverse_approx_log_32_double( uint32_t x ) + { + uint8_t nzbits = uint8_t( x >> 0x18 ); + if( nzbits == 0 ) + return 0.0; + uint32_t b = 1 << 0x18; + uint32_t y = (x & (b-1)) | b; + return std::ldexp( y, int( nzbits ) - 0x18 ); + } + + uint16_t sha256::clz()const + { + const uint8_t* my_bytes = (uint8_t*) data(); + size_t size = data_size(); + size_t lzbits = 0; + static const uint8_t char2lzbits[] = { + // 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 26 27 28 29 30 31 + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + size_t i = 0; + + while( true ) + { + uint8_t c = my_bytes[i]; + lzbits += char2lzbits[c]; + if( c != 0 ) + break; + ++i; + if( i >= size ) + return 0x100; + } + + return lzbits; + } + void to_variant( const sha256& bi, variant& v ) { v = std::vector( (const char*)&bi, ((const char*)&bi) + sizeof(bi) ); diff --git a/src/crypto/sha512.cpp b/src/crypto/sha512.cpp old mode 100644 new mode 100755 diff --git a/src/exception.cpp b/src/exception.cpp old mode 100644 new mode 100755 index fef482a..0e0b956 --- a/src/exception.cpp +++ b/src/exception.cpp @@ -21,7 +21,6 @@ namespace fc (eof_exception) (unknown_host_exception) (null_optional) - (udt_exception) (aes_exception) (overflow_exception) (underflow_exception) @@ -156,7 +155,7 @@ namespace fc * and other information that is generally only useful for * developers. */ - string exception::to_detail_string( log_level ll )const + string exception::to_detail_string( log_level ll )const { fc::stringstream ss; ss << variant(my->_code).as_string() <<" " << my->_name << ": " <_what<<"\n"; @@ -174,13 +173,14 @@ namespace fc /** * Generates a user-friendly error report. */ - string exception::to_string( log_level ll )const + string exception::to_string( log_level ll )const { fc::stringstream ss; - ss << what() << " (" << variant(my->_code).as_string() <<")\n"; + ss << what() << ":"; for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr ) { - ss << fc::format_string( itr->get_format(), itr->get_data() ) <<"\n"; + if( itr->get_format().size() ) + ss << " " << fc::format_string( itr->get_format(), itr->get_data() ); // ss << " " << itr->get_context().to_string() <<"\n"; } return ss.str(); diff --git a/src/filesystem.cpp b/src/filesystem.cpp old mode 100644 new mode 100755 index a590065..3046d56 --- a/src/filesystem.cpp +++ b/src/filesystem.cpp @@ -11,10 +11,10 @@ #include #include -#ifdef WIN32 -# include -# include -# include +#ifdef _WIN32 +# include +# include +# include #else #include #include @@ -245,10 +245,16 @@ namespace fc { void remove_all( const path& p ) { boost::filesystem::remove_all(p); } void copy( const path& f, const path& t ) { try { - boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) ); + boost::system::error_code ec; + boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t), ec ); + if( ec ) + { + FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${code} : ${message}", + ("srcfile",f)("dstfile",t)("code",ec.value())("message",ec.message()) ); + } } catch ( boost::system::system_error& e ) { FC_THROW( "Copy from ${srcfile} to ${dstfile} failed because ${reason}", - ("srcfile",f)("dstfile",t)("reason",e.what() ) ); + ("srcfile",f)("dstfile",t)("reason",std::string(e.what()) ) ); } catch ( ... ) { FC_THROW( "Copy from ${srcfile} to ${dstfile} failed", ("srcfile",f)("dstfile",t)("inner", fc::except_str() ) ); @@ -262,7 +268,7 @@ namespace fc { catch ( boost::system::system_error& e ) { FC_THROW( "Resize file '${f}' to size ${s} failed: ${reason}", - ("f",f)("s",t)( "reason", e.what() ) ); + ("f",f)("s",t)( "reason", std::string(e.what()) ) ); } catch ( ... ) { @@ -301,13 +307,14 @@ namespace fc { void rename( const path& f, const path& t ) { try { boost::filesystem::rename( boost::filesystem::path(f), boost::filesystem::path(t) ); - } catch ( boost::system::system_error& ) { - try{ - boost::filesystem::copy( boost::filesystem::path(f), boost::filesystem::path(t) ); - boost::filesystem::remove( boost::filesystem::path(f)); - } catch ( boost::system::system_error& e ) { - FC_THROW( "Rename from ${srcfile} to ${dstfile} failed because ${reason}", - ("srcfile",f)("dstfile",t)("reason",e.what() ) ); + } catch ( boost::system::system_error& er ) { + try { + copy( f, t ); + remove( f ); + } catch ( fc::exception& e ) { + FC_RETHROW_EXCEPTION( e, error, + "Rename from ${srcfile} to ${dstfile} failed due to ${reason}, trying to copy then remove", + ("srcfile",f)("dstfile",t)("reason",std::string(er.what())) ); } } catch ( ... ) { FC_THROW( "Rename from ${srcfile} to ${dstfile} failed", diff --git a/src/git_revision.cpp.in b/src/git_revision.cpp.in old mode 100644 new mode 100755 diff --git a/src/interprocess/file_mapping.cpp b/src/interprocess/file_mapping.cpp old mode 100644 new mode 100755 diff --git a/src/interprocess/file_mutex.cpp b/src/interprocess/file_mutex.cpp new file mode 100755 index 0000000..72b142d --- /dev/null +++ b/src/interprocess/file_mutex.cpp @@ -0,0 +1,100 @@ +#include +//#include +#include +#include +#include +#include +#include + +#include +#include + +namespace fc { + namespace bip = boost::interprocess; + + void yield(); + + namespace detail { + class file_mutex_impl { + public: + file_mutex_impl( const char* f ) + :_file_mutex( f ),_reader_count(0){} + + fc::mutex _write_lock; + bip::file_lock _file_mutex; + boost::atomic _reader_count; + }; + } + + file_mutex::file_mutex( const fc::path& file ) + { + my.reset( new detail::file_mutex_impl( file.generic_string().c_str() ) ); + } + + file_mutex::~file_mutex() { + } + + int file_mutex::readers()const { + return my->_reader_count.load(); + } + + bool file_mutex::try_lock() { + return false; + if( my->_write_lock.try_lock() ) { + if( my->_file_mutex.try_lock() ) + return true; + } + if( my->_file_mutex.try_lock() ) { + if( my->_write_lock.try_lock() ) { + return true; + } else { + my->_file_mutex.unlock(); + } + } + return false; + } + + bool file_mutex::try_lock_for( const microseconds& rel_time ) { + return false; + } + + bool file_mutex::try_lock_until( const time_point& abs_time ) { + return false; + } + + void file_mutex::lock() { + my->_write_lock.lock(); + while( my->_reader_count.load() > 0 ) { + fc::usleep( fc::microseconds(10) ); + } + my->_file_mutex.lock(); + } + + void file_mutex::unlock() { + my->_file_mutex.unlock(); + my->_write_lock.unlock(); + } + + void file_mutex::lock_shared() { + bip::scoped_lock< fc::mutex > lock( my->_write_lock ); + if( 0 == my->_reader_count.fetch_add( 1, boost::memory_order_relaxed ) ) + my->_file_mutex.lock_sharable(); + } + + void file_mutex::unlock_shared() { + if( 1 == my->_reader_count.fetch_add( -1, boost::memory_order_relaxed ) ) + my->_file_mutex.unlock_sharable(); + } + + bool file_mutex::try_lock_shared() { + return false; + if( my->_write_lock.try_lock() ) { + if( my->_reader_count.load() == 0 && my->_file_mutex.try_lock_sharable() ) { + my->_reader_count++; + } + my->_write_lock.unlock(); + } + return false; + } + +} // namespace fc diff --git a/src/interprocess/mmap_struct.cpp b/src/interprocess/mmap_struct.cpp old mode 100644 new mode 100755 diff --git a/src/interprocess/process.cpp b/src/interprocess/process.cpp old mode 100644 new mode 100755 diff --git a/src/interprocess/signals.cpp b/src/interprocess/signals.cpp old mode 100644 new mode 100755 diff --git a/src/io/buffered_iostream.cpp b/src/io/buffered_iostream.cpp old mode 100644 new mode 100755 diff --git a/src/io/console.cpp b/src/io/console.cpp old mode 100644 new mode 100755 diff --git a/src/io/datastream.cpp b/src/io/datastream.cpp old mode 100644 new mode 100755 diff --git a/src/io/fstream.cpp b/src/io/fstream.cpp old mode 100644 new mode 100755 diff --git a/src/io/iostream.cpp b/src/io/iostream.cpp old mode 100644 new mode 100755 diff --git a/src/io/json.cpp b/src/io/json.cpp old mode 100644 new mode 100755 index b3f57cc..a53b3a5 --- a/src/io/json.cpp +++ b/src/io/json.cpp @@ -517,24 +517,61 @@ namespace fc { switch( *itr ) { - case '\t': - os << "\\t"; + case '\b': // \x08 + os << "\\b"; break; - case '\n': + case '\f': // \x0c + os << "\\f"; + break; + case '\n': // \x0a os << "\\n"; break; + case '\r': // \x0d + os << "\\r"; + break; + case '\t': // \x09 + os << "\\t"; + break; case '\\': os << "\\\\"; break; - case '\r': - os << "\\r"; - break; - case '\a': - os << "\\a"; - break; case '\"': os << "\\\""; break; + case '\x00': os << "\\u0000"; break; + case '\x01': os << "\\u0001"; break; + case '\x02': os << "\\u0002"; break; + case '\x03': os << "\\u0003"; break; + case '\x04': os << "\\u0004"; break; + case '\x05': os << "\\u0005"; break; + case '\x06': os << "\\u0006"; break; + case '\x07': os << "\\u0007"; break; // \a is not valid JSON + // case '\x08': os << "\\u0008"; break; // \b + // case '\x09': os << "\\u0009"; break; // \t + // case '\x0a': os << "\\u000a"; break; // \n + case '\x0b': os << "\\u000b"; break; + // case '\x0c': os << "\\u000c"; break; // \f + // case '\x0d': os << "\\u000d"; break; // \r + case '\x0e': os << "\\u000e"; break; + case '\x0f': os << "\\u000f"; break; + + case '\x10': os << "\\u0010"; break; + case '\x11': os << "\\u0011"; break; + case '\x12': os << "\\u0012"; break; + case '\x13': os << "\\u0013"; break; + case '\x14': os << "\\u0014"; break; + case '\x15': os << "\\u0015"; break; + case '\x16': os << "\\u0016"; break; + case '\x17': os << "\\u0017"; break; + case '\x18': os << "\\u0018"; break; + case '\x19': os << "\\u0019"; break; + case '\x1a': os << "\\u001a"; break; + case '\x1b': os << "\\u001b"; break; + case '\x1c': os << "\\u001c"; break; + case '\x1d': os << "\\u001d"; break; + case '\x1e': os << "\\u001e"; break; + case '\x1f': os << "\\u001f"; break; + default: os << *itr; //toUTF8( *itr, os ); diff --git a/src/io/sstream.cpp b/src/io/sstream.cpp old mode 100644 new mode 100755 diff --git a/src/io/varint.cpp b/src/io/varint.cpp old mode 100644 new mode 100755 diff --git a/src/log/appender.cpp b/src/log/appender.cpp old mode 100644 new mode 100755 diff --git a/src/log/console_appender.cpp b/src/log/console_appender.cpp old mode 100644 new mode 100755 index c012743..9c55ff0 --- a/src/log/console_appender.cpp +++ b/src/log/console_appender.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace fc { @@ -27,7 +28,7 @@ namespace fc { #endif }; - console_appender::console_appender( const variant& args ) + console_appender::console_appender( const variant& args ) :my(new impl) { configure( args.as() ); @@ -66,7 +67,7 @@ namespace fc { #ifdef WIN32 static WORD #else - static const char* + static const char* #endif get_console_color(console_appender::color::type t ) { switch( t ) { @@ -140,7 +141,7 @@ namespace fc { #endif if( text.size() ) - fprintf( out, "%s", text.c_str() ); //fmt_str.c_str() ); + fprintf( out, "%s", text.c_str() ); //fmt_str.c_str() ); #ifdef WIN32 if (my->console_handle != INVALID_HANDLE_VALUE) diff --git a/src/log/console_defines.h b/src/log/console_defines.h old mode 100644 new mode 100755 diff --git a/src/log/file_appender.cpp b/src/log/file_appender.cpp old mode 100644 new mode 100755 index 204686a..dabdf3f --- a/src/log/file_appender.cpp +++ b/src/log/file_appender.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace fc { diff --git a/src/log/gelf_appender.cpp b/src/log/gelf_appender.cpp old mode 100644 new mode 100755 diff --git a/src/log/log_message.cpp b/src/log/log_message.cpp old mode 100644 new mode 100755 diff --git a/src/log/logger.cpp b/src/log/logger.cpp old mode 100644 new mode 100755 index 8c4f149..4bce5c4 --- a/src/log/logger.cpp +++ b/src/log/logger.cpp @@ -99,8 +99,8 @@ namespace fc { void logger::add_appender( const fc::shared_ptr& a ) { my->_appenders.push_back(a); } -// void logger::remove_appender( const fc::shared_ptr& a ) - // { my->_appenders.erase(a); } + void logger::remove_appender( const fc::shared_ptr& a ) + { my->_appenders.erase(std::remove(my->_appenders.begin(), my->_appenders.end(), a), my->_appenders.end()); } std::vector > logger::get_appenders()const { diff --git a/src/log/logger_config.cpp b/src/log/logger_config.cpp old mode 100644 new mode 100755 diff --git a/src/network/gntp.cpp b/src/network/gntp.cpp deleted file mode 100644 index 89c1735..0000000 --- a/src/network/gntp.cpp +++ /dev/null @@ -1,291 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace fc -{ - namespace detail - { - static std::string calc_sha1_base32_of_buffer(const std::string& buffer) - { - sha1::encoder sha1_encoder; - sha1_encoder.write(buffer.c_str(), buffer.size()); - sha1 sha1_result = sha1_encoder.result(); - string sha1_result_base32 = to_base32((char*)&sha1_result, sizeof(sha1_result)); - return sha1_result_base32.c_str(); - } - - - class gntp_icon_impl - { - public: - std::string _icon_bytes; - std::string _sha1_hash; - - gntp_icon_impl(const char* buffer, size_t length) : - _icon_bytes(buffer, length), - _sha1_hash(calc_sha1_base32_of_buffer(_icon_bytes)) - { - } - }; - - class gntp_notifier_impl - { - public: - gntp_notifier_impl(const std::string& host_to_notify = "127.0.0.1", uint16_t port = 23053, const optional& password = optional()); - - // there's no API to change these right now, it will always notify localhost at the default GNTP port - std::string hostname; - uint16_t port; - optional password; - - std::string application_name; - gntp_icon_ptr application_icon; - - gntp_notification_type_list notification_types; // list of all notification types we're registered to send - - optional endpoint; // cache the last endpoint we've connected to - - bool connection_failed; // true after we've tried to connect and failed - bool is_registered; // true after we've registered - - void send_gntp_message(const std::string& message); - }; - - gntp_notifier_impl::gntp_notifier_impl(const std::string& host_to_notify /* = "127.0.0.1" */, uint16_t port /* = 23053 */, - const optional& password /* = optional() */) : - hostname(host_to_notify), - port(port), - password(password), - connection_failed(false), - is_registered(false) - { - } - - void gntp_notifier_impl::send_gntp_message(const std::string& message) - { - std::shared_ptr sock(new boost::asio::ip::tcp::socket(asio::default_io_service())); - - bool connected = false; - if (endpoint) - { - // we've successfully connected before, connect to the same endpoint that worked last time - try - { - asio::tcp::connect(*sock, *endpoint); - connected = true; - } - catch (exception& er) - { - ilog("Failed to connect to GNTP service using an endpoint that previously worked: ${error_report}", - ("error_report", er.to_detail_string())); - sock->close(); - // clear the cached endpoint and fall through to the full connection procedure - endpoint = optional(); - } - catch (...) - { - ilog("Failed to connect to GNTP service using an endpoint that previously worked"); - sock->close(); - // clear the cached endpoint and fall through to the full connection procedure - endpoint = optional(); - } - } - if (!connected) - { - // do the full connection procedure - auto eps = asio::tcp::resolve(hostname, boost::lexical_cast(port)); - if (eps.size() == 0) - FC_THROW("Unable to resolve host '${host}'", ("host", hostname)); - - for (uint32_t i = 0; i < eps.size(); ++i) - { - try - { - boost::system::error_code ec; - ilog("Attempting to connect to GNTP srvice"); - asio::tcp::connect(*sock, eps[i]); - endpoint = eps[i]; - connected = true; - break; - } - catch (const exception& er) - { - ilog("Failed to connect to GNTP service: ${error_reprot}", - ("error_report", er.to_detail_string()) ); - sock->close(); - } - catch (...) - { - ilog("Failed to connect to GNTP service"); - sock->close(); - } - } - } - if (!connected) - FC_THROW("Unable to connect to any resolved endpoint for ${host}:${port}", - ("host", hostname)("port", port)); - try - { - asio::ostream write_stream(sock); - write_stream.write(message.c_str(), message.size()); - write_stream.flush(); - write_stream.close(); - } - catch (exception& er) - { - FC_RETHROW_EXCEPTION(er, warn, "Caught an exception while sending data to GNTP service"); - } - catch (...) - { - FC_THROW("Caught an exception while sending data to GNTP service"); - } - } - } // end namespace detail - - gntp_icon::gntp_icon(const char* buffer, size_t length) : - my(new detail::gntp_icon_impl(buffer, length)) - { - } - gntp_icon::~gntp_icon() - { - } - - gntp_notifier::gntp_notifier(const std::string& host_to_notify /* = "127.0.0.1" */, uint16_t port /* = 23053 */, - const optional& password /* = optional() */) : - my(new detail::gntp_notifier_impl(host_to_notify, port, password)) - { - } - - gntp_notifier::~gntp_notifier() - { - } - - void gntp_notifier::set_application_name(std::string appName) - { - my->application_name = appName; - } - void gntp_notifier::set_application_icon(const gntp_icon_ptr& icon) - { - my->application_icon = icon; - } - void gntp_notifier::add_notification_type(const gntp_notification_type& notification_type) - { - my->notification_types.push_back(notification_type); - } - - void gntp_notifier::register_notifications() - { - // this call will reset any errors - my->connection_failed = false; - my->is_registered = false; - - std::ostringstream message; - std::set icons_used; - - message << "GNTP/1.0 REGISTER NONE\r\n"; - message << "Application-Name: " << my->application_name << "\r\n"; - if (my->application_icon) - { - message << "Application-Icon: x-growl-resource://" << my->application_icon->my->_sha1_hash << "\r\n"; - icons_used.insert(my->application_icon); - } - - message << "Notifications-Count: " << my->notification_types.size() << "\r\n"; - for (const gntp_notification_type& notification_type : my->notification_types) - { - message << "\r\n"; - message << "Notification-Name: " << notification_type.name << "\r\n"; - if (!notification_type.display_name.empty()) - message << "Notification-Display-Name: " << notification_type.display_name << "\r\n"; - if (notification_type.icon) - { - message << "Notification-Icon: x-growl-resource://" << notification_type.icon->my->_sha1_hash << "\r\n"; - icons_used.insert(notification_type.icon); - } - message << "Notification-Enabled: " << (notification_type.enabled ? "True" : "False") << "\r\n"; - } - if (!icons_used.empty()) - { - message << "\r\n"; - for (const gntp_icon_ptr& icon : icons_used) - { - message << "Identifier: " << icon->my->_sha1_hash << "\r\n"; - message << "Length: " << icon->my->_icon_bytes.size() << "\r\n"; - message << "\r\n"; - message << icon->my->_icon_bytes; - message << "\r\n"; - } - } - - message << "\r\n\r\n"; - try - { - my->send_gntp_message(message.str()); - my->is_registered = true; - } - catch (const exception&) - { - my->connection_failed = true; - } - } - gntp_guid gntp_notifier::send_notification(std::string name, std::string title, std::string text, - const gntp_icon_ptr& icon, optional coalescingId /* = optional() */) - { - if (my->connection_failed) - return gntp_guid(); - if (!my->is_registered) - return gntp_guid(); - - gntp_guid notification_id; - rand_pseudo_bytes(notification_id.data(), 20); - - std::ostringstream message; - message << "GNTP/1.0 NOTIFY NONE"; - if (my->password) - { - char salt[16]; - rand_pseudo_bytes(salt, sizeof(salt)); - std::string salted_password = *my->password + std::string(salt, 16); - sha256 key = sha256::hash(salted_password); - sha256 keyhash = sha256::hash(key.data(), 32); - message << " SHA256:" << boost::to_upper_copy(to_hex(keyhash.data(), 32)) << "." << boost::to_upper_copy(to_hex(salt, sizeof(salt))); - } - message << "\r\n"; - message << "Application-Name: " << my->application_name << "\r\n"; - message << "Notification-Name: " << name << "\r\n"; - message << "Notification-ID: " << notification_id.str() << "\r\n"; - message << "Notification-Coalescing-ID: " << (coalescingId ? coalescingId->str() : notification_id.str()) << "\r\n"; - message << "Notification-Title: " << title << "\r\n"; - message << "Notification-Text: " << text << "\r\n"; - if (icon) - message << "Notification-Icon: x-growl-resource://" << icon->my->_sha1_hash << "\r\n"; - - if (icon) - { - message << "\r\n"; - message << "Identifier: " << icon->my->_sha1_hash << "\r\n"; - message << "Length: " << icon->my->_icon_bytes.size() << "\r\n"; - message << "\r\n"; - message << icon->my->_icon_bytes; - message << "\r\n"; - } - message << "\r\n\r\n"; - my->send_gntp_message(message.str()); - return notification_id; - } - -} // namespace fc \ No newline at end of file diff --git a/src/network/http/http_connection.cpp b/src/network/http/http_connection.cpp old mode 100644 new mode 100755 diff --git a/src/network/http/http_server.cpp b/src/network/http/http_server.cpp old mode 100644 new mode 100755 diff --git a/src/network/http/websocket.cpp b/src/network/http/websocket.cpp old mode 100644 new mode 100755 index ef880ff..9c8981a --- a/src/network/http/websocket.cpp +++ b/src/network/http/websocket.cpp @@ -168,6 +168,11 @@ namespace fc { namespace http { _ws_connection->close(code,reason); } + virtual std::string get_request_header(const std::string& key)override + { + return _ws_connection->get_request_header(key); + } + T _ws_connection; }; @@ -193,7 +198,7 @@ namespace fc { namespace http { _server_thread.async( [&](){ auto current_con = _connections.find(hdl); assert( current_con != _connections.end() ); - idump(("server")(msg->get_payload())); + wdump(("server")(msg->get_payload())); //std::cerr<<"recv: "<get_payload()<<"\n"; auto payload = msg->get_payload(); std::shared_ptr con = current_con->second; @@ -204,6 +209,11 @@ namespace fc { namespace http { }).wait(); }); + _server.set_socket_init_handler( [&](websocketpp::connection_hdl hdl, boost::asio::ip::tcp::socket& s ) { + boost::asio::ip::tcp::no_delay option(true); + s.lowest_layer().set_option(option); + } ); + _server.set_http_handler( [&]( connection_hdl hdl ){ _server_thread.async( [&](){ auto current_con = std::make_shared>( _server.get_con_from_hdl(hdl) ); @@ -336,7 +346,7 @@ namespace fc { namespace http { _on_connection( current_con ); auto con = _server.get_con_from_hdl(hdl); - idump(("server")(con->get_request_body())); + wdump(("server")(con->get_request_body())); auto response = current_con->on_http( con->get_request_body() ); con->set_body( response ); @@ -457,6 +467,7 @@ namespace fc { namespace http { fc::thread& _client_thread; websocket_client_type _client; websocket_connection_ptr _connection; + std::string _uri; }; @@ -466,9 +477,13 @@ namespace fc { namespace http { public: typedef websocket_tls_client_type::message_ptr message_ptr; - websocket_tls_client_impl() + websocket_tls_client_impl( const std::string& ca_filename ) :_client_thread( fc::thread::current() ) { + // ca_filename has special values: + // "_none" disables cert checking (potentially insecure!) + // "_default" uses default CA's provided by OS + _client.clear_access_channels( websocketpp::log::alevel::all ); _client.set_message_handler( [&]( connection_hdl hdl, message_ptr msg ){ _client_thread.async( [&](){ @@ -505,6 +520,22 @@ namespace fc { namespace http { _closed->set_value(); }); + // + // We need ca_filename to be copied into the closure, as the referenced object might be destroyed by the caller by the time + // tls_init_handler() is called. According to [1], capture-by-value results in the desired behavior (i.e. creation of + // a copy which is stored in the closure) on standards compliant compilers, but some compilers on some optimization levels + // are buggy and are not standards compliant in this situation. Also, keep in mind this is the opinion of a single forum + // poster and might be wrong. + // + // To be safe, the following line explicitly creates a non-reference string which is captured by value, which should have the + // correct behavior on all compilers. + // + // [1] http://www.cplusplus.com/forum/general/142165/ + // [2] http://stackoverflow.com/questions/21443023/capturing-a-reference-by-reference-in-a-c11-lambda + // + + std::string ca_filename_copy = ca_filename; + _client.set_tls_init_handler( [=](websocketpp::connection_hdl) { context_ptr ctx = websocketpp::lib::make_shared(boost::asio::ssl::context::tlsv1); try { @@ -512,6 +543,8 @@ namespace fc { namespace http { boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use); + + setup_peer_verify( ctx, ca_filename_copy ); } catch (std::exception& e) { edump((e.what())); std::cout << e.what() << std::endl; @@ -531,12 +564,32 @@ namespace fc { namespace http { _closed->wait(); } } + + std::string get_host()const + { + return websocketpp::uri( _uri ).get_host(); + } + + void setup_peer_verify( context_ptr& ctx, const std::string& ca_filename ) + { + if( ca_filename == "_none" ) + return; + ctx->set_verify_mode( boost::asio::ssl::verify_peer ); + if( ca_filename == "_default" ) + ctx->set_default_verify_paths(); + else + ctx->load_verify_file( ca_filename ); + ctx->set_verify_depth(10); + ctx->set_verify_callback( boost::asio::ssl::rfc2818_verification( get_host() ) ); + } + bool _shutting_down = false; fc::promise::ptr _connected; fc::promise::ptr _closed; fc::thread& _client_thread; - websocket_tls_client_type _client; + websocket_tls_client_type _client; websocket_connection_ptr _connection; + std::string _uri; }; @@ -588,12 +641,12 @@ namespace fc { namespace http { } - websocket_tls_client::websocket_tls_client():my( new detail::websocket_tls_client_impl() ) {} + websocket_tls_client::websocket_tls_client( const std::string& ca_filename ):my( new detail::websocket_tls_client_impl( ca_filename ) ) {} websocket_tls_client::~websocket_tls_client(){ } - websocket_client::websocket_client():my( new detail::websocket_client_impl() ),smy(new detail::websocket_tls_client_impl()) {} + websocket_client::websocket_client( const std::string& ca_filename ):my( new detail::websocket_client_impl() ),smy(new detail::websocket_tls_client_impl( ca_filename )) {} websocket_client::~websocket_client(){ } websocket_connection_ptr websocket_client::connect( const std::string& uri ) @@ -605,6 +658,7 @@ namespace fc { namespace http { // wlog( "connecting to ${uri}", ("uri",uri)); websocketpp::lib::error_code ec; + my->_uri = uri; my->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); my->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ @@ -631,6 +685,7 @@ namespace fc { namespace http { // wlog( "connecting to ${uri}", ("uri",uri)); websocketpp::lib::error_code ec; + smy->_uri = uri; smy->_connected = fc::promise::ptr( new fc::promise("websocket::connect") ); smy->_client.set_open_handler( [=]( websocketpp::connection_hdl hdl ){ diff --git a/src/network/ip.cpp b/src/network/ip.cpp old mode 100644 new mode 100755 diff --git a/src/network/ntp.cpp b/src/network/ntp.cpp old mode 100644 new mode 100755 diff --git a/src/network/rate_limiting.cpp b/src/network/rate_limiting.cpp old mode 100644 new mode 100755 diff --git a/src/network/resolve.cpp b/src/network/resolve.cpp old mode 100644 new mode 100755 diff --git a/src/network/tcp_socket.cpp b/src/network/tcp_socket.cpp old mode 100644 new mode 100755 index cb96bbb..b40f496 --- a/src/network/tcp_socket.cpp +++ b/src/network/tcp_socket.cpp @@ -8,7 +8,7 @@ #include #if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT -# include +# include #endif namespace fc { @@ -154,12 +154,12 @@ namespace fc { { try { - my->_sock.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(local_endpoint.get_address()), + my->_sock.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(local_endpoint.get_address()), local_endpoint.port())); } catch (const std::exception& except) { - elog("Exception binding outgoing connection to desired local endpoint: ${what}", ("what", except.what())); + elog("Exception binding outgoing connection to desired local endpoint ${endpoint}: ${what}", ("endpoint", local_endpoint)("what", except.what())); FC_THROW("error binding to ${endpoint}: ${what}", ("endpoint", local_endpoint)("what", except.what())); } } @@ -177,13 +177,13 @@ namespace fc { keepalive_settings.keepaliveinterval = (ULONG)(interval.count() / fc::milliseconds(1).count()); DWORD dwBytesRet = 0; - if (WSAIoctl(my->_sock.native(), SIO_KEEPALIVE_VALS, &keepalive_settings, sizeof(keepalive_settings), + if (WSAIoctl(my->_sock.native_handle(), SIO_KEEPALIVE_VALS, &keepalive_settings, sizeof(keepalive_settings), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) wlog("Error setting TCP keepalive values"); #elif !defined(__clang__) || (__clang_major__ >= 6) // This should work for modern Linuxes and for OSX >= Mountain Lion int timeout_sec = interval.count() / fc::seconds(1).count(); - if (setsockopt(my->_sock.native(), IPPROTO_TCP, + if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, #if defined( __APPLE__ ) TCP_KEEPALIVE, #else @@ -192,7 +192,7 @@ namespace fc { (char*)&timeout_sec, sizeof(timeout_sec)) < 0) wlog("Error setting TCP keepalive idle time"); # if !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9 - if (setsockopt(my->_sock.native(), IPPROTO_TCP, TCP_KEEPINTVL, + if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, TCP_KEEPINTVL, (char*)&timeout_sec, sizeof(timeout_sec)) < 0) wlog("Error setting TCP keepalive interval"); # endif // !__APPLE__ || TCP_KEEPINTVL @@ -224,7 +224,7 @@ namespace fc { if (detail::have_so_reuseport) { int reuseport_value = 1; - if (setsockopt(my->_sock.native(), SOL_SOCKET, SO_REUSEPORT, + if (setsockopt(my->_sock.native_handle(), SOL_SOCKET, SO_REUSEPORT, (char*)&reuseport_value, sizeof(reuseport_value)) < 0) { if (errno == ENOPROTOOPT) @@ -291,7 +291,7 @@ namespace fc { if (detail::have_so_reuseport) { int reuseport_value = 1; - if (setsockopt(my->_accept.native(), SOL_SOCKET, SO_REUSEPORT, + if (setsockopt(my->_accept.native_handle(), SOL_SOCKET, SO_REUSEPORT, (char*)&reuseport_value, sizeof(reuseport_value)) < 0) { if (errno == ENOPROTOOPT) @@ -309,7 +309,7 @@ namespace fc { try { my->_accept.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), port)); - my->_accept.listen(); + my->_accept.listen(256); } FC_RETHROW_EXCEPTIONS(warn, "error listening on socket"); } diff --git a/src/network/udp_socket.cpp b/src/network/udp_socket.cpp old mode 100644 new mode 100755 diff --git a/src/network/udt_socket.cpp b/src/network/udt_socket.cpp deleted file mode 100644 index 655e16c..0000000 --- a/src/network/udt_socket.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -# include -#endif - -namespace fc { - - void check_udt_errors() - { - UDT::ERRORINFO& error_info = UDT::getlasterror(); - if( error_info.getErrorCode() ) - { - std::string error_message = error_info.getErrorMessage(); - error_info.clear(); - FC_CAPTURE_AND_THROW( udt_exception, (error_message) ); - } - } - - class udt_epoll_service - { - public: - udt_epoll_service() - :_epoll_thread("udt_epoll") - { - UDT::startup(); - check_udt_errors(); - _epoll_id = UDT::epoll_create(); - _epoll_loop = _epoll_thread.async( [=](){ poll_loop(); }, "udt_poll_loop" ); - } - - ~udt_epoll_service() - { - _epoll_loop.cancel("udt_epoll_service is destructing"); - _epoll_loop.wait(); - UDT::cleanup(); - } - - void poll_loop() - { - std::set read_ready; - std::set write_ready; - while( !_epoll_loop.canceled() ) - { - UDT::epoll_wait( _epoll_id, - &read_ready, - &write_ready, 100000000 ); - - { synchronized(_read_promises_mutex) - for( auto sock : read_ready ) - { - auto itr = _read_promises.find( sock ); - if( itr != _read_promises.end() ) - { - itr->second->set_value(); - _read_promises.erase(itr); - } - } - } // synchronized read promise mutex - - { synchronized(_write_promises_mutex) - for( auto sock : write_ready ) - { - auto itr = _write_promises.find( sock ); - if( itr != _write_promises.end() ) - { - itr->second->set_value(); - _write_promises.erase(itr); - } - } - } // synchronized write promise mutex - } // while not canceled - } // poll_loop - - - void notify_read( int udt_socket_id, - const promise::ptr& p ) - { - int events = UDT_EPOLL_IN | UDT_EPOLL_ERR; - if( 0 != UDT::epoll_add_usock( _epoll_id, - udt_socket_id, - &events ) ) - { - check_udt_errors(); - } - { synchronized(_read_promises_mutex) - - _read_promises[udt_socket_id] = p; - } - } - - void notify_write( int udt_socket_id, - const promise::ptr& p ) - { - int events = UDT_EPOLL_OUT | UDT_EPOLL_ERR; - if( 0 != UDT::epoll_add_usock( _epoll_id, - udt_socket_id, - &events ) ) - { - check_udt_errors(); - } - - { synchronized(_write_promises_mutex) - _write_promises[udt_socket_id] = p; - } - } - void remove( int udt_socket_id ) - { - { synchronized(_read_promises_mutex) - auto read_itr = _read_promises.find( udt_socket_id ); - if( read_itr != _read_promises.end() ) - { - read_itr->second->set_exception( fc::copy_exception( fc::exception() ) ); - _read_promises.erase(read_itr); - } - } - { synchronized(_write_promises_mutex) - auto write_itr = _write_promises.find( udt_socket_id ); - if( write_itr != _write_promises.end() ) - { - write_itr->second->set_exception( fc::copy_exception( fc::exception() ) ); - _write_promises.erase(write_itr); - } - } - UDT::epoll_remove_usock( _epoll_id, udt_socket_id ); - } - - private: - fc::mutex _read_promises_mutex; - fc::mutex _write_promises_mutex; - std::unordered_map::ptr > _read_promises; - std::unordered_map::ptr > _write_promises; - - fc::future _epoll_loop; - fc::thread _epoll_thread; - int _epoll_id; - }; - - - udt_epoll_service& default_epool_service() - { - static udt_epoll_service* default_service = new udt_epoll_service(); - return *default_service; - } - - - - udt_socket::udt_socket() - :_udt_socket_id( UDT::INVALID_SOCK ) - { - } - - udt_socket::~udt_socket() - { - try { - close(); - } catch ( const fc::exception& e ) - { - wlog( "${e}", ("e", e.to_detail_string() ) ); - } - } - - void udt_socket::bind( const fc::ip::endpoint& local_endpoint ) - { try { - if( !is_open() ) - open(); - - sockaddr_in local_addr; - local_addr.sin_family = AF_INET; - local_addr.sin_port = htons(local_endpoint.port()); - local_addr.sin_addr.s_addr = htonl(local_endpoint.get_address()); - - if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&local_addr, sizeof(local_addr)) ) - check_udt_errors(); - } FC_CAPTURE_AND_RETHROW() } - - void udt_socket::connect_to( const ip::endpoint& remote_endpoint ) - { try { - if( !is_open() ) - open(); - - sockaddr_in serv_addr; - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(remote_endpoint.port()); - serv_addr.sin_addr.s_addr = htonl(remote_endpoint.get_address()); - - // UDT doesn't allow now blocking connects... - fc::thread connect_thread("connect_thread"); - connect_thread.async( [&](){ - if( UDT::ERROR == UDT::connect(_udt_socket_id, (sockaddr*)&serv_addr, sizeof(serv_addr)) ) - check_udt_errors(); - }, "udt_socket::connect_to").wait(); - - bool block = false; - UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool)); - UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool)); - check_udt_errors(); - - } FC_CAPTURE_AND_RETHROW( (remote_endpoint) ) } - - ip::endpoint udt_socket::remote_endpoint() const - { try { - sockaddr_in peer_addr; - int peer_addr_size = sizeof(peer_addr); - int error_code = UDT::getpeername( _udt_socket_id, (struct sockaddr*)&peer_addr, &peer_addr_size ); - if( error_code == UDT::ERROR ) - check_udt_errors(); - return ip::endpoint( ip::address( htonl( peer_addr.sin_addr.s_addr ) ), htons(peer_addr.sin_port) ); - } FC_CAPTURE_AND_RETHROW() } - - ip::endpoint udt_socket::local_endpoint() const - { try { - sockaddr_in sock_addr; - int addr_size = sizeof(sock_addr); - int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size ); - if( error_code == UDT::ERROR ) - check_udt_errors(); - return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) ); - } FC_CAPTURE_AND_RETHROW() } - - - /// @{ - size_t udt_socket::readsome( char* buffer, size_t max ) - { try { - auto bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 ); - while( bytes_read == UDT::ERROR ) - { - if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV ) - { - UDT::getlasterror().clear(); - promise::ptr p(new promise("udt_socket::readsome")); - default_epool_service().notify_read( _udt_socket_id, p ); - p->wait(); - bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 ); - } - else - check_udt_errors(); - } - return bytes_read; - } FC_CAPTURE_AND_RETHROW( (max) ) } - - size_t udt_socket::readsome( const std::shared_ptr& buf, size_t len, size_t offset ) - { - return readsome(buf.get() + offset, len); - } - - bool udt_socket::eof()const - { - // TODO... - return false; - } - /// @} - - /// ostream interface - /// @{ - size_t udt_socket::writesome( const char* buffer, size_t len ) - { try { - auto bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0); - - while( UDT::ERROR == bytes_sent ) - { - if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCSND ) - { - UDT::getlasterror().clear(); - promise::ptr p(new promise("udt_socket::writesome")); - default_epool_service().notify_write( _udt_socket_id, p ); - p->wait(); - bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0); - continue; - } - else - check_udt_errors(); - } - return bytes_sent; - } FC_CAPTURE_AND_RETHROW( (len) ) } - - size_t udt_socket::writesome( const std::shared_ptr& buf, size_t len, size_t offset ) - { - return writesome(buf.get() + offset, len); - } - - void udt_socket::flush(){} - - void udt_socket::close() - { try { - if( is_open() ) - { - default_epool_service().remove( _udt_socket_id ); - UDT::close( _udt_socket_id ); - check_udt_errors(); - _udt_socket_id = UDT::INVALID_SOCK; - } - else - { - wlog( "already closed" ); - } - } FC_CAPTURE_AND_RETHROW() } - /// @} - - void udt_socket::open() - { - _udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0); - if( _udt_socket_id == UDT::INVALID_SOCK ) - check_udt_errors(); - } - - bool udt_socket::is_open()const - { - return _udt_socket_id != UDT::INVALID_SOCK; - } - - - - - - - udt_server::udt_server() - :_udt_socket_id( UDT::INVALID_SOCK ) - { - _udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0); - if( _udt_socket_id == UDT::INVALID_SOCK ) - check_udt_errors(); - - bool block = false; - UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool)); - check_udt_errors(); - UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool)); - check_udt_errors(); - } - - udt_server::~udt_server() - { - try { - close(); - } catch ( const fc::exception& e ) - { - wlog( "${e}", ("e", e.to_detail_string() ) ); - } - } - - void udt_server::close() - { try { - if( _udt_socket_id != UDT::INVALID_SOCK ) - { - UDT::close( _udt_socket_id ); - check_udt_errors(); - default_epool_service().remove( _udt_socket_id ); - _udt_socket_id = UDT::INVALID_SOCK; - } - } FC_CAPTURE_AND_RETHROW() } - - void udt_server::accept( udt_socket& s ) - { try { - FC_ASSERT( !s.is_open() ); - int namelen; - sockaddr_in their_addr; - - - while( s._udt_socket_id == UDT::INVALID_SOCK ) - { - s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen ); - if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV ) - { - UDT::getlasterror().clear(); - promise::ptr p(new promise("udt_server::accept")); - default_epool_service().notify_read( _udt_socket_id, p ); - p->wait(); - s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen ); - } - else - check_udt_errors(); - } - } FC_CAPTURE_AND_RETHROW() } - - void udt_server::listen( const ip::endpoint& ep ) - { try { - sockaddr_in my_addr; - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons(ep.port()); - my_addr.sin_addr.s_addr = INADDR_ANY; - memset(&(my_addr.sin_zero), '\0', 8); - - if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&my_addr, sizeof(my_addr)) ) - check_udt_errors(); - - UDT::listen(_udt_socket_id, 10); - check_udt_errors(); - } FC_CAPTURE_AND_RETHROW( (ep) ) } - - fc::ip::endpoint udt_server::local_endpoint() const - { try { - sockaddr_in sock_addr; - int addr_size = sizeof(sock_addr); - int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size ); - if( error_code == UDT::ERROR ) - check_udt_errors(); - return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) ); - } FC_CAPTURE_AND_RETHROW() } - -} diff --git a/src/network/url.cpp b/src/network/url.cpp old mode 100644 new mode 100755 diff --git a/src/real128.cpp b/src/real128.cpp old mode 100644 new mode 100755 diff --git a/src/rpc/bstate.cpp b/src/rpc/bstate.cpp new file mode 100755 index 0000000..832f8ce --- /dev/null +++ b/src/rpc/bstate.cpp @@ -0,0 +1,68 @@ +#include +#include +#include + +namespace fc { namespace rpc { +bstate::~bstate() +{ + close(); +} + +void bstate::add_method( const fc::string& name, method m ) +{ + _methods.emplace(std::pair(name,fc::move(m))); +} + +void bstate::remove_method( const fc::string& name ) +{ + _methods.erase(name); +} + +result_type bstate::local_call( const string& method_name, const params_type& args ) +{ + auto method_itr = _methods.find(method_name); + if( method_itr == _methods.end() && _unhandled ) + return _unhandled( method_name, args ); + FC_ASSERT( method_itr != _methods.end(), "Unknown Method: ${name}", ("name",method_name) ); + return method_itr->second(args); +} + +void bstate::handle_reply( const bresponse& bresponse ) +{ + auto await = _awaiting.find( bresponse.id ); + FC_ASSERT( await != _awaiting.end(), "Unknown Response ID: ${id}", ("id",bresponse.id)("bresponse",bresponse) ); + if( bresponse.result ) + await->second->set_value( *bresponse.result ); + else if( bresponse.error ) + { + await->second->set_exception( exception_ptr(new FC_EXCEPTION( exception, "${error}", ("error",bresponse.error->message)("data",bresponse) ) ) ); + } + else + await->second->set_value( params_type() ); + _awaiting.erase(await); +} + +brequest bstate::start_remote_call( const string& method_name, params_type args ) +{ + brequest brequest{ _next_id++, method_name, std::move(args) }; + _awaiting[*brequest.id] = fc::promise::ptr( new fc::promise("json_connection::async_call") ); + return brequest; +} +result_type bstate::wait_for_response( uint64_t request_id ) +{ + auto itr = _awaiting.find(request_id); + FC_ASSERT( itr != _awaiting.end() ); + return fc::future( itr->second ).wait(); +} +void bstate::close() +{ + for( auto item : _awaiting ) + item.second->set_exception( fc::exception_ptr(new FC_EXCEPTION( eof_exception, "connection closed" )) ); + _awaiting.clear(); +} +void bstate::on_unhandled( const std::function& unhandled ) +{ + _unhandled = unhandled; +} + +} } // namespace fc::rpc diff --git a/src/rpc/cli.cpp b/src/rpc/cli.cpp old mode 100644 new mode 100755 diff --git a/src/rpc/http_api.cpp b/src/rpc/http_api.cpp old mode 100644 new mode 100755 index c842369..c9571a2 --- a/src/rpc/http_api.cpp +++ b/src/rpc/http_api.cpp @@ -11,9 +11,20 @@ http_api_connection::http_api_connection() { _rpc_state.add_method( "call", [this]( const variants& args ) -> variant { + // TODO: This logic is duplicated between http_api_connection and websocket_api_connection + // it should be consolidated into one place instead of copy-pasted FC_ASSERT( args.size() == 3 && args[2].is_array() ); + api_id_type api_id; + if( args[0].is_string() ) + { + variant subresult = this->receive_call( 1, args[0].as_string() ); + api_id = subresult.as_uint64(); + } + else + api_id = args[0].as_uint64(); + return this->receive_call( - args[0].as_uint64(), + api_id, args[1].as_string(), args[2].get_array() ); } ); @@ -85,9 +96,13 @@ void http_api_connection::on_request( const fc::http::request& req, const fc::ht auto call = var.as(); try { - auto result = _rpc_state.local_call( call.method, call.params ); - resp_body = fc::json::to_string( fc::rpc::response( *call.id, result ) ); - resp_status = http::reply::OK; + try + { + auto result = _rpc_state.local_call( call.method, call.params ); + resp_body = fc::json::to_string( fc::rpc::response( *call.id, result ) ); + resp_status = http::reply::OK; + } + FC_CAPTURE_AND_RETHROW( (call.method)(call.params) ); } catch ( const fc::exception& e ) { diff --git a/src/rpc/json_connection.cpp b/src/rpc/json_connection.cpp old mode 100644 new mode 100755 diff --git a/src/rpc/state.cpp b/src/rpc/state.cpp old mode 100644 new mode 100755 diff --git a/src/rpc/websocket_api.cpp b/src/rpc/websocket_api.cpp old mode 100644 new mode 100755 index 39381ab..8c60614 --- a/src/rpc/websocket_api.cpp +++ b/src/rpc/websocket_api.cpp @@ -13,8 +13,17 @@ websocket_api_connection::websocket_api_connection( fc::http::websocket_connecti _rpc_state.add_method( "call", [this]( const variants& args ) -> variant { FC_ASSERT( args.size() == 3 && args[2].is_array() ); + api_id_type api_id; + if( args[0].is_string() ) + { + variant subresult = this->receive_call( 1, args[0].as_string() ); + api_id = subresult.as_uint64(); + } + else + api_id = args[0].as_uint64(); + return this->receive_call( - args[0].as_uint64(), + api_id, args[1].as_string(), args[2].get_array() ); } ); @@ -78,20 +87,39 @@ std::string websocket_api_connection::on_message( { auto var = fc::json::from_string(message); const auto& var_obj = var.get_object(); + if( var_obj.contains( "method" ) ) { auto call = var.as(); exception_ptr optexcept; try { - auto result = _rpc_state.local_call( call.method, call.params ); - if( call.id ) + try { - auto reply = fc::json::to_string( response( *call.id, result ) ); - if( send_message ) - _connection.send_message( reply ); - return reply; +#ifdef LOG_LONG_API + auto start = time_point::now(); +#endif + + auto result = _rpc_state.local_call( call.method, call.params ); + +#ifdef LOG_LONG_API + auto end = time_point::now(); + + if( end - start > fc::milliseconds( LOG_LONG_API_MAX_MS ) ) + elog( "API call execution time limit exceeded. method: ${m} params: ${p} time: ${t}", ("m",call.method)("p",call.params)("t", end - start) ); + else if( end - start > fc::milliseconds( LOG_LONG_API_WARN_MS ) ) + wlog( "API call execution time nearing limit. method: ${m} params: ${p} time: ${t}", ("m",call.method)("p",call.params)("t", end - start) ); +#endif + + if( call.id ) + { + auto reply = fc::json::to_string( response( *call.id, result, "2.0" ) ); + if( send_message ) + _connection.send_message( reply ); + return reply; + } } + FC_CAPTURE_AND_RETHROW( (call.method)(call.params) ) } catch ( const fc::exception& e ) { @@ -102,7 +130,7 @@ std::string websocket_api_connection::on_message( } if( optexcept ) { - auto reply = fc::json::to_string( response( *call.id, error_object{ 1, optexcept->to_detail_string(), fc::variant(*optexcept)} ) ); + auto reply = fc::json::to_string( response( *call.id, error_object{ 1, optexcept->to_string(), fc::variant(*optexcept)}, "2.0" ) ); if( send_message ) _connection.send_message( reply ); diff --git a/src/shared_ptr.cpp b/src/shared_ptr.cpp old mode 100644 new mode 100755 diff --git a/src/ssh/client.cpp b/src/ssh/client.cpp deleted file mode 100644 index 80d8788..0000000 --- a/src/ssh/client.cpp +++ /dev/null @@ -1,717 +0,0 @@ -#define NOMINMAX // prevent windows from defining min and max macros -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "client_impl.hpp" - -namespace fc { namespace ssh { - - namespace detail { - static int ssh_init = libssh2_init(0); - } - - client::client():my( new detail::client_impl() ){ (void)detail::ssh_init; /* fix unused warning...*/ } - client::~client() { my->close(); } - - void client::set_trace_level( int bitmask ) { my->_trace_level = bitmask; } - int client::get_trace_level()const { return my->_trace_level; } - const logger& client::get_logger()const { return my->logr; } - void client::set_logger( const logger& l ) { my->logr = l; } - - void client::connect( const fc::string& user, const fc::string& host, uint16_t port ) { - my->hostname = host; - my->uname = user; - my->port = port; - my->connect(); - } - void client::connect( const fc::string& user, const fc::string& pass, - const fc::string& host, uint16_t port ) { - my->hostname = host; - my->uname = user; - my->upass = pass; - my->port = port; - - my->connect(); - } - - void client::close() { my->close(); } - - -// ssh::process client::exec( const fc::string& cmd, const fc::string& pty_type ) { -// return ssh::process( *this, cmd, pty_type ); -// } - - /** - * @todo implement progress reporting. - */ - void client::scp_send_dir( const fc::path& local_dir, const fc::path& remote_path, - std::function progress ) - { - fc::path remote_dir = remote_path; - if( remote_dir.filename() == fc::path(".") ) - remote_dir /= local_dir.filename(); - - fc_dlog( my->logr, "scp -r ${local} ${remote}", ("local",local_dir)("remote",remote_dir) ); - create_directories( remote_dir ); - - directory_iterator ditr(local_dir); - directory_iterator dend; - - while( ditr != dend ) { - if( (*ditr).filename() == "." || - (*ditr).filename() == ".." ) - { } - else if( fc::is_directory(*ditr) ) - { - scp_send_dir( (*ditr), remote_dir / (*ditr).filename() ); - } else if( fc::is_regular_file(*ditr) ) { - scp_send( *ditr, remote_dir / (*ditr).filename() ); - } else { - fc_wlog( my->logr, "Skipping '${path}", ("path",fc::canonical(*ditr)) ); - } - ++ditr; - } - } - - void client::scp_send( const fc::path& local_path, const fc::path& remote_path, - std::function progress ) { - fc_wlog( my->logr, "scp ${local} ${remote}", ("local",local_path)("remote",remote_path ) ); - if( !fc::exists(local_path) ) { - FC_THROW( "Source file '${file}' does not exist", ("file",local_path) ) ; - } - if( is_directory( local_path ) ) { - FC_THROW( "Source file '${file}' is a directory, expected a file", ("file",local_path) ) ; - } - - // memory map the file - uint64_t fsize = file_size(local_path); - if( fsize == 0 ) { - elog( "file size ${file_size}", ("file_size", fsize) ); - // TODO: handle empty file case - if( progress ) progress(0,0); - return; - } - file_mapping fmap( local_path.string().c_str(), read_only ); - - LIBSSH2_CHANNEL* chan = 0; - time_t now; - memset( &now, 0, sizeof(now) ); - - // TODO: preserve creation / modification date - // TODO: perserve permissions / exec bit? - try { - // libssh2_scp_send64 stores state data in the session object, and it calls channel_open which - // stores its own state data, so lock both. - fc::scoped_lock channel_open_lock(my->channel_open_mutex); - fc::scoped_lock scp_send_lock(my->scp_send_mutex); - chan = my->call_ssh2_ptr_function_throw(boost::bind(libssh2_scp_send64, my->session, remote_path.generic_string().c_str(), 0700, fsize, now, now )); - } catch (fc::exception& er) { - FC_RETHROW_EXCEPTION(er, error, "scp ${local_file} to ${remote_file} failed", ("local_file", local_path)("remote_file",remote_path)); - } - uint64_t total_bytes_written = 0; - try { - const size_t max_mapping_size = 1024*1024*1024; // 1GB - for (uint64_t current_offset = 0; current_offset < fsize; current_offset += max_mapping_size) { - uint64_t total_bytes_left_to_send = fsize - current_offset; - size_t bytes_to_send_this_iteration = (size_t)std::min(total_bytes_left_to_send, max_mapping_size); - mapped_region mr( fmap, fc::read_only, current_offset, bytes_to_send_this_iteration); - size_t bytes_written_this_iteration = 0; - char* pos = reinterpret_cast(mr.get_address()); - while( progress(total_bytes_written, fsize) && bytes_written_this_iteration < bytes_to_send_this_iteration) { - int r = my->call_ssh2_function_throw(boost::bind(libssh2_channel_write_ex, chan, 0, pos, - bytes_to_send_this_iteration - bytes_written_this_iteration), - "scp failed ${code} - ${message}"); - bytes_written_this_iteration += r; - total_bytes_written += r; - pos += r; - // fc_wlog( my->logr, "wrote ${bytes} bytes", ("bytes",r) ); - } - } - my->call_ssh2_function(boost::bind(libssh2_channel_send_eof, chan)); - my->call_ssh2_function(boost::bind(libssh2_channel_wait_eof, chan)); - my->call_ssh2_function(boost::bind(libssh2_channel_close, chan)); - } catch ( fc::exception& er ) { - // clean up chan - my->call_ssh2_function(boost::bind(libssh2_channel_free, chan)); - throw er; - } - my->call_ssh2_function_throw(boost::bind(libssh2_channel_free, chan), - "scp failed ${code} - ${message}"); - } - - - void client::rm( const fc::path& remote_path ) { - try { - auto s = stat(remote_path); - if( s.is_directory() ) { - FC_THROW( "sftp cannot remove directory ${path}", ("path",remote_path) ); - } - else if( !s.exists() ) { - return; // nothing to do - } - - { - fc::scoped_lock scp_unlink_lock(my->scp_unlink_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_unlink_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), - "sftp rm failed ${code}"); - } - } catch ( fc::exception& er ) { - FC_RETHROW_EXCEPTION( er, error, "sftp remove '${remote_path}' failed", ("remote_path",remote_path) ); - } - } - - void client::rmdir( const fc::path& remote_path ) { - try { - auto s = stat(remote_path); - if( !s.is_directory() ) - FC_THROW( "sftp cannot rmdir non-directory ${path}", ("path",remote_path) ); - else if( !s.exists() ) - return; // nothing to do - - { - fc::scoped_lock scp_rmdir_lock(my->scp_rmdir_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_rmdir_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), - "sftp rmdir failed ${code}"); - } - } catch ( fc::exception& er ) { - FC_RETHROW_EXCEPTION( er, error, "sftp rmdir '${remote_path}' failed", ("remote_path",remote_path) ); - } - } - - void client::rmdir_recursive( const fc::path& remote_path ) { - try { - auto s = stat(remote_path); - if( !s.is_directory() ) - FC_THROW( "sftp cannot rmdir non-directory ${path}", ("path",remote_path) ); - else if( !s.exists() ) - return; // nothing to do - - LIBSSH2_SFTP_HANDLE *dir_handle; - { - fc::scoped_lock scp_open_lock(my->scp_open_mutex); - dir_handle = - my->call_ssh2_ptr_function_throw(boost::bind(libssh2_sftp_open_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size(), 0, 0, LIBSSH2_SFTP_OPENDIR), - "sftp libssh2_sftp_opendir failed ${code}"); - } - do { - char mem[512]; - LIBSSH2_SFTP_ATTRIBUTES attrs; - - int rc; - { - fc::scoped_lock scp_readdir_lock(my->scp_readdir_mutex); - rc = my->call_ssh2_function_throw(boost::bind(libssh2_sftp_readdir_ex, dir_handle, mem, sizeof(mem), (char*)NULL, 0, &attrs), - "sftp readdir failed ${code}"); - } - if (rc > 0) { - fc::string file_or_dir_name(mem, rc); - if (file_or_dir_name == "." || file_or_dir_name == "..") - continue; - fc::path full_remote_path = remote_path / file_or_dir_name; - if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) - rmdir_recursive(full_remote_path); - else if (LIBSSH2_SFTP_S_ISREG(attrs.permissions)) { - fc::scoped_lock scp_unlink_lock(my->scp_unlink_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_unlink_ex, my->sftp, full_remote_path.generic_string().c_str(), full_remote_path.generic_string().size()), - "sftp rm failed ${code}"); - } - } else - break; - } while (1); - - { - fc::scoped_lock scp_close_lock(my->scp_close_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_close_handle, dir_handle), "sftp libssh2_sftp_closedir failed ${code}"); - } - { - fc::scoped_lock scp_rmdir_lock(my->scp_rmdir_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_rmdir_ex, my->sftp, remote_path.generic_string().c_str(), remote_path.generic_string().size()), - "sftp rmdir failed ${code}"); - } - } catch ( fc::exception& er ) { - FC_RETHROW_EXCEPTION( er, error, "sftp rmdir recursive '${remote_path}' failed", ("remote_path",remote_path) ); - } - } - - file_attrib client::stat( const fc::path& remote_path ){ - my->init_sftp(); - LIBSSH2_SFTP_ATTRIBUTES att; - int ec; - { - fc::scoped_lock scp_stat_lock(my->scp_stat_mutex); - ec = my->call_ssh2_function(boost::bind(libssh2_sftp_stat_ex, my->sftp, - remote_path.generic_string().c_str(), remote_path.generic_string().size(), - LIBSSH2_SFTP_STAT, &att)); - } - if( ec ) - return file_attrib(); - file_attrib ft; - ft.size = att.filesize; - ft.permissions = att.permissions; - return ft; - } - void client::create_directories( const fc::path& rdir, int mode ) { - boost::filesystem::path dir = rdir; - boost::filesystem::path p; - auto pitr = dir.begin(); - while( pitr != dir.end() ) { - p /= *pitr; - if( !stat( p ).exists() ) { - mkdir(p,mode); - } - ++pitr; - } - } - - void client::mkdir( const fc::path& rdir, int mode ) { - try { - auto s = stat(rdir); - if( s.is_directory() ) - return; - else if( s.exists() ) - FC_THROW( "File already exists at path ${path}", ("path",rdir) ); - - { - fc::scoped_lock scp_mkdir_lock(my->scp_mkdir_mutex); - my->call_ssh2_function_throw(boost::bind(libssh2_sftp_mkdir_ex, my->sftp, - rdir.generic_string().c_str(), rdir.generic_string().size(), mode), - "sftp mkdir error"); - } - } catch ( fc::exception& er ) { - FC_RETHROW_EXCEPTION( er, error, "sftp failed to create directory '${directory}'", ( "directory", rdir ) ); - } - } - - void client::set_remote_system_is_windows(bool is_windows /* = true */) { - my->remote_system_is_windows = is_windows; - } - - - file_attrib::file_attrib() - :size(0),uid(0),gid(0),permissions(0),atime(0),mtime(0) - { } - - bool file_attrib::is_directory() { - return LIBSSH2_SFTP_S_ISDIR(permissions); - } - bool file_attrib::is_file() { - return LIBSSH2_SFTP_S_ISREG(permissions); - } - bool file_attrib::exists() { - return 0 != permissions; - } - - detail::client_impl::client_impl() : - session(nullptr), - knownhosts(nullptr), - sftp(nullptr), - agent(nullptr), - _trace_level(0), // was LIBSSH2_TRACE_ERROR - logr(fc::logger::get( "fc::ssh::client" )), - remote_system_is_windows(false) { - logr.set_parent( fc::logger::get( "default" ) ); - } - - detail::client_impl::~client_impl() { - close(); - } - - /* static */ - void detail::client_impl::kbd_callback(const char *name, int name_len, - const char *instruction, int instruction_len, int num_prompts, - const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, - LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, - void **abstract) { - detail::client_impl* self = (client_impl*)*abstract; - - - for (int i = 0; i < num_prompts; i++) { - fwrite(prompts[i].text, 1, prompts[i].length, stdout); - - if( self->upass.size() == 0 ) { - /** TODO: add keyboard callback here... - fgets(buf, sizeof(buf), stdin); - n = strlen(buf); - while (n > 0 && strchr("\r\n", buf[n - 1])) - n--; - buf[n] = 0; - -#ifdef WIN32 // fix warning -# define strdup _strdup -#endif - responses[i].text = strdup(buf); - responses[i].length = n; - */ - responses[i].text = nullptr; - responses[i].length = 0; - } else { - responses[i].text = strdup(self->upass.c_str()); - responses[i].length = self->upass.size(); - } - } - } - - void detail::client_impl::connect() { - try { - if( libssh2_init(0) < 0 ) - FC_THROW( "Unable to init libssh2" ); - - auto eps = fc::asio::tcp::resolve( hostname, boost::lexical_cast(port) ); - if( eps.size() == 0 ) - FC_THROW( "Unable to resolve host '${host}'", ("host",hostname) ); - - sock.reset( new boost::asio::ip::tcp::socket( fc::asio::default_io_service() ) ); - - bool resolved = false; - for( uint32_t i = 0; i < eps.size(); ++i ) { - std::stringstream ss; ss << eps[i]; - try { - boost::system::error_code ec; - fc_ilog( logr, "Attempting to connect to ${endpoint}", ("endpoint",ss.str().c_str()) ); - fc::asio::tcp::connect( *sock, eps[i] ); - endpt = eps[i]; - resolved = true; - break; - } catch ( fc::exception& er ) { - fc_ilog( logr, "Failed to connect to ${endpoint}\n${error_reprot}", - ("endpoint",ss.str().c_str())("error_report", er.to_detail_string()) ); - sock->close(); - } - } - if( !resolved ) - FC_THROW( "Unable to connect to any resolved endpoint for ${host}:${port}", - ("host", hostname).set("port",port) ); - - session = libssh2_session_init(); - libssh2_trace( session, _trace_level ); - libssh2_trace_sethandler( session, this, client_impl::handle_trace ); - - *libssh2_session_abstract(session) = this; - - libssh2_session_set_blocking( session, 0 ); - try { - call_ssh2_function_throw(boost::bind(libssh2_session_handshake, session, sock->native()), - "SSH Handshake error: ${code} - ${message}"); - } catch (fc::exception& er) { - FC_RETHROW_EXCEPTION( er, error, "Error during SSH handshake" );; - } - //const char* fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); - //slog( "fingerprint: %s", fingerprint ); - - // try to authenticate, throw on error. - try { - authenticate(); - } catch (fc::exception& er) { - FC_RETHROW_EXCEPTION( er, error, "Error during SSH authentication" );; - } - //slog("."); - } catch ( fc::exception& er ) { - elog( "Unable to connect to ssh server: ${detail}", ("detail", er.to_detail_string().c_str()) ); - close(); - FC_RETHROW_EXCEPTION( er, error, "Unable to connect to ssh server" );; - } catch ( ... ) { - close(); - FC_THROW( "Unable to connect to ssh server", ("exception", fc::except_str() ) ); - } - } - - /* static */ - void detail::client_impl::handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ) { - client_impl* my = (client_impl*)context; - fc::string str(data,length); - fc_wlog( my->logr, "${message}", ("message",str) ); - } - - void detail::client_impl::close() { - if( session ) { - if( sftp ) { - try { - call_ssh2_function(boost::bind(libssh2_sftp_shutdown, sftp)); - }catch(...){ - fc_wlog( logr, "caught closing sftp session" ); - } - sftp = 0; - } - - if (agent) { - libssh2_agent_disconnect(agent); - libssh2_agent_free(agent); - agent = nullptr; - } - - try { - call_ssh2_function(boost::bind(libssh2_session_disconnect_ex, session, SSH_DISCONNECT_BY_APPLICATION, "exit cleanly", "")); - call_ssh2_function(boost::bind(libssh2_session_free, session), false); - } catch ( ... ){ - fc_wlog( logr, "caught freeing session" ); - } - session = 0; - try { - if( sock ) - sock->close(); - } catch ( ... ){ - fc_wlog( logr, "caught error closing socket" ); - } - sock.reset(0); - try { - if( read_prom ) - read_prom->wait(); - } catch ( ... ){ - fc_wlog( logr, "caught error waiting on read" ); - } - try { - if( write_prom ) - write_prom->wait(); - } catch ( ... ){ - fc_wlog( logr, "caught error waiting on write" ); - } - } - } - - void detail::client_impl::authenticate() { - try { - char * alist = NULL; - // libssh2_userauth_list has strange enough behavior that we can't use the - // call_blocking_libssh2_function-type functions to wait and retry, so we must - // explicitly lock around the libssh2_userauth_list calls. - // hence, this anonymous scope: - { - fc::unique_lock lock(ssh_session_mutex); - - alist = libssh2_userauth_list(session, uname.c_str(),uname.size()); - - if(alist==NULL) { - char * msg = 0; - int ec = 0; - if(libssh2_userauth_authenticated(session)) - return; // CONNECTED! - ec = libssh2_session_last_error(session,&msg,NULL,0); - - while( !alist && (ec == LIBSSH2_ERROR_EAGAIN) ) { - wait_on_socket(); - alist = libssh2_userauth_list(session, uname.c_str(), uname.size()); - ec = libssh2_session_last_error(session,&msg,NULL,0); - } - if( !alist ) { - FC_THROW( "Error getting authorization list: ${code} - ${message}", - ("code",ec).set("message",msg)); - } - } - } // end anonymous scope - - std::vector split_alist; - bool pubkey = false; - bool pass = false; - bool keybd = false; - boost::split( split_alist, alist, boost::is_any_of(",") ); - std::for_each( split_alist.begin(), split_alist.end(), [&](const std::string& s){ - if( s == "publickey" ) - pubkey = true; - else if( s == "password" ) - pass = true; - else if( s == "keyboard-interactive" ) - keybd = true; - else - fc_dlog( logr, "Unknown/unsupported authentication type '${auth_type}'", ("auth_type",s.c_str())); - }); - - if( pubkey && try_pub_key() ) - return; - if( pass && try_pass() ) - return; - if( keybd && try_keyboard() ) - return; - } catch ( fc::exception& er ) { - FC_RETHROW_EXCEPTION( er, error, "Unable to authenticate ssh connection" ); - } - FC_THROW( "Unable to authenticate ssh connection" ); - } // authenticate() - - bool detail::client_impl::try_pass() { - return !call_ssh2_function(boost::bind(libssh2_userauth_password_ex, session, uname.c_str(), uname.size(), - upass.c_str(), upass.size(), (LIBSSH2_PASSWD_CHANGEREQ_FUNC((*)))NULL)); - } - bool detail::client_impl::try_keyboard() { - return !call_ssh2_function(boost::bind(libssh2_userauth_keyboard_interactive_ex, session, - uname.c_str(), uname.size(), &client_impl::kbd_callback)); - } - bool detail::client_impl::try_pub_key() { - if (privkey.size()) { - if (!call_ssh2_function(boost::bind(libssh2_userauth_publickey_fromfile_ex, - session, - uname.c_str(), uname.size(), - pubkey.c_str(), - privkey.c_str(), - passphrase.c_str()))) - return true; // successful authentication from file - fc_ilog( logr, "failed to authenticate with private key from file '${privkey_filename}'", ("privkey_filename",privkey)); - } else - fc_ilog( logr, "no private key file set, skiping pubkey authorization from file"); - - agent = libssh2_agent_init(session); - if (!agent) { - fc_wlog( logr, "failed to initialize ssh-agent support"); - return false; - } - - if (call_ssh2_function(boost::bind(libssh2_agent_connect, agent))) { - fc_ilog( logr, "failed to connect to ssh-agent"); - return false; - } - - if (call_ssh2_function(boost::bind(libssh2_agent_list_identities, agent))) { - fc_ilog( logr, "failed requesting identities from ssh-agent"); - return false; - } - - struct libssh2_agent_publickey *prev_identity = NULL; - while (1) { - struct libssh2_agent_publickey *identity; - int ec = call_ssh2_function(boost::bind(libssh2_agent_get_identity, agent, &identity, prev_identity)); - if (ec == 1) - break; // done iterating over keys - if (ec < 0) { - fc_ilog( logr, "failed obtaining identity from ssh-agent"); - return false; - } - - if (call_ssh2_function(boost::bind(libssh2_agent_userauth, agent, uname.c_str(), identity))) - fc_ilog( logr, "unable to authenticate with public key '${key_comment}'", ("key_comment",identity->comment)); - else { - fc_ilog( logr, "authenticated with public key '${key_comment}'", ("key_comment",identity->comment)); - return true; - } - prev_identity = identity; - } - return false; - } - - void detail::client_impl::wait_on_socket(int additionalDirections /* = 0 */) { - int dir = libssh2_session_block_directions(session); - dir |= additionalDirections; - if( !dir ) - return; - - fc::promise::ptr rprom, wprom; - if( dir & LIBSSH2_SESSION_BLOCK_INBOUND ) { - fc::scoped_lock lock(this->_spin_lock); - if( !read_prom ) { - read_prom.reset( new fc::promise("read_prom") ); - sock->async_read_some( boost::asio::null_buffers(), - [=]( const boost::system::error_code& e, size_t ) { - fc::scoped_lock lock(this->_spin_lock); - this->read_prom->set_value(e); - this->read_prom.reset(nullptr); - } ); - } - rprom = read_prom; - } - - if( dir & LIBSSH2_SESSION_BLOCK_OUTBOUND ) { - fc::scoped_lock lock(this->_spin_lock); - if( !write_prom ) { - write_prom.reset( new fc::promise("write_prom") ); - sock->async_write_some( boost::asio::null_buffers(), - [=]( const boost::system::error_code& e, size_t ) { - fc::scoped_lock lock(this->_spin_lock); - this->write_prom->set_value(e); - this->write_prom.reset(0); - } ); - } - wprom = write_prom; - } - - boost::system::error_code ec; - if( rprom.get() && wprom.get() ) { - typedef fc::future fprom; - fprom fw(wprom); - fprom fr(rprom); -#if 0 - // EMF: at present there are known bugs in fc::wait_any, and it will fail to wake up - // when one of the futures is ready. - int r = fc::wait_any( fw, fr, fc::seconds(1) ); -#else - int r; - while (1) { - if (fw.ready()) { - r = 0; break; - } - if (fr.ready()) { - r = 1; break; - } - fc::usleep(fc::microseconds(5000)); - } -#endif - switch( r ) { - case 0: - if( wprom->wait() ) { - FC_THROW( "Socket Error ${message}", - ( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - break; - case 1: - if( rprom->wait() ) { - FC_THROW( "Socket Error ${message}", - ( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - break; - } - } else if( rprom ) { - if( rprom->wait() ) { - FC_THROW( "Socket Error ${message}", - ( "message", boost::system::system_error(rprom->wait() ).what() ) ); - } - } else if( wprom ) { - if( wprom->wait() ) { - FC_THROW( "Socket Error ${message}", - ( "message", boost::system::system_error(wprom->wait() ).what() ) ); - } - } - } - void detail::client_impl::init_sftp() { - if( !sftp ) - sftp = call_ssh2_ptr_function_throw(boost::bind(libssh2_sftp_init,session), - "init sftp error ${code} - ${message}"); - } - - - LIBSSH2_CHANNEL* detail::client_impl::open_channel( const fc::string& pty_type ) { - LIBSSH2_CHANNEL* chan = 0; - /* anonymous scope */ { - fc::scoped_lock channel_open_lock(channel_open_mutex); - - chan = call_ssh2_ptr_function_throw(boost::bind(libssh2_channel_open_ex, session, - "session", sizeof("session") - 1, - LIBSSH2_CHANNEL_WINDOW_DEFAULT, - LIBSSH2_CHANNEL_PACKET_DEFAULT, - (const char*)NULL, 0), - "libssh2_channel_open_session failed: ${message}"); - } - - if( pty_type.size() ) - call_ssh2_function_throw(boost::bind(libssh2_channel_request_pty_ex, chan, pty_type.c_str(), pty_type.size(), - (char *)NULL, 0, LIBSSH2_TERM_WIDTH, LIBSSH2_TERM_HEIGHT, - LIBSSH2_TERM_WIDTH_PX, LIBSSH2_TERM_HEIGHT_PX), - "libssh2_channel_req_pty failed: ${message}"); - return chan; - } - -} } diff --git a/src/ssh/client_impl.hpp b/src/ssh/client_impl.hpp deleted file mode 100644 index 606bd36..0000000 --- a/src/ssh/client_impl.hpp +++ /dev/null @@ -1,280 +0,0 @@ -#define NOMINMAX -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -// include this to get acess to the details of the LIBSSH2_SESSION structure, so -// we can verify that all data has really been sent when libssh2 says it has. -#include <../src/libssh2_priv.h> - -namespace fc { namespace ssh { - - namespace detail { - - class client_impl { - public: - client_impl(); - ~client_impl(); - - LIBSSH2_SESSION* session; - LIBSSH2_KNOWNHOSTS* knownhosts; - LIBSSH2_SFTP* sftp; - LIBSSH2_AGENT* agent; - - std::unique_ptr sock; - boost::asio::ip::tcp::endpoint endpt; - - fc::mutex ssh_session_mutex; - fc::mutex channel_open_mutex; - fc::mutex process_startup_mutex; - fc::mutex scp_send_mutex; - fc::mutex scp_stat_mutex; - fc::mutex scp_mkdir_mutex; - fc::mutex scp_rmdir_mutex; - fc::mutex scp_unlink_mutex; - fc::mutex scp_close_mutex; - fc::mutex scp_readdir_mutex; - fc::mutex scp_open_mutex; - - fc::string uname; - fc::string upass; - fc::string pubkey; - fc::string privkey; - fc::string passphrase; - fc::string hostname; - uint16_t port; - bool session_connected; - fc::promise::ptr read_prom; - fc::promise::ptr write_prom; - fc::spin_lock _spin_lock; - int _trace_level; - logger logr; - - bool remote_system_is_windows; // true if windows, false if unix, used for command-line quoting and maybe filename translation - - LIBSSH2_CHANNEL* open_channel( const fc::string& pty_type ); - static void kbd_callback(const char *name, int name_len, - const char *instruction, int instruction_len, int num_prompts, - const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, - LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, - void **abstract); - - void connect(); - - static void handle_trace( LIBSSH2_SESSION* session, void* context, const char* data, size_t length ); - - void close(); - void authenticate(); - - bool try_pass(); - bool try_keyboard(); - bool try_pub_key(); - - // don't call this "unlocked" version directly - template - int call_ssh2_function_unlocked(const T& lambda, bool check_for_errors = true); - - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - template - int call_ssh2_function(const T& lambda, bool check_for_errors = true); - - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} - // set appropriately. - template - int call_ssh2_function_throw(const T& lambda, const char* message = "libssh2 call failed ${code} - ${message}", bool check_for_errors = true); - - // this version is a little different, it handles functions like libssh2_sftp_init which return - // a pointer instead of an int. These retry automatically if the result is NULL and the error - // is LIBSSH2_ERROR_EAGAIN - template - return_type call_ssh2_ptr_function_throw(std::function lambda, const char* message = "libssh2 call failed ${code} - ${message}", bool check_for_errors = true); - - void wait_on_socket(int additionalDirections = 0); - - void init_sftp(); - }; - - - // #define OLD_BLOCKING, - // the OLD_BLOCKING version of these functions will ensure that if a libssh2 function returns - // LIBSSH2_ERROR_EAGAIN, no other libssh2 functions will be called until that function has been - // called again and returned some other value. - // - // if you don't define this and use the new version of this, we will release the lock and let - // other libssh2 functions be called *unless* it appears that there was unwritten data. - // - // the OLD_BLOCKING version is too conservative -- if you try to read on a channel that doesn't - // have any data, you're likely to deadlock. The new version is not heavily tested and may be - // too lax, time will tell. -#ifdef OLD_BLOCKING - // don't call this "unlocked" version directly - template - int client_impl::call_ssh2_function_unlocked(const T& lambda, bool check_for_errors /* = true */) { - int ec = lambda(); - while (ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ec = lambda(); - } - - // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN - // but the internal session data indicates a data write is still in progress - // set check_for_errors to false when closing the connection - assert(!check_for_errors || !session->packet.olen); - - return ec; - } - - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - template - int client_impl::call_ssh2_function(const T& lambda, bool check_for_errors /* = true */) { - fc::scoped_lock lock(ssh_session_mutex); - return call_ssh2_function_unlocked(lambda, check_for_errors); - } -#else - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - template - int client_impl::call_ssh2_function(const T& lambda, bool check_for_errors /* = true */) { - fc::unique_lock lock(ssh_session_mutex); - int ec = lambda(); - while (ec == LIBSSH2_ERROR_EAGAIN) { - bool unlock_to_wait = !session->packet.olen; - if (unlock_to_wait) - lock.unlock(); - wait_on_socket(); - if (unlock_to_wait) - lock.lock(); - ec = lambda(); - } - // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN - // but the internal session data indicates a data write is still in progress - // set check_for_errors to false when closing the connection - assert(!check_for_errors || !session->packet.olen); - return ec; - } -#endif - -#ifdef OLD_BLOCKING - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} - // set appropriately. - template - int client_impl::call_ssh2_function_throw(const T& lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { - fc::scoped_lock lock(ssh_session_mutex); - int ec = call_ssh2_function_unlocked(lambda, check_for_errors); - - if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { - ec = libssh2_sftp_last_error(sftp); - FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); - } else if( ec < 0 ) { - char* msg = 0; - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW(message, ("code",ec).set("message",msg)); - } - return ec; - } -#else - // calls into libssh2, waits and retries the function if we get LIBSSH2_ERROR_EAGAIN - // if libssh2 returns an error, get extended info and throw a message with ${code} and ${message} - // set appropriately. - template - int client_impl::call_ssh2_function_throw(const T& lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { - fc::unique_lock lock(ssh_session_mutex); - int ec = lambda(); - while (ec == LIBSSH2_ERROR_EAGAIN) { - bool unlock_to_wait = !session->packet.olen; - if (unlock_to_wait) - lock.unlock(); - wait_on_socket(); - if (unlock_to_wait) - lock.lock(); - ec = lambda(); - } - // this assert catches bugs in libssh2 if libssh2 returns ec != LIBSSH2_ERROR_EAGAIN - // but the internal session data indicates a data write is still in progress - // set check_for_errors to false when closing the connection - assert(!check_for_errors || !session->packet.olen); - - if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { - ec = libssh2_sftp_last_error(sftp); - FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); - } else if( ec < 0 ) { - char* msg = 0; - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW(message, ("code",ec).set("message",msg)); - } - return ec; - } -#endif - -#ifdef OLD_BLOCKING - // this version is a little different, it handles functions like libssh2_sftp_init which return - // a pointer instead of an int. These retry automatically if the result is NULL and the error - // is LIBSSH2_ERROR_EAGAIN - template - return_type client_impl::call_ssh2_ptr_function_throw(std::function lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { - fc::scoped_lock lock(ssh_session_mutex); - return_type ret = lambda(); - while (!ret) { - char* msg = 0; - int ec = libssh2_session_last_error(session,&msg,NULL,0); - if ( ec == LIBSSH2_ERROR_EAGAIN ) { - wait_on_socket(); - ret = lambda(); - } else if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { - ec = libssh2_sftp_last_error(sftp); - FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); - } else { - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW(message, ("code",ec).set("message",msg)); - } - } - assert(!check_for_errors || !session->packet.olen); - - return ret; - } -#else - // this version is a little different, it handles functions like libssh2_sftp_init which return - // a pointer instead of an int. These retry automatically if the result is NULL and the error - // is LIBSSH2_ERROR_EAGAIN - template - return_type client_impl::call_ssh2_ptr_function_throw(std::function lambda, const char* message /* = "libssh2 call failed ${code} - ${message}" */, bool check_for_errors /* = true */) { - fc::unique_lock lock(ssh_session_mutex); - return_type ret = lambda(); - while (!ret) { - char* msg = 0; - int ec = libssh2_session_last_error(session,&msg,NULL,0); - if ( ec == LIBSSH2_ERROR_EAGAIN ) { - bool unlock_to_wait = !session->packet.olen; - if (unlock_to_wait) - lock.unlock(); - wait_on_socket(); - if (unlock_to_wait) - lock.lock(); - ret = lambda(); - } else if (ec == LIBSSH2_ERROR_SFTP_PROTOCOL && sftp) { - ec = libssh2_sftp_last_error(sftp); - FC_THROW(message, ("code", ec).set("message", "SFTP protocol error")); - } else { - ec = libssh2_session_last_error( session, &msg, 0, 0 ); - FC_THROW(message, ("code",ec).set("message",msg)); - } - } - assert(!check_for_errors || !session->packet.olen); - - return ret; - } -#endif - } - -} } diff --git a/src/ssh/process.cpp b/src/ssh/process.cpp deleted file mode 100644 index 8794c11..0000000 --- a/src/ssh/process.cpp +++ /dev/null @@ -1,334 +0,0 @@ -#define NOMINMAX // prevent windows from defining min and max macros -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "client_impl.hpp" - -#if defined (_MSC_VER) -#pragma warning (disable : 4355) -#endif - -namespace fc { namespace ssh { - - namespace detail { - class process_impl; - class process_istream : public fc::istream { - public: - process_istream( process_impl& p, int c ) - :proc(p),chan(c){} - - virtual size_t readsome( char* buf, size_t len ); - - virtual bool eof() const; - - process_impl& proc; - int chan; - }; - - class process_ostream : public fc::ostream { - public: - process_ostream( process_impl& p ) - :proc(p){} - - virtual size_t writesome( const char* buf, size_t len ); - virtual void close(); - virtual void flush(); - - process_impl& proc; - }; - - class process_impl { - public: - process_impl( client_ptr c ); - ~process_impl(); - //process_impl( const client& c, const fc::string& cmd, const fc::string& pty_type ); - void exec(const fc::path& exe, vector args, - const fc::path& work_dir /* = fc::path() */, fc::iprocess::exec_opts opts /* = open_all */); - - - int read_some( char* data, size_t len, int stream_id ); - int write_some( const char* data, size_t len, int stream_id ); - void flush(); - void send_eof(); - - LIBSSH2_CHANNEL* chan; - client_ptr sshc; - buffered_ostream_ptr buffered_std_in; - buffered_istream_ptr buffered_std_out; - buffered_istream_ptr buffered_std_err; - - fc::string command; - fc::promise::ptr result; - - fc::optional return_code; - fc::ostring return_signal; - fc::ostring return_signal_message; - private: - static fc::string windows_shell_escape(const fc::string& str); - static fc::string unix_shell_escape(const fc::string& str); - static fc::string windows_shell_escape_command(const fc::path& exe, const vector& args); - static fc::string unix_shell_escape_command(const fc::path& exe, const vector& args); - }; - - } // end namespace detail - - - process::process(client_ptr c) : - my(new detail::process_impl(c)) - {} - - process::~process() - {} - - iprocess& process::exec( const fc::path& exe, vector args, - const fc::path& work_dir /* = fc::path() */, exec_opts opts /* = open_all */ ) { - my->exec(exe, args, work_dir, opts); - return *this; - } - - /** - * Blocks until the result code of the process has been returned. - */ - int process::result() { - if (!my->return_code && !my->return_signal) { - // we don't have any cached exit status, so wait and obtain the values now - my->sshc->my->call_ssh2_function(boost::bind(libssh2_channel_wait_eof, my->chan)); - my->sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_wait_closed, my->chan), - "Error waiting on socket to close: ${message}"); - - char* exit_signal; - char* error_message; - libssh2_channel_get_exit_signal(my->chan, &exit_signal, NULL, &error_message, NULL, NULL, NULL); - if (exit_signal) { - // process terminated with a signal - my->return_signal = exit_signal; - libssh2_free(my->chan->session, exit_signal); - if (error_message) { - my->return_signal_message = error_message; - libssh2_free(my->chan->session, error_message); - } - } else - my->return_code = libssh2_channel_get_exit_status(my->chan); - } - if (my->return_signal) - FC_THROW("process terminated with signal ${signal}: ${signal_message}", ("signal", *my->return_signal) - ("signal_message", my->return_signal_message ? *my->return_signal_message : "")); - else - return *my->return_code; - } - - void process::kill() { - elog("error: fc::ssh::process::kill() not supported"); - } - - - /** - * @brief returns a stream that writes to the procss' stdin - */ - fc::buffered_ostream_ptr process::in_stream() { - return my->buffered_std_in; - } - - /** - * @brief returns a stream that reads from the process' stdout - */ - fc::buffered_istream_ptr process::out_stream() { - return my->buffered_std_out; - } - - /** - * @brief returns a stream that reads from the process' stderr - */ - fc::buffered_istream_ptr process::err_stream() { - return my->buffered_std_err; - } - - void detail::process_impl::flush() { - if( !chan ) return; - /* channel_flush deleates input buffer, and does not ensure writes go out - * - int ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_flush_ex( chan, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA ); - } - ec = libssh2_channel_flush( chan ); - while( ec == LIBSSH2_ERROR_EAGAIN ) { - sshc.my->wait_on_socket(); - ec = libssh2_channel_flush( chan ); - } - if( ec < 0 ) { - FC_THROW( "ssh flush failed", ( "channel_error", ec) ); - } - */ - } - - int detail::process_impl::read_some( char* data, size_t len, int stream_id ){ - if( !sshc->my->session ) { FC_THROW( "Session closed" ); } - int rc; - char* buf = data; - size_t buflen = len; - do { - rc = sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_read_ex, chan, stream_id, buf, buflen), - "read failed: ${message}"); - if( rc > 0 ) { - buf += rc; - buflen -= rc; - return buf-data; - } else if( rc == 0 ) { - if( libssh2_channel_eof( chan ) ) - return -1; // eof - sshc->my->wait_on_socket(); - } - } while( rc >= 0 && buflen); - return buf-data; - } - - int detail::process_impl::write_some( const char* data, size_t len, int stream_id ) { - if( !sshc->my->session ) { FC_THROW( "Session closed" ); } - - int rc; - const char* buf = data; - size_t buflen = len; - do { - rc = sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_write_ex, chan, stream_id, buf, buflen), - "write failed: ${message}"); - if( rc > 0 ) { - buf += rc; - buflen -= rc; - return buf-data; - } else if( rc == 0 ) { - if( libssh2_channel_eof( chan ) ) { - FC_THROW( "EOF" ); - //return -1; // eof - } - } - } while( rc >= 0 && buflen); - return buf-data; - } - - void detail::process_impl::send_eof() { - if( sshc->my->session ) - sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_send_eof, chan), - "send eof failed: ${message}"); - } - - size_t detail::process_istream::readsome( char* buf, size_t len ) { - int bytesRead = proc.read_some(buf, len, chan); - if (bytesRead < 0) - FC_THROW("EOF"); - else - return bytesRead; - } - - bool detail::process_istream::eof()const { - return 0 != libssh2_channel_eof( proc.chan ); - } - - size_t detail::process_ostream::writesome( const char* buf, size_t len ) { - return proc.write_some(buf, len, 0); - } - - void detail::process_ostream::close(){ - proc.send_eof(); - } - - void detail::process_ostream::flush(){ - proc.flush(); - } - - detail::process_impl::process_impl( client_ptr c ) - :chan(nullptr), - sshc(c), - buffered_std_in(new buffered_ostream(ostream_ptr(new process_ostream(*this)))), - buffered_std_out(new buffered_istream(istream_ptr(new process_istream(*this, 0)))), - buffered_std_err(new buffered_istream(istream_ptr(new process_istream(*this, SSH_EXTENDED_DATA_STDERR)))) - { - } - - detail::process_impl::~process_impl() { - if (chan) { - sshc->my->call_ssh2_function(boost::bind(libssh2_channel_free, chan)); - chan = NULL; - } - } - - // these rules work pretty well for a standard bash shell on unix - fc::string detail::process_impl::unix_shell_escape(const fc::string& str) { - if (str.find_first_of(" ;&|><*?`$(){}[]!#'\"") == fc::string::npos) - return str; - fc::string escaped_quotes(str); - for (size_t start = escaped_quotes.find("'"); - start != fc::string::npos; - start = escaped_quotes.find("'", start + 5)) - escaped_quotes.replace(start, 1, "'\"'\"'"); - fc::string escaped_str("\'"); - escaped_str += escaped_quotes; - escaped_str += "\'"; - return escaped_str; - } - fc::string detail::process_impl::unix_shell_escape_command(const fc::path& exe, const vector& args) { - fc::stringstream command_line; - command_line << unix_shell_escape(exe.string()); - for (unsigned i = 0; i < args.size(); ++i) - command_line << " " << unix_shell_escape(args[i]); - return command_line.str(); - } - - // windows command-line escaping rules are a disaster, partly because how the command-line is - // parsed depends on what program you're running. In windows, the command line is passed in - // as a single string, and the process is left to interpret it as it sees fit. The standard - // C runtime uses one set of rules, the function CommandLineToArgvW usually used by - // GUI-mode programs uses a different set. - // Here we try to find a common denominator that works well for simple cases - // it's only minimally tested right now due to time constraints. - fc::string detail::process_impl::windows_shell_escape(const fc::string& str) { - if (str.find_first_of(" \"") == fc::string::npos) - return str; - fc::string escaped_quotes(str); - for (size_t start = escaped_quotes.find("\""); - start != fc::string::npos; - start = escaped_quotes.find("\"", start + 2)) - escaped_quotes.replace(start, 1, "\\\""); - fc::string escaped_str("\""); - escaped_str += escaped_quotes; - escaped_str += "\""; - return escaped_str; - } - fc::string detail::process_impl::windows_shell_escape_command(const fc::path& exe, const vector& args) { - fc::stringstream command_line; - command_line << windows_shell_escape(exe.string()); - for (unsigned i = 0; i < args.size(); ++i) - command_line << " " << windows_shell_escape(args[i]); - return command_line.str(); - } - - void detail::process_impl::exec(const fc::path& exe, vector args, - const fc::path& work_dir /* = fc::path() */, - fc::iprocess::exec_opts opts /* = open_all */) { - chan = sshc->my->open_channel(""); - - sshc->my->call_ssh2_function(boost::bind(libssh2_channel_handle_extended_data2, chan, LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL)); - - try { - fc::scoped_lock process_startup_lock(sshc->my->process_startup_mutex); - fc::string command_line = sshc->my->remote_system_is_windows ? windows_shell_escape_command(exe, args) : unix_shell_escape_command(exe, args); - sshc->my->call_ssh2_function_throw(boost::bind(libssh2_channel_process_startup, chan, "exec", sizeof("exec") - 1, command_line.c_str(), command_line.size()), - "exec failed: ${message}"); // equiv to libssh2_channel_exec(chan, cmd) macro - } catch (fc::exception& er) { - elog( "error starting process" ); - FC_RETHROW_EXCEPTION(er, error, "error starting process"); - } - } - -} } diff --git a/src/string.cpp b/src/string.cpp old mode 100644 new mode 100755 index 0b7cb9f..84edb88 --- a/src/string.cpp +++ b/src/string.cpp @@ -172,6 +172,91 @@ namespace fc { return result; } + /** + * Parses a size including an optional multiplicative suffix. + * + * M -> 1024*1024 bytes + * MB -> 1000*1000 bytes + * MiB -> 1024*1024 bytes + * + * The 'M' may be any of KMGTPEZY (upper or lower case) + */ + uint64_t parse_size( const string& s ) + { + try + { + size_t i = 0, n = s.size(), suffix_start = n; + for( i=0; i= '0') && (s[i] <= '9')) ) + { + suffix_start = i; + break; + } + } + uint64_t u = to_uint64( s.substr( 0, suffix_start ) ); + + FC_ASSERT( n - suffix_start <= 3 ); + + uint64_t m = 1; + uint64_t thousand = 1024; + + if( suffix_start == n ) + { + return u; + } + else if( suffix_start == n-1 ) + { + } + else if( suffix_start == n-2 ) + { + FC_ASSERT( (s[suffix_start+1] == 'b') || (s[suffix_start+1] == 'B') ); + thousand = 1000; + } + else if( suffix_start == n-3 ) + { + FC_ASSERT( (s[suffix_start+1] == 'i') || (s[suffix_start+1] == 'I') ); + FC_ASSERT( (s[suffix_start+2] == 'b') || (s[suffix_start+2] == 'B') ); + } + switch( s[suffix_start] ) + { + case 'y': + case 'Y': + m *= thousand; + case 'z': + case 'Z': + m *= thousand; + case 'e': + case 'E': + m *= thousand; + case 'p': + case 'P': + m *= thousand; + case 't': + case 'T': + m *= thousand; + case 'g': + case 'G': + m *= thousand; + case 'm': + case 'M': + m *= thousand; + case 'k': + case 'K': + m *= thousand; + break; + default: + FC_ASSERT( false ); + } + return u*m; + } + catch( const fc::exception& e ) + { + FC_THROW_EXCEPTION( parse_error_exception, "Couldn't parse size" ); + } + } + + } // namespace fc diff --git a/src/thread/context.hpp b/src/thread/context.hpp old mode 100644 new mode 100755 index f6e8a77..18a060c --- a/src/thread/context.hpp +++ b/src/thread/context.hpp @@ -6,7 +6,15 @@ #include -#if BOOST_VERSION >= 105400 +#define BOOST_COROUTINES_NO_DEPRECATION_WARNING // Boost 1.61 +#define BOOST_COROUTINE_NO_DEPRECATION_WARNING // Boost 1.62 + +#if BOOST_VERSION >= 106100 + #include + namespace bc = boost::context::detail; + namespace bco = boost::coroutines; + typedef bco::stack_allocator stack_allocator; +#elif BOOST_VERSION >= 105400 # include namespace bc = boost::context; namespace bco = boost::coroutines; @@ -47,8 +55,13 @@ namespace fc { bco::stack_context stack_ctx; #endif +#if BOOST_VERSION >= 106100 + using context_fn = void (*)(bc::transfer_t); +#else + using context_fn = void(*)(intptr_t); +#endif - context( void (*sf)(intptr_t), stack_allocator& alloc, fc::thread* t ) + context( context_fn sf, stack_allocator& alloc, fc::thread* t ) : caller_context(0), stack_alloc(&alloc), next_blocked(0), diff --git a/src/thread/future.cpp b/src/thread/future.cpp old mode 100644 new mode 100755 diff --git a/src/thread/mutex.cpp b/src/thread/mutex.cpp old mode 100644 new mode 100755 diff --git a/src/thread/non_preemptable_scope_check.cpp b/src/thread/non_preemptable_scope_check.cpp old mode 100644 new mode 100755 diff --git a/src/thread/spin_lock.cpp b/src/thread/spin_lock.cpp old mode 100644 new mode 100755 diff --git a/src/thread/spin_yield_lock.cpp b/src/thread/spin_yield_lock.cpp old mode 100644 new mode 100755 diff --git a/src/thread/task.cpp b/src/thread/task.cpp old mode 100644 new mode 100755 diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp old mode 100644 new mode 100755 index eaa8e40..7b899bb --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -5,7 +5,7 @@ #include "thread_d.hpp" #if defined(_MSC_VER) && !defined(NDEBUG) -# include +# include const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) @@ -92,7 +92,7 @@ namespace fc { p->wait(); my->boost_thread = t; my->name = name; - wlog("name:${n} tid:${tid}", ("n", name)("tid", (uintptr_t)my->boost_thread->native_handle()) ); + //wlog("name:${n} tid:${tid}", ("n", name)("tid", (uintptr_t)my->boost_thread->native_handle()) ); } thread::thread( thread_d* ) { my = new thread_d(*this); @@ -118,24 +118,24 @@ namespace fc { } thread& thread::current() { - if( !current_thread() ) + if( !current_thread() ) current_thread() = new thread((thread_d*)0); return *current_thread(); } - const string& thread::name()const - { - return my->name; + const string& thread::name()const + { + return my->name; } void thread::set_name( const fc::string& n ) - { + { if (!is_current()) { async([=](){ set_name(n); }, "set_name").wait(); return; } - my->name = n; + my->name = n; set_thread_name(my->name.c_str()); // set thread's name for the debugger to display } @@ -145,17 +145,17 @@ namespace fc { return my->current->cur_task->get_desc(); return NULL; } - + void thread::debug( const fc::string& d ) { /*my->debug(d);*/ } - void thread::quit() + void thread::quit() { //if quitting from a different thread, start quit task on thread. //If we have and know our attached boost thread, wait for it to finish, then return. - if( ¤t() != this ) + if( ¤t() != this ) { async( [=](){quit();}, "thread::quit" );//.wait(); - if( my->boost_thread ) + if( my->boost_thread ) { //wlog("destroying boost thread ${tid}",("tid",(uintptr_t)my->boost_thread->native_handle())); my->boost_thread->join(); @@ -170,23 +170,23 @@ namespace fc { // We are quiting from our own thread... // break all promises, thread quit! - while( my->blocked ) + while( my->blocked ) { fc::context* cur = my->blocked; - while( cur ) + while( cur ) { fc::context* n = cur->next; // this will move the context into the ready list. //cur->prom->set_exception( boost::copy_exception( error::thread_quit() ) ); //cur->set_exception_on_blocking_promises( thread_quit() ); cur->set_exception_on_blocking_promises( std::make_shared(FC_LOG_MESSAGE(error, "cancellation reason: thread quitting")) ); - + cur = n; } - if( my->blocked ) - { + if( my->blocked ) + { //wlog( "still blocking... whats up with that?"); - debug( "on quit" ); + debug( "on quit" ); } } BOOST_ASSERT( my->blocked == 0 ); @@ -200,7 +200,7 @@ namespace fc { scheduled_task->set_exception(std::make_shared(FC_LOG_MESSAGE(error, "cancellation reason: thread quitting"))); my->task_sch_queue.clear(); - + // move all sleep tasks to ready for( uint32_t i = 0; i < my->sleep_pqueue.size(); ++i ) @@ -209,7 +209,7 @@ namespace fc { // move all idle tasks to ready fc::context* cur = my->pt_head; - while( cur ) + while( cur ) { fc::context* n = cur->next; cur->next = 0; @@ -217,7 +217,7 @@ namespace fc { cur = n; } - // mark all ready tasks (should be everyone)... as canceled + // mark all ready tasks (should be everyone)... as canceled for (fc::context* ready_context : my->ready_heap) ready_context->canceled = true; @@ -225,22 +225,22 @@ namespace fc { // let them all quit. while (!my->ready_heap.empty()) { - my->start_next_fiber(true); + my->start_next_fiber(true); my->check_for_timeouts(); } my->clear_free_list(); my->cleanup_thread_specific_data(); } - - void thread::exec() + + void thread::exec() { - if( !my->current ) + if( !my->current ) my->current = new fc::context(&fc::thread::current()); - - try + + try { - my->process_tasks(); - } + my->process_tasks(); + } catch( canceled_exception& e ) { dlog( "thread canceled: ${e}", ("e", e.to_detail_string()) ); @@ -248,40 +248,40 @@ namespace fc { delete my->current; my->current = 0; } - - bool thread::is_running()const + + bool thread::is_running()const { return !my->done; } - - priority thread::current_priority()const + + priority thread::current_priority()const { BOOST_ASSERT(my); - if( my->current ) + if( my->current ) return my->current->prio; return priority(); } - void thread::yield(bool reschedule) + void thread::yield(bool reschedule) { my->check_fiber_exceptions(); my->start_next_fiber(reschedule); my->check_fiber_exceptions(); } - void thread::sleep_until( const time_point& tp ) + void thread::sleep_until( const time_point& tp ) { - if( tp <= (time_point::now()+fc::microseconds(10000)) ) + if( tp <= (time_point::now()+fc::microseconds(10000)) ) yield(true); my->yield_until( tp, false ); } int thread::wait_any_until( std::vector&& p, const time_point& timeout) { for( size_t i = 0; i < p.size(); ++i ) - if( p[i]->ready() ) + if( p[i]->ready() ) return i; - if( timeout < time_point::now() ) + if( timeout < time_point::now() ) { fc::stringstream ss; for( auto i = p.begin(); i != p.end(); ++i ) @@ -289,20 +289,20 @@ namespace fc { FC_THROW_EXCEPTION( timeout_exception, "${task}", ("task",ss.str()) ); } - + if( !my->current ) - my->current = new fc::context(&fc::thread::current()); - + my->current = new fc::context(&fc::thread::current()); + for( uint32_t i = 0; i < p.size(); ++i ) my->current->add_blocking_promise(p[i].get(),false); // if not max timeout, added to sleep pqueue - if( timeout != time_point::maximum() ) + if( timeout != time_point::maximum() ) { my->current->resume_time = timeout; my->sleep_pqueue.push_back(my->current); std::push_heap( my->sleep_pqueue.begin(), - my->sleep_pqueue.end(), + my->sleep_pqueue.end(), sleep_priority_less() ); } @@ -311,11 +311,11 @@ namespace fc { for( auto i = p.begin(); i != p.end(); ++i ) my->current->remove_blocking_promise(i->get()); - + my->check_fiber_exceptions(); for( uint32_t i = 0; i < p.size(); ++i ) - if( p[i]->ready() ) + if( p[i]->ready() ) return i; //BOOST_THROW_EXCEPTION( wait_any_error() ); @@ -342,8 +342,8 @@ namespace fc { // Because only one thread can post the 'first task', only that thread will attempt // to aquire the lock and therefore there should be no contention on this lock except - // when *this thread is about to block on a wait condition. - if( this != ¤t() && !stale_head ) { + // when *this thread is about to block on a wait condition. + if( this != ¤t() && !stale_head ) { boost::unique_lock lock(my->task_ready_mutex); my->task_ready.notify_one(); } @@ -359,42 +359,42 @@ namespace fc { thread::current().sleep_until(tp); } - void exec() + void exec() { return thread::current().exec(); } - int wait_any( std::vector&& v, const microseconds& timeout_us ) + int wait_any( std::vector&& v, const microseconds& timeout_us ) { return thread::current().wait_any_until( fc::move(v), time_point::now() + timeout_us ); } - int wait_any_until( std::vector&& v, const time_point& tp ) + int wait_any_until( std::vector&& v, const time_point& tp ) { return thread::current().wait_any_until( fc::move(v), tp ); } - void thread::wait_until( promise_base::ptr&& p, const time_point& timeout ) + void thread::wait_until( promise_base::ptr&& p, const time_point& timeout ) { - if( p->ready() ) + if( p->ready() ) return; - if( timeout < time_point::now() ) + if( timeout < time_point::now() ) FC_THROW_EXCEPTION( timeout_exception, "${task}", ("task", p->get_desc()) ); - - if( !my->current ) - my->current = new fc::context(&fc::thread::current()); - + + if( !my->current ) + my->current = new fc::context(&fc::thread::current()); + //slog( " %1% blocking on %2%", my->current, p.get() ); my->current->add_blocking_promise(p.get(), true); // if not max timeout, added to sleep pqueue - if( timeout != time_point::maximum() ) + if( timeout != time_point::maximum() ) { my->current->resume_time = timeout; my->sleep_pqueue.push_back(my->current); std::push_heap( my->sleep_pqueue.begin(), - my->sleep_pqueue.end(), + my->sleep_pqueue.end(), sleep_priority_less() ); } @@ -412,34 +412,34 @@ namespace fc { my->check_fiber_exceptions(); } - void thread::notify( const promise_base::ptr& p ) + void thread::notify( const promise_base::ptr& p ) { //slog( "this %p my %p", this, my ); BOOST_ASSERT(p->ready()); - if( !is_current() ) + if( !is_current() ) { this->async( [=](){ notify(p); }, "notify", priority::max() ); return; } - // TODO: store a list of blocked contexts with the promise + // TODO: store a list of blocked contexts with the promise // to accelerate the lookup.... unless it introduces contention... - + // iterate over all blocked contexts fc::context* cur_blocked = my->blocked; fc::context* prev_blocked = 0; - while( cur_blocked ) + while( cur_blocked ) { - // if the blocked context is waiting on this promise - if( cur_blocked->try_unblock( p.get() ) ) + // if the blocked context is waiting on this promise + if( cur_blocked->try_unblock( p.get() ) ) { // remove it from the blocked list. // remove this context from the sleep queue... - for( uint32_t i = 0; i < my->sleep_pqueue.size(); ++i ) + for( uint32_t i = 0; i < my->sleep_pqueue.size(); ++i ) { - if( my->sleep_pqueue[i] == cur_blocked ) + if( my->sleep_pqueue[i] == cur_blocked ) { my->sleep_pqueue[i]->blocking_prom.clear(); my->sleep_pqueue[i] = my->sleep_pqueue.back(); @@ -449,28 +449,28 @@ namespace fc { } } auto cur = cur_blocked; - if( prev_blocked ) - { - prev_blocked->next_blocked = cur_blocked->next_blocked; + if( prev_blocked ) + { + prev_blocked->next_blocked = cur_blocked->next_blocked; cur_blocked = prev_blocked->next_blocked; - } - else - { - my->blocked = cur_blocked->next_blocked; + } + else + { + my->blocked = cur_blocked->next_blocked; cur_blocked = my->blocked; } cur->next_blocked = 0; my->add_context_to_ready_list( cur ); - } - else + } + else { // goto the next blocked task prev_blocked = cur_blocked; cur_blocked = cur_blocked->next_blocked; } } } - - bool thread::is_current()const + + bool thread::is_current()const { return this == ¤t(); } diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp old mode 100644 new mode 100755 index 941b2fa..74b59d3 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -18,6 +18,7 @@ namespace fc { class thread_d { public: + using context_pair = std::pair; thread_d(fc::thread& s) :self(s), boost_thread(0), task_in_queue(0), @@ -397,7 +398,11 @@ namespace fc { } // slog( "jump to %p from %p", next, prev ); // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); -#if BOOST_VERSION >= 105600 +#if BOOST_VERSION >= 106100 + auto p = context_pair{nullptr, prev}; + auto t = bc::jump_fcontext( next->my_context, &p ); + static_cast(t.data)->second->my_context = t.fctx; +#elif BOOST_VERSION >= 105600 bc::jump_fcontext( &prev->my_context, next->my_context, 0 ); #elif BOOST_VERSION >= 105300 bc::jump_fcontext( prev->my_context, next->my_context, 0 ); @@ -439,7 +444,11 @@ namespace fc { // slog( "jump to %p from %p", next, prev ); // fc_dlog( logger::get("fc_context"), "from ${from} to ${to}", ( "from", int64_t(prev) )( "to", int64_t(next) ) ); -#if BOOST_VERSION >= 105600 +#if BOOST_VERSION >= 106100 + auto p = context_pair{this, prev}; + auto t = bc::jump_fcontext( next->my_context, &p ); + static_cast(t.data)->second->my_context = t.fctx; +#elif BOOST_VERSION >= 105600 bc::jump_fcontext( &prev->my_context, next->my_context, (intptr_t)this ); #elif BOOST_VERSION >= 105300 bc::jump_fcontext( prev->my_context, next->my_context, (intptr_t)this ); @@ -467,9 +476,17 @@ namespace fc { return true; } +#if BOOST_VERSION >= 106100 + static void start_process_tasks( bc::transfer_t my ) + { + auto p = static_cast(my.data); + auto self = static_cast(p->first); + p->second->my_context = my.fctx; +#else static void start_process_tasks( intptr_t my ) { thread_d* self = (thread_d*)my; +#endif try { self->process_tasks(); diff --git a/src/thread/thread_specific.cpp b/src/thread/thread_specific.cpp old mode 100644 new mode 100755 index a91236d..f04d6da --- a/src/thread/thread_specific.cpp +++ b/src/thread/thread_specific.cpp @@ -22,7 +22,7 @@ namespace fc { if (slot + 1 > specific_data->size()) specific_data->resize(slot + 1); - (*specific_data)[slot] = std::move(detail::specific_data_info(new_value, cleanup)); + (*specific_data)[slot] = detail::specific_data_info(new_value, cleanup); } void* get_thread_specific_data(unsigned slot) @@ -62,4 +62,4 @@ namespace fc } } } -} // end namespace fc \ No newline at end of file +} // end namespace fc diff --git a/src/time.cpp b/src/time.cpp old mode 100644 new mode 100755 diff --git a/src/uint128.cpp b/src/uint128.cpp old mode 100644 new mode 100755 index dae2aef..66128ce --- a/src/uint128.cpp +++ b/src/uint128.cpp @@ -1,15 +1,18 @@ #include #include #include +#include + #include #include "byteswap.hpp" namespace fc { + typedef boost::multiprecision::uint128_t m128; + template static void divide(const T &numerator, const T &denominator, T "ient, T &remainder) { - static const int bits = sizeof(T) * 8;//CHAR_BIT; if(denominator == 0) { @@ -220,8 +223,27 @@ namespace fc uint128& uint128::operator/=(const uint128 &b) { + auto self = (m128(hi) << 64) + m128(lo); + auto other = (m128(b.hi) << 64) + m128(b.lo); + self /= other; + hi = static_cast(self >> 64); + lo = static_cast((self << 64 ) >> 64); + + /* uint128 remainder; - divide(*this, b, *this, remainder); + divide(*this, b, *this, remainder ); //, *this); + if( tmp.hi != hi || tmp.lo != lo ) { + std::cerr << tmp.hi << " " << hi <<"\n"; + std::cerr << tmp.lo << " " << lo << "\n"; + exit(1); + } + */ + + /* + const auto& b128 = std::reinterpret_cast(b); + auto& this128 = std::reinterpret_cast(*this); + this128 /= b128; + */ return *this; } diff --git a/src/utf8.cpp b/src/utf8.cpp old mode 100644 new mode 100755 index 0bab5e0..14551c4 --- a/src/utf8.cpp +++ b/src/utf8.cpp @@ -3,16 +3,36 @@ #include "utf8/checked.h" #include "utf8/core.h" #include "utf8/unchecked.h" +#include #include +#include +#include namespace fc { bool is_utf8( const std::string& str ) { + auto itr = utf8::find_invalid(str.begin(), str.end()); return utf8::is_valid( str.begin(), str.end() ); } + string prune_invalid_utf8( const string& str ) { + string result; + + auto itr = utf8::find_invalid(str.begin(), str.end()); + if( itr == str.end() ) return str; + + result = string( str.begin(), itr ); + while( itr != str.end() ) { + ++itr; + auto start = itr; + itr = utf8::find_invalid( start, str.end()); + result += string( start, itr ); + } + return result; + } + void decodeUtf8(const std::string& input, std::wstring* storage) { assert(storage != nullptr); diff --git a/src/utf8/ReleaseNotes b/src/utf8/ReleaseNotes old mode 100644 new mode 100755 diff --git a/src/utf8/checked.h b/src/utf8/checked.h old mode 100644 new mode 100755 diff --git a/src/utf8/core.h b/src/utf8/core.h old mode 100644 new mode 100755 diff --git a/src/utf8/unchecked.h b/src/utf8/unchecked.h old mode 100644 new mode 100755 diff --git a/src/utf8/utf8cpp.html b/src/utf8/utf8cpp.html old mode 100644 new mode 100755 diff --git a/src/variant.cpp b/src/variant.cpp old mode 100644 new mode 100755 index 542ee66..3af5683 --- a/src/variant.cpp +++ b/src/variant.cpp @@ -663,7 +663,7 @@ void from_variant( const variant& var, std::vector& vo ) if( vo.size() ) { size_t r = from_hex( str, vo.data(), vo.size() ); - FC_ASSERT( r = vo.size() ); + FC_ASSERT( r == vo.size() ); } // std::string b64 = base64_decode( var.as_string() ); // vo = std::vector( b64.c_str(), b64.c_str() + b64.size() ); diff --git a/src/variant_object.cpp b/src/variant_object.cpp old mode 100644 new mode 100755 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100755 index 0000000..c3f125d --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,56 @@ + +add_executable( bip_lock bip_lock.cpp ) +target_link_libraries( bip_lock fc ) + +add_executable( api api.cpp ) +target_link_libraries( api fc ) + +if( ECC_IMPL STREQUAL secp256k1 ) + add_executable( blind all_tests.cpp crypto/blind.cpp ) + target_link_libraries( blind fc ) +endif() + +add_executable( task_cancel_test all_tests.cpp thread/task_cancel.cpp ) +target_link_libraries( task_cancel_test fc ) + + +add_executable( bloom_test all_tests.cpp bloom_test.cpp ) +target_link_libraries( bloom_test fc ) + +add_executable( real128_test all_tests.cpp real128_test.cpp ) +target_link_libraries( real128_test fc ) + +add_executable( hmac_test hmac_test.cpp ) +target_link_libraries( hmac_test fc ) + +add_executable( ecc_test crypto/ecc_test.cpp ) +target_link_libraries( ecc_test fc ) + +add_executable( log_test crypto/log_test.cpp ) +target_link_libraries( log_test fc ) + +#add_executable( test_aes aes_test.cpp ) +#target_link_libraries( test_aes fc ${rt_library} ${pthread_library} ) +#add_executable( test_sleep sleep.cpp ) +#target_link_libraries( test_sleep fc ) +#add_executable( test_rate_limiting rate_limiting.cpp ) +#target_link_libraries( test_rate_limiting fc ) + +add_executable( all_tests all_tests.cpp + compress/compress.cpp + crypto/aes_test.cpp + crypto/base_n_tests.cpp + crypto/bigint_test.cpp + crypto/blind.cpp + crypto/blowfish_test.cpp + crypto/dh_test.cpp + crypto/rand_test.cpp + crypto/sha_tests.cpp + network/http/websocket_test.cpp + thread/task_cancel.cpp + thread/thread_tests.cpp + bloom_test.cpp + real128_test.cpp + utf8_test.cpp + ) +target_link_libraries( all_tests fc ) diff --git a/tests/all_tests.cpp b/tests/all_tests.cpp old mode 100644 new mode 100755 diff --git a/tests/api.cpp b/tests/api.cpp old mode 100644 new mode 100755 diff --git a/tests/bip_lock.cpp b/tests/bip_lock.cpp new file mode 100755 index 0000000..38bf684 --- /dev/null +++ b/tests/bip_lock.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include + +int main( int argc, char** argv ) { + if( argc < 2 ) return 0; + fc::file_mutex m( argv[1] ); + auto mptr = &m; + + fc::thread in("in"); + + std::string cmd; + std::cout << ">>> "; + std::cin >> cmd; + int i = 0; + while( !std::cin.eof() && cmd != "q" ) { + ++i; + fc::async( [i, cmd,mptr]() { + ilog( "start ${c} ${i}", ("c",cmd)("i",i) ); + if( cmd == "L" ) { + mptr->lock(); + } else if( cmd == "l" ) { + mptr->lock_shared(); + } else if( cmd == "U" ) { + mptr->unlock(); + } else if( cmd == "u" ) { + mptr->unlock_shared(); + } + ilog( "end ${c} ${i}", ("c",cmd)("i",i) ); + } ); + fc::usleep( fc::microseconds( 1000 ) ); + cmd = in.async( [&]() { + std::string tmp; + wdump((m.readers())); + std::cin >> tmp; + return tmp; + } ); + } + std::cout << "done"; + + return 0; +} diff --git a/tests/blinding_test.cpp b/tests/blinding_test.cpp old mode 100644 new mode 100755 index 318f161..b363ab1 --- a/tests/blinding_test.cpp +++ b/tests/blinding_test.cpp @@ -42,7 +42,7 @@ static fc::string BLIND_T_X = "80deff382af8a8e4a5f297588e44d5bf858f30a524f74b13e static fc::string BLINDED_HASH = "7196e80cdafdfdfb7496323ad24bf47dda8447febd7426e444facc04940c7309"; static fc::string BLIND_SIG = "40d6a477d849cc860df8ad159481f2ffc5b4dc3131b86a799d7d10460824dd53"; static fc::string UNBLINDED = "700092a72a05e33509f9b068aa1d7c5336d8b5692b4157da199d7ec1e10fd7c0"; - +/* BOOST_AUTO_TEST_CASE(test_extended_keys_1) { char seed[16]; @@ -302,3 +302,4 @@ BOOST_AUTO_TEST_CASE(openssl_blinding) // printf("\nunblinded: "); print(sig->s); // printf("\n"); } +*/ \ No newline at end of file diff --git a/tests/bloom_test.cpp b/tests/bloom_test.cpp old mode 100644 new mode 100755 diff --git a/tests/compress/compress.cpp b/tests/compress/compress.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/aes_test.cpp b/tests/crypto/aes_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/base_n_tests.cpp b/tests/crypto/base_n_tests.cpp old mode 100644 new mode 100755 index a501123..4ec3c1d --- a/tests/crypto/base_n_tests.cpp +++ b/tests/crypto/base_n_tests.cpp @@ -1,7 +1,6 @@ #include #include -#include #include #include #include @@ -44,29 +43,6 @@ BOOST_AUTO_TEST_CASE(hex_test) } -static void test_32( const std::string& test, const std::string& expected ) -{ - std::vector vec( test.begin(), test.end() ); - fc::string enc1 = fc::to_base32( vec ); - fc::string enc2 = fc::to_base32( test.c_str(), test.size() ); - BOOST_CHECK_EQUAL( enc1, enc2 ); - BOOST_CHECK_EQUAL( expected, enc2 ); - - std::vector dec = fc::from_base32( enc1 ); - BOOST_CHECK_EQUAL( vec.size(), dec.size() ); - BOOST_CHECK( !memcmp( vec.data(), dec.data(), vec.size() ) ); -} - -BOOST_AUTO_TEST_CASE(base32_test) -{ - test_32( TEST1, "" ); - test_32( TEST2, "AAATAMI=" ); - test_32( TEST3, "IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======" ); - test_32( TEST4, "777AB7IB7Q======" ); - test_32( TEST5, "AAAAA===" ); -} - - static void test_36( const std::string& test, const std::string& expected ) { std::vector vec( test.begin(), test.end() ); diff --git a/tests/crypto/bigint_test.cpp b/tests/crypto/bigint_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/blind.cpp b/tests/crypto/blind.cpp old mode 100644 new mode 100755 index 29f81f9..33dfb46 --- a/tests/crypto/blind.cpp +++ b/tests/crypto/blind.cpp @@ -50,15 +50,15 @@ BOOST_AUTO_TEST_CASE(blind_test) auto B4 = fc::sha256::hash("B4"); auto C1 = fc::ecc::blind( B1, 1 ); auto C2 = fc::ecc::blind( B2, 2 ); - auto c3 = fc::ecc::blind( b3, 3 ); - auto C4 = fc::ecc::blind( B4, -1 ); + /*auto c3 = */fc::ecc::blind( b3, 3 ); + /*auto C4 = */fc::ecc::blind( B4, -1 ); auto B3 = fc::ecc::blind_sum( {B1,B2}, 2 ); auto C3 = fc::ecc::blind( B3, 3 ); auto B2m1 = fc::ecc::blind_sum( {B2,B1}, 1 ); - auto C2m1 = fc::ecc::blind( B2m1, 1 ); + /*auto C2m1 = */fc::ecc::blind( B2m1, 1 ); BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3}, 0 ) ); BOOST_CHECK( fc::ecc::verify_sum( {C1,C2}, {C3}, 0 ) ); @@ -68,9 +68,9 @@ BOOST_AUTO_TEST_CASE(blind_test) { auto B1 = fc::sha256::hash("B1"); - auto B2 = fc::sha256::hash("B2"); - auto B3 = fc::sha256::hash("B3"); - auto B4 = fc::sha256::hash("B4"); + /*auto B2 = */fc::sha256::hash("B2"); + /*auto B3 = */fc::sha256::hash("B3"); + /*auto B4 = */fc::sha256::hash("B4"); //secp256k1_scalar_get_b32((unsigned char*)&B1, (const secp256k1_scalar_t*)&B2); //B1 = fc::variant("b2e5da56ef9f2a34d3e22fd12634bc99261e95c87b9960bf94ed3d27b30").as(); @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(blind_test) auto C1 = fc::ecc::blind( B1, INT64_MAX ); auto C2 = fc::ecc::blind( B1, 0 ); auto C3 = fc::ecc::blind( B1, 1 ); - auto C4 = fc::ecc::blind( B1, 2 ); + /*auto C4 = */fc::ecc::blind( B1, 2 ); BOOST_CHECK( fc::ecc::verify_sum( {C2}, {C3}, -1 ) ); BOOST_CHECK( fc::ecc::verify_sum( {C1}, {C1}, 0 ) ); diff --git a/tests/crypto/blowfish_test.cpp b/tests/crypto/blowfish_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/dh_test.cpp b/tests/crypto/dh_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/ecc_test.cpp b/tests/crypto/ecc_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/log_test.cpp b/tests/crypto/log_test.cpp new file mode 100755 index 0000000..654c95c --- /dev/null +++ b/tests/crypto/log_test.cpp @@ -0,0 +1,114 @@ + +#include + +#include +#include + +#include +#include +#include + +uint64_t endian_reverse( uint64_t x ) +{ + uint64_t x0 = ((x ) & 0xFF); + uint64_t x1 = ((x >> 0x08) & 0xFF); + uint64_t x2 = ((x >> 0x10) & 0xFF); + uint64_t x3 = ((x >> 0x18) & 0xFF); + uint64_t x4 = ((x >> 0x20) & 0xFF); + uint64_t x5 = ((x >> 0x28) & 0xFF); + uint64_t x6 = ((x >> 0x30) & 0xFF); + uint64_t x7 = ((x >> 0x38) & 0xFF); + + return (x0 << 0x38) + | (x1 << 0x30) + | (x2 << 0x28) + | (x3 << 0x20) + | (x4 << 0x18) + | (x5 << 0x10) + | (x6 << 0x08) + | (x7 ); +} + +int main(int argc, char**argv, char** envp) +{ + std::ifstream infile("log_test.txt"); + uint32_t ref_clz; + std::string str_h; + uint32_t ref_log; + uint32_t cases = 0; + uint32_t errors = 0; + + while( true ) + { + if( !(infile >> std::hex >> ref_clz) ) + break; + if( !(infile >> str_h) ) + break; + if( !(infile >> std::hex >> ref_log) ) + break; + fc::sha256 h(str_h); + if( ref_clz != h.clz() ) + { + std::cerr << "got error on clz(" << str_h << ")" << std::endl; + ++errors; + } + if( ref_log != h.approx_log_32() ) + { + std::cerr << "got error on log(" << str_h << ")" << std::endl; + ++errors; + } + double d_ilog_h_test = h.inverse_approx_log_32_double( ref_log ); + h.set_to_inverse_approx_log_32( ref_log ); + if( ref_log != h.approx_log_32() ) + { + std::cerr << "got error on ilog(" << ref_log << ")" << std::endl; + ++errors; + } + + std::string str_ilog_h = h.str(); + boost::multiprecision::uint256_t u256_ilog_h( "0x" + str_ilog_h ); + double d_ilog_h_ref = u256_ilog_h.template convert_to(); + if( d_ilog_h_ref != d_ilog_h_test ) + { + std::cerr << "got error on d_ilog(" << ref_log << ")" << std::endl; + ++errors; + } + + if( h != fc::sha256() ) + { + fc::sha256 h_before = h; + if( h._hash[3] == 0 ) + { + if( h._hash[2] == 0 ) + { + if( h._hash[1] == 0 ) + { + h._hash[0] = endian_reverse( endian_reverse( h._hash[0] )-1 ); + } + h._hash[1] = endian_reverse( endian_reverse( h._hash[1] )-1 ); + } + h._hash[2] = endian_reverse( endian_reverse( h._hash[2] )-1 ); + } + h._hash[3] = endian_reverse( endian_reverse( h._hash[3] )-1 ); + bool ok = (h.approx_log_32() < ref_log); + if( !ok ) + { + std::cerr << "got error on logm1 for " << ref_log << std::endl; + std::cerr << "h0:" << str_h << std::endl; + std::cerr << "h1:" << h_before.str() << std::endl; + std::cerr << "h2:" << h.str() << std::endl; + std::cerr << "ref_log:" << std::hex << std::setw(8) << ref_log << std::endl; + std::cerr << "log(h) :" << std::hex << std::setw(8) << h.approx_log_32() << std::endl; + std::cerr << std::endl; + ++errors; + } + } + + ++cases; + } + + std::cerr << "sha256_log_test checked " << cases << " cases, got " << errors << " errors" << std::endl; + if( errors ) + return 1; + return 0; +} diff --git a/tests/crypto/log_test.py b/tests/crypto/log_test.py new file mode 100755 index 0000000..ec5c7fe --- /dev/null +++ b/tests/crypto/log_test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +# Independent implementation of algorithm +# To create log_test.txt, run ./log_test.py > log_test.txt + +import random + +rand = random.Random(1234) + +result = set() + +result.add((0, 256)) +result.add(((1 << 256)-1, 0)) +for i in range(256): + y = (1 << i) + result.add((y, 255-i)) + for j in range(32): + result.add((y+rand.randrange(0, y), 255-i)) + +def get_sem_32(y): + bs = "{:0256b}".format(y) + if "1" not in bs: + return 0 + bs += 32*"0" + i = bs.index("1") + return ((255-i) << 24) | int(bs[i+1:i+25], 2) + +for y, lz in sorted(result): + print("{:02x}".format(lz), "{:064x}".format(y), "{:08x}".format(get_sem_32(y))) diff --git a/tests/crypto/rand_test.cpp b/tests/crypto/rand_test.cpp old mode 100644 new mode 100755 diff --git a/tests/crypto/sha_tests.cpp b/tests/crypto/sha_tests.cpp old mode 100644 new mode 100755 diff --git a/tests/hmac_test.cpp b/tests/hmac_test.cpp old mode 100644 new mode 100755 diff --git a/tests/network/http/websocket_test.cpp b/tests/network/http/websocket_test.cpp old mode 100644 new mode 100755 diff --git a/tests/network/ntp_test.cpp b/tests/network/ntp_test.cpp deleted file mode 100644 index f0c02d4..0000000 --- a/tests/network/ntp_test.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include - -#include -#include -#include - -BOOST_AUTO_TEST_SUITE(fc_network) - -BOOST_AUTO_TEST_CASE( ntp_test ) -{ - fc::ntp ntp_service; - ntp_service.set_request_interval(5); - fc::usleep(fc::seconds(4) ); - auto time = ntp_service.get_time(); - BOOST_CHECK( time ); - auto ntp_time = *time; - auto delta = ntp_time - fc::time_point::now(); -// auto minutes = delta.count() / 1000000 / 60; -// auto hours = delta.count() / 1000000 / 60 / 60; -// auto seconds = delta.count() / 1000000; - auto msec= delta.count() / 1000; - BOOST_CHECK( msec < 100 ); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/rate_limiting.cpp b/tests/rate_limiting.cpp old mode 100644 new mode 100755 diff --git a/tests/real128_test.cpp b/tests/real128_test.cpp old mode 100644 new mode 100755 diff --git a/tests/rpc.cpp b/tests/rpc.cpp old mode 100644 new mode 100755 diff --git a/tests/sleep.cpp b/tests/sleep.cpp old mode 100644 new mode 100755 diff --git a/tests/thread/task_cancel.cpp b/tests/thread/task_cancel.cpp old mode 100644 new mode 100755 diff --git a/tests/thread/thread_tests.cpp b/tests/thread/thread_tests.cpp new file mode 100755 index 0000000..1b7ed8e --- /dev/null +++ b/tests/thread/thread_tests.cpp @@ -0,0 +1,95 @@ +#include + +#include + +using namespace fc; + +BOOST_AUTO_TEST_SUITE(thread_tests) + +BOOST_AUTO_TEST_CASE(executes_task) +{ + bool called = false; + fc::thread thread("my"); + thread.async([&called]{called = true;}).wait(); + BOOST_CHECK(called); +} + +BOOST_AUTO_TEST_CASE(returns_value_from_function) +{ + fc::thread thread("my"); + BOOST_CHECK_EQUAL(10, thread.async([]{return 10;}).wait()); +} + +BOOST_AUTO_TEST_CASE(executes_multiple_tasks) +{ + bool called1 = false; + bool called2 = false; + + fc::thread thread("my"); + auto future1 = thread.async([&called1]{called1 = true;}); + auto future2 = thread.async([&called2]{called2 = true;}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK(called1); + BOOST_CHECK(called2); +} + +BOOST_AUTO_TEST_CASE(calls_tasks_in_order) +{ + std::string result; + + fc::thread thread("my"); + auto future1 = thread.async([&result]{result += "hello ";}); + auto future2 = thread.async([&result]{result += "world";}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK_EQUAL("hello world", result); +} + +BOOST_AUTO_TEST_CASE(yields_execution) +{ + std::string result; + + fc::thread thread("my"); + auto future1 = thread.async([&result]{fc::yield(); result += "world";}); + auto future2 = thread.async([&result]{result += "hello ";}); + + future2.wait(); + future1.wait(); + + BOOST_CHECK_EQUAL("hello world", result); +} + +BOOST_AUTO_TEST_CASE(quits_infinite_loop) +{ + fc::thread thread("my"); + auto f = thread.async([]{while (true) fc::yield();}); + + thread.quit(); + BOOST_CHECK_THROW(f.wait(), fc::canceled_exception); +} + +BOOST_AUTO_TEST_CASE(reschedules_yielded_task) +{ + int reschedule_count = 0; + + fc::thread thread("my"); + auto future = thread.async([&reschedule_count] + { + while (reschedule_count < 10) + { + fc::yield(); + reschedule_count++; + } + }); + + future.wait(); + BOOST_CHECK_EQUAL(10, reschedule_count); +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/tests/udt_client.cpp b/tests/udt_client.cpp deleted file mode 100644 index f575b28..0000000 --- a/tests/udt_client.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -using namespace std; -using namespace UDT; - -int main() -{ - UDTSOCKET client = UDT::socket(AF_INET, SOCK_STREAM, 0); - - sockaddr_in serv_addr; - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(9000); - inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); - - memset(&(serv_addr.sin_zero), '\0', 8); - - // connect to the server, implict bind - if (UDT::ERROR == UDT::connect(client, (sockaddr*)&serv_addr, sizeof(serv_addr))) - { - cout << "connect: " << UDT::getlasterror().getErrorMessage(); - return 0; - } - - char* hello = "hello world! 3\n"; - if (UDT::ERROR == UDT::send(client, hello, strlen(hello) + 1, 0)) - { - cout << "send: " << UDT::getlasterror().getErrorMessage(); - return 0; - } - - UDT::close(client); - - return 1; -} diff --git a/tests/udt_server.cpp b/tests/udt_server.cpp deleted file mode 100644 index ff7e2fb..0000000 --- a/tests/udt_server.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include - -using namespace std; - -int main( int argc, char** argv ) -{ - UDTSOCKET serv = UDT::socket(AF_INET, SOCK_STREAM, 0); - bool block = false; - - sockaddr_in my_addr; - my_addr.sin_family = AF_INET; - my_addr.sin_port = htons(9000); - my_addr.sin_addr.s_addr = INADDR_ANY; - memset(&(my_addr.sin_zero), '\0', 8); - - if (UDT::ERROR == UDT::bind(serv, (sockaddr*)&my_addr, sizeof(my_addr))) - { - cout << "bind: " << UDT::getlasterror().getErrorMessage(); - return 0; - } - UDT::listen(serv, 10); - - int namelen; - sockaddr_in their_addr; - - - UDT::setsockopt(serv, 0, UDT_SNDSYN, &block, sizeof(bool)); - UDT::setsockopt(serv, 0, UDT_RCVSYN, &block, sizeof(bool)); - UDTSOCKET recver = UDT::accept(serv, (sockaddr*)&their_addr, &namelen); - if( recver == UDT::INVALID_SOCK ) - { - if( UDT::getlasterror_code() == CUDTException::EASYNCRCV ) - { - std::cout << "nothing yet... better luck next time\n"; - } - } - auto pollid = UDT::epoll_create(); - UDT::epoll_add_usock(pollid, serv, nullptr );// const int* events = NULL); - std::set readready; - std::set writeready; - std::cout << "waiting for 5 seconds\n"; - UDT::epoll_wait( pollid, &readready, &writeready, 10000 ); - - - recver = UDT::accept(serv, (sockaddr*)&their_addr, &namelen); - if( recver == UDT::INVALID_SOCK ) - { - if( UDT::getlasterror_code() == CUDTException::EASYNCRCV ) - { - std::cout << "nothing yet... better luck next time\n"; - } - return 0; - } - UDT::setsockopt(recver, 0, UDT_SNDSYN, &block, sizeof(bool)); - UDT::setsockopt(recver, 0, UDT_RCVSYN, &block, sizeof(bool)); - UDT::epoll_remove_usock(pollid, serv );// const int* events = NULL); - int events = UDT_EPOLL_IN; - - UDT::epoll_add_usock(pollid, recver, &events );// const int* events = NULL); - - readready.clear(); - UDT::epoll_wait( pollid, &readready, &writeready, 5000 ); - - char ip[16]; - cout << "new connection: " << inet_ntoa(their_addr.sin_addr) << ":" << ntohs(their_addr.sin_port) << endl; - - char data[100]; - - while (UDT::ERROR == UDT::recv(recver, data, 100, 0)) - { - cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl; - UDT::epoll_wait( pollid, &readready, &writeready, 5000 ); - } - - cout << data << endl; - - UDT::close(recver); - UDT::close(serv); - - return 1; -} diff --git a/tests/udtc.cpp b/tests/udtc.cpp deleted file mode 100644 index aa48bb3..0000000 --- a/tests/udtc.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace fc; - -int main( int argc, char** argv ) -{ - try { - udt_socket sock; - sock.bind( fc::ip::endpoint::from_string( "127.0.0.1:6666" ) ); - ilog( "." ); - sock.connect_to( fc::ip::endpoint::from_string( "127.0.0.1:7777" ) ); - ilog( "after connect to..." ); - - std::cout << "local endpoint: " < response; - response.resize(1024); - int r = sock.readsome( response.data(), response.size() ); - while( r ) - { - std::cout.write( response.data(), r ); - r = sock.readsome( response.data(), response.size() ); - } - */ - // if we exit too quickly, UDT will not have a chance to - // send the graceful close message. - //fc::usleep( fc::seconds(1) ); - } catch ( const fc::exception& e ) - { - elog( "${e}", ("e",e.to_detail_string() ) ); - } - - return 0; -} diff --git a/tests/udts.cpp b/tests/udts.cpp deleted file mode 100644 index 8b8d575..0000000 --- a/tests/udts.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace fc; - -int main( int argc, char** argv ) -{ - try { - udt_server serv; - serv.listen( fc::ip::endpoint::from_string( "127.0.0.1:7777" ) ); - - while( true ) - { - udt_socket sock; - serv.accept( sock ); - - std::vector response; - response.resize(1024); - int r = sock.readsome( response.data(), response.size() ); - while( r ) - { - std::cout.write( response.data(), r ); - r = sock.readsome( response.data(), response.size() ); - //sock.write( response.data(), response.size() ); - } - - std::string goodbye = "goodbye cruel world"; - sock.write( goodbye.c_str(), goodbye.size() ); - } - } catch ( const fc::exception& e ) - { - elog( "${e}", ("e",e.to_detail_string() ) ); - } - - return 0; -} diff --git a/tests/utf8_test.cpp b/tests/utf8_test.cpp old mode 100644 new mode 100755 diff --git a/vendor/boost_1.51/include/boost/process.hpp b/vendor/boost_1.51/include/boost/process.hpp deleted file mode 100644 index 98e3c89..0000000 --- a/vendor/boost_1.51/include/boost/process.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process.hpp - * - * Convenience header that includes all public Boost.Process header files. - */ - -#ifndef BOOST_PROCESS_HPP -#define BOOST_PROCESS_HPP - -#include - -#endif diff --git a/vendor/boost_1.51/include/boost/process/all.hpp b/vendor/boost_1.51/include/boost/process/all.hpp deleted file mode 100644 index f30e566..0000000 --- a/vendor/boost_1.51/include/boost/process/all.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/all.hpp - * - * Convenience header that includes all public Boost.Process header files. - */ - -#ifndef BOOST_PROCESS_ALL_HPP -#define BOOST_PROCESS_ALL_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/vendor/boost_1.51/include/boost/process/child.hpp b/vendor/boost_1.51/include/boost/process/child.hpp deleted file mode 100644 index 1441e56..0000000 --- a/vendor/boost_1.51/include/boost/process/child.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/child.hpp - * - * Includes the declaration of the child class. - */ - -#ifndef BOOST_PROCESS_CHILD_HPP -#define BOOST_PROCESS_CHILD_HPP - -#include - -#if defined(BOOST_POSIX_API) -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * The child class provides access to a child process. - */ -class child : public process -{ -public: - /** - * Creates a new child object that represents the just spawned child - * process \a id. - */ - child(pid_type id, std::map handles) - : process(id), - handles_(handles) - { - } - -#if defined(BOOST_WINDOWS_API) - /** - * Creates a new child object that represents the just spawned child - * process \a id. - * - * This operation is only available on Windows systems. - */ - child(handle hprocess, std::map handles) - : process(hprocess), - handles_(handles) - { - } -#endif - - /** - * Gets a handle to a stream attached to the child. - * - * If the handle doesn't exist an invalid handle is returned. - */ - handle get_handle(stream_id id) const - { - std::map::const_iterator it = handles_.find(id); - return (it != handles_.end()) ? it->second : handle(); - } - -#if defined(BOOST_WINDOWS_API) - handle::native_type get_os_handle() const - { - return handle_.native(); - } -#endif - - -private: - /** - * Handles providing access to streams attached to the child process. - */ - std::map handles_; -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/config.hpp b/vendor/boost_1.51/include/boost/process/config.hpp deleted file mode 100644 index 7ce15eb..0000000 --- a/vendor/boost_1.51/include/boost/process/config.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/config.hpp - * - * Defines macros that are used by the library to determine the operating - * system it is running under and the features it supports. - */ - -#ifndef BOOST_PROCESS_CONFIG_HPP -#define BOOST_PROCESS_CONFIG_HPP - -#include -#include -#include -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) || defined(BOOST_PROCESS_DOXYGEN) -/** - * Specifies the system's maximal supported path length. - * - * The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer - * value which specifies the system's maximal supported path length. It is - * only used if neither PATH_MAX nor _PC_PATH_MAX and HAVE_PATHCONF are defined. - * The maximal supported path length is required by - * boost::process::self::get_work_dir(). Please note that this function is - * also called by the constructor of boost::process::context. - */ -# define BOOST_PROCESS_POSIX_PATH_MAX 259 -# endif -#endif - -/** \cond */ -#define BOOST_PROCESS_SOURCE_LOCATION \ - "in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": " - -#if defined(BOOST_POSIX_API) -# define BOOST_PROCESS_LAST_ERROR errno -#elif defined(BOOST_WINDOWS_API) -# define BOOST_PROCESS_LAST_ERROR GetLastError() -#endif - -#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \ - boost::throw_exception(boost::system::system_error( \ - boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \ - boost::system::get_system_category()), \ - BOOST_PROCESS_SOURCE_LOCATION what)) - -#define BOOST_PROCESS_THROW_ERROR(error, what) \ - boost::throw_exception(boost::system::system_error( \ - boost::system::error_code(error, \ - boost::system::get_system_category()), \ - BOOST_PROCESS_SOURCE_LOCATION what)) -/** \endcond */ - -#endif diff --git a/vendor/boost_1.51/include/boost/process/context.hpp b/vendor/boost_1.51/include/boost/process/context.hpp deleted file mode 100644 index 1228d9e..0000000 --- a/vendor/boost_1.51/include/boost/process/context.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/context.hpp - * - * Includes the declaration of the context class. - */ - -#ifndef BOOST_PROCESS_CONTEXT_HPP -#define BOOST_PROCESS_CONTEXT_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Context class to define how a child process is created. - * - * The context class is used to configure streams, to set the work directory - * and define environment variables. It is also used to change a process - * name (the variable commonly known as argv[0]). - */ -struct context -{ - typedef std::map > - streams_t; - - /** - * Streams. - * - * Streams of a child process can be configured through factory functions - * which return a pair of handles - one handle to use as a stream end - * in the child process and possibly another handle to use as a stream end - * in the parent process (if a pipe is setup both processes can communicate - * with each other). - */ - streams_t streams; - - /** - * Process name. - * - * The child process can access the process name via a variable - * commonly known as argv[0]. - */ - std::string process_name; - - /** - * Work directory. - */ - std::string work_dir; - - /** - * Environment variables. - */ - environment env; - - /** - * Suppress creation of a console window on win32 (nop on other platforms) - */ - bool suppress_console; - - /** - * Constructs a process context. - * - * The default behavior of standard streams is to inherit them. The current - * work directory is also the work directory of the child process. The child - * process also inherits all environment variables. - */ - context() - : work_dir(self::get_work_dir()), - env(self::get_environment()), - suppress_console(false) - { -#if 0 // this default behavior will throw in non-console apps -#if defined(BOOST_POSIX_API) - streams[stdin_id] = behavior::inherit(STDIN_FILENO); - streams[stdout_id] = behavior::inherit(STDOUT_FILENO); - streams[stderr_id] = behavior::inherit(STDERR_FILENO); -#elif defined(BOOST_WINDOWS_API) - streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE)); - streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE)); - streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE)); -#endif -#endif - } - -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Setups a child process. - * - * This is an extension point to support more configuration options for - * child processes. You can initialize \a setup with a user-defined function - * which is called when a child process is created. - * - * On POSIX platforms setup() is called in the child process. That's why in - * a multithreaded application only async-signal-safe functions must be - * called in the function \a setup is bound to. - * - * On Windows platforms setup() is called in the parent process. A - * reference to a STARTUPINFOA structure is passed as parameter. - */ - boost::function setup; -#elif defined(BOOST_WINDOWS_API) - boost::function setup; -#endif -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/basic_status.hpp b/vendor/boost_1.51/include/boost/process/detail/basic_status.hpp deleted file mode 100644 index 2da361a..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/basic_status.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/basic_status.hpp - * - * Includes the declaration of the basic status class. - */ - -#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP -#define BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP - -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * The basic_status class to wait for processes to exit. - * - * The basic_status class is a Boost.Asio I/O object and supports synchronous - * and asynchronous wait operations. It must be instantiated with a Service. - */ -template -class basic_status - : public boost::asio::basic_io_object -{ -public: - explicit basic_status(boost::asio::io_service &io_service) - : boost::asio::basic_io_object(io_service) - { - } - - /** - * Waits synchronously for a process to exit. - */ - int wait(pid_type pid) - { - return this->service.wait(this->implementation, pid); - } - - /** - * Waits asynchronously for a process to exit. - */ - template - void async_wait(pid_type pid, Handler handler) - { - this->service.async_wait(this->implementation, pid, handler); - } -}; - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp b/vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp deleted file mode 100644 index 2fd1a39..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/basic_status_service.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/basic_status_service.hpp - * - * Includes the declaration of the basic status service class. - */ - -#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP -#define BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * The basic_status_service class provides the service to wait for processes - * synchronously and asynchronously. - */ -template -class basic_status_service - : public boost::asio::detail::service_base -{ -public: - explicit basic_status_service(boost::asio::io_service &io_service) - : boost::asio::detail::service_base(io_service), -#if defined(BOOST_POSIX_API) - interrupt_pid_(-1), - pids_(0) -#elif defined(BOOST_WINDOWS_API) - run_(true) -#endif - { -#if defined(BOOST_WINDOWS_API) - handles_.push_back(CreateEvent(NULL, FALSE, FALSE, NULL)); - if (handles_[0] == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed"); - work_thread_ = boost::thread( - &basic_status_service::work_thread, this); -#endif - } - - ~basic_status_service() - { -#if defined(BOOST_POSIX_API) - boost::unique_lock lock(work_thread_mutex_); - bool worker_thread_active = (pids_ != 0); - lock.unlock(); - if (worker_thread_active) - { - stop_work_thread(); - work_thread_.join(); - } -#elif defined(BOOST_WINDOWS_API) - stop_work_thread(); - work_thread_.join(); - CloseHandle(handles_[0]); -#endif - } - - typedef boost::shared_ptr implementation_type; - - void construct(implementation_type &impl) - { - impl = boost::make_shared(); - boost::unique_lock lock(work_thread_mutex_); - impls_.push_back(impl); - } - - void destroy(implementation_type &impl) - { - boost::unique_lock lock(work_thread_mutex_); - typename std::vector::iterator it = - std::find(impls_.begin(), impls_.end(), impl); - if (it != impls_.end()) - impls_.erase(it); -#if defined(BOOST_WINDOWS_API) - interrupt_work_thread(); - work_thread_cond_.wait(work_thread_mutex_); - impl->clear(handles_); - work_thread_cond_.notify_all(); -#endif - impl.reset(); - } - - int wait(implementation_type &impl, pid_type pid) - { - boost::system::error_code ec; - int status = impl->wait(pid, ec); -#if defined(BOOST_POSIX_API) - if (ec.value() == ECHILD) - { - boost::unique_lock lock(work_thread_mutex_); - boost::unordered_map::iterator it = statuses_.find(pid); - if (it == statuses_.end()) - { - work_thread_cond_.wait(work_thread_mutex_); - it = statuses_.find(pid); - } - if (it != statuses_.end()) - { - status = it->second; - statuses_.erase(it); - ec.clear(); - } - } -#endif - boost::asio::detail::throw_error(ec); - return status; - } - - template - void async_wait(implementation_type &impl, pid_type pid, Handler handler) - { -#if defined(BOOST_POSIX_API) - boost::unique_lock lock(work_thread_mutex_); - if (++pids_ == 1) - { - // if there was a previous worker thread that exited because - // pids_ dropped to 0, we must join it now to free the thread's - // memory before launching a new worker thread - if (work_thread_.joinable()) - work_thread_.join(); - work_.reset(new boost::asio::io_service::work( - this->get_io_service())); - work_thread_ = boost::thread( - &basic_status_service::work_thread, - this); - } - impl->async_wait(pid, this->get_io_service().wrap(handler)); -#elif defined(BOOST_WINDOWS_API) - HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, - FALSE, pid); - if (handle == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - boost::unique_lock lock(work_thread_mutex_); - if (!work_) - work_.reset(new boost::asio::io_service::work( - this->get_io_service())); - interrupt_work_thread(); - work_thread_cond_.wait(work_thread_mutex_); - handles_.push_back(handle); - impl->async_wait(handle, this->get_io_service().wrap(handler)); - work_thread_cond_.notify_all(); -#endif - } - -private: - void shutdown_service() - { -#if defined(BOOST_WINDOWS_API) - boost::unique_lock lock(work_thread_mutex_); - work_.reset(); -#endif - } - - void work_thread() - { -#if defined(BOOST_POSIX_API) - for (;;) - { - int status; - pid_t pid = ::wait(&status); - if (pid == -1) - { - if (errno != EINTR) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("wait(2) failed"); - } - else if (interrupted(pid)) - { - // On POSIX the only reason to interrupt is to break out. - break; - } - else - { - boost::unique_lock lock(work_thread_mutex_); - bool regchild = false; - for (typename std::vector::iterator it = - impls_.begin(); it != impls_.end(); ++it) - regchild |= (*it)->complete(pid, status); - if (regchild && --pids_ == 0) - { - work_.reset(); - break; - } - else if (!regchild) - { - statuses_.insert(boost::unordered_map:: - value_type(pid, status)); - work_thread_cond_.notify_all(); - } - } - } -#elif defined(BOOST_WINDOWS_API) - for (;;) - { - DWORD res = WaitForMultipleObjects(handles_.size(), &handles_[0], - FALSE, INFINITE); - if (res == WAIT_FAILED) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "WaitForMultipleObjects() failed"); - else if (res - WAIT_OBJECT_0 == 0) - { - boost::unique_lock lock(work_thread_mutex_); - if (!run_) - break; - work_thread_cond_.notify_all(); - work_thread_cond_.wait(work_thread_mutex_); - } - else if (res - WAIT_OBJECT_0 > 0) - { - HANDLE handle = handles_[res - WAIT_OBJECT_0]; - DWORD exit_code; - if (!GetExitCodeProcess(handle, &exit_code)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetExitCodeProcess() failed"); - boost::unique_lock lock(work_thread_mutex_); - for (typename std::vector::iterator it = - impls_.begin(); it != impls_.end(); ++it) - (*it)->complete(handle, exit_code); - std::vector::iterator it = handles_.begin(); - std::advance(it, res - WAIT_OBJECT_0); - handles_.erase(it); - if (handles_.size() == 1) - work_.reset(); - } - } -#endif - } - - void interrupt_work_thread() - { -#if defined(BOOST_POSIX_API) - // By creating a child process which immediately exits - // we interrupt wait(). - std::vector args; - args.push_back("-c"); - args.push_back("'exit'"); - interrupt_pid_ = create_child("/bin/sh", args).get_id(); -#elif defined(BOOST_WINDOWS_API) - // By signaling the event in the first slot WaitForMultipleObjects() - // will return. The work thread won't do anything except checking if - // it should continue to run. - if (!SetEvent(handles_[0])) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetEvent() failed"); -#endif - } - -#if defined(BOOST_POSIX_API) - bool interrupted(pid_t pid) - { - boost::mutex::scoped_lock lock(work_thread_mutex_); - return interrupt_pid_ == pid; - } -#endif - - void stop_work_thread() - { - boost::mutex::scoped_lock lock(work_thread_mutex_); -#if defined(BOOST_WINDOWS_API) - // Access to run_ must be sychronized with running(). - run_ = false; -#endif - // Access to interrupt_pid_ must be sychronized with interrupted(). - interrupt_work_thread(); - } - - boost::scoped_ptr work_; - std::vector impls_; - boost::mutex work_thread_mutex_; - boost::thread work_thread_; - boost::condition_variable_any work_thread_cond_; -#if defined(BOOST_POSIX_API) - pid_t interrupt_pid_; - int pids_; - boost::unordered_map statuses_; -#elif defined(BOOST_WINDOWS_API) - bool run_; - std::vector handles_; -#endif -}; - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/posix_helpers.hpp b/vendor/boost_1.51/include/boost/process/detail/posix_helpers.hpp deleted file mode 100644 index 993e2e0..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/posix_helpers.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/posix_helpers.hpp - * - * Includes the declaration of helper functions for POSIX systems. - */ - -#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP -#define BOOST_PROCESS_POSIX_HELPERS_HPP - -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts an environment to a char** table as used by execve(). - * - * Converts the environment's contents to the format used by the - * execve() system call. The returned char** array is allocated - * in dynamic memory; the caller must free it when not used any - * more. Each entry is also allocated in dynamic memory and is a - * NULL-terminated string of the form var=value; these must also be - * released by the caller. - * - * This operation is only available on POSIX systems. - * - * \return The first argument of the pair is an integer that indicates - * how many strings are stored in the second argument. The - * second argument is a NULL-terminated, dynamically allocated - * array of dynamically allocated strings representing the - * enviroment's content. Each array entry is a NULL-terminated - * string of the form var=value. The caller is responsible for - * freeing them. - */ -inline std::pair environment_to_envp(const environment - &env) -{ - std::size_t nargs = env.size(); - char **envp = new char*[nargs + 1]; - environment::size_type i = 0; - for (environment::const_iterator it = env.begin(); it != env.end(); ++it) - { - std::string s = it->first + "=" + it->second; - envp[i] = new char[s.size() + 1]; - std::strncpy(envp[i], s.c_str(), s.size() + 1); - ++i; - } - envp[i] = 0; - return std::pair(nargs, envp); -} - -/** - * Converts the command line to an array of C strings. - * - * Converts the command line's list of arguments to the format expected - * by the \a argv parameter in the POSIX execve() system call. - * - * This operation is only available on POSIX systems. - * - * \return The first argument of the pair is an integer that indicates - * how many strings are stored in the second argument. The - * second argument is a NULL-terminated, dynamically allocated - * array of dynamically allocated strings holding the arguments - * to the executable. The caller is responsible for freeing them. - */ -template -inline std::pair collection_to_argv(const Arguments &args) -{ - std::size_t nargs = args.size(); - char **argv = new char*[nargs + 1]; - typename Arguments::size_type i = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); - ++it) - { - argv[i] = new char[it->size() + 1]; - std::strncpy(argv[i], it->c_str(), it->size() + 1); - ++i; - } - argv[nargs] = 0; - return std::pair(nargs, argv); -} - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/status_impl.hpp b/vendor/boost_1.51/include/boost/process/detail/status_impl.hpp deleted file mode 100644 index 618db49..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/status_impl.hpp +++ /dev/null @@ -1,190 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/status_impl.hpp - * - * Includes the declaration of the status implementation class. - */ - -#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP -#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -#if defined(BOOST_POSIX_API) -typedef pid_t phandle; -#elif defined(BOOST_WINDOWS_API) -typedef HANDLE phandle; -#endif - -struct operation -{ - virtual ~operation(){} - virtual void operator()(int exit_code) - { -#if defined(BOOST_MSVC) - exit_code; -#endif - } -}; - -template -class wrapped_handler : public operation -{ -public: - wrapped_handler(Handler handler) - : handler_(handler) - { - } - - void operator()(int exit_code) - { - handler_(boost::system::error_code(), exit_code); - } - -private: - Handler handler_; -}; - -/** - * The status_impl class saves internal data of every status I/O object. - */ -class status_impl -{ -public: -#if defined(BOOST_WINDOWS_API) - template - void clear(Container &handles) - { - for (operations_type::iterator it = ops_.begin(); it != ops_.end(); - ++it) - { - for (typename Container::iterator it2 = handles.begin(); it2 != - handles.end(); ++it2) - { - if (*it2 == it->first) - { - handles.erase(it2); - break; - } - } - CloseHandle(it->first); - } - } -#endif - - int wait(pid_type pid, boost::system::error_code &ec) - { -#if defined(BOOST_POSIX_API) - pid_t p; - int status; - do - { - p = waitpid(pid, &status, 0); - } while (p == -1 && errno == EINTR); - if (p == -1) - { - ec = boost::system::error_code(errno, - boost::system::get_system_category()); - return -1; - } - return status; -#elif defined(BOOST_WINDOWS_API) - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, - pid); - if (h == NULL) - { - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - - if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) - { - CloseHandle(h); - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - - DWORD exit_code; - if (!GetExitCodeProcess(h, &exit_code)) - { - CloseHandle(h); - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - if (!CloseHandle(h)) - { - ec = boost::system::error_code(GetLastError(), - boost::system::get_system_category()); - return -1; - } - return exit_code; -#endif - } - - template - void async_wait(phandle ph, Handler handler) - { - ops_.insert(ph, new wrapped_handler(handler)); - } - - bool complete(phandle ph, int exit_code) - { - boost::iterator_range r = - ops_.equal_range(ph); - if (r.empty()) - return false; - for (operations_type::iterator it = r.begin(); it != r.end(); ++it) - (*it->second)(exit_code); - ops_.erase(r.begin(), r.end()); -#if defined(BOOST_WINDOWS_API) - if (!CloseHandle(ph)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); -#endif - return true; - } - -private: - typedef boost::ptr_unordered_multimap operations_type; - operations_type ops_; -}; - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/systembuf.hpp b/vendor/boost_1.51/include/boost/process/detail/systembuf.hpp deleted file mode 100644 index d6dce50..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/systembuf.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/systembuf.hpp - * - * Includes the declaration of the systembuf class. - */ - -#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP -#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -class postream; - -namespace detail { - -/** - * std::streambuf implementation for handles. - * - * systembuf provides a std::streambuf implementation for handles. - * Contrarywise to the handle class, this class does \b not take - * ownership of the native handle; this should be taken care of - * somewhere else. - * - * This class follows the expected semantics of a std::streambuf object. - * However, it is not copyable to avoid introducing inconsistences with - * the on-disk file and the in-memory buffers. - */ -class systembuf : public std::streambuf, public boost::noncopyable -{ - friend class boost::process::postream; - -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - */ - typedef NativeHandleType handle_type; -#elif defined(BOOST_POSIX_API) - typedef int handle_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE handle_type; -#endif - - /** - * Constructs a new systembuf for the given handle. - * - * This constructor creates a new systembuf object that reads or - * writes data from/to the \a h native handle. This handle - * is \b not owned by the created systembuf object; the code - * should take care of it externally. - * - * This class buffers input and output; the buffer size may be - * tuned through the \a bufsize parameter, which defaults to 8192 - * bytes. - * - * \see pistream and postream - */ - explicit systembuf(handle_type h, std::size_t bufsize = 8192) - : handle_(h), - bufsize_(bufsize), - read_buf_(new char[bufsize]), - write_buf_(new char[bufsize]) - { -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(handle_ >= 0); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE); -#endif - BOOST_ASSERT(bufsize_ > 0); - setp(write_buf_.get(), write_buf_.get() + bufsize_); - } - -protected: - /** - * Reads new data from the native handle. - * - * This operation is called by input methods when there is no more - * data in the input buffer. The function fills the buffer with new - * data, if available. - * - * \pre All input positions are exhausted (gptr() >= egptr()). - * \post The input buffer has new data, if available. - * \returns traits_type::eof() if a read error occurrs or there are - * no more data to be read. Otherwise returns - * traits_type::to_int_type(*gptr()). - */ - virtual int_type underflow() - { - BOOST_ASSERT(gptr() >= egptr()); - - bool ok; -#if defined(BOOST_POSIX_API) - ssize_t cnt = read(handle_, read_buf_.get(), bufsize_); - ok = (cnt != -1 && cnt != 0); -#elif defined(BOOST_WINDOWS_API) - DWORD cnt; - BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL); - ok = (res && cnt > 0); -#endif - - if (!ok) - return traits_type::eof(); - else - { - setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt); - return traits_type::to_int_type(*gptr()); - } - } - - /** - * Makes room in the write buffer for additional data. - * - * This operation is called by output methods when there is no more - * space in the output buffer to hold a new element. The function - * first flushes the buffer's contents to disk and then clears it to - * leave room for more characters. The given \a c character is - * stored at the beginning of the new space. - * - * \pre All output positions are exhausted (pptr() >= epptr()). - * \post The output buffer has more space if no errors occurred - * during the write to disk. - * \post *(pptr() - 1) is \a c. - * \returns traits_type::eof() if a write error occurrs. Otherwise - * returns traits_type::not_eof(c). - */ - virtual int_type overflow(int c) - { - BOOST_ASSERT(pptr() >= epptr()); - - if (sync() == -1) - return traits_type::eof(); - - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - traits_type::assign(*pptr(), static_cast( - c)); - pbump(1); - } - - return traits_type::not_eof(c); - } - - /** - * Flushes the output buffer to disk. - * - * Synchronizes the systembuf buffers with the contents of the file - * associated to this object through the native handle. The output buffer - * is flushed to disk and cleared to leave new room for more data. - * - * \returns 0 on success, -1 if an error occurred. - */ - virtual int sync() - { -#if defined(BOOST_POSIX_API) - ssize_t cnt = pptr() - pbase(); - bool ok = (write(handle_, pbase(), cnt) == cnt); - if (ok) - pbump(-cnt); - return ok ? 0 : -1; -#elif defined(BOOST_WINDOWS_API) - long cnt = pptr() - pbase(); - DWORD rcnt; - BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL); - bool ok = (res && static_cast(rcnt) == cnt); - if (ok) - pbump(-cnt); - return ok ? 0 : -1; -#endif - } - -private: - /** - * Native handle used by the systembuf object. - */ - handle_type handle_; - - /** - * Internal buffer size used during read and write operations. - */ - std::size_t bufsize_; - - /** - * Internal buffer used during read operations. - */ - boost::scoped_array read_buf_; - - /** - * Internal buffer used during write operations. - */ - boost::scoped_array write_buf_; -}; - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/detail/windows_helpers.hpp b/vendor/boost_1.51/include/boost/process/detail/windows_helpers.hpp deleted file mode 100644 index 5656aaa..0000000 --- a/vendor/boost_1.51/include/boost/process/detail/windows_helpers.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/detail/windows_helpers.hpp - * - * Includes the declaration of helper functions for Windows systems. - */ - -#ifndef BOOST_PROCESS_WINDOWS_HELPERS_HPP -#define BOOST_PROCESS_WINDOWS_HELPERS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace detail { - -/** - * Converts an environment to a string used by CreateProcess(). - * - * Converts the environment's contents to the format used by the - * CreateProcess() system call. The returned char* string is - * allocated in dynamic memory; the caller must free it when not - * used any more. This is enforced by the use of a shared pointer. - * - * This operation is only available on Windows systems. - * - * \return A dynamically allocated char* string that represents - * the environment's content. This string is of the form - * var1=value1\\0var2=value2\\0\\0. - */ -inline boost::shared_array environment_to_windows_strings(environment - &env) -{ - boost::shared_array envp; - - if (env.empty()) - { - envp.reset(new char[2]); - ZeroMemory(envp.get(), 2); - } - else - { - std::string s; - for (environment::const_iterator it = env.begin(); it != env.end(); - ++it) - { - s += it->first + "=" + it->second; - s.push_back(0); - } - envp.reset(new char[s.size() + 1]); -#if (BOOST_MSVC >= 1400) - memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1); -#else - memcpy(envp.get(), s.c_str(), s.size() + 1); -#endif - } - - return envp; -} - -/** - * Converts the command line to a plain string. - * - * Converts the command line's list of arguments to the format expected by the - * \a lpCommandLine parameter in the CreateProcess() system call. - * - * This operation is only available on Windows systems. - * - * \return A dynamically allocated string holding the command line - * to be passed to the executable. It is returned in a - * shared_array object to ensure its release at some point. - */ -template -inline boost::shared_array collection_to_windows_cmdline(const Arguments - &args) -{ - typedef std::vector arguments_t; - arguments_t args2; - typename Arguments::size_type i = 0; - std::size_t size = 0; - for (typename Arguments::const_iterator it = args.begin(); it != args.end(); - ++it) - { - std::string arg = *it; - - std::string::size_type pos = 0; - while ( (pos = arg.find('"', pos)) != std::string::npos) - { - arg.replace(pos, 1, "\\\""); - pos += 2; - } - - if (arg.find(' ') != std::string::npos) - arg = '\"' + arg + '\"'; - - if (i++ != args.size() - 1) - arg += ' '; - - args2.push_back(arg); - size += arg.size() + 1; - } - - boost::shared_array cmdline(new char[size]); - cmdline.get()[0] = '\0'; - for (arguments_t::size_type i = 0; i < args.size(); ++i) -#if (BOOST_MSVC >= 1400) - strcat_s(cmdline.get(), size, args2[i].c_str()); -#else - strncat(cmdline.get(), args2[i].c_str(), args2[i].size()); -#endif - - return cmdline; -} - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/environment.hpp b/vendor/boost_1.51/include/boost/process/environment.hpp deleted file mode 100644 index daf44e3..0000000 --- a/vendor/boost_1.51/include/boost/process/environment.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/environment.hpp - * - * Includes the declaration of the environment class. - */ - -#ifndef BOOST_PROCESS_ENVIRONMENT_HPP -#define BOOST_PROCESS_ENVIRONMENT_HPP - -#include -#include - -namespace boost { -namespace process { - -/** - * Representation of a process' environment variables. - * - * The environment is a map that establishes an unidirectional - * association between variable names and their values and is - * represented by a string to string map. - * - * Variables may be defined to the empty string. Be aware that doing so - * is not portable: POSIX systems will treat such variables as being - * defined to the empty value, but Windows systems are not able to - * distinguish them from undefined variables. - * - * Neither POSIX nor Windows systems support a variable with no name. - * - * It is worthy to note that the environment is sorted alphabetically. - * This is provided for-free by the map container used to implement this - * type, and this behavior is required by Windows systems. - */ -typedef std::map environment; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/handle.hpp b/vendor/boost_1.51/include/boost/process/handle.hpp deleted file mode 100644 index b880a3e..0000000 --- a/vendor/boost_1.51/include/boost/process/handle.hpp +++ /dev/null @@ -1,231 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/handle.hpp - * - * Includes the declaration of the handle class. - */ - -#ifndef BOOST_PROCESS_HANDLE_HPP -#define BOOST_PROCESS_HANDLE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include - -namespace boost { -namespace process { - -/** - * RAII model for handles. - * - * The \a handle class is a RAII model for native handles. This class wraps - * one of such handles grabbing its ownership, and automaticaly closes it - * upon destruction. It is used to avoid leaking open handles, shall an - * unexpected execution trace occur. - */ -class handle -{ -public: -#if defined(BOOST_PROCESS_DOXYGEN) - /** - * Opaque name for the native handle type. - * - * On POSIX systems \a NativeSystemHandle is an integer type while it is - * a \a HANDLE on Windows systems. - */ - typedef NativeSystemHandle native_type; -#elif defined(BOOST_POSIX_API) - typedef int native_type; -#elif defined(BOOST_WINDOWS_API) - typedef HANDLE native_type; -#endif - - /** - * Constructs an invalid handle. - * - * \see valid() - */ - handle() - { - } - - /** - * RAII settings to specify if handle should be automatically closed. - */ - enum close_type { do_close, dont_close }; - - /** - * Constructs a handle from a native handle. - * - * This constructor creates a new \a handle object that takes - * ownership of the given \a native handle. If \a close is set to - * handle::dont_close the \a native handle is not closed upon destruction. - * The user must not close \a native if it is owned by a \a handle object. - * Ownership can be reclaimed using release(). - * - * \see release() - */ - handle(native_type native, close_type close = handle::do_close) - : impl_(boost::make_shared(native, close)) - { - } - - /** - * Checks whether the handle is valid or not. - * - * \return true if the handle is valid; false otherwise. - */ - bool valid() const - { - return impl_ && impl_->valid(); - } - - /** - * Closes the handle. - * - * \post The handle is invalid. - * \post The native handle is closed. - */ - void close() - { - if (impl_) - impl_->close(); - } - - /** - * Gets the native handle. - * - * The caller can issue any operation on it except closing it. - * If closing is required, release() shall be used. - * - * \return The native handle. - */ - native_type native() const - { - return impl_ ? impl_->native() : invalid_handle(); - } - - /** - * Reclaims ownership of the native handle. - * - * The caller is responsible of closing the native handle. - * - * \post The handle is invalid. - * \return The native handle. - */ - native_type release() - { - return impl_ ? impl_->release() : invalid_handle(); - } - -private: - class impl - { - public: - typedef handle::native_type native_type; - - impl(native_type native, close_type close) - : native_(native), - close_(close) - { - } - - ~impl() - { - if (valid() && close_ == handle::do_close) - { -#if defined(BOOST_POSIX_API) - ::close(native_); -#elif defined(BOOST_WINDOWS_API) - CloseHandle(native_); -#endif - } - } - - bool valid() const - { - return native_ != handle::invalid_handle(); - } - - void close() - { - if (valid()) - { -#if defined(BOOST_POSIX_API) - ::close(native_); -#elif defined(BOOST_WINDOWS_API) - CloseHandle(native_); -#endif - native_ = handle::invalid_handle(); - } - } - - native_type native() const - { - return native_; - } - - native_type release() - { - native_type native = native_; - native_ = handle::invalid_handle(); - return native; - } - - private: - native_type native_; - close_type close_; - }; - - /** - * Implementation of handle to store native handle value. - * - * A shared pointer is used as handles represent system resources. If a - * handle is closed and becomes invalid the state of copies of the handle - * object will be updated as they all share the handle implementation. - */ - boost::shared_ptr impl_; - - /** - * Constant function representing an invalid handle value. - * - * Returns the platform-specific handle value that represents an - * invalid handle. This is a constant function rather than a regular - * constant because, in the latter case, we cannot define it under - * Windows due to the value being of a complex type. - */ - static const native_type invalid_handle() - { -#if defined(BOOST_POSIX_API) - return -1; -#elif defined(BOOST_WINDOWS_API) - return INVALID_HANDLE_VALUE; -#endif - } -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/operations.hpp b/vendor/boost_1.51/include/boost/process/operations.hpp deleted file mode 100644 index 1d6da12..0000000 --- a/vendor/boost_1.51/include/boost/process/operations.hpp +++ /dev/null @@ -1,439 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/operations.hpp - * - * Provides miscellaneous free functions. - */ - -#ifndef BOOST_PROCESS_OPERATIONS_HPP -#define BOOST_PROCESS_OPERATIONS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# include -# include -# if defined(__CYGWIN__) -# include -# include -# endif -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Locates the executable program \a file in all the directory components - * specified in \a path. If \a path is empty, the value of the PATH - * environment variable is used. - * - * The path variable is interpreted following the same conventions used - * to parse the PATH environment variable in the underlying platform. - * - * \throw boost::filesystem::filesystem_error If the file cannot be found - * in the path. - */ -inline std::string find_executable_in_path(const std::string &file, - std::string path = "") -{ -#if defined(BOOST_POSIX_API) - BOOST_ASSERT(file.find('/') == std::string::npos); -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos); -#endif - - std::string result; - -#if defined(BOOST_POSIX_API) - if (path.empty()) - { - const char *envpath = getenv("PATH"); - if (!envpath) - boost::throw_exception(boost::filesystem::filesystem_error( - BOOST_PROCESS_SOURCE_LOCATION "file not found", file, - boost::system::errc::make_error_code( - boost::system::errc::no_such_file_or_directory))); - path = envpath; - } - BOOST_ASSERT(!path.empty()); - -#if defined(__CYGWIN__) - if (!cygwin_posix_path_list_p(path.c_str())) - { - int size = cygwin_win32_to_posix_path_list_buf_size(path.c_str()); - boost::scoped_array cygpath(new char[size]); - cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get()); - path = cygpath.get(); - } -#endif - - std::string::size_type pos1 = 0, pos2; - do - { - pos2 = path.find(':', pos1); - std::string dir = (pos2 != std::string::npos) ? - path.substr(pos1, pos2 - pos1) : path.substr(pos1); - std::string f = dir + - (boost::algorithm::ends_with(dir, "/") ? "" : "/") + file; - if (!access(f.c_str(), X_OK)) - result = f; - pos1 = pos2 + 1; - } while (pos2 != std::string::npos && result.empty()); -#elif defined(BOOST_WINDOWS_API) - const char *exts[] = { "", ".exe", ".com", ".bat", NULL }; - const char **ext = exts; - while (*ext) - { - char buf[MAX_PATH]; - char *dummy; - DWORD size = SearchPathA(path.empty() ? NULL : path.c_str(), - file.c_str(), *ext, MAX_PATH, buf, &dummy); - BOOST_ASSERT(size < MAX_PATH); - if (size > 0) - { - result = buf; - break; - } - ++ext; - } -#endif - - if (result.empty()) - boost::throw_exception(boost::filesystem::filesystem_error( - BOOST_PROCESS_SOURCE_LOCATION "file not found", file, - boost::system::errc::make_error_code( - boost::system::errc::no_such_file_or_directory))); - - return result; -} - -/** - * Extracts the program name from a given executable. - * - * \return The program name. On Windows the program name - * is returned without a file extension. - */ -inline std::string executable_to_progname(const std::string &exe) -{ - std::string::size_type begin = 0; - std::string::size_type end = std::string::npos; - -#if defined(BOOST_POSIX_API) - std::string::size_type slash = exe.rfind('/'); -#elif defined(BOOST_WINDOWS_API) - std::string::size_type slash = exe.find_last_of("/\\"); -#endif - if (slash != std::string::npos) - begin = slash + 1; - -#if defined(BOOST_WINDOWS_API) - if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") || - boost::algorithm::iends_with(exe, ".com") || - boost::algorithm::iends_with(exe, ".bat"))) - end = exe.size() - 4; -#endif - - return exe.substr(begin, end - begin); -} - -/** - * Starts a new child process. - * - * Launches a new process based on the binary image specified by the - * executable, the set of arguments passed to it and the execution context. - * - * \remark Blocking remarks: This function may block if the device holding the - * executable blocks when loading the image. This might happen if, e.g., - * the binary is being loaded from a network share. - * - * \return A handle to the new child process. - */ -template -inline child create_child(const std::string &executable, Arguments args, - Context ctx) -{ - typedef std::map handles_t; - handles_t handles; - typename Context::streams_t::iterator it = ctx.streams.begin(); - for (; it != ctx.streams.end(); ++it) - { - if (it->first == stdin_id) - handles[it->first] = it->second(input_stream); - else if (it->first == stdout_id) - handles[it->first] = it->second(output_stream); - else if (it->first == stderr_id) - handles[it->first] = it->second(output_stream); -#if defined(BOOST_POSIX_API) - else - handles[it->first] = it->second(unknown_stream); -#endif - } - - std::string p_name = ctx.process_name.empty() ? - executable_to_progname(executable) : ctx.process_name; - args.insert(args.begin(), p_name); - -#if defined(BOOST_POSIX_API) - // Between fork() and execve() only async-signal-safe functions - // must be called if multithreaded applications should be supported. - // That's why the following code is executed before fork() is called. -#if defined(F_MAXFD) - int maxdescs = fcntl(-1, F_MAXFD, 0); - if (maxdescs == -1) - maxdescs = sysconf(_SC_OPEN_MAX); -#else - int maxdescs = sysconf(_SC_OPEN_MAX); -#endif - if (maxdescs == -1) - maxdescs = 1024; - std::vector closeflags(maxdescs, true); - std::pair argv = detail::collection_to_argv(args); - std::pair envp = - detail::environment_to_envp(ctx.env); - - const char *work_dir = ctx.work_dir.c_str(); - - pid_t pid = fork(); - if (pid == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed"); - else if (pid == 0) - { - if (chdir(work_dir) == -1) - { - auto r = write(STDERR_FILENO, "chdir() failed\n", 15); - if( r || !r ) _exit(127); - } - - for (handles_t::iterator it = handles.begin(); it != handles.end(); - ++it) - { - if (it->second.child.valid()) - { - handles_t::iterator it2 = it; - ++it2; - for (; it2 != handles.end(); ++it2) - { - if (it2->second.child.native() == it->first) - { - int fd = fcntl(it2->second.child.native(), F_DUPFD, - it->first + 1); - if (fd == -1) - { - auto r = write(STDERR_FILENO, "chdir() failed\n", 15); - (void)r; - _exit(127); - } - it2->second.child = fd; - } - } - - if (dup2(it->second.child.native(), it->first) == -1) - { - auto r = write(STDERR_FILENO, "chdir() failed\n", 15); - if( r || !r ) _exit(127); - } - closeflags[it->first] = false; - } - } - - if (ctx.setup) - ctx.setup(); - - for (std::size_t i = 0; i < closeflags.size(); ++i) - { - if (closeflags[i]) - close(i); - } - - execve(executable.c_str(), argv.second, envp.second); - - // Actually we should delete argv and envp data. As we must not - // call any non-async-signal-safe functions though we simply exit. - auto r = write(STDERR_FILENO, "execve() failed\n", 16); - if( r || !r ) _exit(127); - _exit(127); - } - else - { - BOOST_ASSERT(pid > 0); - - for (std::size_t i = 0; i < argv.first; ++i) - delete[] argv.second[i]; - delete[] argv.second; - - for (std::size_t i = 0; i < envp.first; ++i) - delete[] envp.second[i]; - delete[] envp.second; - - std::map parent_ends; - for (handles_t::iterator it = handles.begin(); it != handles.end(); - ++it) - parent_ends[it->first] = it->second.parent; - - return child(pid, parent_ends); - } -#elif defined(BOOST_WINDOWS_API) - STARTUPINFOA startup_info; - ZeroMemory(&startup_info, sizeof(startup_info)); - startup_info.cb = sizeof(startup_info); - startup_info.dwFlags |= STARTF_USESTDHANDLES; - startup_info.hStdInput = handles[stdin_id].child.native(); - startup_info.hStdOutput = handles[stdout_id].child.native(); - startup_info.hStdError = handles[stderr_id].child.native(); - - if (ctx.setup) - ctx.setup(startup_info); - - PROCESS_INFORMATION pi; - ZeroMemory(&pi, sizeof(pi)); - - boost::shared_array cmdline = - detail::collection_to_windows_cmdline(args); - - boost::scoped_array exe(new char[executable.size() + 1]); -#if (BOOST_MSVC >= 1400) - strcpy_s(exe.get(), executable.size() + 1, executable.c_str()); -#else - strcpy(exe.get(), executable.c_str()); -#endif - - boost::scoped_array workdir(new char[ctx.work_dir.size() + 1]); -#if (BOOST_MSVC >= 1400) - strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str()); -#else - strcpy(workdir.get(), ctx.work_dir.c_str()); -#endif - - boost::shared_array envstrs = - detail::environment_to_windows_strings(ctx.env); - - DWORD creation_flags = 0; - if (ctx.suppress_console) - creation_flags |= CREATE_NO_WINDOW; - - if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, creation_flags, - envstrs.get(), workdir.get(), &startup_info, &pi) == 0) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed"); - - handle hprocess(pi.hProcess); - - if (!CloseHandle(pi.hThread)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); - - std::map parent_ends; - parent_ends[stdin_id] = handles[stdin_id].parent; - parent_ends[stdout_id] = handles[stdout_id].parent; - parent_ends[stderr_id] = handles[stderr_id].parent; - - return child(hprocess, parent_ends); -#endif -} - -/** - * \overload - */ -inline child create_child(const std::string &executable) -{ - return create_child(executable, std::vector(), context()); -} - -/** - * \overload - */ -template -inline child create_child(const std::string &executable, Arguments args) -{ - return create_child(executable, args, context()); -} - -/** - * Starts a shell-based command. - * - * Executes the given command through the default system shell. The - * command is subject to pattern expansion, redirection and pipelining. - * The shell is launched as described by the parameters in the context. - * - * This function behaves similarly to the system(3) system call. In a - * POSIX system, the command is fed to /bin/sh whereas under a Windows - * system, it is fed to cmd.exe. It is difficult to write portable - * commands, but this function comes in handy in multiple situations. - * - * \remark Blocking remarks: This function may block if the device holding the - * executable blocks when loading the image. This might happen if, e.g., - * the binary is being loaded from a network share. - * - * \return A handle to the new child process. - */ -template -inline child shell(const std::string &command, Context ctx) -{ -#if defined(BOOST_POSIX_API) - std::string executable = "/bin/sh"; - std::vector args; - args.push_back("-c"); - args.push_back(command); -#elif defined(BOOST_WINDOWS_API) - char sysdir[MAX_PATH]; - UINT size = GetSystemDirectoryA(sysdir, sizeof(sysdir)); - if (!size) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed"); - std::string executable = std::string(sysdir) + - (sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe"); - std::vector args; - args.push_back("/c"); - args.push_back(command); -#endif - return create_child(executable, args, ctx); -} - -/** - * \overload - */ -inline child shell(const std::string &command) -{ - return shell(command, context()); -} - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/pid_type.hpp b/vendor/boost_1.51/include/boost/process/pid_type.hpp deleted file mode 100644 index 49dc51e..0000000 --- a/vendor/boost_1.51/include/boost/process/pid_type.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pid_type.hpp - * - * Includes the declaration of the pid type. - */ - -#ifndef BOOST_PROCESS_PID_TYPE_HPP -#define BOOST_PROCESS_PID_TYPE_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -#elif defined(BOOST_WINDOWS_API) -# include -#endif - -namespace boost { -namespace process { - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * Opaque name for the process identifier type. - * - * Each operating system identifies processes using a specific type. - * The \a pid_type type is used to transparently refer to a process - * regardless of the operating system. - * - * This type is guaranteed to be an integral type on all supported - * platforms. On POSIX systems it is defined as pid_t, on Windows systems as - * DWORD. - */ -typedef NativeProcessId pid_type; -#elif defined(BOOST_POSIX_API) -typedef pid_t pid_type; -#elif defined(BOOST_WINDOWS_API) -typedef DWORD pid_type; -#endif - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/pipe.hpp b/vendor/boost_1.51/include/boost/process/pipe.hpp deleted file mode 100644 index 23eb0a8..0000000 --- a/vendor/boost_1.51/include/boost/process/pipe.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pipe.hpp - * - * Includes the declaration of the pipe class. - */ - -#ifndef BOOST_PROCESS_PIPE_HPP -#define BOOST_PROCESS_PIPE_HPP - -#include -#include - -namespace boost { -namespace process { - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * The pipe class is a type definition for stream-based classes defined by - * Boost.Asio. - * - * The type definition is provided for convenience. You can also use Boost.Asio - * classes directly for asynchronous I/O operations. - */ -typedef BoostAsioPipe pipe; -#elif defined(BOOST_POSIX_API) -typedef boost::asio::posix::stream_descriptor pipe; -#elif defined(BOOST_WINDOWS_API) -typedef boost::asio::windows::stream_handle pipe; -#else -# error "Unsupported platform." -#endif - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/pistream.hpp b/vendor/boost_1.51/include/boost/process/pistream.hpp deleted file mode 100644 index 9bb252f..0000000 --- a/vendor/boost_1.51/include/boost/process/pistream.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/pistream.hpp - * - * Includes the declaration of the pistream class. - */ - -#ifndef BOOST_PROCESS_PISTREAM_HPP -#define BOOST_PROCESS_PISTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' output stream. - * - * The pistream class represents an output communication channel with the - * child process. The child process writes data to this stream and the - * parent process can read it through the pistream object. In other - * words, from the child's point of view, the communication channel is an - * output one, but from the parent's point of view it is an input one; - * hence the confusing pistream name. - * - * pistream objects cannot be copied because they buffer data - * that flows through the communication channel. - * - * A pistream object behaves as a std::istream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that read data from this - * stream can block if the associated handle blocks during - * the read. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child has no more data to send to - * the pipe's system buffer. When this happens, the buffer - * eventually empties and the system blocks until the writer - * generates some data. - */ -class pistream : public std::istream, public boost::noncopyable -{ -public: - /** - * Creates a new process' output stream. - */ - explicit pistream(boost::process::handle h) - : std::istream(0), - handle_(h), - systembuf_(handle_.native()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the handle managed by this stream. - */ - const boost::process::handle &handle() const - { - return handle_; - } - - /** - * Returns the handle managed by this stream. - */ - boost::process::handle &handle() - { - return handle_; - } - - /** - * Closes the handle managed by this stream. - * - * Explicitly closes the handle managed by this stream. This - * function can be used by the user to tell the child process it's - * not willing to receive more data. - */ - void close() - { - handle_.close(); - } - -private: - /** - * The handle managed by this stream. - */ - boost::process::handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/postream.hpp b/vendor/boost_1.51/include/boost/process/postream.hpp deleted file mode 100644 index 23c34a9..0000000 --- a/vendor/boost_1.51/include/boost/process/postream.hpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/postream.hpp - * - * Includes the declaration of the postream class. - */ - -#ifndef BOOST_PROCESS_POSTREAM_HPP -#define BOOST_PROCESS_POSTREAM_HPP - -#include -#include -#include -#include - -namespace boost { -namespace process { - -/** - * Child process' input stream. - * - * The postream class represents an input communication channel with the - * child process. The child process reads data from this stream and the - * parent process can write to it through the postream object. In other - * words, from the child's point of view, the communication channel is an - * input one, but from the parent's point of view it is an output one; - * hence the confusing postream name. - * - * postream objects cannot be copied because they buffer data that flows - * through the communication channel. - * - * A postream object behaves as a std::ostream stream in all senses. - * The class is only provided because it must provide a method to let - * the caller explicitly close the communication channel. - * - * \remark Blocking remarks: Functions that write data to this - * stream can block if the associated handle blocks during - * the write. As this class is used to communicate with child - * processes through anonymous pipes, the most typical blocking - * condition happens when the child is not processing the data - * in the pipe's system buffer. When this happens, the buffer - * eventually fills up and the system blocks until the reader - * consumes some data, leaving some new room. - */ -class postream : public std::ostream, public boost::noncopyable -{ -public: - /** - * Creates a new process' input stream. - */ - explicit postream(boost::process::handle h) - : std::ostream(0), - handle_(h), - systembuf_(handle_.native()) - { - rdbuf(&systembuf_); - } - - /** - * Returns the handle managed by this stream. - */ - const boost::process::handle &handle() const - { - return handle_; - } - - /** - * Returns the handle managed by this stream. - */ - boost::process::handle &handle() - { - return handle_; - } - - /** - * Closes the handle managed by this stream. - * - * Explicitly closes the handle managed by this stream. This - * function can be used by the user to tell the child process there - * is no more data to send. - */ - void close() - { - systembuf_.sync(); - handle_.close(); - } - -private: - /** - * The handle managed by this stream. - */ - boost::process::handle handle_; - - /** - * The systembuf object used to manage this stream's data. - */ - detail::systembuf systembuf_; -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/process.hpp b/vendor/boost_1.51/include/boost/process/process.hpp deleted file mode 100644 index e0e2149..0000000 --- a/vendor/boost_1.51/include/boost/process/process.hpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/process.hpp - * - * Includes the declaration of the process class. - */ - -#ifndef BOOST_PROCESS_PROCESS_HPP -#define BOOST_PROCESS_PROCESS_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -# include -#else -# error "Unsupported platform." -#endif - -#include - -namespace boost { -namespace process { - -/** - * Process class to represent any running process. - */ -class process -{ -public: - /** - * Constructs a new process object. - * - * Creates a new process object that represents a running process - * within the system. - * - * On Windows the process is opened and a handle saved. This is required - * to avoid the operating system removing process resources when the - * process exits. The handle is closed when the process instance (and all - * of its copies) is destroyed. - */ - process(pid_type id) - : id_(id) -#if defined(BOOST_WINDOWS_API) - , handle_(open_process(id)) -#endif - { - } - -#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN) - /** - * Constructs a new process object. - * - * Creates a new process object that represents a running process - * within the system. - * - * This operation is only available on Windows systems. The handle is - * closed when the process instance (and all of its copies) is destroyed. - */ - process(handle h) - : id_(GetProcessId(h.native())), - handle_(h) - { - } -#endif - - /** - * Returns the process identifier. - */ - pid_type get_id() const - { - return id_; - } - - /** - * Terminates the process execution. - * - * Forces the termination of the process execution. Some platforms - * allow processes to ignore some external termination notifications - * or to capture them for a proper exit cleanup. You can set the - * \a force flag to true to force their termination regardless - * of any exit handler. - * - * After this call, accessing this object can be dangerous because the - * process identifier may have been reused by a different process. It - * might still be valid, though, if the process has refused to die. - * - * \throw boost::system::system_error If system calls used to terminate the - * process fail. - */ - void terminate(bool force = false) const - { -#if defined(BOOST_POSIX_API) - if (kill(id_, force ? SIGKILL : SIGTERM) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed"); -#elif defined(BOOST_WINDOWS_API) -#if defined(BOOST_MSVC) - force; -#endif - HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - if (!TerminateProcess(h, EXIT_FAILURE)) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed"); - } - if (!CloseHandle(h)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); -#endif - } - - /** - * Blocks and waits for the process to terminate. - * - * Returns an exit code. The process object ceases to be valid after this - * call. - * - * \remark Blocking remarks: This call blocks if the process has not - * finalized execution and waits until it terminates. - * - * \throw boost::system::system_error If system calls used to wait for the - * process fail. - */ - int wait() const - { -#if defined(BOOST_POSIX_API) - pid_t p; - int status; - do - { - p = waitpid(id_, &status, 0); - } while (p == -1 && errno == EINTR); - if (p == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed"); - return status; -#elif defined(BOOST_WINDOWS_API) - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, - id_); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "WaitForSingleObject() failed"); - } - DWORD exit_code; - if (!GetExitCodeProcess(h, &exit_code)) - { - CloseHandle(h); - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetExitCodeProcess() failed"); - } - if (!CloseHandle(h)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed"); - return exit_code; -#endif - } - -private: - /** - * The process identifier. - */ - pid_type id_; - -#if defined(BOOST_WINDOWS_API) - /** - * Opens a process and returns a handle. - * - * OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure. - * That's why the return value is manually checked in this helper function - * instead of simply passing it to the constructor of the handle class. - */ - HANDLE open_process(pid_type id) - { - HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id); - if (h == NULL) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed"); - return h; - } -protected: - /** - * The process handle. - */ - handle handle_; -private: -#endif -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/self.hpp b/vendor/boost_1.51/include/boost/process/self.hpp deleted file mode 100644 index 704501c..0000000 --- a/vendor/boost_1.51/include/boost/process/self.hpp +++ /dev/null @@ -1,188 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/self.hpp - * - * Includes the declaration of the self class. - */ - -#ifndef BOOST_PROCESS_SELF_HPP -#define BOOST_PROCESS_SELF_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -# include -# if defined(__APPLE__) -# include -# endif -#elif defined(BOOST_WINDOWS_API) -# include -#else -# error "Unsupported platform." -#endif - -#include -#include -#include -#include -#include - -#if defined(BOOST_POSIX_API) -extern "C" -{ - extern char **environ; -} -#endif - -namespace boost { -namespace process { - -/** - * The self class provides access to the process itself. - */ -class self : public process, public boost::noncopyable -{ -public: - /** - * Returns the self instance representing the caller's process. - */ - static self &get_instance() - { - static self *instance = 0; - if (!instance) - instance = new self; - return *instance; - } - - /** - * Returns the current environment. - * - * Returns the current process environment variables. Modifying the - * returned object has no effect on the current environment. - */ - static environment get_environment() - { - environment e; - -#if defined(BOOST_POSIX_API) -# if defined(__APPLE__) - char **env = *_NSGetEnviron(); -# else - char **env = environ; -# endif - - while (*env) - { - std::string s = *env; - std::string::size_type pos = s.find('='); - e.insert(environment::value_type(s.substr(0, pos), - s.substr(pos + 1))); - ++env; - } -#elif defined(BOOST_WINDOWS_API) -# ifdef GetEnvironmentStrings -# undef GetEnvironmentStrings -# endif - - char *ms_environ = GetEnvironmentStrings(); - if (!ms_environ) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetEnvironmentStrings() failed"); - try - { - char *env = ms_environ; - while (*env) - { - std::string s = env; - std::string::size_type pos = s.find('='); - e.insert(environment::value_type(s.substr(0, pos), - s.substr(pos + 1))); - env += s.size() + 1; - } - } - catch (...) - { - FreeEnvironmentStringsA(ms_environ); - throw; - } - FreeEnvironmentStringsA(ms_environ); -#endif - - return e; - } - - /** - * Returns the current work directory. - */ - static std::string get_work_dir() - { -#if defined(BOOST_POSIX_API) -#if defined(PATH_MAX) - char buffer[PATH_MAX]; - char *cwd = buffer; - long size = PATH_MAX; -#elif defined(_PC_PATH_MAX) - errno = 0; - long size = pathconf("/", _PC_PATH_MAX); - if (size == -1 && errno) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed"); - else if (size == -1) - size = BOOST_PROCESS_POSIX_PATH_MAX; - BOOST_ASSERT(size > 0); - boost::scoped_array buffer(new char[size]); - char *cwd = buffer.get(); -#else - char buffer[BOOST_PROCESS_POSIX_PATH_MAX]; - char *cwd = buffer; - long size = BOOST_PROCESS_POSIX_PATH_MAX; -#endif - if (!getcwd(cwd, size)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed"); - BOOST_ASSERT(cwd[0] != '\0'); - return cwd; -#elif defined(BOOST_WINDOWS_API) - BOOST_ASSERT(MAX_PATH > 0); - char cwd[MAX_PATH]; - if (!GetCurrentDirectoryA(sizeof(cwd), cwd)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "GetCurrentDirectory() failed"); - BOOST_ASSERT(cwd[0] != '\0'); - return cwd; -#endif - } - -private: - /** - * Constructs a new self object. - * - * Creates a new self object that represents the current process. - */ - self() : -#if defined(BOOST_POSIX_API) - process(getpid()) -#elif defined(BOOST_WINDOWS_API) - process(GetCurrentProcessId()) -#endif - { - } -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/status.hpp b/vendor/boost_1.51/include/boost/process/status.hpp deleted file mode 100644 index 55b89f3..0000000 --- a/vendor/boost_1.51/include/boost/process/status.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/status.hpp - * - * Includes the declaration of the status class. - */ - -#ifndef BOOST_PROCESS_STATUS_HPP -#define BOOST_PROCESS_STATUS_HPP - -#include -#include -#include - -namespace boost { -namespace process { - -/** - * The status class to wait for processes to exit. - * - * The status class is a Boost.Asio I/O object and supports synchronous - * and asynchronous wait operations. - */ -typedef detail::basic_status > status; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/stream_behavior.hpp b/vendor/boost_1.51/include/boost/process/stream_behavior.hpp deleted file mode 100644 index 2911f56..0000000 --- a/vendor/boost_1.51/include/boost/process/stream_behavior.hpp +++ /dev/null @@ -1,326 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_behavior.hpp - * - * Includes the declaration of stream behavior classes. - */ - -#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP -#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP - -#include - -#if defined(BOOST_POSIX_API) -# include -# include -# include -#elif defined(BOOST_WINDOWS_API) -# include -# include -#endif - -#include -#include -#include -#include -#include - -namespace boost { -namespace process { -namespace behavior { - -/** - * Stream behavior to close streams of a child process. - * - * A child process will not be able to use the stream. - */ -class close -{ -public: - stream_ends operator()(stream_type) const - { - return stream_ends(); - } -}; - -/** - * Stream behavior to make a child process inherit streams. - * - * A child process will use the very same stream of its parent process. - */ -class inherit -{ -public: - inherit(handle::native_type h) - : h_(h, handle::dont_close) - { -#if defined(BOOST_WINDOWS_API) - if (h != INVALID_HANDLE_VALUE) - { - if (!SetHandleInformation(h_.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - { - HANDLE proc = GetCurrentProcess(); - HANDLE dup; - if (!DuplicateHandle(proc, h_.native(), proc, &dup, 0, - TRUE, DUPLICATE_SAME_ACCESS)) - { - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "DuplicateHandle() failed"); - } - h_ = dup; - } - } -#endif - } - - stream_ends operator()(stream_type) const - { - return stream_ends(h_, handle()); - } - -private: - handle h_; -}; - -/** - * Stream behavior to redirect streams with a pipe. - * - * A child process will be able to communicate with its parent process. - */ -class pipe -{ -public: -#if defined(BOOST_POSIX_API) - pipe() - : stype_(unknown_stream) - { - } - - pipe(stream_type stype) - : stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { - handle::native_type ends[2]; -#if defined(BOOST_POSIX_API) - if (::pipe(ends) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed"); - if (stype_ != unknown_stream) - stype = stype_; -#elif defined(BOOST_WINDOWS_API) - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = FALSE; - if (!CreatePipe(&ends[0], &ends[1], &sa, 0)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed"); -#endif - handle child_end = ends[stype == input_stream ? 0 : 1]; - handle parent_end = ends[stype == input_stream ? 1 : 0]; -#if defined(BOOST_WINDOWS_API) - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, parent_end); - } - -#if defined(BOOST_POSIX_API) -private: - stream_type stype_; -#endif -}; - -/** - * Stream behavior to redirect streams with a named pipe. - * - * A child process will be able to communicate with its parent process. - */ -class named_pipe -{ -public: - named_pipe(const std::string &name) - : name_(name) -#if defined(BOOST_POSIX_API) - , stype_(unknown_stream) -#endif - { - } - -#if defined(BOOST_POSIX_API) - named_pipe(const std::string &name, stream_type stype) - : name_(name), - stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { -#if defined(BOOST_POSIX_API) - if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed"); - handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); - int opts = fcntl(child_end.native(), F_GETFL); - if (opts == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed"); - opts ^= O_NONBLOCK; - if (fcntl(child_end.native(), F_SETFL, opts) == -1) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed"); - handle parent_end = open(name_.c_str(), O_WRONLY); - if (!parent_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); - if (stype_ != unknown_stream) - stype = stype_; -#elif defined(BOOST_WINDOWS_API) - SECURITY_ATTRIBUTES sa; - ZeroMemory(&sa, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = TRUE; - handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND | - FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed"); - handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL, - OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (!parent_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); -#endif - if (stype == output_stream) - std::swap(child_end, parent_end); -#if defined(BOOST_WINDOWS_API) - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, parent_end); - } - -private: - std::string name_; - -#if defined(BOOST_POSIX_API) - stream_type stype_; -#endif -}; - -/** - * Stream behavior to redirect streams with a pipe which supports asynchronous - * I/O. - * - * As platforms require different types of pipes for asynchronous I/O this - * stream behavior is provided for convenience. It uses the minimum required - * pipe type on a platform in order to be able to use asynchronous I/O. - */ -#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN) -typedef pipe async_pipe; -#elif defined(BOOST_WINDOWS_API) -class async_pipe -{ -public: - stream_ends operator()(stream_type stype) const - { - UUID uuid; - RPC_STATUS s = UuidCreateSequential(&uuid); - if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY) - BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed"); - unsigned char *c; - s = UuidToStringA(&uuid, &c); - if (s != RPC_S_OK) - BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed"); - std::string name; - try - { - name = reinterpret_cast(c); - } - catch (...) - { - RpcStringFreeA(&c); - throw; - } - RpcStringFreeA(&c); - named_pipe p("\\\\.\\pipe\\boost_process_" + name); - return p(stype); - } -}; -#endif - -/** - * Stream behavior to mute streams. - * - * A child process will be able to use streams. But data written to an - * output stream is discarded and data read from an input stream is 0. - */ -class null -{ -public: -#if defined(BOOST_POSIX_API) - null() - : stype_(unknown_stream) - { - } - - null(stream_type stype) - : stype_(stype) - { - } -#endif - - stream_ends operator()(stream_type stype) const - { -#if defined(BOOST_POSIX_API) - if (stype_ != unknown_stream) - stype = stype_; - std::string filename = (stype == input_stream) ? "/dev/zero" : - "/dev/null"; - int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY; - handle child_end = open(filename.c_str(), flag); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed"); -#elif defined(BOOST_WINDOWS_API) - DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE; - handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (!child_end.valid()) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed"); - if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT, - HANDLE_FLAG_INHERIT)) - BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR( - "SetHandleInformation() failed"); -#endif - return stream_ends(child_end, handle()); - } - -#if defined(BOOST_POSIX_API) -private: - stream_type stype_; -#endif -}; - -} -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/stream_ends.hpp b/vendor/boost_1.51/include/boost/process/stream_ends.hpp deleted file mode 100644 index 2ae87a1..0000000 --- a/vendor/boost_1.51/include/boost/process/stream_ends.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_ends.hpp - * - * Includes the declaration of the stream_ends class. - */ - -#ifndef BOOST_PROCESS_STREAM_ENDS_HPP -#define BOOST_PROCESS_STREAM_ENDS_HPP - -#include -#include - -namespace boost { -namespace process { - -/** - * A pair of handles to configure streams. - * - * Stream behaviors return a pair of handles to specify how a child's stream - * should be configured and possibly the opposite end of a child's end. This - * is the end remaining in the parent process and which can be used for example - * to communicate with a child process through its standard streams. - */ -struct stream_ends { - /** - * The child's end. - */ - handle child; - - /** - * The parent's end. - */ - handle parent; - - /** - * Standard constructor creating two invalid handles. - */ - stream_ends() - { - } - - /** - * Helper constructor to easily initialize handles. - */ - stream_ends(handle c, handle p) - : child(c), - parent(p) - { - } -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/stream_id.hpp b/vendor/boost_1.51/include/boost/process/stream_id.hpp deleted file mode 100644 index cb098c7..0000000 --- a/vendor/boost_1.51/include/boost/process/stream_id.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_id.hpp - * - * Includes the declaration of the stream_id type. - */ - -#ifndef BOOST_PROCESS_STREAM_ID_HPP -#define BOOST_PROCESS_STREAM_ID_HPP - -#include - -namespace boost { -namespace process { - -/** - * Standard stream id to refer to standard streams in a cross-platform manner. - */ -enum std_stream_id { stdin_id, stdout_id, stderr_id }; - -#if defined(BOOST_PROCESS_DOXYGEN) -/** - * Stream id type. - * - * Depending on the platform the stream id type is defined to refer to standard - * streams only or to support more streams. - */ -typedef NativeStreamId stream_id; -#elif defined(BOOST_POSIX_API) -typedef int stream_id; -#elif defined(BOOST_WINDOWS_API) -typedef std_stream_id stream_id; -#endif - -} -} - -#endif diff --git a/vendor/boost_1.51/include/boost/process/stream_type.hpp b/vendor/boost_1.51/include/boost/process/stream_type.hpp deleted file mode 100644 index d78c1f9..0000000 --- a/vendor/boost_1.51/include/boost/process/stream_type.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Boost.Process -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2006, 2007 Julio M. Merino Vidal -// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling -// Copyright (c) 2009 Boris Schaeling -// Copyright (c) 2010 Felipe Tanus, Boris Schaeling -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -/** - * \file boost/process/stream_type.hpp - * - * Includes the declaration of the stream_type enumeration. - */ - -#ifndef BOOST_PROCESS_STREAM_TYPE_HPP -#define BOOST_PROCESS_STREAM_TYPE_HPP - -#include - -namespace boost { -namespace process { - -/** - * Stream type to differentiate between input and output streams. - * - * On POSIX systems another value unknown_stream is defined. It is passed - * to stream behaviors for file descriptors greater than 2. - */ -enum stream_type { - input_stream, - output_stream -#if defined(BOOST_POSIX_API) - , unknown_stream -#endif -}; - -} -} - -#endif diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S deleted file mode 100644 index 7724441..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_arm_aapcs_elf_gas.S +++ /dev/null @@ -1,101 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************* - * * - * ------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * - * ------------------------------------------------------------- * - * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| * - * ------------------------------------------------------------- * - * | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 10 | | * - * ------------------------------------------------------------- * - * | 0x28| | * - * ------------------------------------------------------------- * - * | pc | | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 11 | 12 | | * - * ------------------------------------------------------------- * - * | 0x2c| 0x30| | * - * ------------------------------------------------------------- * - * |sbase|slimit| | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | * - * ------------------------------------------------------------- * - * | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | * - * ------------------------------------------------------------- * - * | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 23 | 24 | 25 | 26 | 27 | 28 | | * - * ------------------------------------------------------------- * - * | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | * - * ------------------------------------------------------------- * - * | s26 | s27 | s28 | s29 | s30 | s31 | | * - * ------------------------------------------------------------- * - * * - * *****************************************************************/ - -.text -.globl jump_fcontext -.align 2 -.type jump_fcontext,%function -jump_fcontext: - stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR - str lr, [a1,#40] @ save LR as PC - -#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) - cmp a4, #0 @ test if fpu env should be preserved - beq 1f - - mov a4, a1 - add a4, #52 - fstmiax a4, {d8-d15} @ save S16-S31 - - mov a4, a2 - add a4, #52 - fldmiax a4, {d8-d15} @ restore S16-S31 -1: -#endif - - mov a1, a3 @ use third arg as return value after jump - @ and as first arg in context function - ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC -.size jump_fcontext,.-jump_fcontext - -.text -.globl make_fcontext -.align 2 -.type make_fcontext,%function -make_fcontext: - str a1, [a1,#0] @ save the address of passed context - str a2, [a1,#40] @ save address of the context function - ldr a2, [a1,#44] @ load the stack base - - push {a1,lr} @ save pointer to fcontext_t - mov a1, a2 @ stack pointer as arg for align_stack - bl align_stack@PLT @ align stack - mov a2, a1 @ begin of aligned stack - pop {a1,lr} @ restore pointer to fcontext_t - - str a2, [a1,#32] @ save the aligned stack base - - adr a2, finish @ address of finish; called after context function returns - str a2, [a1,#36] - - mov a1, #0 - bx lr - -finish: - mov a1, #0 @ exit code is zero - bl _exit@PLT @ exit application -.size make_fcontext,.-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm b/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm deleted file mode 100644 index 0f4dd67..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_i386_ms_pe_masm.asm +++ /dev/null @@ -1,151 +0,0 @@ - -; Copyright Oliver Kowalke 2009. -; Distributed under the Boost Software License, Version 1.0. -; (See accompanying file LICENSE_1_0.txt or copy at -; http://www.boost.org/LICENSE_1_0.txt) - -; -------------------------------------------------------------- -; | 0 | 1 | 2 | 3 | 4 | 5 | -; -------------------------------------------------------------- -; | 0h | 04h | 08h | 0ch | 010h | 014h | -; -------------------------------------------------------------- -; | EDI | ESI | EBX | EBP | ESP | EIP | -; -------------------------------------------------------------- -; -------------------------------------------------------------- -; | 6 | 7 | | -; -------------------------------------------------------------- -; | 018h | 01ch | | -; -------------------------------------------------------------- -; | ss_base | ss_limit| | -; -------------------------------------------------------------- -; -------------------------------------------------------------- -; | 8 | | -; -------------------------------------------------------------- -; | 020h | | -; -------------------------------------------------------------- -; |fc_execpt| | -; -------------------------------------------------------------- -; -------------------------------------------------------------- -; | 9 | | -; -------------------------------------------------------------- -; | 024h | | -; -------------------------------------------------------------- -; |fc_strage| | -; -------------------------------------------------------------- -; -------------------------------------------------------------- -; | 10 | 11 | | -; -------------------------------------------------------------- -; | 028h | 02ch | | -; -------------------------------------------------------------- -; | fc_mxcsr|fc_x87_cw| | -; -------------------------------------------------------------- - -.386 -.XMM -.model flat, c -_exit PROTO, value:SDWORD -align_stack PROTO, vp:DWORD -seh_fcontext PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD -.code - -jump_fcontext PROC EXPORT - mov ecx, [esp+04h] ; load address of the first fcontext_t arg - mov [ecx], edi ; save EDI - mov [ecx+04h], esi ; save ESI - mov [ecx+08h], ebx ; save EBX - mov [ecx+0ch], ebp ; save EBP - - assume fs:nothing - mov edx, fs:[018h] ; load NT_TIB - assume fs:error - mov eax, [edx] ; load current SEH exception list - mov [ecx+020h], eax ; save current exception list - mov eax, [edx+04h] ; load current stack base - mov [ecx+018h], eax ; save current stack base - mov eax, [edx+08h] ; load current stack limit - mov [ecx+01ch], eax ; save current stack limit - mov eax, [edx+010h] ; load fiber local storage - mov [ecx+024h], eax ; save fiber local storage - - lea eax, [esp+04h] ; exclude the return address - mov [ecx+010h], eax ; save as stack pointer - mov eax, [esp] ; load return address - mov [ecx+014h], eax ; save return address - - mov edx, [esp+08h] ; load address of the second fcontext_t arg - mov edi, [edx] ; restore EDI - mov esi, [edx+04h] ; restore ESI - mov ebx, [edx+08h] ; restore EBX - mov ebp, [edx+0ch] ; restore EBP - - mov eax, [esp+010h] ; check if fpu enve preserving was requested - test eax, eax - je nxt - - stmxcsr [ecx+028h] ; save MMX control word - fnstcw [ecx+02ch] ; save x87 control word - ldmxcsr [edx+028h] ; restore MMX control word - fldcw [edx+02ch] ; restore x87 control word -nxt: - mov ecx, edx - assume fs:nothing - mov edx, fs:[018h] ; load NT_TIB - assume fs:error - mov eax, [ecx+020h] ; load SEH exception list - mov [edx], eax ; restore next SEH item - mov eax, [ecx+018h] ; load stack base - mov [edx+04h], eax ; restore stack base - mov eax, [ecx+01ch] ; load stack limit - mov [edx+08h], eax ; restore stack limit - mov eax, [ecx+024h] ; load fiber local storage - mov [edx+010h], eax ; restore fiber local storage - - mov eax, [esp+0ch] ; use third arg as return value after jump - - mov esp, [ecx+010h] ; restore ESP - mov [esp+04h], eax ; use third arg as first arg in context function - mov ecx, [ecx+014h] ; fetch the address to return to - - jmp ecx ; indirect jump to context -jump_fcontext ENDP - -make_fcontext PROC EXPORT - mov eax, [esp+04h] ; load address of the fcontext_t arg0 - mov [eax], eax ; save the address of passed context - mov ecx, [esp+08h] ; load the address of the context function - mov [eax+014h], ecx ; save the address of the context function - mov edx, [eax+018h] ; load the stack base - - push eax ; save pointer to fcontext_t - push edx ; stack pointer as arg for align_stack - call align_stack ; align stack - mov edx, eax ; begin of aligned stack - pop eax ; remove arg for align_stack - pop eax ; restore pointer to fcontext_t - - lea edx, [edx-014h] ; reserve space for last frame on stack, (ESP + 4) & 15 == 0 - mov [eax+010h], edx ; save the aligned stack - - mov ecx, seh_fcontext ; set ECX to exception-handler - mov [edx+0ch], ecx ; save ECX as SEH handler - mov ecx, 0ffffffffh ; set ECX to -1 - mov [edx+08h], ecx ; save ECX as next SEH item - lea ecx, [edx+08h] ; load address of next SEH item - mov [eax+02ch], ecx ; save next SEH - - stmxcsr [eax+028h] ; save MMX control word - fnstcw [eax+02ch] ; save x87 control word - - mov ecx, finish ; address of finish - mov [edx], ecx - - xor eax, eax - ret - -finish: - xor eax, eax - push eax ; exit code is zero - call _exit ; exit application - hlt -make_fcontext ENDP -END diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S deleted file mode 100644 index 7c94ea0..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_elf_gas.S +++ /dev/null @@ -1,122 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************** - * * - * -------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | * - * -------------------------------------------------------------- * - * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * - * -------------------------------------------------------------- * - * | EDI | ESI | EBX | EBP | ESP | EIP | * - * -------------------------------------------------------------- * - * -------------------------------------------------------------- * - * | 6 | 7 | | * - * -------------------------------------------------------------- * - * | 0x18 | 0x1c | | * - * -------------------------------------------------------------- * - * | sbase | slimit | | * - * -------------------------------------------------------------- * - * -------------------------------------------------------------- * - * | 8 | 9 | | * - * -------------------------------------------------------------- * - * | 0x20 | 0x24 | | * - * -------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| | * - * -------------------------------------------------------------- * - * * - * *****************************************************************/ - -.text -.globl jump_fcontext -.align 2 -.type jump_fcontext,@function -jump_fcontext: - movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ - movl %edi, (%ecx) /* save EDI */ - movl %esi, 0x4(%ecx) /* save ESI */ - movl %ebx, 0x8(%ecx) /* save EBX */ - movl %ebp, 0xc(%ecx) /* save EBP */ - - leal 0x4(%esp), %eax /* exclude the return address */ - movl %eax, 0x10(%ecx) /* save as stack pointer */ - movl (%esp), %eax /* load return address */ - movl %eax, 0x14(%ecx) /* save return address */ - - movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ - movl (%edx), %edi /* restore EDI */ - movl 0x4(%edx), %esi /* restore ESI */ - movl 0x8(%edx), %ebx /* restore EBX */ - movl 0xc(%edx), %ebp /* restore EBP */ - - movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ - test %eax, %eax - je 1f - - stmxcsr 0x20(%ecx) /* save MMX control and status word */ - fnstcw 0x24(%ecx) /* save x87 control word */ - ldmxcsr 0x20(%edx) /* restore MMX control and status word */ - fldcw 0x24(%edx) /* restore x87 control word */ -1: - movl 0xc(%esp), %eax /* use third arg as return value after jump */ - - movl 0x10(%edx), %esp /* restore ESP */ - movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ - movl 0x14(%edx), %edx /* fetch the address to return to */ - - jmp *%edx /* indirect jump to context */ -.size jump_fcontext,.-jump_fcontext - -.text -.globl make_fcontext -.align 2 -.type make_fcontext,@function -make_fcontext: - movl 0x4(%esp), %eax /* load address of the fcontext_t */ - movl %eax, (%eax) /* save the address of current context */ - movl 0x8(%esp), %ecx /* load the address of the context function */ - movl %ecx, 0x14(%eax) /* save the address of the context function */ - movl 0x18(%eax), %edx /* load the stack base */ - - pushl %eax /* save pointer to fcontext_t */ - pushl %ebx /* save EBX */ - pushl %edx /* stack pointer as arg for align_stack */ - call 1f -1: popl %ebx /* address of label 1 */ - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */ - call align_stack@PLT /* align stack */ - movl %eax, %edx /* begin of aligned stack */ - popl %eax /* remove arg for align_stack */ - popl %ebx /* restore EBX */ - popl %eax /* restore pointer to fcontext_t */ - - leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */ - movl %edx, 0x10(%eax) /* save the aligned stack base */ - - stmxcsr 0x20(%eax) /* save MMX control and status word */ - fnstcw 0x24(%eax) /* save x87 control word */ - - call 2f -2: popl %ecx /* address of label 2 */ - addl $finish-2b, %ecx /* helper code executed after context function returns */ - movl %ecx, (%edx) - - xorl %eax, %eax - ret - -finish: - leal -0xc(%esp), %esp - - call 3f -3: popl %ebx /* address of label 3 */ - addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */ - - xorl %eax, %eax - pushl %eax /* exit code is zero */ - call _exit@PLT /* exit application */ - hlt -.size make_fcontext,.-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S deleted file mode 100644 index a28c875..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_i386_sysv_macho_gas.S +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************** - * * - * -------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | * - * -------------------------------------------------------------- * - * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | * - * -------------------------------------------------------------- * - * | EDI | ESI | EBX | EBP | ESP | EIP | * - * -------------------------------------------------------------- * - * -------------------------------------------------------------- * - * | 6 | 7 | | * - * -------------------------------------------------------------- * - * | 0x18 | 0x1c | | * - * -------------------------------------------------------------- * - * | sbase | slimit | | * - * -------------------------------------------------------------- * - * -------------------------------------------------------------- * - * | 8 | 9 | | * - * -------------------------------------------------------------- * - * | 0x20 | 0x24 | | * - * -------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| | * - * -------------------------------------------------------------- * - * * - * *****************************************************************/ - -.text -.globl _jump_fcontext -.align 2 -_jump_fcontext: - movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */ - movl %edi, (%ecx) /* save EDI */ - movl %esi, 0x4(%ecx) /* save ESI */ - movl %ebx, 0x8(%ecx) /* save EBX */ - movl %ebp, 0xc(%ecx) /* save EBP */ - - leal 0x4(%esp), %eax /* exclude the return address */ - movl %eax, 0x10(%ecx) /* save as stack pointer */ - movl (%esp), %eax /* load return address */ - movl %eax, 0x14(%ecx) /* save return address */ - - movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */ - movl (%edx), %edi /* restore EDI */ - movl 0x4(%edx), %esi /* restore ESI */ - movl 0x8(%edx), %ebx /* restore EBX */ - movl 0xc(%edx), %ebp /* restore EBP */ - - movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */ - test %eax, %eax - je 1f - - stmxcsr 0x20(%ecx) /* save MMX control and status word */ - fnstcw 0x24(%ecx) /* save x87 control word */ - ldmxcsr 0x20(%edx) /* restore MMX control and status word */ - fldcw 0x24(%edx) /* restore x87 control word */ -1: - movl 0xc(%esp), %eax /* use third arg as return value after jump */ - - movl 0x10(%edx), %esp /* restore ESP */ - movl %eax, 0x4(%esp) /* use third arg as first arg in context function */ - movl 0x14(%edx), %edx /* fetch the address to return to */ - - jmp *%edx /* indirect jump to context */ - -.text -.globl _make_fcontext -.align 2 -_make_fcontext: - movl 0x4(%esp), %eax /* load address of the fcontext_t */ - movl %eax, (%eax) /* save the address of current context */ - movl 0x8(%esp), %ecx /* load the address of the context function */ - movl %ecx, 0x14(%eax) /* save the address of the context function */ - movl 0x18(%eax), %edx /* load the stack base */ - - pushl %eax /* save pointer to fcontext_t */ - pushl %ebx /* save EBX */ - pushl %edx /* stack pointer as arg for align_stack */ - call 1f -1: popl %ebx /* address of label 1 */ - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */ - call align_stack@PLT /* align stack */ - movl %eax, %edx /* begin of aligned stack */ - popl %eax /* remove arg for align_stack */ - popl %ebx /* restore EBX */ - popl %eax /* restore pointer to fcontext_t */ - - leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */ - movl %edx, 0x10(%eax) /* save the aligned stack base */ - - stmxcsr 0x20(%eax) /* save MMX control and status word */ - fnstcw 0x24(%eax) /* save x87 control word */ - - call 2f -2: popl %ecx /* address of label 2 */ - addl $finish-2b, %ecx /* helper code executed after context function returns */ - movl %ecx, (%edx) - - xorl %eax, %eax - ret - -finish: - leal -0xc(%esp), %esp - - call 3f -3: popl %ebx /* address of label 3 */ - addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */ - - xorl %eax, %eax - pushl %eax /* exit code is zero */ - call _exit@PLT /* exit application */ - hlt diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S deleted file mode 100644 index be86f18..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_mips32_o32_elf_gas.S +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************* - * * - * ------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * - * ------------------------------------------------------------- * - * | 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | * - * ------------------------------------------------------------- * - * | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | GP | SP | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 10 | 11 | 12 | | * - * ------------------------------------------------------------- * - * | 80 | 88 | 96 | | * - * ------------------------------------------------------------- * - * | S8 | RA | PC | | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 13 | 14 | | * - * ------------------------------------------------------------- * - * | 104 | 112 | | * - * ------------------------------------------------------------- * - * |sbase|slimt| | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 15 | 16 | 17 | 18 | 19 | 20 | | * - * ------------------------------------------------------------- * - * | 120 | 128 | 136 | 144 | 152 | 160 | | * - * ------------------------------------------------------------- * - * | F20 | F22 | F24 | F26 | F28 | F30 | | * - * ------------------------------------------------------------- * - * * - * *****************************************************************/ - -.text -.globl jump_fcontext -.align 2 -.type jump_fcontext,@function -.ent jump_fcontext -jump_fcontext: - sw $s0, ($a0) # save S0 - sw $s1, 8($a0) # save S1 - sw $s2, 16($a0) # save S2 - sw $s3, 24($a0) # save S3 - sw $s4, 32($a0) # save S4 - sw $s5, 40($a0) # save S5 - sw $s6, 48($a0) # save S6 - sw $s7, 56($a0) # save S7 - sw $gp, 64($a0) # save GP - sw $sp, 72($a0) # save SP - sw $s8, 80($a0) # save S8 - sw $ra, 88($a0) # save RA - sw $ra, 96($a0) # save RA as PC - -#if defined(__mips_hard_float) - beqz $a3, 1f # test if fpu env should be preserved - s.d $f20, 120($a0) # save F20 - s.d $f22, 128($a0) # save F22 - s.d $f24, 136($a0) # save F24 - s.d $f26, 144($a0) # save F26 - s.d $f28, 152($a0) # save F28 - s.d $f30, 160($a0) # save F30 - - l.d $f20, 120($a1) # restore F20 - l.d $f22, 128($a1) # restore F22 - l.d $f24, 136($a1) # restore F24 - l.d $f26, 144($a1) # restore F26 - l.d $f28, 152($a1) # restore F28 - l.d $f30, 160($a1) # restore F30 -1: -#endif - - lw $s0, ($a1) # restore S0 - lw $s1, 8($a1) # restore S1 - lw $s2, 16($a1) # restore S2 - lw $s3, 24($a1) # restore S3 - lw $s4, 32($a1) # restore S4 - lw $s5, 40($a1) # restore S5 - lw $s6, 48($a1) # restore S6 - lw $s7, 56($a1) # restore S7 - lw $gp, 64($a1) # restore GP - lw $sp, 72($a1) # restore SP - lw $s8, 80($a1) # restore S8 - lw $ra, 88($a1) # restore RA - move $a0, $s2 # restore void pointer as argument - - move $v0, $a2 # use third arg as return value after jump - move $a0, $a2 # use third arg as first arg in context function - - lw $t9, 96($a1) # load PC - jr $t9 # jump to context -.end jump_fcontext -.size jump_fcontext, .-jump_fcontext - -.text -.globl make_fcontext -.align 2 -.type make_fcontext,@function -.ent make_fcontext -make_fcontext: -#ifdef __PIC__ -.set noreorder -.cpload $t9 -.set reorder -#endif - sw $a0, ($a0) # save the current context - sw $gp, 24($a0) # save global pointer - sw $a1, 96($a0) # save the address of the context function - lw $t0, 104($a0) # load the stack base - - sub $sp, $sp, 28 - sw $ra, 24($sp) - sw $a0, 20($sp) - move $a0, $t0 # stack pointer as arg for align_stack - lw $t9, %call16(align_stack)($gp) # align stack - jalr $t9 - nop - move $t0, $v0 # begin of aligned stack - lw $ra, 24($sp) - lw $a0, 20($sp) - addi $sp, $sp, 28 - - sub $t0, $t0, 16 # reserve 16 byte of argument space - sw $t0, 72($a0) # save the algned stack base - - la $t9, finish # helper code executed after context function returns - sw $t9, 88($a0) - - move $v0, $zero - jr $ra - -finish: - move $gp, $s3 # restore GP (global pointer) - move $a0, $zero # exit code is zero - lw $t9, %call16(_exit)($gp) # exit application - jalr $t9 -.end make_fcontext -.size make_fcontext, .-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S deleted file mode 100644 index 69b6ed9..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_ppc32_sysv_elf_gas.S +++ /dev/null @@ -1,222 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************* - * * - * ------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * - * ------------------------------------------------------------- * - * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * - * ------------------------------------------------------------- * - * | R13 | R14 | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * - * ------------------------------------------------------------- * - * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * - * ------------------------------------------------------------- * - * | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | SP | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 20 | 21 | 22 | | * - * ------------------------------------------------------------- * - * | 80 | 84 | 88 | | * - * ------------------------------------------------------------- * - * | CR | LR | PC | | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 23 | 24 | | * - * ------------------------------------------------------------- * - * | 92 | 96 | | * - * ------------------------------------------------------------- * - * |sbase|slimt| | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | * - * ------------------------------------------------------------- * - * | 100 | 104 | 108 | 112 | 116 | 120 | 124 | 128 | 132 | 136 | * - * ------------------------------------------------------------- * - * | F14 | F15 | F16 | F17 | F18 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | * - * ------------------------------------------------------------- * - * | 140 | 144 | 148 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | * - * ------------------------------------------------------------- * - * | F19 | F20 | F21 | F22 | F23 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | * - * ------------------------------------------------------------- * - * | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | * - * ------------------------------------------------------------- * - * | F24 | F25 | F26 | F27 | F28 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | | * - * ------------------------------------------------------------- * - * | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | | * - * ------------------------------------------------------------- * - * | F29 | F30 | F31 | fpscr | | * - * ------------------------------------------------------------- * - * * - * *****************************************************************/ - -.text -.globl jump_fcontext -.align 2 -.type jump_fcontext,@function -jump_fcontext: - stw %r13, 0(%r3) # save R13 - stw %r14, 4(%r3) # save R14 - stw %r15, 8(%r3) # save R15 - stw %r16, 12(%r3) # save R16 - stw %r17, 16(%r3) # save R17 - stw %r18, 20(%r3) # save R18 - stw %r19, 24(%r3) # save R19 - stw %r20, 28(%r3) # save R20 - stw %r21, 32(%r3) # save R21 - stw %r22, 36(%r3) # save R22 - stw %r23, 40(%r3) # save R23 - stw %r24, 44(%r3) # save R24 - stw %r25, 48(%r3) # save R25 - stw %r26, 52(%r3) # save R26 - stw %r27, 56(%r3) # save R27 - stw %r28, 60(%r3) # save R28 - stw %r29, 64(%r3) # save R29 - stw %r30, 68(%r3) # save R30 - stw %r31, 72(%r3) # save R31 - stw %r1, 76(%r3) # save SP - - mfcr %r0 # load CR - stw %r0, 80(%r3) # save CR - mflr %r0 # load LR - stw %r0, 84(%r3) # save LR - stw %r0, 88(%r3) # save LR as PC - - cmpwi cr7, %r6, 0 # test if fpu env should be preserved - beq cr7, 1f - - stfd %f14, 100(%r3) # save F14 - stfd %f15, 108(%r3) # save F15 - stfd %f16, 116(%r3) # save F16 - stfd %f17, 124(%r3) # save F17 - stfd %f18, 132(%r3) # save F18 - stfd %f19, 140(%r3) # save F19 - stfd %f20, 148(%r3) # save F20 - stfd %f21, 156(%r3) # save F21 - stfd %f22, 164(%r3) # save F22 - stfd %f23, 172(%r3) # save F23 - stfd %f24, 180(%r3) # save F24 - stfd %f25, 188(%r3) # save F25 - stfd %f26, 196(%r3) # save F26 - stfd %f27, 204(%r3) # save F27 - stfd %f28, 212(%r3) # save F28 - stfd %f29, 220(%r3) # save F29 - stfd %f30, 228(%r3) # save F30 - stfd %f31, 236(%r3) # save F31 - mffs %f0 # load FPSCR - stfd %f0, 244(%r3) # save FPSCR - - lfd %f14, 100(%r4) # restore F14 - lfd %f15, 108(%r4) # restore F15 - lfd %f16, 116(%r4) # restore F16 - lfd %f17, 124(%r4) # restore F17 - lfd %f18, 132(%r4) # restore F18 - lfd %f19, 140(%r4) # restore F19 - lfd %f20, 148(%r4) # restore F20 - lfd %f21, 156(%r4) # restore F21 - lfd %f22, 164(%r4) # restore F22 - lfd %f23, 172(%r4) # restore F23 - lfd %f24, 180(%r4) # restore F24 - lfd %f25, 188(%r4) # restore F25 - lfd %f26, 196(%r4) # restore F26 - lfd %f27, 204(%r4) # restore F27 - lfd %f28, 212(%r4) # restore F28 - lfd %f29, 220(%r4) # restore F29 - lfd %f30, 228(%r4) # restore F30 - lfd %f31, 236(%r4) # restore F31 - lfd %f0, 244(%r4) # load FPSCR - mtfsf 0xff, %f0 # restore FPSCR -1: - - lwz %r13, 0(%r4) # restore R13 - lwz %r14, 4(%r4) # restore R14 - lwz %r15, 8(%r4) # restore R15 - lwz %r16, 12(%r4) # restore R16 - lwz %r17, 16(%r4) # restore R17 - lwz %r18, 20(%r4) # restore R18 - lwz %r19, 24(%r4) # restore R19 - lwz %r20, 28(%r4) # restore R20 - lwz %r21, 32(%r4) # restore R21 - lwz %r22, 36(%r4) # restore R22 - lwz %r23, 40(%r4) # restore R23 - lwz %r24, 44(%r4) # restore R24 - lwz %r25, 48(%r4) # restore R25 - lwz %r26, 52(%r4) # restore R26 - lwz %r27, 56(%r4) # restore R27 - lwz %r28, 60(%r4) # restore R28 - lwz %r29, 64(%r4) # restore R29 - lwz %r30, 68(%r4) # restore R30 - lwz %r31, 72(%r4) # restore R31 - lwz %r1, 76(%r4) # restore SP - - lwz %r0, 80(%r4) # load CR - mtcr %r0 # restore CR - lwz %r0, 84(%r4) # load LR - mtlr %r0 # restore LR - - mr. %r3, %r5 # use third arg as return value after jump - # and as first arg in context function - - lwz %r0, 88(%r4) # load PC - mtctr %r0 # restore CTR - - bctr # jump to context -.size jump_fcontext, .-jump_fcontext - -.text -.globl make_fcontext -.align 2 -.type make_fcontext,@function -make_fcontext: - stw %r3, 0(%r3) # save the current context - stw %r4, 88(%r3) # save the address of the context function - lwz %r0, 92(%r3) # load the stack base - - li %r4, 28 - subf %r1, %r4, %r1 # reserve space on stack - stw %r3, 24(%r1) # store pointer to fcontext_t on stack - mflr %r4 # load LR - stw %r4, 20(%r1) # store LR on stack - mr. %r3, %r0 # context stack as arg to align_stack - bl align_stack@plt # call align_stack - mr. %r0, %r3 # load result into R0 - lwz %r4, 20(%r1) # pop LR from stack - mtlr %r4 # restore LR - lwz %r3, 24(%r1) # pop pointer to fcontext_t from stack - addi %r1, %r1, 28 # release space on stack - - li %r4, 32 - subf %r0, %r4, %r0 # 32 bytes on stack for parameter area(== 8 registers) - stw %r0, 76(%r3) # save the aligned stack base - - mflr %r0 # load LR - bl 1f # jump to label 1 -1: - mflr %r4 # load LR - addi %r4, %r4, finish - 1b # address of finish; called after context function returns - mtlr %r0 # restore LR - stw %r4, 84(%r3) - - li %r3, 0 - blr - -finish: - li %r3, 0 # exit code is zero - bl _exit@plt # exit application -.size make_fcontext, .-make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S deleted file mode 100644 index 0fcb387..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_ppc64_sysv_elf_gas.S +++ /dev/null @@ -1,250 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/******************************************************************* - * * - * ------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | * - * ------------------------------------------------------------- * - * | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | * - * ------------------------------------------------------------- * - * | R13 | R14 | R15 | R16 | R17 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | * - * ------------------------------------------------------------- * - * | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | * - * ------------------------------------------------------------- * - * | R18 | R19 | R20 | R21 | R22 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | * - * ------------------------------------------------------------- * - * | 80 | 84 | 88 | 92 | 96 | 100 | 104 | 108 | 112 | 116 | * - * ------------------------------------------------------------- * - * | R23 | R24 | R25 | R26 | R27 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * - * ------------------------------------------------------------- * - * | 120 | 124 | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | * - * ------------------------------------------------------------- * - * | R28 | R29 | R30 | R31 | SP | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 40 | 41 | 42 | 43 | 44 | 45 | | * - * ------------------------------------------------------------- * - * | 160 | 164 | 168 | 172 | 176 | 180 | | * - * ------------------------------------------------------------- * - * | CR | LR | PC | | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 46 | 47 | 48 | 49 | | * - * ------------------------------------------------------------- * - * | 184 | 188 | 192 | 196 | | * - * ------------------------------------------------------------- * - * | sbase | slimt | | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | * - * ------------------------------------------------------------- * - * | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | * - * ------------------------------------------------------------- * - * | F14 | F15 | F16 | F17 | F18 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | * - * ------------------------------------------------------------- * - * | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 276 | * - * ------------------------------------------------------------- * - * | F19 | F20 | F21 | F22 | F23 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | * - * ------------------------------------------------------------- * - * | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 308 | 312 | 316 | * - * ------------------------------------------------------------- * - * | F24 | F25 | F26 | F27 | F28 | * - * ------------------------------------------------------------- * - * ------------------------------------------------------------- * - * | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | | * - * ------------------------------------------------------------- * - * | 320 | 324 | 328 | 332 | 336 | 340 | 344 | 348 | | * - * ------------------------------------------------------------- * - * | F29 | F30 | F31 | fpscr | | * - * ------------------------------------------------------------- * - * * - * *****************************************************************/ - -.section ".text" -.align 2 -.globl jump_fcontext -.section ".opd","aw" -.align 3 -jump_fcontext: -.quad .jump_fcontext,.TOC.@tocbase,0 -.previous -.size jump_fcontext,24 -.type .jump_fcontext,@function -.globl .jump_fcontext -.jump_fcontext: - std %r13, 0(%r3) # save R13 - std %r14, 8(%r3) # save R14 - std %r15, 16(%r3) # save R15 - std %r16, 24(%r3) # save R16 - std %r17, 32(%r3) # save R17 - std %r18, 40(%r3) # save R18 - std %r19, 48(%r3) # save R19 - std %r20, 56(%r3) # save R20 - std %r21, 64(%r3) # save R21 - std %r22, 72(%r3) # save R22 - std %r23, 80(%r3) # save R23 - std %r24, 88(%r3) # save R24 - std %r25, 96(%r3) # save R25 - std %r26, 104(%r3) # save R26 - std %r27, 112(%r3) # save R27 - std %r28, 120(%r3) # save R28 - std %r29, 128(%r3) # save R29 - std %r30, 136(%r3) # save R30 - std %r31, 144(%r3) # save R31 - std %r1, 152(%r3) # save SP - - mfcr %r0 # load CR - std %r0, 160(%r3) # save CR - mflr %r0 # load LR - std %r0, 168(%r3) # save LR - std %r0, 176(%r3) # save LR as PC - - cmpwi cr7, %r6, 0 # test if fpu env should be preserved - beq cr7, 1f - - stfd %f14, 200(%r3) # save F14 - stfd %f15, 208(%r3) # save F15 - stfd %f16, 216(%r3) # save F16 - stfd %f17, 224(%r3) # save F17 - stfd %f18, 232(%r3) # save F18 - stfd %f19, 240(%r3) # save F19 - stfd %f20, 248(%r3) # save F20 - stfd %f21, 256(%r3) # save F21 - stfd %f22, 264(%r3) # save F22 - stfd %f23, 272(%r3) # save F23 - stfd %f24, 280(%r3) # save F24 - stfd %f25, 288(%r3) # save F25 - stfd %f26, 296(%r3) # save F26 - stfd %f27, 304(%r3) # save F27 - stfd %f28, 312(%r3) # save F28 - stfd %f29, 320(%r3) # save F29 - stfd %f30, 328(%r3) # save F30 - stfd %f31, 336(%r3) # save F31 - mffs %f0 # load FPSCR - stfd %f0, 344(%r3) # save FPSCR - - lfd %f14, 200(%r4) # restore F14 - lfd %f15, 208(%r4) # restore F15 - lfd %f16, 216(%r4) # restore F16 - lfd %f17, 224(%r4) # restore F17 - lfd %f18, 232(%r4) # restore F18 - lfd %f19, 240(%r4) # restore F19 - lfd %f20, 248(%r4) # restore F20 - lfd %f21, 256(%r4) # restore F21 - lfd %f22, 264(%r4) # restore F22 - lfd %f23, 272(%r4) # restore F23 - lfd %f24, 280(%r4) # restore F24 - lfd %f25, 288(%r4) # restore F25 - lfd %f26, 296(%r4) # restore F26 - lfd %f27, 304(%r4) # restore F27 - lfd %f28, 312(%r4) # restore F28 - lfd %f29, 320(%r4) # restore F29 - lfd %f30, 328(%r4) # restore F30 - lfd %f31, 336(%r4) # restore F31 - lfd %f0, 344(%r4) # load FPSCR - mtfsf 0xff, %f0 # restore FPSCR -1: - - ld %r13, 0(%r4) # restore R13 - ld %r14, 8(%r4) # restore R14 - ld %r15, 16(%r4) # restore R15 - ld %r16, 24(%r4) # restore R16 - ld %r17, 32(%r4) # restore R17 - ld %r18, 40(%r4) # restore R18 - ld %r19, 48(%r4) # restore R19 - ld %r20, 56(%r4) # restore R20 - ld %r21, 64(%r4) # restore R21 - ld %r22, 72(%r4) # restore R22 - ld %r23, 80(%r4) # restore R23 - ld %r24, 88(%r4) # restore R24 - ld %r25, 96(%r4) # restore R25 - ld %r26, 104(%r4) # restore R26 - ld %r27, 112(%r4) # restore R27 - ld %r28, 120(%r4) # restore R28 - ld %r29, 128(%r4) # restore R29 - ld %r30, 136(%r4) # restore r30 - ld %r31, 144(%r4) # restore r31 - ld %r1, 152(%r4) # restore SP - - ld %r0, 160(%r4) # load CR - mtcr %r0 # restore CR - ld %r0, 168(%r4) # load LR - mtlr %r0 # restore LR - - mr. %r3, %r5 # use third arg as return value after jump - # and as first arg in context function - - ld %r0, 176(%r4) # load PC - mtctr %r0 # restore CTR - - bctr # jump to context -.size .jump_fcontext, .-.jump_fcontext - -.section ".text" -.align 2 -.globl make_fcontext -.section ".opd","aw" -.align 3 -make_fcontext: -.quad .make_fcontext,.TOC.@tocbase,0 -.previous -.size make_fcontext,24 -.type .make_fcontext,@function -.globl .make_fcontext -.make_fcontext: - std %r3, 0(%r3) # save the current context - std %r4, 176(%r3) # save the address of the function supposed to be run - ld %r0, 184(%r3) # load the stack base - - li %r4, 56 - subf %r1, %r4, %r1 # reserve space on stack - stw %r3, 48(%r1) # store pointer to fcontext_t on stack - mflr %r4 # load LR - stw %r4, 40(%r1) # store LR on stack - mr. %r3, %r0 # context stack as arg to align_stack - bl align_stack@plt # call align_stack - mr. %r0, %r3 # load result into R0 - lwz %r4, 40(%r1) # pop LR from stack - mtlr %r4 # restore LR - lwz %r3, 48(%r1) # pop pointer to fcontext_t from stack - addi %r1, %r1, 56 # release space on stack - - li %r4, 64 - subf %r0, %r4, %r0 # 64 bytes on stack for parameter area (== 8 registers) - std %r0, 152(%r3) # save the stack base - - mflr %r0 # load LR - bl 1f # jump to label 1 -1: - mflr %r4 # load LR - addi %r4, %r4, finish - 1b # calulate absolute address of finish - mtlr %r0 # restore LR - std %r4, 168(%r3) # save address of finish - - li %r3, 0 # set return value to zero - blr - -finish: - li %r3, 0 # set return value to zero - bl _exit@plt # exit application -.size .make_fcontext, .-.make_fcontext diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm deleted file mode 100644 index f1f8ca1..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_ms_pe_masm.asm +++ /dev/null @@ -1,207 +0,0 @@ - -; Copyright Oliver Kowalke 2009. -; Distributed under the Boost Software License, Version 1.0. -; (See accompanying file LICENSE_1_0.txt or copy at -; http://www.boost.org/LICENSE_1_0.txt) - -; ---------------------------------------------------------------------------------- -; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | -; ---------------------------------------------------------------------------------- -; | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | -; ---------------------------------------------------------------------------------- -; | R12 | R13 | R14 | R15 | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -; ---------------------------------------------------------------------------------- -; | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | -; ---------------------------------------------------------------------------------- -; | RDI | RSI | RBX | RBP | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 16 | 17 | 18 | 19 | | -; ---------------------------------------------------------------------------------- -; | 0x40 | 0x44 | 0x48 | 0x4c | | -; ---------------------------------------------------------------------------------- -; | RSP | RIP | | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 20 | 21 | 22 | 23 | | -; ---------------------------------------------------------------------------------- -; | 0x50 | 0x54 | 0x58 | 0x5c | | -; ---------------------------------------------------------------------------------- -; | sbase | slimit | | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 24 | 25 | | -; ---------------------------------------------------------------------------------- -; | 0x60 | 0x64 | | -; ---------------------------------------------------------------------------------- -; | fbr_strg | | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 26 | 27 | 28 | 29 | | -; ---------------------------------------------------------------------------------- -; | 0x68 | 0x6c | 0x70 | 0x74 | | -; ---------------------------------------------------------------------------------- -; | fc_mxcsr|fc_x87_cw| fc_xmm | | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -; ---------------------------------------------------------------------------------- -; | 0x78 | 0x7c | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 | -; ---------------------------------------------------------------------------------- -; | XMM6 | XMM7 | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -; ---------------------------------------------------------------------------------- -; | 0x98 | 0x9c | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 | -; ---------------------------------------------------------------------------------- -; | XMM8 | XMM9 | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -; ---------------------------------------------------------------------------------- -; | 0x118 | 0x11c | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 | -; ---------------------------------------------------------------------------------- -; | XMM10 | XMM11 | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -; ---------------------------------------------------------------------------------- -; | 0x138 | 0x13c | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 | -; ---------------------------------------------------------------------------------- -; | XMM12 | XMM13 | -; ---------------------------------------------------------------------------------- -; ---------------------------------------------------------------------------------- -; | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -; ---------------------------------------------------------------------------------- -; | 0x158 | 0x15c | 0x160 | 0x164 | 0x168 | 0x16c | 0x170 | 0x174 | -; ---------------------------------------------------------------------------------- -; | XMM14 | XMM15 | -; ---------------------------------------------------------------------------------- - -EXTERN _exit:PROC ; standard C library function -EXTERN align_stack:PROC ; stack alignment -EXTERN seh_fcontext:PROC ; exception handler -.code - -jump_fcontext PROC EXPORT FRAME:seh_fcontext - .endprolog - - mov [rcx], r12 ; save R12 - mov [rcx+08h], r13 ; save R13 - mov [rcx+010h], r14 ; save R14 - mov [rcx+018h], r15 ; save R15 - mov [rcx+020h], rdi ; save RDI - mov [rcx+028h], rsi ; save RSI - mov [rcx+030h], rbx ; save RBX - mov [rcx+038h], rbp ; save RBP - - mov r10, gs:[030h] ; load NT_TIB - mov rax, [r10+08h] ; load current stack base - mov [rcx+050h], rax ; save current stack base - mov rax, [r10+010h] ; load current stack limit - mov [rcx+058h], rax ; save current stack limit - mov rax, [r10+018h] ; load fiber local storage - mov [rcx+060h], rax ; save fiber local storage - - test r9, r9 - je nxt - - stmxcsr [rcx+068h] ; save MMX control and status word - fnstcw [rcx+06ch] ; save x87 control word - mov r10, [rcx+070h] ; address of aligned XMM storage - movaps [r10], xmm6 - movaps [r10+010h], xmm7 - movaps [r10+020h], xmm8 - movaps [r10+030h], xmm9 - movaps [r10+040h], xmm10 - movaps [r10+050h], xmm11 - movaps [r10+060h], xmm12 - movaps [r10+070h], xmm13 - movaps [r10+080h], xmm14 - movaps [r10+090h], xmm15 - - ldmxcsr [rdx+068h] ; restore MMX control and status word - fldcw [rdx+06ch] ; restore x87 control word - mov r10, [rdx+070h] ; address of aligned XMM storage - movaps xmm6, [r10] - movaps xmm7, [r10+010h] - movaps xmm8, [r10+020h] - movaps xmm9, [r10+030h] - movaps xmm10, [r10+040h] - movaps xmm11, [r10+050h] - movaps xmm12, [r10+060h] - movaps xmm13, [r10+070h] - movaps xmm14, [r10+080h] - movaps xmm15, [r10+090h] -nxt: - - lea rax, [rsp+08h] ; exclude the return address - mov [rcx+040h], rax ; save as stack pointer - mov rax, [rsp] ; load return address - mov [rcx+048h], rax ; save return address - - mov r12, [rdx] ; restore R12 - mov r13, [rdx+08h] ; restore R13 - mov r14, [rdx+010h] ; restore R14 - mov r15, [rdx+018h] ; restore R15 - mov rdi, [rdx+020h] ; restore RDI - mov rsi, [rdx+028h] ; restore RSI - mov rbx, [rdx+030h] ; restore RBX - mov rbp, [rdx+038h] ; restore RBP - - mov r10, gs:[030h] ; load NT_TIB - mov rax, [rdx+050h] ; load stack base - mov [r10+08h], rax ; restore stack base - mov rax, [rdx+058h] ; load stack limit - mov [r10+010h], rax ; restore stack limit - mov rax, [rdx+060h] ; load fiber local storage - mov [r10+018h], rax ; restore fiber local storage - - mov rsp, [rdx+040h] ; restore RSP - mov r10, [rdx+048h] ; fetch the address to returned to - - mov rax, r8 ; use third arg as return value after jump - mov rcx, r8 ; use third arg as first arg in context function - - jmp r10 ; indirect jump to caller -jump_fcontext ENDP - -make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E - .endprolog ; .xdata for a function's structured exception handling unwind behavior - - mov [rcx], rcx ; store the address of current context - mov [rcx+048h], rdx ; save the address of the function supposed to run - mov rdx, [rcx+050h] ; load the address where the context stack beginns - - push rcx ; save pointer to fcontext_t - sub rsp, 028h ; reserve shadow space for align_stack - mov rcx, rdx ; stack pointer as arg for align_stack - mov [rsp+8], rcx - call align_stack ; align stack - mov rdx, rax ; begin of aligned stack - add rsp, 028h - pop rcx ; restore pointer to fcontext_t - - lea rdx, [rdx-028h] ; reserve 32byte shadow space + return address on stack, (RSP + 8) % 16 == 0 - mov [rcx+040h], rdx ; save the address where the context stack beginns - - stmxcsr [rcx+068h] ; save MMX control and status word - fnstcw [rcx+06ch] ; save x87 control word - - lea rax, finish ; helper code executed after fn() returns - mov [rdx], rax ; store address off the helper function as return address - - xor rax, rax ; set RAX to zero - ret - -finish: - xor rcx, rcx - mov [rsp+08h], rcx - call _exit ; exit application - hlt -make_fcontext ENDP -END diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S deleted file mode 100644 index ad2d42b..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_elf_gas.S +++ /dev/null @@ -1,116 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/**************************************************************************************** - * * - * ---------------------------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * - * ---------------------------------------------------------------------------------- * - * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * - * ---------------------------------------------------------------------------------- * - * | RBX | R12 | R13 | R14 | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * - * ---------------------------------------------------------------------------------- * - * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * - * ---------------------------------------------------------------------------------- * - * | R15 | RBP | RSP | RIP | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 16 | 17 | 18 | 19 | | * - * ---------------------------------------------------------------------------------- * - * | 0x40 | 0x44 | 0x48 | 0x4c | | * - * ---------------------------------------------------------------------------------- * - * | sbase | slimit | | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 20 | 21 | | * - * ---------------------------------------------------------------------------------- * - * | 0x50 | 0x54 | | * - * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| | * - * ---------------------------------------------------------------------------------- * - * * - * **************************************************************************************/ - -.text -.globl jump_fcontext -.type jump_fcontext,@function -.align 16 -jump_fcontext: - movq %rbx, (%rdi) /* save RBX */ - movq %r12, 0x8(%rdi) /* save R12 */ - movq %r13, 0x10(%rdi) /* save R13 */ - movq %r14, 0x18(%rdi) /* save R14 */ - movq %r15, 0x20(%rdi) /* save R15 */ - movq %rbp, 0x28(%rdi) /* save RBP */ - - cmp $0, %rcx - je 1f - - stmxcsr 0x50(%rdi) /* save MMX control and status word */ - fnstcw 0x54(%rdi) /* save x87 control word */ - - ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ - fldcw 0x54(%rsi) /* restore x87 control word */ -1: - - leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ - movq %rax, 0x30(%rdi) /* save as stack pointer */ - movq (%rsp), %rax /* save return address */ - movq %rax, 0x38(%rdi) /* save return address as RIP */ - - movq (%rsi), %rbx /* restore RBX */ - movq 0x8(%rsi), %r12 /* restore R12 */ - movq 0x10(%rsi), %r13 /* restore R13 */ - movq 0x18(%rsi), %r14 /* restore R14 */ - movq 0x20(%rsi), %r15 /* restore R15 */ - movq 0x28(%rsi), %rbp /* restore RBP */ - - movq 0x30(%rsi), %rsp /* restore RSP */ - movq 0x38(%rsi), %rcx /* fetch the address to return to */ - - movq %rdx, %rax /* use third arg as return value after jump */ - movq %rdx, %rdi /* use third arg as first arg in context function */ - - jmp *%rcx /* indirect jump to context */ -.size jump_fcontext,.-jump_fcontext - -.text -.globl make_fcontext -.type make_fcontext,@function -.align 16 -make_fcontext: - movq %rdi, (%rdi) /* save the address of passed context */ - movq %rsi, 0x38(%rdi) /* save the address of the context function */ - movq 0x40(%rdi), %rdx /* load the stack base */ - - pushq %rdi /* save pointer to fcontext_t */ - movq %rdx, %rdi /* stack pointer as arg for align_stack */ - call align_stack@PLT /* align stack */ - movq %rax, %rdx /* begin of aligned stack */ - popq %rdi /* restore pointer to fcontext_t */ - - leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) & 15 == 0 */ - movq %rdx, 0x30(%rdi) /* save the algined stack base */ - - stmxcsr 0x50(%rdi) /* save MMX control and status word */ - fnstcw 0x54(%rdi) /* save x87 control word */ - - leaq finish(%rip), %rcx /* address of finish; called after context function returns */ - movq %rcx, (%rdx) - - xorq %rax, %rax - ret - -finish: - xorq %rdi, %rdi /* exit code is zero */ - call _exit@PLT /* exit application */ - hlt -.size make_fcontext,.-make_fcontext - diff --git a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S b/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S deleted file mode 100644 index eea76e4..0000000 --- a/vendor/boost_1.51/libs/context/asm/fcontext_x86_64_sysv_macho_gas.S +++ /dev/null @@ -1,111 +0,0 @@ -/* - Copyright Oliver Kowalke 2009. - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt) -*/ - -/**************************************************************************************** - * * - * ---------------------------------------------------------------------------------- * - * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * - * ---------------------------------------------------------------------------------- * - * | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | * - * ---------------------------------------------------------------------------------- * - * | RBX | R12 | R13 | R14 | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * - * ---------------------------------------------------------------------------------- * - * | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | * - * ---------------------------------------------------------------------------------- * - * | R15 | RBP | RSP | RIP | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 16 | 17 | 18 | 19 | | * - * ---------------------------------------------------------------------------------- * - * | 0x40 | 0x44 | 0x48 | 0x4c | | * - * ---------------------------------------------------------------------------------- * - * | sbase | slimit | | * - * ---------------------------------------------------------------------------------- * - * ---------------------------------------------------------------------------------- * - * | 20 | 21 | | * - * ---------------------------------------------------------------------------------- * - * | 0x50 | 0x54 | | * - * ---------------------------------------------------------------------------------- * - * | fc_mxcsr|fc_x87_cw| | * - * ---------------------------------------------------------------------------------- * - * * - * **************************************************************************************/ - -.text -.globl _jump_fcontext -.align 8 -_jump_fcontext: - movq %rbx, (%rdi) /* save RBX */ - movq %r12, 0x8(%rdi) /* save R12 */ - movq %r13, 0x10(%rdi) /* save R13 */ - movq %r14, 0x18(%rdi) /* save R14 */ - movq %r15, 0x20(%rdi) /* save R15 */ - movq %rbp, 0x28(%rdi) /* save RBP */ - - cmp $0, %rcx - je 1f - - stmxcsr 0x50(%rdi) /* save MMX control and status word */ - fnstcw 0x54(%rdi) /* save x87 control word */ - - ldmxcsr 0x50(%rsi) /* restore MMX control and status word */ - fldcw 0x54(%rsi) /* restore x87 control word */ -1: - - leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */ - movq %rax, 0x30(%rdi) /* save as stack pointer */ - movq (%rsp), %rax /* save return address */ - movq %rax, 0x38(%rdi) /* save return address as RIP */ - - movq (%rsi), %rbx /* restore RBX */ - movq 0x8(%rsi), %r12 /* restore R12 */ - movq 0x10(%rsi), %r13 /* restore R13 */ - movq 0x18(%rsi), %r14 /* restore R14 */ - movq 0x20(%rsi), %r15 /* restore R15 */ - movq 0x28(%rsi), %rbp /* restore RBP */ - - movq 0x30(%rsi), %rsp /* restore RSP */ - movq 0x38(%rsi), %rcx /* fetch the address to return to */ - - movq %rdx, %rax /* use third arg as return value after jump */ - movq %rdx, %rdi /* use third arg as first arg in context function */ - - jmp *%rcx /* indirect jump to context */ - -.text -.globl _make_fcontext -.align 8 -_make_fcontext: - movq %rdi, (%rdi) /* save the address of current context */ - movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */ - movq 0x40(%rdi), %rdx /* load the stack base */ - - pushq %rdi /* save pointer to fcontext_t */ - movq %rdx, %rdi /* stack pointer as arg for align_stack */ - call _align_stack /* align stack */ - movq %rax, %rdx /* begin of aligned stack */ - popq %rdi /* restore pointer to fcontext_t */ - - leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) % 16 == 0 */ - movq %rdx, 0x30(%rdi) /* save the address */ - - stmxcsr 0x50(%rdi) /* save MMX control and status word */ - fnstcw 0x54(%rdi) /* save x87 control word */ - - leaq finish(%rip), %rcx /* helper code executed after context function returns */ - movq %rcx, (%rdx) - - xorq %rax, %rax /* set RAX to zero */ - ret - -finish: - xorq %rdi, %rdi /* exit code is zero */ - call _exit /* exit application */ - hlt diff --git a/vendor/boost_1.51/libs/context/fcontext.cpp b/vendor/boost_1.51/libs/context/fcontext.cpp deleted file mode 100644 index 596cbd8..0000000 --- a/vendor/boost_1.51/libs/context/fcontext.cpp +++ /dev/null @@ -1,36 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace ctx { -namespace detail { - -extern "C" BOOST_CONTEXT_DECL -void * BOOST_CONTEXT_CALLDECL align_stack( void * vp) -{ - void * base = vp; - if ( 0 != ( ( ( uintptr_t) base) & 15) ) - base = ( char * ) ( ( ( ( uintptr_t) base) - 15) & ~0x0F); - return base; -} - -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/vendor/boost_1.51/libs/context/seh.cpp b/vendor/boost_1.51/libs/context/seh.cpp deleted file mode 100644 index 9363805..0000000 --- a/vendor/boost_1.51/libs/context/seh.cpp +++ /dev/null @@ -1,83 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -extern "C" { - -#include -#include - -#include -#include -#include - -#if defined(_MSC_VER) -# define SNPRINTF _snprintf -#else -# define SNPRINTF snprintf -#endif - -static const char * exception_description( - _EXCEPTION_RECORD const* record, char * description, size_t len) -{ - const DWORD code = record->ExceptionCode; - const ULONG_PTR * info = record->ExceptionInformation; - - switch ( code) - { - case EXCEPTION_ACCESS_VIOLATION: - { - const char * accessType = ( info[0]) ? "writing" : "reading"; - const ULONG_PTR address = info[1]; - SNPRINTF( description, len, "Access violation %s %p", accessType, reinterpret_cast< void * >( address) ); - return description; - } - case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype misalignment"; - case EXCEPTION_BREAKPOINT: return "Breakpoint"; - case EXCEPTION_SINGLE_STEP: return "Single step"; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded"; - case EXCEPTION_FLT_DENORMAL_OPERAND: return "FPU denormal operand"; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "FPU divide by zero"; - case EXCEPTION_FLT_INEXACT_RESULT: return "FPU inexact result"; - case EXCEPTION_FLT_INVALID_OPERATION: return "FPU invalid operation"; - case EXCEPTION_FLT_OVERFLOW: return "FPU overflow"; - case EXCEPTION_FLT_STACK_CHECK: return "FPU stack check"; - case EXCEPTION_FLT_UNDERFLOW: return "FPU underflow"; - case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer divide by zero"; - case EXCEPTION_INT_OVERFLOW: return "Integer overflow"; - case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction"; - case EXCEPTION_IN_PAGE_ERROR: return "In page error"; - case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal instruction"; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Noncontinuable exception"; - case EXCEPTION_STACK_OVERFLOW: return "Stack overflow"; - case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition"; - case EXCEPTION_GUARD_PAGE: return "Guard page"; - case EXCEPTION_INVALID_HANDLE: return "Invalid handle"; - } - - SNPRINTF( description, len, "Unknown (0x%08lX)", code); - return description; -} - -EXCEPTION_DISPOSITION seh_fcontext( - struct _EXCEPTION_RECORD * record, - void *, - struct _CONTEXT *, - void *) -{ - char description[255]; - - fprintf( stderr, "exception: %s (%08lX)\n", - exception_description( record, description, sizeof( description) ), - record->ExceptionCode); - - ExitProcess( -1); - - return ExceptionContinueSearch; // never reached -} - -} diff --git a/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp b/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp deleted file mode 100644 index 64291e7..0000000 --- a/vendor/boost_1.51/libs/context/stack_allocator_posix.cpp +++ /dev/null @@ -1,85 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -#include -#include -#include -#include -} - -#include - -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace ctx { - -void * -stack_allocator::allocate( std::size_t size) const -{ - if ( minimum_stacksize() > size) - throw std::invalid_argument( - boost::str( boost::format("invalid stack size: must be at least %d bytes") - % minimum_stacksize() ) ); - - if ( ! is_stack_unbound() && ( maximum_stacksize() < size) ) - throw std::invalid_argument( - boost::str( boost::format("invalid stack size: must not be larger than %d bytes") - % maximum_stacksize() ) ); - - const std::size_t pages( page_count( size) + 1); // add +1 for guard page - std::size_t size_ = pages * pagesize(); - - -# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) - void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -# else - const int fd( ::open("/dev/zero", O_RDONLY) ); - BOOST_ASSERT( -1 != fd); - void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - ::close( fd); -# endif - if ( ! limit) throw std::bad_alloc(); - - const int result( ::mprotect( limit, pagesize(), PROT_NONE) ); - BOOST_ASSERT( 0 == result); - (void)result; // unused in release build - - return static_cast< char * >( limit) + size_; -} - -void -stack_allocator::deallocate( void * vp, std::size_t size) const -{ - if ( vp) - { - const std::size_t pages( page_count( size) + 1); // add +1 for guard page - std::size_t size_ = pages * pagesize(); - BOOST_ASSERT( 0 < size && 0 < size_); - void * limit = static_cast< char * >( vp) - size_; - ::munmap( limit, size_); - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp b/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp deleted file mode 100644 index 518239f..0000000 --- a/vendor/boost_1.51/libs/context/stack_allocator_windows.cpp +++ /dev/null @@ -1,86 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -} - -#include - -#include -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -# if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4244 4267) -# endif - -namespace boost { -namespace ctx { - -void * -stack_allocator::allocate( std::size_t size) const -{ - if ( minimum_stacksize() > size) - throw std::invalid_argument( - boost::str( boost::format("invalid stack size: must be at least %d bytes") - % minimum_stacksize() ) ); - - if ( ! is_stack_unbound() && ( maximum_stacksize() < size) ) - throw std::invalid_argument( - boost::str( boost::format("invalid stack size: must not be larger than %d bytes") - % maximum_stacksize() ) ); - - const std::size_t pages( page_count( size) + 1); // add +1 for guard page - std::size_t size_ = pages * pagesize(); - -#ifndef BOOST_CONTEXT_FIBER - void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE); - if ( ! limit) throw std::bad_alloc(); - - DWORD old_options; - const BOOL result = ::VirtualProtect( - limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options); - BOOST_ASSERT( FALSE != result); - - return static_cast< char * >( limit) + size_; -#endif -} - -void -stack_allocator::deallocate( void * vp, std::size_t size) const -{ - if ( vp) - { - const std::size_t pages( page_count( size) + 1); // add +1 for guard page - std::size_t size_ = pages * pagesize(); - BOOST_ASSERT( 0 < size && 0 < size_); - void * limit = static_cast< char * >( vp) - size_; - ::VirtualFree( limit, 0, MEM_RELEASE); - } -} - -}} - -# if defined(BOOST_MSVC) -# pragma warning(pop) -# endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/vendor/boost_1.51/libs/context/stack_utils_posix.cpp b/vendor/boost_1.51/libs/context/stack_utils_posix.cpp deleted file mode 100644 index 13c4e4e..0000000 --- a/vendor/boost_1.51/libs/context/stack_utils_posix.cpp +++ /dev/null @@ -1,81 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -#include -#include -#include -} - -#include - -#include - -namespace { - -static rlimit stacksize_limit_() -{ - rlimit limit; - const int result = ::getrlimit( RLIMIT_STACK, & limit); - BOOST_ASSERT( 0 == result); - (void)result; // unused when in release mode... - return limit; -} - -static rlimit stacksize_limit() -{ - static rlimit limit = stacksize_limit_(); - return limit; -} - -} - -namespace boost { -namespace ctx { - -BOOST_CONTEXT_DECL -std::size_t default_stacksize() -{ - static std::size_t size = 256 * 1024; - return size; -} - -BOOST_CONTEXT_DECL -std::size_t minimum_stacksize() -{ return SIGSTKSZ; } - -BOOST_CONTEXT_DECL -std::size_t maximum_stacksize() -{ - BOOST_ASSERT( ! is_stack_unbound() ); - return static_cast< std::size_t >( stacksize_limit().rlim_max); -} - -BOOST_CONTEXT_DECL -bool is_stack_unbound() -{ return RLIM_INFINITY == stacksize_limit().rlim_max; } - -BOOST_CONTEXT_DECL -std::size_t pagesize() -{ - static std::size_t pagesize( ::getpagesize() ); - return pagesize; -} - -BOOST_CONTEXT_DECL -std::size_t page_count( std::size_t stacksize) -{ - return static_cast< std::size_t >( - std::ceil( - static_cast< float >( stacksize) / pagesize() ) ); -} - -}} diff --git a/vendor/boost_1.51/libs/context/stack_utils_windows.cpp b/vendor/boost_1.51/libs/context/stack_utils_windows.cpp deleted file mode 100644 index 373033d..0000000 --- a/vendor/boost_1.51/libs/context/stack_utils_windows.cpp +++ /dev/null @@ -1,84 +0,0 @@ - -// Copyright Oliver Kowalke 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_CONTEXT_SOURCE - -#include - -extern "C" { -#include -} - -#include -#include - -#include - -namespace { - -static SYSTEM_INFO system_info_() -{ - SYSTEM_INFO si; - ::GetSystemInfo( & si); - return si; -} - -static SYSTEM_INFO system_info() -{ - static SYSTEM_INFO si = system_info_(); - return si; -} - -} - -namespace boost { -namespace ctx { - -BOOST_CONTEXT_DECL -std::size_t default_stacksize() -{ - static std::size_t size = 256 * 1024; - return size; -} - -BOOST_CONTEXT_DECL -std::size_t minimum_stacksize() -{ - static std::size_t stacksize( - static_cast< std::size_t >( system_info().dwAllocationGranularity) ); - return stacksize; -} - -BOOST_CONTEXT_DECL -std::size_t maximum_stacksize() -{ - BOOST_ASSERT( ! is_stack_unbound() ); - static std::size_t stacksize = 8 * 1024 * 1024; - return stacksize; -} - -// Windows seams not to provide a limit for the stacksize -BOOST_CONTEXT_DECL -bool is_stack_unbound() -{ return true; } - -BOOST_CONTEXT_DECL -std::size_t pagesize() -{ - static std::size_t pagesize( - static_cast< std::size_t >( system_info().dwPageSize) ); - return pagesize; -} - -BOOST_CONTEXT_DECL -std::size_t page_count( std::size_t stacksize) -{ - return static_cast< std::size_t >( - std::ceil( - static_cast< float >( stacksize) / pagesize() ) ); -} - -}} diff --git a/vendor/cyoencode-1.0.2/LICENSE.TXT b/vendor/cyoencode-1.0.2/LICENSE.TXT deleted file mode 100644 index 4e10e73..0000000 --- a/vendor/cyoencode-1.0.2/LICENSE.TXT +++ /dev/null @@ -1,27 +0,0 @@ -All the files in this library are covered under the terms of the Berkeley -Software Distribution (BSD) License: - -Copyright (c) 2009-2012, Graham Bull. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/vendor/cyoencode-1.0.2/README.TXT b/vendor/cyoencode-1.0.2/README.TXT deleted file mode 100644 index 30df17d..0000000 --- a/vendor/cyoencode-1.0.2/README.TXT +++ /dev/null @@ -1,50 +0,0 @@ -=============================================================================== -CyoEncode -http://cyoencode.sourceforge.net/ - -Copyright (c) 2009-2012, Graham Bull. All rights reserved. -=============================================================================== - -Version 1.0.2 -Release Date 5th January 2012 - -------------------------------------------------------------------------------- -1. License -------------------------------------------------------------------------------- - -CyoEncode is made available under the terms of the Berkeley Software -Distribution (BSD) licence, as detailed in LICENSE.TXT. This allows you -complete freedom to use and distribute the code in source and/or binary form, -as long as you respect the original copyright. - -------------------------------------------------------------------------------- -2. Instructions -------------------------------------------------------------------------------- - -Simply copy the required source files (CyoEncode.h/cpp and CyoDecode.h/cpp) -into your C/C++ project. - -Examples of usage can be found in the test.c file. - -For Unix/Linux developers, there's a shell script that will build the test -using GCC. - -For Windows developers, Visual Studio projects are included. - -------------------------------------------------------------------------------- -3. Release Notes -------------------------------------------------------------------------------- - -1.0.2 - 5th January 2012 -- A little refactoring, added some shared functions. -- Added VS42010 project file. -- Added x64 build configurations. - -1.0.1 - 25th September 2009 -- Added the cyoBase??Validate() functions. -- Added detection of invalid encodings in the cyoBase??Decode() functions, - rather than relying on assertions. - -1.0.0 - 19th August 2009 -- First release. - diff --git a/vendor/cyoencode-1.0.2/src/CyoDecode.c b/vendor/cyoencode-1.0.2/src/CyoDecode.c deleted file mode 100644 index d40e3a8..0000000 --- a/vendor/cyoencode-1.0.2/src/CyoDecode.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * CyoDecode.c - part of the CyoEncode library - * - * Copyright (c) 2009-2012, Graham Bull. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "CyoDecode.h" - -#include - -#include //TEMP - -/********************************** Shared ***********************************/ - -static int cyoBaseXXValidate( const char* src, size_t size, size_t inputBytes, size_t maxPadding, - unsigned char maxValue, const unsigned char table[] ) -{ - /* - * returns 0 if the source is a valid baseXX encoding - */ - - if (!src) - return -1; /*ERROR - NULL pointer*/ - - if (size % inputBytes != 0) - return -1; /*ERROR - extra characters*/ - - /* check the bytes */ - for (; size >= 1; --size, ++src) - { - unsigned char ch = *src; - if ((ch >= 0x80) || (table[ ch ] > maxValue)) - break; - } - - /* check any padding */ - for (; 1 <= size && size <= maxPadding; --size, ++src) - { - unsigned char ch = *src; - if ((ch >= 0x80) || (table[ ch ] != maxValue + 1)) - break; - } - - /* if size isn't zero then the encoded string isn't valid */ - if (size != 0) - return -2; /*ERROR - invalid baseXX character*/ - - /* OK */ - return 0; -} - -static size_t cyoBaseXXDecodeGetLength( size_t size, size_t inputBytes, size_t outputBytes ) -{ - if (size % inputBytes != 0) - return 0; /*ERROR - extra characters*/ - - /* OK */ - return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/ -} - -/****************************** Base16 Decoding ******************************/ - -static const size_t BASE16_INPUT = 2; -static const size_t BASE16_OUTPUT = 1; -static const size_t BASE16_MAX_PADDING = 0; -static const unsigned char BASE16_MAX_VALUE = 15; -static const unsigned char BASE16_TABLE[ 0x80 ] = { - /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*30-37*/ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /*8 = '0'-'7'*/ - /*38-3f*/ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*2 = '8'-'9'*/ - /*40-47*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'A'-'F'*/ - /*48-4f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*50-57*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*58-5f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*60-67*/ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, /*6 = 'a'-'f' (same as 'A'-'F')*/ - /*68-6f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*70-77*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*78-7f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -int cyoBase16Validate( const char* src, size_t size ) -{ - return cyoBaseXXValidate( src, size, BASE16_INPUT, BASE16_MAX_PADDING, BASE16_MAX_VALUE, BASE16_TABLE ); -} - -size_t cyoBase16DecodeGetLength( size_t size ) -{ - return cyoBaseXXDecodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT ); -} - -size_t cyoBase16Decode( void* dest, const char* src, size_t size ) -{ - /* - * output 1 byte for every 2 input: - * - * outputs: 1 - * inputs: 1 = ----1111 = 1111---- - * 2 = ----2222 = ----2222 - */ - - if (dest && src && (size % BASE16_INPUT == 0)) - { - unsigned char* pDest = (unsigned char*)dest; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - unsigned char in1, in2; - - while (dwSrcSize >= 1) - { - /* 2 inputs */ - in1 = *src++; - in2 = *src++; - dwSrcSize -= BASE16_INPUT; - - /* Validate ascii */ - if (in1 >= 0x80 || in2 >= 0x80) - return 0; /*ERROR - invalid base16 character*/ - - /* Convert ascii to base16 */ - in1 = BASE16_TABLE[ in1 ]; - in2 = BASE16_TABLE[ in2 ]; - - /* Validate base16 */ - if (in1 > BASE16_MAX_VALUE || in2 > BASE16_MAX_VALUE) - return 0; /*ERROR - invalid base16 character*/ - - /* 1 output */ - *pDest++ = ((in1 << 4) | in2); - dwDestSize += BASE16_OUTPUT; - } - *pDest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer, or size isn't a multiple of 2*/ -} - -/****************************** Base32 Decoding ******************************/ - -static const size_t BASE32_INPUT = 8; -static const size_t BASE32_OUTPUT = 5; -static const size_t BASE32_MAX_PADDING = 6; -static const unsigned char BASE32_MAX_VALUE = 31; -static const unsigned char BASE32_TABLE[ 0x80 ] = { - /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*28-2f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*30-37*/ 0xFF, 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /*6 = '2'-'7'*/ - /*38-3f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0xFF, 0xFF, /*1 = '='*/ - /*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/ - /*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/ - /*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/ - /*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/ - /*60-67*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'a'-'g' (same as 'A'-'G')*/ - /*68-6f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'h'-'o' (same as 'H'-'O')*/ - /*70-77*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'p'-'w' (same as 'P'-'W')*/ - /*78-7f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z' (same as 'X'-'Z')*/ -}; - -int cyoBase32Validate( const char* src, size_t size ) -{ - return cyoBaseXXValidate( src, size, BASE32_INPUT, BASE32_MAX_PADDING, BASE32_MAX_VALUE, BASE32_TABLE ); -} - -size_t cyoBase32DecodeGetLength( size_t size ) -{ - return cyoBaseXXDecodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT ); -} - -size_t cyoBase32Decode( void* dest, const char* src, size_t size ) -{ - /* - * output 5 bytes for every 8 input: - * - * outputs: 1 2 3 4 5 - * inputs: 1 = ---11111 = 11111--- - * 2 = ---222XX = -----222 XX------ - * 3 = ---33333 = --33333- - * 4 = ---4XXXX = -------4 XXXX---- - * 5 = ---5555X = ----5555 X------- - * 6 = ---66666 = -66666-- - * 7 = ---77XXX = ------77 XXX----- - * 8 = ---88888 = ---88888 - */ - - if (dest && src && (size % BASE32_INPUT == 0)) - { - unsigned char* pDest = (unsigned char*)dest; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - unsigned char in1, in2, in3, in4, in5, in6, in7, in8; - - while (dwSrcSize >= 1) - { - /* 8 inputs */ - in1 = *src++; - in2 = *src++; - in3 = *src++; - in4 = *src++; - in5 = *src++; - in6 = *src++; - in7 = *src++; - in8 = *src++; - dwSrcSize -= BASE32_INPUT; - - /* Validate ascii */ - if ( in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80 - || in5 >= 0x80 || in6 >= 0x80 || in7 >= 0x80 || in8 >= 0x80) - return 0; /*ERROR - invalid base32 character*/ - - /* Convert ascii to base16 */ - in1 = BASE32_TABLE[ in1 ]; - in2 = BASE32_TABLE[ in2 ]; - in3 = BASE32_TABLE[ in3 ]; - in4 = BASE32_TABLE[ in4 ]; - in5 = BASE32_TABLE[ in5 ]; - in6 = BASE32_TABLE[ in6 ]; - in7 = BASE32_TABLE[ in7 ]; - in8 = BASE32_TABLE[ in8 ]; - - /* Validate base32 */ - if (in1 > BASE32_MAX_VALUE || in2 > BASE32_MAX_VALUE) - return 0; /*ERROR - invalid base32 character*/ - /*the following can be padding*/ - if ( in3 > BASE32_MAX_VALUE + 1 || in4 > BASE32_MAX_VALUE + 1 || in5 > BASE32_MAX_VALUE + 1 - || in6 > BASE32_MAX_VALUE + 1 || in7 > BASE32_MAX_VALUE + 1 || in8 > BASE32_MAX_VALUE + 1) - return 0; /*ERROR - invalid base32 character*/ - - /* 5 outputs */ - *pDest++ = ((in1 & 0x1f) << 3) | ((in2 & 0x1c) >> 2); - *pDest++ = ((in2 & 0x03) << 6) | ((in3 & 0x1f) << 1) | ((in4 & 0x10) >> 4); - *pDest++ = ((in4 & 0x0f) << 4) | ((in5 & 0x1e) >> 1); - *pDest++ = ((in5 & 0x01) << 7) | ((in6 & 0x1f) << 2) | ((in7 & 0x18) >> 3); - *pDest++ = ((in7 & 0x07) << 5) | (in8 & 0x1f); - dwDestSize += BASE32_OUTPUT; - - /* Padding */ - if (in8 == BASE32_MAX_VALUE + 1) - { - --dwDestSize; - assert( (in7 == BASE32_MAX_VALUE + 1 && in6 == BASE32_MAX_VALUE + 1) || (in7 != BASE32_MAX_VALUE + 1) ); - if (in6 == BASE32_MAX_VALUE + 1) - { - --dwDestSize; - if (in5 == BASE32_MAX_VALUE + 1) - { - --dwDestSize; - assert( (in4 == BASE32_MAX_VALUE + 1 && in3 == BASE32_MAX_VALUE + 1) || (in4 != BASE32_MAX_VALUE + 1) ); - if (in3 == BASE32_MAX_VALUE + 1) - { - --dwDestSize; - } - } - } - } - } - *pDest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer, or size isn't a multiple of 8*/ -} - -/****************************** Base64 Decoding ******************************/ - -static const size_t BASE64_INPUT = 4; -static const size_t BASE64_OUTPUT = 3; -static const size_t BASE64_MAX_PADDING = 2; -static const unsigned char BASE64_MAX_VALUE = 63; -static const unsigned char BASE64_TABLE[ 0x80 ] = { - /*00-07*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*08-0f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*10-17*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*18-1f*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*20-27*/ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /*28-2f*/ 0xFF, 0xFF, 0xFF, 0x3e, 0xFF, 0xFF, 0xFF, 0x3f, /*2 = '+' and '/'*/ - /*30-37*/ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, /*8 = '0'-'7'*/ - /*38-3f*/ 0x3c, 0x3d, 0xFF, 0xFF, 0xFF, 0x40, 0xFF, 0xFF, /*2 = '8'-'9' and '='*/ - /*40-47*/ 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /*7 = 'A'-'G'*/ - /*48-4f*/ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, /*8 = 'H'-'O'*/ - /*50-57*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /*8 = 'P'-'W'*/ - /*58-5f*/ 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /*3 = 'X'-'Z'*/ - /*60-67*/ 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, /*7 = 'a'-'g'*/ - /*68-6f*/ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, /*8 = 'h'-'o'*/ - /*70-77*/ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, /*8 = 'p'-'w'*/ - /*78-7f*/ 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /*3 = 'x'-'z'*/ -}; - -int cyoBase64Validate( const char* src, size_t size ) -{ - return cyoBaseXXValidate( src, size, BASE64_INPUT, BASE64_MAX_PADDING, BASE64_MAX_VALUE, BASE64_TABLE ); -} - -size_t cyoBase64DecodeGetLength( size_t size ) -{ - return cyoBaseXXDecodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT ); -} - -size_t cyoBase64Decode( void* dest, const char* src, size_t size ) -{ - /* - * output 3 bytes for every 4 input: - * - * outputs: 1 2 3 - * inputs: 1 = --111111 = 111111-- - * 2 = --22XXXX = ------22 XXXX---- - * 3 = --3333XX = ----3333 XX------ - * 4 = --444444 = --444444 - */ - - if (dest && src && (size % BASE64_INPUT == 0)) - { - unsigned char* pDest = (unsigned char*)dest; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - unsigned char in1, in2, in3, in4; - - while (dwSrcSize >= 1) - { - /* 4 inputs */ - in1 = *src++; - in2 = *src++; - in3 = *src++; - in4 = *src++; - dwSrcSize -= BASE64_INPUT; - - /* Validate ascii */ - if (in1 >= 0x80 || in2 >= 0x80 || in3 >= 0x80 || in4 >= 0x80) - return 0; /*ERROR - invalid base64 character*/ - - /* Convert ascii to base64 */ - in1 = BASE64_TABLE[ in1 ]; - in2 = BASE64_TABLE[ in2 ]; - in3 = BASE64_TABLE[ in3 ]; - in4 = BASE64_TABLE[ in4 ]; - - /* Validate base64 */ - if (in1 > BASE64_MAX_VALUE || in2 > BASE64_MAX_VALUE) - return 0; /*ERROR - invalid base64 character*/ - /*the following can be padding*/ - if (in3 > BASE64_MAX_VALUE + 1 || in4 > BASE64_MAX_VALUE + 1) - return 0; /*ERROR - invalid base64 character*/ - - /* 3 outputs */ - *pDest++ = ((in1 & 0x3f) << 2) | ((in2 & 0x30) >> 4); - *pDest++ = ((in2 & 0x0f) << 4) | ((in3 & 0x3c) >> 2); - *pDest++ = ((in3 & 0x03) << 6) | (in4 & 0x3f); - dwDestSize += BASE64_OUTPUT; - - /* Padding */ - if (in4 == BASE64_MAX_VALUE + 1) - { - --dwDestSize; - if (in3 == BASE64_MAX_VALUE + 1) - { - --dwDestSize; - } - } - } - *pDest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer, or size isn't a multiple of 4*/ -} diff --git a/vendor/cyoencode-1.0.2/src/CyoDecode.h b/vendor/cyoencode-1.0.2/src/CyoDecode.h deleted file mode 100644 index 873ed20..0000000 --- a/vendor/cyoencode-1.0.2/src/CyoDecode.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * CyoDecode.h - part of the CyoEncode library - * - * Copyright (c) 2009-2012, Graham Bull. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __CYODECODE_H -#define __CYODECODE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Base16 Decoding */ -int cyoBase16Validate( const char* src, size_t size ); -size_t cyoBase16DecodeGetLength( size_t size ); -size_t cyoBase16Decode( void* dest, const char* src, size_t size ); - -/* Base32 Decoding */ -int cyoBase32Validate( const char* src, size_t size ); -size_t cyoBase32DecodeGetLength( size_t size ); -size_t cyoBase32Decode( void* dest, const char* src, size_t size ); - -/* Base64 Decoding */ -int cyoBase64Validate( const char* src, size_t size ); -size_t cyoBase64DecodeGetLength( size_t size ); -size_t cyoBase64Decode( void* dest, const char* src, size_t size ); - -#ifdef __cplusplus -} -#endif - -#endif /*__CYODECODE_H*/ - diff --git a/vendor/cyoencode-1.0.2/src/CyoEncode.c b/vendor/cyoencode-1.0.2/src/CyoEncode.c deleted file mode 100644 index 3e9191f..0000000 --- a/vendor/cyoencode-1.0.2/src/CyoEncode.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * CyoEncode.c - part of the CyoEncode library - * - * Copyright (c) 2009-2012, Graham Bull. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "CyoEncode.h" - -#include - -/********************************** Shared ***********************************/ - -static size_t cyoBaseXXEncodeGetLength( size_t size, size_t inputBytes, size_t outputBytes ) -{ - return (((size + inputBytes - 1) / inputBytes) * outputBytes) + 1; /*plus terminator*/ -} - -/****************************** Base16 Encoding ******************************/ - -static const size_t BASE16_INPUT = 1; -static const size_t BASE16_OUTPUT = 2; -static const char* const BASE16_TABLE = "0123456789ABCDEF"; - -size_t cyoBase16EncodeGetLength( size_t size ) -{ - return cyoBaseXXEncodeGetLength( size, BASE16_INPUT, BASE16_OUTPUT ); -} - -size_t cyoBase16Encode( char* dest, const void* src, size_t size ) -{ - /* - * output 2 bytes for every 1 input: - * - * inputs: 1 - * outputs: 1 = ----1111 = 1111---- - * 2 = ----2222 = ----2222 - */ - - if (dest && src) - { - unsigned char* pSrc = (unsigned char*)src; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - unsigned char ch; - - while (dwSrcSize >= 1) - { - /* 1 input */ - ch = *pSrc++; - dwSrcSize -= BASE16_INPUT; - - /* 2 outputs */ - *dest++ = BASE16_TABLE[ (ch & 0xf0) >> 4 ]; - *dest++ = BASE16_TABLE[ (ch & 0x0f) ]; - dwDestSize += BASE16_OUTPUT; - } - *dest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer*/ -} - -/****************************** Base32 Encoding ******************************/ - -static const size_t BASE32_INPUT = 5; -static const size_t BASE32_OUTPUT = 8; -static const char* const BASE32_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; - -size_t cyoBase32EncodeGetLength( size_t size ) -{ - return cyoBaseXXEncodeGetLength( size, BASE32_INPUT, BASE32_OUTPUT ); -} - -size_t cyoBase32Encode( char* dest, const void* src, size_t size ) -{ - /* - * output 8 bytes for every 5 input: - * - * inputs: 1 2 3 4 5 - * outputs: 1 = ---11111 = 11111--- - * 2 = ---222XX = -----222 XX------ - * 3 = ---33333 = --33333- - * 4 = ---4XXXX = -------4 XXXX---- - * 5 = ---5555X = ----5555 X------- - * 6 = ---66666 = -66666-- - * 7 = ---77XXX = ------77 XXX----- - * 8 = ---88888 = ---88888 - */ - - if (dest && src) - { - unsigned char* pSrc = (unsigned char*)src; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - size_t dwBlockSize; - unsigned char n1, n2, n3, n4, n5, n6, n7, n8; - - while (dwSrcSize >= 1) - { - /* Encode inputs */ - dwBlockSize = (dwSrcSize < BASE32_INPUT ? dwSrcSize : BASE32_INPUT); - n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = 0; - switch (dwBlockSize) - { - case 5: - n8 = (pSrc[ 4 ] & 0x1f); - n7 = ((pSrc[ 4 ] & 0xe0) >> 5); - case 4: - n7 |= ((pSrc[ 3 ] & 0x03) << 3); - n6 = ((pSrc[ 3 ] & 0x7c) >> 2); - n5 = ((pSrc[ 3 ] & 0x80) >> 7); - case 3: - n5 |= ((pSrc[ 2 ] & 0x0f) << 1); - n4 = ((pSrc[ 2 ] & 0xf0) >> 4); - case 2: - n4 |= ((pSrc[ 1 ] & 0x01) << 4); - n3 = ((pSrc[ 1 ] & 0x3e) >> 1); - n2 = ((pSrc[ 1 ] & 0xc0) >> 6); - case 1: - n2 |= ((pSrc[ 0 ] & 0x07) << 2); - n1 = ((pSrc[ 0 ] & 0xf8) >> 3); - break; - - default: - assert( 0 ); - } - pSrc += dwBlockSize; - dwSrcSize -= dwBlockSize; - - /* Validate */ - assert( n1 <= 31 ); - assert( n2 <= 31 ); - assert( n3 <= 31 ); - assert( n4 <= 31 ); - assert( n5 <= 31 ); - assert( n6 <= 31 ); - assert( n7 <= 31 ); - assert( n8 <= 31 ); - - /* Padding */ - switch (dwBlockSize) - { - case 1: n3 = n4 = 32; - case 2: n5 = 32; - case 3: n6 = n7 = 32; - case 4: n8 = 32; - case 5: - break; - - default: - assert( 0 ); - } - - /* 8 outputs */ - *dest++ = BASE32_TABLE[ n1 ]; - *dest++ = BASE32_TABLE[ n2 ]; - *dest++ = BASE32_TABLE[ n3 ]; - *dest++ = BASE32_TABLE[ n4 ]; - *dest++ = BASE32_TABLE[ n5 ]; - *dest++ = BASE32_TABLE[ n6 ]; - *dest++ = BASE32_TABLE[ n7 ]; - *dest++ = BASE32_TABLE[ n8 ]; - dwDestSize += BASE32_OUTPUT; - } - *dest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer*/ -} - -/****************************** Base64 Encoding ******************************/ - -static const size_t BASE64_INPUT = 3; -static const size_t BASE64_OUTPUT = 4; -static const char* const BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - -size_t cyoBase64EncodeGetLength( size_t size ) -{ - return cyoBaseXXEncodeGetLength( size, BASE64_INPUT, BASE64_OUTPUT ); -} - -size_t cyoBase64Encode( char* dest, const void* src, size_t size ) -{ - /* - * output 4 bytes for every 3 input: - * - * inputs: 1 2 3 - * outputs: 1 = --111111 = 111111-- - * 2 = --22XXXX = ------22 XXXX---- - * 3 = --3333XX = ----3333 XX------ - * 4 = --444444 = --444444 - */ - - if (dest && src) - { - unsigned char* pSrc = (unsigned char*)src; - size_t dwSrcSize = size; - size_t dwDestSize = 0; - size_t dwBlockSize = 0; - unsigned char n1, n2, n3, n4; - - while (dwSrcSize >= 1) - { - /* Encode inputs */ - dwBlockSize = (dwSrcSize < BASE64_INPUT ? dwSrcSize : BASE64_INPUT); - n1 = n2 = n3 = n4 = 0; - switch (dwBlockSize) - { - case 3: - n4 = (pSrc[ 2 ] & 0x3f); - n3 = ((pSrc[ 2 ] & 0xc0) >> 6); - case 2: - n3 |= ((pSrc[ 1 ] & 0x0f) << 2); - n2 = ((pSrc[ 1 ] & 0xf0) >> 4); - case 1: - n2 |= ((pSrc[ 0 ] & 0x03) << 4); - n1 = ((pSrc[ 0 ] & 0xfc) >> 2); - break; - - default: - assert( 0 ); - } - pSrc += dwBlockSize; - dwSrcSize -= dwBlockSize; - - /* Validate */ - assert( n1 <= 63 ); - assert( n2 <= 63 ); - assert( n3 <= 63 ); - assert( n4 <= 63 ); - - /* Padding */ - switch (dwBlockSize) - { - case 1: n3 = 64; - case 2: n4 = 64; - case 3: - break; - - default: - assert( 0 ); - } - - /* 4 outputs */ - *dest++ = BASE64_TABLE[ n1 ]; - *dest++ = BASE64_TABLE[ n2 ]; - *dest++ = BASE64_TABLE[ n3 ]; - *dest++ = BASE64_TABLE[ n4 ]; - dwDestSize += BASE64_OUTPUT; - } - *dest++ = '\x0'; /*append terminator*/ - - return dwDestSize; - } - else - return 0; /*ERROR - null pointer*/ -} diff --git a/vendor/cyoencode-1.0.2/src/CyoEncode.h b/vendor/cyoencode-1.0.2/src/CyoEncode.h deleted file mode 100644 index 183a66e..0000000 --- a/vendor/cyoencode-1.0.2/src/CyoEncode.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * CyoEncode.h - part of the CyoEncode library - * - * Copyright (c) 2009-2012, Graham Bull. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __CYOENCODE_H -#define __CYOENCODE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Base16 Encoding */ -size_t cyoBase16EncodeGetLength( size_t size ); -size_t cyoBase16Encode( char* dest, const void* src, size_t size ); - -/* Base32 Encoding */ -size_t cyoBase32EncodeGetLength( size_t size ); -size_t cyoBase32Encode( char* dest, const void* src, size_t size ); - -/* Base64 Encoding */ -size_t cyoBase64EncodeGetLength( size_t size ); -size_t cyoBase64Encode( char* dest, const void* src, size_t size ); - -#ifdef __cplusplus -} -#endif - -#endif /*__CYOENCODE_H*/ - diff --git a/vendor/cyoencode-1.0.2/src/build.sh b/vendor/cyoencode-1.0.2/src/build.sh deleted file mode 100755 index 67c0907..0000000 --- a/vendor/cyoencode-1.0.2/src/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -gcc test.c CyoEncode.c CyoDecode.c -o test - diff --git a/vendor/cyoencode-1.0.2/src/cyoencode-vc100.vcxproj b/vendor/cyoencode-1.0.2/src/cyoencode-vc100.vcxproj deleted file mode 100644 index 8c3a8d2..0000000 --- a/vendor/cyoencode-1.0.2/src/cyoencode-vc100.vcxproj +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - cyoencode-vc100 - {C773C1E9-CAC6-40AF-A400-567F73AB0178} - cyoencodevc100 - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - true - - - Application - Unicode - - - Application - Unicode - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - EditAndContinue - - - true - Console - MachineX86 - - - - - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - EnableFastChecks - MultiThreadedDebugDLL - - - Level4 - ProgramDatabase - - - true - Console - - - - - MaxSpeed - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level4 - ProgramDatabase - - - true - Console - true - true - MachineX86 - - - - - MaxSpeed - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level4 - ProgramDatabase - - - true - Console - true - true - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/vendor/cyoencode-1.0.2/src/cyoencode-vc71.vcproj b/vendor/cyoencode-1.0.2/src/cyoencode-vc71.vcproj deleted file mode 100644 index 26c46ff..0000000 --- a/vendor/cyoencode-1.0.2/src/cyoencode-vc71.vcproj +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/cyoencode-1.0.2/src/cyoencode-vc80.vcproj b/vendor/cyoencode-1.0.2/src/cyoencode-vc80.vcproj deleted file mode 100644 index c08685a..0000000 --- a/vendor/cyoencode-1.0.2/src/cyoencode-vc80.vcproj +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/cyoencode-1.0.2/src/cyoencode-vc90.vcproj b/vendor/cyoencode-1.0.2/src/cyoencode-vc90.vcproj deleted file mode 100644 index ee5927b..0000000 --- a/vendor/cyoencode-1.0.2/src/cyoencode-vc90.vcproj +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/cyoencode-1.0.2/src/test.c b/vendor/cyoencode-1.0.2/src/test.c deleted file mode 100644 index 9274105..0000000 --- a/vendor/cyoencode-1.0.2/src/test.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * test.c - part of the CyoEncode library - * - * Copyright (c) 2009-2012, Graham Bull. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "CyoEncode.h" -#include "CyoDecode.h" - -#include -#include -#include - -#define TEST_BASExx(base,str,expected) \ - printf( "TEST_BASE%s('%s')='%s'", #base, str, expected ); \ - required = cyoBase##base##EncodeGetLength( strlen( str )); \ - encoded = (char*)malloc( required ); \ - if (encoded == NULL) { \ - printf( "\n*** ERROR: Unable to allocate buffer for encoding ***\n" ); \ - goto exit; \ - } \ - cyoBase##base##Encode( encoded, str, strlen( str )); \ - if (strcmp( encoded, expected ) != 0) { \ - printf( "\n*** ERROR: Encoding failure ***\n" ); \ - goto exit; \ - } \ - valid = cyoBase##base##Validate( encoded, strlen( encoded )); \ - if (valid < 0) \ - { \ - printf( "\n*** ERROR: Unable to validate encoding (error %d) ***\n", valid ); \ - goto exit; \ - } \ - printf( " [passed]\n" ); \ - free( encoded ); encoded = NULL; - -#define TEST_BASE64(str,expected) TEST_BASExx(64,str,expected) -#define TEST_BASE32(str,expected) TEST_BASExx(32,str,expected) -#define TEST_BASE16(str,expected) TEST_BASExx(16,str,expected) - -#define CHECK_INVALID_BASExx(base,str,res) \ - printf( "CHECK_INVALID_BASE%s('%s')=%d", #base, str, res ); \ - valid = cyoBase##base##Validate( str, strlen( str )); \ - if (valid == 0) \ - { \ - printf( "\n*** ERROR: This is a valid encoding! ***\n" ); \ - goto exit; \ - } \ - if (valid != res) \ - { \ - printf( "\n*** ERROR: Expected a different return code! (%d) ***\n", valid ); \ - goto exit; \ - } \ - printf( " [passed]\n", #base, str ); \ - -#define CHECK_INVALID_BASE16(enc,res) CHECK_INVALID_BASExx(16,enc,res) -#define CHECK_INVALID_BASE32(enc,res) CHECK_INVALID_BASExx(32,enc,res) -#define CHECK_INVALID_BASE64(enc,res) CHECK_INVALID_BASExx(64,enc,res) - -int main( void ) -{ - const char* const original = "A wise man speaks when he has something to say"; - size_t required = 0; - char* encoded = NULL; - char* decoded = NULL; - int valid = 0; - int retcode = 1; - - printf( "Running CyoEncode tests...\n" ); - - /* Encode using Base64 */ - - printf( "Original = '%s'\n", original ); - required = cyoBase64EncodeGetLength( strlen( original )); - encoded = (char*)malloc( required ); - if (encoded == NULL) - { - printf( "*** ERROR: Unable to allocate buffer for encoding ***\n" ); - goto exit; - } - cyoBase64Encode( encoded, original, strlen( original )); - printf( "Encoded = '%s'\n", encoded ); - - /* Validate encoding */ - - valid = cyoBase64Validate( encoded, strlen( encoded )); - if (valid < 0) - { - printf( "*** ERROR: Encoding failure (error %d) ***\n", valid ); - goto exit; - } - - /* Decode using Base64 */ - - required = cyoBase64DecodeGetLength( strlen( encoded )); - decoded = (char*)malloc( required ); - if (decoded == NULL) - { - printf( "*** ERROR: Unable to allocate buffer for decoding ***\n" ); - goto exit; - } - cyoBase64Decode( decoded, encoded, strlen( encoded )); - printf( "Decoded = '%s'\n", decoded ); - - /* Validate */ - - if (strcmp( original, decoded ) != 0) - { - printf( "*** ERROR: Encoding/decoding failure ***\n" ); - goto exit; - } - - free( encoded ); - encoded = NULL; - free( decoded ); - decoded = NULL; - - /* Test vectors from RFC 4648 */ - - TEST_BASE16( "", "" ); - TEST_BASE16( "f", "66" ); - TEST_BASE16( "fo", "666F" ); - TEST_BASE16( "foo", "666F6F" ); - TEST_BASE16( "foob", "666F6F62" ); - TEST_BASE16( "fooba", "666F6F6261" ); - TEST_BASE16( "foobar", "666F6F626172" ); - - TEST_BASE32( "", "" ); - TEST_BASE32( "f", "MY======" ); - TEST_BASE32( "fo", "MZXQ====" ); - TEST_BASE32( "foo", "MZXW6===" ); - TEST_BASE32( "foob", "MZXW6YQ=" ); - TEST_BASE32( "fooba", "MZXW6YTB" ); - TEST_BASE32( "foobar", "MZXW6YTBOI======" ); - - TEST_BASE64( "", "" ); - TEST_BASE64( "f", "Zg==" ); - TEST_BASE64( "fo", "Zm8=" ); - TEST_BASE64( "foo", "Zm9v" ); - TEST_BASE64( "foob", "Zm9vYg==" ); - TEST_BASE64( "fooba", "Zm9vYmE=" ); - TEST_BASE64( "foobar", "Zm9vYmFy" ); - - /* Other tests */ - - CHECK_INVALID_BASE16( "1", -1 ); - CHECK_INVALID_BASE16( "123", -1 ); - CHECK_INVALID_BASE16( "1G", -2 ); - - CHECK_INVALID_BASE32( "A", -1 ); - CHECK_INVALID_BASE32( "ABCDEFG", -1 ); - CHECK_INVALID_BASE32( "ABCDEFG1", -2 ); - CHECK_INVALID_BASE32( "A=======", -2 ); - - CHECK_INVALID_BASE64( "A", -1 ); - CHECK_INVALID_BASE64( "ABCDE", -1 ); - CHECK_INVALID_BASE64( "A&B=", -2 ); - CHECK_INVALID_BASE64( "A===", -2 ); - - printf( "*** All tests passed ***\n" ); - retcode = 0; - -exit: - if (encoded != NULL) - free( encoded ); - if (decoded != NULL) - free( decoded ); - - return retcode; -} diff --git a/vendor/udt4/CMakeLists.txt b/vendor/udt4/CMakeLists.txt deleted file mode 100644 index 9d65ee7..0000000 --- a/vendor/udt4/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ - -IF( APPLE ) - add_definitions( -DOSX ) -ELSEIF( WIN32 ) - -ELSE() - add_definitions( -DLINUX ) -ENDIF() - -set( udt_sources - src/api.cpp - src/buffer.cpp - src/cache.cpp - src/ccc.cpp - src/channel.cpp - src/common.cpp - src/core.cpp - src/epoll.cpp - src/list.cpp - src/md5.cpp - src/packet.cpp - src/queue.cpp - src/window.cpp - ) - -add_library( udt ${udt_sources} ) diff --git a/vendor/udt4/LICENSE.txt b/vendor/udt4/LICENSE.txt deleted file mode 100644 index eec89df..0000000 --- a/vendor/udt4/LICENSE.txt +++ /dev/null @@ -1,32 +0,0 @@ -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/udt4/README.txt b/vendor/udt4/README.txt deleted file mode 100644 index 105be42..0000000 --- a/vendor/udt4/README.txt +++ /dev/null @@ -1,43 +0,0 @@ -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All Rights Reserved. -Copyright (c) 2011 - 2012, Google, Inc. All Rights Reserved. - -UDP-based Data Transfer (UDT) Library - version 4 -Author: Yunhong Gu [yunhong.gu @ gmail.com] - -UDT version 4 is free software under BSD License. See ./LICENSE.txt. - -============================================================================ - -UDT Website: -http://udt.sf.net -http://sf.net/projects/udt/ - - -CONTENT: -./src: UDT source code -./app: Example programs -./doc: UDT documentation (HTML) -./win: Visual C++ project files for the Windows version of UDT - - -To make: - make -e os=XXX arch=YYY - -XXX: [LINUX(default), BSD, OSX] -YYY: [IA32(default), POWERPC, IA64, AMD64] - -For example, on OS X, you may need to do "make -e os=OSX arch=POWERPC"; -on 32-bit i386 Linux system, simply use "make". - -On Windows systems, use the Visual C++ project files in ./win directory. - -Note for BSD users, please use GNU Make. - -To use UDT in your application: -Read index.htm in ./doc. The documentation is in HTML format and requires your -browser to support JavaScript. - - -Questions? please post to the UDT project forum: -https://sourceforge.net/projects/udt/forums diff --git a/vendor/udt4/src/api.cpp b/vendor/udt4/src/api.cpp deleted file mode 100644 index e444218..0000000 --- a/vendor/udt4/src/api.cpp +++ /dev/null @@ -1,2392 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 07/09/2011 -*****************************************************************************/ - -#ifdef WIN32 - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#else - #include -#endif -#include -#include "api.h" -#include "core.h" - -using namespace std; - -CUDTSocket::CUDTSocket(): -m_Status(INIT), -m_TimeStamp(0), -m_iIPversion(0), -m_pSelfAddr(NULL), -m_pPeerAddr(NULL), -m_SocketID(0), -m_ListenSocket(0), -m_PeerID(0), -m_iISN(0), -m_pUDT(NULL), -m_pQueuedSockets(NULL), -m_pAcceptSockets(NULL), -m_AcceptCond(), -m_AcceptLock(), -m_uiBackLog(0), -m_iMuxID(-1) -{ - #ifndef WIN32 - pthread_mutex_init(&m_AcceptLock, NULL); - pthread_cond_init(&m_AcceptCond, NULL); - pthread_mutex_init(&m_ControlLock, NULL); - #else - m_AcceptLock = CreateMutex(NULL, false, NULL); - m_AcceptCond = CreateEvent(NULL, false, false, NULL); - m_ControlLock = CreateMutex(NULL, false, NULL); - #endif -} - -CUDTSocket::~CUDTSocket() -{ - if (AF_INET == m_iIPversion) - { - delete (sockaddr_in*)m_pSelfAddr; - delete (sockaddr_in*)m_pPeerAddr; - } - else - { - delete (sockaddr_in6*)m_pSelfAddr; - delete (sockaddr_in6*)m_pPeerAddr; - } - - delete m_pUDT; - m_pUDT = NULL; - - delete m_pQueuedSockets; - delete m_pAcceptSockets; - - #ifndef WIN32 - pthread_mutex_destroy(&m_AcceptLock); - pthread_cond_destroy(&m_AcceptCond); - pthread_mutex_destroy(&m_ControlLock); - #else - CloseHandle(m_AcceptLock); - CloseHandle(m_AcceptCond); - CloseHandle(m_ControlLock); - #endif -} - -//////////////////////////////////////////////////////////////////////////////// - -CUDTUnited::CUDTUnited(): -m_Sockets(), -m_ControlLock(), -m_IDLock(), -m_SocketID(0), -m_TLSError(), -m_mMultiplexer(), -m_MultiplexerLock(), -m_pCache(NULL), -m_bClosing(false), -m_GCStopLock(), -m_GCStopCond(), -m_InitLock(), -m_iInstanceCount(0), -m_bGCStatus(false), -m_GCThread(), -m_ClosedSockets() -{ - // Socket ID MUST start from a random value - srand((unsigned int)CTimer::getTime()); - m_SocketID = 1 + (int)((1 << 30) * (double(rand()) / RAND_MAX)); - - #ifndef WIN32 - pthread_mutex_init(&m_ControlLock, NULL); - pthread_mutex_init(&m_IDLock, NULL); - pthread_mutex_init(&m_InitLock, NULL); - #else - m_ControlLock = CreateMutex(NULL, false, NULL); - m_IDLock = CreateMutex(NULL, false, NULL); - m_InitLock = CreateMutex(NULL, false, NULL); - #endif - - #ifndef WIN32 - pthread_key_create(&m_TLSError, TLSDestroy); - #else - m_TLSError = TlsAlloc(); - m_TLSLock = CreateMutex(NULL, false, NULL); - #endif - - m_pCache = new CCache; -} - -CUDTUnited::~CUDTUnited() -{ - #ifndef WIN32 - pthread_mutex_destroy(&m_ControlLock); - pthread_mutex_destroy(&m_IDLock); - pthread_mutex_destroy(&m_InitLock); - #else - CloseHandle(m_ControlLock); - CloseHandle(m_IDLock); - CloseHandle(m_InitLock); - #endif - - #ifndef WIN32 - pthread_key_delete(m_TLSError); - #else - TlsFree(m_TLSError); - CloseHandle(m_TLSLock); - #endif - - delete m_pCache; -} - -int CUDTUnited::startup() -{ - CGuard gcinit(m_InitLock); - - if (m_iInstanceCount++ > 0) - return 0; - - // Global initialization code - #ifdef WIN32 - WORD wVersionRequested; - WSADATA wsaData; - wVersionRequested = MAKEWORD(2, 2); - - if (0 != WSAStartup(wVersionRequested, &wsaData)) - throw CUDTException(1, 0, WSAGetLastError()); - #endif - - //init CTimer::EventLock - - if (m_bGCStatus) - return true; - - m_bClosing = false; - #ifndef WIN32 - pthread_mutex_init(&m_GCStopLock, NULL); - pthread_cond_init(&m_GCStopCond, NULL); - pthread_create(&m_GCThread, NULL, garbageCollect, this); - #else - m_GCStopLock = CreateMutex(NULL, false, NULL); - m_GCStopCond = CreateEvent(NULL, false, false, NULL); - DWORD ThreadID; - m_GCThread = CreateThread(NULL, 0, garbageCollect, this, 0, &ThreadID); - #endif - - m_bGCStatus = true; - - return 0; -} - -int CUDTUnited::cleanup() -{ - CGuard gcinit(m_InitLock); - - if (--m_iInstanceCount > 0) - return 0; - - //destroy CTimer::EventLock - - if (!m_bGCStatus) - return 0; - - m_bClosing = true; - #ifndef WIN32 - pthread_cond_signal(&m_GCStopCond); - pthread_join(m_GCThread, NULL); - pthread_mutex_destroy(&m_GCStopLock); - pthread_cond_destroy(&m_GCStopCond); - #else - SetEvent(m_GCStopCond); - WaitForSingleObject(m_GCThread, INFINITE); - CloseHandle(m_GCThread); - CloseHandle(m_GCStopLock); - CloseHandle(m_GCStopCond); - #endif - - m_bGCStatus = false; - - // Global destruction code - #ifdef WIN32 - WSACleanup(); - #endif - - return 0; -} - -UDTSOCKET CUDTUnited::newSocket(int af, int type) -{ - if ((type != SOCK_STREAM) && (type != SOCK_DGRAM)) - throw CUDTException(5, 3, 0); - - CUDTSocket* ns = NULL; - - try - { - ns = new CUDTSocket; - ns->m_pUDT = new CUDT; - if (AF_INET == af) - { - ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in); - ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0; - } - else - { - ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6); - ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0; - } - } - catch (...) - { - delete ns; - throw CUDTException(3, 2, 0); - } - - CGuard::enterCS(m_IDLock); - ns->m_SocketID = -- m_SocketID; - CGuard::leaveCS(m_IDLock); - - ns->m_Status = INIT; - ns->m_ListenSocket = 0; - ns->m_pUDT->m_SocketID = ns->m_SocketID; - ns->m_pUDT->m_iSockType = (SOCK_STREAM == type) ? UDT_STREAM : UDT_DGRAM; - ns->m_pUDT->m_iIPversion = ns->m_iIPversion = af; - ns->m_pUDT->m_pCache = m_pCache; - - // protect the m_Sockets structure. - CGuard::enterCS(m_ControlLock); - try - { - m_Sockets[ns->m_SocketID] = ns; - } - catch (...) - { - //failure and rollback - CGuard::leaveCS(m_ControlLock); - delete ns; - ns = NULL; - } - CGuard::leaveCS(m_ControlLock); - - if (NULL == ns) - throw CUDTException(3, 2, 0); - - return ns->m_SocketID; -} - -int CUDTUnited::newConnection(const UDTSOCKET listen, const sockaddr* peer, CHandShake* hs) -{ - CUDTSocket* ns = NULL; - CUDTSocket* ls = locate(listen); - - if (NULL == ls) - return -1; - - // if this connection has already been processed - if (NULL != (ns = locate(peer, hs->m_iID, hs->m_iISN))) - { - if (ns->m_pUDT->m_bBroken) - { - // last connection from the "peer" address has been broken - ns->m_Status = CLOSED; - ns->m_TimeStamp = CTimer::getTime(); - - CGuard::enterCS(ls->m_AcceptLock); - ls->m_pQueuedSockets->erase(ns->m_SocketID); - ls->m_pAcceptSockets->erase(ns->m_SocketID); - CGuard::leaveCS(ls->m_AcceptLock); - } - else - { - // connection already exist, this is a repeated connection request - // respond with existing HS information - - hs->m_iISN = ns->m_pUDT->m_iISN; - hs->m_iMSS = ns->m_pUDT->m_iMSS; - hs->m_iFlightFlagSize = ns->m_pUDT->m_iFlightFlagSize; - hs->m_iReqType = -1; - hs->m_iID = ns->m_SocketID; - - return 0; - - //except for this situation a new connection should be started - } - } - - // exceeding backlog, refuse the connection request - if (ls->m_pQueuedSockets->size() >= ls->m_uiBackLog) - return -1; - - try - { - ns = new CUDTSocket; - ns->m_pUDT = new CUDT(*(ls->m_pUDT)); - if (AF_INET == ls->m_iIPversion) - { - ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in); - ((sockaddr_in*)(ns->m_pSelfAddr))->sin_port = 0; - ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in); - memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in)); - } - else - { - ns->m_pSelfAddr = (sockaddr*)(new sockaddr_in6); - ((sockaddr_in6*)(ns->m_pSelfAddr))->sin6_port = 0; - ns->m_pPeerAddr = (sockaddr*)(new sockaddr_in6); - memcpy(ns->m_pPeerAddr, peer, sizeof(sockaddr_in6)); - } - } - catch (...) - { - delete ns; - return -1; - } - - CGuard::enterCS(m_IDLock); - ns->m_SocketID = -- m_SocketID; - CGuard::leaveCS(m_IDLock); - - ns->m_ListenSocket = listen; - ns->m_iIPversion = ls->m_iIPversion; - ns->m_pUDT->m_SocketID = ns->m_SocketID; - ns->m_PeerID = hs->m_iID; - ns->m_iISN = hs->m_iISN; - - int error = 0; - - try - { - // bind to the same addr of listening socket - ns->m_pUDT->open(); - updateMux(ns, ls); - ns->m_pUDT->connect(peer, hs); - } - catch (...) - { - error = 1; - goto ERR_ROLLBACK; - } - - ns->m_Status = CONNECTED; - - // copy address information of local node - ns->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(ns->m_pSelfAddr); - CIPAddress::pton(ns->m_pSelfAddr, ns->m_pUDT->m_piSelfIP, ns->m_iIPversion); - - // protect the m_Sockets structure. - CGuard::enterCS(m_ControlLock); - try - { - m_Sockets[ns->m_SocketID] = ns; - m_PeerRec[(ns->m_PeerID << 30) + ns->m_iISN].insert(ns->m_SocketID); - } - catch (...) - { - error = 2; - } - CGuard::leaveCS(m_ControlLock); - - CGuard::enterCS(ls->m_AcceptLock); - try - { - ls->m_pQueuedSockets->insert(ns->m_SocketID); - } - catch (...) - { - error = 3; - } - CGuard::leaveCS(ls->m_AcceptLock); - - // acknowledge users waiting for new connections on the listening socket - m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, true); - - CTimer::triggerEvent(); - - ERR_ROLLBACK: - if (error > 0) - { - ns->m_pUDT->close(); - ns->m_Status = CLOSED; - ns->m_TimeStamp = CTimer::getTime(); - - return -1; - } - - // wake up a waiting accept() call - #ifndef WIN32 - pthread_mutex_lock(&(ls->m_AcceptLock)); - pthread_cond_signal(&(ls->m_AcceptCond)); - pthread_mutex_unlock(&(ls->m_AcceptLock)); - #else - SetEvent(ls->m_AcceptCond); - #endif - - return 1; -} - -CUDT* CUDTUnited::lookup(const UDTSOCKET u) -{ - // protects the m_Sockets structure - CGuard cg(m_ControlLock); - - map::iterator i = m_Sockets.find(u); - - if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) - throw CUDTException(5, 4, 0); - - return i->second->m_pUDT; -} - -UDTSTATUS CUDTUnited::getStatus(const UDTSOCKET u) -{ - // protects the m_Sockets structure - CGuard cg(m_ControlLock); - - map::iterator i = m_Sockets.find(u); - - if (i == m_Sockets.end()) - { - if (m_ClosedSockets.find(u) != m_ClosedSockets.end()) - return CLOSED; - - return NONEXIST; - } - - if (i->second->m_pUDT->m_bBroken) - return BROKEN; - - return i->second->m_Status; -} - -int CUDTUnited::bind(const UDTSOCKET u, const sockaddr* name, int namelen) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - CGuard cg(s->m_ControlLock); - - // cannot bind a socket more than once - if (INIT != s->m_Status) - throw CUDTException(5, 0, 0); - - // check the size of SOCKADDR structure - if (AF_INET == s->m_iIPversion) - { - if (namelen != sizeof(sockaddr_in)) - throw CUDTException(5, 3, 0); - } - else - { - if (namelen != sizeof(sockaddr_in6)) - throw CUDTException(5, 3, 0); - } - - s->m_pUDT->open(); - updateMux(s, name); - s->m_Status = OPENED; - - // copy address information of local node - s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); - - return 0; -} - -int CUDTUnited::bind(UDTSOCKET u, UDPSOCKET udpsock) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - CGuard cg(s->m_ControlLock); - - // cannot bind a socket more than once - if (INIT != s->m_Status) - throw CUDTException(5, 0, 0); - - sockaddr_in name4; - sockaddr_in6 name6; - sockaddr* name; - socklen_t namelen; - - if (AF_INET == s->m_iIPversion) - { - namelen = sizeof(sockaddr_in); - name = (sockaddr*)&name4; - } - else - { - namelen = sizeof(sockaddr_in6); - name = (sockaddr*)&name6; - } - - if (-1 == ::getsockname(udpsock, name, &namelen)) - throw CUDTException(5, 3); - - s->m_pUDT->open(); - updateMux(s, name, &udpsock); - s->m_Status = OPENED; - - // copy address information of local node - s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); - - return 0; -} - -int CUDTUnited::listen(const UDTSOCKET u, int backlog) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - CGuard cg(s->m_ControlLock); - - // do nothing if the socket is already listening - if (LISTENING == s->m_Status) - return 0; - - // a socket can listen only if is in OPENED status - if (OPENED != s->m_Status) - throw CUDTException(5, 5, 0); - - // listen is not supported in rendezvous connection setup - if (s->m_pUDT->m_bRendezvous) - throw CUDTException(5, 7, 0); - - if (backlog <= 0) - throw CUDTException(5, 3, 0); - - s->m_uiBackLog = backlog; - - try - { - s->m_pQueuedSockets = new set; - s->m_pAcceptSockets = new set; - } - catch (...) - { - delete s->m_pQueuedSockets; - delete s->m_pAcceptSockets; - throw CUDTException(3, 2, 0); - } - - s->m_pUDT->listen(); - - s->m_Status = LISTENING; - - return 0; -} - -UDTSOCKET CUDTUnited::accept(const UDTSOCKET listen, sockaddr* addr, int* addrlen) -{ - if ((NULL != addr) && (NULL == addrlen)) - throw CUDTException(5, 3, 0); - - CUDTSocket* ls = locate(listen); - - if (ls == NULL) - throw CUDTException(5, 4, 0); - - // the "listen" socket must be in LISTENING status - if (LISTENING != ls->m_Status) - throw CUDTException(5, 6, 0); - - // no "accept" in rendezvous connection setup - if (ls->m_pUDT->m_bRendezvous) - throw CUDTException(5, 7, 0); - - UDTSOCKET u = CUDT::INVALID_SOCK; - bool accepted = false; - - // !!only one conection can be set up each time!! - #ifndef WIN32 - while (!accepted) - { - pthread_mutex_lock(&(ls->m_AcceptLock)); - - if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken) - { - // This socket has been closed. - accepted = true; - } - else if (ls->m_pQueuedSockets->size() > 0) - { - u = *(ls->m_pQueuedSockets->begin()); - ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u); - ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin()); - accepted = true; - } - else if (!ls->m_pUDT->m_bSynRecving) - { - accepted = true; - } - - if (!accepted && (LISTENING == ls->m_Status)) - pthread_cond_wait(&(ls->m_AcceptCond), &(ls->m_AcceptLock)); - - if (ls->m_pQueuedSockets->empty()) - m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, false); - - pthread_mutex_unlock(&(ls->m_AcceptLock)); - } - #else - while (!accepted) - { - WaitForSingleObject(ls->m_AcceptLock, INFINITE); - - if (ls->m_pQueuedSockets->size() > 0) - { - u = *(ls->m_pQueuedSockets->begin()); - ls->m_pAcceptSockets->insert(ls->m_pAcceptSockets->end(), u); - ls->m_pQueuedSockets->erase(ls->m_pQueuedSockets->begin()); - - accepted = true; - } - else if (!ls->m_pUDT->m_bSynRecving) - accepted = true; - - ReleaseMutex(ls->m_AcceptLock); - - if (!accepted & (LISTENING == ls->m_Status)) - WaitForSingleObject(ls->m_AcceptCond, INFINITE); - - if ((LISTENING != ls->m_Status) || ls->m_pUDT->m_bBroken) - { - // Send signal to other threads that are waiting to accept. - SetEvent(ls->m_AcceptCond); - accepted = true; - } - - if (ls->m_pQueuedSockets->empty()) - m_EPoll.update_events(listen, ls->m_pUDT->m_sPollID, UDT_EPOLL_IN, false); - } - #endif - - if (u == CUDT::INVALID_SOCK) - { - // non-blocking receiving, no connection available - if (!ls->m_pUDT->m_bSynRecving) - throw CUDTException(6, 2, 0); - - // listening socket is closed - throw CUDTException(5, 6, 0); - } - - if ((addr != NULL) && (addrlen != NULL)) - { - if (AF_INET == locate(u)->m_iIPversion) - *addrlen = sizeof(sockaddr_in); - else - *addrlen = sizeof(sockaddr_in6); - - // copy address information of peer node - memcpy(addr, locate(u)->m_pPeerAddr, *addrlen); - } - - return u; -} - -int CUDTUnited::connect(const UDTSOCKET u, const sockaddr* name, int namelen) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - CGuard cg(s->m_ControlLock); - - // check the size of SOCKADDR structure - if (AF_INET == s->m_iIPversion) - { - if (namelen != sizeof(sockaddr_in)) - throw CUDTException(5, 3, 0); - } - else - { - if (namelen != sizeof(sockaddr_in6)) - throw CUDTException(5, 3, 0); - } - - // a socket can "connect" only if it is in INIT or OPENED status - if (INIT == s->m_Status) - { - if (!s->m_pUDT->m_bRendezvous) - { - s->m_pUDT->open(); - updateMux(s); - s->m_Status = OPENED; - } - else - throw CUDTException(5, 8, 0); - } - else if (OPENED != s->m_Status) - throw CUDTException(5, 2, 0); - - // connect_complete() may be called before connect() returns. - // So we need to update the status before connect() is called, - // otherwise the status may be overwritten with wrong value (CONNECTED vs. CONNECTING). - s->m_Status = CONNECTING; - try - { - s->m_pUDT->connect(name); - } - catch (CUDTException e) - { - s->m_Status = OPENED; - throw e; - } - - // record peer address - delete s->m_pPeerAddr; - if (AF_INET == s->m_iIPversion) - { - s->m_pPeerAddr = (sockaddr*)(new sockaddr_in); - memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in)); - } - else - { - s->m_pPeerAddr = (sockaddr*)(new sockaddr_in6); - memcpy(s->m_pPeerAddr, name, sizeof(sockaddr_in6)); - } - - return 0; -} - -void CUDTUnited::connect_complete(const UDTSOCKET u) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - // copy address information of local node - // the local port must be correctly assigned BEFORE CUDT::connect(), - // otherwise if connect() fails, the multiplexer cannot be located by garbage collection and will cause leak - s->m_pUDT->m_pSndQueue->m_pChannel->getSockAddr(s->m_pSelfAddr); - CIPAddress::pton(s->m_pSelfAddr, s->m_pUDT->m_piSelfIP, s->m_iIPversion); - - s->m_Status = CONNECTED; -} - -int CUDTUnited::close(const UDTSOCKET u) -{ - CUDTSocket* s = locate(u); - if (NULL == s) - throw CUDTException(5, 4, 0); - - CGuard socket_cg(s->m_ControlLock); - - if (s->m_Status == LISTENING) - { - if (s->m_pUDT->m_bBroken) - return 0; - - s->m_TimeStamp = CTimer::getTime(); - s->m_pUDT->m_bBroken = true; - - // broadcast all "accept" waiting - #ifndef WIN32 - pthread_mutex_lock(&(s->m_AcceptLock)); - pthread_cond_broadcast(&(s->m_AcceptCond)); - pthread_mutex_unlock(&(s->m_AcceptLock)); - #else - SetEvent(s->m_AcceptCond); - #endif - - return 0; - } - - s->m_pUDT->close(); - - // synchronize with garbage collection. - CGuard manager_cg(m_ControlLock); - - // since "s" is located before m_ControlLock, locate it again in case it became invalid - map::iterator i = m_Sockets.find(u); - if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) - return 0; - s = i->second; - - s->m_Status = CLOSED; - - // a socket will not be immediated removed when it is closed - // in order to prevent other methods from accessing invalid address - // a timer is started and the socket will be removed after approximately 1 second - s->m_TimeStamp = CTimer::getTime(); - - m_Sockets.erase(s->m_SocketID); - m_ClosedSockets.insert(pair(s->m_SocketID, s)); - - CTimer::triggerEvent(); - - return 0; -} - -int CUDTUnited::getpeername(const UDTSOCKET u, sockaddr* name, int* namelen) -{ - if (CONNECTED != getStatus(u)) - throw CUDTException(2, 2, 0); - - CUDTSocket* s = locate(u); - - if (NULL == s) - throw CUDTException(5, 4, 0); - - if (!s->m_pUDT->m_bConnected || s->m_pUDT->m_bBroken) - throw CUDTException(2, 2, 0); - - if (AF_INET == s->m_iIPversion) - *namelen = sizeof(sockaddr_in); - else - *namelen = sizeof(sockaddr_in6); - - // copy address information of peer node - memcpy(name, s->m_pPeerAddr, *namelen); - - return 0; -} - -int CUDTUnited::getsockname(const UDTSOCKET u, sockaddr* name, int* namelen) -{ - CUDTSocket* s = locate(u); - - if (NULL == s) - throw CUDTException(5, 4, 0); - - if (s->m_pUDT->m_bBroken) - throw CUDTException(5, 4, 0); - - if (INIT == s->m_Status) - throw CUDTException(2, 2, 0); - - if (AF_INET == s->m_iIPversion) - *namelen = sizeof(sockaddr_in); - else - *namelen = sizeof(sockaddr_in6); - - // copy address information of local node - memcpy(name, s->m_pSelfAddr, *namelen); - - return 0; -} - -int CUDTUnited::select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout) -{ - uint64_t entertime = CTimer::getTime(); - - uint64_t to; - if (NULL == timeout) - to = 0xFFFFFFFFFFFFFFFFULL; - else - to = timeout->tv_sec * 1000000 + timeout->tv_usec; - - // initialize results - int count = 0; - set rs, ws, es; - - // retrieve related UDT sockets - vector ru, wu, eu; - CUDTSocket* s; - if (NULL != readfds) - for (set::iterator i1 = readfds->begin(); i1 != readfds->end(); ++ i1) - { - if (BROKEN == getStatus(*i1)) - { - rs.insert(*i1); - ++ count; - } - else if (NULL == (s = locate(*i1))) - throw CUDTException(5, 4, 0); - else - ru.push_back(s); - } - if (NULL != writefds) - for (set::iterator i2 = writefds->begin(); i2 != writefds->end(); ++ i2) - { - if (BROKEN == getStatus(*i2)) - { - ws.insert(*i2); - ++ count; - } - else if (NULL == (s = locate(*i2))) - throw CUDTException(5, 4, 0); - else - wu.push_back(s); - } - if (NULL != exceptfds) - for (set::iterator i3 = exceptfds->begin(); i3 != exceptfds->end(); ++ i3) - { - if (BROKEN == getStatus(*i3)) - { - es.insert(*i3); - ++ count; - } - else if (NULL == (s = locate(*i3))) - throw CUDTException(5, 4, 0); - else - eu.push_back(s); - } - - do - { - // query read sockets - for (vector::iterator j1 = ru.begin(); j1 != ru.end(); ++ j1) - { - s = *j1; - - if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pRcvBuffer->getRcvDataSize() > 0) && ((s->m_pUDT->m_iSockType == UDT_STREAM) || (s->m_pUDT->m_pRcvBuffer->getRcvMsgNum() > 0))) - || (!s->m_pUDT->m_bListening && (s->m_pUDT->m_bBroken || !s->m_pUDT->m_bConnected)) - || (s->m_pUDT->m_bListening && (s->m_pQueuedSockets->size() > 0)) - || (s->m_Status == CLOSED)) - { - rs.insert(s->m_SocketID); - ++ count; - } - } - - // query write sockets - for (vector::iterator j2 = wu.begin(); j2 != wu.end(); ++ j2) - { - s = *j2; - - if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pSndBuffer->getCurrBufSize() < s->m_pUDT->m_iSndBufSize)) - || s->m_pUDT->m_bBroken || !s->m_pUDT->m_bConnected || (s->m_Status == CLOSED)) - { - ws.insert(s->m_SocketID); - ++ count; - } - } - - // query exceptions on sockets - for (vector::iterator j3 = eu.begin(); j3 != eu.end(); ++ j3) - { - // check connection request status, not supported now - } - - if (0 < count) - break; - - CTimer::waitForEvent(); - } while (to > CTimer::getTime() - entertime); - - if (NULL != readfds) - *readfds = rs; - - if (NULL != writefds) - *writefds = ws; - - if (NULL != exceptfds) - *exceptfds = es; - - return count; -} - -int CUDTUnited::selectEx(const vector& fds, vector* readfds, vector* writefds, vector* exceptfds, int64_t msTimeOut) -{ - uint64_t entertime = CTimer::getTime(); - - uint64_t to; - if (msTimeOut >= 0) - to = msTimeOut * 1000; - else - to = 0xFFFFFFFFFFFFFFFFULL; - - // initialize results - int count = 0; - if (NULL != readfds) - readfds->clear(); - if (NULL != writefds) - writefds->clear(); - if (NULL != exceptfds) - exceptfds->clear(); - - do - { - for (vector::const_iterator i = fds.begin(); i != fds.end(); ++ i) - { - CUDTSocket* s = locate(*i); - - if ((NULL == s) || s->m_pUDT->m_bBroken || (s->m_Status == CLOSED)) - { - if (NULL != exceptfds) - { - exceptfds->push_back(*i); - ++ count; - } - continue; - } - - if (NULL != readfds) - { - if ((s->m_pUDT->m_bConnected && (s->m_pUDT->m_pRcvBuffer->getRcvDataSize() > 0) && ((s->m_pUDT->m_iSockType == UDT_STREAM) || (s->m_pUDT->m_pRcvBuffer->getRcvMsgNum() > 0))) - || (s->m_pUDT->m_bListening && (s->m_pQueuedSockets->size() > 0))) - { - readfds->push_back(s->m_SocketID); - ++ count; - } - } - - if (NULL != writefds) - { - if (s->m_pUDT->m_bConnected && (s->m_pUDT->m_pSndBuffer->getCurrBufSize() < s->m_pUDT->m_iSndBufSize)) - { - writefds->push_back(s->m_SocketID); - ++ count; - } - } - } - - if (count > 0) - break; - - CTimer::waitForEvent(); - } while (to > CTimer::getTime() - entertime); - - return count; -} - -int CUDTUnited::epoll_create() -{ - return m_EPoll.create(); -} - -int CUDTUnited::epoll_add_usock(const int eid, const UDTSOCKET u, const int* events) -{ - CUDTSocket* s = locate(u); - int ret = -1; - if (NULL != s) - { - ret = m_EPoll.add_usock(eid, u, events); - s->m_pUDT->addEPoll(eid); - } - else - { - throw CUDTException(5, 4); - } - - return ret; -} - -int CUDTUnited::epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events) -{ - return m_EPoll.add_ssock(eid, s, events); -} - -int CUDTUnited::epoll_remove_usock(const int eid, const UDTSOCKET u) -{ - int ret = m_EPoll.remove_usock(eid, u); - - CUDTSocket* s = locate(u); - if (NULL != s) - { - s->m_pUDT->removeEPoll(eid); - } - //else - //{ - // throw CUDTException(5, 4); - //} - - return ret; -} - -int CUDTUnited::epoll_remove_ssock(const int eid, const SYSSOCKET s) -{ - return m_EPoll.remove_ssock(eid, s); -} - -int CUDTUnited::epoll_wait(const int eid, set* readfds, set* writefds, int64_t msTimeOut, set* lrfds, set* lwfds) -{ - return m_EPoll.wait(eid, readfds, writefds, msTimeOut, lrfds, lwfds); -} - -int CUDTUnited::epoll_release(const int eid) -{ - return m_EPoll.release(eid); -} - -CUDTSocket* CUDTUnited::locate(const UDTSOCKET u) -{ - CGuard cg(m_ControlLock); - - map::iterator i = m_Sockets.find(u); - - if ((i == m_Sockets.end()) || (i->second->m_Status == CLOSED)) - return NULL; - - return i->second; -} - -CUDTSocket* CUDTUnited::locate(const sockaddr* peer, const UDTSOCKET id, int32_t isn) -{ - CGuard cg(m_ControlLock); - - map >::iterator i = m_PeerRec.find((id << 30) + isn); - if (i == m_PeerRec.end()) - return NULL; - - for (set::iterator j = i->second.begin(); j != i->second.end(); ++ j) - { - map::iterator k = m_Sockets.find(*j); - // this socket might have been closed and moved m_ClosedSockets - if (k == m_Sockets.end()) - continue; - - if (CIPAddress::ipcmp(peer, k->second->m_pPeerAddr, k->second->m_iIPversion)) - return k->second; - } - - return NULL; -} - -void CUDTUnited::checkBrokenSockets() -{ - CGuard cg(m_ControlLock); - - // set of sockets To Be Closed and To Be Removed - vector tbc; - vector tbr; - - for (map::iterator i = m_Sockets.begin(); i != m_Sockets.end(); ++ i) - { - // check broken connection - if (i->second->m_pUDT->m_bBroken) - { - if (i->second->m_Status == LISTENING) - { - // for a listening socket, it should wait an extra 3 seconds in case a client is connecting - if (CTimer::getTime() - i->second->m_TimeStamp < 3000000) - continue; - } - else if ((i->second->m_pUDT->m_pRcvBuffer != NULL) && (i->second->m_pUDT->m_pRcvBuffer->getRcvDataSize() > 0) && (i->second->m_pUDT->m_iBrokenCounter -- > 0)) - { - // if there is still data in the receiver buffer, wait longer - continue; - } - - //close broken connections and start removal timer - i->second->m_Status = CLOSED; - i->second->m_TimeStamp = CTimer::getTime(); - tbc.push_back(i->first); - m_ClosedSockets[i->first] = i->second; - - // remove from listener's queue - map::iterator ls = m_Sockets.find(i->second->m_ListenSocket); - if (ls == m_Sockets.end()) - { - ls = m_ClosedSockets.find(i->second->m_ListenSocket); - if (ls == m_ClosedSockets.end()) - continue; - } - - CGuard::enterCS(ls->second->m_AcceptLock); - ls->second->m_pQueuedSockets->erase(i->second->m_SocketID); - ls->second->m_pAcceptSockets->erase(i->second->m_SocketID); - CGuard::leaveCS(ls->second->m_AcceptLock); - } - } - - for (map::iterator j = m_ClosedSockets.begin(); j != m_ClosedSockets.end(); ++ j) - { - if (j->second->m_pUDT->m_ullLingerExpiration > 0) - { - // asynchronous close: - if ((NULL == j->second->m_pUDT->m_pSndBuffer) || (0 == j->second->m_pUDT->m_pSndBuffer->getCurrBufSize()) || (j->second->m_pUDT->m_ullLingerExpiration <= CTimer::getTime())) - { - j->second->m_pUDT->m_ullLingerExpiration = 0; - j->second->m_pUDT->m_bClosing = true; - j->second->m_TimeStamp = CTimer::getTime(); - } - } - - // timeout 1 second to destroy a socket AND it has been removed from RcvUList - if ((CTimer::getTime() - j->second->m_TimeStamp > 1000000) && ((NULL == j->second->m_pUDT->m_pRNode) || !j->second->m_pUDT->m_pRNode->m_bOnList)) - { - tbr.push_back(j->first); - } - } - - // move closed sockets to the ClosedSockets structure - for (vector::iterator k = tbc.begin(); k != tbc.end(); ++ k) - m_Sockets.erase(*k); - - // remove those timeout sockets - for (vector::iterator l = tbr.begin(); l != tbr.end(); ++ l) - removeSocket(*l); -} - -void CUDTUnited::removeSocket(const UDTSOCKET u) -{ - map::iterator i = m_ClosedSockets.find(u); - - // invalid socket ID - if (i == m_ClosedSockets.end()) - return; - - // decrease multiplexer reference count, and remove it if necessary - const int mid = i->second->m_iMuxID; - - if (NULL != i->second->m_pQueuedSockets) - { - CGuard::enterCS(i->second->m_AcceptLock); - - // if it is a listener, close all un-accepted sockets in its queue and remove them later - for (set::iterator q = i->second->m_pQueuedSockets->begin(); q != i->second->m_pQueuedSockets->end(); ++ q) - { - m_Sockets[*q]->m_pUDT->m_bBroken = true; - m_Sockets[*q]->m_pUDT->close(); - m_Sockets[*q]->m_TimeStamp = CTimer::getTime(); - m_Sockets[*q]->m_Status = CLOSED; - m_ClosedSockets[*q] = m_Sockets[*q]; - m_Sockets.erase(*q); - } - - CGuard::leaveCS(i->second->m_AcceptLock); - } - - // remove from peer rec - map >::iterator j = m_PeerRec.find((i->second->m_PeerID << 30) + i->second->m_iISN); - if (j != m_PeerRec.end()) - { - j->second.erase(u); - if (j->second.empty()) - m_PeerRec.erase(j); - } - - // delete this one - i->second->m_pUDT->close(); - delete i->second; - m_ClosedSockets.erase(i); - - map::iterator m; - m = m_mMultiplexer.find(mid); - if (m == m_mMultiplexer.end()) - { - //something is wrong!!! - return; - } - - m->second.m_iRefCount --; - if (0 == m->second.m_iRefCount) - { - m->second.m_pChannel->close(); - delete m->second.m_pSndQueue; - delete m->second.m_pRcvQueue; - delete m->second.m_pTimer; - delete m->second.m_pChannel; - m_mMultiplexer.erase(m); - } -} - -void CUDTUnited::setError(CUDTException* e) -{ - #ifndef WIN32 - delete (CUDTException*)pthread_getspecific(m_TLSError); - pthread_setspecific(m_TLSError, e); - #else - CGuard tg(m_TLSLock); - delete (CUDTException*)TlsGetValue(m_TLSError); - TlsSetValue(m_TLSError, e); - m_mTLSRecord[GetCurrentThreadId()] = e; - #endif -} - -CUDTException* CUDTUnited::getError() -{ - #ifndef WIN32 - if(NULL == pthread_getspecific(m_TLSError)) - pthread_setspecific(m_TLSError, new CUDTException); - return (CUDTException*)pthread_getspecific(m_TLSError); - #else - CGuard tg(m_TLSLock); - if(NULL == TlsGetValue(m_TLSError)) - { - CUDTException* e = new CUDTException; - TlsSetValue(m_TLSError, e); - m_mTLSRecord[GetCurrentThreadId()] = e; - } - return (CUDTException*)TlsGetValue(m_TLSError); - #endif -} - -#ifdef WIN32 -void CUDTUnited::checkTLSValue() -{ - CGuard tg(m_TLSLock); - - vector tbr; - for (map::iterator i = m_mTLSRecord.begin(); i != m_mTLSRecord.end(); ++ i) - { - HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, i->first); - if (NULL == h) - { - tbr.push_back(i->first); - break; - } - if (WAIT_OBJECT_0 == WaitForSingleObject(h, 0)) - { - delete i->second; - tbr.push_back(i->first); - } - CloseHandle(h); - } - for (vector::iterator j = tbr.begin(); j != tbr.end(); ++ j) - m_mTLSRecord.erase(*j); -} -#endif - -void CUDTUnited::updateMux(CUDTSocket* s, const sockaddr* addr, const UDPSOCKET* udpsock) -{ - CGuard cg(m_ControlLock); - - if ((s->m_pUDT->m_bReuseAddr) && (NULL != addr)) - { - int port = (AF_INET == s->m_pUDT->m_iIPversion) ? ntohs(((sockaddr_in*)addr)->sin_port) : ntohs(((sockaddr_in6*)addr)->sin6_port); - - // find a reusable address - for (map::iterator i = m_mMultiplexer.begin(); i != m_mMultiplexer.end(); ++ i) - { - if ((i->second.m_iIPversion == s->m_pUDT->m_iIPversion) && (i->second.m_iMSS == s->m_pUDT->m_iMSS) && i->second.m_bReusable) - { - if (i->second.m_iPort == port) - { - // reuse the existing multiplexer - ++ i->second.m_iRefCount; - s->m_pUDT->m_pSndQueue = i->second.m_pSndQueue; - s->m_pUDT->m_pRcvQueue = i->second.m_pRcvQueue; - s->m_iMuxID = i->second.m_iID; - return; - } - } - } - } - - // a new multiplexer is needed - CMultiplexer m; - m.m_iMSS = s->m_pUDT->m_iMSS; - m.m_iIPversion = s->m_pUDT->m_iIPversion; - m.m_iRefCount = 1; - m.m_bReusable = s->m_pUDT->m_bReuseAddr; - m.m_iID = s->m_SocketID; - - m.m_pChannel = new CChannel(s->m_pUDT->m_iIPversion); - m.m_pChannel->setSndBufSize(s->m_pUDT->m_iUDPSndBufSize); - m.m_pChannel->setRcvBufSize(s->m_pUDT->m_iUDPRcvBufSize); - - try - { - if (NULL != udpsock) - m.m_pChannel->open(*udpsock); - else - m.m_pChannel->open(addr); - } - catch (CUDTException& e) - { - m.m_pChannel->close(); - delete m.m_pChannel; - throw e; - } - - sockaddr* sa = (AF_INET == s->m_pUDT->m_iIPversion) ? (sockaddr*) new sockaddr_in : (sockaddr*) new sockaddr_in6; - m.m_pChannel->getSockAddr(sa); - m.m_iPort = (AF_INET == s->m_pUDT->m_iIPversion) ? ntohs(((sockaddr_in*)sa)->sin_port) : ntohs(((sockaddr_in6*)sa)->sin6_port); - if (AF_INET == s->m_pUDT->m_iIPversion) delete (sockaddr_in*)sa; else delete (sockaddr_in6*)sa; - - m.m_pTimer = new CTimer; - - m.m_pSndQueue = new CSndQueue; - m.m_pSndQueue->init(m.m_pChannel, m.m_pTimer); - m.m_pRcvQueue = new CRcvQueue; - m.m_pRcvQueue->init(32, s->m_pUDT->m_iPayloadSize, m.m_iIPversion, 1024, m.m_pChannel, m.m_pTimer); - - m_mMultiplexer[m.m_iID] = m; - - s->m_pUDT->m_pSndQueue = m.m_pSndQueue; - s->m_pUDT->m_pRcvQueue = m.m_pRcvQueue; - s->m_iMuxID = m.m_iID; -} - -void CUDTUnited::updateMux(CUDTSocket* s, const CUDTSocket* ls) -{ - CGuard cg(m_ControlLock); - - int port = (AF_INET == ls->m_iIPversion) ? ntohs(((sockaddr_in*)ls->m_pSelfAddr)->sin_port) : ntohs(((sockaddr_in6*)ls->m_pSelfAddr)->sin6_port); - - // find the listener's address - for (map::iterator i = m_mMultiplexer.begin(); i != m_mMultiplexer.end(); ++ i) - { - if (i->second.m_iPort == port) - { - // reuse the existing multiplexer - ++ i->second.m_iRefCount; - s->m_pUDT->m_pSndQueue = i->second.m_pSndQueue; - s->m_pUDT->m_pRcvQueue = i->second.m_pRcvQueue; - s->m_iMuxID = i->second.m_iID; - return; - } - } -} - -#ifndef WIN32 - void* CUDTUnited::garbageCollect(void* p) -#else - DWORD WINAPI CUDTUnited::garbageCollect(LPVOID p) -#endif -{ - CUDTUnited* self = (CUDTUnited*)p; - - CGuard gcguard(self->m_GCStopLock); - - while (!self->m_bClosing) - { - self->checkBrokenSockets(); - - #ifdef WIN32 - self->checkTLSValue(); - #endif - - #ifndef WIN32 - timeval now; - timespec timeout; - gettimeofday(&now, 0); - timeout.tv_sec = now.tv_sec + 1; - timeout.tv_nsec = now.tv_usec * 1000; - - pthread_cond_timedwait(&self->m_GCStopCond, &self->m_GCStopLock, &timeout); - #else - WaitForSingleObject(self->m_GCStopCond, 1000); - #endif - } - - // remove all sockets and multiplexers - CGuard::enterCS(self->m_ControlLock); - for (map::iterator i = self->m_Sockets.begin(); i != self->m_Sockets.end(); ++ i) - { - i->second->m_pUDT->m_bBroken = true; - i->second->m_pUDT->close(); - i->second->m_Status = CLOSED; - i->second->m_TimeStamp = CTimer::getTime(); - self->m_ClosedSockets[i->first] = i->second; - - // remove from listener's queue - map::iterator ls = self->m_Sockets.find(i->second->m_ListenSocket); - if (ls == self->m_Sockets.end()) - { - ls = self->m_ClosedSockets.find(i->second->m_ListenSocket); - if (ls == self->m_ClosedSockets.end()) - continue; - } - - CGuard::enterCS(ls->second->m_AcceptLock); - ls->second->m_pQueuedSockets->erase(i->second->m_SocketID); - ls->second->m_pAcceptSockets->erase(i->second->m_SocketID); - CGuard::leaveCS(ls->second->m_AcceptLock); - } - self->m_Sockets.clear(); - - for (map::iterator j = self->m_ClosedSockets.begin(); j != self->m_ClosedSockets.end(); ++ j) - { - j->second->m_TimeStamp = 0; - } - CGuard::leaveCS(self->m_ControlLock); - - while (true) - { - self->checkBrokenSockets(); - - CGuard::enterCS(self->m_ControlLock); - bool empty = self->m_ClosedSockets.empty(); - CGuard::leaveCS(self->m_ControlLock); - - if (empty) - break; - - CTimer::sleep(); - } - - #ifndef WIN32 - return NULL; - #else - return 0; - #endif -} - -//////////////////////////////////////////////////////////////////////////////// - -int CUDT::startup() -{ - return s_UDTUnited.startup(); -} - -int CUDT::cleanup() -{ - return s_UDTUnited.cleanup(); -} - -UDTSOCKET CUDT::socket(int af, int type, int) -{ - if (!s_UDTUnited.m_bGCStatus) - s_UDTUnited.startup(); - - try - { - return s_UDTUnited.newSocket(af, type); - } - catch (CUDTException& e) - { - s_UDTUnited.setError(new CUDTException(e)); - return INVALID_SOCK; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return INVALID_SOCK; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return INVALID_SOCK; - } -} - -int CUDT::bind(UDTSOCKET u, const sockaddr* name, int namelen) -{ - try - { - return s_UDTUnited.bind(u, name, namelen); - } - catch (CUDTException& e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::bind(UDTSOCKET u, UDPSOCKET udpsock) -{ - try - { - return s_UDTUnited.bind(u, udpsock); - } - catch (CUDTException& e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::listen(UDTSOCKET u, int backlog) -{ - try - { - return s_UDTUnited.listen(u, backlog); - } - catch (CUDTException& e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -UDTSOCKET CUDT::accept(UDTSOCKET u, sockaddr* addr, int* addrlen) -{ - try - { - return s_UDTUnited.accept(u, addr, addrlen); - } - catch (CUDTException& e) - { - s_UDTUnited.setError(new CUDTException(e)); - return INVALID_SOCK; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return INVALID_SOCK; - } -} - -int CUDT::connect(UDTSOCKET u, const sockaddr* name, int namelen) -{ - try - { - return s_UDTUnited.connect(u, name, namelen); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::close(UDTSOCKET u) -{ - try - { - return s_UDTUnited.close(u); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::getpeername(UDTSOCKET u, sockaddr* name, int* namelen) -{ - try - { - return s_UDTUnited.getpeername(u, name, namelen); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::getsockname(UDTSOCKET u, sockaddr* name, int* namelen) -{ - try - { - return s_UDTUnited.getsockname(u, name, namelen);; - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::getsockopt(UDTSOCKET u, int, UDTOpt optname, void* optval, int* optlen) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - udt->getOpt(optname, optval, *optlen); - return 0; - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::setsockopt(UDTSOCKET u, int, UDTOpt optname, const void* optval, int optlen) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - udt->setOpt(optname, optval, optlen); - return 0; - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::send(UDTSOCKET u, const char* buf, int len, int) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->send(buf, len); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::recv(UDTSOCKET u, char* buf, int len, int) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->recv(buf, len); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::sendmsg(UDTSOCKET u, const char* buf, int len, int ttl, bool inorder) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->sendmsg(buf, len, ttl, inorder); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::recvmsg(UDTSOCKET u, char* buf, int len) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->recvmsg(buf, len); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int64_t CUDT::sendfile(UDTSOCKET u, fstream& ifs, int64_t& offset, int64_t size, int block) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->sendfile(ifs, offset, size, block); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int64_t CUDT::recvfile(UDTSOCKET u, fstream& ofs, int64_t& offset, int64_t size, int block) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - return udt->recvfile(ofs, offset, size, block); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::select(int, ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout) -{ - if ((NULL == readfds) && (NULL == writefds) && (NULL == exceptfds)) - { - s_UDTUnited.setError(new CUDTException(5, 3, 0)); - return ERROR; - } - - try - { - return s_UDTUnited.select(readfds, writefds, exceptfds, timeout); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::selectEx(const vector& fds, vector* readfds, vector* writefds, vector* exceptfds, int64_t msTimeOut) -{ - if ((NULL == readfds) && (NULL == writefds) && (NULL == exceptfds)) - { - s_UDTUnited.setError(new CUDTException(5, 3, 0)); - return ERROR; - } - - try - { - return s_UDTUnited.selectEx(fds, readfds, writefds, exceptfds, msTimeOut); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (bad_alloc&) - { - s_UDTUnited.setError(new CUDTException(3, 2, 0)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_create() -{ - try - { - return s_UDTUnited.epoll_create(); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_add_usock(const int eid, const UDTSOCKET u, const int* events) -{ - try - { - return s_UDTUnited.epoll_add_usock(eid, u, events); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events) -{ - try - { - return s_UDTUnited.epoll_add_ssock(eid, s, events); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_remove_usock(const int eid, const UDTSOCKET u) -{ - try - { - return s_UDTUnited.epoll_remove_usock(eid, u); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_remove_ssock(const int eid, const SYSSOCKET s) -{ - try - { - return s_UDTUnited.epoll_remove_ssock(eid, s); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_wait(const int eid, set* readfds, set* writefds, int64_t msTimeOut, set* lrfds, set* lwfds) -{ - try - { - return s_UDTUnited.epoll_wait(eid, readfds, writefds, msTimeOut, lrfds, lwfds); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -int CUDT::epoll_release(const int eid) -{ - try - { - return s_UDTUnited.epoll_release(eid); - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -CUDTException& CUDT::getlasterror() -{ - return *s_UDTUnited.getError(); -} - -int CUDT::perfmon(UDTSOCKET u, CPerfMon* perf, bool clear) -{ - try - { - CUDT* udt = s_UDTUnited.lookup(u); - udt->sample(perf, clear); - return 0; - } - catch (CUDTException e) - { - s_UDTUnited.setError(new CUDTException(e)); - return ERROR; - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return ERROR; - } -} - -CUDT* CUDT::getUDTHandle(UDTSOCKET u) -{ - try - { - return s_UDTUnited.lookup(u); - } - catch (...) - { - return NULL; - } -} - -UDTSTATUS CUDT::getsockstate(UDTSOCKET u) -{ - try - { - return s_UDTUnited.getStatus(u); - } - catch (...) - { - s_UDTUnited.setError(new CUDTException(-1, 0, 0)); - return NONEXIST; - } -} - - -//////////////////////////////////////////////////////////////////////////////// - -namespace UDT -{ - -int startup() -{ - return CUDT::startup(); -} - -int cleanup() -{ - return CUDT::cleanup(); -} - -UDTSOCKET socket(int af, int type, int protocol) -{ - return CUDT::socket(af, type, protocol); -} - -int bind(UDTSOCKET u, const struct sockaddr* name, int namelen) -{ - return CUDT::bind(u, name, namelen); -} - -int bind2(UDTSOCKET u, UDPSOCKET udpsock) -{ - return CUDT::bind(u, udpsock); -} - -int listen(UDTSOCKET u, int backlog) -{ - return CUDT::listen(u, backlog); -} - -UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen) -{ - return CUDT::accept(u, addr, addrlen); -} - -int connect(UDTSOCKET u, const struct sockaddr* name, int namelen) -{ - return CUDT::connect(u, name, namelen); -} - -int close(UDTSOCKET u) -{ - return CUDT::close(u); -} - -int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen) -{ - return CUDT::getpeername(u, name, namelen); -} - -int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen) -{ - return CUDT::getsockname(u, name, namelen); -} - -int getsockopt(UDTSOCKET u, int level, SOCKOPT optname, void* optval, int* optlen) -{ - return CUDT::getsockopt(u, level, optname, optval, optlen); -} - -int setsockopt(UDTSOCKET u, int level, SOCKOPT optname, const void* optval, int optlen) -{ - return CUDT::setsockopt(u, level, optname, optval, optlen); -} - -int send(UDTSOCKET u, const char* buf, int len, int flags) -{ - return CUDT::send(u, buf, len, flags); -} - -int recv(UDTSOCKET u, char* buf, int len, int flags) -{ - return CUDT::recv(u, buf, len, flags); -} - -int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl, bool inorder) -{ - return CUDT::sendmsg(u, buf, len, ttl, inorder); -} - -int recvmsg(UDTSOCKET u, char* buf, int len) -{ - return CUDT::recvmsg(u, buf, len); -} - -int64_t sendfile(UDTSOCKET u, fstream& ifs, int64_t& offset, int64_t size, int block) -{ - return CUDT::sendfile(u, ifs, offset, size, block); -} - -int64_t recvfile(UDTSOCKET u, fstream& ofs, int64_t& offset, int64_t size, int block) -{ - return CUDT::recvfile(u, ofs, offset, size, block); -} - -int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block) -{ - fstream ifs(path, ios::binary | ios::in); - int64_t ret = CUDT::sendfile(u, ifs, *offset, size, block); - ifs.close(); - return ret; -} - -int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block) -{ - fstream ofs(path, ios::binary | ios::out); - int64_t ret = CUDT::recvfile(u, ofs, *offset, size, block); - ofs.close(); - return ret; -} - -int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout) -{ - return CUDT::select(nfds, readfds, writefds, exceptfds, timeout); -} - -int selectEx(const vector& fds, vector* readfds, vector* writefds, vector* exceptfds, int64_t msTimeOut) -{ - return CUDT::selectEx(fds, readfds, writefds, exceptfds, msTimeOut); -} - -int epoll_create() -{ - return CUDT::epoll_create(); -} - -int epoll_add_usock(int eid, UDTSOCKET u, const int* events) -{ - return CUDT::epoll_add_usock(eid, u, events); -} - -int epoll_add_ssock(int eid, SYSSOCKET s, const int* events) -{ - return CUDT::epoll_add_ssock(eid, s, events); -} - -int epoll_remove_usock(int eid, UDTSOCKET u) -{ - return CUDT::epoll_remove_usock(eid, u); -} - -int epoll_remove_ssock(int eid, SYSSOCKET s) -{ - return CUDT::epoll_remove_ssock(eid, s); -} - -int epoll_wait(int eid, set* readfds, set* writefds, int64_t msTimeOut, set* lrfds, set* lwfds) -{ - return CUDT::epoll_wait(eid, readfds, writefds, msTimeOut, lrfds, lwfds); -} - -#define SET_RESULT(val, num, fds, it) \ - if ((val != NULL) && !val->empty()) \ - { \ - if (*num > static_cast(val->size())) \ - *num = val->size(); \ - int count = 0; \ - for (it = val->begin(); it != val->end(); ++ it) \ - { \ - if (count >= *num) \ - break; \ - fds[count ++] = *it; \ - } \ - } -int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut, - SYSSOCKET* lrfds, int* lrnum, SYSSOCKET* lwfds, int* lwnum) -{ - // This API is an alternative format for epoll_wait, created for compatability with other languages. - // Users need to pass in an array for holding the returned sockets, with the maximum array length - // stored in *rnum, etc., which will be updated with returned number of sockets. - - set readset; - set writeset; - set lrset; - set lwset; - set* rval = NULL; - set* wval = NULL; - set* lrval = NULL; - set* lwval = NULL; - if ((readfds != NULL) && (rnum != NULL)) - rval = &readset; - if ((writefds != NULL) && (wnum != NULL)) - wval = &writeset; - if ((lrfds != NULL) && (lrnum != NULL)) - lrval = &lrset; - if ((lwfds != NULL) && (lwnum != NULL)) - lwval = &lwset; - - int ret = CUDT::epoll_wait(eid, rval, wval, msTimeOut, lrval, lwval); - if (ret > 0) - { - set::const_iterator i; - SET_RESULT(rval, rnum, readfds, i); - SET_RESULT(wval, wnum, writefds, i); - set::const_iterator j; - SET_RESULT(lrval, lrnum, lrfds, j); - SET_RESULT(lwval, lwnum, lwfds, j); - } - return ret; -} - -int epoll_release(int eid) -{ - return CUDT::epoll_release(eid); -} - -ERRORINFO& getlasterror() -{ - return CUDT::getlasterror(); -} - -int getlasterror_code() -{ - return CUDT::getlasterror().getErrorCode(); -} - -const char* getlasterror_desc() -{ - return CUDT::getlasterror().getErrorMessage(); -} - -int perfmon(UDTSOCKET u, TRACEINFO* perf, bool clear) -{ - return CUDT::perfmon(u, perf, clear); -} - -UDTSTATUS getsockstate(UDTSOCKET u) -{ - return CUDT::getsockstate(u); -} - -} // namespace UDT diff --git a/vendor/udt4/src/api.h b/vendor/udt4/src/api.h deleted file mode 100644 index 24f1a02..0000000 --- a/vendor/udt4/src/api.h +++ /dev/null @@ -1,268 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 09/28/2010 -*****************************************************************************/ - -#ifndef __UDT_API_H__ -#define __UDT_API_H__ - - -#include -#include -#include "udt.h" -#include "packet.h" -#include "queue.h" -#include "cache.h" -#include "epoll.h" - -class CUDT; - -class CUDTSocket -{ -public: - CUDTSocket(); - ~CUDTSocket(); - - UDTSTATUS m_Status; // current socket state - - uint64_t m_TimeStamp; // time when the socket is closed - - int m_iIPversion; // IP version - sockaddr* m_pSelfAddr; // pointer to the local address of the socket - sockaddr* m_pPeerAddr; // pointer to the peer address of the socket - - UDTSOCKET m_SocketID; // socket ID - UDTSOCKET m_ListenSocket; // ID of the listener socket; 0 means this is an independent socket - - UDTSOCKET m_PeerID; // peer socket ID - int32_t m_iISN; // initial sequence number, used to tell different connection from same IP:port - - CUDT* m_pUDT; // pointer to the UDT entity - - std::set* m_pQueuedSockets; // set of connections waiting for accept() - std::set* m_pAcceptSockets; // set of accept()ed connections - - pthread_cond_t m_AcceptCond; // used to block "accept" call - pthread_mutex_t m_AcceptLock; // mutex associated to m_AcceptCond - - unsigned int m_uiBackLog; // maximum number of connections in queue - - int m_iMuxID; // multiplexer ID - - pthread_mutex_t m_ControlLock; // lock this socket exclusively for control APIs: bind/listen/connect - -private: - CUDTSocket(const CUDTSocket&); - CUDTSocket& operator=(const CUDTSocket&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CUDTUnited -{ -friend class CUDT; -friend class CRendezvousQueue; - -public: - CUDTUnited(); - ~CUDTUnited(); - -public: - - // Functionality: - // initialize the UDT library. - // Parameters: - // None. - // Returned value: - // 0 if success, otherwise -1 is returned. - - int startup(); - - // Functionality: - // release the UDT library. - // Parameters: - // None. - // Returned value: - // 0 if success, otherwise -1 is returned. - - int cleanup(); - - // Functionality: - // Create a new UDT socket. - // Parameters: - // 0) [in] af: IP version, IPv4 (AF_INET) or IPv6 (AF_INET6). - // 1) [in] type: socket type, SOCK_STREAM or SOCK_DGRAM - // Returned value: - // The new UDT socket ID, or INVALID_SOCK. - - UDTSOCKET newSocket(int af, int type); - - // Functionality: - // Create a new UDT connection. - // Parameters: - // 0) [in] listen: the listening UDT socket; - // 1) [in] peer: peer address. - // 2) [in/out] hs: handshake information from peer side (in), negotiated value (out); - // Returned value: - // If the new connection is successfully created: 1 success, 0 already exist, -1 error. - - int newConnection(const UDTSOCKET listen, const sockaddr* peer, CHandShake* hs); - - // Functionality: - // look up the UDT entity according to its ID. - // Parameters: - // 0) [in] u: the UDT socket ID. - // Returned value: - // Pointer to the UDT entity. - - CUDT* lookup(const UDTSOCKET u); - - // Functionality: - // Check the status of the UDT socket. - // Parameters: - // 0) [in] u: the UDT socket ID. - // Returned value: - // UDT socket status, or NONEXIST if not found. - - UDTSTATUS getStatus(const UDTSOCKET u); - - // socket APIs - - int bind(const UDTSOCKET u, const sockaddr* name, int namelen); - int bind(const UDTSOCKET u, UDPSOCKET udpsock); - int listen(const UDTSOCKET u, int backlog); - UDTSOCKET accept(const UDTSOCKET listen, sockaddr* addr, int* addrlen); - int connect(const UDTSOCKET u, const sockaddr* name, int namelen); - int close(const UDTSOCKET u); - int getpeername(const UDTSOCKET u, sockaddr* name, int* namelen); - int getsockname(const UDTSOCKET u, sockaddr* name, int* namelen); - int select(ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout); - int selectEx(const std::vector& fds, std::vector* readfds, std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - int epoll_create(); - int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL); - int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL); - int epoll_remove_usock(const int eid, const UDTSOCKET u); - int epoll_remove_ssock(const int eid, const SYSSOCKET s); - int epoll_wait(const int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds = NULL, std::set* lwfds = NULL); - int epoll_release(const int eid); - - // Functionality: - // record the UDT exception. - // Parameters: - // 0) [in] e: pointer to a UDT exception instance. - // Returned value: - // None. - - void setError(CUDTException* e); - - // Functionality: - // look up the most recent UDT exception. - // Parameters: - // None. - // Returned value: - // pointer to a UDT exception instance. - - CUDTException* getError(); - -private: -// void init(); - -private: - std::map m_Sockets; // stores all the socket structures - - pthread_mutex_t m_ControlLock; // used to synchronize UDT API - - pthread_mutex_t m_IDLock; // used to synchronize ID generation - UDTSOCKET m_SocketID; // seed to generate a new unique socket ID - - std::map > m_PeerRec;// record sockets from peers to avoid repeated connection request, int64_t = (socker_id << 30) + isn - -private: - pthread_key_t m_TLSError; // thread local error record (last error) - #ifndef WIN32 - static void TLSDestroy(void* e) {if (NULL != e) delete (CUDTException*)e;} - #else - std::map m_mTLSRecord; - void checkTLSValue(); - pthread_mutex_t m_TLSLock; - #endif - -private: - void connect_complete(const UDTSOCKET u); - CUDTSocket* locate(const UDTSOCKET u); - CUDTSocket* locate(const sockaddr* peer, const UDTSOCKET id, int32_t isn); - void updateMux(CUDTSocket* s, const sockaddr* addr = NULL, const UDPSOCKET* = NULL); - void updateMux(CUDTSocket* s, const CUDTSocket* ls); - -private: - std::map m_mMultiplexer; // UDP multiplexer - pthread_mutex_t m_MultiplexerLock; - -private: - CCache* m_pCache; // UDT network information cache - -private: - volatile bool m_bClosing; - pthread_mutex_t m_GCStopLock; - pthread_cond_t m_GCStopCond; - - pthread_mutex_t m_InitLock; - int m_iInstanceCount; // number of startup() called by application - bool m_bGCStatus; // if the GC thread is working (true) - - pthread_t m_GCThread; - #ifndef WIN32 - static void* garbageCollect(void*); - #else - static DWORD WINAPI garbageCollect(LPVOID); - #endif - - std::map m_ClosedSockets; // temporarily store closed sockets - - void checkBrokenSockets(); - void removeSocket(const UDTSOCKET u); - -private: - CEPoll m_EPoll; // handling epoll data structures and events - -private: - CUDTUnited(const CUDTUnited&); - CUDTUnited& operator=(const CUDTUnited&); -}; - -#endif diff --git a/vendor/udt4/src/buffer.cpp b/vendor/udt4/src/buffer.cpp deleted file mode 100644 index 327ab76..0000000 --- a/vendor/udt4/src/buffer.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 03/12/2011 -*****************************************************************************/ - -#include -#include -#include "buffer.h" - -using namespace std; - -CSndBuffer::CSndBuffer(int size, int mss): -m_BufLock(), -m_pBlock(NULL), -m_pFirstBlock(NULL), -m_pCurrBlock(NULL), -m_pLastBlock(NULL), -m_pBuffer(NULL), -m_iNextMsgNo(1), -m_iSize(size), -m_iMSS(mss), -m_iCount(0) -{ - // initial physical buffer of "size" - m_pBuffer = new Buffer; - m_pBuffer->m_pcData = new char [m_iSize * m_iMSS]; - m_pBuffer->m_iSize = m_iSize; - m_pBuffer->m_pNext = NULL; - - // circular linked list for out bound packets - m_pBlock = new Block; - Block* pb = m_pBlock; - for (int i = 1; i < m_iSize; ++ i) - { - pb->m_pNext = new Block; - pb->m_iMsgNo = 0; - pb = pb->m_pNext; - } - pb->m_pNext = m_pBlock; - - pb = m_pBlock; - char* pc = m_pBuffer->m_pcData; - for (int i = 0; i < m_iSize; ++ i) - { - pb->m_pcData = pc; - pb = pb->m_pNext; - pc += m_iMSS; - } - - m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock; - - #ifndef WIN32 - pthread_mutex_init(&m_BufLock, NULL); - #else - m_BufLock = CreateMutex(NULL, false, NULL); - #endif -} - -CSndBuffer::~CSndBuffer() -{ - Block* pb = m_pBlock->m_pNext; - while (pb != m_pBlock) - { - Block* temp = pb; - pb = pb->m_pNext; - delete temp; - } - delete m_pBlock; - - while (m_pBuffer != NULL) - { - Buffer* temp = m_pBuffer; - m_pBuffer = m_pBuffer->m_pNext; - delete [] temp->m_pcData; - delete temp; - } - - #ifndef WIN32 - pthread_mutex_destroy(&m_BufLock); - #else - CloseHandle(m_BufLock); - #endif -} - -void CSndBuffer::addBuffer(const char* data, int len, int ttl, bool order) -{ - int size = len / m_iMSS; - if ((len % m_iMSS) != 0) - size ++; - - // dynamically increase sender buffer - while (size + m_iCount >= m_iSize) - increase(); - - uint64_t time = CTimer::getTime(); - int32_t inorder = order; - inorder <<= 29; - - Block* s = m_pLastBlock; - for (int i = 0; i < size; ++ i) - { - int pktlen = len - i * m_iMSS; - if (pktlen > m_iMSS) - pktlen = m_iMSS; - - memcpy(s->m_pcData, data + i * m_iMSS, pktlen); - s->m_iLength = pktlen; - - s->m_iMsgNo = m_iNextMsgNo | inorder; - if (i == 0) - s->m_iMsgNo |= 0x80000000; - if (i == size - 1) - s->m_iMsgNo |= 0x40000000; - - s->m_OriginTime = time; - s->m_iTTL = ttl; - - s = s->m_pNext; - } - m_pLastBlock = s; - - CGuard::enterCS(m_BufLock); - m_iCount += size; - CGuard::leaveCS(m_BufLock); - - m_iNextMsgNo ++; - if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo) - m_iNextMsgNo = 1; -} - -int CSndBuffer::addBufferFromFile(fstream& ifs, int len) -{ - int size = len / m_iMSS; - if ((len % m_iMSS) != 0) - size ++; - - // dynamically increase sender buffer - while (size + m_iCount >= m_iSize) - increase(); - - Block* s = m_pLastBlock; - int total = 0; - for (int i = 0; i < size; ++ i) - { - if (ifs.bad() || ifs.fail() || ifs.eof()) - break; - - int pktlen = len - i * m_iMSS; - if (pktlen > m_iMSS) - pktlen = m_iMSS; - - ifs.read(s->m_pcData, pktlen); - if ((pktlen = ifs.gcount()) <= 0) - break; - - // currently file transfer is only available in streaming mode, message is always in order, ttl = infinite - s->m_iMsgNo = m_iNextMsgNo | 0x20000000; - if (i == 0) - s->m_iMsgNo |= 0x80000000; - if (i == size - 1) - s->m_iMsgNo |= 0x40000000; - - s->m_iLength = pktlen; - s->m_iTTL = -1; - s = s->m_pNext; - - total += pktlen; - } - m_pLastBlock = s; - - CGuard::enterCS(m_BufLock); - m_iCount += size; - CGuard::leaveCS(m_BufLock); - - m_iNextMsgNo ++; - if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo) - m_iNextMsgNo = 1; - - return total; -} - -int CSndBuffer::readData(char** data, int32_t& msgno) -{ - // No data to read - if (m_pCurrBlock == m_pLastBlock) - return 0; - - *data = m_pCurrBlock->m_pcData; - int readlen = m_pCurrBlock->m_iLength; - msgno = m_pCurrBlock->m_iMsgNo; - - m_pCurrBlock = m_pCurrBlock->m_pNext; - - return readlen; -} - -int CSndBuffer::readData(char** data, const int offset, int32_t& msgno, int& msglen) -{ - CGuard bufferguard(m_BufLock); - - Block* p = m_pFirstBlock; - - for (int i = 0; i < offset; ++ i) - p = p->m_pNext; - - if ((p->m_iTTL >= 0) && ((CTimer::getTime() - p->m_OriginTime) / 1000 > (uint64_t)p->m_iTTL)) - { - msgno = p->m_iMsgNo & 0x1FFFFFFF; - - msglen = 1; - p = p->m_pNext; - bool move = false; - while (msgno == (p->m_iMsgNo & 0x1FFFFFFF)) - { - if (p == m_pCurrBlock) - move = true; - p = p->m_pNext; - if (move) - m_pCurrBlock = p; - msglen ++; - } - - return -1; - } - - *data = p->m_pcData; - int readlen = p->m_iLength; - msgno = p->m_iMsgNo; - - return readlen; -} - -void CSndBuffer::ackData(int offset) -{ - CGuard bufferguard(m_BufLock); - - for (int i = 0; i < offset; ++ i) - m_pFirstBlock = m_pFirstBlock->m_pNext; - - m_iCount -= offset; - - CTimer::triggerEvent(); -} - -int CSndBuffer::getCurrBufSize() const -{ - return m_iCount; -} - -void CSndBuffer::increase() -{ - int unitsize = m_pBuffer->m_iSize; - - // new physical buffer - Buffer* nbuf = NULL; - try - { - nbuf = new Buffer; - nbuf->m_pcData = new char [unitsize * m_iMSS]; - } - catch (...) - { - delete nbuf; - throw CUDTException(3, 2, 0); - } - nbuf->m_iSize = unitsize; - nbuf->m_pNext = NULL; - - // insert the buffer at the end of the buffer list - Buffer* p = m_pBuffer; - while (NULL != p->m_pNext) - p = p->m_pNext; - p->m_pNext = nbuf; - - // new packet blocks - Block* nblk = NULL; - try - { - nblk = new Block; - } - catch (...) - { - delete nblk; - throw CUDTException(3, 2, 0); - } - Block* pb = nblk; - for (int i = 1; i < unitsize; ++ i) - { - pb->m_pNext = new Block; - pb = pb->m_pNext; - } - - // insert the new blocks onto the existing one - pb->m_pNext = m_pLastBlock->m_pNext; - m_pLastBlock->m_pNext = nblk; - - pb = nblk; - char* pc = nbuf->m_pcData; - for (int i = 0; i < unitsize; ++ i) - { - pb->m_pcData = pc; - pb = pb->m_pNext; - pc += m_iMSS; - } - - m_iSize += unitsize; -} - -//////////////////////////////////////////////////////////////////////////////// - -CRcvBuffer::CRcvBuffer(CUnitQueue* queue, int bufsize): -m_pUnit(NULL), -m_iSize(bufsize), -m_pUnitQueue(queue), -m_iStartPos(0), -m_iLastAckPos(0), -m_iMaxPos(0), -m_iNotch(0) -{ - m_pUnit = new CUnit* [m_iSize]; - for (int i = 0; i < m_iSize; ++ i) - m_pUnit[i] = NULL; -} - -CRcvBuffer::~CRcvBuffer() -{ - for (int i = 0; i < m_iSize; ++ i) - { - if (NULL != m_pUnit[i]) - { - m_pUnit[i]->m_iFlag = 0; - -- m_pUnitQueue->m_iCount; - } - } - - delete [] m_pUnit; -} - -int CRcvBuffer::addData(CUnit* unit, int offset) -{ - int pos = (m_iLastAckPos + offset) % m_iSize; - if (offset > m_iMaxPos) - m_iMaxPos = offset; - - if (NULL != m_pUnit[pos]) - return -1; - - m_pUnit[pos] = unit; - - unit->m_iFlag = 1; - ++ m_pUnitQueue->m_iCount; - - return 0; -} - -int CRcvBuffer::readBuffer(char* data, int len) -{ - int p = m_iStartPos; - int lastack = m_iLastAckPos; - int rs = len; - - while ((p != lastack) && (rs > 0)) - { - int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch; - if (unitsize > rs) - unitsize = rs; - - memcpy(data, m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize); - data += unitsize; - - if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch)) - { - CUnit* tmp = m_pUnit[p]; - m_pUnit[p] = NULL; - tmp->m_iFlag = 0; - -- m_pUnitQueue->m_iCount; - - if (++ p == m_iSize) - p = 0; - - m_iNotch = 0; - } - else - m_iNotch += rs; - - rs -= unitsize; - } - - m_iStartPos = p; - return len - rs; -} - -int CRcvBuffer::readBufferToFile(fstream& ofs, int len) -{ - int p = m_iStartPos; - int lastack = m_iLastAckPos; - int rs = len; - - while ((p != lastack) && (rs > 0)) - { - int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch; - if (unitsize > rs) - unitsize = rs; - - ofs.write(m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize); - if (ofs.fail()) - break; - - if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch)) - { - CUnit* tmp = m_pUnit[p]; - m_pUnit[p] = NULL; - tmp->m_iFlag = 0; - -- m_pUnitQueue->m_iCount; - - if (++ p == m_iSize) - p = 0; - - m_iNotch = 0; - } - else - m_iNotch += rs; - - rs -= unitsize; - } - - m_iStartPos = p; - - return len - rs; -} - -void CRcvBuffer::ackData(int len) -{ - m_iLastAckPos = (m_iLastAckPos + len) % m_iSize; - m_iMaxPos -= len; - if (m_iMaxPos < 0) - m_iMaxPos = 0; - - CTimer::triggerEvent(); -} - -int CRcvBuffer::getAvailBufSize() const -{ - // One slot must be empty in order to tell the difference between "empty buffer" and "full buffer" - return m_iSize - getRcvDataSize() - 1; -} - -int CRcvBuffer::getRcvDataSize() const -{ - if (m_iLastAckPos >= m_iStartPos) - return m_iLastAckPos - m_iStartPos; - - return m_iSize + m_iLastAckPos - m_iStartPos; -} - -void CRcvBuffer::dropMsg(int32_t msgno) -{ - for (int i = m_iStartPos, n = (m_iLastAckPos + m_iMaxPos) % m_iSize; i != n; i = (i + 1) % m_iSize) - if ((NULL != m_pUnit[i]) && (msgno == m_pUnit[i]->m_Packet.m_iMsgNo)) - m_pUnit[i]->m_iFlag = 3; -} - -int CRcvBuffer::readMsg(char* data, int len) -{ - int p, q; - bool passack; - if (!scanMsg(p, q, passack)) - return 0; - - int rs = len; - while (p != (q + 1) % m_iSize) - { - int unitsize = m_pUnit[p]->m_Packet.getLength(); - if ((rs >= 0) && (unitsize > rs)) - unitsize = rs; - - if (unitsize > 0) - { - memcpy(data, m_pUnit[p]->m_Packet.m_pcData, unitsize); - data += unitsize; - rs -= unitsize; - } - - if (!passack) - { - CUnit* tmp = m_pUnit[p]; - m_pUnit[p] = NULL; - tmp->m_iFlag = 0; - -- m_pUnitQueue->m_iCount; - } - else - m_pUnit[p]->m_iFlag = 2; - - if (++ p == m_iSize) - p = 0; - } - - if (!passack) - m_iStartPos = (q + 1) % m_iSize; - - return len - rs; -} - -int CRcvBuffer::getRcvMsgNum() -{ - int p, q; - bool passack; - return scanMsg(p, q, passack) ? 1 : 0; -} - -bool CRcvBuffer::scanMsg(int& p, int& q, bool& passack) -{ - // empty buffer - if ((m_iStartPos == m_iLastAckPos) && (m_iMaxPos <= 0)) - return false; - - //skip all bad msgs at the beginning - while (m_iStartPos != m_iLastAckPos) - { - if (NULL == m_pUnit[m_iStartPos]) - { - if (++ m_iStartPos == m_iSize) - m_iStartPos = 0; - continue; - } - - if ((1 == m_pUnit[m_iStartPos]->m_iFlag) && (m_pUnit[m_iStartPos]->m_Packet.getMsgBoundary() > 1)) - { - bool good = true; - - // look ahead for the whole message - for (int i = m_iStartPos; i != m_iLastAckPos;) - { - if ((NULL == m_pUnit[i]) || (1 != m_pUnit[i]->m_iFlag)) - { - good = false; - break; - } - - if ((m_pUnit[i]->m_Packet.getMsgBoundary() == 1) || (m_pUnit[i]->m_Packet.getMsgBoundary() == 3)) - break; - - if (++ i == m_iSize) - i = 0; - } - - if (good) - break; - } - - CUnit* tmp = m_pUnit[m_iStartPos]; - m_pUnit[m_iStartPos] = NULL; - tmp->m_iFlag = 0; - -- m_pUnitQueue->m_iCount; - - if (++ m_iStartPos == m_iSize) - m_iStartPos = 0; - } - - p = -1; // message head - q = m_iStartPos; // message tail - passack = m_iStartPos == m_iLastAckPos; - bool found = false; - - // looking for the first message - for (int i = 0, n = m_iMaxPos + getRcvDataSize(); i <= n; ++ i) - { - if ((NULL != m_pUnit[q]) && (1 == m_pUnit[q]->m_iFlag)) - { - switch (m_pUnit[q]->m_Packet.getMsgBoundary()) - { - case 3: // 11 - p = q; - found = true; - break; - - case 2: // 10 - p = q; - break; - - case 1: // 01 - if (p != -1) - found = true; - } - } - else - { - // a hole in this message, not valid, restart search - p = -1; - } - - if (found) - { - // the msg has to be ack'ed or it is allowed to read out of order, and was not read before - if (!passack || !m_pUnit[q]->m_Packet.getMsgOrderFlag()) - break; - - found = false; - } - - if (++ q == m_iSize) - q = 0; - - if (q == m_iLastAckPos) - passack = true; - } - - // no msg found - if (!found) - { - // if the message is larger than the receiver buffer, return part of the message - if ((p != -1) && ((q + 1) % m_iSize == p)) - found = true; - } - - return found; -} diff --git a/vendor/udt4/src/buffer.h b/vendor/udt4/src/buffer.h deleted file mode 100644 index 4377e79..0000000 --- a/vendor/udt4/src/buffer.h +++ /dev/null @@ -1,275 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2009 -*****************************************************************************/ - -#ifndef __UDT_BUFFER_H__ -#define __UDT_BUFFER_H__ - - -#include "udt.h" -#include "list.h" -#include "queue.h" -#include - -class CSndBuffer -{ -public: - CSndBuffer(int size = 32, int mss = 1500); - ~CSndBuffer(); - - // Functionality: - // Insert a user buffer into the sending list. - // Parameters: - // 0) [in] data: pointer to the user data block. - // 1) [in] len: size of the block. - // 2) [in] ttl: time to live in milliseconds - // 3) [in] order: if the block should be delivered in order, for DGRAM only - // Returned value: - // None. - - void addBuffer(const char* data, int len, int ttl = -1, bool order = false); - - // Functionality: - // Read a block of data from file and insert it into the sending list. - // Parameters: - // 0) [in] ifs: input file stream. - // 1) [in] len: size of the block. - // Returned value: - // actual size of data added from the file. - - int addBufferFromFile(std::fstream& ifs, int len); - - // Functionality: - // Find data position to pack a DATA packet from the furthest reading point. - // Parameters: - // 0) [out] data: the pointer to the data position. - // 1) [out] msgno: message number of the packet. - // Returned value: - // Actual length of data read. - - int readData(char** data, int32_t& msgno); - - // Functionality: - // Find data position to pack a DATA packet for a retransmission. - // Parameters: - // 0) [out] data: the pointer to the data position. - // 1) [in] offset: offset from the last ACK point. - // 2) [out] msgno: message number of the packet. - // 3) [out] msglen: length of the message - // Returned value: - // Actual length of data read. - - int readData(char** data, const int offset, int32_t& msgno, int& msglen); - - // Functionality: - // Update the ACK point and may release/unmap/return the user data according to the flag. - // Parameters: - // 0) [in] offset: number of packets acknowledged. - // Returned value: - // None. - - void ackData(int offset); - - // Functionality: - // Read size of data still in the sending list. - // Parameters: - // None. - // Returned value: - // Current size of the data in the sending list. - - int getCurrBufSize() const; - -private: - void increase(); - -private: - pthread_mutex_t m_BufLock; // used to synchronize buffer operation - - struct Block - { - char* m_pcData; // pointer to the data block - int m_iLength; // length of the block - - int32_t m_iMsgNo; // message number - uint64_t m_OriginTime; // original request time - int m_iTTL; // time to live (milliseconds) - - Block* m_pNext; // next block - } *m_pBlock, *m_pFirstBlock, *m_pCurrBlock, *m_pLastBlock; - - // m_pBlock: The head pointer - // m_pFirstBlock: The first block - // m_pCurrBlock: The current block - // m_pLastBlock: The last block (if first == last, buffer is empty) - - struct Buffer - { - char* m_pcData; // buffer - int m_iSize; // size - Buffer* m_pNext; // next buffer - } *m_pBuffer; // physical buffer - - int32_t m_iNextMsgNo; // next message number - - int m_iSize; // buffer size (number of packets) - int m_iMSS; // maximum seqment/packet size - - int m_iCount; // number of used blocks - -private: - CSndBuffer(const CSndBuffer&); - CSndBuffer& operator=(const CSndBuffer&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CRcvBuffer -{ -public: - CRcvBuffer(CUnitQueue* queue, int bufsize = 65536); - ~CRcvBuffer(); - - // Functionality: - // Write data into the buffer. - // Parameters: - // 0) [in] unit: pointer to a data unit containing new packet - // 1) [in] offset: offset from last ACK point. - // Returned value: - // 0 is success, -1 if data is repeated. - - int addData(CUnit* unit, int offset); - - // Functionality: - // Read data into a user buffer. - // Parameters: - // 0) [in] data: pointer to user buffer. - // 1) [in] len: length of user buffer. - // Returned value: - // size of data read. - - int readBuffer(char* data, int len); - - // Functionality: - // Read data directly into file. - // Parameters: - // 0) [in] file: C++ file stream. - // 1) [in] len: expected length of data to write into the file. - // Returned value: - // size of data read. - - int readBufferToFile(std::fstream& ofs, int len); - - // Functionality: - // Update the ACK point of the buffer. - // Parameters: - // 0) [in] len: size of data to be acknowledged. - // Returned value: - // 1 if a user buffer is fulfilled, otherwise 0. - - void ackData(int len); - - // Functionality: - // Query how many buffer space left for data receiving. - // Parameters: - // None. - // Returned value: - // size of available buffer space (including user buffer) for data receiving. - - int getAvailBufSize() const; - - // Functionality: - // Query how many data has been continuously received (for reading). - // Parameters: - // None. - // Returned value: - // size of valid (continous) data for reading. - - int getRcvDataSize() const; - - // Functionality: - // mark the message to be dropped from the message list. - // Parameters: - // 0) [in] msgno: message nuumer. - // Returned value: - // None. - - void dropMsg(int32_t msgno); - - // Functionality: - // read a message. - // Parameters: - // 0) [out] data: buffer to write the message into. - // 1) [in] len: size of the buffer. - // Returned value: - // actuall size of data read. - - int readMsg(char* data, int len); - - // Functionality: - // Query how many messages are available now. - // Parameters: - // None. - // Returned value: - // number of messages available for recvmsg. - - int getRcvMsgNum(); - -private: - bool scanMsg(int& start, int& end, bool& passack); - -private: - CUnit** m_pUnit; // pointer to the protocol buffer - int m_iSize; // size of the protocol buffer - CUnitQueue* m_pUnitQueue; // the shared unit queue - - int m_iStartPos; // the head position for I/O (inclusive) - int m_iLastAckPos; // the last ACKed position (exclusive) - // EMPTY: m_iStartPos = m_iLastAckPos FULL: m_iStartPos = m_iLastAckPos + 1 - int m_iMaxPos; // the furthest data position - - int m_iNotch; // the starting read point of the first unit - -private: - CRcvBuffer(); - CRcvBuffer(const CRcvBuffer&); - CRcvBuffer& operator=(const CRcvBuffer&); -}; - - -#endif diff --git a/vendor/udt4/src/cache.cpp b/vendor/udt4/src/cache.cpp deleted file mode 100644 index ea0aad1..0000000 --- a/vendor/udt4/src/cache.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2009 -*****************************************************************************/ - -#ifdef WIN32 - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#endif - -#include -#include "cache.h" -#include "core.h" - -using namespace std; - -CInfoBlock& CInfoBlock::operator=(const CInfoBlock& obj) -{ - std::copy(obj.m_piIP, obj.m_piIP + 3, m_piIP); - m_iIPversion = obj.m_iIPversion; - m_ullTimeStamp = obj.m_ullTimeStamp; - m_iRTT = obj.m_iRTT; - m_iBandwidth = obj.m_iBandwidth; - m_iLossRate = obj.m_iLossRate; - m_iReorderDistance = obj.m_iReorderDistance; - m_dInterval = obj.m_dInterval; - m_dCWnd = obj.m_dCWnd; - - return *this; -} - -bool CInfoBlock::operator==(const CInfoBlock& obj) -{ - if (m_iIPversion != obj.m_iIPversion) - return false; - - else if (m_iIPversion == AF_INET) - return (m_piIP[0] == obj.m_piIP[0]); - - for (int i = 0; i < 4; ++ i) - { - if (m_piIP[i] != obj.m_piIP[i]) - return false; - } - - return true; -} - -CInfoBlock* CInfoBlock::clone() -{ - CInfoBlock* obj = new CInfoBlock; - - std::copy(m_piIP, m_piIP + 3, obj->m_piIP); - obj->m_iIPversion = m_iIPversion; - obj->m_ullTimeStamp = m_ullTimeStamp; - obj->m_iRTT = m_iRTT; - obj->m_iBandwidth = m_iBandwidth; - obj->m_iLossRate = m_iLossRate; - obj->m_iReorderDistance = m_iReorderDistance; - obj->m_dInterval = m_dInterval; - obj->m_dCWnd = m_dCWnd; - - return obj; -} - -int CInfoBlock::getKey() -{ - if (m_iIPversion == AF_INET) - return m_piIP[0]; - - return m_piIP[0] + m_piIP[1] + m_piIP[2] + m_piIP[3]; -} - -void CInfoBlock::convert(const sockaddr* addr, int ver, uint32_t ip[]) -{ - if (ver == AF_INET) - { - ip[0] = ((sockaddr_in*)addr)->sin_addr.s_addr; - ip[1] = ip[2] = ip[3] = 0; - } - else - { - memcpy((char*)ip, (char*)((sockaddr_in6*)addr)->sin6_addr.s6_addr, 16); - } -} diff --git a/vendor/udt4/src/cache.h b/vendor/udt4/src/cache.h deleted file mode 100644 index 22d9624..0000000 --- a/vendor/udt4/src/cache.h +++ /dev/null @@ -1,293 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/27/2011 -*****************************************************************************/ - -#ifndef __UDT_CACHE_H__ -#define __UDT_CACHE_H__ - -#include -#include - -#include "common.h" -#include "udt.h" - -class CCacheItem -{ -public: - virtual ~CCacheItem() {} - -public: - virtual CCacheItem& operator=(const CCacheItem&) = 0; - - // The "==" operator SHOULD only compare key values. - virtual bool operator==(const CCacheItem&) = 0; - - // Functionality: - // get a deep copy clone of the current item - // Parameters: - // None. - // Returned value: - // Pointer to the new item, or NULL if failed. - - virtual CCacheItem* clone() = 0; - - // Functionality: - // get a random key value between 0 and MAX_INT to be used for the hash in cache - // Parameters: - // None. - // Returned value: - // A random hash key. - - virtual int getKey() = 0; - - // If there is any shared resources between the cache item and its clone, - // the shared resource should be released by this function. - virtual void release() {} -}; - -template class CCache -{ -public: - CCache(int size = 1024): - m_iMaxSize(size), - m_iHashSize(size * 3), - m_iCurrSize(0) - { - m_vHashPtr.resize(m_iHashSize); - CGuard::createMutex(m_Lock); - } - - ~CCache() - { - clear(); - CGuard::releaseMutex(m_Lock); - } - -public: - // Functionality: - // find the matching item in the cache. - // Parameters: - // 0) [in/out] data: storage for the retrieved item; initially it must carry the key information - // Returned value: - // 0 if found a match, otherwise -1. - - int lookup(T* data) - { - CGuard cacheguard(m_Lock); - - int key = data->getKey(); - if (key < 0) - return -1; - if (key >= m_iMaxSize) - key %= m_iHashSize; - - const ItemPtrList& item_list = m_vHashPtr[key]; - for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i) - { - if (*data == ***i) - { - // copy the cached info - *data = ***i; - return 0; - } - } - - return -1; - } - - // Functionality: - // update an item in the cache, or insert one if it doesn't exist; oldest item may be removed - // Parameters: - // 0) [in] data: the new item to updated/inserted to the cache - // Returned value: - // 0 if success, otherwise -1. - - int update(T* data) - { - CGuard cacheguard(m_Lock); - - int key = data->getKey(); - if (key < 0) - return -1; - if (key >= m_iMaxSize) - key %= m_iHashSize; - - T* curr = NULL; - - ItemPtrList& item_list = m_vHashPtr[key]; - for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) - { - if (*data == ***i) - { - // update the existing entry with the new value - ***i = *data; - curr = **i; - - // remove the current entry - m_StorageList.erase(*i); - item_list.erase(i); - - // re-insert to the front - m_StorageList.push_front(curr); - item_list.push_front(m_StorageList.begin()); - - return 0; - } - } - - // create new entry and insert to front - curr = data->clone(); - m_StorageList.push_front(curr); - item_list.push_front(m_StorageList.begin()); - - ++ m_iCurrSize; - if (m_iCurrSize >= m_iMaxSize) - { - // Cache overflow, remove oldest entry. - T* last_data = m_StorageList.back(); - int last_key = last_data->getKey() % m_iHashSize; - - item_list = m_vHashPtr[last_key]; - for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i) - { - if (*last_data == ***i) - { - item_list.erase(i); - break; - } - } - - last_data->release(); - delete last_data; - m_StorageList.pop_back(); - -- m_iCurrSize; - } - - return 0; - } - - // Functionality: - // Specify the cache size (i.e., max number of items). - // Parameters: - // 0) [in] size: max cache size. - // Returned value: - // None. - - void setSizeLimit(int size) - { - m_iMaxSize = size; - m_iHashSize = size * 3; - m_vHashPtr.resize(m_iHashSize); - } - - // Functionality: - // Clear all entries in the cache, restore to initialization state. - // Parameters: - // None. - // Returned value: - // None. - - void clear() - { - for (typename std::list::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i) - { - (*i)->release(); - delete *i; - } - m_StorageList.clear(); - for (typename std::vector::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i) - i->clear(); - m_iCurrSize = 0; - } - -private: - std::list m_StorageList; - typedef typename std::list::iterator ItemPtr; - typedef std::list ItemPtrList; - std::vector m_vHashPtr; - - int m_iMaxSize; - int m_iHashSize; - int m_iCurrSize; - - pthread_mutex_t m_Lock; - -private: - CCache(const CCache&); - CCache& operator=(const CCache&); -}; - - -class CInfoBlock -{ -public: - uint32_t m_piIP[4]; // IP address, machine read only, not human readable format - int m_iIPversion; // IP version - uint64_t m_ullTimeStamp; // last update time - int m_iRTT; // RTT - int m_iBandwidth; // estimated bandwidth - int m_iLossRate; // average loss rate - int m_iReorderDistance; // packet reordering distance - double m_dInterval; // inter-packet time, congestion control - double m_dCWnd; // congestion window size, congestion control - -public: - virtual ~CInfoBlock() {} - virtual CInfoBlock& operator=(const CInfoBlock& obj); - virtual bool operator==(const CInfoBlock& obj); - virtual CInfoBlock* clone(); - virtual int getKey(); - virtual void release() {} - -public: - - // Functionality: - // convert sockaddr structure to an integer array - // Parameters: - // 0) [in] addr: network address - // 1) [in] ver: IP version - // 2) [out] ip: the result machine readable IP address in integer array - // Returned value: - // None. - - static void convert(const sockaddr* addr, int ver, uint32_t ip[]); -}; - - -#endif diff --git a/vendor/udt4/src/ccc.cpp b/vendor/udt4/src/ccc.cpp deleted file mode 100644 index 048b7ec..0000000 --- a/vendor/udt4/src/ccc.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 02/21/2013 -*****************************************************************************/ - - -#include "core.h" -#include "ccc.h" -#include -#include - -CCC::CCC(): -m_iSYNInterval(CUDT::m_iSYNInterval), -m_dPktSndPeriod(1.0), -m_dCWndSize(16.0), -m_iBandwidth(), -m_dMaxCWndSize(), -m_iMSS(), -m_iSndCurrSeqNo(), -m_iRcvRate(), -m_iRTT(), -m_pcParam(NULL), -m_iPSize(0), -m_UDT(), -m_iACKPeriod(0), -m_iACKInterval(0), -m_bUserDefinedRTO(false), -m_iRTO(-1), -m_PerfInfo() -{ -} - -CCC::~CCC() -{ - delete [] m_pcParam; -} - -void CCC::setACKTimer(int msINT) -{ - m_iACKPeriod = msINT > m_iSYNInterval ? m_iSYNInterval : msINT; -} - -void CCC::setACKInterval(int pktINT) -{ - m_iACKInterval = pktINT; -} - -void CCC::setRTO(int usRTO) -{ - m_bUserDefinedRTO = true; - m_iRTO = usRTO; -} - -void CCC::sendCustomMsg(CPacket& pkt) const -{ - CUDT* u = CUDT::getUDTHandle(m_UDT); - - if (NULL != u) - { - pkt.m_iID = u->m_PeerID; - u->m_pSndQueue->sendto(u->m_pPeerAddr, pkt); - } -} - -const CPerfMon* CCC::getPerfInfo() -{ - try - { - CUDT* u = CUDT::getUDTHandle(m_UDT); - if (NULL != u) - u->sample(&m_PerfInfo, false); - } - catch (...) - { - return NULL; - } - - return &m_PerfInfo; -} - -void CCC::setMSS(int mss) -{ - m_iMSS = mss; -} - -void CCC::setBandwidth(int bw) -{ - m_iBandwidth = bw; -} - -void CCC::setSndCurrSeqNo(int32_t seqno) -{ - m_iSndCurrSeqNo = seqno; -} - -void CCC::setRcvRate(int rcvrate) -{ - m_iRcvRate = rcvrate; -} - -void CCC::setMaxCWndSize(int cwnd) -{ - m_dMaxCWndSize = cwnd; -} - -void CCC::setRTT(int rtt) -{ - m_iRTT = rtt; -} - -void CCC::setUserParam(const char* param, int size) -{ - delete [] m_pcParam; - m_pcParam = new char[size]; - memcpy(m_pcParam, param, size); - m_iPSize = size; -} - -// -CUDTCC::CUDTCC(): -m_iRCInterval(), -m_LastRCTime(), -m_bSlowStart(), -m_iLastAck(), -m_bLoss(), -m_iLastDecSeq(), -m_dLastDecPeriod(), -m_iNAKCount(), -m_iDecRandom(), -m_iAvgNAKNum(), -m_iDecCount() -{ -} - -void CUDTCC::init() -{ - m_iRCInterval = m_iSYNInterval; - m_LastRCTime = CTimer::getTime(); - setACKTimer(m_iRCInterval); - - m_bSlowStart = true; - m_iLastAck = m_iSndCurrSeqNo; - m_bLoss = false; - m_iLastDecSeq = CSeqNo::decseq(m_iLastAck); - m_dLastDecPeriod = 1; - m_iAvgNAKNum = 0; - m_iNAKCount = 0; - m_iDecRandom = 1; - - m_dCWndSize = 16; - m_dPktSndPeriod = 1; -} - -void CUDTCC::onACK(int32_t ack) -{ - int64_t B = 0; - double inc = 0; - // Note: 1/24/2012 - // The minimum increase parameter is increased from "1.0 / m_iMSS" to 0.01 - // because the original was too small and caused sending rate to stay at low level - // for long time. - const double min_inc = 0.01; - - uint64_t currtime = CTimer::getTime(); - if (currtime - m_LastRCTime < (uint64_t)m_iRCInterval) - return; - - m_LastRCTime = currtime; - - if (m_bSlowStart) - { - m_dCWndSize += CSeqNo::seqlen(m_iLastAck, ack); - m_iLastAck = ack; - - if (m_dCWndSize > m_dMaxCWndSize) - { - m_bSlowStart = false; - if (m_iRcvRate > 0) - m_dPktSndPeriod = 1000000.0 / m_iRcvRate; - else - m_dPktSndPeriod = (m_iRTT + m_iRCInterval) / m_dCWndSize; - } - } - else - m_dCWndSize = m_iRcvRate / 1000000.0 * (m_iRTT + m_iRCInterval) + 16; - - // During Slow Start, no rate increase - if (m_bSlowStart) - return; - - if (m_bLoss) - { - m_bLoss = false; - return; - } - - B = (int64_t)(m_iBandwidth - 1000000.0 / m_dPktSndPeriod); - if ((m_dPktSndPeriod > m_dLastDecPeriod) && ((m_iBandwidth / 9) < B)) - B = m_iBandwidth / 9; - if (B <= 0) - inc = min_inc; - else - { - // inc = max(10 ^ ceil(log10( B * MSS * 8 ) * Beta / MSS, 1/MSS) - // Beta = 1.5 * 10^(-6) - - inc = pow(10.0, ceil(log10(B * m_iMSS * 8.0))) * 0.0000015 / m_iMSS; - - if (inc < min_inc) - inc = min_inc; - } - - m_dPktSndPeriod = (m_dPktSndPeriod * m_iRCInterval) / (m_dPktSndPeriod * inc + m_iRCInterval); -} - -void CUDTCC::onLoss(const int32_t* losslist, int) -{ - //Slow Start stopped, if it hasn't yet - if (m_bSlowStart) - { - m_bSlowStart = false; - if (m_iRcvRate > 0) - { - // Set the sending rate to the receiving rate. - m_dPktSndPeriod = 1000000.0 / m_iRcvRate; - return; - } - // If no receiving rate is observed, we have to compute the sending - // rate according to the current window size, and decrease it - // using the method below. - m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); - } - - m_bLoss = true; - - if (CSeqNo::seqcmp(losslist[0] & 0x7FFFFFFF, m_iLastDecSeq) > 0) - { - m_dLastDecPeriod = m_dPktSndPeriod; - m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); - - m_iAvgNAKNum = (int)ceil(m_iAvgNAKNum * 0.875 + m_iNAKCount * 0.125); - m_iNAKCount = 1; - m_iDecCount = 1; - - m_iLastDecSeq = m_iSndCurrSeqNo; - - // remove global synchronization using randomization - srand(m_iLastDecSeq); - m_iDecRandom = (int)ceil(m_iAvgNAKNum * (double(rand()) / RAND_MAX)); - if (m_iDecRandom < 1) - m_iDecRandom = 1; - } - else if ((m_iDecCount ++ < 5) && (0 == (++ m_iNAKCount % m_iDecRandom))) - { - // 0.875^5 = 0.51, rate should not be decreased by more than half within a congestion period - m_dPktSndPeriod = ceil(m_dPktSndPeriod * 1.125); - m_iLastDecSeq = m_iSndCurrSeqNo; - } -} - -void CUDTCC::onTimeout() -{ - if (m_bSlowStart) - { - m_bSlowStart = false; - if (m_iRcvRate > 0) - m_dPktSndPeriod = 1000000.0 / m_iRcvRate; - else - m_dPktSndPeriod = m_dCWndSize / (m_iRTT + m_iRCInterval); - } - else - { - /* - m_dLastDecPeriod = m_dPktSndPeriod; - m_dPktSndPeriod = ceil(m_dPktSndPeriod * 2); - m_iLastDecSeq = m_iLastAck; - */ - } -} diff --git a/vendor/udt4/src/ccc.h b/vendor/udt4/src/ccc.h deleted file mode 100644 index 5585975..0000000 --- a/vendor/udt4/src/ccc.h +++ /dev/null @@ -1,278 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 02/28/2012 -*****************************************************************************/ - - -#ifndef __UDT_CCC_H__ -#define __UDT_CCC_H__ - - -#include "udt.h" -#include "packet.h" - - -class UDT_API CCC -{ -friend class CUDT; - -public: - CCC(); - virtual ~CCC(); - -private: - CCC(const CCC&); - CCC& operator=(const CCC&) {return *this;} - -public: - - // Functionality: - // Callback function to be called (only) at the start of a UDT connection. - // note that this is different from CCC(), which is always called. - // Parameters: - // None. - // Returned value: - // None. - - virtual void init() {} - - // Functionality: - // Callback function to be called when a UDT connection is closed. - // Parameters: - // None. - // Returned value: - // None. - - virtual void close() {} - - // Functionality: - // Callback function to be called when an ACK packet is received. - // Parameters: - // 0) [in] ackno: the data sequence number acknowledged by this ACK. - // Returned value: - // None. - - virtual void onACK(int32_t) {} - - // Functionality: - // Callback function to be called when a loss report is received. - // Parameters: - // 0) [in] losslist: list of sequence number of packets, in the format describled in packet.cpp. - // 1) [in] size: length of the loss list. - // Returned value: - // None. - - virtual void onLoss(const int32_t*, int) {} - - // Functionality: - // Callback function to be called when a timeout event occurs. - // Parameters: - // None. - // Returned value: - // None. - - virtual void onTimeout() {} - - // Functionality: - // Callback function to be called when a data is sent. - // Parameters: - // 0) [in] seqno: the data sequence number. - // 1) [in] size: the payload size. - // Returned value: - // None. - - virtual void onPktSent(const CPacket*) {} - - // Functionality: - // Callback function to be called when a data is received. - // Parameters: - // 0) [in] seqno: the data sequence number. - // 1) [in] size: the payload size. - // Returned value: - // None. - - virtual void onPktReceived(const CPacket*) {} - - // Functionality: - // Callback function to Process a user defined packet. - // Parameters: - // 0) [in] pkt: the user defined packet. - // Returned value: - // None. - - virtual void processCustomMsg(const CPacket*) {} - -protected: - - // Functionality: - // Set periodical acknowldging and the ACK period. - // Parameters: - // 0) [in] msINT: the period to send an ACK. - // Returned value: - // None. - - void setACKTimer(int msINT); - - // Functionality: - // Set packet-based acknowldging and the number of packets to send an ACK. - // Parameters: - // 0) [in] pktINT: the number of packets to send an ACK. - // Returned value: - // None. - - void setACKInterval(int pktINT); - - // Functionality: - // Set RTO value. - // Parameters: - // 0) [in] msRTO: RTO in macroseconds. - // Returned value: - // None. - - void setRTO(int usRTO); - - // Functionality: - // Send a user defined control packet. - // Parameters: - // 0) [in] pkt: user defined packet. - // Returned value: - // None. - - void sendCustomMsg(CPacket& pkt) const; - - // Functionality: - // retrieve performance information. - // Parameters: - // None. - // Returned value: - // Pointer to a performance info structure. - - const CPerfMon* getPerfInfo(); - - // Functionality: - // Set user defined parameters. - // Parameters: - // 0) [in] param: the paramters in one buffer. - // 1) [in] size: the size of the buffer. - // Returned value: - // None. - - void setUserParam(const char* param, int size); - -private: - void setMSS(int mss); - void setMaxCWndSize(int cwnd); - void setBandwidth(int bw); - void setSndCurrSeqNo(int32_t seqno); - void setRcvRate(int rcvrate); - void setRTT(int rtt); - -protected: - const int32_t& m_iSYNInterval; // UDT constant parameter, SYN - - double m_dPktSndPeriod; // Packet sending period, in microseconds - double m_dCWndSize; // Congestion window size, in packets - - int m_iBandwidth; // estimated bandwidth, packets per second - double m_dMaxCWndSize; // maximum cwnd size, in packets - - int m_iMSS; // Maximum Packet Size, including all packet headers - int32_t m_iSndCurrSeqNo; // current maximum seq no sent out - int m_iRcvRate; // packet arrive rate at receiver side, packets per second - int m_iRTT; // current estimated RTT, microsecond - - char* m_pcParam; // user defined parameter - int m_iPSize; // size of m_pcParam - -private: - UDTSOCKET m_UDT; // The UDT entity that this congestion control algorithm is bound to - - int m_iACKPeriod; // Periodical timer to send an ACK, in milliseconds - int m_iACKInterval; // How many packets to send one ACK, in packets - - bool m_bUserDefinedRTO; // if the RTO value is defined by users - int m_iRTO; // RTO value, microseconds - - CPerfMon m_PerfInfo; // protocol statistics information -}; - -class CCCVirtualFactory -{ -public: - virtual ~CCCVirtualFactory() {} - - virtual CCC* create() = 0; - virtual CCCVirtualFactory* clone() = 0; -}; - -template -class CCCFactory: public CCCVirtualFactory -{ -public: - virtual ~CCCFactory() {} - - virtual CCC* create() {return new T;} - virtual CCCVirtualFactory* clone() {return new CCCFactory;} -}; - -class CUDTCC: public CCC -{ -public: - CUDTCC(); - -public: - virtual void init(); - virtual void onACK(int32_t); - virtual void onLoss(const int32_t*, int); - virtual void onTimeout(); - -private: - int m_iRCInterval; // UDT Rate control interval - uint64_t m_LastRCTime; // last rate increase time - bool m_bSlowStart; // if in slow start phase - int32_t m_iLastAck; // last ACKed seq no - bool m_bLoss; // if loss happened since last rate increase - int32_t m_iLastDecSeq; // max pkt seq no sent out when last decrease happened - double m_dLastDecPeriod; // value of pktsndperiod when last decrease happened - int m_iNAKCount; // NAK counter - int m_iDecRandom; // random threshold on decrease by number of loss events - int m_iAvgNAKNum; // average number of NAKs per congestion - int m_iDecCount; // number of decreases in a congestion epoch -}; - -#endif diff --git a/vendor/udt4/src/channel.cpp b/vendor/udt4/src/channel.cpp deleted file mode 100644 index 7b010f0..0000000 --- a/vendor/udt4/src/channel.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -****************************************************************************/ - -/**************************************************************************** -written by - Yunhong Gu, last updated 01/27/2011 -*****************************************************************************/ - -#ifndef WIN32 - #include - #include - #include - #include - #include - #include - #include -#else - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#endif -#include "channel.h" -#include "packet.h" - -#ifdef WIN32 - #define socklen_t int -#endif - -#ifndef WIN32 - #define NET_ERROR errno -#else - #define NET_ERROR WSAGetLastError() -#endif - - -CChannel::CChannel(): -m_iIPversion(AF_INET), -m_iSockAddrSize(sizeof(sockaddr_in)), -m_iSocket(), -m_iSndBufSize(65536), -m_iRcvBufSize(65536) -{ -} - -CChannel::CChannel(int version): -m_iIPversion(version), -m_iSocket(), -m_iSndBufSize(65536), -m_iRcvBufSize(65536) -{ - m_iSockAddrSize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); -} - -CChannel::~CChannel() -{ -} - -void CChannel::open(const sockaddr* addr) -{ - // construct an socket - m_iSocket = ::socket(m_iIPversion, SOCK_DGRAM, 0); - - #ifdef WIN32 - if (INVALID_SOCKET == m_iSocket) - #else - if (m_iSocket < 0) - #endif - throw CUDTException(1, 0, NET_ERROR); - - if (NULL != addr) - { - socklen_t namelen = m_iSockAddrSize; - - if (0 != ::bind(m_iSocket, addr, namelen)) - throw CUDTException(1, 3, NET_ERROR); - } - else - { - //sendto or WSASendTo will also automatically bind the socket - addrinfo hints; - addrinfo* res; - - memset(&hints, 0, sizeof(struct addrinfo)); - - hints.ai_flags = AI_PASSIVE; - hints.ai_family = m_iIPversion; - hints.ai_socktype = SOCK_DGRAM; - - if (0 != ::getaddrinfo(NULL, "0", &hints, &res)) - throw CUDTException(1, 3, NET_ERROR); - - if (0 != ::bind(m_iSocket, res->ai_addr, res->ai_addrlen)) - throw CUDTException(1, 3, NET_ERROR); - - ::freeaddrinfo(res); - } - - setUDPSockOpt(); -} - -void CChannel::open(UDPSOCKET udpsock) -{ - m_iSocket = udpsock; - setUDPSockOpt(); -} - -void CChannel::setUDPSockOpt() -{ - #if defined(BSD) || defined(OSX) - // BSD system will fail setsockopt if the requested buffer size exceeds system maximum value - int maxsize = 64000; - if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) - ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&maxsize, sizeof(int)); - if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int))) - ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&maxsize, sizeof(int)); - #else - // for other systems, if requested is greated than maximum, the maximum value will be automactally used - if ((0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char*)&m_iRcvBufSize, sizeof(int))) || - (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char*)&m_iSndBufSize, sizeof(int)))) - throw CUDTException(1, 3, NET_ERROR); - #endif - - timeval tv; - tv.tv_sec = 0; - #if defined (BSD) || defined (OSX) - // Known BSD bug as the day I wrote this code. - // A small time out value will cause the socket to block forever. - tv.tv_usec = 10000; - #else - tv.tv_usec = 100; - #endif - - #ifdef UNIX - // Set non-blocking I/O - // UNIX does not support SO_RCVTIMEO - int opts = ::fcntl(m_iSocket, F_GETFL); - if (-1 == ::fcntl(m_iSocket, F_SETFL, opts | O_NONBLOCK)) - throw CUDTException(1, 3, NET_ERROR); - #elif WIN32 - DWORD ot = 1; //milliseconds - if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&ot, sizeof(DWORD))) - throw CUDTException(1, 3, NET_ERROR); - #else - // Set receiving time-out value - if (0 != ::setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(timeval))) - throw CUDTException(1, 3, NET_ERROR); - #endif -} - -void CChannel::close() const -{ - #ifndef WIN32 - ::close(m_iSocket); - #else - ::closesocket(m_iSocket); - #endif -} - -int CChannel::getSndBufSize() -{ - socklen_t size = sizeof(socklen_t); - ::getsockopt(m_iSocket, SOL_SOCKET, SO_SNDBUF, (char *)&m_iSndBufSize, &size); - return m_iSndBufSize; -} - -int CChannel::getRcvBufSize() -{ - socklen_t size = sizeof(socklen_t); - ::getsockopt(m_iSocket, SOL_SOCKET, SO_RCVBUF, (char *)&m_iRcvBufSize, &size); - return m_iRcvBufSize; -} - -void CChannel::setSndBufSize(int size) -{ - m_iSndBufSize = size; -} - -void CChannel::setRcvBufSize(int size) -{ - m_iRcvBufSize = size; -} - -void CChannel::getSockAddr(sockaddr* addr) const -{ - socklen_t namelen = m_iSockAddrSize; - ::getsockname(m_iSocket, addr, &namelen); -} - -void CChannel::getPeerAddr(sockaddr* addr) const -{ - socklen_t namelen = m_iSockAddrSize; - ::getpeername(m_iSocket, addr, &namelen); -} - -int CChannel::sendto(const sockaddr* addr, CPacket& packet) const -{ - // convert control information into network order - if (packet.getFlag()) - for (int i = 0, n = packet.getLength() / 4; i < n; ++ i) - *((uint32_t *)packet.m_pcData + i) = htonl(*((uint32_t *)packet.m_pcData + i)); - - // convert packet header into network order - //for (int j = 0; j < 4; ++ j) - // packet.m_nHeader[j] = htonl(packet.m_nHeader[j]); - uint32_t* p = packet.m_nHeader; - for (int j = 0; j < 4; ++ j) - { - *p = htonl(*p); - ++ p; - } - - #ifndef WIN32 - msghdr mh; - mh.msg_name = (sockaddr*)addr; - mh.msg_namelen = m_iSockAddrSize; - mh.msg_iov = (iovec*)packet.m_PacketVector; - mh.msg_iovlen = 2; - mh.msg_control = NULL; - mh.msg_controllen = 0; - mh.msg_flags = 0; - - int res = ::sendmsg(m_iSocket, &mh, 0); - #else - DWORD size = CPacket::m_iPktHdrSize + packet.getLength(); - int addrsize = m_iSockAddrSize; - int res = ::WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr, addrsize, NULL, NULL); - res = (0 == res) ? size : -1; - #endif - - // convert back into local host order - //for (int k = 0; k < 4; ++ k) - // packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]); - p = packet.m_nHeader; - for (int k = 0; k < 4; ++ k) - { - *p = ntohl(*p); - ++ p; - } - - if (packet.getFlag()) - { - for (int l = 0, n = packet.getLength() / 4; l < n; ++ l) - *((uint32_t *)packet.m_pcData + l) = ntohl(*((uint32_t *)packet.m_pcData + l)); - } - - return res; -} - -int CChannel::recvfrom(sockaddr* addr, CPacket& packet) const -{ - #ifndef WIN32 - msghdr mh; - mh.msg_name = addr; - mh.msg_namelen = m_iSockAddrSize; - mh.msg_iov = packet.m_PacketVector; - mh.msg_iovlen = 2; - mh.msg_control = NULL; - mh.msg_controllen = 0; - mh.msg_flags = 0; - - #ifdef UNIX - fd_set set; - timeval tv; - FD_ZERO(&set); - FD_SET(m_iSocket, &set); - tv.tv_sec = 0; - tv.tv_usec = 10000; - ::select(m_iSocket+1, &set, NULL, &set, &tv); - #endif - - int res = ::recvmsg(m_iSocket, &mh, 0); - #else - DWORD size = CPacket::m_iPktHdrSize + packet.getLength(); - DWORD flag = 0; - int addrsize = m_iSockAddrSize; - - int res = ::WSARecvFrom(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, &flag, addr, &addrsize, NULL, NULL); - res = (0 == res) ? size : -1; - #endif - - if (res <= 0) - { - packet.setLength(-1); - return -1; - } - - packet.setLength(res - CPacket::m_iPktHdrSize); - - // convert back into local host order - //for (int i = 0; i < 4; ++ i) - // packet.m_nHeader[i] = ntohl(packet.m_nHeader[i]); - uint32_t* p = packet.m_nHeader; - for (int i = 0; i < 4; ++ i) - { - *p = ntohl(*p); - ++ p; - } - - if (packet.getFlag()) - { - for (int j = 0, n = packet.getLength() / 4; j < n; ++ j) - *((uint32_t *)packet.m_pcData + j) = ntohl(*((uint32_t *)packet.m_pcData + j)); - } - - return packet.getLength(); -} diff --git a/vendor/udt4/src/channel.h b/vendor/udt4/src/channel.h deleted file mode 100644 index 0e47acc..0000000 --- a/vendor/udt4/src/channel.h +++ /dev/null @@ -1,171 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/27/2011 -*****************************************************************************/ - -#ifndef __UDT_CHANNEL_H__ -#define __UDT_CHANNEL_H__ - - -#include "udt.h" -#include "packet.h" - - -class CChannel -{ -public: - CChannel(); - CChannel(int version); - ~CChannel(); - - // Functionality: - // Open a UDP channel. - // Parameters: - // 0) [in] addr: The local address that UDP will use. - // Returned value: - // None. - - void open(const sockaddr* addr = NULL); - - // Functionality: - // Open a UDP channel based on an existing UDP socket. - // Parameters: - // 0) [in] udpsock: UDP socket descriptor. - // Returned value: - // None. - - void open(UDPSOCKET udpsock); - - // Functionality: - // Disconnect and close the UDP entity. - // Parameters: - // None. - // Returned value: - // None. - - void close() const; - - // Functionality: - // Get the UDP sending buffer size. - // Parameters: - // None. - // Returned value: - // Current UDP sending buffer size. - - int getSndBufSize(); - - // Functionality: - // Get the UDP receiving buffer size. - // Parameters: - // None. - // Returned value: - // Current UDP receiving buffer size. - - int getRcvBufSize(); - - // Functionality: - // Set the UDP sending buffer size. - // Parameters: - // 0) [in] size: expected UDP sending buffer size. - // Returned value: - // None. - - void setSndBufSize(int size); - - // Functionality: - // Set the UDP receiving buffer size. - // Parameters: - // 0) [in] size: expected UDP receiving buffer size. - // Returned value: - // None. - - void setRcvBufSize(int size); - - // Functionality: - // Query the socket address that the channel is using. - // Parameters: - // 0) [out] addr: pointer to store the returned socket address. - // Returned value: - // None. - - void getSockAddr(sockaddr* addr) const; - - // Functionality: - // Query the peer side socket address that the channel is connect to. - // Parameters: - // 0) [out] addr: pointer to store the returned socket address. - // Returned value: - // None. - - void getPeerAddr(sockaddr* addr) const; - - // Functionality: - // Send a packet to the given address. - // Parameters: - // 0) [in] addr: pointer to the destination address. - // 1) [in] packet: reference to a CPacket entity. - // Returned value: - // Actual size of data sent. - - int sendto(const sockaddr* addr, CPacket& packet) const; - - // Functionality: - // Receive a packet from the channel and record the source address. - // Parameters: - // 0) [in] addr: pointer to the source address. - // 1) [in] packet: reference to a CPacket entity. - // Returned value: - // Actual size of data received. - - int recvfrom(sockaddr* addr, CPacket& packet) const; - -private: - void setUDPSockOpt(); - -private: - int m_iIPversion; // IP version - int m_iSockAddrSize; // socket address structure size (pre-defined to avoid run-time test) - - UDPSOCKET m_iSocket; // socket descriptor - - int m_iSndBufSize; // UDP sending buffer size - int m_iRcvBufSize; // UDP receiving buffer size -}; - - -#endif diff --git a/vendor/udt4/src/common.cpp b/vendor/udt4/src/common.cpp deleted file mode 100644 index 3b6ffda..0000000 --- a/vendor/udt4/src/common.cpp +++ /dev/null @@ -1,765 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 07/25/2010 -*****************************************************************************/ - - -#ifndef WIN32 - #include - #include - #include - #ifdef OSX - #include - #endif -#else - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#endif - -#include -#include "md5.h" -#include "common.h" - -bool CTimer::m_bUseMicroSecond = false; -uint64_t CTimer::s_ullCPUFrequency = CTimer::readCPUFrequency(); -#ifndef WIN32 - pthread_mutex_t CTimer::m_EventLock = PTHREAD_MUTEX_INITIALIZER; - pthread_cond_t CTimer::m_EventCond = PTHREAD_COND_INITIALIZER; -#else - pthread_mutex_t CTimer::m_EventLock = CreateMutex(NULL, false, NULL); - pthread_cond_t CTimer::m_EventCond = CreateEvent(NULL, false, false, NULL); -#endif - -CTimer::CTimer(): -m_ullSchedTime(), -m_TickCond(), -m_TickLock() -{ - #ifndef WIN32 - pthread_mutex_init(&m_TickLock, NULL); - pthread_cond_init(&m_TickCond, NULL); - #else - m_TickLock = CreateMutex(NULL, false, NULL); - m_TickCond = CreateEvent(NULL, false, false, NULL); - #endif -} - -CTimer::~CTimer() -{ - #ifndef WIN32 - pthread_mutex_destroy(&m_TickLock); - pthread_cond_destroy(&m_TickCond); - #else - CloseHandle(m_TickLock); - CloseHandle(m_TickCond); - #endif -} - -void CTimer::rdtsc(uint64_t &x) -{ - if (m_bUseMicroSecond) - { - x = getTime(); - return; - } - - #ifdef IA32 - uint32_t lval, hval; - //asm volatile ("push %eax; push %ebx; push %ecx; push %edx"); - //asm volatile ("xor %eax, %eax; cpuid"); - asm volatile ("rdtsc" : "=a" (lval), "=d" (hval)); - //asm volatile ("pop %edx; pop %ecx; pop %ebx; pop %eax"); - x = hval; - x = (x << 32) | lval; - #elif defined(IA64) - asm ("mov %0=ar.itc" : "=r"(x) :: "memory"); - #elif defined(AMD64) - uint32_t lval, hval; - asm ("rdtsc" : "=a" (lval), "=d" (hval)); - x = hval; - x = (x << 32) | lval; - #elif defined(WIN32) - //HANDLE hCurThread = ::GetCurrentThread(); - //DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1); - BOOL ret = QueryPerformanceCounter((LARGE_INTEGER *)&x); - //SetThreadAffinityMask(hCurThread, dwOldMask); - if (!ret) - x = getTime() * s_ullCPUFrequency; - #elif defined(OSX) - x = mach_absolute_time(); - #else - // use system call to read time clock for other archs - x = getTime(); - #endif -} - -uint64_t CTimer::readCPUFrequency() -{ - uint64_t frequency = 1; // 1 tick per microsecond. - - #if defined(IA32) || defined(IA64) || defined(AMD64) - uint64_t t1, t2; - - rdtsc(t1); - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 100000000; - nanosleep(&ts, NULL); - rdtsc(t2); - - // CPU clocks per microsecond - frequency = (t2 - t1) / 100000; - #elif defined(WIN32) - int64_t ccf; - if (QueryPerformanceFrequency((LARGE_INTEGER *)&ccf)) - frequency = ccf / 1000000; - #elif defined(OSX) - mach_timebase_info_data_t info; - mach_timebase_info(&info); - frequency = info.denom * 1000ULL / info.numer; - #endif - - // Fall back to microsecond if the resolution is not high enough. - if (frequency < 10) - { - frequency = 1; - m_bUseMicroSecond = true; - } - return frequency; -} - -uint64_t CTimer::getCPUFrequency() -{ - return s_ullCPUFrequency; -} - -void CTimer::sleep(uint64_t interval) -{ - uint64_t t; - rdtsc(t); - - // sleep next "interval" time - sleepto(t + interval); -} - -void CTimer::sleepto(uint64_t nexttime) -{ - // Use class member such that the method can be interrupted by others - m_ullSchedTime = nexttime; - - uint64_t t; - rdtsc(t); - - while (t < m_ullSchedTime) - { - #ifndef NO_BUSY_WAITING - #ifdef IA32 - __asm__ volatile ("pause; rep; nop; nop; nop; nop; nop;"); - #elif IA64 - __asm__ volatile ("nop 0; nop 0; nop 0; nop 0; nop 0;"); - #elif AMD64 - __asm__ volatile ("nop; nop; nop; nop; nop;"); - #endif - #else - #ifndef WIN32 - timeval now; - timespec timeout; - gettimeofday(&now, 0); - if (now.tv_usec < 990000) - { - timeout.tv_sec = now.tv_sec; - timeout.tv_nsec = (now.tv_usec + 10000) * 1000; - } - else - { - timeout.tv_sec = now.tv_sec + 1; - timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000; - } - pthread_mutex_lock(&m_TickLock); - pthread_cond_timedwait(&m_TickCond, &m_TickLock, &timeout); - pthread_mutex_unlock(&m_TickLock); - #else - WaitForSingleObject(m_TickCond, 1); - #endif - #endif - - rdtsc(t); - } -} - -void CTimer::interrupt() -{ - // schedule the sleepto time to the current CCs, so that it will stop - rdtsc(m_ullSchedTime); - tick(); -} - -void CTimer::tick() -{ - #ifndef WIN32 - pthread_cond_signal(&m_TickCond); - #else - SetEvent(m_TickCond); - #endif -} - -uint64_t CTimer::getTime() -{ - //For Cygwin and other systems without microsecond level resolution, uncomment the following three lines - //uint64_t x; - //rdtsc(x); - //return x / s_ullCPUFrequency; - //Specific fix may be necessary if rdtsc is not available either. - - #ifndef WIN32 - timeval t; - gettimeofday(&t, 0); - return t.tv_sec * 1000000ULL + t.tv_usec; - #else - LARGE_INTEGER ccf; - HANDLE hCurThread = ::GetCurrentThread(); - DWORD_PTR dwOldMask = ::SetThreadAffinityMask(hCurThread, 1); - if (QueryPerformanceFrequency(&ccf)) - { - LARGE_INTEGER cc; - if (QueryPerformanceCounter(&cc)) - { - SetThreadAffinityMask(hCurThread, dwOldMask); - return (cc.QuadPart * 1000000ULL / ccf.QuadPart); - } - } - - SetThreadAffinityMask(hCurThread, dwOldMask); - return GetTickCount() * 1000ULL; - #endif -} - -void CTimer::triggerEvent() -{ - #ifndef WIN32 - pthread_cond_signal(&m_EventCond); - #else - SetEvent(m_EventCond); - #endif -} - -void CTimer::waitForEvent() -{ - #ifndef WIN32 - timeval now; - timespec timeout; - gettimeofday(&now, 0); - if (now.tv_usec < 990000) - { - timeout.tv_sec = now.tv_sec; - timeout.tv_nsec = (now.tv_usec + 10000) * 1000; - } - else - { - timeout.tv_sec = now.tv_sec + 1; - timeout.tv_nsec = (now.tv_usec + 10000 - 1000000) * 1000; - } - pthread_mutex_lock(&m_EventLock); - pthread_cond_timedwait(&m_EventCond, &m_EventLock, &timeout); - pthread_mutex_unlock(&m_EventLock); - #else - WaitForSingleObject(m_EventCond, 1); - #endif -} - -void CTimer::sleep() -{ - #ifndef WIN32 - usleep(10); - #else - Sleep(1); - #endif -} - - -// -// Automatically lock in constructor -CGuard::CGuard(pthread_mutex_t& lock): -m_Mutex(lock), -m_iLocked() -{ - #ifndef WIN32 - m_iLocked = pthread_mutex_lock(&m_Mutex); - #else - m_iLocked = WaitForSingleObject(m_Mutex, INFINITE); - #endif -} - -// Automatically unlock in destructor -CGuard::~CGuard() -{ - #ifndef WIN32 - if (0 == m_iLocked) - pthread_mutex_unlock(&m_Mutex); - #else - if (WAIT_FAILED != m_iLocked) - ReleaseMutex(m_Mutex); - #endif -} - -void CGuard::enterCS(pthread_mutex_t& lock) -{ - #ifndef WIN32 - pthread_mutex_lock(&lock); - #else - WaitForSingleObject(lock, INFINITE); - #endif -} - -void CGuard::leaveCS(pthread_mutex_t& lock) -{ - #ifndef WIN32 - pthread_mutex_unlock(&lock); - #else - ReleaseMutex(lock); - #endif -} - -void CGuard::createMutex(pthread_mutex_t& lock) -{ - #ifndef WIN32 - pthread_mutex_init(&lock, NULL); - #else - lock = CreateMutex(NULL, false, NULL); - #endif -} - -void CGuard::releaseMutex(pthread_mutex_t& lock) -{ - #ifndef WIN32 - pthread_mutex_destroy(&lock); - #else - CloseHandle(lock); - #endif -} - -void CGuard::createCond(pthread_cond_t& cond) -{ - #ifndef WIN32 - pthread_cond_init(&cond, NULL); - #else - cond = CreateEvent(NULL, false, false, NULL); - #endif -} - -void CGuard::releaseCond(pthread_cond_t& cond) -{ - #ifndef WIN32 - pthread_cond_destroy(&cond); - #else - CloseHandle(cond); - #endif - -} - -// -CUDTException::CUDTException(int major, int minor, int err): -m_iMajor(major), -m_iMinor(minor) -{ - if (-1 == err) - #ifndef WIN32 - m_iErrno = errno; - #else - m_iErrno = GetLastError(); - #endif - else - m_iErrno = err; -} - -CUDTException::CUDTException(const CUDTException& e): -m_iMajor(e.m_iMajor), -m_iMinor(e.m_iMinor), -m_iErrno(e.m_iErrno), -m_strMsg() -{ -} - -CUDTException::~CUDTException() -{ -} - -const char* CUDTException::getErrorMessage() -{ - // translate "Major:Minor" code into text message. - - switch (m_iMajor) - { - case 0: - m_strMsg = "Success"; - break; - - case 1: - m_strMsg = "Connection setup failure"; - - switch (m_iMinor) - { - case 1: - m_strMsg += ": connection time out"; - break; - - case 2: - m_strMsg += ": connection rejected"; - break; - - case 3: - m_strMsg += ": unable to create/configure UDP socket"; - break; - - case 4: - m_strMsg += ": abort for security reasons"; - break; - - default: - break; - } - - break; - - case 2: - switch (m_iMinor) - { - case 1: - m_strMsg = "Connection was broken"; - break; - - case 2: - m_strMsg = "Connection does not exist"; - break; - - default: - break; - } - - break; - - case 3: - m_strMsg = "System resource failure"; - - switch (m_iMinor) - { - case 1: - m_strMsg += ": unable to create new threads"; - break; - - case 2: - m_strMsg += ": unable to allocate buffers"; - break; - - default: - break; - } - - break; - - case 4: - m_strMsg = "File system failure"; - - switch (m_iMinor) - { - case 1: - m_strMsg += ": cannot seek read position"; - break; - - case 2: - m_strMsg += ": failure in read"; - break; - - case 3: - m_strMsg += ": cannot seek write position"; - break; - - case 4: - m_strMsg += ": failure in write"; - break; - - default: - break; - } - - break; - - case 5: - m_strMsg = "Operation not supported"; - - switch (m_iMinor) - { - case 1: - m_strMsg += ": Cannot do this operation on a BOUND socket"; - break; - - case 2: - m_strMsg += ": Cannot do this operation on a CONNECTED socket"; - break; - - case 3: - m_strMsg += ": Bad parameters"; - break; - - case 4: - m_strMsg += ": Invalid socket ID"; - break; - - case 5: - m_strMsg += ": Cannot do this operation on an UNBOUND socket"; - break; - - case 6: - m_strMsg += ": Socket is not in listening state"; - break; - - case 7: - m_strMsg += ": Listen/accept is not supported in rendezous connection setup"; - break; - - case 8: - m_strMsg += ": Cannot call connect on UNBOUND socket in rendezvous connection setup"; - break; - - case 9: - m_strMsg += ": This operation is not supported in SOCK_STREAM mode"; - break; - - case 10: - m_strMsg += ": This operation is not supported in SOCK_DGRAM mode"; - break; - - case 11: - m_strMsg += ": Another socket is already listening on the same port"; - break; - - case 12: - m_strMsg += ": Message is too large to send (it must be less than the UDT send buffer size)"; - break; - - case 13: - m_strMsg += ": Invalid epoll ID"; - break; - - default: - break; - } - - break; - - case 6: - m_strMsg = "Non-blocking call failure"; - - switch (m_iMinor) - { - case 1: - m_strMsg += ": no buffer available for sending"; - break; - - case 2: - m_strMsg += ": no data available for reading"; - break; - - default: - break; - } - - break; - - case 7: - m_strMsg = "The peer side has signalled an error"; - - break; - - default: - m_strMsg = "Unknown error"; - } - - // Adding "errno" information - if ((0 != m_iMajor) && (0 < m_iErrno)) - { - m_strMsg += ": "; - #ifndef WIN32 - char errmsg[1024]; - if (strerror_r(m_iErrno, errmsg, 1024) == 0) - m_strMsg += errmsg; - #else - LPVOID lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_iErrno, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); - m_strMsg += (char*)lpMsgBuf; - LocalFree(lpMsgBuf); - #endif - } - - // period - #ifndef WIN32 - m_strMsg += "."; - #endif - - return m_strMsg.c_str(); -} - -int CUDTException::getErrorCode() const -{ - return m_iMajor * 1000 + m_iMinor; -} - -void CUDTException::clear() -{ - m_iMajor = 0; - m_iMinor = 0; - m_iErrno = 0; -} - -const int CUDTException::SUCCESS = 0; -const int CUDTException::ECONNSETUP = 1000; -const int CUDTException::ENOSERVER = 1001; -const int CUDTException::ECONNREJ = 1002; -const int CUDTException::ESOCKFAIL = 1003; -const int CUDTException::ESECFAIL = 1004; -const int CUDTException::ECONNFAIL = 2000; -const int CUDTException::ECONNLOST = 2001; -const int CUDTException::ENOCONN = 2002; -const int CUDTException::ERESOURCE = 3000; -const int CUDTException::ETHREAD = 3001; -const int CUDTException::ENOBUF = 3002; -const int CUDTException::EFILE = 4000; -const int CUDTException::EINVRDOFF = 4001; -const int CUDTException::ERDPERM = 4002; -const int CUDTException::EINVWROFF = 4003; -const int CUDTException::EWRPERM = 4004; -const int CUDTException::EINVOP = 5000; -const int CUDTException::EBOUNDSOCK = 5001; -const int CUDTException::ECONNSOCK = 5002; -const int CUDTException::EINVPARAM = 5003; -const int CUDTException::EINVSOCK = 5004; -const int CUDTException::EUNBOUNDSOCK = 5005; -const int CUDTException::ENOLISTEN = 5006; -const int CUDTException::ERDVNOSERV = 5007; -const int CUDTException::ERDVUNBOUND = 5008; -const int CUDTException::ESTREAMILL = 5009; -const int CUDTException::EDGRAMILL = 5010; -const int CUDTException::EDUPLISTEN = 5011; -const int CUDTException::ELARGEMSG = 5012; -const int CUDTException::EINVPOLLID = 5013; -const int CUDTException::EASYNCFAIL = 6000; -const int CUDTException::EASYNCSND = 6001; -const int CUDTException::EASYNCRCV = 6002; -const int CUDTException::ETIMEOUT = 6003; -const int CUDTException::EPEERERR = 7000; -const int CUDTException::EUNKNOWN = -1; - - -// -bool CIPAddress::ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver) -{ - if (AF_INET == ver) - { - sockaddr_in* a1 = (sockaddr_in*)addr1; - sockaddr_in* a2 = (sockaddr_in*)addr2; - - if ((a1->sin_port == a2->sin_port) && (a1->sin_addr.s_addr == a2->sin_addr.s_addr)) - return true; - } - else - { - sockaddr_in6* a1 = (sockaddr_in6*)addr1; - sockaddr_in6* a2 = (sockaddr_in6*)addr2; - - if (a1->sin6_port == a2->sin6_port) - { - for (int i = 0; i < 16; ++ i) - if (*((char*)&(a1->sin6_addr) + i) != *((char*)&(a2->sin6_addr) + i)) - return false; - - return true; - } - } - - return false; -} - -void CIPAddress::ntop(const sockaddr* addr, uint32_t ip[4], int ver) -{ - if (AF_INET == ver) - { - sockaddr_in* a = (sockaddr_in*)addr; - ip[0] = a->sin_addr.s_addr; - } - else - { - sockaddr_in6* a = (sockaddr_in6*)addr; - ip[3] = (a->sin6_addr.s6_addr[15] << 24) + (a->sin6_addr.s6_addr[14] << 16) + (a->sin6_addr.s6_addr[13] << 8) + a->sin6_addr.s6_addr[12]; - ip[2] = (a->sin6_addr.s6_addr[11] << 24) + (a->sin6_addr.s6_addr[10] << 16) + (a->sin6_addr.s6_addr[9] << 8) + a->sin6_addr.s6_addr[8]; - ip[1] = (a->sin6_addr.s6_addr[7] << 24) + (a->sin6_addr.s6_addr[6] << 16) + (a->sin6_addr.s6_addr[5] << 8) + a->sin6_addr.s6_addr[4]; - ip[0] = (a->sin6_addr.s6_addr[3] << 24) + (a->sin6_addr.s6_addr[2] << 16) + (a->sin6_addr.s6_addr[1] << 8) + a->sin6_addr.s6_addr[0]; - } -} - -void CIPAddress::pton(sockaddr* addr, const uint32_t ip[4], int ver) -{ - if (AF_INET == ver) - { - sockaddr_in* a = (sockaddr_in*)addr; - a->sin_addr.s_addr = ip[0]; - } - else - { - sockaddr_in6* a = (sockaddr_in6*)addr; - for (int i = 0; i < 4; ++ i) - { - a->sin6_addr.s6_addr[i * 4] = ip[i] & 0xFF; - a->sin6_addr.s6_addr[i * 4 + 1] = (unsigned char)((ip[i] & 0xFF00) >> 8); - a->sin6_addr.s6_addr[i * 4 + 2] = (unsigned char)((ip[i] & 0xFF0000) >> 16); - a->sin6_addr.s6_addr[i * 4 + 3] = (unsigned char)((ip[i] & 0xFF000000) >> 24); - } - } -} - -// -void CMD5::compute(const char* input, unsigned char result[16]) -{ - md5_state_t state; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)input, strlen(input)); - md5_finish(&state, result); -} diff --git a/vendor/udt4/src/common.h b/vendor/udt4/src/common.h deleted file mode 100644 index 20c0bb4..0000000 --- a/vendor/udt4/src/common.h +++ /dev/null @@ -1,321 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2009, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 08/01/2009 -*****************************************************************************/ - -#ifndef __UDT_COMMON_H__ -#define __UDT_COMMON_H__ - - -#ifndef WIN32 - #include - #include - #include -#else - #include -#endif -#include -#include -#include "udt.h" - - -#ifdef WIN32 - // Windows compability - typedef HANDLE pthread_t; - typedef HANDLE pthread_mutex_t; - typedef HANDLE pthread_cond_t; - typedef DWORD pthread_key_t; -#endif - - -//////////////////////////////////////////////////////////////////////////////// - -class CTimer -{ -public: - CTimer(); - ~CTimer(); - -public: - - // Functionality: - // Sleep for "interval" CCs. - // Parameters: - // 0) [in] interval: CCs to sleep. - // Returned value: - // None. - - void sleep(uint64_t interval); - - // Functionality: - // Seelp until CC "nexttime". - // Parameters: - // 0) [in] nexttime: next time the caller is waken up. - // Returned value: - // None. - - void sleepto(uint64_t nexttime); - - // Functionality: - // Stop the sleep() or sleepto() methods. - // Parameters: - // None. - // Returned value: - // None. - - void interrupt(); - - // Functionality: - // trigger the clock for a tick, for better granuality in no_busy_waiting timer. - // Parameters: - // None. - // Returned value: - // None. - - void tick(); - -public: - - // Functionality: - // Read the CPU clock cycle into x. - // Parameters: - // 0) [out] x: to record cpu clock cycles. - // Returned value: - // None. - - static void rdtsc(uint64_t &x); - - // Functionality: - // return the CPU frequency. - // Parameters: - // None. - // Returned value: - // CPU frequency. - - static uint64_t getCPUFrequency(); - - // Functionality: - // check the current time, 64bit, in microseconds. - // Parameters: - // None. - // Returned value: - // current time in microseconds. - - static uint64_t getTime(); - - // Functionality: - // trigger an event such as new connection, close, new data, etc. for "select" call. - // Parameters: - // None. - // Returned value: - // None. - - static void triggerEvent(); - - // Functionality: - // wait for an event to br triggered by "triggerEvent". - // Parameters: - // None. - // Returned value: - // None. - - static void waitForEvent(); - - // Functionality: - // sleep for a short interval. exact sleep time does not matter - // Parameters: - // None. - // Returned value: - // None. - - static void sleep(); - -private: - uint64_t getTimeInMicroSec(); - -private: - uint64_t m_ullSchedTime; // next schedulled time - - pthread_cond_t m_TickCond; - pthread_mutex_t m_TickLock; - - static pthread_cond_t m_EventCond; - static pthread_mutex_t m_EventLock; - -private: - static uint64_t s_ullCPUFrequency; // CPU frequency : clock cycles per microsecond - static uint64_t readCPUFrequency(); - static bool m_bUseMicroSecond; // No higher resolution timer available, use gettimeofday(). -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CGuard -{ -public: - CGuard(pthread_mutex_t& lock); - ~CGuard(); - -public: - static void enterCS(pthread_mutex_t& lock); - static void leaveCS(pthread_mutex_t& lock); - - static void createMutex(pthread_mutex_t& lock); - static void releaseMutex(pthread_mutex_t& lock); - - static void createCond(pthread_cond_t& cond); - static void releaseCond(pthread_cond_t& cond); - -private: - pthread_mutex_t& m_Mutex; // Alias name of the mutex to be protected - int m_iLocked; // Locking status - - CGuard& operator=(const CGuard&); -}; - - - -//////////////////////////////////////////////////////////////////////////////// - -// UDT Sequence Number 0 - (2^31 - 1) - -// seqcmp: compare two seq#, considering the wraping -// seqlen: length from the 1st to the 2nd seq#, including both -// seqoff: offset from the 2nd to the 1st seq# -// incseq: increase the seq# by 1 -// decseq: decrease the seq# by 1 -// incseq: increase the seq# by a given offset - -class CSeqNo -{ -public: - inline static int seqcmp(int32_t seq1, int32_t seq2) - {return (abs(seq1 - seq2) < m_iSeqNoTH) ? (seq1 - seq2) : (seq2 - seq1);} - - inline static int seqlen(int32_t seq1, int32_t seq2) - {return (seq1 <= seq2) ? (seq2 - seq1 + 1) : (seq2 - seq1 + m_iMaxSeqNo + 2);} - - inline static int seqoff(int32_t seq1, int32_t seq2) - { - if (abs(seq1 - seq2) < m_iSeqNoTH) - return seq2 - seq1; - - if (seq1 < seq2) - return seq2 - seq1 - m_iMaxSeqNo - 1; - - return seq2 - seq1 + m_iMaxSeqNo + 1; - } - - inline static int32_t incseq(int32_t seq) - {return (seq == m_iMaxSeqNo) ? 0 : seq + 1;} - - inline static int32_t decseq(int32_t seq) - {return (seq == 0) ? m_iMaxSeqNo : seq - 1;} - - inline static int32_t incseq(int32_t seq, int32_t inc) - {return (m_iMaxSeqNo - seq >= inc) ? seq + inc : seq - m_iMaxSeqNo + inc - 1;} - -public: - static const int32_t m_iSeqNoTH; // threshold for comparing seq. no. - static const int32_t m_iMaxSeqNo; // maximum sequence number used in UDT -}; - -//////////////////////////////////////////////////////////////////////////////// - -// UDT ACK Sub-sequence Number: 0 - (2^31 - 1) - -class CAckNo -{ -public: - inline static int32_t incack(int32_t ackno) - {return (ackno == m_iMaxAckSeqNo) ? 0 : ackno + 1;} - -public: - static const int32_t m_iMaxAckSeqNo; // maximum ACK sub-sequence number used in UDT -}; - -//////////////////////////////////////////////////////////////////////////////// - -// UDT Message Number: 0 - (2^29 - 1) - -class CMsgNo -{ -public: - inline static int msgcmp(int32_t msgno1, int32_t msgno2) - {return (abs(msgno1 - msgno2) < m_iMsgNoTH) ? (msgno1 - msgno2) : (msgno2 - msgno1);} - - inline static int msglen(int32_t msgno1, int32_t msgno2) - {return (msgno1 <= msgno2) ? (msgno2 - msgno1 + 1) : (msgno2 - msgno1 + m_iMaxMsgNo + 2);} - - inline static int msgoff(int32_t msgno1, int32_t msgno2) - { - if (abs(msgno1 - msgno2) < m_iMsgNoTH) - return msgno2 - msgno1; - - if (msgno1 < msgno2) - return msgno2 - msgno1 - m_iMaxMsgNo - 1; - - return msgno2 - msgno1 + m_iMaxMsgNo + 1; - } - - inline static int32_t incmsg(int32_t msgno) - {return (msgno == m_iMaxMsgNo) ? 0 : msgno + 1;} - -public: - static const int32_t m_iMsgNoTH; // threshold for comparing msg. no. - static const int32_t m_iMaxMsgNo; // maximum message number used in UDT -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct CIPAddress -{ - static bool ipcmp(const sockaddr* addr1, const sockaddr* addr2, int ver = AF_INET); - static void ntop(const sockaddr* addr, uint32_t ip[4], int ver = AF_INET); - static void pton(sockaddr* addr, const uint32_t ip[4], int ver = AF_INET); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct CMD5 -{ - static void compute(const char* input, unsigned char result[16]); -}; - - -#endif diff --git a/vendor/udt4/src/core.cpp b/vendor/udt4/src/core.cpp deleted file mode 100644 index ba989aa..0000000 --- a/vendor/udt4/src/core.cpp +++ /dev/null @@ -1,2675 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 02/28/2012 -*****************************************************************************/ - -#ifndef WIN32 - #include - #include - #include - #include - #include - #include -#else - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#endif -#include -#include -#include "queue.h" -#include "core.h" - -using namespace std; - - -CUDTUnited CUDT::s_UDTUnited; - -const UDTSOCKET CUDT::INVALID_SOCK = -1; -const int CUDT::ERROR = -1; - -const UDTSOCKET UDT::INVALID_SOCK = CUDT::INVALID_SOCK; -const int UDT::ERROR = CUDT::ERROR; - -const int32_t CSeqNo::m_iSeqNoTH = 0x3FFFFFFF; -const int32_t CSeqNo::m_iMaxSeqNo = 0x7FFFFFFF; -const int32_t CAckNo::m_iMaxAckSeqNo = 0x7FFFFFFF; -const int32_t CMsgNo::m_iMsgNoTH = 0xFFFFFFF; -const int32_t CMsgNo::m_iMaxMsgNo = 0x1FFFFFFF; - -const int CUDT::m_iVersion = 4; -const int CUDT::m_iSYNInterval = 10000; -const int CUDT::m_iSelfClockInterval = 64; - - -CUDT::CUDT() -{ - m_pSndBuffer = NULL; - m_pRcvBuffer = NULL; - m_pSndLossList = NULL; - m_pRcvLossList = NULL; - m_pACKWindow = NULL; - m_pSndTimeWindow = NULL; - m_pRcvTimeWindow = NULL; - - m_pSndQueue = NULL; - m_pRcvQueue = NULL; - m_pPeerAddr = NULL; - m_pSNode = NULL; - m_pRNode = NULL; - - // Initilize mutex and condition variables - initSynch(); - - // Default UDT configurations - m_iMSS = 1500; - m_bSynSending = true; - m_bSynRecving = true; - m_iFlightFlagSize = 25600; - m_iSndBufSize = 8192; - m_iRcvBufSize = 8192; //Rcv buffer MUST NOT be bigger than Flight Flag size - m_Linger.l_onoff = 1; - m_Linger.l_linger = 180; - m_iUDPSndBufSize = 65536; - m_iUDPRcvBufSize = m_iRcvBufSize * m_iMSS; - m_iSockType = UDT_STREAM; - m_iIPversion = AF_INET; - m_bRendezvous = false; - m_iSndTimeOut = -1; - m_iRcvTimeOut = -1; - m_bReuseAddr = true; - m_llMaxBW = -1; - - m_pCCFactory = new CCCFactory; - m_pCC = NULL; - m_pCache = NULL; - - // Initial status - m_bOpened = false; - m_bListening = false; - m_bConnecting = false; - m_bConnected = false; - m_bClosing = false; - m_bShutdown = false; - m_bBroken = false; - m_bPeerHealth = true; - m_ullLingerExpiration = 0; -} - -CUDT::CUDT(const CUDT& ancestor) -{ - m_pSndBuffer = NULL; - m_pRcvBuffer = NULL; - m_pSndLossList = NULL; - m_pRcvLossList = NULL; - m_pACKWindow = NULL; - m_pSndTimeWindow = NULL; - m_pRcvTimeWindow = NULL; - - m_pSndQueue = NULL; - m_pRcvQueue = NULL; - m_pPeerAddr = NULL; - m_pSNode = NULL; - m_pRNode = NULL; - - // Initilize mutex and condition variables - initSynch(); - - // Default UDT configurations - m_iMSS = ancestor.m_iMSS; - m_bSynSending = ancestor.m_bSynSending; - m_bSynRecving = ancestor.m_bSynRecving; - m_iFlightFlagSize = ancestor.m_iFlightFlagSize; - m_iSndBufSize = ancestor.m_iSndBufSize; - m_iRcvBufSize = ancestor.m_iRcvBufSize; - m_Linger = ancestor.m_Linger; - m_iUDPSndBufSize = ancestor.m_iUDPSndBufSize; - m_iUDPRcvBufSize = ancestor.m_iUDPRcvBufSize; - m_iSockType = ancestor.m_iSockType; - m_iIPversion = ancestor.m_iIPversion; - m_bRendezvous = ancestor.m_bRendezvous; - m_iSndTimeOut = ancestor.m_iSndTimeOut; - m_iRcvTimeOut = ancestor.m_iRcvTimeOut; - m_bReuseAddr = true; // this must be true, because all accepted sockets shared the same port with the listener - m_llMaxBW = ancestor.m_llMaxBW; - - m_pCCFactory = ancestor.m_pCCFactory->clone(); - m_pCC = NULL; - m_pCache = ancestor.m_pCache; - - // Initial status - m_bOpened = false; - m_bListening = false; - m_bConnecting = false; - m_bConnected = false; - m_bClosing = false; - m_bShutdown = false; - m_bBroken = false; - m_bPeerHealth = true; - m_ullLingerExpiration = 0; -} - -CUDT::~CUDT() -{ - // release mutex/condtion variables - destroySynch(); - - // destroy the data structures - delete m_pSndBuffer; - delete m_pRcvBuffer; - delete m_pSndLossList; - delete m_pRcvLossList; - delete m_pACKWindow; - delete m_pSndTimeWindow; - delete m_pRcvTimeWindow; - delete m_pCCFactory; - delete m_pCC; - delete m_pPeerAddr; - delete m_pSNode; - delete m_pRNode; -} - -void CUDT::setOpt(UDTOpt optName, const void* optval, int) -{ - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - - CGuard cg(m_ConnectionLock); - CGuard sendguard(m_SendLock); - CGuard recvguard(m_RecvLock); - - switch (optName) - { - case UDT_MSS: - if (m_bOpened) - throw CUDTException(5, 1, 0); - - if (*(int*)optval < int(28 + CHandShake::m_iContentSize)) - throw CUDTException(5, 3, 0); - - m_iMSS = *(int*)optval; - - // Packet size cannot be greater than UDP buffer size - if (m_iMSS > m_iUDPSndBufSize) - m_iMSS = m_iUDPSndBufSize; - if (m_iMSS > m_iUDPRcvBufSize) - m_iMSS = m_iUDPRcvBufSize; - - break; - - case UDT_SNDSYN: - m_bSynSending = *(bool *)optval; - break; - - case UDT_RCVSYN: - m_bSynRecving = *(bool *)optval; - break; - - case UDT_CC: - if (m_bConnecting || m_bConnected) - throw CUDTException(5, 1, 0); - if (NULL != m_pCCFactory) - delete m_pCCFactory; - m_pCCFactory = ((CCCVirtualFactory *)optval)->clone(); - - break; - - case UDT_FC: - if (m_bConnecting || m_bConnected) - throw CUDTException(5, 2, 0); - - if (*(int*)optval < 1) - throw CUDTException(5, 3); - - // Mimimum recv flight flag size is 32 packets - if (*(int*)optval > 32) - m_iFlightFlagSize = *(int*)optval; - else - m_iFlightFlagSize = 32; - - break; - - case UDT_SNDBUF: - if (m_bOpened) - throw CUDTException(5, 1, 0); - - if (*(int*)optval <= 0) - throw CUDTException(5, 3, 0); - - m_iSndBufSize = *(int*)optval / (m_iMSS - 28); - - break; - - case UDT_RCVBUF: - if (m_bOpened) - throw CUDTException(5, 1, 0); - - if (*(int*)optval <= 0) - throw CUDTException(5, 3, 0); - - // Mimimum recv buffer size is 32 packets - if (*(int*)optval > (m_iMSS - 28) * 32) - m_iRcvBufSize = *(int*)optval / (m_iMSS - 28); - else - m_iRcvBufSize = 32; - - // recv buffer MUST not be greater than FC size - if (m_iRcvBufSize > m_iFlightFlagSize) - m_iRcvBufSize = m_iFlightFlagSize; - - break; - - case UDT_LINGER: - m_Linger = *(linger*)optval; - break; - - case UDP_SNDBUF: - if (m_bOpened) - throw CUDTException(5, 1, 0); - - m_iUDPSndBufSize = *(int*)optval; - - if (m_iUDPSndBufSize < m_iMSS) - m_iUDPSndBufSize = m_iMSS; - - break; - - case UDP_RCVBUF: - if (m_bOpened) - throw CUDTException(5, 1, 0); - - m_iUDPRcvBufSize = *(int*)optval; - - if (m_iUDPRcvBufSize < m_iMSS) - m_iUDPRcvBufSize = m_iMSS; - - break; - - case UDT_RENDEZVOUS: - if (m_bConnecting || m_bConnected) - throw CUDTException(5, 1, 0); - m_bRendezvous = *(bool *)optval; - break; - - case UDT_SNDTIMEO: - m_iSndTimeOut = *(int*)optval; - break; - - case UDT_RCVTIMEO: - m_iRcvTimeOut = *(int*)optval; - break; - - case UDT_REUSEADDR: - if (m_bOpened) - throw CUDTException(5, 1, 0); - m_bReuseAddr = *(bool*)optval; - break; - - case UDT_MAXBW: - m_llMaxBW = *(int64_t*)optval; - break; - - default: - throw CUDTException(5, 0, 0); - } -} - -void CUDT::getOpt(UDTOpt optName, void* optval, int& optlen) -{ - CGuard cg(m_ConnectionLock); - - switch (optName) - { - case UDT_MSS: - *(int*)optval = m_iMSS; - optlen = sizeof(int); - break; - - case UDT_SNDSYN: - *(bool*)optval = m_bSynSending; - optlen = sizeof(bool); - break; - - case UDT_RCVSYN: - *(bool*)optval = m_bSynRecving; - optlen = sizeof(bool); - break; - - case UDT_CC: - if (!m_bOpened) - throw CUDTException(5, 5, 0); - *(CCC**)optval = m_pCC; - optlen = sizeof(CCC*); - - break; - - case UDT_FC: - *(int*)optval = m_iFlightFlagSize; - optlen = sizeof(int); - break; - - case UDT_SNDBUF: - *(int*)optval = m_iSndBufSize * (m_iMSS - 28); - optlen = sizeof(int); - break; - - case UDT_RCVBUF: - *(int*)optval = m_iRcvBufSize * (m_iMSS - 28); - optlen = sizeof(int); - break; - - case UDT_LINGER: - if (optlen < (int)(sizeof(linger))) - throw CUDTException(5, 3, 0); - - *(linger*)optval = m_Linger; - optlen = sizeof(linger); - break; - - case UDP_SNDBUF: - *(int*)optval = m_iUDPSndBufSize; - optlen = sizeof(int); - break; - - case UDP_RCVBUF: - *(int*)optval = m_iUDPRcvBufSize; - optlen = sizeof(int); - break; - - case UDT_RENDEZVOUS: - *(bool *)optval = m_bRendezvous; - optlen = sizeof(bool); - break; - - case UDT_SNDTIMEO: - *(int*)optval = m_iSndTimeOut; - optlen = sizeof(int); - break; - - case UDT_RCVTIMEO: - *(int*)optval = m_iRcvTimeOut; - optlen = sizeof(int); - break; - - case UDT_REUSEADDR: - *(bool *)optval = m_bReuseAddr; - optlen = sizeof(bool); - break; - - case UDT_MAXBW: - *(int64_t*)optval = m_llMaxBW; - optlen = sizeof(int64_t); - break; - - case UDT_STATE: - *(int32_t*)optval = s_UDTUnited.getStatus(m_SocketID); - optlen = sizeof(int32_t); - break; - - case UDT_EVENT: - { - int32_t event = 0; - if (m_bBroken) - event |= UDT_EPOLL_ERR; - else - { - if (m_pRcvBuffer && (m_pRcvBuffer->getRcvDataSize() > 0)) - event |= UDT_EPOLL_IN; - if (m_pSndBuffer && (m_iSndBufSize > m_pSndBuffer->getCurrBufSize())) - event |= UDT_EPOLL_OUT; - } - *(int32_t*)optval = event; - optlen = sizeof(int32_t); - break; - } - - case UDT_SNDDATA: - if (m_pSndBuffer) - *(int32_t*)optval = m_pSndBuffer->getCurrBufSize(); - else - *(int32_t*)optval = 0; - optlen = sizeof(int32_t); - break; - - case UDT_RCVDATA: - if (m_pRcvBuffer) - *(int32_t*)optval = m_pRcvBuffer->getRcvDataSize(); - else - *(int32_t*)optval = 0; - optlen = sizeof(int32_t); - break; - - default: - throw CUDTException(5, 0, 0); - } -} - -void CUDT::open() -{ - CGuard cg(m_ConnectionLock); - - // Initial sequence number, loss, acknowledgement, etc. - m_iPktSize = m_iMSS - 28; - m_iPayloadSize = m_iPktSize - CPacket::m_iPktHdrSize; - - m_iEXPCount = 1; - m_iBandwidth = 1; - m_iDeliveryRate = 16; - m_iAckSeqNo = 0; - m_ullLastAckTime = 0; - - // trace information - m_StartTime = CTimer::getTime(); - m_llSentTotal = m_llRecvTotal = m_iSndLossTotal = m_iRcvLossTotal = m_iRetransTotal = m_iSentACKTotal = m_iRecvACKTotal = m_iSentNAKTotal = m_iRecvNAKTotal = 0; - m_LastSampleTime = CTimer::getTime(); - m_llTraceSent = m_llTraceRecv = m_iTraceSndLoss = m_iTraceRcvLoss = m_iTraceRetrans = m_iSentACK = m_iRecvACK = m_iSentNAK = m_iRecvNAK = 0; - m_llSndDuration = m_llSndDurationTotal = 0; - - // structures for queue - if (NULL == m_pSNode) - m_pSNode = new CSNode; - m_pSNode->m_pUDT = this; - m_pSNode->m_llTimeStamp = 1; - m_pSNode->m_iHeapLoc = -1; - - if (NULL == m_pRNode) - m_pRNode = new CRNode; - m_pRNode->m_pUDT = this; - m_pRNode->m_llTimeStamp = 1; - m_pRNode->m_pPrev = m_pRNode->m_pNext = NULL; - m_pRNode->m_bOnList = false; - - m_iRTT = 10 * m_iSYNInterval; - m_iRTTVar = m_iRTT >> 1; - m_ullCPUFrequency = CTimer::getCPUFrequency(); - - // set up the timers - m_ullSYNInt = m_iSYNInterval * m_ullCPUFrequency; - - // set minimum NAK and EXP timeout to 100ms - m_ullMinNakInt = 300000 * m_ullCPUFrequency; - m_ullMinExpInt = 300000 * m_ullCPUFrequency; - - m_ullACKInt = m_ullSYNInt; - m_ullNAKInt = m_ullMinNakInt; - - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - m_ullNextACKTime = currtime + m_ullSYNInt; - m_ullNextNAKTime = currtime + m_ullNAKInt; - - m_iPktCount = 0; - m_iLightACKCount = 1; - - m_ullTargetTime = 0; - m_ullTimeDiff = 0; - - // Now UDT is opened. - m_bOpened = true; -} - -void CUDT::listen() -{ - CGuard cg(m_ConnectionLock); - - if (!m_bOpened) - throw CUDTException(5, 0, 0); - - if (m_bConnecting || m_bConnected) - throw CUDTException(5, 2, 0); - - // listen can be called more than once - if (m_bListening) - return; - - // if there is already another socket listening on the same port - if (m_pRcvQueue->setListener(this) < 0) - throw CUDTException(5, 11, 0); - - m_bListening = true; -} - -void CUDT::connect(const sockaddr* serv_addr) -{ - CGuard cg(m_ConnectionLock); - - if (!m_bOpened) - throw CUDTException(5, 0, 0); - - if (m_bListening) - throw CUDTException(5, 2, 0); - - if (m_bConnecting || m_bConnected) - throw CUDTException(5, 2, 0); - - // record peer/server address - delete m_pPeerAddr; - m_pPeerAddr = (AF_INET == m_iIPversion) ? (sockaddr*)new sockaddr_in : (sockaddr*)new sockaddr_in6; - memcpy(m_pPeerAddr, serv_addr, (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); - - // register this socket in the rendezvous queue - // RendezevousQueue is used to temporarily store incoming handshake, non-rendezvous connections also require this function - uint64_t ttl = 3000000; - if (m_bRendezvous) - ttl *= 10; - ttl += CTimer::getTime(); - m_pRcvQueue->registerConnector(m_SocketID, this, m_iIPversion, serv_addr, ttl); - - // This is my current configurations - m_ConnReq.m_iVersion = m_iVersion; - m_ConnReq.m_iType = m_iSockType; - m_ConnReq.m_iMSS = m_iMSS; - m_ConnReq.m_iFlightFlagSize = (m_iRcvBufSize < m_iFlightFlagSize)? m_iRcvBufSize : m_iFlightFlagSize; - m_ConnReq.m_iReqType = (!m_bRendezvous) ? 1 : 0; - m_ConnReq.m_iID = m_SocketID; - CIPAddress::ntop(serv_addr, m_ConnReq.m_piPeerIP, m_iIPversion); - - // Random Initial Sequence Number - srand((unsigned int)CTimer::getTime()); - m_iISN = m_ConnReq.m_iISN = (int32_t)(CSeqNo::m_iMaxSeqNo * (double(rand()) / RAND_MAX)); - - m_iLastDecSeq = m_iISN - 1; - m_iSndLastAck = m_iISN; - m_iSndLastDataAck = m_iISN; - m_iSndCurrSeqNo = m_iISN - 1; - m_iSndLastAck2 = m_iISN; - m_ullSndLastAck2Time = CTimer::getTime(); - - // Inform the server my configurations. - CPacket request; - char* reqdata = new char [m_iPayloadSize]; - request.pack(0, NULL, reqdata, m_iPayloadSize); - // ID = 0, connection request - request.m_iID = 0; - - int hs_size = m_iPayloadSize; - m_ConnReq.serialize(reqdata, hs_size); - request.setLength(hs_size); - m_pSndQueue->sendto(serv_addr, request); - m_llLastReqTime = CTimer::getTime(); - - m_bConnecting = true; - - // asynchronous connect, return immediately - if (!m_bSynRecving) - { - delete [] reqdata; - return; - } - - // Wait for the negotiated configurations from the peer side. - CPacket response; - char* resdata = new char [m_iPayloadSize]; - response.pack(0, NULL, resdata, m_iPayloadSize); - - CUDTException e(0, 0); - - while (!m_bClosing) - { - // avoid sending too many requests, at most 1 request per 250ms - if (CTimer::getTime() - m_llLastReqTime > 250000) - { - m_ConnReq.serialize(reqdata, hs_size); - request.setLength(hs_size); - if (m_bRendezvous) - request.m_iID = m_ConnRes.m_iID; - m_pSndQueue->sendto(serv_addr, request); - m_llLastReqTime = CTimer::getTime(); - } - - response.setLength(m_iPayloadSize); - if (m_pRcvQueue->recvfrom(m_SocketID, response) > 0) - { - if (connect(response) <= 0) - break; - - // new request/response should be sent out immediately on receving a response - m_llLastReqTime = 0; - } - - if (CTimer::getTime() > ttl) - { - // timeout - e = CUDTException(1, 1, 0); - break; - } - } - - delete [] reqdata; - delete [] resdata; - - if (e.getErrorCode() == 0) - { - if (m_bClosing) // if the socket is closed before connection... - e = CUDTException(1); - else if (1002 == m_ConnRes.m_iReqType) // connection request rejected - e = CUDTException(1, 2, 0); - else if ((!m_bRendezvous) && (m_iISN != m_ConnRes.m_iISN)) // secuity check - e = CUDTException(1, 4, 0); - } - - if (e.getErrorCode() != 0) - throw e; -} - -int CUDT::connect(const CPacket& response) throw () -{ - // this is the 2nd half of a connection request. If the connection is setup successfully this returns 0. - // returning -1 means there is an error. - // returning 1 or 2 means the connection is in process and needs more handshake - - if (!m_bConnecting) - return -1; - - if (m_bRendezvous && ((0 == response.getFlag()) || (1 == response.getType())) && (0 != m_ConnRes.m_iType)) - { - //a data packet or a keep-alive packet comes, which means the peer side is already connected - // in this situation, the previously recorded response will be used - goto POST_CONNECT; - } - - if ((1 != response.getFlag()) || (0 != response.getType())) - return -1; - - m_ConnRes.deserialize(response.m_pcData, response.getLength()); - - if (m_bRendezvous) - { - // regular connect should NOT communicate with rendezvous connect - // rendezvous connect require 3-way handshake - if (1 == m_ConnRes.m_iReqType) - return -1; - - if ((0 == m_ConnReq.m_iReqType) || (0 == m_ConnRes.m_iReqType)) - { - m_ConnReq.m_iReqType = -1; - // the request time must be updated so that the next handshake can be sent out immediately. - m_llLastReqTime = 0; - return 1; - } - } - else - { - // set cookie - if (1 == m_ConnRes.m_iReqType) - { - m_ConnReq.m_iReqType = -1; - m_ConnReq.m_iCookie = m_ConnRes.m_iCookie; - m_llLastReqTime = 0; - return 1; - } - } - -POST_CONNECT: - // Remove from rendezvous queue - m_pRcvQueue->removeConnector(m_SocketID); - - // Re-configure according to the negotiated values. - m_iMSS = m_ConnRes.m_iMSS; - m_iFlowWindowSize = m_ConnRes.m_iFlightFlagSize; - m_iPktSize = m_iMSS - 28; - m_iPayloadSize = m_iPktSize - CPacket::m_iPktHdrSize; - m_iPeerISN = m_ConnRes.m_iISN; - m_iRcvLastAck = m_ConnRes.m_iISN; - m_iRcvLastAckAck = m_ConnRes.m_iISN; - m_iRcvCurrSeqNo = m_ConnRes.m_iISN - 1; - m_PeerID = m_ConnRes.m_iID; - memcpy(m_piSelfIP, m_ConnRes.m_piPeerIP, 16); - - // Prepare all data structures - try - { - m_pSndBuffer = new CSndBuffer(32, m_iPayloadSize); - m_pRcvBuffer = new CRcvBuffer(&(m_pRcvQueue->m_UnitQueue), m_iRcvBufSize); - // after introducing lite ACK, the sndlosslist may not be cleared in time, so it requires twice space. - m_pSndLossList = new CSndLossList(m_iFlowWindowSize * 2); - m_pRcvLossList = new CRcvLossList(m_iFlightFlagSize); - m_pACKWindow = new CACKWindow(1024); - m_pRcvTimeWindow = new CPktTimeWindow(16, 64); - m_pSndTimeWindow = new CPktTimeWindow(); - } - catch (...) - { - throw CUDTException(3, 2, 0); - } - - CInfoBlock ib; - ib.m_iIPversion = m_iIPversion; - CInfoBlock::convert(m_pPeerAddr, m_iIPversion, ib.m_piIP); - if (m_pCache->lookup(&ib) >= 0) - { - m_iRTT = ib.m_iRTT; - m_iBandwidth = ib.m_iBandwidth; - } - - m_pCC = m_pCCFactory->create(); - m_pCC->m_UDT = m_SocketID; - m_pCC->setMSS(m_iMSS); - m_pCC->setMaxCWndSize(m_iFlowWindowSize); - m_pCC->setSndCurrSeqNo(m_iSndCurrSeqNo); - m_pCC->setRcvRate(m_iDeliveryRate); - m_pCC->setRTT(m_iRTT); - m_pCC->setBandwidth(m_iBandwidth); - m_pCC->init(); - - m_ullInterval = (uint64_t)(m_pCC->m_dPktSndPeriod * m_ullCPUFrequency); - m_dCongestionWindow = m_pCC->m_dCWndSize; - - // And, I am connected too. - m_bConnecting = false; - m_bConnected = true; - - // register this socket for receiving data packets - m_pRNode->m_bOnList = true; - m_pRcvQueue->setNewEntry(this); - - // acknowledge the management module. - s_UDTUnited.connect_complete(m_SocketID); - - // acknowledde any waiting epolls to write - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, true); - - return 0; -} - -void CUDT::connect(const sockaddr* peer, CHandShake* hs) -{ - CGuard cg(m_ConnectionLock); - - // Uses the smaller MSS between the peers - if (hs->m_iMSS > m_iMSS) - hs->m_iMSS = m_iMSS; - else - m_iMSS = hs->m_iMSS; - - // exchange info for maximum flow window size - m_iFlowWindowSize = hs->m_iFlightFlagSize; - hs->m_iFlightFlagSize = (m_iRcvBufSize < m_iFlightFlagSize)? m_iRcvBufSize : m_iFlightFlagSize; - - m_iPeerISN = hs->m_iISN; - - m_iRcvLastAck = hs->m_iISN; - m_iRcvLastAckAck = hs->m_iISN; - m_iRcvCurrSeqNo = hs->m_iISN - 1; - - m_PeerID = hs->m_iID; - hs->m_iID = m_SocketID; - - // use peer's ISN and send it back for security check - m_iISN = hs->m_iISN; - - m_iLastDecSeq = m_iISN - 1; - m_iSndLastAck = m_iISN; - m_iSndLastDataAck = m_iISN; - m_iSndCurrSeqNo = m_iISN - 1; - m_iSndLastAck2 = m_iISN; - m_ullSndLastAck2Time = CTimer::getTime(); - - // this is a reponse handshake - hs->m_iReqType = -1; - - // get local IP address and send the peer its IP address (because UDP cannot get local IP address) - memcpy(m_piSelfIP, hs->m_piPeerIP, 16); - CIPAddress::ntop(peer, hs->m_piPeerIP, m_iIPversion); - - m_iPktSize = m_iMSS - 28; - m_iPayloadSize = m_iPktSize - CPacket::m_iPktHdrSize; - - // Prepare all structures - try - { - m_pSndBuffer = new CSndBuffer(32, m_iPayloadSize); - m_pRcvBuffer = new CRcvBuffer(&(m_pRcvQueue->m_UnitQueue), m_iRcvBufSize); - m_pSndLossList = new CSndLossList(m_iFlowWindowSize * 2); - m_pRcvLossList = new CRcvLossList(m_iFlightFlagSize); - m_pACKWindow = new CACKWindow(1024); - m_pRcvTimeWindow = new CPktTimeWindow(16, 64); - m_pSndTimeWindow = new CPktTimeWindow(); - } - catch (...) - { - throw CUDTException(3, 2, 0); - } - - CInfoBlock ib; - ib.m_iIPversion = m_iIPversion; - CInfoBlock::convert(peer, m_iIPversion, ib.m_piIP); - if (m_pCache->lookup(&ib) >= 0) - { - m_iRTT = ib.m_iRTT; - m_iBandwidth = ib.m_iBandwidth; - } - - m_pCC = m_pCCFactory->create(); - m_pCC->m_UDT = m_SocketID; - m_pCC->setMSS(m_iMSS); - m_pCC->setMaxCWndSize(m_iFlowWindowSize); - m_pCC->setSndCurrSeqNo(m_iSndCurrSeqNo); - m_pCC->setRcvRate(m_iDeliveryRate); - m_pCC->setRTT(m_iRTT); - m_pCC->setBandwidth(m_iBandwidth); - m_pCC->init(); - - m_ullInterval = (uint64_t)(m_pCC->m_dPktSndPeriod * m_ullCPUFrequency); - m_dCongestionWindow = m_pCC->m_dCWndSize; - - m_pPeerAddr = (AF_INET == m_iIPversion) ? (sockaddr*)new sockaddr_in : (sockaddr*)new sockaddr_in6; - memcpy(m_pPeerAddr, peer, (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); - - // And of course, it is connected. - m_bConnected = true; - - // register this socket for receiving data packets - m_pRNode->m_bOnList = true; - m_pRcvQueue->setNewEntry(this); - - //send the response to the peer, see listen() for more discussions about this - CPacket response; - int size = CHandShake::m_iContentSize; - char* buffer = new char[size]; - hs->serialize(buffer, size); - response.pack(0, NULL, buffer, size); - response.m_iID = m_PeerID; - m_pSndQueue->sendto(peer, response); - delete [] buffer; -} - -void CUDT::close() -{ - if (!m_bOpened) - return; - - if (0 != m_Linger.l_onoff) - { - uint64_t entertime = CTimer::getTime(); - - while (!m_bBroken && m_bConnected && (m_pSndBuffer->getCurrBufSize() > 0) && (CTimer::getTime() - entertime < m_Linger.l_linger * 1000000ULL)) - { - // linger has been checked by previous close() call and has expired - if (m_ullLingerExpiration >= entertime) - break; - - if (!m_bSynSending) - { - // if this socket enables asynchronous sending, return immediately and let GC to close it later - if (0 == m_ullLingerExpiration) - m_ullLingerExpiration = entertime + m_Linger.l_linger * 1000000ULL; - - return; - } - - #ifndef WIN32 - timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - #else - Sleep(1); - #endif - } - } - - // remove this socket from the snd queue - if (m_bConnected) - m_pSndQueue->m_pSndUList->remove(this); - - // trigger any pending IO events. - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_ERR, true); - // then remove itself from all epoll monitoring - try - { - for (set::iterator i = m_sPollID.begin(); i != m_sPollID.end(); ++ i) - s_UDTUnited.m_EPoll.remove_usock(*i, m_SocketID); - } - catch (...) - { - } - - if (!m_bOpened) - return; - - // Inform the threads handler to stop. - m_bClosing = true; - - CGuard cg(m_ConnectionLock); - - // Signal the sender and recver if they are waiting for data. - releaseSynch(); - - if (m_bListening) - { - m_bListening = false; - m_pRcvQueue->removeListener(this); - } - else if (m_bConnecting) - { - m_pRcvQueue->removeConnector(m_SocketID); - } - - if (m_bConnected) - { - if (!m_bShutdown) - sendCtrl(5); - - m_pCC->close(); - - // Store current connection information. - CInfoBlock ib; - ib.m_iIPversion = m_iIPversion; - CInfoBlock::convert(m_pPeerAddr, m_iIPversion, ib.m_piIP); - ib.m_iRTT = m_iRTT; - ib.m_iBandwidth = m_iBandwidth; - m_pCache->update(&ib); - - m_bConnected = false; - } - - // waiting all send and recv calls to stop - CGuard sendguard(m_SendLock); - CGuard recvguard(m_RecvLock); - - // CLOSED. - m_bOpened = false; -} - -int CUDT::send(const char* data, int len) -{ - if (UDT_DGRAM == m_iSockType) - throw CUDTException(5, 10, 0); - - // throw an exception if not connected - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - - if (len <= 0) - return 0; - - CGuard sendguard(m_SendLock); - - if (m_pSndBuffer->getCurrBufSize() == 0) - { - // delay the EXP timer to avoid mis-fired timeout - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - } - - if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) - { - if (!m_bSynSending) - throw CUDTException(6, 1, 0); - else - { - // wait here during a blocking sending - #ifndef WIN32 - pthread_mutex_lock(&m_SendBlockLock); - if (m_iSndTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth) - pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; - timespec locktime; - - locktime.tv_sec = exptime / 1000000; - locktime.tv_nsec = (exptime % 1000000) * 1000; - - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth && (CTimer::getTime() < exptime)) - pthread_cond_timedwait(&m_SendBlockCond, &m_SendBlockLock, &locktime); - } - pthread_mutex_unlock(&m_SendBlockLock); - #else - if (m_iSndTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth) - WaitForSingleObject(m_SendBlockCond, INFINITE); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; - - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth && (CTimer::getTime() < exptime)) - WaitForSingleObject(m_SendBlockCond, DWORD((exptime - CTimer::getTime()) / 1000)); - } - #endif - - // check the connection status - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if (!m_bPeerHealth) - { - m_bPeerHealth = true; - throw CUDTException(7); - } - } - } - - if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) - { - if (m_iSndTimeOut >= 0) - throw CUDTException(6, 3, 0); - - return 0; - } - - int size = (m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize; - if (size > len) - size = len; - - // record total time used for sending - if (0 == m_pSndBuffer->getCurrBufSize()) - m_llSndDurationCounter = CTimer::getTime(); - - // insert the user buffer into the sening list - m_pSndBuffer->addBuffer(data, size); - - // insert this socket to snd list if it is not on the list yet - m_pSndQueue->m_pSndUList->update(this, false); - - if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) - { - // write is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, false); - } - - return size; -} - -int CUDT::recv(char* data, int len) -{ - if (UDT_DGRAM == m_iSockType) - throw CUDTException(5, 10, 0); - - // throw an exception if not connected - if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer->getRcvDataSize())) - throw CUDTException(2, 1, 0); - - if (len <= 0) - return 0; - - CGuard recvguard(m_RecvLock); - - if (0 == m_pRcvBuffer->getRcvDataSize()) - { - if (!m_bSynRecving) - throw CUDTException(6, 2, 0); - else - { - #ifndef WIN32 - pthread_mutex_lock(&m_RecvDataLock); - if (m_iRcvTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - pthread_cond_wait(&m_RecvDataCond, &m_RecvDataLock); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iRcvTimeOut * 1000ULL; - timespec locktime; - - locktime.tv_sec = exptime / 1000000; - locktime.tv_nsec = (exptime % 1000000) * 1000; - - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - { - pthread_cond_timedwait(&m_RecvDataCond, &m_RecvDataLock, &locktime); - if (CTimer::getTime() >= exptime) - break; - } - } - pthread_mutex_unlock(&m_RecvDataLock); - #else - if (m_iRcvTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - WaitForSingleObject(m_RecvDataCond, INFINITE); - } - else - { - uint64_t enter_time = CTimer::getTime(); - - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - { - int diff = int(CTimer::getTime() - enter_time) / 1000; - if (diff >= m_iRcvTimeOut) - break; - WaitForSingleObject(m_RecvDataCond, DWORD(m_iRcvTimeOut - diff )); - } - } - #endif - } - } - - // throw an exception if not connected - if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer->getRcvDataSize())) - throw CUDTException(2, 1, 0); - - int res = m_pRcvBuffer->readBuffer(data, len); - - if (m_pRcvBuffer->getRcvDataSize() <= 0) - { - // read is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, false); - } - - if ((res <= 0) && (m_iRcvTimeOut >= 0)) - throw CUDTException(6, 3, 0); - - return res; -} - -int CUDT::sendmsg(const char* data, int len, int msttl, bool inorder) -{ - if (UDT_STREAM == m_iSockType) - throw CUDTException(5, 9, 0); - - // throw an exception if not connected - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - - if (len <= 0) - return 0; - - if (len > m_iSndBufSize * m_iPayloadSize) - throw CUDTException(5, 12, 0); - - CGuard sendguard(m_SendLock); - - if (m_pSndBuffer->getCurrBufSize() == 0) - { - // delay the EXP timer to avoid mis-fired timeout - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - } - - if ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len) - { - if (!m_bSynSending) - throw CUDTException(6, 1, 0); - else - { - // wait here during a blocking sending - #ifndef WIN32 - pthread_mutex_lock(&m_SendBlockLock); - if (m_iSndTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len)) - pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; - timespec locktime; - - locktime.tv_sec = exptime / 1000000; - locktime.tv_nsec = (exptime % 1000000) * 1000; - - while (!m_bBroken && m_bConnected && !m_bClosing && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len) && (CTimer::getTime() < exptime)) - pthread_cond_timedwait(&m_SendBlockCond, &m_SendBlockLock, &locktime); - } - pthread_mutex_unlock(&m_SendBlockLock); - #else - if (m_iSndTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len)) - WaitForSingleObject(m_SendBlockCond, INFINITE); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; - - while (!m_bBroken && m_bConnected && !m_bClosing && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len) && (CTimer::getTime() < exptime)) - WaitForSingleObject(m_SendBlockCond, DWORD((exptime - CTimer::getTime()) / 1000)); - } - #endif - - // check the connection status - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - } - } - - if ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len) - { - if (m_iSndTimeOut >= 0) - throw CUDTException(6, 3, 0); - - return 0; - } - - // record total time used for sending - if (0 == m_pSndBuffer->getCurrBufSize()) - m_llSndDurationCounter = CTimer::getTime(); - - // insert the user buffer into the sening list - m_pSndBuffer->addBuffer(data, len, msttl, inorder); - - // insert this socket to the snd list if it is not on the list yet - m_pSndQueue->m_pSndUList->update(this, false); - - if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) - { - // write is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, false); - } - - return len; -} - -int CUDT::recvmsg(char* data, int len) -{ - if (UDT_STREAM == m_iSockType) - throw CUDTException(5, 9, 0); - - // throw an exception if not connected - if (!m_bConnected) - throw CUDTException(2, 2, 0); - - if (len <= 0) - return 0; - - CGuard recvguard(m_RecvLock); - - if (m_bBroken || m_bClosing) - { - int res = m_pRcvBuffer->readMsg(data, len); - - if (m_pRcvBuffer->getRcvMsgNum() <= 0) - { - // read is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, false); - } - - if (0 == res) - throw CUDTException(2, 1, 0); - else - return res; - } - - if (!m_bSynRecving) - { - int res = m_pRcvBuffer->readMsg(data, len); - if (0 == res) - throw CUDTException(6, 2, 0); - else - return res; - } - - int res = 0; - bool timeout = false; - - do - { - #ifndef WIN32 - pthread_mutex_lock(&m_RecvDataLock); - - if (m_iRcvTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == (res = m_pRcvBuffer->readMsg(data, len)))) - pthread_cond_wait(&m_RecvDataCond, &m_RecvDataLock); - } - else - { - uint64_t exptime = CTimer::getTime() + m_iRcvTimeOut * 1000ULL; - timespec locktime; - - locktime.tv_sec = exptime / 1000000; - locktime.tv_nsec = (exptime % 1000000) * 1000; - - if (pthread_cond_timedwait(&m_RecvDataCond, &m_RecvDataLock, &locktime) == ETIMEDOUT) - timeout = true; - - res = m_pRcvBuffer->readMsg(data, len); - } - pthread_mutex_unlock(&m_RecvDataLock); - #else - if (m_iRcvTimeOut < 0) - { - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == (res = m_pRcvBuffer->readMsg(data, len)))) - WaitForSingleObject(m_RecvDataCond, INFINITE); - } - else - { - if (WaitForSingleObject(m_RecvDataCond, DWORD(m_iRcvTimeOut)) == WAIT_TIMEOUT) - timeout = true; - - res = m_pRcvBuffer->readMsg(data, len); - } - #endif - - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - } while ((0 == res) && !timeout); - - if (m_pRcvBuffer->getRcvMsgNum() <= 0) - { - // read is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, false); - } - - if ((res <= 0) && (m_iRcvTimeOut >= 0)) - throw CUDTException(6, 3, 0); - - return res; -} - -int64_t CUDT::sendfile(fstream& ifs, int64_t& offset, int64_t size, int block) -{ - if (UDT_DGRAM == m_iSockType) - throw CUDTException(5, 10, 0); - - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - - if (size <= 0) - return 0; - - CGuard sendguard(m_SendLock); - - if (m_pSndBuffer->getCurrBufSize() == 0) - { - // delay the EXP timer to avoid mis-fired timeout - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - } - - int64_t tosend = size; - int unitsize; - - // positioning... - try - { - ifs.seekg((streamoff)offset); - } - catch (...) - { - throw CUDTException(4, 1); - } - - // sending block by block - while (tosend > 0) - { - if (ifs.fail()) - throw CUDTException(4, 4); - - if (ifs.eof()) - break; - - unitsize = int((tosend >= block) ? block : tosend); - - #ifndef WIN32 - pthread_mutex_lock(&m_SendBlockLock); - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth) - pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); - pthread_mutex_unlock(&m_SendBlockLock); - #else - while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) && m_bPeerHealth) - WaitForSingleObject(m_SendBlockCond, INFINITE); - #endif - - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - else if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if (!m_bPeerHealth) - { - // reset peer health status, once this error returns, the app should handle the situation at the peer side - m_bPeerHealth = true; - throw CUDTException(7); - } - - // record total time used for sending - if (0 == m_pSndBuffer->getCurrBufSize()) - m_llSndDurationCounter = CTimer::getTime(); - - int64_t sentsize = m_pSndBuffer->addBufferFromFile(ifs, unitsize); - - if (sentsize > 0) - { - tosend -= sentsize; - offset += sentsize; - } - - // insert this socket to snd list if it is not on the list yet - m_pSndQueue->m_pSndUList->update(this, false); - } - - if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) - { - // write is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, false); - } - - return size - tosend; -} - -int64_t CUDT::recvfile(fstream& ofs, int64_t& offset, int64_t size, int block) -{ - if (UDT_DGRAM == m_iSockType) - throw CUDTException(5, 10, 0); - - if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer->getRcvDataSize())) - throw CUDTException(2, 1, 0); - - if (size <= 0) - return 0; - - CGuard recvguard(m_RecvLock); - - int64_t torecv = size; - int unitsize = block; - int recvsize; - - // positioning... - try - { - ofs.seekp((streamoff)offset); - } - catch (...) - { - throw CUDTException(4, 3); - } - - // receiving... "recvfile" is always blocking - while (torecv > 0) - { - if (ofs.fail()) - { - // send the sender a signal so it will not be blocked forever - int32_t err_code = CUDTException::EFILE; - sendCtrl(8, &err_code); - - throw CUDTException(4, 4); - } - - #ifndef WIN32 - pthread_mutex_lock(&m_RecvDataLock); - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - pthread_cond_wait(&m_RecvDataCond, &m_RecvDataLock); - pthread_mutex_unlock(&m_RecvDataLock); - #else - while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer->getRcvDataSize())) - WaitForSingleObject(m_RecvDataCond, INFINITE); - #endif - - if (!m_bConnected) - throw CUDTException(2, 2, 0); - else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer->getRcvDataSize())) - throw CUDTException(2, 1, 0); - - unitsize = int((torecv >= block) ? block : torecv); - recvsize = m_pRcvBuffer->readBufferToFile(ofs, unitsize); - - if (recvsize > 0) - { - torecv -= recvsize; - offset += recvsize; - } - } - - if (m_pRcvBuffer->getRcvDataSize() <= 0) - { - // read is not available any more - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, false); - } - - return size - torecv; -} - -void CUDT::sample(CPerfMon* perf, bool clear) -{ - if (!m_bConnected) - throw CUDTException(2, 2, 0); - if (m_bBroken || m_bClosing) - throw CUDTException(2, 1, 0); - - uint64_t currtime = CTimer::getTime(); - perf->msTimeStamp = (currtime - m_StartTime) / 1000; - - perf->pktSent = m_llTraceSent; - perf->pktRecv = m_llTraceRecv; - perf->pktSndLoss = m_iTraceSndLoss; - perf->pktRcvLoss = m_iTraceRcvLoss; - perf->pktRetrans = m_iTraceRetrans; - perf->pktSentACK = m_iSentACK; - perf->pktRecvACK = m_iRecvACK; - perf->pktSentNAK = m_iSentNAK; - perf->pktRecvNAK = m_iRecvNAK; - perf->usSndDuration = m_llSndDuration; - - perf->pktSentTotal = m_llSentTotal; - perf->pktRecvTotal = m_llRecvTotal; - perf->pktSndLossTotal = m_iSndLossTotal; - perf->pktRcvLossTotal = m_iRcvLossTotal; - perf->pktRetransTotal = m_iRetransTotal; - perf->pktSentACKTotal = m_iSentACKTotal; - perf->pktRecvACKTotal = m_iRecvACKTotal; - perf->pktSentNAKTotal = m_iSentNAKTotal; - perf->pktRecvNAKTotal = m_iRecvNAKTotal; - perf->usSndDurationTotal = m_llSndDurationTotal; - - double interval = double(currtime - m_LastSampleTime); - - perf->mbpsSendRate = double(m_llTraceSent) * m_iPayloadSize * 8.0 / interval; - perf->mbpsRecvRate = double(m_llTraceRecv) * m_iPayloadSize * 8.0 / interval; - - perf->usPktSndPeriod = m_ullInterval / double(m_ullCPUFrequency); - perf->pktFlowWindow = m_iFlowWindowSize; - perf->pktCongestionWindow = (int)m_dCongestionWindow; - perf->pktFlightSize = CSeqNo::seqlen(m_iSndLastAck, CSeqNo::incseq(m_iSndCurrSeqNo)) - 1; - perf->msRTT = m_iRTT/1000.0; - perf->mbpsBandwidth = m_iBandwidth * m_iPayloadSize * 8.0 / 1000000.0; - - #ifndef WIN32 - if (0 == pthread_mutex_trylock(&m_ConnectionLock)) - #else - if (WAIT_OBJECT_0 == WaitForSingleObject(m_ConnectionLock, 0)) - #endif - { - perf->byteAvailSndBuf = (NULL == m_pSndBuffer) ? 0 : (m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iMSS; - perf->byteAvailRcvBuf = (NULL == m_pRcvBuffer) ? 0 : m_pRcvBuffer->getAvailBufSize() * m_iMSS; - - #ifndef WIN32 - pthread_mutex_unlock(&m_ConnectionLock); - #else - ReleaseMutex(m_ConnectionLock); - #endif - } - else - { - perf->byteAvailSndBuf = 0; - perf->byteAvailRcvBuf = 0; - } - - if (clear) - { - m_llTraceSent = m_llTraceRecv = m_iTraceSndLoss = m_iTraceRcvLoss = m_iTraceRetrans = m_iSentACK = m_iRecvACK = m_iSentNAK = m_iRecvNAK = 0; - m_llSndDuration = 0; - m_LastSampleTime = currtime; - } -} - -void CUDT::CCUpdate() -{ - m_ullInterval = (uint64_t)(m_pCC->m_dPktSndPeriod * m_ullCPUFrequency); - m_dCongestionWindow = m_pCC->m_dCWndSize; - - if (m_llMaxBW <= 0) - return; - const double minSP = 1000000.0 / (double(m_llMaxBW) / m_iMSS) * m_ullCPUFrequency; - if (m_ullInterval < minSP) - m_ullInterval = minSP; -} - -void CUDT::initSynch() -{ - #ifndef WIN32 - pthread_mutex_init(&m_SendBlockLock, NULL); - pthread_cond_init(&m_SendBlockCond, NULL); - pthread_mutex_init(&m_RecvDataLock, NULL); - pthread_cond_init(&m_RecvDataCond, NULL); - pthread_mutex_init(&m_SendLock, NULL); - pthread_mutex_init(&m_RecvLock, NULL); - pthread_mutex_init(&m_AckLock, NULL); - pthread_mutex_init(&m_ConnectionLock, NULL); - #else - m_SendBlockLock = CreateMutex(NULL, false, NULL); - m_SendBlockCond = CreateEvent(NULL, false, false, NULL); - m_RecvDataLock = CreateMutex(NULL, false, NULL); - m_RecvDataCond = CreateEvent(NULL, false, false, NULL); - m_SendLock = CreateMutex(NULL, false, NULL); - m_RecvLock = CreateMutex(NULL, false, NULL); - m_AckLock = CreateMutex(NULL, false, NULL); - m_ConnectionLock = CreateMutex(NULL, false, NULL); - #endif -} - -void CUDT::destroySynch() -{ - #ifndef WIN32 - pthread_mutex_destroy(&m_SendBlockLock); - pthread_cond_destroy(&m_SendBlockCond); - pthread_mutex_destroy(&m_RecvDataLock); - pthread_cond_destroy(&m_RecvDataCond); - pthread_mutex_destroy(&m_SendLock); - pthread_mutex_destroy(&m_RecvLock); - pthread_mutex_destroy(&m_AckLock); - pthread_mutex_destroy(&m_ConnectionLock); - #else - CloseHandle(m_SendBlockLock); - CloseHandle(m_SendBlockCond); - CloseHandle(m_RecvDataLock); - CloseHandle(m_RecvDataCond); - CloseHandle(m_SendLock); - CloseHandle(m_RecvLock); - CloseHandle(m_AckLock); - CloseHandle(m_ConnectionLock); - #endif -} - -void CUDT::releaseSynch() -{ - #ifndef WIN32 - // wake up user calls - pthread_mutex_lock(&m_SendBlockLock); - pthread_cond_signal(&m_SendBlockCond); - pthread_mutex_unlock(&m_SendBlockLock); - - pthread_mutex_lock(&m_SendLock); - pthread_mutex_unlock(&m_SendLock); - - pthread_mutex_lock(&m_RecvDataLock); - pthread_cond_signal(&m_RecvDataCond); - pthread_mutex_unlock(&m_RecvDataLock); - - pthread_mutex_lock(&m_RecvLock); - pthread_mutex_unlock(&m_RecvLock); - #else - SetEvent(m_SendBlockCond); - WaitForSingleObject(m_SendLock, INFINITE); - ReleaseMutex(m_SendLock); - SetEvent(m_RecvDataCond); - WaitForSingleObject(m_RecvLock, INFINITE); - ReleaseMutex(m_RecvLock); - #endif -} - -void CUDT::sendCtrl(int pkttype, void* lparam, void* rparam, int size) -{ - CPacket ctrlpkt; - - switch (pkttype) - { - case 2: //010 - Acknowledgement - { - int32_t ack; - - // If there is no loss, the ACK is the current largest sequence number plus 1; - // Otherwise it is the smallest sequence number in the receiver loss list. - if (0 == m_pRcvLossList->getLossLength()) - ack = CSeqNo::incseq(m_iRcvCurrSeqNo); - else - ack = m_pRcvLossList->getFirstLostSeq(); - - if (ack == m_iRcvLastAckAck) - break; - - // send out a lite ACK - // to save time on buffer processing and bandwidth/AS measurement, a lite ACK only feeds back an ACK number - if (4 == size) - { - ctrlpkt.pack(pkttype, NULL, &ack, size); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - } - - uint64_t currtime; - CTimer::rdtsc(currtime); - - // There are new received packets to acknowledge, update related information. - if (CSeqNo::seqcmp(ack, m_iRcvLastAck) > 0) - { - int acksize = CSeqNo::seqoff(m_iRcvLastAck, ack); - - m_iRcvLastAck = ack; - - m_pRcvBuffer->ackData(acksize); - - // signal a waiting "recv" call if there is any data available - #ifndef WIN32 - pthread_mutex_lock(&m_RecvDataLock); - if (m_bSynRecving) - pthread_cond_signal(&m_RecvDataCond); - pthread_mutex_unlock(&m_RecvDataLock); - #else - if (m_bSynRecving) - SetEvent(m_RecvDataCond); - #endif - - // acknowledge any waiting epolls to read - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, true); - } - else if (ack == m_iRcvLastAck) - { - if ((currtime - m_ullLastAckTime) < ((m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency)) - break; - } - else - break; - - // Send out the ACK only if has not been received by the sender before - if (CSeqNo::seqcmp(m_iRcvLastAck, m_iRcvLastAckAck) > 0) - { - int32_t data[6]; - - m_iAckSeqNo = CAckNo::incack(m_iAckSeqNo); - data[0] = m_iRcvLastAck; - data[1] = m_iRTT; - data[2] = m_iRTTVar; - data[3] = m_pRcvBuffer->getAvailBufSize(); - // a minimum flow window of 2 is used, even if buffer is full, to break potential deadlock - if (data[3] < 2) - data[3] = 2; - - if (currtime - m_ullLastAckTime > m_ullSYNInt) - { - data[4] = m_pRcvTimeWindow->getPktRcvSpeed(); - data[5] = m_pRcvTimeWindow->getBandwidth(); - ctrlpkt.pack(pkttype, &m_iAckSeqNo, data, 24); - - CTimer::rdtsc(m_ullLastAckTime); - } - else - { - ctrlpkt.pack(pkttype, &m_iAckSeqNo, data, 16); - } - - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - m_pACKWindow->store(m_iAckSeqNo, m_iRcvLastAck); - - ++ m_iSentACK; - ++ m_iSentACKTotal; - } - - break; - } - - case 6: //110 - Acknowledgement of Acknowledgement - ctrlpkt.pack(pkttype, lparam); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 3: //011 - Loss Report - { - if (NULL != rparam) - { - if (1 == size) - { - // only 1 loss packet - ctrlpkt.pack(pkttype, NULL, (int32_t *)rparam + 1, 4); - } - else - { - // more than 1 loss packets - ctrlpkt.pack(pkttype, NULL, rparam, 8); - } - - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - ++ m_iSentNAK; - ++ m_iSentNAKTotal; - } - else if (m_pRcvLossList->getLossLength() > 0) - { - // this is periodically NAK report; make sure NAK cannot be sent back too often - - // read loss list from the local receiver loss list - int32_t* data = new int32_t[m_iPayloadSize / 4]; - int losslen; - m_pRcvLossList->getLossArray(data, losslen, m_iPayloadSize / 4); - - if (0 < losslen) - { - ctrlpkt.pack(pkttype, NULL, data, losslen * 4); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - ++ m_iSentNAK; - ++ m_iSentNAKTotal; - } - - delete [] data; - } - - // update next NAK time, which should wait enough time for the retansmission, but not too long - m_ullNAKInt = (m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency; - int rcv_speed = m_pRcvTimeWindow->getPktRcvSpeed(); - if (rcv_speed > 0) - m_ullNAKInt += (m_pRcvLossList->getLossLength() * 1000000ULL / rcv_speed) * m_ullCPUFrequency; - if (m_ullNAKInt < m_ullMinNakInt) - m_ullNAKInt = m_ullMinNakInt; - - break; - } - - case 4: //100 - Congestion Warning - ctrlpkt.pack(pkttype); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - CTimer::rdtsc(m_ullLastWarningTime); - - break; - - case 1: //001 - Keep-alive - ctrlpkt.pack(pkttype); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 0: //000 - Handshake - ctrlpkt.pack(pkttype, NULL, rparam, sizeof(CHandShake)); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 5: //101 - Shutdown - ctrlpkt.pack(pkttype); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 7: //111 - Msg drop request - ctrlpkt.pack(pkttype, lparam, rparam, 8); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 8: //1000 - acknowledge the peer side a special error - ctrlpkt.pack(pkttype, lparam); - ctrlpkt.m_iID = m_PeerID; - m_pSndQueue->sendto(m_pPeerAddr, ctrlpkt); - - break; - - case 32767: //0x7FFF - Resevered for future use - break; - - default: - break; - } -} - -void CUDT::processCtrl(CPacket& ctrlpkt) -{ - // Just heard from the peer, reset the expiration count. - m_iEXPCount = 1; - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - - switch (ctrlpkt.getType()) - { - case 2: //010 - Acknowledgement - { - int32_t ack; - - // process a lite ACK - if (4 == ctrlpkt.getLength()) - { - ack = *(int32_t *)ctrlpkt.m_pcData; - if (CSeqNo::seqcmp(ack, m_iSndLastAck) >= 0) - { - m_iFlowWindowSize -= CSeqNo::seqoff(m_iSndLastAck, ack); - m_iSndLastAck = ack; - } - - break; - } - - // read ACK seq. no. - ack = ctrlpkt.getAckSeqNo(); - - // send ACK acknowledgement - // number of ACK2 can be much less than number of ACK - uint64_t now = CTimer::getTime(); - if ((currtime - m_ullSndLastAck2Time > (uint64_t)m_iSYNInterval) || (ack == m_iSndLastAck2)) - { - sendCtrl(6, &ack); - m_iSndLastAck2 = ack; - m_ullSndLastAck2Time = now; - } - - // Got data ACK - ack = *(int32_t *)ctrlpkt.m_pcData; - - // check the validation of the ack - if (CSeqNo::seqcmp(ack, CSeqNo::incseq(m_iSndCurrSeqNo)) > 0) - { - //this should not happen: attack or bug - m_bBroken = true; - m_iBrokenCounter = 0; - break; - } - - if (CSeqNo::seqcmp(ack, m_iSndLastAck) >= 0) - { - // Update Flow Window Size, must update before and together with m_iSndLastAck - m_iFlowWindowSize = *((int32_t *)ctrlpkt.m_pcData + 3); - m_iSndLastAck = ack; - } - - // protect packet retransmission - CGuard::enterCS(m_AckLock); - - int offset = CSeqNo::seqoff(m_iSndLastDataAck, ack); - if (offset <= 0) - { - // discard it if it is a repeated ACK - CGuard::leaveCS(m_AckLock); - break; - } - - // acknowledge the sending buffer - m_pSndBuffer->ackData(offset); - - // record total time used for sending - m_llSndDuration += currtime - m_llSndDurationCounter; - m_llSndDurationTotal += currtime - m_llSndDurationCounter; - m_llSndDurationCounter = currtime; - - // update sending variables - m_iSndLastDataAck = ack; - m_pSndLossList->remove(CSeqNo::decseq(m_iSndLastDataAck)); - - CGuard::leaveCS(m_AckLock); - - #ifndef WIN32 - pthread_mutex_lock(&m_SendBlockLock); - if (m_bSynSending) - pthread_cond_signal(&m_SendBlockCond); - pthread_mutex_unlock(&m_SendBlockLock); - #else - if (m_bSynSending) - SetEvent(m_SendBlockCond); - #endif - - // acknowledde any waiting epolls to write - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, true); - - // insert this socket to snd list if it is not on the list yet - m_pSndQueue->m_pSndUList->update(this, false); - - // Update RTT - //m_iRTT = *((int32_t *)ctrlpkt.m_pcData + 1); - //m_iRTTVar = *((int32_t *)ctrlpkt.m_pcData + 2); - int rtt = *((int32_t *)ctrlpkt.m_pcData + 1); - m_iRTTVar = (m_iRTTVar * 3 + abs(rtt - m_iRTT)) >> 2; - m_iRTT = (m_iRTT * 7 + rtt) >> 3; - - m_pCC->setRTT(m_iRTT); - - if (ctrlpkt.getLength() > 16) - { - // Update Estimated Bandwidth and packet delivery rate - if (*((int32_t *)ctrlpkt.m_pcData + 4) > 0) - m_iDeliveryRate = (m_iDeliveryRate * 7 + *((int32_t *)ctrlpkt.m_pcData + 4)) >> 3; - - if (*((int32_t *)ctrlpkt.m_pcData + 5) > 0) - m_iBandwidth = (m_iBandwidth * 7 + *((int32_t *)ctrlpkt.m_pcData + 5)) >> 3; - - m_pCC->setRcvRate(m_iDeliveryRate); - m_pCC->setBandwidth(m_iBandwidth); - } - - m_pCC->onACK(ack); - CCUpdate(); - - ++ m_iRecvACK; - ++ m_iRecvACKTotal; - - break; - } - - case 6: //110 - Acknowledgement of Acknowledgement - { - int32_t ack; - int rtt = -1; - - // update RTT - rtt = m_pACKWindow->acknowledge(ctrlpkt.getAckSeqNo(), ack); - if (rtt <= 0) - break; - - //if increasing delay detected... - // sendCtrl(4); - - // RTT EWMA - m_iRTTVar = (m_iRTTVar * 3 + abs(rtt - m_iRTT)) >> 2; - m_iRTT = (m_iRTT * 7 + rtt) >> 3; - - m_pCC->setRTT(m_iRTT); - - // update last ACK that has been received by the sender - if (CSeqNo::seqcmp(ack, m_iRcvLastAckAck) > 0) - m_iRcvLastAckAck = ack; - - break; - } - - case 3: //011 - Loss Report - { - int32_t* losslist = (int32_t *)(ctrlpkt.m_pcData); - - m_pCC->onLoss(losslist, ctrlpkt.getLength() / 4); - CCUpdate(); - - bool secure = true; - - // decode loss list message and insert loss into the sender loss list - for (int i = 0, n = (int)(ctrlpkt.getLength() / 4); i < n; ++ i) - { - if (0 != (losslist[i] & 0x80000000)) - { - if ((CSeqNo::seqcmp(losslist[i] & 0x7FFFFFFF, losslist[i + 1]) > 0) || (CSeqNo::seqcmp(losslist[i + 1], m_iSndCurrSeqNo) > 0)) - { - // seq_a must not be greater than seq_b; seq_b must not be greater than the most recent sent seq - secure = false; - break; - } - - int num = 0; - if (CSeqNo::seqcmp(losslist[i] & 0x7FFFFFFF, m_iSndLastAck) >= 0) - num = m_pSndLossList->insert(losslist[i] & 0x7FFFFFFF, losslist[i + 1]); - else if (CSeqNo::seqcmp(losslist[i + 1], m_iSndLastAck) >= 0) - num = m_pSndLossList->insert(m_iSndLastAck, losslist[i + 1]); - - m_iTraceSndLoss += num; - m_iSndLossTotal += num; - - ++ i; - } - else if (CSeqNo::seqcmp(losslist[i], m_iSndLastAck) >= 0) - { - if (CSeqNo::seqcmp(losslist[i], m_iSndCurrSeqNo) > 0) - { - //seq_a must not be greater than the most recent sent seq - secure = false; - break; - } - - int num = m_pSndLossList->insert(losslist[i], losslist[i]); - - m_iTraceSndLoss += num; - m_iSndLossTotal += num; - } - } - - if (!secure) - { - //this should not happen: attack or bug - m_bBroken = true; - m_iBrokenCounter = 0; - break; - } - - // the lost packet (retransmission) should be sent out immediately - m_pSndQueue->m_pSndUList->update(this); - - ++ m_iRecvNAK; - ++ m_iRecvNAKTotal; - - break; - } - - case 4: //100 - Delay Warning - // One way packet delay is increasing, so decrease the sending rate - m_ullInterval = (uint64_t)ceil(m_ullInterval * 1.125); - m_iLastDecSeq = m_iSndCurrSeqNo; - - break; - - case 1: //001 - Keep-alive - // The only purpose of keep-alive packet is to tell that the peer is still alive - // nothing needs to be done. - - break; - - case 0: //000 - Handshake - { - CHandShake req; - req.deserialize(ctrlpkt.m_pcData, ctrlpkt.getLength()); - if ((req.m_iReqType > 0) || (m_bRendezvous && (req.m_iReqType != -2))) - { - // The peer side has not received the handshake message, so it keeps querying - // resend the handshake packet - - CHandShake initdata; - initdata.m_iISN = m_iISN; - initdata.m_iMSS = m_iMSS; - initdata.m_iFlightFlagSize = m_iFlightFlagSize; - initdata.m_iReqType = (!m_bRendezvous) ? -1 : -2; - initdata.m_iID = m_SocketID; - - char* hs = new char [m_iPayloadSize]; - int hs_size = m_iPayloadSize; - initdata.serialize(hs, hs_size); - sendCtrl(0, NULL, hs, hs_size); - delete [] hs; - } - - break; - } - - case 5: //101 - Shutdown - m_bShutdown = true; - m_bClosing = true; - m_bBroken = true; - m_iBrokenCounter = 60; - - // Signal the sender and recver if they are waiting for data. - releaseSynch(); - - CTimer::triggerEvent(); - - break; - - case 7: //111 - Msg drop request - m_pRcvBuffer->dropMsg(ctrlpkt.getMsgSeq()); - m_pRcvLossList->remove(*(int32_t*)ctrlpkt.m_pcData, *(int32_t*)(ctrlpkt.m_pcData + 4)); - - // move forward with current recv seq no. - if ((CSeqNo::seqcmp(*(int32_t*)ctrlpkt.m_pcData, CSeqNo::incseq(m_iRcvCurrSeqNo)) <= 0) - && (CSeqNo::seqcmp(*(int32_t*)(ctrlpkt.m_pcData + 4), m_iRcvCurrSeqNo) > 0)) - { - m_iRcvCurrSeqNo = *(int32_t*)(ctrlpkt.m_pcData + 4); - } - - break; - - case 8: // 1000 - An error has happened to the peer side - //int err_type = packet.getAddInfo(); - - // currently only this error is signalled from the peer side - // if recvfile() failes (e.g., due to disk fail), blcoked sendfile/send should return immediately - // giving the app a chance to fix the issue - - m_bPeerHealth = false; - - break; - - case 32767: //0x7FFF - reserved and user defined messages - m_pCC->processCustomMsg(&ctrlpkt); - CCUpdate(); - - break; - - default: - break; - } -} - -int CUDT::packData(CPacket& packet, uint64_t& ts) -{ - int payload = 0; - bool probe = false; - - uint64_t entertime; - CTimer::rdtsc(entertime); - - if ((0 != m_ullTargetTime) && (entertime > m_ullTargetTime)) - m_ullTimeDiff += entertime - m_ullTargetTime; - - // Loss retransmission always has higher priority. - if ((packet.m_iSeqNo = m_pSndLossList->getLostSeq()) >= 0) - { - // protect m_iSndLastDataAck from updating by ACK processing - CGuard ackguard(m_AckLock); - - int offset = CSeqNo::seqoff(m_iSndLastDataAck, packet.m_iSeqNo); - if (offset < 0) - return 0; - - int msglen; - - payload = m_pSndBuffer->readData(&(packet.m_pcData), offset, packet.m_iMsgNo, msglen); - - if (-1 == payload) - { - int32_t seqpair[2]; - seqpair[0] = packet.m_iSeqNo; - seqpair[1] = CSeqNo::incseq(seqpair[0], msglen); - sendCtrl(7, &packet.m_iMsgNo, seqpair, 8); - - // only one msg drop request is necessary - m_pSndLossList->remove(seqpair[1]); - - // skip all dropped packets - if (CSeqNo::seqcmp(m_iSndCurrSeqNo, CSeqNo::incseq(seqpair[1])) < 0) - m_iSndCurrSeqNo = CSeqNo::incseq(seqpair[1]); - - return 0; - } - else if (0 == payload) - return 0; - - ++ m_iTraceRetrans; - ++ m_iRetransTotal; - } - else - { - // If no loss, pack a new packet. - - // check congestion/flow window limit - int cwnd = (m_iFlowWindowSize < (int)m_dCongestionWindow) ? m_iFlowWindowSize : (int)m_dCongestionWindow; - if (cwnd >= CSeqNo::seqlen(m_iSndLastAck, CSeqNo::incseq(m_iSndCurrSeqNo))) - { - if (0 != (payload = m_pSndBuffer->readData(&(packet.m_pcData), packet.m_iMsgNo))) - { - m_iSndCurrSeqNo = CSeqNo::incseq(m_iSndCurrSeqNo); - m_pCC->setSndCurrSeqNo(m_iSndCurrSeqNo); - - packet.m_iSeqNo = m_iSndCurrSeqNo; - - // every 16 (0xF) packets, a packet pair is sent - if (0 == (packet.m_iSeqNo & 0xF)) - probe = true; - } - else - { - m_ullTargetTime = 0; - m_ullTimeDiff = 0; - ts = 0; - return 0; - } - } - else - { - m_ullTargetTime = 0; - m_ullTimeDiff = 0; - ts = 0; - return 0; - } - } - - packet.m_iTimeStamp = int(CTimer::getTime() - m_StartTime); - packet.m_iID = m_PeerID; - packet.setLength(payload); - - m_pCC->onPktSent(&packet); - //m_pSndTimeWindow->onPktSent(packet.m_iTimeStamp); - - ++ m_llTraceSent; - ++ m_llSentTotal; - - if (probe) - { - // sends out probing packet pair - ts = entertime; - probe = false; - } - else - { - #ifndef NO_BUSY_WAITING - ts = entertime + m_ullInterval; - #else - if (m_ullTimeDiff >= m_ullInterval) - { - ts = entertime; - m_ullTimeDiff -= m_ullInterval; - } - else - { - ts = entertime + m_ullInterval - m_ullTimeDiff; - m_ullTimeDiff = 0; - } - #endif - } - - m_ullTargetTime = ts; - - return payload; -} - -int CUDT::processData(CUnit* unit) -{ - CPacket& packet = unit->m_Packet; - - // Just heard from the peer, reset the expiration count. - m_iEXPCount = 1; - uint64_t currtime; - CTimer::rdtsc(currtime); - m_ullLastRspTime = currtime; - - m_pCC->onPktReceived(&packet); - ++ m_iPktCount; - // update time information - m_pRcvTimeWindow->onPktArrival(); - - // check if it is probing packet pair - if (0 == (packet.m_iSeqNo & 0xF)) - m_pRcvTimeWindow->probe1Arrival(); - else if (1 == (packet.m_iSeqNo & 0xF)) - m_pRcvTimeWindow->probe2Arrival(); - - ++ m_llTraceRecv; - ++ m_llRecvTotal; - - int32_t offset = CSeqNo::seqoff(m_iRcvLastAck, packet.m_iSeqNo); - if ((offset < 0) || (offset >= m_pRcvBuffer->getAvailBufSize())) - return -1; - - if (m_pRcvBuffer->addData(unit, offset) < 0) - return -1; - - // Loss detection. - if (CSeqNo::seqcmp(packet.m_iSeqNo, CSeqNo::incseq(m_iRcvCurrSeqNo)) > 0) - { - // If loss found, insert them to the receiver loss list - m_pRcvLossList->insert(CSeqNo::incseq(m_iRcvCurrSeqNo), CSeqNo::decseq(packet.m_iSeqNo)); - - // pack loss list for NAK - int32_t lossdata[2]; - lossdata[0] = CSeqNo::incseq(m_iRcvCurrSeqNo) | 0x80000000; - lossdata[1] = CSeqNo::decseq(packet.m_iSeqNo); - - // Generate loss report immediately. - sendCtrl(3, NULL, lossdata, (CSeqNo::incseq(m_iRcvCurrSeqNo) == CSeqNo::decseq(packet.m_iSeqNo)) ? 1 : 2); - - int loss = CSeqNo::seqlen(m_iRcvCurrSeqNo, packet.m_iSeqNo) - 2; - m_iTraceRcvLoss += loss; - m_iRcvLossTotal += loss; - } - - // This is not a regular fixed size packet... - //an irregular sized packet usually indicates the end of a message, so send an ACK immediately - if (packet.getLength() != m_iPayloadSize) - CTimer::rdtsc(m_ullNextACKTime); - - // Update the current largest sequence number that has been received. - // Or it is a retransmitted packet, remove it from receiver loss list. - if (CSeqNo::seqcmp(packet.m_iSeqNo, m_iRcvCurrSeqNo) > 0) - m_iRcvCurrSeqNo = packet.m_iSeqNo; - else - m_pRcvLossList->remove(packet.m_iSeqNo); - - return 0; -} - -int CUDT::listen(sockaddr* addr, CPacket& packet) -{ - if (m_bClosing) - return 1002; - - if (packet.getLength() != CHandShake::m_iContentSize) - return 1004; - - CHandShake hs; - hs.deserialize(packet.m_pcData, packet.getLength()); - - // SYN cookie - char clienthost[NI_MAXHOST]; - char clientport[NI_MAXSERV]; - getnameinfo(addr, (AF_INET == m_iVersion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6), clienthost, sizeof(clienthost), clientport, sizeof(clientport), NI_NUMERICHOST|NI_NUMERICSERV); - int64_t timestamp = (CTimer::getTime() - m_StartTime) / 60000000; // secret changes every one minute - stringstream cookiestr; - cookiestr << clienthost << ":" << clientport << ":" << timestamp; - unsigned char cookie[16]; - CMD5::compute(cookiestr.str().c_str(), cookie); - - if (1 == hs.m_iReqType) - { - hs.m_iCookie = *(int*)cookie; - packet.m_iID = hs.m_iID; - int size = packet.getLength(); - hs.serialize(packet.m_pcData, size); - m_pSndQueue->sendto(addr, packet); - return 0; - } - else - { - if (hs.m_iCookie != *(int*)cookie) - { - timestamp --; - cookiestr << clienthost << ":" << clientport << ":" << timestamp; - CMD5::compute(cookiestr.str().c_str(), cookie); - - if (hs.m_iCookie != *(int*)cookie) - return -1; - } - } - - int32_t id = hs.m_iID; - - // When a peer side connects in... - if ((1 == packet.getFlag()) && (0 == packet.getType())) - { - if ((hs.m_iVersion != m_iVersion) || (hs.m_iType != m_iSockType)) - { - // mismatch, reject the request - hs.m_iReqType = 1002; - int size = CHandShake::m_iContentSize; - hs.serialize(packet.m_pcData, size); - packet.m_iID = id; - m_pSndQueue->sendto(addr, packet); - } - else - { - int result = s_UDTUnited.newConnection(m_SocketID, addr, &hs); - if (result == -1) - hs.m_iReqType = 1002; - - // send back a response if connection failed or connection already existed - // new connection response should be sent in connect() - if (result != 1) - { - int size = CHandShake::m_iContentSize; - hs.serialize(packet.m_pcData, size); - packet.m_iID = id; - m_pSndQueue->sendto(addr, packet); - } - else - { - // a new connection has been created, enable epoll for write - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, true); - } - } - } - - return hs.m_iReqType; -} - -void CUDT::checkTimers() -{ - // update CC parameters - CCUpdate(); - //uint64_t minint = (uint64_t)(m_ullCPUFrequency * m_pSndTimeWindow->getMinPktSndInt() * 0.9); - //if (m_ullInterval < minint) - // m_ullInterval = minint; - - uint64_t currtime; - CTimer::rdtsc(currtime); - - if ((currtime > m_ullNextACKTime) || ((m_pCC->m_iACKInterval > 0) && (m_pCC->m_iACKInterval <= m_iPktCount))) - { - // ACK timer expired or ACK interval is reached - - sendCtrl(2); - CTimer::rdtsc(currtime); - if (m_pCC->m_iACKPeriod > 0) - m_ullNextACKTime = currtime + m_pCC->m_iACKPeriod * m_ullCPUFrequency; - else - m_ullNextACKTime = currtime + m_ullACKInt; - - m_iPktCount = 0; - m_iLightACKCount = 1; - } - else if (m_iSelfClockInterval * m_iLightACKCount <= m_iPktCount) - { - //send a "light" ACK - sendCtrl(2, NULL, NULL, 4); - ++ m_iLightACKCount; - } - - // we are not sending back repeated NAK anymore and rely on the sender's EXP for retransmission - //if ((m_pRcvLossList->getLossLength() > 0) && (currtime > m_ullNextNAKTime)) - //{ - // // NAK timer expired, and there is loss to be reported. - // sendCtrl(3); - // - // CTimer::rdtsc(currtime); - // m_ullNextNAKTime = currtime + m_ullNAKInt; - //} - - uint64_t next_exp_time; - if (m_pCC->m_bUserDefinedRTO) - next_exp_time = m_ullLastRspTime + m_pCC->m_iRTO * m_ullCPUFrequency; - else - { - uint64_t exp_int = (m_iEXPCount * (m_iRTT + 4 * m_iRTTVar) + m_iSYNInterval) * m_ullCPUFrequency; - if (exp_int < m_iEXPCount * m_ullMinExpInt) - exp_int = m_iEXPCount * m_ullMinExpInt; - next_exp_time = m_ullLastRspTime + exp_int; - } - - if (currtime > next_exp_time) - { - // Haven't receive any information from the peer, is it dead?! - // timeout: at least 16 expirations and must be greater than 10 seconds - if ((m_iEXPCount > 16) && (currtime - m_ullLastRspTime > 5000000 * m_ullCPUFrequency)) - { - // - // Connection is broken. - // UDT does not signal any information about this instead of to stop quietly. - // Application will detect this when it calls any UDT methods next time. - // - m_bClosing = true; - m_bBroken = true; - m_iBrokenCounter = 30; - - // update snd U list to remove this socket - m_pSndQueue->m_pSndUList->update(this); - - releaseSynch(); - - // app can call any UDT API to learn the connection_broken error - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN | UDT_EPOLL_OUT | UDT_EPOLL_ERR, true); - - CTimer::triggerEvent(); - - return; - } - - // sender: Insert all the packets sent after last received acknowledgement into the sender loss list. - // recver: Send out a keep-alive packet - if (m_pSndBuffer->getCurrBufSize() > 0) - { - if ((CSeqNo::incseq(m_iSndCurrSeqNo) != m_iSndLastAck) && (m_pSndLossList->getLossLength() == 0)) - { - // resend all unacknowledged packets on timeout, but only if there is no packet in the loss list - int32_t csn = m_iSndCurrSeqNo; - int num = m_pSndLossList->insert(m_iSndLastAck, csn); - m_iTraceSndLoss += num; - m_iSndLossTotal += num; - } - - m_pCC->onTimeout(); - CCUpdate(); - - // immediately restart transmission - m_pSndQueue->m_pSndUList->update(this); - } - else - { - sendCtrl(1); - } - - ++ m_iEXPCount; - // Reset last response time since we just sent a heart-beat. - m_ullLastRspTime = currtime; - } -} - -void CUDT::addEPoll(const int eid) -{ - CGuard::enterCS(s_UDTUnited.m_EPoll.m_EPollLock); - m_sPollID.insert(eid); - CGuard::leaveCS(s_UDTUnited.m_EPoll.m_EPollLock); - - if (!m_bConnected || m_bBroken || m_bClosing) - return; - - if (((UDT_STREAM == m_iSockType) && (m_pRcvBuffer->getRcvDataSize() > 0)) || - ((UDT_DGRAM == m_iSockType) && (m_pRcvBuffer->getRcvMsgNum() > 0))) - { - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_IN, true); - } - if (m_iSndBufSize > m_pSndBuffer->getCurrBufSize()) - { - s_UDTUnited.m_EPoll.update_events(m_SocketID, m_sPollID, UDT_EPOLL_OUT, true); - } -} - -void CUDT::removeEPoll(const int eid) -{ - // clear IO events notifications; - // since this happens after the epoll ID has been removed, they cannot be set again - set remove; - remove.insert(eid); - s_UDTUnited.m_EPoll.update_events(m_SocketID, remove, UDT_EPOLL_IN | UDT_EPOLL_OUT, false); - - CGuard::enterCS(s_UDTUnited.m_EPoll.m_EPollLock); - m_sPollID.erase(eid); - CGuard::leaveCS(s_UDTUnited.m_EPoll.m_EPollLock); -} diff --git a/vendor/udt4/src/core.h b/vendor/udt4/src/core.h deleted file mode 100644 index 47caa79..0000000 --- a/vendor/udt4/src/core.h +++ /dev/null @@ -1,458 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 02/28/2012 -*****************************************************************************/ - -#ifndef __UDT_CORE_H__ -#define __UDT_CORE_H__ - - -#include "udt.h" -#include "common.h" -#include "list.h" -#include "buffer.h" -#include "window.h" -#include "packet.h" -#include "channel.h" -#include "api.h" -#include "ccc.h" -#include "cache.h" -#include "queue.h" - -enum UDTSockType {UDT_STREAM = 1, UDT_DGRAM}; - -class CUDT -{ -friend class CUDTSocket; -friend class CUDTUnited; -friend class CCC; -friend struct CUDTComp; -friend class CCache; -friend class CRendezvousQueue; -friend class CSndQueue; -friend class CRcvQueue; -friend class CSndUList; -friend class CRcvUList; - -private: // constructor and desctructor - CUDT(); - CUDT(const CUDT& ancestor); - const CUDT& operator=(const CUDT&) {return *this;} - ~CUDT(); - -public: //API - static int startup(); - static int cleanup(); - static UDTSOCKET socket(int af, int type = SOCK_STREAM, int protocol = 0); - static int bind(UDTSOCKET u, const sockaddr* name, int namelen); - static int bind(UDTSOCKET u, UDPSOCKET udpsock); - static int listen(UDTSOCKET u, int backlog); - static UDTSOCKET accept(UDTSOCKET u, sockaddr* addr, int* addrlen); - static int connect(UDTSOCKET u, const sockaddr* name, int namelen); - static int close(UDTSOCKET u); - static int getpeername(UDTSOCKET u, sockaddr* name, int* namelen); - static int getsockname(UDTSOCKET u, sockaddr* name, int* namelen); - static int getsockopt(UDTSOCKET u, int level, UDTOpt optname, void* optval, int* optlen); - static int setsockopt(UDTSOCKET u, int level, UDTOpt optname, const void* optval, int optlen); - static int send(UDTSOCKET u, const char* buf, int len, int flags); - static int recv(UDTSOCKET u, char* buf, int len, int flags); - static int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false); - static int recvmsg(UDTSOCKET u, char* buf, int len); - static int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); - static int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); - static int select(int nfds, ud_set* readfds, ud_set* writefds, ud_set* exceptfds, const timeval* timeout); - static int selectEx(const std::vector& fds, std::vector* readfds, std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - static int epoll_create(); - static int epoll_add_usock(const int eid, const UDTSOCKET u, const int* events = NULL); - static int epoll_add_ssock(const int eid, const SYSSOCKET s, const int* events = NULL); - static int epoll_remove_usock(const int eid, const UDTSOCKET u); - static int epoll_remove_ssock(const int eid, const SYSSOCKET s); - static int epoll_wait(const int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds = NULL, std::set* wrfds = NULL); - static int epoll_release(const int eid); - static CUDTException& getlasterror(); - static int perfmon(UDTSOCKET u, CPerfMon* perf, bool clear = true); - static UDTSTATUS getsockstate(UDTSOCKET u); - -public: // internal API - static CUDT* getUDTHandle(UDTSOCKET u); - -private: - // Functionality: - // initialize a UDT entity and bind to a local address. - // Parameters: - // None. - // Returned value: - // None. - - void open(); - - // Functionality: - // Start listening to any connection request. - // Parameters: - // None. - // Returned value: - // None. - - void listen(); - - // Functionality: - // Connect to a UDT entity listening at address "peer". - // Parameters: - // 0) [in] peer: The address of the listening UDT entity. - // Returned value: - // None. - - void connect(const sockaddr* peer); - - // Functionality: - // Process the response handshake packet. - // Parameters: - // 0) [in] pkt: handshake packet. - // Returned value: - // Return 0 if connected, positive value if connection is in progress, otherwise error code. - - int connect(const CPacket& pkt) throw (); - - // Functionality: - // Connect to a UDT entity listening at address "peer", which has sent "hs" request. - // Parameters: - // 0) [in] peer: The address of the listening UDT entity. - // 1) [in/out] hs: The handshake information sent by the peer side (in), negotiated value (out). - // Returned value: - // None. - - void connect(const sockaddr* peer, CHandShake* hs); - - // Functionality: - // Close the opened UDT entity. - // Parameters: - // None. - // Returned value: - // None. - - void close(); - - // Functionality: - // Request UDT to send out a data block "data" with size of "len". - // Parameters: - // 0) [in] data: The address of the application data to be sent. - // 1) [in] len: The size of the data block. - // Returned value: - // Actual size of data sent. - - int send(const char* data, int len); - - // Functionality: - // Request UDT to receive data to a memory block "data" with size of "len". - // Parameters: - // 0) [out] data: data received. - // 1) [in] len: The desired size of data to be received. - // Returned value: - // Actual size of data received. - - int recv(char* data, int len); - - // Functionality: - // send a message of a memory block "data" with size of "len". - // Parameters: - // 0) [out] data: data received. - // 1) [in] len: The desired size of data to be received. - // 2) [in] ttl: the time-to-live of the message. - // 3) [in] inorder: if the message should be delivered in order. - // Returned value: - // Actual size of data sent. - - int sendmsg(const char* data, int len, int ttl, bool inorder); - - // Functionality: - // Receive a message to buffer "data". - // Parameters: - // 0) [out] data: data received. - // 1) [in] len: size of the buffer. - // Returned value: - // Actual size of data received. - - int recvmsg(char* data, int len); - - // Functionality: - // Request UDT to send out a file described as "fd", starting from "offset", with size of "size". - // Parameters: - // 0) [in] ifs: The input file stream. - // 1) [in, out] offset: From where to read and send data; output is the new offset when the call returns. - // 2) [in] size: How many data to be sent. - // 3) [in] block: size of block per read from disk - // Returned value: - // Actual size of data sent. - - int64_t sendfile(std::fstream& ifs, int64_t& offset, int64_t size, int block = 366000); - - // Functionality: - // Request UDT to receive data into a file described as "fd", starting from "offset", with expected size of "size". - // Parameters: - // 0) [out] ofs: The output file stream. - // 1) [in, out] offset: From where to write data; output is the new offset when the call returns. - // 2) [in] size: How many data to be received. - // 3) [in] block: size of block per write to disk - // Returned value: - // Actual size of data received. - - int64_t recvfile(std::fstream& ofs, int64_t& offset, int64_t size, int block = 7320000); - - // Functionality: - // Configure UDT options. - // Parameters: - // 0) [in] optName: The enum name of a UDT option. - // 1) [in] optval: The value to be set. - // 2) [in] optlen: size of "optval". - // Returned value: - // None. - - void setOpt(UDTOpt optName, const void* optval, int optlen); - - // Functionality: - // Read UDT options. - // Parameters: - // 0) [in] optName: The enum name of a UDT option. - // 1) [in] optval: The value to be returned. - // 2) [out] optlen: size of "optval". - // Returned value: - // None. - - void getOpt(UDTOpt optName, void* optval, int& optlen); - - // Functionality: - // read the performance data since last sample() call. - // Parameters: - // 0) [in, out] perf: pointer to a CPerfMon structure to record the performance data. - // 1) [in] clear: flag to decide if the local performance trace should be cleared. - // Returned value: - // None. - - void sample(CPerfMon* perf, bool clear = true); - -private: - static CUDTUnited s_UDTUnited; // UDT global management base - -public: - static const UDTSOCKET INVALID_SOCK; // invalid socket descriptor - static const int ERROR; // socket api error returned value - -private: // Identification - UDTSOCKET m_SocketID; // UDT socket number - UDTSockType m_iSockType; // Type of the UDT connection (SOCK_STREAM or SOCK_DGRAM) - UDTSOCKET m_PeerID; // peer id, for multiplexer - static const int m_iVersion; // UDT version, for compatibility use - -private: // Packet sizes - int m_iPktSize; // Maximum/regular packet size, in bytes - int m_iPayloadSize; // Maximum/regular payload size, in bytes - -private: // Options - int m_iMSS; // Maximum Segment Size, in bytes - bool m_bSynSending; // Sending syncronization mode - bool m_bSynRecving; // Receiving syncronization mode - int m_iFlightFlagSize; // Maximum number of packets in flight from the peer side - int m_iSndBufSize; // Maximum UDT sender buffer size - int m_iRcvBufSize; // Maximum UDT receiver buffer size - linger m_Linger; // Linger information on close - int m_iUDPSndBufSize; // UDP sending buffer size - int m_iUDPRcvBufSize; // UDP receiving buffer size - int m_iIPversion; // IP version - bool m_bRendezvous; // Rendezvous connection mode - int m_iSndTimeOut; // sending timeout in milliseconds - int m_iRcvTimeOut; // receiving timeout in milliseconds - bool m_bReuseAddr; // reuse an exiting port or not, for UDP multiplexer - int64_t m_llMaxBW; // maximum data transfer rate (threshold) - -private: // congestion control - CCCVirtualFactory* m_pCCFactory; // Factory class to create a specific CC instance - CCC* m_pCC; // congestion control class - CCache* m_pCache; // network information cache - -private: // Status - volatile bool m_bListening; // If the UDT entit is listening to connection - volatile bool m_bConnecting; // The short phase when connect() is called but not yet completed - volatile bool m_bConnected; // Whether the connection is on or off - volatile bool m_bClosing; // If the UDT entity is closing - volatile bool m_bShutdown; // If the peer side has shutdown the connection - volatile bool m_bBroken; // If the connection has been broken - volatile bool m_bPeerHealth; // If the peer status is normal - bool m_bOpened; // If the UDT entity has been opened - int m_iBrokenCounter; // a counter (number of GC checks) to let the GC tag this socket as disconnected - - int m_iEXPCount; // Expiration counter - int m_iBandwidth; // Estimated bandwidth, number of packets per second - int m_iRTT; // RTT, in microseconds - int m_iRTTVar; // RTT variance - int m_iDeliveryRate; // Packet arrival rate at the receiver side - - uint64_t m_ullLingerExpiration; // Linger expiration time (for GC to close a socket with data in sending buffer) - - CHandShake m_ConnReq; // connection request - CHandShake m_ConnRes; // connection response - int64_t m_llLastReqTime; // last time when a connection request is sent - -private: // Sending related data - CSndBuffer* m_pSndBuffer; // Sender buffer - CSndLossList* m_pSndLossList; // Sender loss list - CPktTimeWindow* m_pSndTimeWindow; // Packet sending time window - - volatile uint64_t m_ullInterval; // Inter-packet time, in CPU clock cycles - uint64_t m_ullTimeDiff; // aggregate difference in inter-packet time - - volatile int m_iFlowWindowSize; // Flow control window size - volatile double m_dCongestionWindow; // congestion window size - - volatile int32_t m_iSndLastAck; // Last ACK received - volatile int32_t m_iSndLastDataAck; // The real last ACK that updates the sender buffer and loss list - volatile int32_t m_iSndCurrSeqNo; // The largest sequence number that has been sent - int32_t m_iLastDecSeq; // Sequence number sent last decrease occurs - int32_t m_iSndLastAck2; // Last ACK2 sent back - uint64_t m_ullSndLastAck2Time; // The time when last ACK2 was sent back - - int32_t m_iISN; // Initial Sequence Number - - void CCUpdate(); - -private: // Receiving related data - CRcvBuffer* m_pRcvBuffer; // Receiver buffer - CRcvLossList* m_pRcvLossList; // Receiver loss list - CACKWindow* m_pACKWindow; // ACK history window - CPktTimeWindow* m_pRcvTimeWindow; // Packet arrival time window - - int32_t m_iRcvLastAck; // Last sent ACK - uint64_t m_ullLastAckTime; // Timestamp of last ACK - int32_t m_iRcvLastAckAck; // Last sent ACK that has been acknowledged - int32_t m_iAckSeqNo; // Last ACK sequence number - int32_t m_iRcvCurrSeqNo; // Largest received sequence number - - uint64_t m_ullLastWarningTime; // Last time that a warning message is sent - - int32_t m_iPeerISN; // Initial Sequence Number of the peer side - -private: // synchronization: mutexes and conditions - pthread_mutex_t m_ConnectionLock; // used to synchronize connection operation - - pthread_cond_t m_SendBlockCond; // used to block "send" call - pthread_mutex_t m_SendBlockLock; // lock associated to m_SendBlockCond - - pthread_mutex_t m_AckLock; // used to protected sender's loss list when processing ACK - - pthread_cond_t m_RecvDataCond; // used to block "recv" when there is no data - pthread_mutex_t m_RecvDataLock; // lock associated to m_RecvDataCond - - pthread_mutex_t m_SendLock; // used to synchronize "send" call - pthread_mutex_t m_RecvLock; // used to synchronize "recv" call - - void initSynch(); - void destroySynch(); - void releaseSynch(); - -private: // Generation and processing of packets - void sendCtrl(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0); - void processCtrl(CPacket& ctrlpkt); - int packData(CPacket& packet, uint64_t& ts); - int processData(CUnit* unit); - int listen(sockaddr* addr, CPacket& packet); - -private: // Trace - uint64_t m_StartTime; // timestamp when the UDT entity is started - int64_t m_llSentTotal; // total number of sent data packets, including retransmissions - int64_t m_llRecvTotal; // total number of received packets - int m_iSndLossTotal; // total number of lost packets (sender side) - int m_iRcvLossTotal; // total number of lost packets (receiver side) - int m_iRetransTotal; // total number of retransmitted packets - int m_iSentACKTotal; // total number of sent ACK packets - int m_iRecvACKTotal; // total number of received ACK packets - int m_iSentNAKTotal; // total number of sent NAK packets - int m_iRecvNAKTotal; // total number of received NAK packets - int64_t m_llSndDurationTotal; // total real time for sending - - uint64_t m_LastSampleTime; // last performance sample time - int64_t m_llTraceSent; // number of pakctes sent in the last trace interval - int64_t m_llTraceRecv; // number of pakctes received in the last trace interval - int m_iTraceSndLoss; // number of lost packets in the last trace interval (sender side) - int m_iTraceRcvLoss; // number of lost packets in the last trace interval (receiver side) - int m_iTraceRetrans; // number of retransmitted packets in the last trace interval - int m_iSentACK; // number of ACKs sent in the last trace interval - int m_iRecvACK; // number of ACKs received in the last trace interval - int m_iSentNAK; // number of NAKs sent in the last trace interval - int m_iRecvNAK; // number of NAKs received in the last trace interval - int64_t m_llSndDuration; // real time for sending - int64_t m_llSndDurationCounter; // timers to record the sending duration - -private: // Timers - uint64_t m_ullCPUFrequency; // CPU clock frequency, used for Timer, ticks per microsecond - - static const int m_iSYNInterval; // Periodical Rate Control Interval, 10000 microsecond - static const int m_iSelfClockInterval; // ACK interval for self-clocking - - uint64_t m_ullNextACKTime; // Next ACK time, in CPU clock cycles, same below - uint64_t m_ullNextNAKTime; // Next NAK time - - volatile uint64_t m_ullSYNInt; // SYN interval - volatile uint64_t m_ullACKInt; // ACK interval - volatile uint64_t m_ullNAKInt; // NAK interval - volatile uint64_t m_ullLastRspTime; // time stamp of last response from the peer - - uint64_t m_ullMinNakInt; // NAK timeout lower bound; too small value can cause unnecessary retransmission - uint64_t m_ullMinExpInt; // timeout lower bound threshold: too small timeout can cause problem - - int m_iPktCount; // packet counter for ACK - int m_iLightACKCount; // light ACK counter - - uint64_t m_ullTargetTime; // scheduled time of next packet sending - - void checkTimers(); - -private: // for UDP multiplexer - CSndQueue* m_pSndQueue; // packet sending queue - CRcvQueue* m_pRcvQueue; // packet receiving queue - sockaddr* m_pPeerAddr; // peer address - uint32_t m_piSelfIP[4]; // local UDP IP address - CSNode* m_pSNode; // node information for UDT list used in snd queue - CRNode* m_pRNode; // node information for UDT list used in rcv queue - -private: // for epoll - std::set m_sPollID; // set of epoll ID to trigger - void addEPoll(const int eid); - void removeEPoll(const int eid); -}; - - -#endif diff --git a/vendor/udt4/src/epoll.cpp b/vendor/udt4/src/epoll.cpp deleted file mode 100644 index 0e7ddb1..0000000 --- a/vendor/udt4/src/epoll.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/01/2011 -*****************************************************************************/ - -#ifdef LINUX - #include - #include -#endif -#include -#include -#include -#include - -#include "common.h" -#include "epoll.h" -#include "udt.h" - -using namespace std; - -CEPoll::CEPoll(): -m_iIDSeed(0) -{ - CGuard::createMutex(m_EPollLock); -} - -CEPoll::~CEPoll() -{ - CGuard::releaseMutex(m_EPollLock); -} - -int CEPoll::create() -{ - CGuard pg(m_EPollLock); - - int localid = 0; - - #ifdef LINUX - localid = epoll_create(1024); - if (localid < 0) - throw CUDTException(-1, 0, errno); - #else - // on BSD, use kqueue - // on Solaris, use /dev/poll - // on Windows, select - #endif - - if (++ m_iIDSeed >= 0x7FFFFFFF) - m_iIDSeed = 0; - - CEPollDesc desc; - desc.m_iID = m_iIDSeed; - desc.m_iLocalID = localid; - m_mPolls[desc.m_iID] = desc; - - return desc.m_iID; -} - -int CEPoll::add_usock(const int eid, const UDTSOCKET& u, const int* events) -{ - CGuard pg(m_EPollLock); - - map::iterator p = m_mPolls.find(eid); - if (p == m_mPolls.end()) - throw CUDTException(5, 13); - - if (!events || (*events & UDT_EPOLL_IN)) - p->second.m_sUDTSocksIn.insert(u); - if (!events || (*events & UDT_EPOLL_OUT)) - p->second.m_sUDTSocksOut.insert(u); - - return 0; -} - -int CEPoll::add_ssock(const int eid, const SYSSOCKET& s, const int* events) -{ - CGuard pg(m_EPollLock); - - map::iterator p = m_mPolls.find(eid); - if (p == m_mPolls.end()) - throw CUDTException(5, 13); - -#ifdef LINUX - epoll_event ev; - memset(&ev, 0, sizeof(epoll_event)); - - if (NULL == events) - ev.events = EPOLLIN | EPOLLOUT | EPOLLERR; - else - { - ev.events = 0; - if (*events & UDT_EPOLL_IN) - ev.events |= EPOLLIN; - if (*events & UDT_EPOLL_OUT) - ev.events |= EPOLLOUT; - if (*events & UDT_EPOLL_ERR) - ev.events |= EPOLLERR; - } - - ev.data.fd = s; - if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_ADD, s, &ev) < 0) - throw CUDTException(); -#endif - - p->second.m_sLocals.insert(s); - - return 0; -} - -int CEPoll::remove_usock(const int eid, const UDTSOCKET& u) -{ - CGuard pg(m_EPollLock); - - map::iterator p = m_mPolls.find(eid); - if (p == m_mPolls.end()) - throw CUDTException(5, 13); - - p->second.m_sUDTSocksIn.erase(u); - p->second.m_sUDTSocksOut.erase(u); - p->second.m_sUDTSocksEx.erase(u); - - return 0; -} - -int CEPoll::remove_ssock(const int eid, const SYSSOCKET& s) -{ - CGuard pg(m_EPollLock); - - map::iterator p = m_mPolls.find(eid); - if (p == m_mPolls.end()) - throw CUDTException(5, 13); - -#ifdef LINUX - epoll_event ev; // ev is ignored, for compatibility with old Linux kernel only. - if (::epoll_ctl(p->second.m_iLocalID, EPOLL_CTL_DEL, s, &ev) < 0) - throw CUDTException(); -#endif - - p->second.m_sLocals.erase(s); - - return 0; -} - -int CEPoll::wait(const int eid, set* readfds, set* writefds, int64_t msTimeOut, set* lrfds, set* lwfds) -{ - // if all fields is NULL and waiting time is infinite, then this would be a deadlock - if (!readfds && !writefds && !lrfds && lwfds && (msTimeOut < 0)) - throw CUDTException(5, 3, 0); - - // Clear these sets in case the app forget to do it. - if (readfds) readfds->clear(); - if (writefds) writefds->clear(); - if (lrfds) lrfds->clear(); - if (lwfds) lwfds->clear(); - - int total = 0; - - int64_t entertime = CTimer::getTime(); - while (true) - { - CGuard::enterCS(m_EPollLock); - - map::iterator p = m_mPolls.find(eid); - if (p == m_mPolls.end()) - { - CGuard::leaveCS(m_EPollLock); - throw CUDTException(5, 13); - } - - if (p->second.m_sUDTSocksIn.empty() && p->second.m_sUDTSocksOut.empty() && p->second.m_sLocals.empty() && (msTimeOut < 0)) - { - // no socket is being monitored, this may be a deadlock - CGuard::leaveCS(m_EPollLock); - throw CUDTException(5, 3); - } - - // Sockets with exceptions are returned to both read and write sets. - if ((NULL != readfds) && (!p->second.m_sUDTReads.empty() || !p->second.m_sUDTExcepts.empty())) - { - *readfds = p->second.m_sUDTReads; - for (set::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i) - readfds->insert(*i); - total += p->second.m_sUDTReads.size() + p->second.m_sUDTExcepts.size(); - } - if ((NULL != writefds) && (!p->second.m_sUDTWrites.empty() || !p->second.m_sUDTExcepts.empty())) - { - *writefds = p->second.m_sUDTWrites; - for (set::const_iterator i = p->second.m_sUDTExcepts.begin(); i != p->second.m_sUDTExcepts.end(); ++ i) - writefds->insert(*i); - total += p->second.m_sUDTWrites.size() + p->second.m_sUDTExcepts.size(); - } - - if (lrfds || lwfds) - { - #ifdef LINUX - const int max_events = p->second.m_sLocals.size(); - epoll_event ev[max_events]; - int nfds = ::epoll_wait(p->second.m_iLocalID, ev, max_events, 0); - - for (int i = 0; i < nfds; ++ i) - { - if ((NULL != lrfds) && (ev[i].events & EPOLLIN)) - { - lrfds->insert(ev[i].data.fd); - ++ total; - } - if ((NULL != lwfds) && (ev[i].events & EPOLLOUT)) - { - lwfds->insert(ev[i].data.fd); - ++ total; - } - } - #else - //currently "select" is used for all non-Linux platforms. - //faster approaches can be applied for specific systems in the future. - - //"select" has a limitation on the number of sockets - - fd_set readfds; - fd_set writefds; - FD_ZERO(&readfds); - FD_ZERO(&writefds); - - for (set::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i) - { - if (lrfds) - FD_SET(*i, &readfds); - if (lwfds) - FD_SET(*i, &writefds); - } - - timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - if (::select(0, &readfds, &writefds, NULL, &tv) > 0) - { - for (set::const_iterator i = p->second.m_sLocals.begin(); i != p->second.m_sLocals.end(); ++ i) - { - if (lrfds && FD_ISSET(*i, &readfds)) - { - lrfds->insert(*i); - ++ total; - } - if (lwfds && FD_ISSET(*i, &writefds)) - { - lwfds->insert(*i); - ++ total; - } - } - } - #endif - } - - CGuard::leaveCS(m_EPollLock); - - if (total > 0) - return total; - - if ((msTimeOut >= 0) && (int64_t(CTimer::getTime() - entertime) >= msTimeOut * 1000LL)) - throw CUDTException(6, 3, 0); - - CTimer::waitForEvent(); - } - - return 0; -} - -int CEPoll::release(const int eid) -{ - CGuard pg(m_EPollLock); - - map::iterator i = m_mPolls.find(eid); - if (i == m_mPolls.end()) - throw CUDTException(5, 13); - - #ifdef LINUX - // release local/system epoll descriptor - ::close(i->second.m_iLocalID); - #endif - - m_mPolls.erase(i); - - return 0; -} - -namespace -{ - -void update_epoll_sets(const UDTSOCKET& uid, const set& watch, set& result, bool enable) -{ - if (enable && (watch.find(uid) != watch.end())) - { - result.insert(uid); - } - else if (!enable) - { - result.erase(uid); - } -} - -} // namespace - -int CEPoll::update_events(const UDTSOCKET& uid, std::set& eids, int events, bool enable) -{ - CGuard pg(m_EPollLock); - - map::iterator p; - - vector lost; - for (set::iterator i = eids.begin(); i != eids.end(); ++ i) - { - p = m_mPolls.find(*i); - if (p == m_mPolls.end()) - { - lost.push_back(*i); - } - else - { - if ((events & UDT_EPOLL_IN) != 0) - update_epoll_sets(uid, p->second.m_sUDTSocksIn, p->second.m_sUDTReads, enable); - if ((events & UDT_EPOLL_OUT) != 0) - update_epoll_sets(uid, p->second.m_sUDTSocksOut, p->second.m_sUDTWrites, enable); - if ((events & UDT_EPOLL_ERR) != 0) - update_epoll_sets(uid, p->second.m_sUDTSocksEx, p->second.m_sUDTExcepts, enable); - } - } - - for (vector::iterator i = lost.begin(); i != lost.end(); ++ i) - eids.erase(*i); - - return 0; -} diff --git a/vendor/udt4/src/epoll.h b/vendor/udt4/src/epoll.h deleted file mode 100644 index a19f8ab..0000000 --- a/vendor/udt4/src/epoll.h +++ /dev/null @@ -1,173 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2010, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 08/20/2010 -*****************************************************************************/ - -#ifndef __UDT_EPOLL_H__ -#define __UDT_EPOLL_H__ - - -#include -#include -#include "udt.h" - - -struct CEPollDesc -{ - int m_iID; // epoll ID - std::set m_sUDTSocksOut; // set of UDT sockets waiting for write events - std::set m_sUDTSocksIn; // set of UDT sockets waiting for read events - std::set m_sUDTSocksEx; // set of UDT sockets waiting for exceptions - - int m_iLocalID; // local system epoll ID - std::set m_sLocals; // set of local (non-UDT) descriptors - - std::set m_sUDTWrites; // UDT sockets ready for write - std::set m_sUDTReads; // UDT sockets ready for read - std::set m_sUDTExcepts; // UDT sockets with exceptions (connection broken, etc.) -}; - -class CEPoll -{ -friend class CUDT; -friend class CRendezvousQueue; - -public: - CEPoll(); - ~CEPoll(); - -public: // for CUDTUnited API - - // Functionality: - // create a new EPoll. - // Parameters: - // None. - // Returned value: - // new EPoll ID if success, otherwise an error number. - - int create(); - - // Functionality: - // add a UDT socket to an EPoll. - // Parameters: - // 0) [in] eid: EPoll ID. - // 1) [in] u: UDT Socket ID. - // 2) [in] events: events to watch. - // Returned value: - // 0 if success, otherwise an error number. - - int add_usock(const int eid, const UDTSOCKET& u, const int* events = NULL); - - // Functionality: - // add a system socket to an EPoll. - // Parameters: - // 0) [in] eid: EPoll ID. - // 1) [in] s: system Socket ID. - // 2) [in] events: events to watch. - // Returned value: - // 0 if success, otherwise an error number. - - int add_ssock(const int eid, const SYSSOCKET& s, const int* events = NULL); - - // Functionality: - // remove a UDT socket event from an EPoll; socket will be removed if no events to watch - // Parameters: - // 0) [in] eid: EPoll ID. - // 1) [in] u: UDT socket ID. - // Returned value: - // 0 if success, otherwise an error number. - - int remove_usock(const int eid, const UDTSOCKET& u); - - // Functionality: - // remove a system socket event from an EPoll; socket will be removed if no events to watch - // Parameters: - // 0) [in] eid: EPoll ID. - // 1) [in] s: system socket ID. - // Returned value: - // 0 if success, otherwise an error number. - - int remove_ssock(const int eid, const SYSSOCKET& s); - - // Functionality: - // wait for EPoll events or timeout. - // Parameters: - // 0) [in] eid: EPoll ID. - // 1) [out] readfds: UDT sockets available for reading. - // 2) [out] writefds: UDT sockets available for writing. - // 3) [in] msTimeOut: timeout threshold, in milliseconds. - // 4) [out] lrfds: system file descriptors for reading. - // 5) [out] lwfds: system file descriptors for writing. - // Returned value: - // number of sockets available for IO. - - int wait(const int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, std::set* lrfds, std::set* lwfds); - - // Functionality: - // close and release an EPoll. - // Parameters: - // 0) [in] eid: EPoll ID. - // Returned value: - // 0 if success, otherwise an error number. - - int release(const int eid); - -public: // for CUDT to acknowledge IO status - - // Functionality: - // Update events available for a UDT socket. - // Parameters: - // 0) [in] uid: UDT socket ID. - // 1) [in] eids: EPoll IDs to be set - // 1) [in] events: Combination of events to update - // 1) [in] enable: true -> enable, otherwise disable - // Returned value: - // 0 if success, otherwise an error number - - int update_events(const UDTSOCKET& uid, std::set& eids, int events, bool enable); - -private: - int m_iIDSeed; // seed to generate a new ID - pthread_mutex_t m_SeedLock; - - std::map m_mPolls; // all epolls - pthread_mutex_t m_EPollLock; -}; - - -#endif diff --git a/vendor/udt4/src/list.cpp b/vendor/udt4/src/list.cpp deleted file mode 100644 index 00b7e57..0000000 --- a/vendor/udt4/src/list.cpp +++ /dev/null @@ -1,703 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/22/2011 -*****************************************************************************/ - -#include "list.h" - -CSndLossList::CSndLossList(int size): -m_piData1(NULL), -m_piData2(NULL), -m_piNext(NULL), -m_iHead(-1), -m_iLength(0), -m_iSize(size), -m_iLastInsertPos(-1), -m_ListLock() -{ - m_piData1 = new int32_t [m_iSize]; - m_piData2 = new int32_t [m_iSize]; - m_piNext = new int [m_iSize]; - - // -1 means there is no data in the node - for (int i = 0; i < size; ++ i) - { - m_piData1[i] = -1; - m_piData2[i] = -1; - } - - // sender list needs mutex protection - #ifndef WIN32 - pthread_mutex_init(&m_ListLock, 0); - #else - m_ListLock = CreateMutex(NULL, false, NULL); - #endif -} - -CSndLossList::~CSndLossList() -{ - delete [] m_piData1; - delete [] m_piData2; - delete [] m_piNext; - - #ifndef WIN32 - pthread_mutex_destroy(&m_ListLock); - #else - CloseHandle(m_ListLock); - #endif -} - -int CSndLossList::insert(int32_t seqno1, int32_t seqno2) -{ - CGuard listguard(m_ListLock); - - if (0 == m_iLength) - { - // insert data into an empty list - - m_iHead = 0; - m_piData1[m_iHead] = seqno1; - if (seqno2 != seqno1) - m_piData2[m_iHead] = seqno2; - - m_piNext[m_iHead] = -1; - m_iLastInsertPos = m_iHead; - - m_iLength += CSeqNo::seqlen(seqno1, seqno2); - - return m_iLength; - } - - // otherwise find the position where the data can be inserted - int origlen = m_iLength; - int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); - int loc = (m_iHead + offset + m_iSize) % m_iSize; - - if (offset < 0) - { - // Insert data prior to the head pointer - - m_piData1[loc] = seqno1; - if (seqno2 != seqno1) - m_piData2[loc] = seqno2; - - // new node becomes head - m_piNext[loc] = m_iHead; - m_iHead = loc; - m_iLastInsertPos = loc; - - m_iLength += CSeqNo::seqlen(seqno1, seqno2); - } - else if (offset > 0) - { - if (seqno1 == m_piData1[loc]) - { - m_iLastInsertPos = loc; - - // first seqno is equivlent, compare the second - if (-1 == m_piData2[loc]) - { - if (seqno2 != seqno1) - { - m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; - m_piData2[loc] = seqno2; - } - } - else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) - { - // new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7] - m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; - m_piData2[loc] = seqno2; - } - else - // Do nothing if it is already there - return 0; - } - else - { - // searching the prior node - int i; - if ((-1 != m_iLastInsertPos) && (CSeqNo::seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0)) - i = m_iLastInsertPos; - else - i = m_iHead; - - while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno1) < 0)) - i = m_piNext[i]; - - if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(m_piData2[i], seqno1) < 0)) - { - m_iLastInsertPos = loc; - - // no overlap, create new node - m_piData1[loc] = seqno1; - if (seqno2 != seqno1) - m_piData2[loc] = seqno2; - - m_piNext[loc] = m_piNext[i]; - m_piNext[i] = loc; - - m_iLength += CSeqNo::seqlen(seqno1, seqno2); - } - else - { - m_iLastInsertPos = i; - - // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7] - if (CSeqNo::seqcmp(m_piData2[i], seqno2) < 0) - { - m_iLength += CSeqNo::seqlen(m_piData2[i], seqno2) - 1; - m_piData2[i] = seqno2; - - loc = i; - } - else - return 0; - } - } - } - else - { - m_iLastInsertPos = m_iHead; - - // insert to head node - if (seqno2 != seqno1) - { - if (-1 == m_piData2[loc]) - { - m_iLength += CSeqNo::seqlen(seqno1, seqno2) - 1; - m_piData2[loc] = seqno2; - } - else if (CSeqNo::seqcmp(seqno2, m_piData2[loc]) > 0) - { - m_iLength += CSeqNo::seqlen(m_piData2[loc], seqno2) - 1; - m_piData2[loc] = seqno2; - } - else - return 0; - } - else - return 0; - } - - // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9] - while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc])) - { - int i = m_piNext[loc]; - - if (CSeqNo::seqcmp(m_piData1[i], CSeqNo::incseq(m_piData2[loc])) <= 0) - { - // coalesce if there is overlap - if (-1 != m_piData2[i]) - { - if (CSeqNo::seqcmp(m_piData2[i], m_piData2[loc]) > 0) - { - if (CSeqNo::seqcmp(m_piData2[loc], m_piData1[i]) >= 0) - m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[loc]); - - m_piData2[loc] = m_piData2[i]; - } - else - m_iLength -= CSeqNo::seqlen(m_piData1[i], m_piData2[i]); - } - else - { - if (m_piData1[i] == CSeqNo::incseq(m_piData2[loc])) - m_piData2[loc] = m_piData1[i]; - else - m_iLength --; - } - - m_piData1[i] = -1; - m_piData2[i] = -1; - m_piNext[loc] = m_piNext[i]; - } - else - break; - } - - return m_iLength - origlen; -} - -void CSndLossList::remove(int32_t seqno) -{ - CGuard listguard(m_ListLock); - - if (0 == m_iLength) - return; - - // Remove all from the head pointer to a node with a larger seq. no. or the list is empty - int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); - int loc = (m_iHead + offset + m_iSize) % m_iSize; - - if (0 == offset) - { - // It is the head. Remove the head and point to the next node - loc = (loc + 1) % m_iSize; - - if (-1 == m_piData2[m_iHead]) - loc = m_piNext[m_iHead]; - else - { - m_piData1[loc] = CSeqNo::incseq(seqno); - if (CSeqNo::seqcmp(m_piData2[m_iHead], CSeqNo::incseq(seqno)) > 0) - m_piData2[loc] = m_piData2[m_iHead]; - - m_piData2[m_iHead] = -1; - - m_piNext[loc] = m_piNext[m_iHead]; - } - - m_piData1[m_iHead] = -1; - - if (m_iLastInsertPos == m_iHead) - m_iLastInsertPos = -1; - - m_iHead = loc; - - m_iLength --; - } - else if (offset > 0) - { - int h = m_iHead; - - if (seqno == m_piData1[loc]) - { - // target node is not empty, remove part/all of the seqno in the node. - int temp = loc; - loc = (loc + 1) % m_iSize; - - if (-1 == m_piData2[temp]) - m_iHead = m_piNext[temp]; - else - { - // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3) - m_piData1[loc] = CSeqNo::incseq(seqno); - if (CSeqNo::seqcmp(m_piData2[temp], m_piData1[loc]) > 0) - m_piData2[loc] = m_piData2[temp]; - m_iHead = loc; - m_piNext[loc] = m_piNext[temp]; - m_piNext[temp] = loc; - m_piData2[temp] = -1; - } - } - else - { - // target node is empty, check prior node - int i = m_iHead; - while ((-1 != m_piNext[i]) && (CSeqNo::seqcmp(m_piData1[m_piNext[i]], seqno) < 0)) - i = m_piNext[i]; - - loc = (loc + 1) % m_iSize; - - if (-1 == m_piData2[i]) - m_iHead = m_piNext[i]; - else if (CSeqNo::seqcmp(m_piData2[i], seqno) > 0) - { - // remove part/all seqno in the prior node - m_piData1[loc] = CSeqNo::incseq(seqno); - if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) - m_piData2[loc] = m_piData2[i]; - - m_piData2[i] = seqno; - - m_piNext[loc] = m_piNext[i]; - m_piNext[i] = loc; - - m_iHead = loc; - } - else - m_iHead = m_piNext[i]; - } - - // Remove all nodes prior to the new head - while (h != m_iHead) - { - if (m_piData2[h] != -1) - { - m_iLength -= CSeqNo::seqlen(m_piData1[h], m_piData2[h]); - m_piData2[h] = -1; - } - else - m_iLength --; - - m_piData1[h] = -1; - - if (m_iLastInsertPos == h) - m_iLastInsertPos = -1; - - h = m_piNext[h]; - } - } -} - -int CSndLossList::getLossLength() -{ - CGuard listguard(m_ListLock); - - return m_iLength; -} - -int32_t CSndLossList::getLostSeq() -{ - if (0 == m_iLength) - return -1; - - CGuard listguard(m_ListLock); - - if (0 == m_iLength) - return -1; - - if (m_iLastInsertPos == m_iHead) - m_iLastInsertPos = -1; - - // return the first loss seq. no. - int32_t seqno = m_piData1[m_iHead]; - - // head moves to the next node - if (-1 == m_piData2[m_iHead]) - { - //[3, -1] becomes [], and head moves to next node in the list - m_piData1[m_iHead] = -1; - m_iHead = m_piNext[m_iHead]; - } - else - { - // shift to next node, e.g., [3, 7] becomes [], [4, 7] - int loc = (m_iHead + 1) % m_iSize; - - m_piData1[loc] = CSeqNo::incseq(seqno); - if (CSeqNo::seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0) - m_piData2[loc] = m_piData2[m_iHead]; - - m_piData1[m_iHead] = -1; - m_piData2[m_iHead] = -1; - - m_piNext[loc] = m_piNext[m_iHead]; - m_iHead = loc; - } - - m_iLength --; - - return seqno; -} - -//////////////////////////////////////////////////////////////////////////////// - -CRcvLossList::CRcvLossList(int size): -m_piData1(NULL), -m_piData2(NULL), -m_piNext(NULL), -m_piPrior(NULL), -m_iHead(-1), -m_iTail(-1), -m_iLength(0), -m_iSize(size) -{ - m_piData1 = new int32_t [m_iSize]; - m_piData2 = new int32_t [m_iSize]; - m_piNext = new int [m_iSize]; - m_piPrior = new int [m_iSize]; - - // -1 means there is no data in the node - for (int i = 0; i < size; ++ i) - { - m_piData1[i] = -1; - m_piData2[i] = -1; - } -} - -CRcvLossList::~CRcvLossList() -{ - delete [] m_piData1; - delete [] m_piData2; - delete [] m_piNext; - delete [] m_piPrior; -} - -void CRcvLossList::insert(int32_t seqno1, int32_t seqno2) -{ - // Data to be inserted must be larger than all those in the list - // guaranteed by the UDT receiver - - if (0 == m_iLength) - { - // insert data into an empty list - m_iHead = 0; - m_iTail = 0; - m_piData1[m_iHead] = seqno1; - if (seqno2 != seqno1) - m_piData2[m_iHead] = seqno2; - - m_piNext[m_iHead] = -1; - m_piPrior[m_iHead] = -1; - m_iLength += CSeqNo::seqlen(seqno1, seqno2); - - return; - } - - // otherwise searching for the position where the node should be - int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno1); - int loc = (m_iHead + offset) % m_iSize; - - if ((-1 != m_piData2[m_iTail]) && (CSeqNo::incseq(m_piData2[m_iTail]) == seqno1)) - { - // coalesce with prior node, e.g., [2, 5], [6, 7] becomes [2, 7] - loc = m_iTail; - m_piData2[loc] = seqno2; - } - else - { - // create new node - m_piData1[loc] = seqno1; - - if (seqno2 != seqno1) - m_piData2[loc] = seqno2; - - m_piNext[m_iTail] = loc; - m_piPrior[loc] = m_iTail; - m_piNext[loc] = -1; - m_iTail = loc; - } - - m_iLength += CSeqNo::seqlen(seqno1, seqno2); -} - -bool CRcvLossList::remove(int32_t seqno) -{ - if (0 == m_iLength) - return false; - - // locate the position of "seqno" in the list - int offset = CSeqNo::seqoff(m_piData1[m_iHead], seqno); - if (offset < 0) - return false; - - int loc = (m_iHead + offset) % m_iSize; - - if (seqno == m_piData1[loc]) - { - // This is a seq. no. that starts the loss sequence - - if (-1 == m_piData2[loc]) - { - // there is only 1 loss in the sequence, delete it from the node - if (m_iHead == loc) - { - m_iHead = m_piNext[m_iHead]; - if (-1 != m_iHead) - m_piPrior[m_iHead] = -1; - } - else - { - m_piNext[m_piPrior[loc]] = m_piNext[loc]; - if (-1 != m_piNext[loc]) - m_piPrior[m_piNext[loc]] = m_piPrior[loc]; - else - m_iTail = m_piPrior[loc]; - } - - m_piData1[loc] = -1; - } - else - { - // there are more than 1 loss in the sequence - // move the node to the next and update the starter as the next loss inSeqNo(seqno) - - // find next node - int i = (loc + 1) % m_iSize; - - // remove the "seqno" and change the starter as next seq. no. - m_piData1[i] = CSeqNo::incseq(m_piData1[loc]); - - // process the sequence end - if (CSeqNo::seqcmp(m_piData2[loc], CSeqNo::incseq(m_piData1[loc])) > 0) - m_piData2[i] = m_piData2[loc]; - - // remove the current node - m_piData1[loc] = -1; - m_piData2[loc] = -1; - - // update list pointer - m_piNext[i] = m_piNext[loc]; - m_piPrior[i] = m_piPrior[loc]; - - if (m_iHead == loc) - m_iHead = i; - else - m_piNext[m_piPrior[i]] = i; - - if (m_iTail == loc) - m_iTail = i; - else - m_piPrior[m_piNext[i]] = i; - } - - m_iLength --; - - return true; - } - - // There is no loss sequence in the current position - // the "seqno" may be contained in a previous node - - // searching previous node - int i = (loc - 1 + m_iSize) % m_iSize; - while (-1 == m_piData1[i]) - i = (i - 1 + m_iSize) % m_iSize; - - // not contained in this node, return - if ((-1 == m_piData2[i]) || (CSeqNo::seqcmp(seqno, m_piData2[i]) > 0)) - return false; - - if (seqno == m_piData2[i]) - { - // it is the sequence end - - if (seqno == CSeqNo::incseq(m_piData1[i])) - m_piData2[i] = -1; - else - m_piData2[i] = CSeqNo::decseq(seqno); - } - else - { - // split the sequence - - // construct the second sequence from CSeqNo::incseq(seqno) to the original sequence end - // located at "loc + 1" - loc = (loc + 1) % m_iSize; - - m_piData1[loc] = CSeqNo::incseq(seqno); - if (CSeqNo::seqcmp(m_piData2[i], m_piData1[loc]) > 0) - m_piData2[loc] = m_piData2[i]; - - // the first (original) sequence is between the original sequence start to CSeqNo::decseq(seqno) - if (seqno == CSeqNo::incseq(m_piData1[i])) - m_piData2[i] = -1; - else - m_piData2[i] = CSeqNo::decseq(seqno); - - // update the list pointer - m_piNext[loc] = m_piNext[i]; - m_piNext[i] = loc; - m_piPrior[loc] = i; - - if (m_iTail == i) - m_iTail = loc; - else - m_piPrior[m_piNext[loc]] = loc; - } - - m_iLength --; - - return true; -} - -bool CRcvLossList::remove(int32_t seqno1, int32_t seqno2) -{ - if (seqno1 <= seqno2) - { - for (int32_t i = seqno1; i <= seqno2; ++ i) - remove(i); - } - else - { - for (int32_t j = seqno1; j < CSeqNo::m_iMaxSeqNo; ++ j) - remove(j); - for (int32_t k = 0; k <= seqno2; ++ k) - remove(k); - } - - return true; -} - -bool CRcvLossList::find(int32_t seqno1, int32_t seqno2) const -{ - if (0 == m_iLength) - return false; - - int p = m_iHead; - - while (-1 != p) - { - if ((CSeqNo::seqcmp(m_piData1[p], seqno1) == 0) || - ((CSeqNo::seqcmp(m_piData1[p], seqno1) > 0) && (CSeqNo::seqcmp(m_piData1[p], seqno2) <= 0)) || - ((CSeqNo::seqcmp(m_piData1[p], seqno1) < 0) && (m_piData2[p] != -1) && CSeqNo::seqcmp(m_piData2[p], seqno1) >= 0)) - return true; - - p = m_piNext[p]; - } - - return false; -} - -int CRcvLossList::getLossLength() const -{ - return m_iLength; -} - -int CRcvLossList::getFirstLostSeq() const -{ - if (0 == m_iLength) - return -1; - - return m_piData1[m_iHead]; -} - -void CRcvLossList::getLossArray(int32_t* array, int& len, int limit) -{ - len = 0; - - int i = m_iHead; - - while ((len < limit - 1) && (-1 != i)) - { - array[len] = m_piData1[i]; - if (-1 != m_piData2[i]) - { - // there are more than 1 loss in the sequence - array[len] |= 0x80000000; - ++ len; - array[len] = m_piData2[i]; - } - - ++ len; - - i = m_piNext[i]; - } -} diff --git a/vendor/udt4/src/list.h b/vendor/udt4/src/list.h deleted file mode 100644 index 6be9694..0000000 --- a/vendor/udt4/src/list.h +++ /dev/null @@ -1,202 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/22/2011 -*****************************************************************************/ - -#ifndef __UDT_LIST_H__ -#define __UDT_LIST_H__ - - -#include "udt.h" -#include "common.h" - - -class CSndLossList -{ -public: - CSndLossList(int size = 1024); - ~CSndLossList(); - - // Functionality: - // Insert a seq. no. into the sender loss list. - // Parameters: - // 0) [in] seqno1: sequence number starts. - // 1) [in] seqno2: sequence number ends. - // Returned value: - // number of packets that are not in the list previously. - - int insert(int32_t seqno1, int32_t seqno2); - - // Functionality: - // Remove ALL the seq. no. that are not greater than the parameter. - // Parameters: - // 0) [in] seqno: sequence number. - // Returned value: - // None. - - void remove(int32_t seqno); - - // Functionality: - // Read the loss length. - // Parameters: - // None. - // Returned value: - // The length of the list. - - int getLossLength(); - - // Functionality: - // Read the first (smallest) loss seq. no. in the list and remove it. - // Parameters: - // None. - // Returned value: - // The seq. no. or -1 if the list is empty. - - int32_t getLostSeq(); - -private: - int32_t* m_piData1; // sequence number starts - int32_t* m_piData2; // seqnence number ends - int* m_piNext; // next node in the list - - int m_iHead; // first node - int m_iLength; // loss length - int m_iSize; // size of the static array - int m_iLastInsertPos; // position of last insert node - - pthread_mutex_t m_ListLock; // used to synchronize list operation - -private: - CSndLossList(const CSndLossList&); - CSndLossList& operator=(const CSndLossList&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CRcvLossList -{ -public: - CRcvLossList(int size = 1024); - ~CRcvLossList(); - - // Functionality: - // Insert a series of loss seq. no. between "seqno1" and "seqno2" into the receiver's loss list. - // Parameters: - // 0) [in] seqno1: sequence number starts. - // 1) [in] seqno2: seqeunce number ends. - // Returned value: - // None. - - void insert(int32_t seqno1, int32_t seqno2); - - // Functionality: - // Remove a loss seq. no. from the receiver's loss list. - // Parameters: - // 0) [in] seqno: sequence number. - // Returned value: - // if the packet is removed (true) or no such lost packet is found (false). - - bool remove(int32_t seqno); - - // Functionality: - // Remove all packets between seqno1 and seqno2. - // Parameters: - // 0) [in] seqno1: start sequence number. - // 1) [in] seqno2: end sequence number. - // Returned value: - // if the packet is removed (true) or no such lost packet is found (false). - - bool remove(int32_t seqno1, int32_t seqno2); - - // Functionality: - // Find if there is any lost packets whose sequence number falling seqno1 and seqno2. - // Parameters: - // 0) [in] seqno1: start sequence number. - // 1) [in] seqno2: end sequence number. - // Returned value: - // True if found; otherwise false. - - bool find(int32_t seqno1, int32_t seqno2) const; - - // Functionality: - // Read the loss length. - // Parameters: - // None. - // Returned value: - // the length of the list. - - int getLossLength() const; - - // Functionality: - // Read the first (smallest) seq. no. in the list. - // Parameters: - // None. - // Returned value: - // the sequence number or -1 if the list is empty. - - int getFirstLostSeq() const; - - // Functionality: - // Get a encoded loss array for NAK report. - // Parameters: - // 0) [out] array: the result list of seq. no. to be included in NAK. - // 1) [out] physical length of the result array. - // 2) [in] limit: maximum length of the array. - // Returned value: - // None. - - void getLossArray(int32_t* array, int& len, int limit); - -private: - int32_t* m_piData1; // sequence number starts - int32_t* m_piData2; // sequence number ends - int* m_piNext; // next node in the list - int* m_piPrior; // prior node in the list; - - int m_iHead; // first node in the list - int m_iTail; // last node in the list; - int m_iLength; // loss length - int m_iSize; // size of the static array - -private: - CRcvLossList(const CRcvLossList&); - CRcvLossList& operator=(const CRcvLossList&); -}; - - -#endif diff --git a/vendor/udt4/src/md5.cpp b/vendor/udt4/src/md5.cpp deleted file mode 100644 index d6fd5d3..0000000 --- a/vendor/udt4/src/md5.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.cpp,v 1.3 2008/01/20 22:52:04 lilyco Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -#include "md5.h" -#include - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - -# if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -# else -# define xbuf X /* (static only) */ -# endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/vendor/udt4/src/md5.h b/vendor/udt4/src/md5.h deleted file mode 100644 index f7402e7..0000000 --- a/vendor/udt4/src/md5.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.h,v 1.2 2007/12/24 05:58:37 lilyco Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.h is L. Peter Deutsch - . Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke . - 1999-05-03 lpd Original version. - */ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); - -/* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - -/* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* md5_INCLUDED */ diff --git a/vendor/udt4/src/packet.cpp b/vendor/udt4/src/packet.cpp deleted file mode 100644 index e238a04..0000000 --- a/vendor/udt4/src/packet.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 02/12/2011 -*****************************************************************************/ - - -////////////////////////////////////////////////////////////////////////////// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Packet Header | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | | -// ~ Data / Control Information Field ~ -// | | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |0| Sequence Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |ff |o| Message Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Time Stamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Destination Socket ID | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// bit 0: -// 0: Data Packet -// 1: Control Packet -// bit ff: -// 11: solo message packet -// 10: first packet of a message -// 01: last packet of a message -// bit o: -// 0: in order delivery not required -// 1: in order delivery required -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |1| Type | Reserved | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Additional Info | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Time Stamp | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Destination Socket ID | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// bit 1-15: -// 0: Protocol Connection Handshake -// Add. Info: Undefined -// Control Info: Handshake information (see CHandShake) -// 1: Keep-alive -// Add. Info: Undefined -// Control Info: None -// 2: Acknowledgement (ACK) -// Add. Info: The ACK sequence number -// Control Info: The sequence number to which (but not include) all the previous packets have beed received -// Optional: RTT -// RTT Variance -// available receiver buffer size (in bytes) -// advertised flow window size (number of packets) -// estimated bandwidth (number of packets per second) -// 3: Negative Acknowledgement (NAK) -// Add. Info: Undefined -// Control Info: Loss list (see loss list coding below) -// 4: Congestion/Delay Warning -// Add. Info: Undefined -// Control Info: None -// 5: Shutdown -// Add. Info: Undefined -// Control Info: None -// 6: Acknowledgement of Acknowledement (ACK-square) -// Add. Info: The ACK sequence number -// Control Info: None -// 7: Message Drop Request -// Add. Info: Message ID -// Control Info: first sequence number of the message -// last seqeunce number of the message -// 8: Error Signal from the Peer Side -// Add. Info: Error code -// Control Info: None -// 0x7FFF: Explained by bits 16 - 31 -// -// bit 16 - 31: -// This space is used for future expansion or user defined control packets. -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |1| Sequence Number a (first) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |0| Sequence Number b (last) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// |0| Sequence Number (single) | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// Loss List Field Coding: -// For any consectutive lost seqeunce numbers that the differnece between -// the last and first is more than 1, only record the first (a) and the -// the last (b) sequence numbers in the loss list field, and modify the -// the first bit of a to 1. -// For any single loss or consectutive loss less than 2 packets, use -// the original sequence numbers in the field. - - -#include -#include "packet.h" - - -const int CPacket::m_iPktHdrSize = 16; -const int CHandShake::m_iContentSize = 48; - - -// Set up the aliases in the constructure -CPacket::CPacket(): -m_iSeqNo((int32_t&)(m_nHeader[0])), -m_iMsgNo((int32_t&)(m_nHeader[1])), -m_iTimeStamp((int32_t&)(m_nHeader[2])), -m_iID((int32_t&)(m_nHeader[3])), -m_pcData((char*&)(m_PacketVector[1].iov_base)), -__pad() -{ - for (int i = 0; i < 4; ++ i) - m_nHeader[i] = 0; - m_PacketVector[0].iov_base = (char *)m_nHeader; - m_PacketVector[0].iov_len = CPacket::m_iPktHdrSize; - m_PacketVector[1].iov_base = NULL; - m_PacketVector[1].iov_len = 0; -} - -CPacket::~CPacket() -{ -} - -int CPacket::getLength() const -{ - return m_PacketVector[1].iov_len; -} - -void CPacket::setLength(int len) -{ - m_PacketVector[1].iov_len = len; -} - -void CPacket::pack(int pkttype, void* lparam, void* rparam, int size) -{ - // Set (bit-0 = 1) and (bit-1~15 = type) - m_nHeader[0] = 0x80000000 | (pkttype << 16); - - // Set additional information and control information field - switch (pkttype) - { - case 2: //0010 - Acknowledgement (ACK) - // ACK packet seq. no. - if (NULL != lparam) - m_nHeader[1] = *(int32_t *)lparam; - - // data ACK seq. no. - // optional: RTT (microsends), RTT variance (microseconds) advertised flow window size (packets), and estimated link capacity (packets per second) - m_PacketVector[1].iov_base = (char *)rparam; - m_PacketVector[1].iov_len = size; - - break; - - case 6: //0110 - Acknowledgement of Acknowledgement (ACK-2) - // ACK packet seq. no. - m_nHeader[1] = *(int32_t *)lparam; - - // control info field should be none - // but "writev" does not allow this - m_PacketVector[1].iov_base = (char *)&__pad; //NULL; - m_PacketVector[1].iov_len = 4; //0; - - break; - - case 3: //0011 - Loss Report (NAK) - // loss list - m_PacketVector[1].iov_base = (char *)rparam; - m_PacketVector[1].iov_len = size; - - break; - - case 4: //0100 - Congestion Warning - // control info field should be none - // but "writev" does not allow this - m_PacketVector[1].iov_base = (char *)&__pad; //NULL; - m_PacketVector[1].iov_len = 4; //0; - - break; - - case 1: //0001 - Keep-alive - // control info field should be none - // but "writev" does not allow this - m_PacketVector[1].iov_base = (char *)&__pad; //NULL; - m_PacketVector[1].iov_len = 4; //0; - - break; - - case 0: //0000 - Handshake - // control info filed is handshake info - m_PacketVector[1].iov_base = (char *)rparam; - m_PacketVector[1].iov_len = size; //sizeof(CHandShake); - - break; - - case 5: //0101 - Shutdown - // control info field should be none - // but "writev" does not allow this - m_PacketVector[1].iov_base = (char *)&__pad; //NULL; - m_PacketVector[1].iov_len = 4; //0; - - break; - - case 7: //0111 - Message Drop Request - // msg id - m_nHeader[1] = *(int32_t *)lparam; - - //first seq no, last seq no - m_PacketVector[1].iov_base = (char *)rparam; - m_PacketVector[1].iov_len = size; - - break; - - case 8: //1000 - Error Signal from the Peer Side - // Error type - m_nHeader[1] = *(int32_t *)lparam; - - // control info field should be none - // but "writev" does not allow this - m_PacketVector[1].iov_base = (char *)&__pad; //NULL; - m_PacketVector[1].iov_len = 4; //0; - - break; - - case 32767: //0x7FFF - Reserved for user defined control packets - // for extended control packet - // "lparam" contains the extended type information for bit 16 - 31 - // "rparam" is the control information - m_nHeader[0] |= *(int32_t *)lparam; - - if (NULL != rparam) - { - m_PacketVector[1].iov_base = (char *)rparam; - m_PacketVector[1].iov_len = size; - } - else - { - m_PacketVector[1].iov_base = (char *)&__pad; - m_PacketVector[1].iov_len = 4; - } - - break; - - default: - break; - } -} - -iovec* CPacket::getPacketVector() -{ - return m_PacketVector; -} - -int CPacket::getFlag() const -{ - // read bit 0 - return m_nHeader[0] >> 31; -} - -int CPacket::getType() const -{ - // read bit 1~15 - return (m_nHeader[0] >> 16) & 0x00007FFF; -} - -int CPacket::getExtendedType() const -{ - // read bit 16~31 - return m_nHeader[0] & 0x0000FFFF; -} - -int32_t CPacket::getAckSeqNo() const -{ - // read additional information field - return m_nHeader[1]; -} - -int CPacket::getMsgBoundary() const -{ - // read [1] bit 0~1 - return m_nHeader[1] >> 30; -} - -bool CPacket::getMsgOrderFlag() const -{ - // read [1] bit 2 - return (1 == ((m_nHeader[1] >> 29) & 1)); -} - -int32_t CPacket::getMsgSeq() const -{ - // read [1] bit 3~31 - return m_nHeader[1] & 0x1FFFFFFF; -} - -CPacket* CPacket::clone() const -{ - CPacket* pkt = new CPacket; - memcpy(pkt->m_nHeader, m_nHeader, m_iPktHdrSize); - pkt->m_pcData = new char[m_PacketVector[1].iov_len]; - memcpy(pkt->m_pcData, m_pcData, m_PacketVector[1].iov_len); - pkt->m_PacketVector[1].iov_len = m_PacketVector[1].iov_len; - - return pkt; -} - -CHandShake::CHandShake(): -m_iVersion(0), -m_iType(0), -m_iISN(0), -m_iMSS(0), -m_iFlightFlagSize(0), -m_iReqType(0), -m_iID(0), -m_iCookie(0) -{ - for (int i = 0; i < 4; ++ i) - m_piPeerIP[i] = 0; -} - -int CHandShake::serialize(char* buf, int& size) -{ - if (size < m_iContentSize) - return -1; - - int32_t* p = (int32_t*)buf; - *p++ = m_iVersion; - *p++ = m_iType; - *p++ = m_iISN; - *p++ = m_iMSS; - *p++ = m_iFlightFlagSize; - *p++ = m_iReqType; - *p++ = m_iID; - *p++ = m_iCookie; - for (int i = 0; i < 4; ++ i) - *p++ = m_piPeerIP[i]; - - size = m_iContentSize; - - return 0; -} - -int CHandShake::deserialize(const char* buf, int size) -{ - if (size < m_iContentSize) - return -1; - - int32_t* p = (int32_t*)buf; - m_iVersion = *p++; - m_iType = *p++; - m_iISN = *p++; - m_iMSS = *p++; - m_iFlightFlagSize = *p++; - m_iReqType = *p++; - m_iID = *p++; - m_iCookie = *p++; - for (int i = 0; i < 4; ++ i) - m_piPeerIP[i] = *p++; - - return 0; -} diff --git a/vendor/udt4/src/packet.h b/vendor/udt4/src/packet.h deleted file mode 100644 index 76cc951..0000000 --- a/vendor/udt4/src/packet.h +++ /dev/null @@ -1,223 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/02/2011 -*****************************************************************************/ - -#ifndef __UDT_PACKET_H__ -#define __UDT_PACKET_H__ - - -#include "udt.h" - -#ifdef WIN32 - struct iovec - { - int iov_len; - char* iov_base; - }; -#endif - -class CChannel; - -class CPacket -{ -friend class CChannel; -friend class CSndQueue; -friend class CRcvQueue; - -public: - int32_t& m_iSeqNo; // alias: sequence number - int32_t& m_iMsgNo; // alias: message number - int32_t& m_iTimeStamp; // alias: timestamp - int32_t& m_iID; // alias: socket ID - char*& m_pcData; // alias: data/control information - - static const int m_iPktHdrSize; // packet header size - -public: - CPacket(); - ~CPacket(); - - // Functionality: - // Get the payload or the control information field length. - // Parameters: - // None. - // Returned value: - // the payload or the control information field length. - - int getLength() const; - - // Functionality: - // Set the payload or the control information field length. - // Parameters: - // 0) [in] len: the payload or the control information field length. - // Returned value: - // None. - - void setLength(int len); - - // Functionality: - // Pack a Control packet. - // Parameters: - // 0) [in] pkttype: packet type filed. - // 1) [in] lparam: pointer to the first data structure, explained by the packet type. - // 2) [in] rparam: pointer to the second data structure, explained by the packet type. - // 3) [in] size: size of rparam, in number of bytes; - // Returned value: - // None. - - void pack(int pkttype, void* lparam = NULL, void* rparam = NULL, int size = 0); - - // Functionality: - // Read the packet vector. - // Parameters: - // None. - // Returned value: - // Pointer to the packet vector. - - iovec* getPacketVector(); - - // Functionality: - // Read the packet flag. - // Parameters: - // None. - // Returned value: - // packet flag (0 or 1). - - int getFlag() const; - - // Functionality: - // Read the packet type. - // Parameters: - // None. - // Returned value: - // packet type filed (000 ~ 111). - - int getType() const; - - // Functionality: - // Read the extended packet type. - // Parameters: - // None. - // Returned value: - // extended packet type filed (0x000 ~ 0xFFF). - - int getExtendedType() const; - - // Functionality: - // Read the ACK-2 seq. no. - // Parameters: - // None. - // Returned value: - // packet header field (bit 16~31). - - int32_t getAckSeqNo() const; - - // Functionality: - // Read the message boundary flag bit. - // Parameters: - // None. - // Returned value: - // packet header field [1] (bit 0~1). - - int getMsgBoundary() const; - - // Functionality: - // Read the message inorder delivery flag bit. - // Parameters: - // None. - // Returned value: - // packet header field [1] (bit 2). - - bool getMsgOrderFlag() const; - - // Functionality: - // Read the message sequence number. - // Parameters: - // None. - // Returned value: - // packet header field [1] (bit 3~31). - - int32_t getMsgSeq() const; - - // Functionality: - // Clone this packet. - // Parameters: - // None. - // Returned value: - // Pointer to the new packet. - - CPacket* clone() const; - -protected: - uint32_t m_nHeader[4]; // The 128-bit header field - iovec m_PacketVector[2]; // The 2-demension vector of UDT packet [header, data] - - int32_t __pad; - -protected: - CPacket& operator=(const CPacket&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CHandShake -{ -public: - CHandShake(); - - int serialize(char* buf, int& size); - int deserialize(const char* buf, int size); - -public: - static const int m_iContentSize; // Size of hand shake data - -public: - int32_t m_iVersion; // UDT version - int32_t m_iType; // UDT socket type - int32_t m_iISN; // random initial sequence number - int32_t m_iMSS; // maximum segment size - int32_t m_iFlightFlagSize; // flow control window size - int32_t m_iReqType; // connection request type: 1: regular connection request, 0: rendezvous connection request, -1/-2: response - int32_t m_iID; // socket ID - int32_t m_iCookie; // cookie - uint32_t m_piPeerIP[4]; // The IP address that the peer's UDP port is bound to -}; - - -#endif diff --git a/vendor/udt4/src/queue.cpp b/vendor/udt4/src/queue.cpp deleted file mode 100644 index 2caea2a..0000000 --- a/vendor/udt4/src/queue.cpp +++ /dev/null @@ -1,1253 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 05/05/2011 -*****************************************************************************/ - -#ifdef WIN32 - #include - #include - #ifdef LEGACY_WIN32 - #include - #endif -#endif -#include - -#include "common.h" -#include "core.h" -#include "queue.h" - -using namespace std; - -CUnitQueue::CUnitQueue(): -m_pQEntry(NULL), -m_pCurrQueue(NULL), -m_pLastQueue(NULL), -m_iSize(0), -m_iCount(0), -m_iMSS(), -m_iIPversion() -{ -} - -CUnitQueue::~CUnitQueue() -{ - CQEntry* p = m_pQEntry; - - while (p != NULL) - { - delete [] p->m_pUnit; - delete [] p->m_pBuffer; - - CQEntry* q = p; - if (p == m_pLastQueue) - p = NULL; - else - p = p->m_pNext; - delete q; - } -} - -int CUnitQueue::init(int size, int mss, int version) -{ - CQEntry* tempq = NULL; - CUnit* tempu = NULL; - char* tempb = NULL; - - try - { - tempq = new CQEntry; - tempu = new CUnit [size]; - tempb = new char [size * mss]; - } - catch (...) - { - delete tempq; - delete [] tempu; - delete [] tempb; - - return -1; - } - - for (int i = 0; i < size; ++ i) - { - tempu[i].m_iFlag = 0; - tempu[i].m_Packet.m_pcData = tempb + i * mss; - } - tempq->m_pUnit = tempu; - tempq->m_pBuffer = tempb; - tempq->m_iSize = size; - - m_pQEntry = m_pCurrQueue = m_pLastQueue = tempq; - m_pQEntry->m_pNext = m_pQEntry; - - m_pAvailUnit = m_pCurrQueue->m_pUnit; - - m_iSize = size; - m_iMSS = mss; - m_iIPversion = version; - - return 0; -} - -int CUnitQueue::increase() -{ - // adjust/correct m_iCount - int real_count = 0; - CQEntry* p = m_pQEntry; - while (p != NULL) - { - CUnit* u = p->m_pUnit; - for (CUnit* end = u + p->m_iSize; u != end; ++ u) - if (u->m_iFlag != 0) - ++ real_count; - - if (p == m_pLastQueue) - p = NULL; - else - p = p->m_pNext; - } - m_iCount = real_count; - if (double(m_iCount) / m_iSize < 0.9) - return -1; - - CQEntry* tempq = NULL; - CUnit* tempu = NULL; - char* tempb = NULL; - - // all queues have the same size - int size = m_pQEntry->m_iSize; - - try - { - tempq = new CQEntry; - tempu = new CUnit [size]; - tempb = new char [size * m_iMSS]; - } - catch (...) - { - delete tempq; - delete [] tempu; - delete [] tempb; - - return -1; - } - - for (int i = 0; i < size; ++ i) - { - tempu[i].m_iFlag = 0; - tempu[i].m_Packet.m_pcData = tempb + i * m_iMSS; - } - tempq->m_pUnit = tempu; - tempq->m_pBuffer = tempb; - tempq->m_iSize = size; - - m_pLastQueue->m_pNext = tempq; - m_pLastQueue = tempq; - m_pLastQueue->m_pNext = m_pQEntry; - - m_iSize += size; - - return 0; -} - -int CUnitQueue::shrink() -{ - // currently queue cannot be shrunk. - return -1; -} - -CUnit* CUnitQueue::getNextAvailUnit() -{ - if (m_iCount * 10 > m_iSize * 9) - increase(); - - if (m_iCount >= m_iSize) - return NULL; - - CQEntry* entrance = m_pCurrQueue; - - do - { - for (CUnit* sentinel = m_pCurrQueue->m_pUnit + m_pCurrQueue->m_iSize - 1; m_pAvailUnit != sentinel; ++ m_pAvailUnit) - if (m_pAvailUnit->m_iFlag == 0) - return m_pAvailUnit; - - if (m_pCurrQueue->m_pUnit->m_iFlag == 0) - { - m_pAvailUnit = m_pCurrQueue->m_pUnit; - return m_pAvailUnit; - } - - m_pCurrQueue = m_pCurrQueue->m_pNext; - m_pAvailUnit = m_pCurrQueue->m_pUnit; - } while (m_pCurrQueue != entrance); - - increase(); - - return NULL; -} - - -CSndUList::CSndUList(): -m_pHeap(NULL), -m_iArrayLength(4096), -m_iLastEntry(-1), -m_ListLock(), -m_pWindowLock(NULL), -m_pWindowCond(NULL), -m_pTimer(NULL) -{ - m_pHeap = new CSNode*[m_iArrayLength]; - - #ifndef WIN32 - pthread_mutex_init(&m_ListLock, NULL); - #else - m_ListLock = CreateMutex(NULL, false, NULL); - #endif -} - -CSndUList::~CSndUList() -{ - delete [] m_pHeap; - - #ifndef WIN32 - pthread_mutex_destroy(&m_ListLock); - #else - CloseHandle(m_ListLock); - #endif -} - -void CSndUList::insert(int64_t ts, const CUDT* u) -{ - CGuard listguard(m_ListLock); - - // increase the heap array size if necessary - if (m_iLastEntry == m_iArrayLength - 1) - { - CSNode** temp = NULL; - - try - { - temp = new CSNode*[m_iArrayLength * 2]; - } - catch(...) - { - return; - } - - memcpy(temp, m_pHeap, sizeof(CSNode*) * m_iArrayLength); - m_iArrayLength *= 2; - delete [] m_pHeap; - m_pHeap = temp; - } - - insert_(ts, u); -} - -void CSndUList::update(const CUDT* u, bool reschedule) -{ - CGuard listguard(m_ListLock); - - CSNode* n = u->m_pSNode; - - if (n->m_iHeapLoc >= 0) - { - if (!reschedule) - return; - - if (n->m_iHeapLoc == 0) - { - n->m_llTimeStamp = 1; - m_pTimer->interrupt(); - return; - } - - remove_(u); - } - - insert_(1, u); -} - -int CSndUList::pop(sockaddr*& addr, CPacket& pkt) -{ - CGuard listguard(m_ListLock); - - if (-1 == m_iLastEntry) - return -1; - - // no pop until the next schedulled time - uint64_t ts; - CTimer::rdtsc(ts); - if (ts < m_pHeap[0]->m_llTimeStamp) - return -1; - - CUDT* u = m_pHeap[0]->m_pUDT; - remove_(u); - - if (!u->m_bConnected || u->m_bBroken) - return -1; - - // pack a packet from the socket - if (u->packData(pkt, ts) <= 0) - return -1; - - addr = u->m_pPeerAddr; - - // insert a new entry, ts is the next processing time - if (ts > 0) - insert_(ts, u); - - return 1; -} - -void CSndUList::remove(const CUDT* u) -{ - CGuard listguard(m_ListLock); - - remove_(u); -} - -uint64_t CSndUList::getNextProcTime() -{ - CGuard listguard(m_ListLock); - - if (-1 == m_iLastEntry) - return 0; - - return m_pHeap[0]->m_llTimeStamp; -} - -void CSndUList::insert_(int64_t ts, const CUDT* u) -{ - CSNode* n = u->m_pSNode; - - // do not insert repeated node - if (n->m_iHeapLoc >= 0) - return; - - m_iLastEntry ++; - m_pHeap[m_iLastEntry] = n; - n->m_llTimeStamp = ts; - - int q = m_iLastEntry; - int p = q; - while (p != 0) - { - p = (q - 1) >> 1; - if (m_pHeap[p]->m_llTimeStamp > m_pHeap[q]->m_llTimeStamp) - { - CSNode* t = m_pHeap[p]; - m_pHeap[p] = m_pHeap[q]; - m_pHeap[q] = t; - t->m_iHeapLoc = q; - q = p; - } - else - break; - } - - n->m_iHeapLoc = q; - - // an earlier event has been inserted, wake up sending worker - if (n->m_iHeapLoc == 0) - m_pTimer->interrupt(); - - // first entry, activate the sending queue - if (0 == m_iLastEntry) - { - #ifndef WIN32 - pthread_mutex_lock(m_pWindowLock); - pthread_cond_signal(m_pWindowCond); - pthread_mutex_unlock(m_pWindowLock); - #else - SetEvent(*m_pWindowCond); - #endif - } -} - -void CSndUList::remove_(const CUDT* u) -{ - CSNode* n = u->m_pSNode; - - if (n->m_iHeapLoc >= 0) - { - // remove the node from heap - m_pHeap[n->m_iHeapLoc] = m_pHeap[m_iLastEntry]; - m_iLastEntry --; - m_pHeap[n->m_iHeapLoc]->m_iHeapLoc = n->m_iHeapLoc; - - int q = n->m_iHeapLoc; - int p = q * 2 + 1; - while (p <= m_iLastEntry) - { - if ((p + 1 <= m_iLastEntry) && (m_pHeap[p]->m_llTimeStamp > m_pHeap[p + 1]->m_llTimeStamp)) - p ++; - - if (m_pHeap[q]->m_llTimeStamp > m_pHeap[p]->m_llTimeStamp) - { - CSNode* t = m_pHeap[p]; - m_pHeap[p] = m_pHeap[q]; - m_pHeap[p]->m_iHeapLoc = p; - m_pHeap[q] = t; - m_pHeap[q]->m_iHeapLoc = q; - - q = p; - p = q * 2 + 1; - } - else - break; - } - - n->m_iHeapLoc = -1; - } - - // the only event has been deleted, wake up immediately - if (0 == m_iLastEntry) - m_pTimer->interrupt(); -} - -// -CSndQueue::CSndQueue(): -m_WorkerThread(), -m_pSndUList(NULL), -m_pChannel(NULL), -m_pTimer(NULL), -m_WindowLock(), -m_WindowCond(), -m_bClosing(false), -m_ExitCond() -{ - #ifndef WIN32 - pthread_cond_init(&m_WindowCond, NULL); - pthread_mutex_init(&m_WindowLock, NULL); - #else - m_WindowLock = CreateMutex(NULL, false, NULL); - m_WindowCond = CreateEvent(NULL, false, false, NULL); - m_ExitCond = CreateEvent(NULL, false, false, NULL); - #endif -} - -CSndQueue::~CSndQueue() -{ - m_bClosing = true; - - #ifndef WIN32 - pthread_mutex_lock(&m_WindowLock); - pthread_cond_signal(&m_WindowCond); - pthread_mutex_unlock(&m_WindowLock); - if (0 != m_WorkerThread) - pthread_join(m_WorkerThread, NULL); - pthread_cond_destroy(&m_WindowCond); - pthread_mutex_destroy(&m_WindowLock); - #else - SetEvent(m_WindowCond); - if (NULL != m_WorkerThread) - WaitForSingleObject(m_ExitCond, INFINITE); - CloseHandle(m_WorkerThread); - CloseHandle(m_WindowLock); - CloseHandle(m_WindowCond); - CloseHandle(m_ExitCond); - #endif - - delete m_pSndUList; -} - -void CSndQueue::init(CChannel* c, CTimer* t) -{ - m_pChannel = c; - m_pTimer = t; - m_pSndUList = new CSndUList; - m_pSndUList->m_pWindowLock = &m_WindowLock; - m_pSndUList->m_pWindowCond = &m_WindowCond; - m_pSndUList->m_pTimer = m_pTimer; - - #ifndef WIN32 - if (0 != pthread_create(&m_WorkerThread, NULL, CSndQueue::worker, this)) - { - m_WorkerThread = 0; - throw CUDTException(3, 1); - } - #else - DWORD threadID; - m_WorkerThread = CreateThread(NULL, 0, CSndQueue::worker, this, 0, &threadID); - if (NULL == m_WorkerThread) - throw CUDTException(3, 1); - #endif -} - -#ifndef WIN32 - void* CSndQueue::worker(void* param) -#else - DWORD WINAPI CSndQueue::worker(LPVOID param) -#endif -{ - CSndQueue* self = (CSndQueue*)param; - - while (!self->m_bClosing) - { - uint64_t ts = self->m_pSndUList->getNextProcTime(); - - if (ts > 0) - { - // wait until next processing time of the first socket on the list - uint64_t currtime; - CTimer::rdtsc(currtime); - if (currtime < ts) - self->m_pTimer->sleepto(ts); - - // it is time to send the next pkt - sockaddr* addr; - CPacket pkt; - if (self->m_pSndUList->pop(addr, pkt) < 0) - continue; - - self->m_pChannel->sendto(addr, pkt); - } - else - { - // wait here if there is no sockets with data to be sent - #ifndef WIN32 - pthread_mutex_lock(&self->m_WindowLock); - if (!self->m_bClosing && (self->m_pSndUList->m_iLastEntry < 0)) - pthread_cond_wait(&self->m_WindowCond, &self->m_WindowLock); - pthread_mutex_unlock(&self->m_WindowLock); - #else - WaitForSingleObject(self->m_WindowCond, INFINITE); - #endif - } - } - - #ifndef WIN32 - return NULL; - #else - SetEvent(self->m_ExitCond); - return 0; - #endif -} - -int CSndQueue::sendto(const sockaddr* addr, CPacket& packet) -{ - // send out the packet immediately (high priority), this is a control packet - m_pChannel->sendto(addr, packet); - return packet.getLength(); -} - - -// -CRcvUList::CRcvUList(): -m_pUList(NULL), -m_pLast(NULL) -{ -} - -CRcvUList::~CRcvUList() -{ -} - -void CRcvUList::insert(const CUDT* u) -{ - CRNode* n = u->m_pRNode; - CTimer::rdtsc(n->m_llTimeStamp); - - if (NULL == m_pUList) - { - // empty list, insert as the single node - n->m_pPrev = n->m_pNext = NULL; - m_pLast = m_pUList = n; - - return; - } - - // always insert at the end for RcvUList - n->m_pPrev = m_pLast; - n->m_pNext = NULL; - m_pLast->m_pNext = n; - m_pLast = n; -} - -void CRcvUList::remove(const CUDT* u) -{ - CRNode* n = u->m_pRNode; - - if (!n->m_bOnList) - return; - - if (NULL == n->m_pPrev) - { - // n is the first node - m_pUList = n->m_pNext; - if (NULL == m_pUList) - m_pLast = NULL; - else - m_pUList->m_pPrev = NULL; - } - else - { - n->m_pPrev->m_pNext = n->m_pNext; - if (NULL == n->m_pNext) - { - // n is the last node - m_pLast = n->m_pPrev; - } - else - n->m_pNext->m_pPrev = n->m_pPrev; - } - - n->m_pNext = n->m_pPrev = NULL; -} - -void CRcvUList::update(const CUDT* u) -{ - CRNode* n = u->m_pRNode; - - if (!n->m_bOnList) - return; - - CTimer::rdtsc(n->m_llTimeStamp); - - // if n is the last node, do not need to change - if (NULL == n->m_pNext) - return; - - if (NULL == n->m_pPrev) - { - m_pUList = n->m_pNext; - m_pUList->m_pPrev = NULL; - } - else - { - n->m_pPrev->m_pNext = n->m_pNext; - n->m_pNext->m_pPrev = n->m_pPrev; - } - - n->m_pPrev = m_pLast; - n->m_pNext = NULL; - m_pLast->m_pNext = n; - m_pLast = n; -} - -// -CHash::CHash(): -m_pBucket(NULL), -m_iHashSize(0) -{ -} - -CHash::~CHash() -{ - for (int i = 0; i < m_iHashSize; ++ i) - { - CBucket* b = m_pBucket[i]; - while (NULL != b) - { - CBucket* n = b->m_pNext; - delete b; - b = n; - } - } - - delete [] m_pBucket; -} - -void CHash::init(int size) -{ - m_pBucket = new CBucket* [size]; - - for (int i = 0; i < size; ++ i) - m_pBucket[i] = NULL; - - m_iHashSize = size; -} - -CUDT* CHash::lookup(int32_t id) -{ - // simple hash function (% hash table size); suitable for socket descriptors - CBucket* b = m_pBucket[id % m_iHashSize]; - - while (NULL != b) - { - if (id == b->m_iID) - return b->m_pUDT; - b = b->m_pNext; - } - - return NULL; -} - -void CHash::insert(int32_t id, CUDT* u) -{ - CBucket* b = m_pBucket[id % m_iHashSize]; - - CBucket* n = new CBucket; - n->m_iID = id; - n->m_pUDT = u; - n->m_pNext = b; - - m_pBucket[id % m_iHashSize] = n; -} - -void CHash::remove(int32_t id) -{ - CBucket* b = m_pBucket[id % m_iHashSize]; - CBucket* p = NULL; - - while (NULL != b) - { - if (id == b->m_iID) - { - if (NULL == p) - m_pBucket[id % m_iHashSize] = b->m_pNext; - else - p->m_pNext = b->m_pNext; - - delete b; - - return; - } - - p = b; - b = b->m_pNext; - } -} - - -// -CRendezvousQueue::CRendezvousQueue(): -m_lRendezvousID(), -m_RIDVectorLock() -{ - #ifndef WIN32 - pthread_mutex_init(&m_RIDVectorLock, NULL); - #else - m_RIDVectorLock = CreateMutex(NULL, false, NULL); - #endif -} - -CRendezvousQueue::~CRendezvousQueue() -{ - #ifndef WIN32 - pthread_mutex_destroy(&m_RIDVectorLock); - #else - CloseHandle(m_RIDVectorLock); - #endif - - for (list::iterator i = m_lRendezvousID.begin(); i != m_lRendezvousID.end(); ++ i) - { - if (AF_INET == i->m_iIPversion) - delete (sockaddr_in*)i->m_pPeerAddr; - else - delete (sockaddr_in6*)i->m_pPeerAddr; - } - - m_lRendezvousID.clear(); -} - -void CRendezvousQueue::insert(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl) -{ - CGuard vg(m_RIDVectorLock); - - CRL r; - r.m_iID = id; - r.m_pUDT = u; - r.m_iIPversion = ipv; - r.m_pPeerAddr = (AF_INET == ipv) ? (sockaddr*)new sockaddr_in : (sockaddr*)new sockaddr_in6; - memcpy(r.m_pPeerAddr, addr, (AF_INET == ipv) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); - r.m_ullTTL = ttl; - - m_lRendezvousID.push_back(r); -} - -void CRendezvousQueue::remove(const UDTSOCKET& id) -{ - CGuard vg(m_RIDVectorLock); - - for (list::iterator i = m_lRendezvousID.begin(); i != m_lRendezvousID.end(); ++ i) - { - if (i->m_iID == id) - { - if (AF_INET == i->m_iIPversion) - delete (sockaddr_in*)i->m_pPeerAddr; - else - delete (sockaddr_in6*)i->m_pPeerAddr; - - m_lRendezvousID.erase(i); - - return; - } - } -} - -CUDT* CRendezvousQueue::retrieve(const sockaddr* addr, UDTSOCKET& id) -{ - CGuard vg(m_RIDVectorLock); - - // TODO: optimize search - for (list::iterator i = m_lRendezvousID.begin(); i != m_lRendezvousID.end(); ++ i) - { - if (CIPAddress::ipcmp(addr, i->m_pPeerAddr, i->m_iIPversion) && ((0 == id) || (id == i->m_iID))) - { - id = i->m_iID; - return i->m_pUDT; - } - } - - return NULL; -} - -void CRendezvousQueue::updateConnStatus() -{ - if (m_lRendezvousID.empty()) - return; - - CGuard vg(m_RIDVectorLock); - - for (list::iterator i = m_lRendezvousID.begin(); i != m_lRendezvousID.end(); ++ i) - { - // avoid sending too many requests, at most 1 request per 250ms - if (CTimer::getTime() - i->m_pUDT->m_llLastReqTime > 250000) - { - if (CTimer::getTime() >= i->m_ullTTL) - { - // connection timer expired, acknowledge app via epoll - i->m_pUDT->m_bConnecting = false; - CUDT::s_UDTUnited.m_EPoll.update_events(i->m_iID, i->m_pUDT->m_sPollID, UDT_EPOLL_ERR, true); - continue; - } - - CPacket request; - char* reqdata = new char [i->m_pUDT->m_iPayloadSize]; - request.pack(0, NULL, reqdata, i->m_pUDT->m_iPayloadSize); - // ID = 0, connection request - request.m_iID = !i->m_pUDT->m_bRendezvous ? 0 : i->m_pUDT->m_ConnRes.m_iID; - int hs_size = i->m_pUDT->m_iPayloadSize; - i->m_pUDT->m_ConnReq.serialize(reqdata, hs_size); - request.setLength(hs_size); - i->m_pUDT->m_pSndQueue->sendto(i->m_pPeerAddr, request); - i->m_pUDT->m_llLastReqTime = CTimer::getTime(); - delete [] reqdata; - } - } -} - -// -CRcvQueue::CRcvQueue(): -m_WorkerThread(), -m_UnitQueue(), -m_pRcvUList(NULL), -m_pHash(NULL), -m_pChannel(NULL), -m_pTimer(NULL), -m_iPayloadSize(), -m_bClosing(false), -m_ExitCond(), -m_LSLock(), -m_pListener(NULL), -m_pRendezvousQueue(NULL), -m_vNewEntry(), -m_IDLock(), -m_mBuffer(), -m_PassLock(), -m_PassCond() -{ - #ifndef WIN32 - pthread_mutex_init(&m_PassLock, NULL); - pthread_cond_init(&m_PassCond, NULL); - pthread_mutex_init(&m_LSLock, NULL); - pthread_mutex_init(&m_IDLock, NULL); - #else - m_PassLock = CreateMutex(NULL, false, NULL); - m_PassCond = CreateEvent(NULL, false, false, NULL); - m_LSLock = CreateMutex(NULL, false, NULL); - m_IDLock = CreateMutex(NULL, false, NULL); - m_ExitCond = CreateEvent(NULL, false, false, NULL); - #endif -} - -CRcvQueue::~CRcvQueue() -{ - m_bClosing = true; - - #ifndef WIN32 - if (0 != m_WorkerThread) - pthread_join(m_WorkerThread, NULL); - pthread_mutex_destroy(&m_PassLock); - pthread_cond_destroy(&m_PassCond); - pthread_mutex_destroy(&m_LSLock); - pthread_mutex_destroy(&m_IDLock); - #else - if (NULL != m_WorkerThread) - WaitForSingleObject(m_ExitCond, INFINITE); - CloseHandle(m_WorkerThread); - CloseHandle(m_PassLock); - CloseHandle(m_PassCond); - CloseHandle(m_LSLock); - CloseHandle(m_IDLock); - CloseHandle(m_ExitCond); - #endif - - delete m_pRcvUList; - delete m_pHash; - delete m_pRendezvousQueue; - - // remove all queued messages - for (map >::iterator i = m_mBuffer.begin(); i != m_mBuffer.end(); ++ i) - { - while (!i->second.empty()) - { - CPacket* pkt = i->second.front(); - delete [] pkt->m_pcData; - delete pkt; - i->second.pop(); - } - } -} - -void CRcvQueue::init(int qsize, int payload, int version, int hsize, CChannel* cc, CTimer* t) -{ - m_iPayloadSize = payload; - - m_UnitQueue.init(qsize, payload, version); - - m_pHash = new CHash; - m_pHash->init(hsize); - - m_pChannel = cc; - m_pTimer = t; - - m_pRcvUList = new CRcvUList; - m_pRendezvousQueue = new CRendezvousQueue; - - #ifndef WIN32 - if (0 != pthread_create(&m_WorkerThread, NULL, CRcvQueue::worker, this)) - { - m_WorkerThread = 0; - throw CUDTException(3, 1); - } - #else - DWORD threadID; - m_WorkerThread = CreateThread(NULL, 0, CRcvQueue::worker, this, 0, &threadID); - if (NULL == m_WorkerThread) - throw CUDTException(3, 1); - #endif -} - -#ifndef WIN32 - void* CRcvQueue::worker(void* param) -#else - DWORD WINAPI CRcvQueue::worker(LPVOID param) -#endif -{ - CRcvQueue* self = (CRcvQueue*)param; - - sockaddr* addr = (AF_INET == self->m_UnitQueue.m_iIPversion) ? (sockaddr*) new sockaddr_in : (sockaddr*) new sockaddr_in6; - CUDT* u = NULL; - int32_t id; - - while (!self->m_bClosing) - { - #ifdef NO_BUSY_WAITING - self->m_pTimer->tick(); - #endif - - // check waiting list, if new socket, insert it to the list - while (self->ifNewEntry()) - { - CUDT* ne = self->getNewEntry(); - if (NULL != ne) - { - self->m_pRcvUList->insert(ne); - self->m_pHash->insert(ne->m_SocketID, ne); - } - } - - // find next available slot for incoming packet - CUnit* unit = self->m_UnitQueue.getNextAvailUnit(); - if (NULL == unit) - { - // no space, skip this packet - CPacket temp; - temp.m_pcData = new char[self->m_iPayloadSize]; - temp.setLength(self->m_iPayloadSize); - self->m_pChannel->recvfrom(addr, temp); - delete [] temp.m_pcData; - goto TIMER_CHECK; - } - - unit->m_Packet.setLength(self->m_iPayloadSize); - - // reading next incoming packet, recvfrom returns -1 is nothing has been received - if (self->m_pChannel->recvfrom(addr, unit->m_Packet) < 0) - goto TIMER_CHECK; - - id = unit->m_Packet.m_iID; - - // ID 0 is for connection request, which should be passed to the listening socket or rendezvous sockets - if (0 == id) - { - if (NULL != self->m_pListener) - self->m_pListener->listen(addr, unit->m_Packet); - else if (NULL != (u = self->m_pRendezvousQueue->retrieve(addr, id))) - { - // asynchronous connect: call connect here - // otherwise wait for the UDT socket to retrieve this packet - if (!u->m_bSynRecving) - u->connect(unit->m_Packet); - else - self->storePkt(id, unit->m_Packet.clone()); - } - } - else if (id > 0) - { - if (NULL != (u = self->m_pHash->lookup(id))) - { - if (CIPAddress::ipcmp(addr, u->m_pPeerAddr, u->m_iIPversion)) - { - if (u->m_bConnected && !u->m_bBroken && !u->m_bClosing) - { - if (0 == unit->m_Packet.getFlag()) - u->processData(unit); - else - u->processCtrl(unit->m_Packet); - - u->checkTimers(); - self->m_pRcvUList->update(u); - } - } - } - else if (NULL != (u = self->m_pRendezvousQueue->retrieve(addr, id))) - { - if (!u->m_bSynRecving) - u->connect(unit->m_Packet); - else - self->storePkt(id, unit->m_Packet.clone()); - } - } - -TIMER_CHECK: - // take care of the timing event for all UDT sockets - - uint64_t currtime; - CTimer::rdtsc(currtime); - - CRNode* ul = self->m_pRcvUList->m_pUList; - uint64_t ctime = currtime - 100000 * CTimer::getCPUFrequency(); - while ((NULL != ul) && (ul->m_llTimeStamp < ctime)) - { - CUDT* u = ul->m_pUDT; - - if (u->m_bConnected && !u->m_bBroken && !u->m_bClosing) - { - u->checkTimers(); - self->m_pRcvUList->update(u); - } - else - { - // the socket must be removed from Hash table first, then RcvUList - self->m_pHash->remove(u->m_SocketID); - self->m_pRcvUList->remove(u); - u->m_pRNode->m_bOnList = false; - } - - ul = self->m_pRcvUList->m_pUList; - } - - // Check connection requests status for all sockets in the RendezvousQueue. - self->m_pRendezvousQueue->updateConnStatus(); - } - - if (AF_INET == self->m_UnitQueue.m_iIPversion) - delete (sockaddr_in*)addr; - else - delete (sockaddr_in6*)addr; - - #ifndef WIN32 - return NULL; - #else - SetEvent(self->m_ExitCond); - return 0; - #endif -} - -int CRcvQueue::recvfrom(int32_t id, CPacket& packet) -{ - CGuard bufferlock(m_PassLock); - - map >::iterator i = m_mBuffer.find(id); - - if (i == m_mBuffer.end()) - { - #ifndef WIN32 - uint64_t now = CTimer::getTime(); - timespec timeout; - - timeout.tv_sec = now / 1000000 + 1; - timeout.tv_nsec = (now % 1000000) * 1000; - - pthread_cond_timedwait(&m_PassCond, &m_PassLock, &timeout); - #else - ReleaseMutex(m_PassLock); - WaitForSingleObject(m_PassCond, 1000); - WaitForSingleObject(m_PassLock, INFINITE); - #endif - - i = m_mBuffer.find(id); - if (i == m_mBuffer.end()) - { - packet.setLength(-1); - return -1; - } - } - - // retrieve the earliest packet - CPacket* newpkt = i->second.front(); - - if (packet.getLength() < newpkt->getLength()) - { - packet.setLength(-1); - return -1; - } - - // copy packet content - memcpy(packet.m_nHeader, newpkt->m_nHeader, CPacket::m_iPktHdrSize); - memcpy(packet.m_pcData, newpkt->m_pcData, newpkt->getLength()); - packet.setLength(newpkt->getLength()); - - delete [] newpkt->m_pcData; - delete newpkt; - - // remove this message from queue, - // if no more messages left for this socket, release its data structure - i->second.pop(); - if (i->second.empty()) - m_mBuffer.erase(i); - - return packet.getLength(); -} - -int CRcvQueue::setListener(CUDT* u) -{ - CGuard lslock(m_LSLock); - - if (NULL != m_pListener) - return -1; - - m_pListener = u; - return 0; -} - -void CRcvQueue::removeListener(const CUDT* u) -{ - CGuard lslock(m_LSLock); - - if (u == m_pListener) - m_pListener = NULL; -} - -void CRcvQueue::registerConnector(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl) -{ - m_pRendezvousQueue->insert(id, u, ipv, addr, ttl); -} - -void CRcvQueue::removeConnector(const UDTSOCKET& id) -{ - m_pRendezvousQueue->remove(id); - - CGuard bufferlock(m_PassLock); - - map >::iterator i = m_mBuffer.find(id); - if (i != m_mBuffer.end()) - { - while (!i->second.empty()) - { - delete [] i->second.front()->m_pcData; - delete i->second.front(); - i->second.pop(); - } - m_mBuffer.erase(i); - } -} - -void CRcvQueue::setNewEntry(CUDT* u) -{ - CGuard listguard(m_IDLock); - m_vNewEntry.push_back(u); -} - -bool CRcvQueue::ifNewEntry() -{ - return !(m_vNewEntry.empty()); -} - -CUDT* CRcvQueue::getNewEntry() -{ - CGuard listguard(m_IDLock); - - if (m_vNewEntry.empty()) - return NULL; - - CUDT* u = (CUDT*)*(m_vNewEntry.begin()); - m_vNewEntry.erase(m_vNewEntry.begin()); - - return u; -} - -void CRcvQueue::storePkt(int32_t id, CPacket* pkt) -{ - CGuard bufferlock(m_PassLock); - - map >::iterator i = m_mBuffer.find(id); - - if (i == m_mBuffer.end()) - { - m_mBuffer[id].push(pkt); - - #ifndef WIN32 - pthread_cond_signal(&m_PassCond); - #else - SetEvent(m_PassCond); - #endif - } - else - { - //avoid storing too many packets, in case of malfunction or attack - if (i->second.size() > 16) - return; - - i->second.push(pkt); - } -} diff --git a/vendor/udt4/src/queue.h b/vendor/udt4/src/queue.h deleted file mode 100644 index 9feff18..0000000 --- a/vendor/udt4/src/queue.h +++ /dev/null @@ -1,527 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/12/2011 -*****************************************************************************/ - - -#ifndef __UDT_QUEUE_H__ -#define __UDT_QUEUE_H__ - -#include "channel.h" -#include "common.h" -#include "packet.h" -#include -#include -#include -#include - -class CUDT; - -struct CUnit -{ - CPacket m_Packet; // packet - int m_iFlag; // 0: free, 1: occupied, 2: msg read but not freed (out-of-order), 3: msg dropped -}; - -class CUnitQueue -{ -friend class CRcvQueue; -friend class CRcvBuffer; - -public: - CUnitQueue(); - ~CUnitQueue(); - -public: - - // Functionality: - // Initialize the unit queue. - // Parameters: - // 1) [in] size: queue size - // 2) [in] mss: maximum segament size - // 3) [in] version: IP version - // Returned value: - // 0: success, -1: failure. - - int init(int size, int mss, int version); - - // Functionality: - // Increase (double) the unit queue size. - // Parameters: - // None. - // Returned value: - // 0: success, -1: failure. - - int increase(); - - // Functionality: - // Decrease (halve) the unit queue size. - // Parameters: - // None. - // Returned value: - // 0: success, -1: failure. - - int shrink(); - - // Functionality: - // find an available unit for incoming packet. - // Parameters: - // None. - // Returned value: - // Pointer to the available unit, NULL if not found. - - CUnit* getNextAvailUnit(); - -private: - struct CQEntry - { - CUnit* m_pUnit; // unit queue - char* m_pBuffer; // data buffer - int m_iSize; // size of each queue - - CQEntry* m_pNext; - } - *m_pQEntry, // pointer to the first unit queue - *m_pCurrQueue, // pointer to the current available queue - *m_pLastQueue; // pointer to the last unit queue - - CUnit* m_pAvailUnit; // recent available unit - - int m_iSize; // total size of the unit queue, in number of packets - int m_iCount; // total number of valid packets in the queue - - int m_iMSS; // unit buffer size - int m_iIPversion; // IP version - -private: - CUnitQueue(const CUnitQueue&); - CUnitQueue& operator=(const CUnitQueue&); -}; - -struct CSNode -{ - CUDT* m_pUDT; // Pointer to the instance of CUDT socket - uint64_t m_llTimeStamp; // Time Stamp - - int m_iHeapLoc; // location on the heap, -1 means not on the heap -}; - -class CSndUList -{ -friend class CSndQueue; - -public: - CSndUList(); - ~CSndUList(); - -public: - - // Functionality: - // Insert a new UDT instance into the list. - // Parameters: - // 1) [in] ts: time stamp: next processing time - // 2) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void insert(int64_t ts, const CUDT* u); - - // Functionality: - // Update the timestamp of the UDT instance on the list. - // Parameters: - // 1) [in] u: pointer to the UDT instance - // 2) [in] resechedule: if the timestampe shoudl be rescheduled - // Returned value: - // None. - - void update(const CUDT* u, bool reschedule = true); - - // Functionality: - // Retrieve the next packet and peer address from the first entry, and reschedule it in the queue. - // Parameters: - // 0) [out] addr: destination address of the next packet - // 1) [out] pkt: the next packet to be sent - // Returned value: - // 1 if successfully retrieved, -1 if no packet found. - - int pop(sockaddr*& addr, CPacket& pkt); - - // Functionality: - // Remove UDT instance from the list. - // Parameters: - // 1) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void remove(const CUDT* u); - - // Functionality: - // Retrieve the next scheduled processing time. - // Parameters: - // None. - // Returned value: - // Scheduled processing time of the first UDT socket in the list. - - uint64_t getNextProcTime(); - -private: - void insert_(int64_t ts, const CUDT* u); - void remove_(const CUDT* u); - -private: - CSNode** m_pHeap; // The heap array - int m_iArrayLength; // physical length of the array - int m_iLastEntry; // position of last entry on the heap array - - pthread_mutex_t m_ListLock; - - pthread_mutex_t* m_pWindowLock; - pthread_cond_t* m_pWindowCond; - - CTimer* m_pTimer; - -private: - CSndUList(const CSndUList&); - CSndUList& operator=(const CSndUList&); -}; - -struct CRNode -{ - CUDT* m_pUDT; // Pointer to the instance of CUDT socket - uint64_t m_llTimeStamp; // Time Stamp - - CRNode* m_pPrev; // previous link - CRNode* m_pNext; // next link - - bool m_bOnList; // if the node is already on the list -}; - -class CRcvUList -{ -public: - CRcvUList(); - ~CRcvUList(); - -public: - - // Functionality: - // Insert a new UDT instance to the list. - // Parameters: - // 1) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void insert(const CUDT* u); - - // Functionality: - // Remove the UDT instance from the list. - // Parameters: - // 1) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void remove(const CUDT* u); - - // Functionality: - // Move the UDT instance to the end of the list, if it already exists; otherwise, do nothing. - // Parameters: - // 1) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void update(const CUDT* u); - -public: - CRNode* m_pUList; // the head node - -private: - CRNode* m_pLast; // the last node - -private: - CRcvUList(const CRcvUList&); - CRcvUList& operator=(const CRcvUList&); -}; - -class CHash -{ -public: - CHash(); - ~CHash(); - -public: - - // Functionality: - // Initialize the hash table. - // Parameters: - // 1) [in] size: hash table size - // Returned value: - // None. - - void init(int size); - - // Functionality: - // Look for a UDT instance from the hash table. - // Parameters: - // 1) [in] id: socket ID - // Returned value: - // Pointer to a UDT instance, or NULL if not found. - - CUDT* lookup(int32_t id); - - // Functionality: - // Insert an entry to the hash table. - // Parameters: - // 1) [in] id: socket ID - // 2) [in] u: pointer to the UDT instance - // Returned value: - // None. - - void insert(int32_t id, CUDT* u); - - // Functionality: - // Remove an entry from the hash table. - // Parameters: - // 1) [in] id: socket ID - // Returned value: - // None. - - void remove(int32_t id); - -private: - struct CBucket - { - int32_t m_iID; // Socket ID - CUDT* m_pUDT; // Socket instance - - CBucket* m_pNext; // next bucket - } **m_pBucket; // list of buckets (the hash table) - - int m_iHashSize; // size of hash table - -private: - CHash(const CHash&); - CHash& operator=(const CHash&); -}; - -class CRendezvousQueue -{ -public: - CRendezvousQueue(); - ~CRendezvousQueue(); - -public: - void insert(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl); - void remove(const UDTSOCKET& id); - CUDT* retrieve(const sockaddr* addr, UDTSOCKET& id); - - void updateConnStatus(); - -private: - struct CRL - { - UDTSOCKET m_iID; // UDT socket ID (self) - CUDT* m_pUDT; // UDT instance - int m_iIPversion; // IP version - sockaddr* m_pPeerAddr; // UDT sonnection peer address - uint64_t m_ullTTL; // the time that this request expires - }; - std::list m_lRendezvousID; // The sockets currently in rendezvous mode - - pthread_mutex_t m_RIDVectorLock; -}; - -class CSndQueue -{ -friend class CUDT; -friend class CUDTUnited; - -public: - CSndQueue(); - ~CSndQueue(); - -public: - - // Functionality: - // Initialize the sending queue. - // Parameters: - // 1) [in] c: UDP channel to be associated to the queue - // 2) [in] t: Timer - // Returned value: - // None. - - void init(CChannel* c, CTimer* t); - - // Functionality: - // Send out a packet to a given address. - // Parameters: - // 1) [in] addr: destination address - // 2) [in] packet: packet to be sent out - // Returned value: - // Size of data sent out. - - int sendto(const sockaddr* addr, CPacket& packet); - -private: -#ifndef WIN32 - static void* worker(void* param); -#else - static DWORD WINAPI worker(LPVOID param); -#endif - - pthread_t m_WorkerThread; - -private: - CSndUList* m_pSndUList; // List of UDT instances for data sending - CChannel* m_pChannel; // The UDP channel for data sending - CTimer* m_pTimer; // Timing facility - - pthread_mutex_t m_WindowLock; - pthread_cond_t m_WindowCond; - - volatile bool m_bClosing; // closing the worker - pthread_cond_t m_ExitCond; - -private: - CSndQueue(const CSndQueue&); - CSndQueue& operator=(const CSndQueue&); -}; - -class CRcvQueue -{ -friend class CUDT; -friend class CUDTUnited; - -public: - CRcvQueue(); - ~CRcvQueue(); - -public: - - // Functionality: - // Initialize the receiving queue. - // Parameters: - // 1) [in] size: queue size - // 2) [in] mss: maximum packet size - // 3) [in] version: IP version - // 4) [in] hsize: hash table size - // 5) [in] c: UDP channel to be associated to the queue - // 6) [in] t: timer - // Returned value: - // None. - - void init(int size, int payload, int version, int hsize, CChannel* c, CTimer* t); - - // Functionality: - // Read a packet for a specific UDT socket id. - // Parameters: - // 1) [in] id: Socket ID - // 2) [out] packet: received packet - // Returned value: - // Data size of the packet - - int recvfrom(int32_t id, CPacket& packet); - -private: -#ifndef WIN32 - static void* worker(void* param); -#else - static DWORD WINAPI worker(LPVOID param); -#endif - - pthread_t m_WorkerThread; - -private: - CUnitQueue m_UnitQueue; // The received packet queue - - CRcvUList* m_pRcvUList; // List of UDT instances that will read packets from the queue - CHash* m_pHash; // Hash table for UDT socket looking up - CChannel* m_pChannel; // UDP channel for receving packets - CTimer* m_pTimer; // shared timer with the snd queue - - int m_iPayloadSize; // packet payload size - - volatile bool m_bClosing; // closing the workder - pthread_cond_t m_ExitCond; - -private: - int setListener(CUDT* u); - void removeListener(const CUDT* u); - - void registerConnector(const UDTSOCKET& id, CUDT* u, int ipv, const sockaddr* addr, uint64_t ttl); - void removeConnector(const UDTSOCKET& id); - - void setNewEntry(CUDT* u); - bool ifNewEntry(); - CUDT* getNewEntry(); - - void storePkt(int32_t id, CPacket* pkt); - -private: - pthread_mutex_t m_LSLock; - CUDT* m_pListener; // pointer to the (unique, if any) listening UDT entity - CRendezvousQueue* m_pRendezvousQueue; // The list of sockets in rendezvous mode - - std::vector m_vNewEntry; // newly added entries, to be inserted - pthread_mutex_t m_IDLock; - - std::map > m_mBuffer; // temporary buffer for rendezvous connection request - pthread_mutex_t m_PassLock; - pthread_cond_t m_PassCond; - -private: - CRcvQueue(const CRcvQueue&); - CRcvQueue& operator=(const CRcvQueue&); -}; - -struct CMultiplexer -{ - CSndQueue* m_pSndQueue; // The sending queue - CRcvQueue* m_pRcvQueue; // The receiving queue - CChannel* m_pChannel; // The UDP channel for sending and receiving - CTimer* m_pTimer; // The timer - - int m_iPort; // The UDP port number of this multiplexer - int m_iIPversion; // IP version - int m_iMSS; // Maximum Segment Size - int m_iRefCount; // number of UDT instances that are associated with this multiplexer - bool m_bReusable; // if this one can be shared with others - - int m_iID; // multiplexer ID -}; - -#endif diff --git a/vendor/udt4/src/udt.h b/vendor/udt4/src/udt.h deleted file mode 100644 index 7dc75a3..0000000 --- a/vendor/udt4/src/udt.h +++ /dev/null @@ -1,359 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/18/2011 -*****************************************************************************/ - -#ifndef __UDT_H__ -#define __UDT_H__ - - -#ifndef WIN32 - #include - #include - #include -#else - #ifdef __MINGW__ - #include - #include - #endif - #include -#endif -#include -#include -#include -#include - -#include - - -//////////////////////////////////////////////////////////////////////////////// - -//if compiling on VC6.0 or pre-WindowsXP systems -//use -DLEGACY_WIN32 - -//if compiling with MinGW, it only works on XP or above -//use -D_WIN32_WINNT=0x0501 - - -#ifdef WIN32 - #if !defined(__MINGW__) && defined(UDT_IS_DLL) - // Explicitly define 32-bit and 64-bit numbers - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int32 uint32_t; - #ifndef LEGACY_WIN32 - typedef unsigned __int64 uint64_t; - #else - // VC 6.0 does not support unsigned __int64: may cause potential problems. - typedef __int64 uint64_t; - #endif - - #ifdef UDT_EXPORTS - #define UDT_API __declspec(dllexport) - #else - #define UDT_API __declspec(dllimport) - #endif - #else - #define UDT_API - #endif -#else - #define UDT_API __attribute__ ((visibility("default"))) -#endif - -#define NO_BUSY_WAITING - -#ifdef WIN32 - #ifndef __MINGW__ - typedef SOCKET SYSSOCKET; - #else - typedef int SYSSOCKET; - #endif -#else - typedef int SYSSOCKET; -#endif - -typedef SYSSOCKET UDPSOCKET; -typedef int UDTSOCKET; - -//////////////////////////////////////////////////////////////////////////////// - -typedef std::set ud_set; -#define UD_CLR(u, uset) ((uset)->erase(u)) -#define UD_ISSET(u, uset) ((uset)->find(u) != (uset)->end()) -#define UD_SET(u, uset) ((uset)->insert(u)) -#define UD_ZERO(uset) ((uset)->clear()) - -enum EPOLLOpt -{ - // this values are defined same as linux epoll.h - // so that if system values are used by mistake, they should have the same effect - UDT_EPOLL_IN = 0x1, - UDT_EPOLL_OUT = 0x4, - UDT_EPOLL_ERR = 0x8 -}; - -enum UDTSTATUS {INIT = 1, OPENED, LISTENING, CONNECTING, CONNECTED, BROKEN, CLOSING, CLOSED, NONEXIST}; - -//////////////////////////////////////////////////////////////////////////////// - -enum UDTOpt -{ - UDT_MSS, // the Maximum Transfer Unit - UDT_SNDSYN, // if sending is blocking - UDT_RCVSYN, // if receiving is blocking - UDT_CC, // custom congestion control algorithm - UDT_FC, // Flight flag size (window size) - UDT_SNDBUF, // maximum buffer in sending queue - UDT_RCVBUF, // UDT receiving buffer size - UDT_LINGER, // waiting for unsent data when closing - UDP_SNDBUF, // UDP sending buffer size - UDP_RCVBUF, // UDP receiving buffer size - UDT_MAXMSG, // maximum datagram message size - UDT_MSGTTL, // time-to-live of a datagram message - UDT_RENDEZVOUS, // rendezvous connection mode - UDT_SNDTIMEO, // send() timeout - UDT_RCVTIMEO, // recv() timeout - UDT_REUSEADDR, // reuse an existing port or create a new one - UDT_MAXBW, // maximum bandwidth (bytes per second) that the connection can use - UDT_STATE, // current socket state, see UDTSTATUS, read only - UDT_EVENT, // current avalable events associated with the socket - UDT_SNDDATA, // size of data in the sending buffer - UDT_RCVDATA // size of data available for recv -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct CPerfMon -{ - // global measurements - int64_t msTimeStamp; // time since the UDT entity is started, in milliseconds - int64_t pktSentTotal; // total number of sent data packets, including retransmissions - int64_t pktRecvTotal; // total number of received packets - int pktSndLossTotal; // total number of lost packets (sender side) - int pktRcvLossTotal; // total number of lost packets (receiver side) - int pktRetransTotal; // total number of retransmitted packets - int pktSentACKTotal; // total number of sent ACK packets - int pktRecvACKTotal; // total number of received ACK packets - int pktSentNAKTotal; // total number of sent NAK packets - int pktRecvNAKTotal; // total number of received NAK packets - int64_t usSndDurationTotal; // total time duration when UDT is sending data (idle time exclusive) - - // local measurements - int64_t pktSent; // number of sent data packets, including retransmissions - int64_t pktRecv; // number of received packets - int pktSndLoss; // number of lost packets (sender side) - int pktRcvLoss; // number of lost packets (receiver side) - int pktRetrans; // number of retransmitted packets - int pktSentACK; // number of sent ACK packets - int pktRecvACK; // number of received ACK packets - int pktSentNAK; // number of sent NAK packets - int pktRecvNAK; // number of received NAK packets - double mbpsSendRate; // sending rate in Mb/s - double mbpsRecvRate; // receiving rate in Mb/s - int64_t usSndDuration; // busy sending time (i.e., idle time exclusive) - - // instant measurements - double usPktSndPeriod; // packet sending period, in microseconds - int pktFlowWindow; // flow window size, in number of packets - int pktCongestionWindow; // congestion window size, in number of packets - int pktFlightSize; // number of packets on flight - double msRTT; // RTT, in milliseconds - double mbpsBandwidth; // estimated bandwidth, in Mb/s - int byteAvailSndBuf; // available UDT sender buffer size - int byteAvailRcvBuf; // available UDT receiver buffer size -}; - -//////////////////////////////////////////////////////////////////////////////// - -class UDT_API CUDTException -{ -public: - CUDTException(int major = 0, int minor = 0, int err = -1); - CUDTException(const CUDTException& e); - virtual ~CUDTException(); - - // Functionality: - // Get the description of the exception. - // Parameters: - // None. - // Returned value: - // Text message for the exception description. - - virtual const char* getErrorMessage(); - - // Functionality: - // Get the system errno for the exception. - // Parameters: - // None. - // Returned value: - // errno. - - virtual int getErrorCode() const; - - // Functionality: - // Clear the error code. - // Parameters: - // None. - // Returned value: - // None. - - virtual void clear(); - -private: - int m_iMajor; // major exception categories - -// 0: correct condition -// 1: network setup exception -// 2: network connection broken -// 3: memory exception -// 4: file exception -// 5: method not supported -// 6+: undefined error - - int m_iMinor; // for specific error reasons - int m_iErrno; // errno returned by the system if there is any - std::string m_strMsg; // text error message - - std::string m_strAPI; // the name of UDT function that returns the error - std::string m_strDebug; // debug information, set to the original place that causes the error - -public: // Error Code - static const int SUCCESS; - static const int ECONNSETUP; - static const int ENOSERVER; - static const int ECONNREJ; - static const int ESOCKFAIL; - static const int ESECFAIL; - static const int ECONNFAIL; - static const int ECONNLOST; - static const int ENOCONN; - static const int ERESOURCE; - static const int ETHREAD; - static const int ENOBUF; - static const int EFILE; - static const int EINVRDOFF; - static const int ERDPERM; - static const int EINVWROFF; - static const int EWRPERM; - static const int EINVOP; - static const int EBOUNDSOCK; - static const int ECONNSOCK; - static const int EINVPARAM; - static const int EINVSOCK; - static const int EUNBOUNDSOCK; - static const int ENOLISTEN; - static const int ERDVNOSERV; - static const int ERDVUNBOUND; - static const int ESTREAMILL; - static const int EDGRAMILL; - static const int EDUPLISTEN; - static const int ELARGEMSG; - static const int EINVPOLLID; - static const int EASYNCFAIL; - static const int EASYNCSND; - static const int EASYNCRCV; - static const int ETIMEOUT; - static const int EPEERERR; - static const int EUNKNOWN; -}; - -//////////////////////////////////////////////////////////////////////////////// - -// If you need to export these APIs to be used by a different language, -// declare extern "C" for them, and add a "udt_" prefix to each API. -// The following APIs: sendfile(), recvfile(), epoll_wait(), geterrormsg(), -// include C++ specific feature, please use the corresponding sendfile2(), etc. - -namespace UDT -{ - -typedef CUDTException ERRORINFO; -typedef UDTOpt SOCKOPT; -typedef CPerfMon TRACEINFO; -typedef ud_set UDSET; - -UDT_API extern const UDTSOCKET INVALID_SOCK; -#undef ERROR -UDT_API extern const int ERROR; - -UDT_API int startup(); -UDT_API int cleanup(); -UDT_API UDTSOCKET socket(int af, int type, int protocol); -UDT_API int bind(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int bind2(UDTSOCKET u, UDPSOCKET udpsock); -UDT_API int listen(UDTSOCKET u, int backlog); -UDT_API UDTSOCKET accept(UDTSOCKET u, struct sockaddr* addr, int* addrlen); -UDT_API int connect(UDTSOCKET u, const struct sockaddr* name, int namelen); -UDT_API int close(UDTSOCKET u); -UDT_API int getpeername(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockname(UDTSOCKET u, struct sockaddr* name, int* namelen); -UDT_API int getsockopt(UDTSOCKET u, int level, SOCKOPT optname, void* optval, int* optlen); -UDT_API int setsockopt(UDTSOCKET u, int level, SOCKOPT optname, const void* optval, int optlen); -UDT_API int send(UDTSOCKET u, const char* buf, int len, int flags); -UDT_API int recv(UDTSOCKET u, char* buf, int len, int flags); -UDT_API int sendmsg(UDTSOCKET u, const char* buf, int len, int ttl = -1, bool inorder = false); -UDT_API int recvmsg(UDTSOCKET u, char* buf, int len); -UDT_API int64_t sendfile(UDTSOCKET u, std::fstream& ifs, int64_t& offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile(UDTSOCKET u, std::fstream& ofs, int64_t& offset, int64_t size, int block = 7280000); -UDT_API int64_t sendfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 364000); -UDT_API int64_t recvfile2(UDTSOCKET u, const char* path, int64_t* offset, int64_t size, int block = 7280000); - -// select and selectEX are DEPRECATED; please use epoll. -UDT_API int select(int nfds, UDSET* readfds, UDSET* writefds, UDSET* exceptfds, const struct timeval* timeout); -UDT_API int selectEx(const std::vector& fds, std::vector* readfds, - std::vector* writefds, std::vector* exceptfds, int64_t msTimeOut); - -UDT_API int epoll_create(); -UDT_API int epoll_add_usock(int eid, UDTSOCKET u, const int* events = NULL); -UDT_API int epoll_add_ssock(int eid, SYSSOCKET s, const int* events = NULL); -UDT_API int epoll_remove_usock(int eid, UDTSOCKET u); -UDT_API int epoll_remove_ssock(int eid, SYSSOCKET s); -UDT_API int epoll_wait(int eid, std::set* readfds, std::set* writefds, int64_t msTimeOut, - std::set* lrfds = NULL, std::set* wrfds = NULL); -UDT_API int epoll_wait2(int eid, UDTSOCKET* readfds, int* rnum, UDTSOCKET* writefds, int* wnum, int64_t msTimeOut, - SYSSOCKET* lrfds = NULL, int* lrnum = NULL, SYSSOCKET* lwfds = NULL, int* lwnum = NULL); -UDT_API int epoll_release(int eid); -UDT_API ERRORINFO& getlasterror(); -UDT_API int getlasterror_code(); -UDT_API const char* getlasterror_desc(); -UDT_API int perfmon(UDTSOCKET u, TRACEINFO* perf, bool clear = true); -UDT_API UDTSTATUS getsockstate(UDTSOCKET u); - -} // namespace UDT - -#endif diff --git a/vendor/udt4/src/window.cpp b/vendor/udt4/src/window.cpp deleted file mode 100644 index bca37e9..0000000 --- a/vendor/udt4/src/window.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/22/2011 -*****************************************************************************/ - -#include -#include "common.h" -#include "window.h" -#include - -using namespace std; - -CACKWindow::CACKWindow(int size): -m_piACKSeqNo(NULL), -m_piACK(NULL), -m_pTimeStamp(NULL), -m_iSize(size), -m_iHead(0), -m_iTail(0) -{ - m_piACKSeqNo = new int32_t[m_iSize]; - m_piACK = new int32_t[m_iSize]; - m_pTimeStamp = new uint64_t[m_iSize]; - - m_piACKSeqNo[0] = -1; -} - -CACKWindow::~CACKWindow() -{ - delete [] m_piACKSeqNo; - delete [] m_piACK; - delete [] m_pTimeStamp; -} - -void CACKWindow::store(int32_t seq, int32_t ack) -{ - m_piACKSeqNo[m_iHead] = seq; - m_piACK[m_iHead] = ack; - m_pTimeStamp[m_iHead] = CTimer::getTime(); - - m_iHead = (m_iHead + 1) % m_iSize; - - // overwrite the oldest ACK since it is not likely to be acknowledged - if (m_iHead == m_iTail) - m_iTail = (m_iTail + 1) % m_iSize; -} - -int CACKWindow::acknowledge(int32_t seq, int32_t& ack) -{ - if (m_iHead >= m_iTail) - { - // Head has not exceeded the physical boundary of the window - - for (int i = m_iTail, n = m_iHead; i < n; ++ i) - { - // looking for indentical ACK Seq. No. - if (seq == m_piACKSeqNo[i]) - { - // return the Data ACK it carried - ack = m_piACK[i]; - - // calculate RTT - int rtt = int(CTimer::getTime() - m_pTimeStamp[i]); - - if (i + 1 == m_iHead) - { - m_iTail = m_iHead = 0; - m_piACKSeqNo[0] = -1; - } - else - m_iTail = (i + 1) % m_iSize; - - return rtt; - } - } - - // Bad input, the ACK node has been overwritten - return -1; - } - - // Head has exceeded the physical window boundary, so it is behind tail - for (int j = m_iTail, n = m_iHead + m_iSize; j < n; ++ j) - { - // looking for indentical ACK seq. no. - if (seq == m_piACKSeqNo[j % m_iSize]) - { - // return Data ACK - j %= m_iSize; - ack = m_piACK[j]; - - // calculate RTT - int rtt = int(CTimer::getTime() - m_pTimeStamp[j]); - - if (j == m_iHead) - { - m_iTail = m_iHead = 0; - m_piACKSeqNo[0] = -1; - } - else - m_iTail = (j + 1) % m_iSize; - - return rtt; - } - } - - // bad input, the ACK node has been overwritten - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// - -CPktTimeWindow::CPktTimeWindow(int asize, int psize): -m_iAWSize(asize), -m_piPktWindow(NULL), -m_iPktWindowPtr(0), -m_iPWSize(psize), -m_piProbeWindow(NULL), -m_iProbeWindowPtr(0), -m_iLastSentTime(0), -m_iMinPktSndInt(1000000), -m_LastArrTime(), -m_CurrArrTime(), -m_ProbeTime() -{ - m_piPktWindow = new int[m_iAWSize]; - m_piPktReplica = new int[m_iAWSize]; - m_piProbeWindow = new int[m_iPWSize]; - m_piProbeReplica = new int[m_iPWSize]; - - m_LastArrTime = CTimer::getTime(); - - for (int i = 0; i < m_iAWSize; ++ i) - m_piPktWindow[i] = 1000000; - - for (int k = 0; k < m_iPWSize; ++ k) - m_piProbeWindow[k] = 1000; -} - -CPktTimeWindow::~CPktTimeWindow() -{ - delete [] m_piPktWindow; - delete [] m_piPktReplica; - delete [] m_piProbeWindow; - delete [] m_piProbeReplica; -} - -int CPktTimeWindow::getMinPktSndInt() const -{ - return m_iMinPktSndInt; -} - -int CPktTimeWindow::getPktRcvSpeed() const -{ - // get median value, but cannot change the original value order in the window - std::copy(m_piPktWindow, m_piPktWindow + m_iAWSize - 1, m_piPktReplica); - std::nth_element(m_piPktReplica, m_piPktReplica + (m_iAWSize / 2), m_piPktReplica + m_iAWSize - 1); - int median = m_piPktReplica[m_iAWSize / 2]; - - int count = 0; - int sum = 0; - int upper = median << 3; - int lower = median >> 3; - - // median filtering - int* p = m_piPktWindow; - for (int i = 0, n = m_iAWSize; i < n; ++ i) - { - if ((*p < upper) && (*p > lower)) - { - ++ count; - sum += *p; - } - ++ p; - } - - // claculate speed, or return 0 if not enough valid value - if (count > (m_iAWSize >> 1)) - return (int)ceil(1000000.0 / (sum / count)); - else - return 0; -} - -int CPktTimeWindow::getBandwidth() const -{ - // get median value, but cannot change the original value order in the window - std::copy(m_piProbeWindow, m_piProbeWindow + m_iPWSize - 1, m_piProbeReplica); - std::nth_element(m_piProbeReplica, m_piProbeReplica + (m_iPWSize / 2), m_piProbeReplica + m_iPWSize - 1); - int median = m_piProbeReplica[m_iPWSize / 2]; - - int count = 1; - int sum = median; - int upper = median << 3; - int lower = median >> 3; - - // median filtering - int* p = m_piProbeWindow; - for (int i = 0, n = m_iPWSize; i < n; ++ i) - { - if ((*p < upper) && (*p > lower)) - { - ++ count; - sum += *p; - } - ++ p; - } - - return (int)ceil(1000000.0 / (double(sum) / double(count))); -} - -void CPktTimeWindow::onPktSent(int currtime) -{ - int interval = currtime - m_iLastSentTime; - - if ((interval < m_iMinPktSndInt) && (interval > 0)) - m_iMinPktSndInt = interval; - - m_iLastSentTime = currtime; -} - -void CPktTimeWindow::onPktArrival() -{ - m_CurrArrTime = CTimer::getTime(); - - // record the packet interval between the current and the last one - *(m_piPktWindow + m_iPktWindowPtr) = int(m_CurrArrTime - m_LastArrTime); - - // the window is logically circular - ++ m_iPktWindowPtr; - if (m_iPktWindowPtr == m_iAWSize) - m_iPktWindowPtr = 0; - - // remember last packet arrival time - m_LastArrTime = m_CurrArrTime; -} - -void CPktTimeWindow::probe1Arrival() -{ - m_ProbeTime = CTimer::getTime(); -} - -void CPktTimeWindow::probe2Arrival() -{ - m_CurrArrTime = CTimer::getTime(); - - // record the probing packets interval - *(m_piProbeWindow + m_iProbeWindowPtr) = int(m_CurrArrTime - m_ProbeTime); - // the window is logically circular - ++ m_iProbeWindowPtr; - if (m_iProbeWindowPtr == m_iPWSize) - m_iProbeWindowPtr = 0; -} diff --git a/vendor/udt4/src/window.h b/vendor/udt4/src/window.h deleted file mode 100644 index f118a26..0000000 --- a/vendor/udt4/src/window.h +++ /dev/null @@ -1,187 +0,0 @@ -/***************************************************************************** -Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the - above copyright notice, this list of conditions - and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the University of Illinois - nor the names of its contributors may be used to - endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*****************************************************************************/ - -/***************************************************************************** -written by - Yunhong Gu, last updated 01/22/2011 -*****************************************************************************/ - -#ifndef __UDT_WINDOW_H__ -#define __UDT_WINDOW_H__ - - -#ifndef WIN32 - #include - #include -#endif -#include "udt.h" - - -class CACKWindow -{ -public: - CACKWindow(int size = 1024); - ~CACKWindow(); - - // Functionality: - // Write an ACK record into the window. - // Parameters: - // 0) [in] seq: ACK seq. no. - // 1) [in] ack: DATA ACK no. - // Returned value: - // None. - - void store(int32_t seq, int32_t ack); - - // Functionality: - // Search the ACK-2 "seq" in the window, find out the DATA "ack" and caluclate RTT . - // Parameters: - // 0) [in] seq: ACK-2 seq. no. - // 1) [out] ack: the DATA ACK no. that matches the ACK-2 no. - // Returned value: - // RTT. - - int acknowledge(int32_t seq, int32_t& ack); - -private: - int32_t* m_piACKSeqNo; // Seq. No. for the ACK packet - int32_t* m_piACK; // Data Seq. No. carried by the ACK packet - uint64_t* m_pTimeStamp; // The timestamp when the ACK was sent - - int m_iSize; // Size of the ACK history window - int m_iHead; // Pointer to the lastest ACK record - int m_iTail; // Pointer to the oldest ACK record - -private: - CACKWindow(const CACKWindow&); - CACKWindow& operator=(const CACKWindow&); -}; - -//////////////////////////////////////////////////////////////////////////////// - -class CPktTimeWindow -{ -public: - CPktTimeWindow(int asize = 16, int psize = 16); - ~CPktTimeWindow(); - - // Functionality: - // read the minimum packet sending interval. - // Parameters: - // None. - // Returned value: - // minimum packet sending interval (microseconds). - - int getMinPktSndInt() const; - - // Functionality: - // Calculate the packes arrival speed. - // Parameters: - // None. - // Returned value: - // Packet arrival speed (packets per second). - - int getPktRcvSpeed() const; - - // Functionality: - // Estimate the bandwidth. - // Parameters: - // None. - // Returned value: - // Estimated bandwidth (packets per second). - - int getBandwidth() const; - - // Functionality: - // Record time information of a packet sending. - // Parameters: - // 0) currtime: timestamp of the packet sending. - // Returned value: - // None. - - void onPktSent(int currtime); - - // Functionality: - // Record time information of an arrived packet. - // Parameters: - // None. - // Returned value: - // None. - - void onPktArrival(); - - // Functionality: - // Record the arrival time of the first probing packet. - // Parameters: - // None. - // Returned value: - // None. - - void probe1Arrival(); - - // Functionality: - // Record the arrival time of the second probing packet and the interval between packet pairs. - // Parameters: - // None. - // Returned value: - // None. - - void probe2Arrival(); - -private: - int m_iAWSize; // size of the packet arrival history window - int* m_piPktWindow; // packet information window - int* m_piPktReplica; - int m_iPktWindowPtr; // position pointer of the packet info. window. - - int m_iPWSize; // size of probe history window size - int* m_piProbeWindow; // record inter-packet time for probing packet pairs - int* m_piProbeReplica; - int m_iProbeWindowPtr; // position pointer to the probing window - - int m_iLastSentTime; // last packet sending time - int m_iMinPktSndInt; // Minimum packet sending interval - - uint64_t m_LastArrTime; // last packet arrival time - uint64_t m_CurrArrTime; // current packet arrival time - uint64_t m_ProbeTime; // arrival time of the first probing packet - -private: - CPktTimeWindow(const CPktTimeWindow&); - CPktTimeWindow &operator=(const CPktTimeWindow&); -}; - - -#endif diff --git a/vendor/websocketpp b/vendor/websocketpp deleted file mode 160000 index c5510d6..0000000 --- a/vendor/websocketpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c5510d6de04917812b910a8dd44735c1f17061d9 diff --git a/vendor/websocketpp/.gitattributes b/vendor/websocketpp/.gitattributes new file mode 100644 index 0000000..a9e4fc7 --- /dev/null +++ b/vendor/websocketpp/.gitattributes @@ -0,0 +1,18 @@ +# Lineendings +*.sln eol=crlf +*.vcproj eol=crlf +*.vcxproj* eol=crlf + +# Whitespace rules +# strict (no trailing, no tabs) +*.cpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.hpp whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.c whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol +*.h whitespace=trailing-space,space-before-tab,tab-in-indent,cr-at-eol + +# normal (no trailing) +*.sql whitespace=trailing-space,space-before-tab,cr-at-eol +*.txt whitespace=trailing-space,space-before-tab,cr-at-eol + +# special files which must ignore whitespace +*.patch whitespace=-trailing-space diff --git a/vendor/websocketpp/.gitignore b/vendor/websocketpp/.gitignore new file mode 100644 index 0000000..1d0c715 --- /dev/null +++ b/vendor/websocketpp/.gitignore @@ -0,0 +1,94 @@ +# make .git* files visible to git +!.gitignore +!.gitattributes + +.DS_Store + +#vim stuff +*~ +*.swp + +*.o +*.so +*.so.? +*.so.?.?.? +*.a +*.dylib +lib/* + +# CMake +*.cmake +*.dir +CMakeFiles +INSTALL.* +ZERO_CHECK.* +CMakeCache.txt +install_manifest.txt + +# Windows/Visual Studio +*.vcproj* +*.sln +*.suo +*.ncb +*/Debug/* +*/*/Debug/* +bin/Debug +*/Release/* +*/*/Release/* +*/RelWithDebInfo/* +*/*/RelWithDebInfo/* + +# explicitly allow this path with /debug/ in it +!websocketpp/transport/debug/* + +objs_shared/ +objs_static/ + +examples/chat_server/chat_server +examples/echo_server/echo_server +examples/chat_client/chat_client +examples/echo_client/echo_client +test/basic/tests +libwebsocketpp.dylib.0.1.0 + +websocketpp.xcodeproj/xcuserdata/* +websocketpp.xcodeproj/project.xcworkspace/xcuserdata/* +policy_based_notes.hpp + +examples/echo_server_tls/echo_server_tls + +examples/fuzzing_client/fuzzing_client + +examples/stress_client/stress_client + +examples/broadcast_server_tls/broadcast_server + +test/basic/perf + +examples/echo_server_tls/echo_server_tls + +examples/concurrent_server/concurrent_server + +examples/fuzzing_server_tls/fuzzing_server + +examples/wsperf/wsperf + +.sconsign.dblite + +build/ +doxygen/ +examples/wsperf/wsperf_client + +*.out + +*.log +*.opensdf +*.sdf +*.vcxproj +*.vcxproj.filters +*.user +install +Makefile +bin + +Testing/Temporary/CTestCostData.txt diff --git a/vendor/websocketpp/.travis.yml b/vendor/websocketpp/.travis.yml new file mode 100644 index 0000000..a2aa970 --- /dev/null +++ b/vendor/websocketpp/.travis.yml @@ -0,0 +1,21 @@ +language: cpp +compiler: + - gcc +before_install: + #- sudo apt-get install libboost-chrono1.48-dev libboost-regex1.48-dev libboost-system1.48-dev libboost-thread1.48-dev libboost-test1.48-dev libboost-random1.48-dev -y + - sudo add-apt-repository -y ppa:boost-latest/ppa && sudo apt-get update -q && sudo apt-get install -y libboost-chrono1.55-dev libboost-random1.55-dev libboost-regex1.55-dev libboost-system1.55-dev libboost-thread1.55-dev libboost-test1.55-dev +env: + global: + - BOOST_INCLUDES=/usr/include + - BOOST_LIBS=/usr/lib/x86_64-linux-gnu +script: scons -j 2 && scons test +branches: + only: + - master + - develop +notifications: + recipients: + - travis@zaphoyd.com + email: + on_success: change + on_failure: always diff --git a/vendor/websocketpp/CMakeLists.txt b/vendor/websocketpp/CMakeLists.txt new file mode 100644 index 0000000..f60caa1 --- /dev/null +++ b/vendor/websocketpp/CMakeLists.txt @@ -0,0 +1,261 @@ + +############ Setup project and cmake + +# Project name +project (websocketpp) + +# Minimum cmake requirement. We should require a quite recent +# cmake for the dependency find macros etc. to be up to date. +cmake_minimum_required (VERSION 2.6) + +set (WEBSOCKETPP_MAJOR_VERSION 0) +set (WEBSOCKETPP_MINOR_VERSION 7) +set (WEBSOCKETPP_PATCH_VERSION 0) +set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION}) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") +if (WIN32 AND NOT CYGWIN) + set (DEF_INSTALL_CMAKE_DIR cmake) +else () + set (DEF_INSTALL_CMAKE_DIR lib/cmake/websocketpp) +endif () +set (INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files") + +# Make relative paths absolute (needed later on) +foreach (p INCLUDE CMAKE) + set (var INSTALL_${p}_DIR) + if (NOT IS_ABSOLUTE "${${var}}") + set (${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") + endif () +endforeach () + +# Set CMake library search policy +if (COMMAND cmake_policy) + cmake_policy (SET CMP0003 NEW) + cmake_policy (SET CMP0005 NEW) +endif () + +# Disable unnecessary build types +set (CMAKE_CONFIGURATION_TYPES "Release;RelWithDebInfo;Debug" CACHE STRING "Configurations" FORCE) + +# Include our cmake macros +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +include (CMakeHelpers) + +############ Paths + +set (WEBSOCKETPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) +set (WEBSOCKETPP_INCLUDE ${WEBSOCKETPP_ROOT}/websocketpp) +set (WEBSOCKETPP_BUILD_ROOT ${CMAKE_CURRENT_BINARY_DIR}) +set (WEBSOCKETPP_BIN ${WEBSOCKETPP_BUILD_ROOT}/bin) +set (WEBSOCKETPP_LIB ${WEBSOCKETPP_BUILD_ROOT}/lib) + +# CMake install step prefix. I assume linux users want the prefix to +# be the default /usr or /usr/local so this is only adjusted on Windows. +# - Windows: Build the INSTALL project in your solution file. +# - Linux/OSX: make install. +if (MSVC) + set (CMAKE_INSTALL_PREFIX "${WEBSOCKETPP_ROOT}/install") +endif () + +############ Build customization + +# Override from command line "CMake -D