├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── COPYING ├── Doxyfile ├── Makefile.am ├── README ├── autoexp.dat ├── buildtools ├── build-cmake.sh ├── build-xcode.sh ├── build.bat ├── build.sh ├── build32Or64.bat ├── cleanlibs.bat ├── coverage.bat ├── coverage.sh ├── getlibs.bat ├── installprep.vcxproj ├── unit-test-xcode.sh ├── unit-test.bat └── unit-test.sh ├── cmake ├── configureThirdParty.cmake └── utils.cmake ├── cmakeconfig.h.in ├── config.rpath ├── configure.ac ├── linux.supp ├── lucid.suppressions ├── m4 ├── .gitignore ├── ax_boost_base.m4 ├── ax_boost_program_options.m4 ├── ax_boost_regex.m4 ├── ax_boost_system.m4 ├── ax_boost_thread.m4 ├── ax_check_compile_flag.m4 ├── ax_check_lzma.m4 ├── ax_check_openssl.m4 ├── ax_check_zlib.m4 ├── ax_lib_postgresql.m4 ├── check_valgrind.m4 ├── iconv.m4 ├── lib-ld.m4 ├── lib-link.m4 ├── lib-prefix.m4 ├── osx.m4 └── ragel.m4 ├── mordor.sln ├── mordor.xcodeproj └── project.pbxproj ├── mordor ├── .gitignore ├── CMakeLists.txt ├── anymap.h ├── assert.cpp ├── assert.h ├── atomic.h ├── config.cpp ├── config.h ├── coroutine.h ├── cxa_exception.cpp ├── cxa_exception.h ├── daemon.cpp ├── daemon.h ├── date_time.cpp ├── date_time.h ├── endian.h ├── eventloop.cpp ├── eventloop.h ├── examples │ ├── .gitignore │ ├── CMakeLists.txt │ ├── cat.cpp │ ├── cat.vcxproj │ ├── cat.vcxproj.filters │ ├── decodebacktrace.cpp │ ├── decodebacktrace.vcxproj │ ├── decodebacktrace.vcxproj.filters │ ├── echoserver.cpp │ ├── echoserver.vcxproj │ ├── echoserver.vcxproj.filters │ ├── iombench.cpp │ ├── iombench.vcxproj │ ├── iombench.vcxproj.filters │ ├── netbench.cpp │ ├── netbench.h │ ├── simpleappserver.cpp │ ├── simpleclient.cpp │ ├── simpleclient.vcxproj │ ├── simpleclient.vcxproj.filters │ ├── tunnel.cpp │ ├── tunnel.vcxproj │ ├── tunnel.vcxproj.filters │ ├── udpstats.cpp │ ├── wget.cpp │ ├── wget.vcxproj │ ├── wget.vcxproj.filters │ └── zipstreaming.cpp ├── exception.cpp ├── exception.h ├── factory.h ├── fiber.cpp ├── fiber.h ├── fibersynchronization.cpp ├── fibersynchronization.h ├── future.h ├── http │ ├── .gitignore │ ├── auth.cpp │ ├── auth.h │ ├── basic.cpp │ ├── basic.h │ ├── broker.cpp │ ├── broker.h │ ├── chunked.cpp │ ├── chunked.h │ ├── client.cpp │ ├── client.h │ ├── connection.cpp │ ├── connection.h │ ├── digest.cpp │ ├── digest.h │ ├── http.cpp │ ├── http.h │ ├── http_parser.rl │ ├── multipart.cpp │ ├── multipart.h │ ├── negotiate.cpp │ ├── negotiate.h │ ├── oauth.cpp │ ├── oauth.h │ ├── oauth2.cpp │ ├── oauth2.h │ ├── parser.h │ ├── proxy.cpp │ ├── proxy.h │ ├── server.cpp │ ├── server.h │ ├── servlet.cpp │ ├── servlet.h │ └── servlets │ │ ├── config.cpp │ │ └── config.h ├── iomanager.h ├── iomanager_epoll.cpp ├── iomanager_epoll.h ├── iomanager_iocp.cpp ├── iomanager_iocp.h ├── iomanager_kqueue.cpp ├── iomanager_kqueue.h ├── json.h ├── json.rl ├── libmordor.pc.in ├── libmordorprotobuf.pc.in ├── libmordoryaml.pc.in ├── log.cpp ├── log.h ├── log_base.h ├── main.cpp ├── main.h ├── mordor.v12.vcxproj ├── mordor.v12.vcxproj.filters ├── mordor.vcxproj.filters ├── mordorprotobuf.v12.vcxproj ├── mordorprotobuf.v12.vcxproj.filters ├── mordorprotobuf.vcxproj.filters ├── mordoryaml.vcxproj ├── mordoryaml.vcxproj.filters ├── openssl_lock.cpp ├── openssl_lock.h ├── parallel.cpp ├── parallel.h ├── pch.cpp ├── pch.h ├── pq │ ├── connection.cpp │ ├── connection.h │ ├── connectionpool.cpp │ ├── connectionpool.h │ ├── copy.cpp │ ├── exception.cpp │ ├── exception.h │ ├── libmordorpq.pc.in │ ├── mordorpq.vcxproj │ ├── mordorpq.vcxproj.filters │ ├── preparedstatement.cpp │ ├── preparedstatement.h │ ├── result.cpp │ ├── result.h │ ├── tests │ │ ├── .gitignore │ │ ├── pq.cpp │ │ ├── pqtests.vcxproj │ │ └── pqtests.vcxproj.filters │ ├── transaction.cpp │ └── transaction.h ├── predef.h ├── protobuf.cpp ├── protobuf.h ├── protoc.props ├── protoc.targets ├── protoc.xml ├── ragel.cpp ├── ragel.h ├── ragel.props ├── ragel.rules ├── ragel.targets ├── ragel.xml ├── runtime_linking.cpp ├── runtime_linking.h ├── scheduler.cpp ├── scheduler.h ├── semaphore.cpp ├── semaphore.h ├── sleep.cpp ├── sleep.h ├── socket.cpp ├── socket.h ├── socks.cpp ├── socks.h ├── statistics.cpp ├── statistics.h ├── streams │ ├── buffer.cpp │ ├── buffer.h │ ├── buffered.cpp │ ├── buffered.h │ ├── cat.cpp │ ├── cat.h │ ├── counter.cpp │ ├── counter.h │ ├── crypto.cpp │ ├── crypto.h │ ├── deflate.h │ ├── delay.h │ ├── duplex.h │ ├── efs.cpp │ ├── efs.h │ ├── fd.cpp │ ├── fd.h │ ├── file.cpp │ ├── file.h │ ├── filter.cpp │ ├── filter.h │ ├── gzip.h │ ├── handle.cpp │ ├── handle.h │ ├── hash.cpp │ ├── hash.h │ ├── hashfwd.h │ ├── http.cpp │ ├── http.h │ ├── limited.cpp │ ├── limited.h │ ├── lzma2.cpp │ ├── lzma2.h │ ├── memory.cpp │ ├── memory.h │ ├── namedpipe.cpp │ ├── namedpipe.h │ ├── notify.h │ ├── null.cpp │ ├── null.h │ ├── pipe.cpp │ ├── pipe.h │ ├── progress.h │ ├── random.cpp │ ├── random.h │ ├── scheduler.h │ ├── singleplex.cpp │ ├── singleplex.h │ ├── socket.cpp │ ├── socket.h │ ├── ssl.cpp │ ├── ssl.h │ ├── std.cpp │ ├── std.h │ ├── stdcrypto.cpp │ ├── stdcrypto.h │ ├── stream.cpp │ ├── stream.h │ ├── temp.cpp │ ├── temp.h │ ├── test.cpp │ ├── test.h │ ├── throttle.cpp │ ├── throttle.h │ ├── timeout.cpp │ ├── timeout.h │ ├── transfer.cpp │ ├── transfer.h │ ├── zero.cpp │ ├── zero.h │ ├── zlib.cpp │ └── zlib.h ├── string.cpp ├── string.h ├── tar.cpp ├── tar.h ├── test │ ├── .gitignore │ ├── CMakeLists.txt │ ├── antxmllistener.cpp │ ├── antxmllistener.h │ ├── compoundlistener.cpp │ ├── compoundlistener.h │ ├── libmordortest.pc.in │ ├── mordortest.v12.vcxproj │ ├── mordortest.v12.vcxproj.filters │ ├── mordortest.vcxproj │ ├── mordortest.vcxproj.filters │ ├── stdoutlistener.cpp │ ├── stdoutlistener.h │ ├── test.cpp │ └── test.h ├── tests │ ├── .gitignore │ ├── CMakeLists.txt │ ├── atomic.cpp │ ├── buffer.cpp │ ├── buffered_stream.cpp │ ├── cat_stream.cpp │ ├── chunked_stream.cpp │ ├── config.cpp │ ├── coroutine.cpp │ ├── counter_stream.cpp │ ├── crypto.cpp │ ├── efs_stream.cpp │ ├── endian.cpp │ ├── fibers.cpp │ ├── fibersync.cpp │ ├── file_stream.cpp │ ├── fls.cpp │ ├── future.cpp │ ├── hash_stream.cpp │ ├── hmac.cpp │ ├── http_client.cpp │ ├── http_parser.cpp │ ├── http_proxy.cpp │ ├── http_server.cpp │ ├── http_servlet_dispatcher.cpp │ ├── http_stream.cpp │ ├── iomanager.cpp │ ├── iomanager_iocp.cpp │ ├── json.cpp │ ├── log.cpp │ ├── memory_stream.cpp │ ├── notify_stream.cpp │ ├── oauth.cpp │ ├── pch.cpp │ ├── pch.h │ ├── pipe_stream.cpp │ ├── ragel.cpp │ ├── run_tests.cpp │ ├── scheduler.cpp │ ├── socket.cpp │ ├── ssl_stream.cpp │ ├── statistics.cpp │ ├── stdcrypto.cpp │ ├── stream.cpp │ ├── string.cpp │ ├── tar.cpp │ ├── temp_stream.cpp │ ├── tests.vcxproj │ ├── tests.vcxproj.filters │ ├── thread.cpp │ ├── timeout_stream.cpp │ ├── timer.cpp │ ├── transfer_stream.cpp │ ├── unicode.cpp │ ├── uri.cpp │ ├── util.cpp │ ├── xml.cpp │ ├── zip.cpp │ └── zlib.cpp ├── thirdPartyPaths-win32-v12.Debug.props ├── thirdPartyPaths-win32-v12.Release.props ├── thirdPartyPaths-win64-v12.Debug.props ├── thirdPartyPaths-win64-v12.Release.props ├── thirdPartyPaths-win64.props ├── thread.cpp ├── thread.h ├── thread_local_storage.h ├── timer.cpp ├── timer.h ├── uri.h ├── uri.rl ├── util.cpp ├── util.h ├── version.h ├── workerpool.cpp ├── workerpool.h ├── xml │ ├── .gitignore │ ├── dom_parser.cpp │ ├── dom_parser.h │ ├── parser.h │ └── xml_parser.rl ├── yaml.cpp ├── yaml.h ├── zip.cpp └── zip.h ├── mordor_cmake.vcxproj └── osx.supp /.gitattributes: -------------------------------------------------------------------------------- 1 | #Enforce line ending conventions based on file extension 2 | 3 | # Enforce the line endings for linux/osx 4 | # files just in case they are edited 5 | # with a bad editor on windows 6 | Makefile.am text eol=lf 7 | *.in text eol=lf 8 | *.sh text eol=lf 9 | 10 | #For consistency in cmake 11 | CMakeLists.txt eol=lf 12 | *.cmake eol=lf 13 | 14 | #Windows specific files 15 | *.bat text eol=crlf 16 | *.cmd text eol=crlf 17 | *.vcxproj text eol=crlf 18 | *.vcxproj.filters text eol=crlf 19 | 20 | ##For source code we use linux endings 21 | ##even on Windows 22 | *.h text eol=lf 23 | *.cpp text eol=lf 24 | *.c text eol=lf 25 | *.hpp text eol=lf 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gcno 2 | *.gcda 3 | *.gcov 4 | *.gch 5 | *.la 6 | *.lo 7 | *.ncb 8 | *.o 9 | *.opensdf 10 | *.sdf 11 | *.suo 12 | *.user 13 | *.swp 14 | .deps 15 | .dirstamp 16 | .libs 17 | a.out.dSYM 18 | aclocal.m4 19 | autom4te.cache 20 | build 21 | compile 22 | config.guess* 23 | autoconfig.h 24 | autoconfig.h.in 25 | autoconfig.h.in~ 26 | config.h 27 | config.h.in 28 | config.h.in~ 29 | config.log 30 | config.status 31 | config.sub* 32 | configure 33 | depcomp 34 | html 35 | install-sh 36 | iphone 37 | lcov* 38 | libtool 39 | ltmain.sh 40 | Makefile 41 | Makefile.in 42 | missing 43 | mordor.xcodeproj/*.mode1v3 44 | mordor.xcodeproj/*.pbxuser 45 | mordor.xcodeproj/*.perspectivev3 46 | mordor.xcodeproj/project.xcworkspace/ 47 | 48 | obj* 49 | stamp-h1 50 | Win32 51 | x64 52 | Debug 53 | Release 54 | *.pc 55 | xcuserdata 56 | .DS_Store 57 | tags 58 | test-results/ 59 | /ipch/ 60 | /packages/ 61 | /.vs/ 62 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Main entry for the mordor cmake projects 2 | #cmake would be invoked with the specific generator to create Windows/OSX/Linux output 3 | #and generation also decides 32 versus 64 bit for windows case 4 | 5 | #Minimum could probably be earlier, e.g. try with default cmake on our oldest linux distro 6 | cmake_minimum_required(VERSION 3.0 FATAL_ERROR) 7 | 8 | # 9 | # Define options to customize the build 10 | # Caller can override default at generation by using "-D" argument or using cmake-gui. 11 | # The values are cached, so to change after first generation a clean cache is required. 12 | # 13 | 14 | #The examples are optional - this can be disabled when using cmake-gui or passing argument 15 | #on the command lines 16 | option(BUILD_EXAMPLES "Build mordor example programs" ON) 17 | option(BUILD_MORDOR_TESTS "Build mordor tests" ON) 18 | 19 | option(BUILD_COVERAGE "Build for code coverage" OFF) 20 | 21 | # 22 | # Mac SDK 23 | # This must be set as cache variable before project set. It is ignored by other platforms 24 | # 25 | 26 | set(CMAKE_OSX_DEPLOYMENT_TARGET "10.7" CACHE STRING "Minimum OS X deployment version") 27 | 28 | #This determines name of the solution file etc. 29 | #Warning until it is specified many variables are not available, such as MSVC 30 | project(mordor) 31 | 32 | 33 | include(cmake/utils.cmake) 34 | include(cmake/configureThirdParty.cmake) 35 | 36 | setStandardDefines() 37 | 38 | setStandardConfigs() 39 | 40 | # 41 | # Configuration of the output location 42 | # 43 | 44 | 45 | getThirdPartyRoot() 46 | message(STATUS "Thirdparty THIRDPARTY_LIB_ROOT = ${THIRDPARTY_LIB_ROOT}") 47 | 48 | configureOutput() 49 | message(STATUS "Output CMAKE_BINARY_DIR = ${CMAKE_BINARY_DIR}") 50 | 51 | # 52 | # Global 3rd party configuration 53 | # These functions append to the global include directory list 54 | # and generate variables for use a link time 55 | # 56 | 57 | 58 | configure_openssl("1.0.1e") 59 | 60 | #List all boost libraries that are needed (except for the header-only ones which require no linking) 61 | #This will result in a populated Boost_LIBRARIES variable 62 | set(boost_libs filesystem regex program_options date_time thread) 63 | configure_boost("1.61.0" boost_libs) 64 | 65 | config_lzma() 66 | config_zlib() 67 | config_ragel() 68 | 69 | #configure header file autoconfig.h on Linux 70 | configure_headers(${CMAKE_CURRENT_SOURCE_DIR}) 71 | 72 | #Note: not calling config_protobuf() here because that is only needed by one library 73 | 74 | setStandardCompilerSettings() 75 | 76 | #recursive into the source directory 77 | add_subdirectory(mordor) 78 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Decho Corporation 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of Decho Corporation nor the names of its contributors 12 | may be used to endorse or promote products derived from this software 13 | without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /buildtools/build-xcode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TARGETS="mordor mordorprotobuf mordortest run_tests" 4 | ARCH=${arch:-"x86_64"} 5 | CONFIG=Debug 6 | 7 | if [[ "$1" == release ]] ; then 8 | CONFIG=Release 9 | fi 10 | 11 | if [[ $ARCH == "amd64" ]] ; then 12 | ARCH=x86_64 13 | fi 14 | 15 | for t in $TARGETS 16 | do 17 | echo "build xcodebuild -target $t -configuration $CONFIG -arch $ARCH ..." 18 | xcodebuild -target $t -configuration $CONFIG -arch $ARCH 19 | done 20 | -------------------------------------------------------------------------------- /buildtools/build.bat: -------------------------------------------------------------------------------- 1 | @IF DEFINED _ECHO ECHO ON 2 | @SETLOCAL 3 | 4 | @SET CONFIG=Release 5 | @SET BUILD32=1 6 | 7 | REM For the moment forcing cmake by default 8 | @SET CMAKEARG= 9 | 10 | REM Most arguments are processed in build32Or64.bat 11 | FOR %%A IN (%*) DO ( 12 | @IF /i "%%A" EQU "debug" SET CONFIG=Debug 13 | @IF /i "%%A" EQU "coverage" SET CONFIG=Debug 14 | @IF /i "%%A" EQU "release" SET CONFIG=Release 15 | 16 | @IF /i "%%A" EQU "no32" SET BUILD32=0 17 | 18 | @IF /i "%%A" EQU "cmake" SET CMAKEARG=cmake 19 | @IF /i "%%A" EQU "nocmake" SET CMAKEARG= 20 | ) 21 | 22 | @IF "%BUILD32%" EQU "0" ( 23 | ECHO Skipping 32-bit build 24 | GOTO :build64 25 | ) 26 | 27 | CALL buildtools\build32Or64.bat %CONFIG% Win32 %CMAKEARG% 28 | IF ERRORLEVEL 1 EXIT /B 29 | 30 | :build64 31 | 32 | CALL buildtools\build32Or64.bat %CONFIG% x64 %CMAKEARG% 33 | IF ERRORLEVEL 1 EXIT /B 34 | 35 | :done64build 36 | 37 | ECHO Copying 64-bit unit tests to package directory 38 | 39 | @IF NOT EXIST packages ( 40 | MKDIR packages 41 | ) 42 | 43 | COPY /Y x64\%CONFIG%\tests.exe packages\tests.exe 44 | 45 | REM Copy openssl, zlib dlls needed by tests 46 | COPY /Y x64\%CONFIG%\*.dll packages 47 | -------------------------------------------------------------------------------- /buildtools/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Trigger builds on linux or mac 4 | #By default autoconf and xcode projects are used. 5 | 6 | set -e -u 7 | 8 | CONFIG=release 9 | USE_CMAKE=0 10 | 11 | while [[ $# -gt 0 ]] ; do 12 | key="$1" 13 | case "$1" in 14 | release|debug|coverage|valgrind) 15 | CONFIG=$1 16 | ;; 17 | cmake) 18 | USE_CMAKE=1 19 | ;; 20 | --) 21 | #Arguments after -- are forwarded to configure 22 | shift 23 | break 24 | ;; 25 | *) 26 | echo "Unknown option $1" 27 | ;; 28 | esac 29 | shift 30 | done 31 | 32 | if [ "${USE_CMAKE}" = "1" ] ; then 33 | . buildtools/build-cmake.sh $CONFIG 34 | elif [ `uname` = 'Darwin' ] ; then 35 | #To be phased out when building osx exclusively with cmake 36 | . buildtools/build-xcode.sh $CONFIG 37 | else 38 | #Linux autotools base build 39 | if [ ! -x configure ]; then 40 | autoreconf -i 41 | fi 42 | 43 | CXXFLAGS= 44 | VALGRINDFLAGS= 45 | ASSERTFLAGS= 46 | POSTGRESFLAGS= 47 | 48 | if [ ! -f Makefile ]; then 49 | if [ "${CONFIG}" = "debug" ]; then 50 | CXXFLAGS+=' -g -O0' 51 | elif [ "${CONFIG}" = "coverage" ]; then 52 | CXXFLAGS+=' -g -O0 -fprofile-arcs -ftest-coverage' 53 | elif [ "${CONFIG}" = "valgrind" ]; then 54 | CXXFLAGS+=' -g -O0' 55 | VALGRINDFLAGS=--enable-valgrind=yes 56 | else 57 | ASSERTFLAGS=--disable-assert 58 | fi 59 | if [[ -n "$CXXFLAGS" ]] ; then 60 | export CXXFLAGS 61 | fi 62 | which pg_config >/dev/null || POSTGRESFLAGS=--without-postgresql 63 | ./configure --disable-shared $ASSERTFLAGS $POSTGRESFLAGS $VALGRINDFLAGS "$@" 64 | fi 65 | if [ $(uname) = 'Linux' ]; then 66 | j=$(grep processor /proc/cpuinfo | wc -l) 67 | else 68 | j=2 69 | fi 70 | make check -j$j 71 | fi 72 | 73 | -------------------------------------------------------------------------------- /buildtools/cleanlibs.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Script to clean up all the 3rd party dlls required by the client 4 | REM in the directory where the client binaries are compiled. 5 | REM cleanlibs.bat $(SolutionDir)$(Platform)\$(Configuration) 6 | 7 | REM check if destination exists 8 | IF NOT EXIST "%1" GOTO :EOF 9 | 10 | FOR %%X IN (libeay32.dll libeay32.pdb ssleay32.dll ssleay32.pdb zlib1.dll) DO ( 11 | IF EXIST "%1\%%X" ( 12 | ECHO Removing %1\%%X 13 | DEL /F /Q "%1\%%X" 14 | ) 15 | ) 16 | -------------------------------------------------------------------------------- /buildtools/coverage.bat: -------------------------------------------------------------------------------- 1 | MKDIR test-results 2 | ECHO ^ > test-results/coverage.xml 3 | ECHO ^ >> test-results/coverage.xml 4 | ECHO ^^ >> test-results/coverage.xml 5 | -------------------------------------------------------------------------------- /buildtools/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p test-results 4 | gcovr -r . -e mordor/uri.cpp -e mordor/xml/xml_parser.cpp -e mordor/json.cpp -e mordor/http/http_parser.cpp -e 'mordor/tests/.*' -e 'mordor/pq/tests/.*' -e 'mordor/examples/.*' -x > test-results/coverage.xml 5 | -------------------------------------------------------------------------------- /buildtools/getlibs.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Script to copy the 3rd party dlls required by our executables 4 | REM into the directory where the binaries are compiled. 5 | REM That makes it easier to launch the executables 6 | REM with no dependency on dlls being found in the PATH. 7 | REM For example this script can be triggered in Visual Studio as 8 | REM getlibs.bat $(SolutionDir)$(Platform)\$(Configuration) 9 | 10 | REM make sure destination exists 11 | IF NOT EXIST %1 MD %1 12 | 13 | FOR %%X IN (libeay32.dll ssleay32.dll zlib1.dll) DO ( 14 | CALL :findlib %%X %1 15 | IF ERRORLEVEL 1 EXIT /B %ERRORLEVEL% 16 | ) 17 | 18 | EXIT /B %ERRORLEVEL% 19 | 20 | 21 | REM ------------------------ 22 | 23 | :findlib 24 | 25 | SET WHICH=%~$LIB:1 26 | IF "%WHICH%" == "" ( 27 | ECHO Could not find %1 28 | EXIT /B 1 29 | ) ELSE ( 30 | ECHO Copying %WHICH% to %2 31 | COPY /Y "%WHICH%" %2 >NUL 32 | EXIT /B 0 33 | ) 34 | 35 | 36 | -------------------------------------------------------------------------------- /buildtools/unit-test-xcode.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p test-results 4 | rm -rf test-results/TEST-*.xml 5 | CONFIG=DEBUG 6 | TEST_ANTXML_DIRECTORY=test-results/ build/$CONFIG/run_tests 7 | -------------------------------------------------------------------------------- /buildtools/unit-test.bat: -------------------------------------------------------------------------------- 1 | @SETLOCAL 2 | 3 | MKDIR test-results 4 | DEL /F /Q test-results\TEST-*.xml 5 | @SET TEST_ANTXML_DIRECTORY=test-results\ 6 | packages\tests.exe 7 | -------------------------------------------------------------------------------- /buildtools/unit-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p test-results 4 | rm -rf test-results/TEST-*.xml 5 | export TEST_ANTXML_DIRECTORY=test-results/ 6 | 7 | #cmake builds generate binaries out-of-source 8 | if [ -e build/run_tests ] ; then 9 | build/run_tests $* 10 | else 11 | mordor/tests/run_tests $* 12 | fi 13 | -------------------------------------------------------------------------------- /cmakeconfig.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine HAVE_ICONV 2 | -------------------------------------------------------------------------------- /lucid.suppressions: -------------------------------------------------------------------------------- 1 | { 2 | strftime 3 | Memcheck:Cond 4 | fun:__strftime_internal 5 | fun:strftime_l 6 | } 7 | { 8 | global Fiber::ptr 9 | Memcheck:Leak 10 | fun:_Znwm 11 | ... 12 | fun:_ZN5boost19thread_specific_ptrINS_10shared_ptrIN6Mordor5FiberEEEE* 13 | } 14 | { 15 | boost::once_pre_thread_epoch 16 | Memcheck:Leak 17 | fun:malloc 18 | fun:_ZN5boost6detail25get_once_per_thread_epochEv 19 | obj:/usr/lib/libboost_thread.so.1.40.0 20 | fun:_ZN5boost6detail23get_current_thread_dataEv 21 | fun:_ZN5boost6detail13find_tss_dataEPKv 22 | fun:_ZN5boost6detail12get_tss_dataEPKv 23 | } 24 | { 25 | SSL_COMP_get_compressions_methods 26 | Memcheck:Leak 27 | fun:malloc 28 | fun:CRYPTO_malloc 29 | obj:/usr/lib/libssl.so.0.9.8 30 | fun:SSL_COMP_get_compression_methods 31 | fun:SSL_library_init 32 | } 33 | { 34 | backtrace pthread_once init 35 | Memcheck:Leak 36 | fun:malloc 37 | fun:_dl_map_object_deps 38 | fun:dl_open_worker 39 | fun:_dl_catch_error 40 | fun:_dl_open 41 | fun:do_dlopen 42 | fun:_dl_catch_error 43 | fun:__libc_dlopen_mode 44 | fun:init 45 | fun:pthread_once 46 | fun:backtrace 47 | } 48 | -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | libtool.m4 2 | ltoptions.m4 3 | ltsugar.m4 4 | ltversion.m4 5 | lt~obsolete.m4 6 | -------------------------------------------------------------------------------- /m4/ax_check_lzma.m4: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | # 3 | # AX_CHECK_LZMA 4 | # 5 | # DESCRIPTION 6 | # 7 | # This macro searches for an installed lzma2/zx library. 8 | # 9 | # This macro calls: 10 | # 11 | # AC_SUBST(LZMA_CFLAGS) 12 | # AC_SUBST(LZMA_LDFLAGS) 13 | # AC_SUBST(LZMA_LIB) 14 | # AC_DEFINE(HAVE_LIBLZMA) 15 | # AM_CONDITIONAL(HAVE_LZMA) 16 | # 17 | # if the lzma development files are found 18 | 19 | AC_DEFUN([AX_CHECK_LZMA], 20 | [ 21 | AC_MSG_CHECKING(if lzma/zx is wanted) 22 | lzma_places="/usr/local /usr /opt/local /sw" 23 | AC_ARG_WITH([lzma], 24 | [ --with-lzma=DIR root directory path of lzma installation [defaults to 25 | /usr/local or /usr if not found in /usr/local] 26 | --without-lzma to disable lzma usage completely], 27 | [if test "$withval" != no ; then 28 | want_lzma="yes" 29 | if test -d "$withval"; then 30 | lzma_places="$withval $lzma_places" 31 | fi 32 | else 33 | want_lzma="no" 34 | fi], 35 | [want_lzma="check"]) 36 | 37 | if test "$want_lzma" != "no"; then 38 | for LZMA_HOME in ${lzma_places} ; do 39 | if test -f "${LZMA_HOME}/include/lzma.h"; then break; fi 40 | LZMA_HOME="" 41 | done 42 | 43 | LZMA_SAVED_LDFLAGS=$LDFLAGS 44 | LZMA_SAVED_CPPFLAGS=$CPPFLAGS 45 | LZMA_SAVED_LIBS=$LIBS 46 | if test -n "${LZMA_HOME}"; then 47 | LZMA_CFLAGS="-I${LZMA_HOME}/include" 48 | LZMA_LDFLAGS="-L${LZMA_HOME}/lib" 49 | LZMA_LIB="-llzma" 50 | CPPFLAGS="$CPPFLAGS $LZMA_CFLAGS" 51 | LDFLAGS="$LDFLAGS $LZMA_LDFLAGS" 52 | LIBS="$LIBS $LZMA_LIB" 53 | fi 54 | AC_CACHE_CHECK([whether lzma library is available], 55 | ax_cv_lzma, 56 | [AC_LANG_PUSH([C]) 57 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM( 58 | [[@%:@include ]], 59 | [[lzma_end(NULL);]])], 60 | ax_cv_lzma=yes, 61 | ax_cv_lzma=no) 62 | AC_LANG_POP([C])]) 63 | if test "$ax_cv_lzma" = "yes"; then 64 | # If both library and header were found, use them 65 | AC_SUBST(LZMA_CFLAGS) 66 | AC_SUBST(LZMA_LDFLAGS) 67 | AC_SUBST(LZMA_LIB) 68 | AC_DEFINE([HAVE_LZMA], [1], 69 | [Define if `lzma' library (-llzma) is available]) 70 | elif test "$want_lzma" = "yes"; then 71 | AC_MSG_ERROR([either specify a valid lzma installation with --with-lzma=DIR or disable lzma usage with --without-lzma]) 72 | fi 73 | # Restore variables 74 | LDFLAGS="$LZMA_SAVED_LDFLAGS" 75 | CPPFLAGS="$LZMA_SAVED_CPPFLAGS" 76 | LIBS="$LZMA_SAVED_LIBS" 77 | fi 78 | AM_CONDITIONAL(HAVE_LZMA, test "x[$]ax_cv_lzma" = xyes) 79 | ]) 80 | -------------------------------------------------------------------------------- /m4/check_valgrind.m4: -------------------------------------------------------------------------------- 1 | # SYNOPSIS 2 | # 3 | # AC_CHECK_VALGRIND 4 | # 5 | # DESCRIPTION 6 | # 7 | # Test for enable/disable HAVE_VALGRIND macro 8 | # 9 | # This macro enable following option 10 | # 11 | # --disable-valgrind 12 | # --enable-valgrind= 13 | # 14 | # This macro calls: 15 | # AC_SUBST(VALGRIND_CPPFLAGS) 16 | # 17 | # And sets: 18 | # 19 | # HAVE_VALGRIND 20 | 21 | AC_DEFUN([AC_CHECK_VALGRIND], 22 | [ 23 | AC_ARG_ENABLE([valgrind], 24 | AS_HELP_STRING( 25 | [--with-valgrind@<:@=ARG@:>@], 26 | [Compile with HAVE_VALGRIND macro defined (ARG=yes), 27 | or disable it (ARG=no) 28 | @<:@ARG=no@:>@ ] 29 | ), 30 | [ 31 | if test "$enableval" = "yes"; then 32 | want_valgrind="yes" 33 | else 34 | want_valgrind="no" 35 | fi 36 | ], 37 | [want_valgrind="no"] 38 | ) 39 | 40 | AC_MSG_CHECKING([whether enable HAVE_VALGRIND macro]) 41 | if test x${want_valgrind} = "xyes" ; then 42 | AC_MSG_RESULT([yes]) 43 | AC_DEFINE(HAVE_VALGRIND,1,[define if compiling for running valgrind ]) 44 | VALGRIND_CPPFLAGS="-DHAVE_VALGRIND" 45 | AC_SUBST(VALGRIND_CPPFLAGS) 46 | else 47 | AC_MSG_RESULT([no]) 48 | fi 49 | ]) 50 | -------------------------------------------------------------------------------- /m4/ragel.m4: -------------------------------------------------------------------------------- 1 | dnl Check for presence of the Ragel State Machine generator. 2 | dnl 3 | dnl This macro checks for the presence of the ragel tool in the system, 4 | dnl and whether the ragel tool is absolutely needed for a complete 5 | dnl build. 6 | dnl 7 | dnl To check for the need for Ragel, you have to provide the relative 8 | dnl path of a source file generated through Ragel: if the file is 9 | dnl present in the source tree, a missing ragel command will not cause 10 | dnl the configure to abort. 11 | 12 | AC_DEFUN([_RAGEL_VARS], [ 13 | AC_ARG_VAR([RAGEL], [Ragel generator command]) 14 | AC_ARG_VAR([RAGELFLAGS], [Ragel generator flags]) 15 | ]) 16 | 17 | AC_DEFUN([CHECK_RAGEL], [ 18 | AC_REQUIRE([_RAGEL_VARS]) 19 | AC_PATH_PROG([RAGEL], [ragel], [no], [$PATH:/usr/local/bin:/opt/local/bin]) 20 | 21 | dnl We set RAGEL to false so that it would execute the "false" 22 | dnl command if needed. 23 | AS_IF([test x"$RAGEL" = x"no"], 24 | [RAGEL=false], 25 | AS_IF([test x"$2" != "x"], 26 | [ragel_version=`$RAGEL --version | sed -n -e '1s:.*version \(@<:@0-9@:>@\.@<:@0-9@:>@\) .*:\1:p'` 27 | ragel_version_compare=`echo $ragel_version | tr -d .` 28 | ragel_wanted_version=`echo $2 | tr -d .` 29 | AS_IF([test $ragel_version_compare -lt $ragel_wanted_version], 30 | [AC_MSG_WARN([Found Ragel $ragel_version but Ragel $2 requested]) 31 | RAGEL=false 32 | ]) 33 | ])) 34 | 35 | dnl Only test the need if not found 36 | AS_IF([test x"$RAGEL" = x"false"], [ 37 | AC_MSG_CHECKING([whether we need ragel to regenerate sources]) 38 | AS_IF([test -a "${srcdir}/$1"], [ragel_needed=no], [ragel_needed=yes]) 39 | AC_MSG_RESULT([$ragel_needed]) 40 | 41 | AS_IF([test x"$ragel_needed" = x"yes"], 42 | [AC_MSG_ERROR([dnl 43 | You need Ragel to build from development sources. 44 | You can find Ragel at http://www.complang.org/ragel/dnl 45 | ])]) 46 | ]) 47 | ]) 48 | 49 | AC_DEFUN([CHECK_RAGEL_AM], [ 50 | CHECK_RAGEL([$1], [$2]) 51 | 52 | AM_CONDITIONAL([HAVE_RAGEL], [test x"$RAGEL" != x"false"]) 53 | ]) 54 | -------------------------------------------------------------------------------- /mordor/.gitignore: -------------------------------------------------------------------------------- 1 | json.cpp 2 | uri.cpp 3 | json.cpp 4 | libmordor.pc 5 | -------------------------------------------------------------------------------- /mordor/anymap.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_ANYMAP_H__ 2 | #define __MORDOR_ANYMAP_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | namespace Mordor { 11 | 12 | template 13 | class anymaptag 14 | { 15 | public: 16 | typedef Tag tag_type; 17 | typedef T value_type; 18 | }; 19 | 20 | class anymap 21 | { 22 | public: 23 | typedef boost::shared_ptr ptr; 24 | 25 | private: 26 | class anymaptypeinfo 27 | { 28 | public: 29 | anymaptypeinfo(const std::type_info &type) 30 | : m_type(type) 31 | {} 32 | anymaptypeinfo(const anymaptypeinfo ©) 33 | : m_type(copy.m_type) 34 | {} 35 | bool operator <(const anymaptypeinfo& rhs) const 36 | { 37 | return !!m_type.before(rhs.m_type); 38 | } 39 | 40 | private: 41 | const std::type_info &m_type; 42 | }; 43 | 44 | public: 45 | template 46 | typename TagType::value_type& 47 | operator[](const TagType &) 48 | { 49 | boost::any &val = m_map[typeid(typename TagType::tag_type)]; 50 | if (val.empty()) { 51 | val = typename TagType::value_type(); 52 | } 53 | return *boost::any_cast(&val); 54 | } 55 | 56 | template 57 | size_t erase(const TagType &) 58 | { 59 | return m_map.erase(typeid(typename TagType::tag_type)); 60 | } 61 | 62 | void clear() 63 | { 64 | m_map.clear(); 65 | } 66 | 67 | size_t size() const 68 | { 69 | return m_map.size(); 70 | } 71 | 72 | 73 | bool empty() const 74 | { 75 | return m_map.empty(); 76 | } 77 | 78 | private: 79 | std::map m_map; 80 | }; 81 | 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /mordor/assert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "assert.h" 4 | 5 | #include "version.h" 6 | 7 | #ifdef LINUX 8 | #include 9 | #elif defined(OSX) 10 | #include 11 | #endif 12 | 13 | namespace Mordor { 14 | 15 | bool Assertion::throwOnAssertion; 16 | 17 | bool isDebuggerAttached() 18 | { 19 | #ifdef WINDOWS 20 | return !!IsDebuggerPresent(); 21 | #elif defined(LINUX) 22 | bool result = false; 23 | char buffer[1024]; 24 | snprintf(buffer, 1024, "/proc/%d/status", getpid()); 25 | int fd = open(buffer, O_RDONLY); 26 | if (fd >= 0) { 27 | int rc = read(fd, buffer, 1024); 28 | if (rc > 0) { 29 | const char *tracerPidStr = strstr(buffer, "TracerPid:"); 30 | if (tracerPidStr) { 31 | int tracingPid = atoi(tracerPidStr + 13); 32 | if (tracingPid != 0) { 33 | result = true; 34 | } 35 | } 36 | } 37 | close(fd); 38 | } 39 | return result; 40 | #elif defined(OSX) 41 | int mib[4]; 42 | kinfo_proc info; 43 | size_t size; 44 | mib[0] = CTL_KERN; 45 | mib[1] = KERN_PROC; 46 | mib[2] = KERN_PROC_PID; 47 | mib[3] = getpid(); 48 | size = sizeof(kinfo_proc); 49 | info.kp_proc.p_flag = 0; 50 | sysctl(mib, 4, &info, &size, NULL, 0); 51 | return !!(info.kp_proc.p_flag & P_TRACED); 52 | #else 53 | return false; 54 | #endif 55 | } 56 | 57 | void debugBreak() 58 | { 59 | #ifdef WINDOWS 60 | DebugBreak(); 61 | #elif defined (GCC) 62 | #ifdef PPC 63 | __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" 64 | : : : "memory","r0","r3","r4" ); 65 | #elif defined(X86) || defined(X86_64) 66 | __asm__("int $3\n" : : ); 67 | #endif 68 | #endif 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /mordor/cxa_exception.cpp: -------------------------------------------------------------------------------- 1 | #include "cxa_exception.h" 2 | 3 | #include "assert.h" 4 | 5 | // exception handling implemented by GCC and Clang conform to this ABI. 6 | // both implementation store the exception stack to a thread local storage 7 | // variable and swapcontext(3) does not care about pthread's TLS. 8 | namespace __cxxabiv1 { 9 | extern "C" __cxa_eh_globals * __cxa_get_globals() throw(); 10 | } 11 | 12 | namespace Mordor { 13 | 14 | ExceptionStack::ExceptionStack() 15 | { 16 | #ifdef CXXABIV1_EXCEPTION 17 | memset(&m_eh, 0, sizeof(m_eh)); 18 | #endif 19 | } 20 | 21 | 22 | void 23 | ExceptionStack::swap(ExceptionStack &rhs) { 24 | #ifdef CXXABIV1_EXCEPTION 25 | __cxxabiv1::__cxa_eh_globals *eh = __cxxabiv1::__cxa_get_globals(); 26 | MORDOR_ASSERT(eh); 27 | m_eh = *eh; 28 | *eh = rhs.m_eh; 29 | #endif 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /mordor/cxa_exception.h: -------------------------------------------------------------------------------- 1 | #ifndef __CXA_EXCEPTION_H__ 2 | #define __CXA_EXCEPTION_H__ 3 | 4 | /// @file cxa_exception.h 5 | /// this file declares some interfaces for "Exception Handling APIs" 6 | /// see http://www.codesourcery.com/public/cxx-abi/abi-eh.html 7 | 8 | #if defined(__GNUC__) || defined(__clang__) 9 | # define CXXABIV1_EXCEPTION 10 | // MSVC compiler has /GT option for supporting fiber-safe thread-local storage 11 | #endif 12 | 13 | #ifdef CXXABIV1_EXCEPTION 14 | 15 | #include 16 | #include 17 | 18 | namespace __cxxabiv1 { 19 | // __cxa_exception is defined in unwind.h which is in turn a part of GCC. 20 | // here we do not care about the internals of it. so make it a `void'. 21 | typedef void __cxa_exception_; 22 | // Each thread in a C++ program has access to a __cxa_eh_globals object. 23 | struct __cxa_eh_globals { 24 | __cxa_exception_ * caughtExceptions; 25 | unsigned int uncaughtExceptions; 26 | #ifdef __ARM_EABI_UNWINDER__ 27 | __cxa_exception* propagatingExceptions; 28 | #endif 29 | }; 30 | } 31 | #endif 32 | 33 | namespace Mordor { 34 | 35 | class ExceptionStack 36 | { 37 | public: 38 | ExceptionStack(); 39 | /// save current exception stack to this fiber, and replace current 40 | /// exception stack with the one in toFiber. 41 | void swap(ExceptionStack &); 42 | private: 43 | #ifdef CXXABIV1_EXCEPTION 44 | __cxxabiv1::__cxa_eh_globals m_eh; 45 | #endif 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /mordor/date_time.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "date_time.h" 4 | 5 | namespace Mordor { 6 | 7 | time_t toTimeT(const boost::posix_time::ptime &ptime) 8 | { 9 | static const boost::posix_time::ptime time_t_epoch(boost::gregorian::date(1970,1,1)); 10 | boost::posix_time::time_duration diff = ptime - time_t_epoch; 11 | return diff.total_seconds(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mordor/date_time.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_DATE_TIME_H__ 2 | #define __MORDOR_DATE_TIME_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | namespace Mordor { 8 | time_t toTimeT(const boost::posix_time::ptime &ptime); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /mordor/eventloop.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_EVENTLOOP_H__ 2 | #define __MORDOR_EVENTLOOP_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #ifdef WINDOWS 6 | 7 | #include "scheduler.h" 8 | #include "socket.h" 9 | #include "timer.h" 10 | 11 | namespace Mordor { 12 | 13 | /// Scheduler that processes UI events 14 | class EventLoop : public Scheduler, public TimerManager 15 | { 16 | private: 17 | struct Initializer 18 | { 19 | Initializer(); 20 | ~Initializer(); 21 | }; 22 | 23 | public: 24 | EventLoop(); 25 | ~EventLoop(); 26 | 27 | bool stopping(); 28 | 29 | protected: 30 | void idle(); 31 | void tickle(); 32 | void onTimerInsertedAtFront(); 33 | 34 | private: 35 | static LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 36 | static LRESULT CALLBACK foregroundIdleProc(int nCode, WPARAM wParam, LPARAM lParam); 37 | void messagePump(); 38 | 39 | private: 40 | static Initializer g_init; 41 | 42 | HWND m_messageWindow; 43 | HHOOK m_idleHook; 44 | }; 45 | 46 | } 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /mordor/examples/.gitignore: -------------------------------------------------------------------------------- 1 | cat 2 | echoserver 3 | iombench 4 | simpleclient 5 | tunnel 6 | udpstats 7 | wget 8 | simpleappserver 9 | zipstreaming 10 | zipstreaming_example.zip 11 | 12 | -------------------------------------------------------------------------------- /mordor/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Compile Mordor examples 2 | 3 | function(set_mordor_example_linking target) 4 | target_link_libraries(${target} mordor ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ${ZLIB_LIBRARIES}) 5 | 6 | add_osspecific_linking(${target}) 7 | endfunction(set_mordor_example_linking) 8 | 9 | #Syntax helper because most examples only have a single .cpp file 10 | #whose name matches the test output 11 | function(compile_example name) 12 | add_executable(${name} ${name}.cpp) 13 | set_mordor_example_linking(${name}) 14 | endfunction() 15 | 16 | compile_example("cat") 17 | compile_example("wget") 18 | compile_example("echoserver") 19 | compile_example("tunnel") 20 | 21 | if (MSVC) 22 | compile_example("decodebacktrace") 23 | compile_example("simpleclient") 24 | else() 25 | compile_example("udpstats") 26 | compile_example("zipstreaming") 27 | compile_example("simpleappserver") 28 | endif() 29 | 30 | #This example has two source files 31 | add_executable(iombench iombench.cpp netbench.cpp) 32 | set_mordor_example_linking(iombench) 33 | -------------------------------------------------------------------------------- /mordor/examples/cat.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | 5 | #include 6 | 7 | #include "mordor/config.h" 8 | #include "mordor/main.h" 9 | #include "mordor/streams/file.h" 10 | #include "mordor/streams/std.h" 11 | #include "mordor/streams/transfer.h" 12 | #include "mordor/workerpool.h" 13 | 14 | using namespace Mordor; 15 | 16 | MORDOR_MAIN(int argc, const char * const argv[]) 17 | { 18 | try { 19 | Config::loadFromEnvironment(); 20 | StdoutStream stdoutStream; 21 | WorkerPool pool(2); 22 | if (argc == 1) { 23 | argc = 2; 24 | const char * const hyphen[] = { "", "-" }; 25 | argv = hyphen; 26 | } 27 | for (int i = 1; i < argc; ++i) { 28 | Stream::ptr inStream; 29 | std::string arg(argv[i]); 30 | if (arg == "-") { 31 | inStream.reset(new StdinStream()); 32 | } else { 33 | inStream.reset(new FileStream(arg, FileStream::READ)); 34 | } 35 | transferStream(inStream, stdoutStream); 36 | } 37 | } catch (...) { 38 | std::cerr << boost::current_exception_diagnostic_information() 39 | << std::endl; 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /mordor/examples/cat.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/examples/decodebacktrace.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/examples/echoserver.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/examples/iombench.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /mordor/examples/simpleappserver.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | 5 | #include 6 | 7 | #include "mordor/config.h" 8 | #include "mordor/http/server.h" 9 | #include "mordor/iomanager.h" 10 | #include "mordor/main.h" 11 | #include "mordor/socket.h" 12 | #include "mordor/streams/memory.h" 13 | #include "mordor/streams/socket.h" 14 | #include "mordor/streams/transfer.h" 15 | 16 | using namespace Mordor; 17 | 18 | static std::map g_state; 19 | 20 | static void httpRequest(HTTP::ServerRequest::ptr request) 21 | { 22 | const std::string &method = request->request().requestLine.method; 23 | const URI &uri = request->request().requestLine.uri; 24 | 25 | if (method == HTTP::GET || method == HTTP::HEAD) { 26 | std::map::iterator it = 27 | g_state.find(uri); 28 | if (it == g_state.end()) { 29 | HTTP::respondError(request, HTTP::NOT_FOUND); 30 | } else { 31 | MemoryStream::ptr copy(new MemoryStream(it->second->buffer())); 32 | HTTP::respondStream(request, copy); 33 | } 34 | } else if (method == HTTP::PUT) { 35 | MemoryStream::ptr stream(new MemoryStream()); 36 | transferStream(request->requestStream(), stream); 37 | g_state[uri] = stream; 38 | HTTP::respondError(request, HTTP::OK); 39 | } else { 40 | HTTP::respondError(request, HTTP::METHOD_NOT_ALLOWED); 41 | } 42 | } 43 | 44 | MORDOR_MAIN(int argc, char *argv[]) 45 | { 46 | try { 47 | Config::loadFromEnvironment(); 48 | IOManager ioManager; 49 | Socket s(ioManager, AF_INET, SOCK_STREAM); 50 | IPv4Address address(INADDR_ANY, 80); 51 | 52 | s.bind(address); 53 | s.listen(); 54 | 55 | while (true) { 56 | Socket::ptr socket = s.accept(); 57 | Stream::ptr stream(new SocketStream(socket)); 58 | HTTP::ServerConnection::ptr conn(new HTTP::ServerConnection(stream, 59 | &httpRequest)); 60 | conn->processRequests(); 61 | } 62 | } catch (...) { 63 | std::cerr << boost::current_exception_diagnostic_information() << std::endl; 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /mordor/examples/simpleclient.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | 5 | #include 6 | 7 | #include "mordor/config.h" 8 | #include "mordor/fiber.h" 9 | #include "mordor/iomanager.h" 10 | #include "mordor/main.h" 11 | #include "mordor/socket.h" 12 | 13 | using namespace Mordor; 14 | 15 | MORDOR_MAIN(int argc, char *argv[]) 16 | { 17 | try { 18 | Config::loadFromEnvironment(); 19 | IOManager ioManager; 20 | std::vector addresses = Address::lookup(argv[1]); 21 | Socket::ptr s(addresses[0]->createSocket(ioManager, SOCK_STREAM)); 22 | s->connect(addresses[0]); 23 | size_t rc = s->send("hello\r\n", 7); 24 | char buf[8192]; 25 | rc = s->receive(buf, 8192); 26 | buf[rc] = 0; 27 | std::cout << "Read " << buf << " from conn" << std::endl; 28 | s->shutdown(); 29 | } catch (...) { 30 | std::cerr << boost::current_exception_diagnostic_information() << std::endl; 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /mordor/examples/simpleclient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/examples/tunnel.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/examples/udpstats.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | 5 | #include 6 | 7 | #include "mordor/config.h" 8 | #include "mordor/iomanager.h" 9 | #include "mordor/socket.h" 10 | #include "mordor/statistics.h" 11 | 12 | using namespace Mordor; 13 | 14 | ConfigVar::ptr g_perCount = Config::lookup("dumpfrequency", 10u, "How often should statistics be dumped (packets)"); 15 | 16 | int main(int argc, char **argv) 17 | { 18 | Config::loadFromEnvironment(); 19 | if (argc != 2) { 20 | std::cerr << "Usage:
" << std::endl; 21 | return 1; 22 | } 23 | try { 24 | IOManager ioManager; 25 | AverageMinMaxStatistic &stats = Statistics::registerStatistic("broadcasts", 26 | AverageMinMaxStatistic("bytes", "packets")); 27 | 28 | std::vector addresses = Address::lookup(argv[1]); 29 | Socket::ptr sock = addresses[0]->createSocket(ioManager, SOCK_DGRAM); 30 | sock->bind(addresses[0]); 31 | char buf[65536]; 32 | IPv4Address addr; 33 | while (true) { 34 | size_t read = sock->receiveFrom(buf, 65536, addr); 35 | stats.update(read); 36 | if (stats.count.count % g_perCount->val() == 0) 37 | Statistics::dump(std::cout); 38 | } 39 | } catch (...) { 40 | std::cerr << boost::current_exception_diagnostic_information() << std::endl; 41 | return 2; 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /mordor/examples/wget.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /mordor/factory.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_FACTORY_H__ 2 | #define __MORDOR_FACTORY_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | namespace Mordor { 6 | 7 | // Wish I could use boost functional/factory, but that's new in boost 1.43, 8 | // which no version of Debian currently has 9 | 10 | struct Dummy; 11 | 12 | template 13 | class Creator 14 | { 15 | public: 16 | BaseType *create0() { return new T(); } 17 | BaseType *create1(A1 a1) { return new T(a1); } 18 | BaseType *create2(A1 a1, A2 a2) { return new T(a1, a2); } 19 | }; 20 | 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /mordor/http/.gitignore: -------------------------------------------------------------------------------- 1 | http_parser.cpp 2 | 3 | -------------------------------------------------------------------------------- /mordor/http/auth.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_AUTH_H__ 2 | #define __MORDOR_HTTP_AUTH_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "broker.h" 10 | #include "mordor/version.h" 11 | 12 | namespace Mordor { 13 | namespace HTTP { 14 | 15 | class AuthRequestBroker : public RequestBrokerFilter 16 | { 17 | public: 18 | AuthRequestBroker(RequestBroker::ptr parent, 19 | boost::function /* priorRequest = ClientRequest::ptr() */, 21 | std::string & /* scheme */, std::string & /* realm */, 22 | std::string & /* username */, std::string & /* password */, 23 | size_t /* attempts */)> 24 | getCredentialsDg, 25 | boost::function /* priorRequest = ClientRequest::ptr() */, 27 | std::string & /* scheme */, std::string & /* realm */, 28 | std::string & /* username */, std::string & /* password */, 29 | size_t /* attempts */)> 30 | getProxyCredentialsDg) 31 | : RequestBrokerFilter(parent), 32 | m_getCredentialsDg(getCredentialsDg), 33 | m_getProxyCredentialsDg(getProxyCredentialsDg) 34 | {} 35 | 36 | boost::shared_ptr request(Request &requestHeaders, 37 | bool forceNewConnection = false, 38 | boost::function)> bodyDg = NULL); 39 | 40 | private: 41 | boost::function, 42 | std::string &, std::string &, std::string &, std::string &, size_t)> 43 | m_getCredentialsDg, m_getProxyCredentialsDg; 44 | }; 45 | 46 | #ifdef OSX 47 | bool getCredentialsFromKeychain(const URI &uri, 48 | boost::shared_ptr priorRequest, 49 | std::string &scheme, std::string &realm, std::string &username, 50 | std::string &password, size_t attempts); 51 | #endif 52 | 53 | }} 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /mordor/http/basic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "basic.h" 4 | 5 | #include "http.h" 6 | #include "mordor/string.h" 7 | 8 | namespace Mordor { 9 | namespace HTTP { 10 | namespace BasicAuth { 11 | 12 | void authorize(AuthParams &authorization, const std::string &username, 13 | const std::string &password) 14 | { 15 | authorization.scheme = "Basic"; 16 | authorization.param = base64encode(username + ":" + password); 17 | authorization.parameters.clear(); 18 | } 19 | 20 | void authorize(Request &nextRequest, 21 | const std::string &username, const std::string &password, 22 | bool proxy) 23 | { authorize(proxy ? nextRequest.request.proxyAuthorization : 24 | nextRequest.request.authorization, username, password); } 25 | 26 | 27 | }}} 28 | -------------------------------------------------------------------------------- /mordor/http/basic.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_BASIC_AUTH_H__ 2 | #define __MORDOR_HTTP_BASIC_AUTH_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | namespace Mordor { 8 | namespace HTTP { 9 | 10 | struct AuthParams; 11 | struct Request; 12 | 13 | namespace BasicAuth { 14 | 15 | void authorize(AuthParams &authorization, const std::string &username, 16 | const std::string &password); 17 | 18 | /// @deprecated 19 | void authorize(Request &nextRequest, 20 | const std::string &username, const std::string &password, 21 | bool proxy = false); 22 | 23 | }}} 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /mordor/http/chunked.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_CHUNKED_H__ 2 | #define __MORDOR_HTTP_CHUNKED_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "mordor/exception.h" 6 | #include "mordor/streams/filter.h" 7 | 8 | namespace Mordor { 9 | namespace HTTP { 10 | 11 | struct InvalidChunkException : virtual StreamException 12 | { 13 | public: 14 | enum Type 15 | { 16 | HEADER, 17 | FOOTER 18 | }; 19 | InvalidChunkException(const std::string &line, Type type); 20 | ~InvalidChunkException() throw() {} 21 | 22 | const std::string &line() const { return m_line; } 23 | Type type() const { return m_type; } 24 | 25 | private: 26 | std::string m_line; 27 | Type m_type; 28 | }; 29 | 30 | class ChunkedStream : public MutatingFilterStream 31 | { 32 | public: 33 | ChunkedStream(Stream::ptr parent, bool own = true); 34 | 35 | void close(CloseType type = BOTH); 36 | using MutatingFilterStream::read; 37 | size_t read(Buffer &b, size_t len); 38 | using MutatingFilterStream::write; 39 | size_t write(const Buffer &b, size_t len); 40 | 41 | private: 42 | unsigned long long m_nextChunk; 43 | }; 44 | 45 | }} 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /mordor/http/connection.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_CONNECTION_H__ 2 | #define __MORDOR_HTTP_CONNECTION_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "mordor/anymap.h" 10 | #include "http.h" 11 | 12 | namespace Mordor { 13 | 14 | class Stream; 15 | 16 | namespace HTTP { 17 | 18 | class Connection 19 | { 20 | public: 21 | boost::shared_ptr stream() { return m_stream; } 22 | 23 | static bool hasMessageBody(const GeneralHeaders &general, 24 | const EntityHeaders &entity, 25 | const std::string &method, 26 | Status status, 27 | bool includeEmpty = true); 28 | 29 | /// @note Be sure to lock the cacheMutex whenever you access the cache 30 | anymap &cache() { return m_cache; } 31 | boost::mutex &cacheMutex() { return m_cacheMutex; } 32 | 33 | /// lock cacheMutex and return a copy of value 34 | template 35 | typename TagType::value_type getCache(const TagType &key) 36 | { 37 | boost::mutex::scoped_lock lock(m_cacheMutex); 38 | return m_cache[key]; 39 | } 40 | 41 | /// update cache with lock 42 | template 43 | void setCache(const TagType &key, const typename TagType::value_type& value) 44 | { 45 | boost::mutex::scoped_lock lock(m_cacheMutex); 46 | m_cache[key] = value; 47 | } 48 | 49 | protected: 50 | Connection(boost::shared_ptr stream); 51 | 52 | boost::shared_ptr getStream(const GeneralHeaders &general, 53 | const EntityHeaders &entity, 54 | const std::string &method, 55 | Status status, 56 | boost::function notifyOnEof, 57 | boost::function notifyOnException, 58 | bool forRead); 59 | 60 | protected: 61 | boost::shared_ptr m_stream; 62 | 63 | private: 64 | boost::mutex m_cacheMutex; 65 | anymap m_cache; 66 | }; 67 | 68 | }} 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /mordor/http/digest.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_DIGEST_AUTH_H__ 2 | #define __MORDOR_HTTP_DIGEST_AUTH_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "http.h" 6 | 7 | namespace Mordor { 8 | namespace HTTP { 9 | namespace DigestAuth { 10 | 11 | struct InvalidParamsException : virtual InvalidMessageHeaderException {}; 12 | struct InvalidQopException : virtual InvalidParamsException 13 | { 14 | public: 15 | InvalidQopException(const std::string &message) : m_message(message) {} 16 | ~InvalidQopException() throw() {} 17 | 18 | const char *what() const throw() { return m_message.c_str(); } 19 | private: 20 | std::string m_message; 21 | }; 22 | struct InvalidAlgorithmException : virtual InvalidParamsException 23 | { 24 | public: 25 | InvalidAlgorithmException(const std::string &message) : m_message(message) {} 26 | ~InvalidAlgorithmException() throw() {} 27 | 28 | const char *what() const throw() { return m_message.c_str(); } 29 | private: 30 | std::string m_message; 31 | }; 32 | 33 | void authorize(const AuthParams &challenge, AuthParams &authorization, 34 | const URI &uri, const std::string &method, const std::string &username, 35 | const std::string &password); 36 | 37 | /// @deprecated 38 | void authorize(const Response &challenge, Request &nextRequest, 39 | const std::string &username, const std::string &password); 40 | 41 | }}} 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /mordor/http/multipart.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_MULTIPART_H__ 2 | #define __MORDOR_MULTIPART_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | // This implementation comply with http://www.rfc-editor.org/rfc/rfc2046.txt 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "http.h" 13 | 14 | namespace Mordor { 15 | 16 | class BodyPart; 17 | class Stream; 18 | 19 | struct MissingMultipartBoundaryException : virtual HTTP::Exception, virtual StreamException 20 | {}; 21 | struct InvalidMultipartBoundaryException : virtual HTTP::Exception 22 | {}; 23 | 24 | class Multipart : public boost::enable_shared_from_this, boost::noncopyable 25 | { 26 | friend class BodyPart; 27 | public: 28 | typedef boost::shared_ptr ptr; 29 | 30 | static std::string randomBoundary(); 31 | 32 | Multipart(boost::shared_ptr stream, std::string boundary); 33 | 34 | boost::shared_ptr nextPart(); 35 | void finish(); 36 | 37 | boost::function multipartFinished; 38 | 39 | private: 40 | void partDone(); 41 | 42 | private: 43 | boost::shared_ptr m_stream; 44 | std::string m_boundary; 45 | boost::shared_ptr m_currentPart; 46 | bool m_finished; 47 | bool m_firstPart; 48 | }; 49 | 50 | class BodyPart 51 | { 52 | friend class Multipart; 53 | public: 54 | typedef boost::shared_ptr ptr; 55 | 56 | private: 57 | BodyPart(Multipart::ptr multipart); 58 | 59 | public: 60 | HTTP::EntityHeaders &headers(); 61 | boost::shared_ptr stream(); 62 | Multipart::ptr multipart(); 63 | 64 | private: 65 | HTTP::EntityHeaders m_headers; 66 | Multipart::ptr m_multipart; 67 | boost::shared_ptr m_stream; 68 | Multipart::ptr m_childMultipart; 69 | }; 70 | 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /mordor/http/negotiate.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_NEGOTIATE_AUTH_H__ 2 | #define __MORDOR_HTTP_NEGOTIATE_AUTH_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | 11 | namespace Mordor { 12 | 13 | struct URI; 14 | 15 | namespace HTTP { 16 | 17 | struct AuthParams; 18 | struct Request; 19 | struct Response; 20 | 21 | class NegotiateAuth : public boost::noncopyable 22 | { 23 | public: 24 | NegotiateAuth(const std::string &username, const std::string &password); 25 | ~NegotiateAuth(); 26 | 27 | bool authorize(const AuthParams &challenge, AuthParams &authorization, 28 | const URI &uri); 29 | 30 | private: 31 | std::wstring m_username, m_password, m_domain; 32 | CredHandle m_creds; 33 | SecHandle m_secCtx; 34 | }; 35 | 36 | }} 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /mordor/http/oauth2.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011 - Mozy, Inc. 2 | 3 | #include "oauth2.h" 4 | #include "client.h" 5 | 6 | namespace Mordor { 7 | namespace HTTP { 8 | namespace OAuth2 { 9 | 10 | void 11 | authorize(Request &nextRequest, const std::string &token) 12 | { 13 | MORDOR_ASSERT(!token.empty()); 14 | 15 | AuthParams &authorization = nextRequest.request.authorization; 16 | authorization.scheme = "Bearer"; 17 | authorization.param = base64encode(token); 18 | authorization.parameters.clear(); 19 | } 20 | 21 | static void authorizeDg(ClientRequest::ptr request, 22 | const std::string &token, 23 | boost::function bodyDg) 24 | { 25 | authorize(request->request(), token); 26 | if (bodyDg) 27 | bodyDg(request); 28 | else 29 | request->doRequest(); 30 | } 31 | 32 | ClientRequest::ptr 33 | RequestBroker::request(Request &requestHeaders, bool forceNewConnection, 34 | boost::function bodyDg) 35 | { 36 | ClientRequest::ptr priorRequest; 37 | std::string token; 38 | size_t attempts = 0; 39 | while (true) { 40 | boost::function wrappedBodyDg = bodyDg; 41 | if (m_getCredentialsDg(requestHeaders.requestLine.uri, priorRequest, token, attempts++)) 42 | wrappedBodyDg = boost::bind(&authorizeDg, _1, boost::cref(token), bodyDg); 43 | else if (priorRequest) 44 | return priorRequest; 45 | if (priorRequest) 46 | priorRequest->finish(); 47 | priorRequest = parent()->request(requestHeaders, forceNewConnection, 48 | wrappedBodyDg); 49 | if (priorRequest->response().status.status == UNAUTHORIZED && 50 | isAcceptable(priorRequest->response().response.wwwAuthenticate, 51 | "Bearer")) 52 | continue; 53 | return priorRequest; 54 | } 55 | } 56 | 57 | }}} 58 | -------------------------------------------------------------------------------- /mordor/http/oauth2.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_OAUTH2_H__ 2 | #define __MORDOR_HTTP_OAUTH2_H__ 3 | // Copyright (c) 2011 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "broker.h" 8 | 9 | namespace Mordor { 10 | namespace HTTP { 11 | namespace OAuth2 { 12 | 13 | void authorize(Request &nextRequest, 14 | const std::string &token); 15 | 16 | class RequestBroker : public RequestBrokerFilter 17 | { 18 | public: 19 | RequestBroker(HTTP::RequestBroker::ptr parent, 20 | boost::function /* priorRequest = ClientRequest::ptr() */, 22 | std::string & /* token */, 23 | size_t /* attempts */)> getCredentialsDg) 24 | : RequestBrokerFilter(parent), 25 | m_getCredentialsDg(getCredentialsDg) 26 | {} 27 | 28 | boost::shared_ptr request(Request &requestHeaders, 29 | bool forceNewConnection = false, 30 | boost::function)> bodyDg = NULL); 31 | 32 | private: 33 | boost::function, std::string &, 34 | size_t)> m_getCredentialsDg; 35 | }; 36 | 37 | }}} 38 | 39 | #endif // __MORDOR_HTTP_OAUTH2_H__ 40 | 41 | -------------------------------------------------------------------------------- /mordor/http/servlets/config.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HTTP_SERVLETS_CONFIG_H__ 2 | #define __MORDOR_HTTP_SERVLETS_CONFIG_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "mordor/http/servlet.h" 8 | 9 | namespace Mordor { 10 | namespace HTTP { 11 | class ServerRequest; 12 | namespace Servlets { 13 | 14 | class Config : public Servlet 15 | { 16 | public: 17 | enum Access 18 | { 19 | READONLY, 20 | READWRITE 21 | }; 22 | 23 | public: 24 | Config(Access access) 25 | : m_access(access) 26 | {} 27 | 28 | void request(boost::shared_ptr request) 29 | { return this->request(request, m_access); } 30 | void request(boost::shared_ptr request, Access access); 31 | 32 | private: 33 | Access m_access; 34 | }; 35 | 36 | }}} 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /mordor/iomanager.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_IOMANAGER_H__ 2 | #define __MORDOR_IOMANAGER_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "version.h" 6 | 7 | #ifdef WINDOWS 8 | #include "iomanager_iocp.h" 9 | #elif defined(LINUX) 10 | #include "iomanager_epoll.h" 11 | #elif defined(BSD) 12 | #include "iomanager_kqueue.h" 13 | #else 14 | #error Unsupported Platform 15 | #endif 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /mordor/iomanager_epoll.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_IOMANAGER_EPOLL_H__ 2 | #define __MORDOR_IOMANAGER_EPOLL_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "scheduler.h" 6 | #include "timer.h" 7 | #include "version.h" 8 | 9 | #ifndef LINUX 10 | #error IOManagerEPoll is Linux only 11 | #endif 12 | 13 | namespace Mordor { 14 | 15 | class Fiber; 16 | 17 | class IOManager : public Scheduler, public TimerManager 18 | { 19 | public: 20 | enum Event { 21 | NONE = 0x0000, 22 | READ = 0x0001, 23 | WRITE = 0x0004, 24 | CLOSE = 0x2000 25 | }; 26 | 27 | private: 28 | struct AsyncState : boost::noncopyable 29 | { 30 | AsyncState(); 31 | ~AsyncState(); 32 | 33 | struct EventContext 34 | { 35 | EventContext() : scheduler(NULL) {} 36 | Scheduler *scheduler; 37 | boost::shared_ptr fiber; 38 | boost::function dg; 39 | }; 40 | 41 | EventContext &contextForEvent(Event event); 42 | bool triggerEvent(Event event, size_t &pendingEventCount); 43 | void resetContext(EventContext &); 44 | 45 | int m_fd; 46 | EventContext m_in, m_out, m_close; 47 | Event m_events; 48 | boost::mutex m_mutex; 49 | 50 | private: 51 | void asyncResetContext(EventContext&); 52 | }; 53 | 54 | public: 55 | /// @param autoStart whether call the start() automatically in constructor 56 | /// @note @p autoStart provides a more friendly behavior for derived class 57 | /// that inherits from IOManager 58 | IOManager(size_t threads = 1, bool useCaller = true, bool autoStart = true, size_t batchSize = 1); 59 | ~IOManager(); 60 | 61 | bool stopping(); 62 | 63 | void registerEvent(int fd, Event events, 64 | boost::function dg = NULL); 65 | /// Will not cause the event to fire 66 | /// @return If the event was successfully unregistered before firing normally 67 | bool unregisterEvent(int fd, Event events); 68 | /// Will cause the event to fire 69 | bool cancelEvent(int fd, Event events); 70 | 71 | protected: 72 | bool stopping(unsigned long long &nextTimeout); 73 | void idle(); 74 | void tickle(); 75 | 76 | void onTimerInsertedAtFront() { tickle(); } 77 | 78 | private: 79 | int m_epfd; 80 | int m_tickleFds[2]; 81 | size_t m_pendingEventCount; 82 | boost::mutex m_mutex; 83 | std::vector m_pendingEvents; 84 | }; 85 | 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /mordor/iomanager_kqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_IOMANAGER_EPOLL_H__ 2 | #define __MORDOR_IOMANAGER_EPOLL_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include "scheduler.h" 11 | #include "timer.h" 12 | #include "version.h" 13 | 14 | #ifndef BSD 15 | #error IOManagerKQueue is BSD only 16 | #endif 17 | 18 | namespace Mordor { 19 | 20 | class IOManager : public Scheduler, public TimerManager 21 | { 22 | public: 23 | enum Event { 24 | READ, 25 | WRITE, 26 | CLOSE 27 | }; 28 | 29 | private: 30 | struct AsyncEvent 31 | { 32 | struct kevent event; 33 | 34 | Scheduler *m_scheduler, *m_schedulerClose; 35 | boost::shared_ptr m_fiber, m_fiberClose; 36 | boost::function m_dg, m_dgClose; 37 | }; 38 | 39 | public: 40 | IOManager(size_t threads = 1, bool useCaller = true, bool autoStart = true); 41 | ~IOManager(); 42 | 43 | bool stopping(); 44 | 45 | void registerEvent(int fd, Event events, boost::function dg = NULL); 46 | void cancelEvent(int fd, Event events); 47 | void unregisterEvent(int fd, Event events); 48 | 49 | protected: 50 | bool stopping(unsigned long long &nextTimeout); 51 | void idle(); 52 | void tickle(); 53 | 54 | void onTimerInsertedAtFront() { tickle(); } 55 | 56 | private: 57 | int m_kqfd; 58 | int m_tickleFds[2]; 59 | std::map, AsyncEvent> m_pendingEvents; 60 | boost::mutex m_mutex; 61 | }; 62 | 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /mordor/libmordor.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libmordor 7 | Description: High performance I/O library based on fibers 8 | Requires: z ssl 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -lmordor 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /mordor/libmordorprotobuf.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libmordorprotobuf 7 | Description: Google Protobuf parsing support for libmordor 8 | Requires: mordor protobuf 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -lmordorprotobuf 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /mordor/libmordoryaml.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libmordoryaml 7 | Description: YAML parsing support for libmordor 8 | Requires: mordor yaml 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -lmordoryaml 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /mordor/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "main.h" 4 | 5 | #ifdef WINDOWS 6 | namespace Mordor { 7 | 8 | char **CommandLineToUtf8(int argc, wchar_t **argvW) 9 | { 10 | DWORD totalLength = (argc + 1) * sizeof(char *); 11 | DWORD wcFlags = WC_ERR_INVALID_CHARS; 12 | for (int i = 0; i < argc; ++i) { 13 | int ret = WideCharToMultiByte(CP_UTF8, wcFlags, argvW[i], -1, NULL, 0, NULL, NULL); 14 | if (ret == 0 && GetLastError() == ERROR_INVALID_FLAGS) { 15 | wcFlags = 0; 16 | ret = WideCharToMultiByte(CP_UTF8, wcFlags, argvW[i], -1, NULL, 0, NULL, NULL); 17 | } 18 | if (ret == 0) 19 | return NULL; 20 | totalLength += ret; 21 | } 22 | char **result = (char **)LocalAlloc(LMEM_FIXED, totalLength); 23 | if (!result) 24 | return NULL; 25 | char *strings = (char *)result + (argc + 1) * sizeof(char *); 26 | totalLength -= (argc + 1) * sizeof(char *); 27 | for (int i = 0; i < argc; ++i) { 28 | result[i] = strings; 29 | int ret = WideCharToMultiByte(CP_UTF8, wcFlags, argvW[i], -1, strings, 30 | totalLength, NULL, NULL); 31 | if (ret == 0) { 32 | LocalFree(result); 33 | return NULL; 34 | } 35 | strings += ret; 36 | totalLength -= ret; 37 | } 38 | result[argc] = NULL; 39 | return result; 40 | } 41 | 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /mordor/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_MAIN_H__ 2 | #define __MORDOR_MAIN_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include "version.h" 6 | 7 | #ifdef WINDOWS 8 | 9 | #include 10 | 11 | namespace Mordor { 12 | /// @return argv array in UTF-8. Caller should free with LocalFree when it is 13 | /// no longer needed 14 | char **CommandLineToUtf8(int argc, wchar_t **argv); 15 | } 16 | /// Defines main in a cross-platform way, ensuring UTF-8 for argv 17 | /// @example 18 | /// MORDOR_MAIN(int argc, char **argv) 19 | /// { 20 | /// return 0; 21 | /// } 22 | #define MORDOR_MAIN(argctype, argvtype) \ 23 | static int utf8main(argctype, argvtype); \ 24 | extern "C" int main(int argc, char *argv[]) \ 25 | { \ 26 | LPWSTR lpCmdLineW = GetCommandLineW(); \ 27 | int localArgc = 0; \ 28 | LPWSTR *argvW = CommandLineToArgvW(lpCmdLineW, &localArgc); \ 29 | if (!argvW) \ 30 | return GetLastError(); \ 31 | char **argvUtf8 = CommandLineToUtf8(localArgc, argvW); \ 32 | LocalFree(argvW); \ 33 | if (!argvUtf8) \ 34 | return GetLastError(); \ 35 | int result = utf8main(localArgc, argvUtf8); \ 36 | LocalFree(argvUtf8); \ 37 | return result; \ 38 | } \ 39 | static int utf8main(argctype, argvtype) 40 | #else 41 | #define MORDOR_MAIN(argc, argv) \ 42 | int main(argc, argv) 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /mordor/mordorprotobuf.v12.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /mordor/mordorprotobuf.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /mordor/mordoryaml.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /mordor/openssl_lock.cpp: -------------------------------------------------------------------------------- 1 | #include "openssl_lock.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #ifndef USE_FIBER_MUTEX 9 | #include 10 | #else 11 | #include "fibersynchronization.h" 12 | #endif 13 | 14 | #include "fiber.h" 15 | 16 | namespace { 17 | 18 | // Convenient function to store a pointer into integer. 19 | // - Specially handles that if the `T' type is not large enough to 20 | // hold the pointer 21 | // 22 | // NOTE: On any platform, only one of following two template functions will be 23 | // enabled. And the first one is applicable on most platform. 24 | template 25 | typename boost::enable_if_c= sizeof(void *), T>::type 26 | pointer2integer(void * p) { return (T) p; } 27 | 28 | template 29 | typename boost::enable_if_c::type 30 | pointer2integer(void *p) 31 | { 32 | static const T mask = (T) -1; 33 | uintptr_t x = (uintptr_t) p; 34 | return (x & mask) ^ (x >> (sizeof(T) << 3)); 35 | } 36 | 37 | } 38 | 39 | namespace Mordor { 40 | 41 | OpensslLockManager & 42 | OpensslLockManager::instance() 43 | { 44 | static OpensslLockManager s; 45 | return s; 46 | } 47 | 48 | OpensslLockManager::OpensslLockManager() 49 | : m_locks(CRYPTO_num_locks()) 50 | , m_initialized(false) 51 | { 52 | for (Locks::iterator it = m_locks.begin(); it != m_locks.end(); ++it) 53 | (*it).reset(new LockType); 54 | } 55 | 56 | OpensslLockManager::~OpensslLockManager() 57 | { 58 | if (m_initialized) 59 | uninstallLockCallBacks(); 60 | m_locks.clear(); 61 | } 62 | 63 | void 64 | OpensslLockManager::installLockCallbacks() 65 | { 66 | CRYPTO_set_locking_callback(OpensslLockManager::locking_function); 67 | CRYPTO_set_id_callback(OpensslLockManager::id); 68 | m_initialized = true; 69 | } 70 | 71 | void 72 | OpensslLockManager::uninstallLockCallBacks() 73 | { 74 | m_initialized = false; 75 | CRYPTO_set_locking_callback(0); 76 | CRYPTO_set_id_callback(0); 77 | } 78 | 79 | void 80 | OpensslLockManager::locking_function(int mode, int n, const char *file, int line) 81 | { 82 | instance().locking(mode, n, file, line); 83 | } 84 | 85 | void 86 | OpensslLockManager::locking(int mode, int n, const char *file, int line) 87 | { 88 | if (mode & CRYPTO_LOCK) 89 | m_locks[n]->lock(); 90 | else 91 | m_locks[n]->unlock(); 92 | } 93 | 94 | unsigned long 95 | OpensslLockManager::id() 96 | { 97 | return pointer2integer(Mordor::Fiber::getThis().get()); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /mordor/openssl_lock.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_OPENSSL_LOCK_H__ 2 | #define __MORDOR_OPENSSL_LOCK_H__ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #ifndef USE_FIBER_MUTEX 10 | namespace boost { 11 | class mutex; 12 | } 13 | #else 14 | namespace Mordor { 15 | class FiberMutex; 16 | } 17 | #endif 18 | 19 | namespace Mordor { 20 | 21 | class OpensslLockManager : public boost::noncopyable 22 | { 23 | public: 24 | #ifndef USE_FIBER_MUTEX 25 | typedef boost::mutex LockType; 26 | #else 27 | typedef Mordor::FiberMutex LockType; 28 | #endif 29 | 30 | static OpensslLockManager & instance(); 31 | static unsigned long id(); 32 | static void locking_function(int mode, int n, const char *file, int line); 33 | 34 | void installLockCallbacks(); 35 | void uninstallLockCallBacks(); 36 | 37 | protected: 38 | typedef std::vector > Locks; 39 | 40 | OpensslLockManager(); 41 | ~OpensslLockManager(); 42 | 43 | void locking(int mode, int n, const char * file, int line); 44 | 45 | protected: 46 | std::vector > m_locks; 47 | bool m_initialized; 48 | }; 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /mordor/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "mordor/pch.h" -------------------------------------------------------------------------------- /mordor/pq/connectionpool.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PQ_CONNECTIONPOOL_H__ 2 | #define __MORDOR_PQ_CONNECTIONPOOL_H__ 3 | 4 | #include 5 | 6 | #include 7 | 8 | #include "mordor/fibersynchronization.h" 9 | 10 | namespace Mordor { 11 | 12 | class IOManager; 13 | 14 | namespace PQ { 15 | 16 | class Connection; 17 | 18 | class ConnectionPool : boost::noncopyable { 19 | public: 20 | typedef boost::shared_ptr ptr; 21 | 22 | /// Constructor of ConnectionPool 23 | /// @param conninfo db connect string 24 | /// @param iomanager IO manager 25 | /// @param size pool size, 5 by default 26 | /// @param idleTolerance re-connect interval(in us) for idle 27 | /// connection, disable re-connect by setting it to 0 28 | ConnectionPool(const std::string &conninfo, IOManager *iomanager, 29 | size_t size = 5, unsigned long long idleTolerance = 0); 30 | ~ConnectionPool(); 31 | boost::shared_ptr getConnection(); 32 | void resize(size_t num); 33 | 34 | private: 35 | void releaseConnection(Mordor::PQ::Connection* conn); 36 | bool connectionExpired(unsigned long long freeTime) const; 37 | 38 | private: 39 | std::list > m_busyConnections; 40 | 41 | /// @note element of the free list is pair of connection and a timestamp, the 42 | /// timestamp indicates that when the connection was put into the free list. 43 | // Before re-using any connection in the free list, should use the timestamp 44 | // to calculate wheter the connection has been idle for too long, if so should 45 | // re-connect it. 46 | std::list, unsigned long long> > m_freeConnections; 48 | std::string m_conninfo; 49 | IOManager *m_iomanager; 50 | FiberMutex m_mutex; 51 | FiberCondition m_condition; 52 | size_t m_total; 53 | unsigned long long m_idleTolerance; 54 | }; 55 | 56 | }} 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /mordor/pq/libmordorpq.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libmordorpq 7 | Description: High performance postgresql library based on mordor fibers 8 | Requires: pq mordor 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -lmordorpq 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /mordor/pq/mordorpq.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | -------------------------------------------------------------------------------- /mordor/pq/result.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PQ_RESULT_H__ 2 | #define __MORDOR_PQ_RESULT_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Mordor { 10 | namespace PQ { 11 | 12 | class Connection; 13 | class PreparedStatement; 14 | 15 | class Result 16 | { 17 | friend class Connection; 18 | friend class PreparedStatement; 19 | private: 20 | Result(boost::shared_ptr result) 21 | : m_result(result) 22 | {} 23 | 24 | public: 25 | Result() {} 26 | 27 | public: 28 | size_t rows() const; 29 | size_t columns() const; 30 | 31 | size_t column(const char *name) const; 32 | size_t column(const std::string &name) const 33 | { return column(name.c_str()); } 34 | 35 | Oid getType(size_t column) const; 36 | Oid getType(const char *col) const 37 | { return getType(column(col)); } 38 | Oid getType(const std::string &col) const 39 | { return getType(column(col)); } 40 | 41 | bool getIsNull(size_t row, size_t column) const; 42 | bool getIsNull(size_t row, const char *col) const 43 | { return getIsNull(row, column(col)); } 44 | bool getIsNull(size_t row, const std::string &col) const 45 | { return getIsNull(row, column(col)); } 46 | 47 | /// Get the value of a cell 48 | /// 49 | /// Supported overloads: 50 | /// * std::string (bytea, text, ) 51 | /// * const char * (bytea, text, ) 52 | /// * bool (boolean) 53 | /// * char (char) 54 | /// * long long (bigint) 55 | /// * short (smallint) 56 | /// * int (integer) 57 | /// * float (real) 58 | /// * double (double precision) 59 | /// * boost::posix_time::ptime (timestamp) 60 | /// * std::vector (integer[]) 61 | /// * std::pair (inet, cidr) 62 | /// * IPAddress::ptr (inet, cidr) 63 | /// @note Except for the string overloads, these will all ASSERT if the 64 | /// value is NULL. Additionally, the integer[] will also ASSERT if 65 | /// any of the values within the array are NULL. 66 | template T get(size_t row, size_t column) const; 67 | template T get(size_t row, const char* col) const 68 | { return get(row, column(col)); } 69 | template T get(size_t row, const std::string & col) const 70 | { return get(row, column(col)); } 71 | 72 | private: 73 | boost::shared_ptr m_result; 74 | }; 75 | 76 | 77 | }} 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /mordor/pq/tests/.gitignore: -------------------------------------------------------------------------------- 1 | run_tests 2 | -------------------------------------------------------------------------------- /mordor/pq/tests/pqtests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /mordor/pq/transaction.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PQ_TRANSACTION_H__ 2 | #define __MORDOR_PQ_TRANSACTION_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | namespace Mordor { 6 | namespace PQ { 7 | 8 | class Connection; 9 | 10 | struct Transaction 11 | { 12 | public: 13 | enum IsolationLevel 14 | { 15 | DEFAULT, 16 | SERIALIZABLE, 17 | REPEATABLE_READ = SERIALIZABLE, 18 | READ_COMMITTED, 19 | READ_UNCOMMITTED = READ_COMMITTED 20 | }; 21 | enum Mode 22 | { 23 | READ_WRITE, 24 | READ_ONLY 25 | }; 26 | 27 | public: 28 | Transaction(Connection &connection, IsolationLevel isolationLevel 29 | = DEFAULT); 30 | Transaction(Connection &connection, IsolationLevel isolationLevel, 31 | Mode mode); 32 | ~Transaction(); 33 | 34 | void commit(); 35 | void rollback(); 36 | 37 | private: 38 | Connection &m_connection; 39 | bool m_active; 40 | }; 41 | 42 | }} 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /mordor/predef.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PREDEF_H__ 2 | #define __MORDOR_PREDEF_H__ 3 | 4 | #include "version.h" 5 | 6 | #ifdef WINDOWS 7 | // Get Win7+ APIs 8 | #ifndef _WIN32_WINNT 9 | #define _WIN32_WINNT 0x0601 10 | #endif 11 | 12 | // Don't include tons of crap from windows.h 13 | #define WIN32_LEAN_AND_MEAN 14 | // Define this so security.h works 15 | #define SECURITY_WIN32 16 | // Shut up, CRT 17 | #ifndef _CRT_SECURE_NO_WARNINGS 18 | #define _CRT_SECURE_NO_WARNINGS 19 | #endif 20 | #ifndef _CRT_NONSTDC_NO_WARNINGS 21 | #define _CRT_NONSTDC_NO_WARNINGS 22 | #endif 23 | #ifndef _SCL_SECURE_NO_WARNINGS 24 | #define _SCL_SECURE_NO_WARNINGS 25 | #endif 26 | 27 | // Use more common names for functions 28 | // (cross-platform 64-bit, strip the underscores) 29 | #define atoll _atoi64 30 | #define strtoll _strtoi64 31 | #define strtoull _strtoui64 32 | #if !defined(strnicmp) 33 | #define strnicmp _strnicmp 34 | #endif 35 | #define mkdir _mkdir 36 | #define snprintf _snprintf 37 | 38 | #include 39 | #define WIN32_NO_STATUS 40 | #include 41 | // define the PSAPI_VERSION to 1 so that we can still run on old XP systems 42 | // The specific function that was failing fo kalypso was GetModuleName 43 | /* http://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=vs.85).aspx */ 44 | #define PSAPI_VERSION (1) 45 | 46 | // 'inet_addr' is deprecated but will break xp machines if we replace it. 47 | // Use inet_pton() or InetPton() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings 48 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 49 | 50 | #include 51 | 52 | // Take things out of the preprocessor, and put into the global namespace 53 | // From WinGDI.h: #define ERROR 0 54 | #ifdef ERROR 55 | #undef ERROR 56 | enum { 57 | ERROR = 0 58 | }; 59 | #endif 60 | 61 | // From WinNT.h: #define DELETE (0x00010000L) 62 | #ifdef DELETE 63 | #undef DELETE 64 | enum { 65 | DELETE = (0x00010000L) 66 | }; 67 | #endif 68 | 69 | #else 70 | #ifdef LINUX 71 | #include 72 | 73 | #ifdef major 74 | #undef major 75 | #endif 76 | #ifdef minor 77 | #undef minor 78 | #endif 79 | #endif 80 | 81 | #ifndef stricmp 82 | #define stricmp(a,b) strcasecmp(a,b) 83 | #endif 84 | #ifndef strnicmp 85 | #define strnicmp(a,b,c) strncasecmp(a,b,c) 86 | #endif 87 | 88 | #endif 89 | 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /mordor/protoc.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | Midl 6 | CustomBuild 7 | 8 | 9 | _SelectedFiles;$(ProtocDependsOn) 11 | 12 | 13 | 14 | $(IntDir) 15 | protoc.exe [AllOptions] [AdditionalOptions] --error_format=msvs [inputs] 16 | %(CppOutDir)%(Filename).pb.cc;%(CppOutDir)%(Filename).pb.h 17 | Compiling protobuf: [inputs] 18 | 19 | 20 | -------------------------------------------------------------------------------- /mordor/ragel.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_RAGEL_H__ 2 | #define __MORDOR_RAGEL_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace Mordor { 12 | 13 | struct Buffer; 14 | class Stream; 15 | 16 | class RagelParser 17 | { 18 | public: 19 | virtual ~RagelParser() {} 20 | 21 | // Complete parsing 22 | size_t run(const void *buffer, size_t length); 23 | size_t run(const char *string); 24 | size_t run(const std::string &string); 25 | size_t run(const Buffer &buffer); 26 | unsigned long long run(Stream &stream); 27 | unsigned long long run(boost::shared_ptr stream) { return run(*stream); } 28 | 29 | // Partial parsing 30 | virtual void init(); 31 | size_t run(const void *buffer, size_t length, bool isEof); 32 | 33 | virtual bool complete() const { return final(); } 34 | virtual bool final() const = 0; 35 | virtual bool error() const = 0; 36 | 37 | protected: 38 | virtual void exec() = 0; 39 | 40 | virtual const char *earliestPointer() const; 41 | virtual void adjustPointers(ptrdiff_t offset); 42 | 43 | protected: 44 | // Ragel state 45 | int cs; 46 | const char *p, *pe, *eof, *mark; 47 | std::string m_fullString; 48 | }; 49 | 50 | class RagelParserWithStack : public RagelParser 51 | { 52 | protected: 53 | void prepush(); 54 | void postpop(); 55 | 56 | protected: 57 | // Ragel state 58 | std::vector stack; 59 | size_t top; 60 | }; 61 | 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /mordor/ragel.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | Midl 6 | CustomBuild 7 | 8 | 9 | _SelectedFiles;$(RagelDependsOn) 11 | 12 | 13 | 14 | false 15 | false 16 | false 17 | false 18 | false 19 | $(IntDir)%(Filename).cpp 20 | 0 21 | 0 22 | 0 23 | ragel.exe [AllOptions] [AdditionalOptions] --error-format=msvc [inputs] 24 | %(OutputFileName) 25 | Generating finite state machines: [inputs] 26 | 27 | 28 | -------------------------------------------------------------------------------- /mordor/semaphore.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SEMAPHORE_H__ 2 | #define __MORDOR_SEMAPHORE_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "version.h" 6 | 7 | #include 8 | 9 | #ifdef WINDOWS 10 | #include 11 | #elif defined(OSX) 12 | #include 13 | #elif defined(FREEBSD) 14 | #else 15 | #include 16 | #endif 17 | 18 | namespace Mordor { 19 | 20 | class Semaphore : boost::noncopyable 21 | { 22 | public: 23 | Semaphore(unsigned int count = 0); 24 | ~Semaphore(); 25 | 26 | void wait(); 27 | 28 | void notify(); 29 | 30 | private: 31 | #ifdef WINDOWS 32 | HANDLE m_semaphore; 33 | #elif defined(OSX) 34 | task_t m_task; 35 | semaphore_t m_semaphore; 36 | #elif defined(FREEBSD) 37 | int m_semaphore; 38 | #else 39 | sem_t m_semaphore; 40 | #endif 41 | }; 42 | 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /mordor/sleep.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "sleep.h" 6 | 7 | #include "assert.h" 8 | #include "fiber.h" 9 | #include "scheduler.h" 10 | #include "timer.h" 11 | 12 | namespace Mordor { 13 | 14 | static void scheduleMe(Scheduler *scheduler, Fiber::ptr fiber) 15 | { 16 | scheduler->schedule(fiber); 17 | } 18 | 19 | void 20 | sleep(TimerManager &timerManager, unsigned long long us) 21 | { 22 | MORDOR_ASSERT(Scheduler::getThis()); 23 | timerManager.registerTimer(us, 24 | boost::bind(&scheduleMe, Scheduler::getThis(), Fiber::getThis())); 25 | Scheduler::yieldTo(); 26 | } 27 | 28 | void 29 | sleep(unsigned long long us) 30 | { 31 | #ifdef WINDOWS 32 | Sleep((DWORD)(us / 1000)); 33 | #else 34 | struct timespec ts; 35 | ts.tv_sec = us / 1000000; 36 | ts.tv_nsec = (us % 1000000) * 1000; 37 | while (true) { 38 | if (nanosleep(&ts, &ts) == -1) { 39 | if (errno == EINTR) 40 | continue; 41 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("nanosleep"); 42 | } 43 | break; 44 | } 45 | #endif 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /mordor/sleep.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SLEEP_H__ 2 | #define __MORDOR_SLEEP_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | namespace Mordor { 6 | 7 | class TimerManager; 8 | 9 | /// Suspend execution of the current thread 10 | /// @note This is a normal sleep, and will block the current thread 11 | /// @param us How long to sleep, in microseconds 12 | void sleep(unsigned long long us); 13 | 14 | /// Suspend execution of the current Fiber 15 | /// @note This will use the TimerManager to yield the current Fiber and allow 16 | /// other Fibers to run until this Fiber is ready to run again. 17 | /// @param timerManager The TimerManager (typically an IOManager) to use to 18 | /// to control this sleep 19 | /// @param us How long to sleep, in microseconds 20 | /// @pre Scheduler::getThis() != NULL 21 | void sleep(TimerManager &timerManager, unsigned long long us); 22 | 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /mordor/socks.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SOCKS_H__ 2 | #define __MORDOR_SOCKS_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "mordor/exception.h" 8 | 9 | namespace Mordor { 10 | 11 | struct IPAddress; 12 | class Stream; 13 | struct URI; 14 | 15 | namespace HTTP { 16 | 17 | class StreamBroker; 18 | 19 | } 20 | 21 | namespace SOCKS { 22 | 23 | struct Exception : virtual Mordor::Exception {}; 24 | struct ProtocolViolationException : virtual Exception {}; 25 | struct NoAcceptableAuthenticationMethodException : virtual Exception {}; 26 | struct InvalidResponseException : virtual Exception 27 | { 28 | InvalidResponseException(unsigned char status) 29 | : m_status(status) 30 | {} 31 | 32 | unsigned char status() const { return m_status; } 33 | private: 34 | unsigned char m_status; 35 | }; 36 | 37 | boost::shared_ptr tunnel(boost::shared_ptr streamBroker, 38 | const URI &proxy, boost::shared_ptr targetIP, 39 | const std::string &targetDomain = std::string(), 40 | unsigned short targetPort = 0, 41 | unsigned char version = 5); 42 | 43 | }} 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /mordor/statistics.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "statistics.h" 4 | 5 | #include "atomic.h" 6 | #include "timer.h" 7 | 8 | namespace Mordor { 9 | 10 | Statistic *Statistics::lookup(const std::string &name) 11 | { 12 | StatisticsCache::const_iterator it = stats().find(name); 13 | if (it == stats().end()) { 14 | return NULL; 15 | } else { 16 | return it->second.second.get(); 17 | } 18 | } 19 | 20 | static std::ostream & 21 | dump(std::ostream &os, const Statistic &stat, int level = 0) 22 | { 23 | std::string indent(level++ * 4, ' '); 24 | os << indent << typeid(stat).name() << ": " << stat; 25 | if (stat.units) 26 | os << " " << stat.units; 27 | os << std::endl; 28 | const Statistic *substat = stat.begin(); 29 | while (substat) { 30 | dump(os, *substat, level); 31 | substat = stat.next(substat); 32 | } 33 | return os; 34 | } 35 | 36 | void 37 | Statistic::dump(std::ostream &os) 38 | { 39 | Mordor::dump(os, *this); 40 | } 41 | 42 | std::ostream & 43 | Statistics::dump(std::ostream &os) 44 | { 45 | for (StatisticsCache::const_iterator it = statistics().begin(); 46 | it != statistics().end(); 47 | ++it) { 48 | os << it->first; 49 | if (!it->second.first.empty()) 50 | os << " (" << it->second.first << ")"; 51 | os << ": "; 52 | Mordor::dump(os, *it->second.second.get()); 53 | } 54 | return os; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /mordor/streams/buffered.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_BUFFERED_STREAM_H__ 2 | #define __MORDOR_BUFFERED_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "buffer.h" 6 | #include "filter.h" 7 | 8 | namespace Mordor { 9 | 10 | /* NOTE: 11 | * In current implementation, BufferedStream inherits parent stream's 12 | * read-write thread-safe ability only when parent stream is seekless. 13 | * Problem: 14 | * When parent stream is seekable, read() operation will operate both 15 | * m_readBuffer and m_writeBuffer, and so does write(). Read-write 16 | * thread-safe ability can't be held anymore inside BufferedStream itself. 17 | * TODO: 18 | * enhance the implementaton to allow BufferedStream inherits parent stream's 19 | * read-write thread-safe ability also for seekable stream. 20 | */ 21 | class BufferedStream : public FilterStream 22 | { 23 | public: 24 | typedef boost::shared_ptr ptr; 25 | 26 | BufferedStream(Stream::ptr parent, bool own = true); 27 | 28 | size_t bufferSize() { return m_bufferSize; } 29 | void bufferSize(size_t bufferSize) { m_bufferSize = bufferSize; } 30 | 31 | bool allowPartialReads() { return m_allowPartialReads; } 32 | void allowPartialReads(bool allowPartialReads) { m_allowPartialReads = allowPartialReads; } 33 | 34 | bool flushMultiplesOfBuffer() { return m_flushMultiplesOfBuffer; } 35 | void flushMultiplesOfBuffer(bool flushMultiplesOfBuffer ) { m_flushMultiplesOfBuffer = flushMultiplesOfBuffer; } 36 | 37 | bool supportsFind() { return supportsRead(); } 38 | bool supportsUnread() { return supportsRead() && (!supportsWrite() || !supportsSeek()); } 39 | 40 | void close(CloseType type = BOTH); 41 | size_t read(Buffer &buffer, size_t length); 42 | size_t read(void *buffer, size_t length); 43 | size_t write(const Buffer &buffer, size_t length); 44 | size_t write(const void *buffer, size_t length); 45 | long long seek(long long offset, Anchor anchor = BEGIN); 46 | long long size(); 47 | void truncate(long long size); 48 | void flush(bool flushParent = true); 49 | ptrdiff_t find(char delim, size_t sanitySize = ~0, bool throwIfNotFound = true); 50 | ptrdiff_t find(const std::string &str, size_t sanitySize = ~0, bool throwIfNotFound = true); 51 | void unread(const Buffer &b, size_t len = ~0); 52 | 53 | private: 54 | template size_t readInternal(T &buffer, size_t length); 55 | size_t flushWrite(size_t length); 56 | 57 | private: 58 | size_t m_bufferSize; 59 | bool m_allowPartialReads, m_flushMultiplesOfBuffer; 60 | Buffer m_readBuffer, m_writeBuffer; 61 | }; 62 | 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /mordor/streams/cat.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_CAT_STREAM__ 2 | #define __MORDOR_CAT_STREAM__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "stream.h" 8 | 9 | namespace Mordor { 10 | 11 | class CatStream : public Stream 12 | { 13 | public: 14 | CatStream(const std::vector &streams); 15 | 16 | bool supportsRead() { return true; } 17 | bool supportsSeek() { return m_seekable; } 18 | bool supportsTell() { return true; } 19 | bool supportsSize() { return m_size != -1ll; } 20 | 21 | using Stream::read; 22 | size_t read(Buffer &buffer, size_t length); 23 | 24 | long long seek(long long offset, Anchor anchor = BEGIN); 25 | long long size(); 26 | 27 | private: 28 | std::vector m_streams; 29 | std::vector::iterator m_it; 30 | bool m_seekable; 31 | long long m_size; 32 | long long m_pos; 33 | }; 34 | 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /mordor/streams/counter.cpp: -------------------------------------------------------------------------------- 1 | #include "counter.h" 2 | 3 | namespace Mordor { 4 | 5 | size_t 6 | CounterStream::read(Buffer &b, size_t len) 7 | { 8 | size_t ret = parent()->read(b, len); 9 | m_read += ret; 10 | return ret; 11 | } 12 | 13 | size_t 14 | CounterStream::write(const Buffer &b, size_t len) 15 | { 16 | size_t ret = parent()->write(b, len); 17 | m_written += ret; 18 | return ret; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /mordor/streams/counter.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_COUNTER_STREAM_H__ 2 | #define __MORDOR_COUNTER_STREAM_H__ 3 | 4 | #include "filter.h" 5 | 6 | namespace Mordor { 7 | 8 | class CounterStream : public FilterStream 9 | { 10 | public: 11 | typedef boost::shared_ptr ptr; 12 | 13 | public: 14 | CounterStream(Stream::ptr parent, bool own = true) 15 | : FilterStream(parent, own) 16 | , m_read(0) 17 | , m_written(0) 18 | {} 19 | 20 | using FilterStream::read; 21 | size_t read(Buffer &, size_t); 22 | using FilterStream::write; 23 | size_t write(const Buffer &, size_t); 24 | 25 | unsigned long long bytesRead() const { return m_read; } 26 | unsigned long long bytesWritten() const { return m_written; } 27 | 28 | private: 29 | unsigned long long m_read, m_written; 30 | }; 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /mordor/streams/deflate.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_DEFLATE_STREAM_H__ 2 | #define __MORDOR_DEFLATE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "zlib.h" 6 | 7 | namespace Mordor { 8 | 9 | class DeflateStream : public ZlibStream 10 | { 11 | public: 12 | DeflateStream(Stream::ptr parent, int level, int windowBits, int memlevel, Strategy strategy, bool own = true, bool invert = false) 13 | : ZlibStream(parent, own, DEFLATE, level, windowBits, memlevel, strategy, invert) 14 | {} 15 | 16 | DeflateStream(Stream::ptr parent, bool own = true, bool invert = false) 17 | : ZlibStream(parent, own, DEFLATE, Z_DEFAULT_COMPRESSION, 15, 8, DEFAULT, invert) 18 | {} 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /mordor/streams/delay.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_DELAY_STREAM_H_ 2 | #define __MORDOR_DELAY_STREAM_H_ 3 | 4 | #include "mordor/sleep.h" 5 | #include "mordor/streams/filter.h" 6 | 7 | namespace Mordor { 8 | 9 | /// Helper stream for unittest to force delay r/w. 10 | class DelayStream: public FilterStream 11 | { 12 | public: 13 | typedef boost::shared_ptr ptr; 14 | 15 | DelayStream(Stream::ptr parent, TimerManager * mgr = NULL, 16 | unsigned long long delay = 0ull, bool own = true): 17 | FilterStream(parent, own), 18 | m_delay(delay), 19 | m_p_mgr(mgr) 20 | {} 21 | 22 | using FilterStream::read; 23 | size_t read(Buffer &buffer, size_t length) 24 | { 25 | delay(); 26 | return parent()->read(buffer, length); 27 | } 28 | 29 | using FilterStream::write; 30 | size_t write(const Buffer &buffer, size_t length) 31 | { 32 | delay(); 33 | return parent()->write(buffer, length); 34 | } 35 | 36 | protected: 37 | void delay() 38 | { 39 | if (m_delay > 0) { 40 | if (m_p_mgr) 41 | Mordor::sleep(*m_p_mgr, m_delay); 42 | else 43 | Mordor::sleep(m_delay); 44 | } 45 | } 46 | 47 | private: 48 | unsigned long long m_delay; 49 | TimerManager * m_p_mgr; 50 | }; 51 | 52 | } 53 | #endif 54 | -------------------------------------------------------------------------------- /mordor/streams/efs.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_EFS_STREAM__ 2 | #define __MORDOR_EFS_STREAM__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | 7 | namespace Mordor { 8 | 9 | class Fiber; 10 | 11 | class EFSStream : public Stream 12 | { 13 | public: 14 | EFSStream(void *context, bool read = true, bool ownContext = true); 15 | EFSStream(const char *filename, bool read = true); 16 | EFSStream(const wchar_t *filename, bool read = true); 17 | EFSStream(const std::string &filename, bool read = true); 18 | EFSStream(const std::wstring &filename, bool read = true); 19 | ~EFSStream(); 20 | 21 | bool supportsRead() { return m_read; } 22 | bool supportsWrite() { return !m_read; } 23 | bool supportsSeek() { return m_read; } 24 | 25 | void close(CloseType type = BOTH); 26 | size_t read(Buffer &b, size_t len); 27 | size_t write(const Buffer &b, size_t len); 28 | long long seek(long long offset, Anchor anchor = BEGIN); 29 | 30 | private: 31 | void init(); 32 | void readFiber(); 33 | static DWORD WINAPI ExportCallback(PBYTE pbData, PVOID pvCallbackContext, 34 | ULONG ulLength); 35 | void writeFiber(); 36 | static DWORD WINAPI ImportCallback(PBYTE pbData, PVOID pvCallbackContext, 37 | PULONG ulLength); 38 | 39 | private: 40 | boost::shared_ptr m_fiber; 41 | void *m_context; 42 | bool m_read, m_own; 43 | union { 44 | Buffer *m_readBuffer; 45 | const Buffer *m_writeBuffer; 46 | }; 47 | size_t m_todo; 48 | long long m_pos; 49 | long long m_seekTarget; 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /mordor/streams/fd.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_FD_STREAM_H__ 2 | #define __MORDOR_FD_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | 7 | namespace Mordor { 8 | 9 | class IOManager; 10 | class Scheduler; 11 | 12 | class FDStream : public Stream 13 | { 14 | public: 15 | typedef boost::shared_ptr ptr; 16 | 17 | protected: 18 | FDStream(); 19 | void init(int fd, IOManager *ioManager = NULL, Scheduler *scheduler = NULL, 20 | bool own = true); 21 | public: 22 | FDStream(int fd, IOManager *ioManager = NULL, Scheduler *scheduler = NULL, 23 | bool own = true) 24 | { init(fd, ioManager, scheduler, own); } 25 | ~FDStream(); 26 | 27 | bool supportsRead() { return true; } 28 | bool supportsWrite() { return true; } 29 | bool supportsSeek() { return true; } 30 | bool supportsSize() { return true; } 31 | bool supportsTruncate() { return true; } 32 | 33 | void close(CloseType type = BOTH); 34 | size_t read(Buffer &buffer, size_t length); 35 | size_t read(void *buffer, size_t length); 36 | size_t write(const Buffer &buffer, size_t length); 37 | size_t write(const void *buffer, size_t length); 38 | long long seek(long long offset, Anchor anchor = BEGIN); 39 | long long size(); 40 | void truncate(long long size); 41 | void flush(bool flushParent = true); 42 | 43 | int fd() { return m_fd; } 44 | 45 | private: 46 | IOManager *m_ioManager; 47 | Scheduler *m_scheduler; 48 | int m_fd; 49 | bool m_own; 50 | }; 51 | 52 | typedef FDStream NativeStream; 53 | typedef int NativeHandle; 54 | 55 | } 56 | 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /mordor/streams/file.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_FILE_STREAM_H__ 2 | #define __MORDOR_FILE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "mordor/version.h" 6 | 7 | #ifdef WINDOWS 8 | #include "handle.h" 9 | #else 10 | #include 11 | 12 | #include "fd.h" 13 | #endif 14 | 15 | namespace Mordor { 16 | 17 | class FileStream : public NativeStream 18 | { 19 | public: 20 | typedef boost::shared_ptr ptr; 21 | 22 | #ifdef WINDOWS 23 | enum AccessFlags { 24 | READ = 0x01, 25 | WRITE = 0x02, 26 | READWRITE = 0x03, 27 | APPEND = 0x06, 28 | }; 29 | enum CreateFlags { 30 | OPEN = OPEN_EXISTING, 31 | CREATE = CREATE_NEW, 32 | OPEN_OR_CREATE = OPEN_ALWAYS, 33 | OVERWRITE = TRUNCATE_EXISTING, 34 | OVERWRITE_OR_CREATE = CREATE_ALWAYS, 35 | 36 | DELETE_ON_CLOSE = 0x80000000 37 | }; 38 | #else 39 | enum AccessFlags { 40 | READ = O_RDONLY, 41 | WRITE = O_WRONLY, 42 | READWRITE = O_RDWR, 43 | APPEND = O_APPEND | O_WRONLY 44 | }; 45 | enum CreateFlags { 46 | /// Open a file. Fail if it does not exist. 47 | OPEN = 1, 48 | /// Create a file. Fail if it exists. 49 | CREATE, 50 | /// Open a file. Create it if it does not exist. 51 | OPEN_OR_CREATE, 52 | /// Open a file, and recreate it from scratch. Fail if it does not exist. 53 | OVERWRITE, 54 | /// Create a file. If it exists, recreate it from scratch. 55 | OVERWRITE_OR_CREATE, 56 | 57 | /// Delete the file when it is closed. Can be combined with any of the 58 | /// other options 59 | DELETE_ON_CLOSE = 0x80000000 60 | }; 61 | #endif 62 | 63 | protected: 64 | FileStream(); 65 | void init(const std::string &path, 66 | AccessFlags accessFlags = READWRITE, CreateFlags createFlags = OPEN, 67 | IOManager *ioManager = NULL, Scheduler *scheduler = NULL); 68 | 69 | void setSupportFlags(AccessFlags flags); 70 | void setPath(const std::string & path) { m_path = path; } 71 | 72 | public: 73 | FileStream(const std::string &path, 74 | AccessFlags accessFlags = READWRITE, CreateFlags createFlags = OPEN, 75 | IOManager *ioManager = NULL, Scheduler *scheduler = NULL) 76 | { init(path, accessFlags, createFlags, ioManager, scheduler); } 77 | 78 | bool supportsRead() { return m_supportsRead && NativeStream::supportsRead(); } 79 | bool supportsWrite() { return m_supportsWrite && NativeStream::supportsWrite(); } 80 | bool supportsSeek() { return m_supportsSeek && NativeStream::supportsSeek(); } 81 | 82 | std::string path() const { return m_path; } 83 | 84 | private: 85 | bool m_supportsRead, m_supportsWrite, m_supportsSeek; 86 | std::string m_path; 87 | }; 88 | 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /mordor/streams/filter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "filter.h" 4 | 5 | #include "mordor/assert.h" 6 | 7 | namespace Mordor { 8 | 9 | long long 10 | MutatingFilterStream::seek(long long offset, Anchor anchor) 11 | { 12 | MORDOR_NOTREACHED(); 13 | } 14 | 15 | long long 16 | MutatingFilterStream::size() 17 | { 18 | MORDOR_NOTREACHED(); 19 | } 20 | 21 | void 22 | MutatingFilterStream::truncate(long long size) 23 | { 24 | MORDOR_NOTREACHED(); 25 | } 26 | 27 | ptrdiff_t 28 | MutatingFilterStream::find(char delim, size_t sanitySize, bool throwIfNotFound) 29 | { 30 | MORDOR_NOTREACHED(); 31 | } 32 | 33 | ptrdiff_t 34 | MutatingFilterStream::find(const std::string &str, size_t sanitySize, 35 | bool throwIfNotFound) 36 | { 37 | MORDOR_NOTREACHED(); 38 | } 39 | 40 | void 41 | MutatingFilterStream::unread(const Buffer &b, size_t len) 42 | { 43 | MORDOR_NOTREACHED(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /mordor/streams/gzip.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_GZIP_STREAM_H__ 2 | #define __MORDOR_GZIP_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "zlib.h" 6 | 7 | namespace Mordor { 8 | 9 | class GzipStream : public ZlibStream 10 | { 11 | public: 12 | GzipStream(Stream::ptr parent, int level, int windowBits, int memlevel, Strategy strategy, bool own = true, bool invert = false) 13 | : ZlibStream(parent, own, GZIP, level, windowBits, memlevel, strategy, invert) 14 | {} 15 | 16 | GzipStream(Stream::ptr parent, bool own = true, bool invert = false) 17 | : ZlibStream(parent, own, GZIP, Z_DEFAULT_COMPRESSION, 15, 8, DEFAULT, invert) 18 | {} 19 | }; 20 | 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /mordor/streams/handle.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HANDLE_STREAM_H__ 2 | #define __MORDOR_HANDLE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "mordor/iomanager.h" 8 | #include "stream.h" 9 | 10 | namespace Mordor { 11 | 12 | class HandleStream : public Stream 13 | { 14 | public: 15 | typedef boost::shared_ptr ptr; 16 | 17 | protected: 18 | HandleStream(); 19 | void init(HANDLE hFile, IOManager *ioManager = NULL, 20 | Scheduler *scheduler = NULL, bool own = true); 21 | public: 22 | HandleStream(HANDLE hFile, IOManager *ioManager = NULL, 23 | Scheduler *scheduler = NULL, bool own = true) : 24 | m_maxOpSize(0xffffffff) 25 | { init(hFile, ioManager, scheduler, own); } 26 | ~HandleStream(); 27 | 28 | bool supportsRead() { return true; } 29 | bool supportsWrite() { return true; } 30 | bool supportsCancel(); 31 | bool supportsSeek() { return GetFileType(m_hFile) == FILE_TYPE_DISK; } 32 | bool supportsSize() { return supportsSeek(); } 33 | bool supportsTruncate() { return supportsSeek(); } 34 | 35 | void close(CloseType type = BOTH); 36 | size_t read(void *buffer, size_t length); 37 | void cancelRead(); 38 | size_t write(const void *buffer, size_t length); 39 | void cancelWrite(); 40 | long long seek(long long offset, Anchor anchor = BEGIN); 41 | long long size(); 42 | void truncate(long long size); 43 | void flush(bool flushParent = true); 44 | 45 | HANDLE handle() { return m_hFile; } 46 | 47 | protected: 48 | IOManager *m_ioManager; 49 | bool m_skipCompletionPortOnSuccess; 50 | Scheduler *m_scheduler; 51 | AsyncEvent m_readEvent; 52 | AsyncEvent m_writeEvent; 53 | long long m_pos; 54 | HANDLE m_hFile; 55 | bool m_own, m_cancelRead, m_cancelWrite; 56 | size_t m_maxOpSize; 57 | }; 58 | 59 | typedef HandleStream NativeStream; 60 | typedef HANDLE NativeHandle; 61 | 62 | } 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /mordor/streams/hashfwd.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_HASH_STREAM_FWD_H__ 2 | #define __MORDOR_HASH_STREAM_FWD_H__ 3 | 4 | 5 | namespace Mordor { 6 | class HashStream; 7 | enum HASH_TYPE 8 | { 9 | MD5 = 0, 10 | #ifndef OPENSSL_NO_SHA0 11 | SHA0 = 1, 12 | #endif 13 | #ifndef OPENSSL_NO_SHA1 14 | SHA1 = 2, 15 | #endif 16 | #ifndef OPENSSL_NO_SHA256 17 | SHA224 = 3, 18 | SHA256 = 4, 19 | #endif 20 | #ifndef OPENSSL_NO_SHA512 21 | SHA384 = 5, 22 | SHA512 = 6, 23 | #endif 24 | }; 25 | 26 | template class _HashStream; 27 | #ifndef OPENSSL_NO_SHA0 28 | typedef _HashStream SHA0Stream; 29 | #endif 30 | #ifndef OPENSSL_NO_SHA1 31 | typedef _HashStream SHA1Stream; 32 | #endif 33 | #ifndef OPENSSL_NO_SHA256 34 | typedef _HashStream SHA224Stream; 35 | typedef _HashStream SHA256Stream; 36 | #endif 37 | typedef _HashStream MD5Stream; 38 | 39 | class CRC32Stream; 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /mordor/streams/limited.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "limited.h" 4 | 5 | #include 6 | 7 | #include "mordor/assert.h" 8 | 9 | namespace Mordor { 10 | 11 | LimitedStream::LimitedStream(Stream::ptr parent, long long size, bool own) 12 | : MutatingFilterStream(parent, own), 13 | m_pos(0), 14 | m_size(size), 15 | m_strict(false) 16 | { 17 | MORDOR_ASSERT(size >= 0); 18 | } 19 | 20 | size_t 21 | LimitedStream::read(Buffer &b, size_t len) 22 | { 23 | if (m_pos >= m_size) 24 | return 0; 25 | 26 | len = (size_t)std::min(len, m_size - m_pos); 27 | size_t result = parent()->read(b, len); 28 | if (result == 0 && m_strict) 29 | MORDOR_THROW_EXCEPTION(UnexpectedEofException()); 30 | m_pos += result; 31 | return result; 32 | } 33 | 34 | size_t 35 | LimitedStream::write(const Buffer &b, size_t len) 36 | { 37 | if (m_pos >= m_size) 38 | MORDOR_THROW_EXCEPTION(WriteBeyondEofException()); 39 | len = (size_t)std::min(len, m_size - m_pos); 40 | size_t result = parent()->write(b, len); 41 | m_pos += result; 42 | return result; 43 | } 44 | 45 | long long 46 | LimitedStream::seek(long long offset, Anchor anchor) 47 | { 48 | if (anchor == END) { 49 | offset += size(); 50 | anchor = BEGIN; 51 | } 52 | if (anchor == BEGIN && offset == m_pos) { 53 | anchor = CURRENT; 54 | offset = 0; 55 | } 56 | // If the parent doesn't support seek, we only support tell 57 | if (!parent()->supportsSeek()) { 58 | MORDOR_ASSERT(anchor == CURRENT && offset == 0); 59 | return m_pos; 60 | } 61 | return m_pos = parent()->seek(offset, anchor); 62 | } 63 | 64 | long long 65 | LimitedStream::size() 66 | { 67 | if (!parent()->supportsSize()) { 68 | return m_size; 69 | } 70 | try { 71 | return (std::min)(m_size, parent()->size()); 72 | } catch (const std::runtime_error&) { 73 | return m_size; 74 | } 75 | } 76 | 77 | void 78 | LimitedStream::truncate(long long size) 79 | { 80 | MORDOR_NOTREACHED(); 81 | } 82 | 83 | void 84 | LimitedStream::unread(const Buffer &b, size_t len) 85 | { 86 | parent()->unread(b, len); 87 | m_pos -= len; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /mordor/streams/limited.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_LIMITED_STREAM_H__ 2 | #define __MORDOR_LIMITED_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "filter.h" 6 | 7 | namespace Mordor { 8 | 9 | class LimitedStream : public MutatingFilterStream 10 | { 11 | public: 12 | typedef boost::shared_ptr ptr; 13 | 14 | public: 15 | LimitedStream(Stream::ptr parent, long long size, bool own = true); 16 | 17 | void reset() { m_pos = 0; } 18 | void reset(long long size) { m_pos = 0; m_size = size; } 19 | 20 | bool strict() { return m_strict; } 21 | void strict(bool strict) { m_strict = strict; } 22 | 23 | bool supportsSeek() { return parent()->supportsSeek(); } 24 | bool supportsTell() { return true; } 25 | bool supportsSize() { return true; } 26 | bool supportsTruncate() { return false; } 27 | 28 | using MutatingFilterStream::read; 29 | size_t read(Buffer &b, size_t len); 30 | using MutatingFilterStream::write; 31 | size_t write(const Buffer &b, size_t len); 32 | long long seek(long long offset, Anchor anchor = BEGIN); 33 | long long size(); 34 | void truncate(long long size); 35 | void unread(const Buffer &b, size_t len); 36 | 37 | private: 38 | long long m_pos, m_size; 39 | bool m_strict; 40 | }; 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /mordor/streams/lzma2.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_LZMA_STREAM_H__ 2 | #define __MORDOR_LZMA_STREAM_H__ 3 | // Copyright (c) 2012 - VMware, Inc. 4 | 5 | #ifdef MSVC 6 | #define LZMA_API_STATIC // static-link with liblzma 7 | #endif 8 | 9 | #include 10 | 11 | #include "buffer.h" 12 | #include "filter.h" 13 | 14 | namespace Mordor { 15 | 16 | struct LZMAException : virtual Exception 17 | { 18 | LZMAException(lzma_ret rc) : m_rc(rc) {} 19 | lzma_ret rc() const { 20 | return m_rc; 21 | } 22 | private: 23 | lzma_ret m_rc; 24 | }; 25 | 26 | struct UnknownLZMAFormatException : LZMAException 27 | { 28 | UnknownLZMAFormatException() : LZMAException(LZMA_FORMAT_ERROR) 29 | {} 30 | }; 31 | 32 | struct CorruptedLZMAStreamException : LZMAException 33 | { 34 | CorruptedLZMAStreamException() : LZMAException(LZMA_DATA_ERROR) 35 | {} 36 | }; 37 | 38 | struct UnsupportedOptionsException : LZMAException 39 | { 40 | UnsupportedOptionsException() : LZMAException(LZMA_OPTIONS_ERROR) 41 | {} 42 | }; 43 | 44 | /// Stream for compressing or decompressing streams using the lzma2 algorithm 45 | /// 46 | /// Lzma2 is an extension on top of the original lzma but features support for 47 | /// some advanced features, flushing the encoder and improves support for 48 | /// multithreading, among other things. 49 | /// Although lzma2 encoder can be highly customized, we just hardwire two filters, 50 | /// LZMA_FILTER_${ARCH} and LZMA_FILTER_LZMA2, into the encoder in hope that it 51 | /// can be optimal under most circumstances. 52 | /// @note lzma2 is @em not compatible with plain lzma format. 53 | /// As a side note, XZ is a container format of one or more lzma2 streams. 54 | class LZMAStream : public MutatingFilterStream 55 | { 56 | public: 57 | LZMAStream(Stream::ptr parent, uint32_t preset = LZMA_PRESET_DEFAULT, 58 | lzma_check check = LZMA_CHECK_CRC64, bool own = true); 59 | ~LZMAStream(); 60 | void close(CloseType type = BOTH); 61 | using MutatingFilterStream::read; 62 | size_t read(Buffer &b, size_t len); 63 | using MutatingFilterStream::write; 64 | size_t write(const Buffer &b, size_t len); 65 | void flush(bool flushParent = true); 66 | 67 | private: 68 | void flushBuffer(); 69 | void finish(); 70 | 71 | private: 72 | static const size_t BUFFER_SIZE = 64 * 1024; 73 | lzma_stream m_strm; 74 | Buffer m_inBuffer, m_outBuffer; // only used when compressing 75 | bool m_closed; 76 | }; 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /mordor/streams/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_MEMORY_STREAM_H__ 2 | #define __MORDOR_MEMORY_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "buffer.h" 6 | #include "stream.h" 7 | 8 | namespace Mordor { 9 | 10 | class MemoryStream : public Stream 11 | { 12 | public: 13 | typedef boost::shared_ptr ptr; 14 | public: 15 | MemoryStream(); 16 | MemoryStream(const Buffer &b); 17 | 18 | bool supportsRead() { return true; } 19 | bool supportsWrite() { return true; } 20 | bool supportsSeek() { return true; } 21 | bool supportsSize() { return true; } 22 | bool supportsTruncate() { return true; } 23 | bool supportsFind() { return true; } 24 | 25 | size_t read(Buffer &b, size_t len); 26 | size_t read(void *buffer, size_t length); 27 | size_t write(const Buffer &b, size_t len); 28 | size_t write(const void *b, size_t len); 29 | long long seek(long long offset, Anchor anchor = BEGIN); 30 | long long size(); 31 | void truncate(long long size); 32 | ptrdiff_t find(char delim, size_t sanitySize = ~0, bool throwIfNotFound = true); 33 | ptrdiff_t find(const std::string &str, size_t sanitySize = ~0, bool throwIfNotFound = true); 34 | 35 | // Direct access to memory 36 | const Buffer &buffer() const { return m_original; } 37 | const Buffer &readBuffer() const { return m_read; } 38 | 39 | private: 40 | template size_t readInternal(T &buffer, size_t length); 41 | template size_t writeInternal(const T &buffer, size_t length); 42 | 43 | private: 44 | Buffer m_read; 45 | Buffer m_original; 46 | size_t m_offset; 47 | }; 48 | 49 | } 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /mordor/streams/namedpipe.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_NAMEDPIPE_STREAM_H__ 2 | #define __MORDOR_NAMEDPIPE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "handle.h" 6 | 7 | namespace Mordor { 8 | 9 | class NamedPipeStream : public HandleStream 10 | { 11 | public: 12 | typedef boost::shared_ptr ptr; 13 | 14 | enum Flags { 15 | READ = PIPE_ACCESS_INBOUND, 16 | WRITE = PIPE_ACCESS_OUTBOUND, 17 | READWRITE = PIPE_ACCESS_DUPLEX 18 | }; 19 | 20 | public: 21 | 22 | // Currently this class only supports the Server side of a named pipe connection 23 | // It creates a new pipe based on the passed name argument. 24 | // By default a byte-mode pipe is created (PIPE_TYPE_BYTE), but the pipeModeFlags 25 | // argument can be used to create a message-mode pipe. 26 | NamedPipeStream(const std::string &name, Flags flags = READWRITE, IOManager *ioManager = NULL, Scheduler *scheduler = NULL, DWORD pipeModeFlags = (DWORD)-1); 27 | NamedPipeStream(const std::wstring &name, Flags flags = READWRITE, IOManager *ioManager = NULL, Scheduler *scheduler = NULL, DWORD pipeModeFlags = (DWORD)-1); 28 | 29 | bool supportsRead() { return m_supportsRead; } 30 | bool supportsWrite() { return m_supportsWrite; } 31 | bool supportsSeek() { return false; } 32 | 33 | void close(CloseType type = BOTH); 34 | 35 | // Close a connected client if any, but leave the named pipe open. 36 | // Should be called after processing a client request and before 37 | // calling accept to wait for the next connection. 38 | void disconnectClient(); 39 | 40 | // Accept will put the fiber to sleep until a client connection arrives 41 | // Throws OperationAbortedException if another fiber calls cancelAccept() 42 | void accept(); 43 | 44 | void cancelAccept(); 45 | 46 | private: 47 | void init(const std::wstring &name, Flags flags, DWORD pipeModeFlags, IOManager *ioManager, Scheduler *scheduler); 48 | 49 | bool m_supportsRead, m_supportsWrite; 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /mordor/streams/notify.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_NOTIFY_STREAM_H__ 2 | #define __MORDOR_NOTIFY_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "filter.h" 8 | 9 | namespace Mordor { 10 | 11 | class NotifyStream : public FilterStream 12 | { 13 | public: 14 | typedef boost::shared_ptr ptr; 15 | public: 16 | NotifyStream(Stream::ptr parent, bool own = true) 17 | : FilterStream(parent, own) 18 | {} 19 | 20 | boost::function notifyOnFlush; 21 | boost::function notifyOnEof; 22 | boost::function notifyOnException; 23 | 24 | void close(CloseType type = BOTH) 25 | { 26 | try { 27 | if (ownsParent()) 28 | parent()->close(type); 29 | } catch (...) { 30 | if (notifyOnException) 31 | notifyOnException(); 32 | throw; 33 | } 34 | if (m_notifyOnClose) 35 | m_notifyOnClose(type); 36 | } 37 | 38 | using FilterStream::read; 39 | size_t read(Buffer &b, size_t len) 40 | { 41 | size_t result; 42 | try { 43 | result = parent()->read(b, len); 44 | } catch(...) { 45 | if (notifyOnException) 46 | notifyOnException(); 47 | throw; 48 | } 49 | if (result == 0 && notifyOnEof) 50 | notifyOnEof(); 51 | return result; 52 | } 53 | 54 | using FilterStream::write; 55 | size_t write(const Buffer &b, size_t len) 56 | { 57 | try { 58 | return parent()->write(b, len); 59 | } catch(...) { 60 | if (notifyOnException) 61 | notifyOnException(); 62 | throw; 63 | } 64 | } 65 | 66 | void flush(bool flushParent = true) 67 | { 68 | try { 69 | parent()->flush(flushParent); 70 | } catch(...) { 71 | if (notifyOnException) 72 | notifyOnException(); 73 | throw; 74 | } 75 | if (notifyOnFlush) 76 | notifyOnFlush(); 77 | } 78 | 79 | void notifyOnClose(boost::function dg = NULL) 80 | { 81 | if (dg) 82 | notifyOnClose2(boost::bind(&NotifyStream::onCloseAdapter, dg, _1)); 83 | else 84 | notifyOnClose2(NULL); 85 | } 86 | 87 | void notifyOnClose2(boost::function dg) 88 | { m_notifyOnClose = dg; } 89 | 90 | private: 91 | static void onCloseAdapter(boost::function dg, CloseType type) 92 | { dg(); } 93 | 94 | private: 95 | boost::function m_notifyOnClose; 96 | 97 | }; 98 | 99 | } 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /mordor/streams/null.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "null.h" 4 | 5 | namespace Mordor { 6 | 7 | NullStream NullStream::s_nullStream; 8 | 9 | } 10 | 11 | 12 | -------------------------------------------------------------------------------- /mordor/streams/null.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_NULL_STREAM_H__ 2 | #define __MORDOR_NULL_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | #include "mordor/util.h" 7 | 8 | namespace Mordor { 9 | 10 | class NullStream : public Stream 11 | { 12 | private: 13 | NullStream() {} 14 | 15 | public: 16 | static NullStream &get() { return s_nullStream; } 17 | static Stream::ptr get_ptr() { return Stream::ptr(&s_nullStream, &nop); } 18 | 19 | bool supportsRead() { return true; } 20 | bool supportsWrite() { return true; } 21 | bool supportsSeek() { return true; } 22 | bool supportsSize() { return true; } 23 | 24 | size_t read(Buffer &buffer, size_t length) { return 0; } 25 | size_t read(void *buffer, size_t length) { return 0; } 26 | size_t write(const Buffer &buffer, size_t length) { return length; } 27 | size_t write(const void *buffer, size_t length) { return length; } 28 | long long seek(long long offset, Anchor anchor = BEGIN) { return 0; } 29 | long long size() { return 0; } 30 | 31 | private: 32 | static NullStream s_nullStream; 33 | }; 34 | 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /mordor/streams/pipe.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PIPE_STREAM_H__ 2 | #define __MORDOR_PIPE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Mordor { 10 | 11 | class Stream; 12 | 13 | std::pair, boost::shared_ptr > 14 | pipeStream(size_t bufferSize = ~0); 15 | 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /mordor/streams/progress.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_PROGRESS_STREAM_H__ 2 | #define __MORDOR_PROGRESS_STREAM_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "filter.h" 8 | 9 | namespace Mordor { 10 | 11 | class ProgressStream : public FilterStream 12 | { 13 | public: 14 | typedef boost::shared_ptr ptr; 15 | typedef boost::function progress_callback; 16 | 17 | private: 18 | progress_callback m_readDg, m_writeDg; 19 | size_t m_pendingRead, m_pendingWrite, m_threshold; 20 | 21 | void reportRead() 22 | { 23 | if (m_readDg && m_pendingRead > 0) { 24 | m_readDg(m_pendingRead); 25 | m_pendingRead = 0; 26 | } 27 | } 28 | 29 | void reportWrite() 30 | { 31 | if (m_writeDg && m_pendingWrite > 0) { 32 | m_writeDg(m_pendingWrite); 33 | m_pendingWrite = 0; 34 | } 35 | } 36 | 37 | public: 38 | ProgressStream(Stream::ptr parent, 39 | progress_callback readDg, 40 | progress_callback writeDg, 41 | size_t threshold = 0, 42 | bool own = true) 43 | : FilterStream(parent, own), 44 | m_readDg(readDg), 45 | m_writeDg(writeDg), 46 | m_pendingRead(0), 47 | m_pendingWrite(0), 48 | m_threshold(threshold) 49 | {} 50 | 51 | 52 | void close(CloseType type = BOTH) 53 | { 54 | // report any unreported data before close 55 | reportRead(); 56 | reportWrite(); 57 | 58 | if (ownsParent()) 59 | parent()->close(type); 60 | } 61 | 62 | using FilterStream::read; 63 | size_t read(Buffer &b, size_t len) 64 | { 65 | size_t result = parent()->read(b, len); 66 | 67 | m_pendingRead += result; 68 | if (m_pendingRead >= m_threshold) 69 | reportRead(); 70 | 71 | return result; 72 | } 73 | 74 | using FilterStream::write; 75 | size_t write(const Buffer &b, size_t len) 76 | { 77 | size_t result = parent()->write(b, len); 78 | 79 | m_pendingWrite += result; 80 | if (m_pendingWrite >= m_threshold) 81 | reportWrite(); 82 | 83 | return result; 84 | } 85 | 86 | void flush(bool flushParent = true) 87 | { 88 | // report any unreported data before flush 89 | reportRead(); 90 | reportWrite(); 91 | 92 | parent()->flush(flushParent); 93 | } 94 | }; 95 | 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /mordor/streams/random.cpp: -------------------------------------------------------------------------------- 1 | #include "random.h" 2 | 3 | #ifndef WINDOWS 4 | #include 5 | #include "ssl.h" 6 | #endif 7 | 8 | #include "mordor/endian.h" 9 | #include "mordor/exception.h" 10 | 11 | namespace Mordor { 12 | 13 | RandomStream::RandomStream() 14 | { 15 | #ifdef WINDOWS 16 | BOOL ret = ::CryptAcquireContext(&m_hCP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); 17 | if(!ret || !m_hCP) { 18 | if(lastError() == NTE_BAD_KEYSET) { 19 | ret = ::CryptAcquireContext(&m_hCP, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT); 20 | if(!ret || !m_hCP) { 21 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptAcquireContext"); 22 | } 23 | } else { 24 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptAcquireContext"); 25 | } 26 | } 27 | #endif 28 | } 29 | 30 | RandomStream::~RandomStream() 31 | { 32 | #ifdef WINDOWS 33 | ::CryptReleaseContext(m_hCP, 0); 34 | #endif 35 | } 36 | 37 | size_t RandomStream::read(void *buffer, size_t length) 38 | { 39 | #ifdef WINDOWS 40 | if (length >= 0xffffffffu) 41 | length = 0xffffffffu; 42 | if (!::CryptGenRandom(m_hCP, static_cast(length), static_cast(buffer))) 43 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CryptGenRandom"); 44 | #else 45 | if (!RAND_bytes(static_cast(buffer), length)) 46 | MORDOR_THROW_EXCEPTION(OpenSSLException()); 47 | #endif 48 | return length; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /mordor/streams/random.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_RANDOM_STREAM_H__ 2 | #define __MORDOR_RANDOM_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | 7 | #ifdef WINDOWS 8 | #include 9 | #endif 10 | 11 | namespace Mordor { 12 | 13 | /// a stream to generate random data 14 | /// uses CryptGenRandom() on WINDOWS; OpenSSL RAND_bytes elsewhere (seeded automatically by /dev/urandom) 15 | /// @note RandomStream is not guaranteed to be thread safety. 16 | /// On Windows platform, the thread safety depends on the cryptographic service provider implementation 17 | /// On Linux/MacOS platform, it depends on openssl thread safety. By default it isn't, use OpensslLockManager 18 | /// to ensure the thread safety. 19 | class RandomStream : public Stream 20 | { 21 | public: 22 | typedef boost::shared_ptr ptr; 23 | 24 | RandomStream(); 25 | ~RandomStream(); 26 | 27 | bool supportsRead() { return true; } 28 | size_t read(void *buffer, size_t length); 29 | using Stream::read; 30 | 31 | bool supportsSeek() { return true; } 32 | long long seek(long long offset, Anchor anchor = BEGIN) { return 0; } 33 | 34 | private: 35 | #ifdef WINDOWS 36 | HCRYPTPROV m_hCP; 37 | #endif 38 | }; 39 | 40 | } 41 | 42 | #endif // __MORDOR_RANDOM_STREAM_H__ 43 | 44 | -------------------------------------------------------------------------------- /mordor/streams/singleplex.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "singleplex.h" 4 | 5 | #include "mordor/assert.h" 6 | 7 | namespace Mordor { 8 | 9 | SingleplexStream::SingleplexStream(Stream::ptr parent, Type type, bool own) 10 | : FilterStream(parent, own), 11 | m_type(type) 12 | { 13 | MORDOR_ASSERT(type == READ || type == WRITE); 14 | if (type == READ) MORDOR_ASSERT(parent->supportsRead()); 15 | if (type == WRITE) MORDOR_ASSERT(parent->supportsWrite()); 16 | } 17 | 18 | void 19 | SingleplexStream::close(CloseType type) 20 | { 21 | if (ownsParent()) { 22 | if (m_type == READ && (type & Stream::READ)) { 23 | parent()->close(parent()->supportsHalfClose() ? 24 | Stream::READ : BOTH); 25 | } else if (m_type == WRITE && (type & Stream::WRITE)) { 26 | parent()->close(parent()->supportsHalfClose() ? 27 | Stream::WRITE : BOTH); 28 | } 29 | } 30 | } 31 | 32 | size_t 33 | SingleplexStream::read(Buffer &buffer, size_t length) 34 | { 35 | MORDOR_ASSERT(m_type == READ); 36 | return parent()->read(buffer, length); 37 | } 38 | 39 | size_t 40 | SingleplexStream::read(void * buffer, size_t length) 41 | { 42 | MORDOR_ASSERT(m_type == READ); 43 | return parent()->read(buffer, length); 44 | } 45 | 46 | size_t 47 | SingleplexStream::write(const Buffer &buffer, size_t length) 48 | { 49 | MORDOR_ASSERT(m_type == WRITE); 50 | return parent()->write(buffer, length); 51 | } 52 | 53 | size_t 54 | SingleplexStream::write(const void *buffer, size_t length) 55 | { 56 | MORDOR_ASSERT(m_type == WRITE); 57 | return parent()->write(buffer, length); 58 | } 59 | 60 | void 61 | SingleplexStream::truncate(long long size) 62 | { 63 | MORDOR_ASSERT(m_type == WRITE); 64 | return parent()->truncate(size); 65 | } 66 | 67 | void 68 | SingleplexStream::flush(bool flushParent) 69 | { 70 | if (m_type == READ) 71 | return; 72 | return parent()->flush(flushParent); 73 | } 74 | 75 | ptrdiff_t 76 | SingleplexStream::find(char delimiter, size_t sanitySize, 77 | bool throwIfNotFound) 78 | { 79 | MORDOR_ASSERT(m_type == READ); 80 | return parent()->find(delimiter, sanitySize, throwIfNotFound); 81 | } 82 | 83 | ptrdiff_t 84 | SingleplexStream::find(const std::string &delimiter, size_t sanitySize, 85 | bool throwIfNotFound) 86 | { 87 | MORDOR_ASSERT(m_type == READ); 88 | return parent()->find(delimiter, sanitySize, throwIfNotFound); 89 | } 90 | 91 | void 92 | SingleplexStream::unread(const Buffer &buffer, size_t length) 93 | { 94 | MORDOR_ASSERT(m_type == READ); 95 | return parent()->unread(buffer, length); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /mordor/streams/singleplex.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SINGLEPLEX_STREAM_H__ 2 | #define __MORDOR_SINGLEPLEX_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "filter.h" 6 | 7 | namespace Mordor { 8 | 9 | class SingleplexStream : public FilterStream 10 | { 11 | public: 12 | enum Type { 13 | READ, 14 | WRITE 15 | }; 16 | 17 | SingleplexStream(Stream::ptr parent, Type type, bool own = true); 18 | 19 | bool supportsRead() { return m_type == READ; } 20 | bool supportsWrite() { return m_type == WRITE; } 21 | bool supportsTruncate() 22 | { return m_type == WRITE && parent()->supportsTruncate(); } 23 | bool supportsFind() 24 | { return m_type == READ && parent()->supportsFind(); } 25 | bool supportsUnread() 26 | { return m_type == READ && parent()->supportsUnread(); } 27 | 28 | void close(CloseType type = BOTH); 29 | 30 | size_t read(Buffer &buffer, size_t length); 31 | size_t read(void *buffer, size_t length); 32 | size_t write(const Buffer &buffer, size_t length); 33 | size_t write(const void *buffer, size_t length); 34 | void truncate(long long size); 35 | void flush(bool flushParent = true); 36 | ptrdiff_t find(char delimiter, size_t sanitySize = ~0, 37 | bool throwIfNotFound = true); 38 | ptrdiff_t find(const std::string &delimiter, 39 | size_t sanitySize = ~0, bool throwIfNotFound = true); 40 | void unread(const Buffer &buffer, size_t length); 41 | 42 | private: 43 | Type m_type; 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /mordor/streams/socket.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "socket.h" 4 | 5 | #include "buffer.h" 6 | #include "mordor/assert.h" 7 | #include "mordor/socket.h" 8 | 9 | namespace Mordor { 10 | 11 | SocketStream::SocketStream(Socket::ptr socket, bool own) 12 | : m_socket(socket), 13 | m_own(own) 14 | { 15 | MORDOR_ASSERT(socket); 16 | } 17 | 18 | void 19 | SocketStream::close(CloseType type) 20 | { 21 | if (m_socket && m_own) { 22 | int how; 23 | switch(type) { 24 | case READ: 25 | how = SHUT_RD; 26 | break; 27 | case WRITE: 28 | how = SHUT_WR; 29 | break; 30 | default: 31 | how = SHUT_RDWR; 32 | break; 33 | } 34 | m_socket->shutdown(how); 35 | } 36 | } 37 | 38 | size_t 39 | SocketStream::read(Buffer &buffer, size_t length) 40 | { 41 | std::vector iovs = buffer.writeBuffers(length); 42 | size_t result = m_socket->receive(&iovs[0], iovs.size()); 43 | buffer.produce(result); 44 | return result; 45 | } 46 | 47 | size_t 48 | SocketStream::read(void *buffer, size_t length) 49 | { 50 | return m_socket->receive(buffer, length); 51 | } 52 | 53 | void 54 | SocketStream::cancelRead() 55 | { 56 | m_socket->cancelReceive(); 57 | } 58 | 59 | size_t 60 | SocketStream::write(const Buffer &buffer, size_t length) 61 | { 62 | const std::vector iovs = buffer.readBuffers(length); 63 | size_t result = m_socket->send(&iovs[0], iovs.size()); 64 | MORDOR_ASSERT(result > 0); 65 | return result; 66 | } 67 | 68 | size_t 69 | SocketStream::write(const void *buffer, size_t length) 70 | { 71 | return m_socket->send(buffer, length); 72 | } 73 | 74 | void 75 | SocketStream::cancelWrite() 76 | { 77 | m_socket->cancelSend(); 78 | } 79 | 80 | boost::signals2::connection 81 | SocketStream::onRemoteClose( 82 | const boost::signals2::slot &slot) 83 | { 84 | return m_socket->onRemoteClose(slot); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /mordor/streams/socket.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SOCKET_STREAM_H__ 2 | #define __MORDOR_SOCKET_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | 7 | namespace Mordor { 8 | 9 | class Socket; 10 | 11 | class SocketStream : public Stream 12 | { 13 | public: 14 | typedef boost::shared_ptr ptr; 15 | 16 | public: 17 | SocketStream(boost::shared_ptr socket, bool own = true); 18 | 19 | bool supportsHalfClose() { return true; } 20 | bool supportsRead() { return true; } 21 | bool supportsWrite() { return true; } 22 | bool supportsCancel() { return true; } 23 | 24 | void close(CloseType type = BOTH); 25 | 26 | size_t read(Buffer &buffer, size_t length); 27 | size_t read(void *buffer, size_t length); 28 | void cancelRead(); 29 | size_t write(const Buffer &buffer, size_t length); 30 | size_t write(const void *buffer, size_t length); 31 | void cancelWrite(); 32 | 33 | boost::signals2::connection onRemoteClose( 34 | const boost::signals2::slot &slot); 35 | 36 | boost::shared_ptr socket() { return m_socket; } 37 | 38 | private: 39 | boost::shared_ptr m_socket; 40 | bool m_own; 41 | }; 42 | 43 | } 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /mordor/streams/ssl.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_SSL_STREAM_H__ 2 | #define __MORDOR_SSL_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "filter.h" 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #include "buffer.h" 13 | 14 | namespace Mordor { 15 | 16 | class OpenSSLException : public std::runtime_error 17 | { 18 | public: 19 | OpenSSLException(const std::string &message) 20 | : std::runtime_error(message) 21 | {} 22 | 23 | OpenSSLException(); // queries OpenSSL for the error code 24 | }; 25 | 26 | class CertificateVerificationException : public OpenSSLException 27 | { 28 | public: 29 | CertificateVerificationException(long verifyResult) 30 | : OpenSSLException(constructMessage(verifyResult)), 31 | m_verifyResult(verifyResult) 32 | {} 33 | CertificateVerificationException(long verifyResult, 34 | const std::string &message) 35 | : OpenSSLException(message), 36 | m_verifyResult(verifyResult) 37 | {} 38 | 39 | long verifyResult() const { return m_verifyResult; } 40 | 41 | private: 42 | static std::string constructMessage(long verifyResult); 43 | 44 | private: 45 | long m_verifyResult; 46 | }; 47 | 48 | class SSLStream : public MutatingFilterStream 49 | { 50 | public: 51 | typedef boost::shared_ptr ptr; 52 | 53 | public: 54 | SSLStream(Stream::ptr parent, bool client = true, bool own = true, SSL_CTX *ctx = NULL); 55 | 56 | bool supportsHalfClose() { return false; } 57 | 58 | void close(CloseType type = BOTH); 59 | using MutatingFilterStream::read; 60 | size_t read(void *buffer, size_t length); 61 | size_t write(const Buffer &buffer, size_t length); 62 | size_t write(const void *buffer, size_t length); 63 | void flush(bool flushParent = true); 64 | 65 | void accept(); 66 | void connect(); 67 | 68 | void serverNameIndication(const std::string &hostname); 69 | 70 | void verifyPeerCertificate(); 71 | void verifyPeerCertificate(const std::string &hostname); 72 | void clearSSLError(); 73 | 74 | private: 75 | void wantRead(); 76 | int sslCallWithLock(boost::function dg, unsigned long *error); 77 | 78 | private: 79 | boost::mutex m_mutex; 80 | boost::shared_ptr m_ctx; 81 | boost::shared_ptr m_ssl; 82 | Buffer m_readBuffer, m_writeBuffer; 83 | BIO *m_readBio, *m_writeBio; 84 | }; 85 | 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /mordor/streams/std.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "std.h" 4 | 5 | #include "mordor/exception.h" 6 | 7 | namespace Mordor { 8 | 9 | StdStream::StdStream(IOManager *ioManager, Scheduler *scheduler, int stream) 10 | { 11 | #ifdef WINDOWS 12 | HANDLE hFile = GetStdHandle(stream); 13 | if (hFile == INVALID_HANDLE_VALUE) 14 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("GetStdHandle"); 15 | if (hFile == NULL) 16 | MORDOR_THROW_EXCEPTION_FROM_ERROR_API(ERROR_FILE_NOT_FOUND, "GetStdHandle"); 17 | init(hFile, ioManager, scheduler, false); 18 | #else 19 | init(stream, ioManager, scheduler, stream); 20 | #endif 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /mordor/streams/std.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_STD_STREAM_H__ 2 | #define __MORDOR_STD_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "mordor/version.h" 6 | 7 | #ifdef WINDOWS 8 | #include "handle.h" 9 | #else 10 | #include "fd.h" 11 | #endif 12 | 13 | namespace Mordor { 14 | 15 | class StdStream : public NativeStream 16 | { 17 | protected: 18 | StdStream(IOManager *ioManager, Scheduler *scheduler, int stream); 19 | }; 20 | 21 | class StdinStream : public StdStream 22 | { 23 | public: 24 | StdinStream() 25 | : StdStream(NULL, NULL, MORDOR_NATIVE(STD_INPUT_HANDLE, STDIN_FILENO)) 26 | {} 27 | StdinStream(IOManager &ioManager) 28 | : StdStream(&ioManager, NULL, MORDOR_NATIVE(STD_INPUT_HANDLE, STDIN_FILENO)) 29 | {} 30 | StdinStream(Scheduler &scheduler) 31 | : StdStream(NULL, &scheduler, MORDOR_NATIVE(STD_INPUT_HANDLE, STDIN_FILENO)) 32 | {} 33 | StdinStream(IOManager &ioManager, Scheduler &scheduler) 34 | : StdStream(&ioManager, &scheduler, MORDOR_NATIVE(STD_INPUT_HANDLE, STDIN_FILENO)) 35 | {} 36 | 37 | bool supportsWrite() { return false; } 38 | }; 39 | 40 | class StdoutStream : public StdStream 41 | { 42 | public: 43 | StdoutStream() 44 | : StdStream(NULL, NULL, MORDOR_NATIVE(STD_OUTPUT_HANDLE, STDOUT_FILENO)) 45 | {} 46 | StdoutStream(IOManager &ioManager) 47 | : StdStream(&ioManager, NULL, MORDOR_NATIVE(STD_OUTPUT_HANDLE, STDOUT_FILENO)) 48 | {} 49 | StdoutStream(Scheduler &scheduler) 50 | : StdStream(NULL, &scheduler, MORDOR_NATIVE(STD_OUTPUT_HANDLE, STDOUT_FILENO)) 51 | {} 52 | StdoutStream(IOManager &ioManager, Scheduler &scheduler) 53 | : StdStream(&ioManager, &scheduler, MORDOR_NATIVE(STD_OUTPUT_HANDLE, STDOUT_FILENO)) 54 | {} 55 | 56 | bool supportsRead() { return false; } 57 | }; 58 | 59 | class StderrStream : public StdStream 60 | { 61 | public: 62 | StderrStream() 63 | : StdStream(NULL, NULL, MORDOR_NATIVE(STD_ERROR_HANDLE, STDERR_FILENO)) 64 | {} 65 | StderrStream(IOManager &ioManager) 66 | : StdStream(&ioManager, NULL, MORDOR_NATIVE(STD_ERROR_HANDLE, STDERR_FILENO)) 67 | {} 68 | StderrStream(Scheduler &scheduler) 69 | : StdStream(NULL, &scheduler, MORDOR_NATIVE(STD_ERROR_HANDLE, STDERR_FILENO)) 70 | {} 71 | StderrStream(IOManager &ioManager, Scheduler &scheduler) 72 | : StdStream(&ioManager, &scheduler, MORDOR_NATIVE(STD_ERROR_HANDLE, STDERR_FILENO)) 73 | {} 74 | 75 | bool supportsRead() { return false; } 76 | }; 77 | 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /mordor/streams/stdcrypto.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_STDCRYPTO_STREAM__ 2 | #define __MORDOR_STDCRYPTO_STREAM__ 3 | // Copyright (c) 2016 - Mozy, Inc. 4 | 5 | #include "buffer.h" 6 | #include "filter.h" 7 | 8 | namespace Mordor { 9 | 10 | // encryption/decryption stream compatible with openssl implementation 11 | // * only need passphrase as input parameter, key and iv will be derived from the passphrase 12 | // * optional salt can be generated as well 13 | class StdCryptoStream : public MutatingFilterStream 14 | { 15 | public: 16 | typedef boost::shared_ptr ptr; 17 | 18 | enum Direction { 19 | INFER, // check whether parent supportsRead() or supportsWrite(); 20 | // exactly one of these must be true 21 | READ, 22 | WRITE 23 | }; 24 | enum Operation { 25 | AUTO, // encrypt on WRITE; decrypt on READ 26 | DECRYPT, 27 | ENCRYPT 28 | }; 29 | 30 | StdCryptoStream(Stream::ptr parent, const EVP_CIPHER *cipher, const std::string &pass, 31 | bool nosalt = false, Direction = INFER, Operation = AUTO, bool own = true); 32 | ~StdCryptoStream() {}; 33 | 34 | bool supportsRead() { return m_dir == READ; } 35 | bool supportsWrite() { return m_dir == WRITE; } 36 | bool supportsSeek() { return false; } 37 | bool supportsSize() { return false; } 38 | 39 | void close(CloseType type = BOTH); 40 | void flush(bool flushParent = true); 41 | using MutatingFilterStream::read; 42 | size_t read(Buffer &buffer, size_t len); 43 | using MutatingFilterStream::write; 44 | size_t write(const Buffer &buffer, size_t len); 45 | 46 | private: 47 | Stream::ptr buildCryptoStream(Stream::ptr p, const std::string &salt); 48 | 49 | private: 50 | Buffer m_buffer; 51 | const EVP_CIPHER * m_cipher; 52 | const std::string m_pass; 53 | bool m_nosalt; 54 | Direction m_dir; 55 | Operation m_op; 56 | bool m_extractSalt; 57 | Stream::ptr m_cryptoStream; 58 | }; 59 | 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /mordor/streams/temp.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_TEMP_STREAM_H__ 2 | #define __MORDOR_TEMP_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "file.h" 6 | 7 | namespace Mordor { 8 | 9 | #ifdef WINDOWS 10 | typedef FileStream TempStreamBase; 11 | #else 12 | typedef FDStream TempStreamBase; 13 | #endif 14 | 15 | class TempStream : public TempStreamBase 16 | { 17 | public: 18 | typedef boost::shared_ptr ptr; 19 | 20 | public: 21 | /// Create a stream representing a temporary file 22 | 23 | /// @param prefix The prefix for the temporary file. If it is an absolute 24 | /// path, the file will be created in that location. If it is relative, it 25 | /// will be relative to the system temporary directory. In either case, 26 | /// a suffix will be added to make it unique. 27 | /// @param deleteOnClose If the file will be created with 28 | /// FileStream::DELETE_ON_CLOSE flag, to guarantee the file will be cleaned 29 | /// up when the TempStream destructs (or the process dies). 30 | /// @param ioManager The IOManager to use for any asynchronous I/O, if 31 | /// possible 32 | /// @param scheduler The Scheduler to switchTo for any blocking I/O 33 | TempStream(const std::string &prefix = "", bool deleteOnClose = true, 34 | IOManager *ioManager = NULL, Scheduler *scheduler = NULL); 35 | 36 | #ifndef WINDOWS 37 | std::string path() const { return m_path; } 38 | 39 | private: 40 | std::string m_path; 41 | #endif 42 | }; 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /mordor/streams/test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "test.h" 4 | 5 | namespace Mordor { 6 | 7 | void 8 | TestStream::close(CloseType type) 9 | { 10 | if (m_onClose) 11 | m_onClose(type); 12 | if (ownsParent()) 13 | parent()->close(type); 14 | } 15 | 16 | size_t 17 | TestStream::read(Buffer &b, size_t len) 18 | { 19 | len = (std::min)(len, m_maxReadSize); 20 | if (m_onRead) { 21 | if (m_onReadBytes == 0) { 22 | m_onRead(); 23 | } 24 | } 25 | if (m_onRead && m_onReadBytes > 0) 26 | len = (size_t)std::min(len, m_onReadBytes); 27 | size_t result = parent()->read(b, len); 28 | if (m_onRead && m_onReadBytes > 0) 29 | m_onReadBytes -= result; 30 | return result; 31 | } 32 | 33 | size_t 34 | TestStream::write(const Buffer &b, size_t len) 35 | { 36 | len = (std::min)(len, m_maxWriteSize); 37 | if (m_onWrite) { 38 | if (m_onWriteBytes == 0) { 39 | m_onWrite(); 40 | } 41 | } 42 | if (m_onWrite && m_onWriteBytes > 0) 43 | len = (size_t)std::min(len, m_onWriteBytes); 44 | size_t result = parent()->write(b, len); 45 | if (m_onWrite && m_onWriteBytes > 0) 46 | m_onWriteBytes -= result; 47 | return result; 48 | } 49 | 50 | void 51 | TestStream::flush(bool flushParent) 52 | { 53 | if (m_onFlush) 54 | m_onFlush(flushParent); 55 | parent()->flush(flushParent); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /mordor/streams/test.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_TEST_STREAM_H__ 2 | #define __MORDOR_TEST_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "filter.h" 8 | 9 | namespace Mordor { 10 | 11 | // This stream is for use in unit tests to force 12 | class TestStream : public FilterStream 13 | { 14 | public: 15 | typedef boost::shared_ptr ptr; 16 | 17 | public: 18 | TestStream(Stream::ptr parent) 19 | : FilterStream(parent, true), 20 | m_maxReadSize(~0), 21 | m_maxWriteSize(~0), 22 | m_onReadBytes(0), 23 | m_onWriteBytes(0) 24 | {} 25 | 26 | size_t maxReadSize() const { return m_maxReadSize; } 27 | void maxReadSize(size_t max) { m_maxReadSize = max; } 28 | 29 | size_t maxWriteSize() const { return m_maxWriteSize; } 30 | void maxWriteSize(size_t max) { m_maxWriteSize = max; } 31 | 32 | void onClose(boost::function dg) 33 | { m_onClose = dg; } 34 | void onRead(boost::function dg, long long bytes = 0) 35 | { m_onRead = dg; m_onReadBytes = bytes; } 36 | void onWrite(boost::function dg, long long bytes = 0) 37 | { m_onWrite = dg; m_onWriteBytes = bytes; } 38 | void onFlush(boost::function dg) 39 | { m_onFlush = dg; } 40 | 41 | void close(CloseType type = BOTH); 42 | using FilterStream::read; 43 | size_t read(Buffer &b, size_t len); 44 | using FilterStream::write; 45 | size_t write(const Buffer &b, size_t len); 46 | void flush(bool flushParent = true); 47 | 48 | private: 49 | size_t m_maxReadSize, m_maxWriteSize; 50 | boost::function m_onClose; 51 | boost::function m_onRead, m_onWrite; 52 | boost::function m_onFlush; 53 | long long m_onReadBytes, m_onWriteBytes; 54 | }; 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /mordor/streams/throttle.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_THROTTLE_STREAM_H__ 2 | #define __MORDOR_THROTTLE_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include "filter.h" 8 | 9 | namespace Mordor { 10 | 11 | class TimerManager; 12 | 13 | /// @note In practice, ThrottleStream cannot throttle much slower than 800bps 14 | /// (due to refusing to sleep for more than a tenth of a second at a time) 15 | class ThrottleStream : public FilterStream 16 | { 17 | public: 18 | /// @param dg Returns the current throttle value, in bps (BITS per second). 19 | /// Either 0 or ~0u means to not throttle at the moment. 20 | ThrottleStream(Stream::ptr parent, boost::function dg, 21 | TimerManager &timerManager, bool own = true) 22 | : FilterStream(parent, own), 23 | m_dg(dg), 24 | m_read(0), 25 | m_written(0), 26 | m_readTimestamp(0), 27 | m_writeTimestamp(0), 28 | m_timerManager(&timerManager) 29 | {} 30 | ThrottleStream(Stream::ptr parent, boost::function dg, 31 | bool own = true) 32 | : FilterStream(parent, own), 33 | m_dg(dg), 34 | m_read(0), 35 | m_written(0), 36 | m_readTimestamp(0), 37 | m_writeTimestamp(0), 38 | m_timerManager(NULL) 39 | {} 40 | 41 | using FilterStream::read; 42 | size_t read(Buffer &b, size_t len); 43 | using FilterStream::write; 44 | size_t write(const Buffer &b, size_t len); 45 | 46 | private: 47 | boost::function m_dg; 48 | size_t m_read, m_written; 49 | unsigned long long m_readTimestamp, m_writeTimestamp; 50 | TimerManager *m_timerManager; 51 | }; 52 | 53 | } 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /mordor/streams/transfer.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_TRANSFER_STREAM_H__ 2 | #define __MORDOR_TRANSFER_STREAM_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "stream.h" 6 | 7 | namespace Mordor { 8 | 9 | enum ExactLength 10 | { 11 | /// If toTransfer == ~0ull, use EOF, otherwise EXACT 12 | INFER, 13 | /// If toTransfer bytes can't be read, throw UnexpectedEofException 14 | EXACT, 15 | /// Transfer as many bytes as possible until EOF is hit 16 | UNTILEOF 17 | }; 18 | 19 | unsigned long long transferStream(Stream &src, Stream &dst, 20 | unsigned long long toTransfer = ~0ull, 21 | ExactLength exactLength = INFER); 22 | 23 | inline unsigned long long transferStream(Stream::ptr src, Stream &dst, 24 | unsigned long long toTransfer = ~0ull, 25 | ExactLength exactLength = INFER) 26 | { return transferStream(*src.get(), dst, toTransfer, exactLength); } 27 | inline unsigned long long transferStream(Stream &src, Stream::ptr dst, 28 | unsigned long long toTransfer = ~0ull, 29 | ExactLength exactLength = INFER) 30 | { return transferStream(src, *dst.get(), toTransfer, exactLength); } 31 | inline unsigned long long transferStream(Stream::ptr src, Stream::ptr dst, 32 | unsigned long long toTransfer = ~0ull, 33 | ExactLength exactLength = INFER) 34 | { return transferStream(*src.get(), *dst.get(), toTransfer, exactLength); } 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /mordor/streams/zero.cpp: -------------------------------------------------------------------------------- 1 | #include "zero.h" 2 | 3 | #include 4 | 5 | namespace Mordor { 6 | 7 | ZeroStream ZeroStream::s_zeroStream; 8 | 9 | size_t 10 | ZeroStream::read(void *buffer, size_t length) 11 | { 12 | memset(buffer, 0, length); 13 | return length; 14 | } 15 | 16 | long long 17 | ZeroStream::seek(long long offset, Anchor anchor) 18 | { 19 | return 0; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /mordor/streams/zero.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_ZERO_STREAM_H__ 2 | #define __MORDOR_ZERO_STREAM_H__ 3 | // Copyright (c) 2012 - VMware, Inc. 4 | 5 | #include "stream.h" 6 | #include "mordor/util.h" 7 | 8 | namespace Mordor { 9 | 10 | class ZeroStream : public Mordor::Stream 11 | { 12 | private: 13 | ZeroStream() {} 14 | 15 | public: 16 | static Stream::ptr get_ptr() { 17 | return Mordor::unmanagedPtr(s_zeroStream); 18 | } 19 | virtual bool supportsRead() { return true; } 20 | virtual size_t read(void *buffer, size_t length); 21 | using Mordor::Stream::read; 22 | 23 | virtual bool supportsSeek() { return true; } 24 | long long seek(long long offset, Anchor anchor = BEGIN); 25 | 26 | private: 27 | static ZeroStream s_zeroStream; 28 | }; 29 | 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /mordor/test/.gitignore: -------------------------------------------------------------------------------- 1 | libmordortest.pc 2 | -------------------------------------------------------------------------------- /mordor/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #This library offers mordor unit test framework 2 | #Note: for new test projects boost unit test framework is recommended insted 3 | 4 | set(SRCS 5 | antxmllistener.cpp 6 | antxmllistener.h 7 | compoundlistener.cpp 8 | compoundlistener.h 9 | stdoutlistener.cpp 10 | stdoutlistener.h 11 | test.cpp 12 | test.h 13 | ) 14 | 15 | include_directories(AFTER 16 | ../.. 17 | ) 18 | 19 | add_library(mordortest STATIC ${SRCS}) 20 | -------------------------------------------------------------------------------- /mordor/test/antxmllistener.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_TEST_ANT_XML_LISTENER_H__ 2 | #define __MORDOR_TEST_ANT_XML_LISTENER_H__ 3 | 4 | #include 5 | 6 | #include "test.h" 7 | 8 | namespace Mordor { 9 | namespace Test { 10 | 11 | class AntXMLLogSink; 12 | 13 | class AntXMLListener : public TestListener 14 | { 15 | public: 16 | AntXMLListener(const std::string &directory); 17 | ~AntXMLListener(); 18 | 19 | void testStarted(const std::string &suite, 20 | const std::string &test); 21 | void testComplete(const std::string &suite, 22 | const std::string &test); 23 | void testSkipped(const std::string &suite, 24 | const std::string &tests); 25 | void testAsserted(const std::string &suite, 26 | const std::string &test, const Assertion &message); 27 | void testException(const std::string &suite, 28 | const std::string &test); 29 | void testsComplete(); 30 | 31 | private: 32 | struct TestInfo 33 | { 34 | TestInfo() : start(~0ull), end(~0ull) {} 35 | unsigned long long start; 36 | unsigned long long end; 37 | std::string exceptionMessage; 38 | std::string exceptionType; 39 | std::string exceptionDetails; 40 | }; 41 | 42 | struct TestSuiteInfo 43 | { 44 | TestSuiteInfo() : start(~0ull), end(~0ull), errors(0), failures(0) {} 45 | unsigned long long start; 46 | unsigned long long end; 47 | size_t errors; 48 | size_t failures; 49 | std::map tests; 50 | boost::shared_ptr out; 51 | boost::shared_ptr err; 52 | }; 53 | 54 | private: 55 | boost::shared_ptr m_logSink; 56 | std::string m_directory; 57 | std::map m_testSuites; 58 | }; 59 | 60 | }} 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /mordor/test/compoundlistener.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | 5 | #include "compoundlistener.h" 6 | 7 | using namespace Mordor; 8 | using namespace Mordor::Test; 9 | 10 | void 11 | CompoundListener::addListener(boost::shared_ptr listener) 12 | { 13 | m_listeners.push_back(listener); 14 | } 15 | 16 | void 17 | CompoundListener::testStarted(const std::string &suite, const std::string &test) 18 | { 19 | for (std::vector >::const_iterator it = 20 | m_listeners.begin(); 21 | it != m_listeners.end(); 22 | ++it) 23 | (*it)->testStarted(suite, test); 24 | } 25 | 26 | void 27 | CompoundListener::testComplete(const std::string &suite, const std::string &test) 28 | { 29 | for (std::vector >::const_iterator it = 30 | m_listeners.begin(); 31 | it != m_listeners.end(); 32 | ++it) 33 | (*it)->testComplete(suite, test); 34 | } 35 | 36 | void 37 | CompoundListener::testSkipped(const std::string &suite, const std::string &test) 38 | { 39 | for (std::vector >::const_iterator it = 40 | m_listeners.begin(); 41 | it != m_listeners.end(); 42 | ++it) 43 | (*it)->testSkipped(suite, test); 44 | } 45 | 46 | void 47 | CompoundListener::testAsserted(const std::string &suite, const std::string &test, 48 | const Assertion &assertion) 49 | { 50 | for (std::vector >::const_iterator it = 51 | m_listeners.begin(); 52 | it != m_listeners.end(); 53 | ++it) 54 | (*it)->testAsserted(suite, test, assertion); 55 | } 56 | 57 | void 58 | CompoundListener::testException(const std::string &suite, const std::string &test) 59 | { 60 | for (std::vector >::const_iterator it = 61 | m_listeners.begin(); 62 | it != m_listeners.end(); 63 | ++it) 64 | (*it)->testException(suite, test); 65 | } 66 | 67 | void 68 | CompoundListener::testsComplete() 69 | { 70 | for (std::vector >::const_iterator it = 71 | m_listeners.begin(); 72 | it != m_listeners.end(); 73 | ++it) 74 | (*it)->testsComplete(); 75 | } 76 | -------------------------------------------------------------------------------- /mordor/test/compoundlistener.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_TEST_COMPOUND_LISTENER_H__ 2 | #define __MORDOR_TEST_COMPOUND_LISTENER_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "test.h" 8 | 9 | namespace Mordor { 10 | namespace Test { 11 | 12 | class CompoundListener : public TestListener 13 | { 14 | public: 15 | void addListener(boost::shared_ptr listener); 16 | 17 | void testStarted(const std::string &suite, 18 | const std::string &test); 19 | void testComplete(const std::string &suite, 20 | const std::string &test); 21 | void testSkipped(const std::string &suite, 22 | const std::string &tests); 23 | void testAsserted(const std::string &suite, 24 | const std::string &test, const Assertion &message); 25 | void testException(const std::string &suite, 26 | const std::string &test); 27 | void testsComplete(); 28 | 29 | private: 30 | std::vector > m_listeners; 31 | }; 32 | 33 | }} 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /mordor/test/libmordortest.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: libmordortest 7 | Description: High performance I/O library based on fibers 8 | Requires: mordor 9 | Version: @PACKAGE_VERSION@ 10 | Libs: -L${libdir} -lmordortest 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /mordor/test/mordortest.v12.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /mordor/test/mordortest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /mordor/test/stdoutlistener.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/predef.h" 4 | #include "mordor/config.h" 5 | #include "stdoutlistener.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace Mordor; 12 | using namespace Mordor::Test; 13 | 14 | static ConfigVar::ptr g_include_startime = 15 | Config::lookup("mordor.test.outputstarttime", true, "Print start time in test output"); 16 | 17 | StdoutListener::StdoutListener() 18 | : m_tests(0), 19 | m_success(0), 20 | m_skip(0) 21 | {} 22 | 23 | void 24 | StdoutListener::testStarted(const std::string &suite, const std::string &test) 25 | { 26 | if (test != "") 27 | ++m_tests; 28 | std::cout << "Running "; 29 | if( g_include_startime->val() ) 30 | std::cout << "(" << time(NULL) << ") "; 31 | std::cout << suite << "::" << test << ": "; 32 | std::cout.flush(); 33 | } 34 | 35 | void 36 | StdoutListener::testComplete(const std::string &suite, const std::string &test) 37 | { 38 | if (test != "") 39 | ++m_success; 40 | std::cout << "OK" << std::endl; 41 | } 42 | 43 | void 44 | StdoutListener::testSkipped(const std::string &suite, const std::string &test) 45 | { 46 | if (test != "") { 47 | ++m_skip; 48 | --m_tests; 49 | } 50 | std::cout << "skipped" << std::endl; 51 | } 52 | 53 | void 54 | StdoutListener::testAsserted(const std::string &suite, const std::string &test, 55 | const Assertion &assertion) 56 | { 57 | std::cerr << "Assertion: " 58 | << boost::current_exception_diagnostic_information() << std::endl; 59 | m_failures.push_back(std::make_pair(suite, test)); 60 | } 61 | 62 | void 63 | StdoutListener::testException(const std::string &suite, const std::string &test) 64 | { 65 | std::cerr << "Unexpected exception: " 66 | << boost::current_exception_diagnostic_information() << std::endl; 67 | m_failures.push_back(std::make_pair(suite, test)); 68 | } 69 | 70 | void 71 | StdoutListener::testsComplete() 72 | { 73 | std::cout << "Tests complete. " << m_success << "/" << m_tests 74 | << " passed, " << m_skip << " skipped." << std::endl; 75 | if (!m_failures.empty()) { 76 | std::cout << "Failures:" << std::endl; 77 | for (std::vector >::iterator 78 | it = m_failures.begin(); 79 | it != m_failures.end(); 80 | ++it) 81 | std::cout << '\t' << it->first << "::" << it->second 82 | << std::endl; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /mordor/test/stdoutlistener.h: -------------------------------------------------------------------------------- 1 | #ifndef __STDOUT_LISTENER_H__ 2 | #define __STDOUT_LISTENER_H__ 3 | 4 | #include "test.h" 5 | 6 | namespace Mordor { 7 | namespace Test { 8 | 9 | class StdoutListener : public TestListener 10 | { 11 | public: 12 | StdoutListener(); 13 | 14 | void testStarted(const std::string &suite, 15 | const std::string &test); 16 | void testComplete(const std::string &suite, 17 | const std::string &test); 18 | void testSkipped(const std::string &suite, 19 | const std::string &test); 20 | void testAsserted(const std::string &suite, 21 | const std::string &test, const Assertion &message); 22 | void testException(const std::string &suite, 23 | const std::string &test); 24 | void testsComplete(); 25 | 26 | private: 27 | size_t m_tests; 28 | size_t m_success; 29 | size_t m_skip; 30 | std::vector > m_failures; 31 | }; 32 | 33 | }} 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /mordor/tests/.gitignore: -------------------------------------------------------------------------------- 1 | run_tests 2 | -------------------------------------------------------------------------------- /mordor/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS 2 | buffer.cpp 3 | buffered_stream.cpp 4 | chunked_stream.cpp 5 | config.cpp 6 | coroutine.cpp 7 | counter_stream.cpp 8 | crypto.cpp 9 | efs_stream.cpp 10 | endian.cpp 11 | fibers.cpp 12 | fibersync.cpp 13 | fls.cpp 14 | future.cpp 15 | hash_stream.cpp 16 | hmac.cpp 17 | http_client.cpp 18 | http_parser.cpp 19 | http_proxy.cpp 20 | http_server.cpp 21 | http_servlet_dispatcher.cpp 22 | http_stream.cpp 23 | iomanager.cpp 24 | iomanager_iocp.cpp 25 | json.cpp 26 | log.cpp 27 | memory_stream.cpp 28 | oauth.cpp 29 | pipe_stream.cpp 30 | ragel.cpp 31 | run_tests.cpp 32 | scheduler.cpp 33 | socket.cpp 34 | ssl_stream.cpp 35 | statistics.cpp 36 | stream.cpp 37 | string.cpp 38 | temp_stream.cpp 39 | thread.cpp 40 | timeout_stream.cpp 41 | timer.cpp 42 | transfer_stream.cpp 43 | unicode.cpp 44 | uri.cpp 45 | util.cpp 46 | xml.cpp 47 | zip.cpp 48 | zlib.cpp 49 | ) 50 | 51 | if (NOT MSVC) 52 | #These tests don't run on windows 53 | list(APPEND SRCS 54 | notify_stream.cpp 55 | stdcrypto.cpp) 56 | 57 | if (NOT CMAKE_HOST_APPLE) 58 | list(APPEND SRCS 59 | atomic.cpp 60 | cat_stream.cpp 61 | file_stream.cpp 62 | tar.cpp 63 | ) 64 | endif() 65 | endif() 66 | 67 | #So that paths like "pch.h" resolve (required on Linux) 68 | include_directories(AFTER .) 69 | 70 | add_precompiled_header(pch.h pch.cpp SRCS) 71 | 72 | #For the moment maintain inconsistency in the test executable name 73 | #between platforms. The naming could be made consistent if we also update 74 | #buildtools scripts which trigger the tests 75 | if (MSVC) 76 | set(MORDOR_TEST_EXE_NAME tests) 77 | else() 78 | set(MORDOR_TEST_EXE_NAME run_tests) 79 | endif() 80 | 81 | add_executable(${MORDOR_TEST_EXE_NAME} ${SRCS}) 82 | 83 | target_link_libraries(${MORDOR_TEST_EXE_NAME} 84 | mordortest 85 | mordor 86 | ${OPENSSL_LIBRARIES} 87 | ${Boost_LIBRARIES} 88 | ${ZLIB_LIBRARIES} 89 | ${LIBLZMA_LIBRARIES}) 90 | 91 | add_osspecific_linking(${MORDOR_TEST_EXE_NAME}) 92 | 93 | -------------------------------------------------------------------------------- /mordor/tests/atomic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/atomic.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | 8 | MORDOR_UNITTEST(Atomic, compareAndSwapNoSignExtension) 9 | { 10 | intptr_t storage = 0xb2d015c0; 11 | MORDOR_TEST_ASSERT_EQUAL( 12 | atomicCompareAndSwap(storage, (intptr_t)0xb2d015c1, (intptr_t)0xb2d015c0), 13 | (intptr_t)0xb2d015c0); 14 | } 15 | -------------------------------------------------------------------------------- /mordor/tests/cat_stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "mordor/streams/cat.h" 6 | #include "mordor/streams/buffer.h" 7 | #include "mordor/streams/memory.h" 8 | #include "mordor/streams/null.h" 9 | #include "mordor/streams/stream.h" 10 | #include "mordor/streams/transfer.h" 11 | #include "mordor/test/test.h" 12 | 13 | using namespace Mordor; 14 | 15 | namespace { 16 | 17 | static Stream::ptr genMemoryStream(size_t length, char b) 18 | { 19 | return Stream::ptr(new MemoryStream(Buffer(std::string(length, b)))); 20 | } 21 | 22 | static void readFully(Stream::ptr stream, Buffer &buffer, size_t size) 23 | { 24 | while(size > 0) { 25 | size_t read = stream->read(buffer, size); 26 | if (read == 0) 27 | MORDOR_THROW_EXCEPTION(Mordor::UnexpectedEofException()); 28 | size -= read; 29 | } 30 | } 31 | 32 | MORDOR_UNITTEST(CatStream, catStreamSeekTest) 33 | { 34 | std::vector streams; 35 | streams.push_back(genMemoryStream(1, '0')); 36 | streams.push_back(genMemoryStream(10, '1')); 37 | streams.push_back(genMemoryStream(30, '2')); 38 | 39 | Stream::ptr catStream(new CatStream(streams)); 40 | transferStream(catStream, NullStream::get_ptr()); 41 | 42 | Buffer buf; 43 | 44 | catStream->seek(0); 45 | readFully(catStream, buf, 1); 46 | MORDOR_TEST_ASSERT_EQUAL(buf.toString(), std::string(1, '0')); 47 | buf.consume(1); 48 | 49 | catStream->seek(2); 50 | readFully(catStream, buf, 9); 51 | MORDOR_TEST_ASSERT_EQUAL(buf.toString(), std::string(9, '1')); 52 | buf.consume(9); 53 | 54 | catStream->seek(13); 55 | readFully(catStream, buf, 28); 56 | MORDOR_TEST_ASSERT_EQUAL(buf.toString(), std::string(28, '2')); 57 | buf.consume(28); 58 | 59 | MORDOR_TEST_ASSERT_EXCEPTION(catStream->seek(100, Stream::CURRENT), std::invalid_argument); 60 | MORDOR_TEST_ASSERT_EXCEPTION(catStream->seek(-15), std::invalid_argument); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /mordor/tests/coroutine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/coroutine.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | using namespace Mordor::Test; 8 | 9 | static void countTo5(Coroutine &self) 10 | { 11 | self.yield(1); 12 | self.yield(2); 13 | self.yield(3); 14 | self.yield(4); 15 | self.yield(5); 16 | } 17 | 18 | MORDOR_UNITTEST(Coroutine, basic) 19 | { 20 | Coroutine coro(&countTo5); 21 | int sequence = 0; 22 | MORDOR_TEST_ASSERT_EQUAL(coro.state(), Fiber::INIT); 23 | int value; 24 | while (true) { 25 | value = coro.call(); 26 | if (coro.state() == Fiber::TERM) 27 | break; 28 | MORDOR_TEST_ASSERT_EQUAL(value, ++sequence); 29 | } 30 | MORDOR_TEST_ASSERT_EQUAL(value, 0); 31 | MORDOR_TEST_ASSERT_EQUAL(sequence, 5); 32 | } 33 | 34 | static void echo(Coroutine &self, int arg) 35 | { 36 | while (arg <= 5) { 37 | arg = self.yield(arg); 38 | } 39 | } 40 | 41 | MORDOR_UNITTEST(Coroutine, basicWithArg) 42 | { 43 | Coroutine coro(&echo); 44 | MORDOR_TEST_ASSERT_EQUAL(coro.state(), Fiber::INIT); 45 | for (int i = 0; i <= 5; ++i) { 46 | MORDOR_TEST_ASSERT(coro.state() == Fiber::INIT || coro.state() == Fiber::HOLD); 47 | MORDOR_TEST_ASSERT_EQUAL(coro.call(i), i); 48 | } 49 | } 50 | 51 | static void countTo5Arg(Coroutine &self, int arg) 52 | { 53 | int sequence = 0; 54 | for (int i = 0; i < 5; ++i) { 55 | MORDOR_TEST_ASSERT_EQUAL(arg, sequence++); 56 | arg = self.yield(); 57 | } 58 | } 59 | 60 | MORDOR_UNITTEST(Coroutine, voidWithArg) 61 | { 62 | Coroutine coro(&countTo5Arg); 63 | for (int i = 0; i < 5; ++i) 64 | coro.call(i); 65 | } 66 | -------------------------------------------------------------------------------- /mordor/tests/counter_stream.cpp: -------------------------------------------------------------------------------- 1 | #include "mordor/streams/counter.h" 2 | #include "mordor/streams/memory.h" 3 | #include "mordor/test/test.h" 4 | 5 | namespace Mordor { 6 | 7 | MORDOR_UNITTEST(CounterStream, countReadWrite) 8 | { 9 | MemoryStream::ptr mem(new MemoryStream); 10 | CounterStream::ptr counter(new CounterStream(mem)); 11 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesRead(), 0U); 12 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesWritten(), 0U); 13 | counter->write("1234567890", 10); 14 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesRead(), 0U); 15 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesWritten(), 10U); 16 | mem->seek(0); 17 | Buffer buffer; 18 | counter->read(buffer, 5); 19 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesRead(), 5U); 20 | MORDOR_TEST_ASSERT_EQUAL(counter->bytesWritten(), 10U); 21 | MORDOR_TEST_ASSERT_EQUAL(buffer.readAvailable(), 5U); 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /mordor/tests/endian.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/endian.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | 8 | MORDOR_UNITTEST(Endian, endian) 9 | { 10 | MORDOR_TEST_ASSERT_EQUAL(byteswap((unsigned short)0x0123u), 0x2301u); 11 | MORDOR_TEST_ASSERT_EQUAL(byteswap(0x01234567u), 0x67452301u); 12 | MORDOR_TEST_ASSERT_EQUAL(byteswap(0x0123456789abcdefull), 0xefcdab8967452301ull); 13 | 14 | MORDOR_TEST_ASSERT_EQUAL(byteswap((unsigned short)0x0123u), 15 | byteswapOnLittleEndian(byteswapOnBigEndian((unsigned short)0x0123u))); 16 | MORDOR_TEST_ASSERT_EQUAL(byteswap(0x01234567u), 17 | byteswapOnLittleEndian(byteswapOnBigEndian(0x01234567u))); 18 | MORDOR_TEST_ASSERT_EQUAL(byteswap(0x0123456789abcdefull), 19 | byteswapOnLittleEndian(byteswapOnBigEndian(0x0123456789abcdefull))); 20 | } 21 | -------------------------------------------------------------------------------- /mordor/tests/fls.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "mordor/fiber.h" 6 | #include "mordor/scheduler.h" 7 | #include "mordor/test/test.h" 8 | 9 | using namespace Mordor; 10 | 11 | static void basic(FiberLocalStorage &fls) 12 | { 13 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 0); 14 | fls = 2; 15 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 2); 16 | Fiber::yield(); 17 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 2); 18 | fls = 4; 19 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 4); 20 | Fiber::yield(); 21 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 4); 22 | fls = 6; 23 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 6); 24 | } 25 | 26 | static void thread(FiberLocalStorage &fls, 27 | Fiber::ptr fiber) 28 | { 29 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 0); 30 | fls = 3; 31 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 3); 32 | fiber->call(); 33 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 3); 34 | fls = 5; 35 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 5); 36 | } 37 | 38 | MORDOR_UNITTEST(FLS, basic) 39 | { 40 | FiberLocalStorage fls; 41 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 0); 42 | fls = 1; 43 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 1); 44 | 45 | Fiber::ptr fiber(new Fiber(boost::bind(&basic, boost::ref(fls)))); 46 | fiber->call(); 47 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 1); 48 | 49 | Thread thread1(boost::bind(&thread, boost::ref(fls), fiber)); 50 | thread1.join(); 51 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 1); 52 | fiber->call(); 53 | MORDOR_TEST_ASSERT_EQUAL(fls.get(), 1); 54 | } 55 | -------------------------------------------------------------------------------- /mordor/tests/pch.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | -------------------------------------------------------------------------------- /mordor/tests/pch.h: -------------------------------------------------------------------------------- 1 | #include "../pch.h" 2 | -------------------------------------------------------------------------------- /mordor/tests/ragel.cpp: -------------------------------------------------------------------------------- 1 | #include "mordor/http/http.h" 2 | #include "mordor/http/parser.h" 3 | #include "mordor/streams/buffer.h" 4 | #include "mordor/streams/memory.h" 5 | #include "mordor/test/test.h" 6 | 7 | using namespace Mordor; 8 | using namespace Mordor::Test; 9 | 10 | MORDOR_UNITTEST(RagelParser, parseFromBuffer) 11 | { 12 | Buffer buf("foo,bar"); 13 | HTTP::StringSet stringset; 14 | HTTP::ListParser parser(stringset); 15 | parser.run(buf); 16 | MORDOR_TEST_ASSERT(!parser.error()); 17 | MORDOR_TEST_ASSERT(parser.complete()); 18 | MORDOR_TEST_ASSERT_EQUAL(stringset.size(), 2U); 19 | MORDOR_TEST_ASSERT(stringset.find("foo") != stringset.end()); 20 | MORDOR_TEST_ASSERT(stringset.find("bar") != stringset.end()); 21 | } 22 | 23 | MORDOR_UNITTEST(RagelParser, parseFromBufferRemains) 24 | { 25 | Buffer buf("list\n"); 26 | HTTP::StringSet stringset; 27 | HTTP::ListParser parser(stringset); 28 | parser.run(buf); 29 | MORDOR_TEST_ASSERT(!parser.error()); 30 | MORDOR_TEST_ASSERT(!parser.complete()); 31 | MORDOR_TEST_ASSERT_EQUAL(stringset.size(), 1U); 32 | MORDOR_TEST_ASSERT_EQUAL(*stringset.begin(), std::string("list")); 33 | } 34 | 35 | MORDOR_UNITTEST(RagelParser, parseFromStream) 36 | { 37 | Stream::ptr stream(new MemoryStream(Buffer("foo,bar"))); 38 | HTTP::StringSet stringset; 39 | HTTP::ListParser parser(stringset); 40 | parser.run(stream); 41 | MORDOR_TEST_ASSERT(!parser.error()); 42 | MORDOR_TEST_ASSERT(parser.complete()); 43 | MORDOR_TEST_ASSERT_EQUAL(stringset.size(), 2U); 44 | MORDOR_TEST_ASSERT(stringset.find("foo") != stringset.end()); 45 | MORDOR_TEST_ASSERT(stringset.find("bar") != stringset.end()); 46 | } 47 | -------------------------------------------------------------------------------- /mordor/tests/run_tests.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "mordor/config.h" 6 | #include "mordor/main.h" 7 | #include "mordor/version.h" 8 | #include "mordor/statistics.h" 9 | #include "mordor/test/antxmllistener.h" 10 | #include "mordor/test/compoundlistener.h" 11 | #include "mordor/test/stdoutlistener.h" 12 | 13 | using namespace Mordor; 14 | using namespace Mordor::Test; 15 | 16 | static ConfigVar::ptr g_xmlDirectory = Config::lookup( 17 | "test.antxml.directory", std::string(), "Location to put XML files"); 18 | 19 | MORDOR_MAIN(int argc, char *argv[]) 20 | { 21 | try { 22 | Config::loadFromCommandLine(argc, argv); 23 | } catch (std::invalid_argument &ex) { 24 | ConfigVarBase::ptr configVar = Config::lookup(ex.what()); 25 | MORDOR_ASSERT(configVar); 26 | std::cerr << "Invalid value for " << typeid(*configVar).name() 27 | << ' ' << configVar->name() << ": " << configVar->description() 28 | << std::endl; 29 | return 1; 30 | } 31 | Config::loadFromEnvironment(); 32 | 33 | CompoundListener listener; 34 | std::string xmlDirectory = g_xmlDirectory->val(); 35 | listener.addListener(boost::shared_ptr( 36 | new StdoutListener())); 37 | if (!xmlDirectory.empty()) { 38 | if (xmlDirectory == ".") 39 | xmlDirectory.clear(); 40 | listener.addListener(boost::shared_ptr( 41 | new AntXMLListener(xmlDirectory))); 42 | } 43 | bool result; 44 | if (argc > 1) { 45 | result = runTests(testsForArguments(argc - 1, argv + 1), listener); 46 | } else { 47 | result = runTests(listener); 48 | } 49 | std::cout << Statistics::dump(); 50 | return result ? 0 : 1; 51 | } 52 | -------------------------------------------------------------------------------- /mordor/tests/statistics.cpp: -------------------------------------------------------------------------------- 1 | #include "mordor/statistics.h" 2 | #include "mordor/test/test.h" 3 | 4 | using namespace Mordor; 5 | 6 | MORDOR_UNITTEST(Statistics, dumpStat) 7 | { 8 | SumStatistic sumStat("s"); 9 | sumStat.add(5); 10 | std::ostringstream os; 11 | sumStat.dump(os); 12 | std::ostringstream expectedOS; 13 | expectedOS << typeid(sumStat).name() << ": " 14 | << sumStat << " s" << std::endl; 15 | MORDOR_TEST_ASSERT_EQUAL(os.str(), expectedOS.str()); 16 | } 17 | -------------------------------------------------------------------------------- /mordor/tests/stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/streams/stream.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | 8 | namespace { 9 | 10 | class NoStream : public Stream 11 | { 12 | bool supportsRead() { return true; } 13 | using Stream::read; 14 | size_t read(Buffer &buffer, size_t length) { return 0; } 15 | }; 16 | 17 | } 18 | 19 | MORDOR_UNITTEST(Stream, emulatedDirectReadEOF) 20 | { 21 | NoStream realstream; 22 | Stream *stream = &realstream; 23 | char buf[1]; 24 | MORDOR_TEST_ASSERT_EQUAL(stream->read(buf, 1), 0u); 25 | } 26 | -------------------------------------------------------------------------------- /mordor/tests/string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/string.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | 8 | MORDOR_UNITTEST(String, dataFromHexstring) 9 | { 10 | MORDOR_TEST_ASSERT_EQUAL(dataFromHexstring(""), ""); 11 | MORDOR_TEST_ASSERT_EQUAL(dataFromHexstring("00"), std::string("\0", 1)); 12 | MORDOR_TEST_ASSERT_EQUAL(dataFromHexstring("abcd"), "\xab\xcd"); 13 | MORDOR_TEST_ASSERT_EQUAL(dataFromHexstring("01eF"), "\x01\xef"); 14 | MORDOR_TEST_ASSERT_EXCEPTION(dataFromHexstring("0"), 15 | std::invalid_argument); 16 | MORDOR_TEST_ASSERT_EXCEPTION(dataFromHexstring("fg"), 17 | std::invalid_argument); 18 | MORDOR_TEST_ASSERT_EXCEPTION(dataFromHexstring("fG"), 19 | std::invalid_argument); 20 | MORDOR_TEST_ASSERT_EXCEPTION(dataFromHexstring(std::string("\0\0", 2)), 21 | std::invalid_argument); 22 | } 23 | 24 | MORDOR_UNITTEST(String, sha0sum) 25 | { 26 | MORDOR_TEST_ASSERT_EQUAL(hexstringFromData(sha0sum("")), "f96cea198ad1dd5617ac084a3d92c6107708c0ef"); 27 | MORDOR_TEST_ASSERT_EQUAL(hexstringFromData(sha0sum("1234567890")), "786abc00fc4c0ab7ea5f0f2bd85fb9ab00c2ad82"); 28 | MORDOR_TEST_ASSERT_EQUAL(hexstringFromData(sha0sum((const void *)"\x7e\x54\xe4\xbc\x27\x00\x40\xab", 8)), "ea1d7982eb4c6201498ece16539ce174735b6a21"); 29 | } 30 | 31 | MORDOR_UNITTEST(String, validateUtf8) 32 | { 33 | MORDOR_TEST_ASSERT(validateUtf8(std::string("hello"))); 34 | MORDOR_TEST_ASSERT(!validateUtf8(std::string("\xc0\xc1", 2))); 35 | MORDOR_TEST_ASSERT(!validateUtf8(std::string("\0\xc0\0\xc1", 4))); 36 | MORDOR_TEST_ASSERT(!validateUtf8(std::string("\xf0\xa7\xad", 3))); 37 | MORDOR_TEST_ASSERT(validateUtf8(std::string("\xf0\xa7\xad\xa2", 4))); 38 | MORDOR_TEST_ASSERT(validateUtf8(std::string("\xfb\xbf\xbf\xbf\xbf", 5))); 39 | MORDOR_TEST_ASSERT(!validateUtf8(std::string("\xf8\x80\x80\x80\x80", 5))); 40 | MORDOR_TEST_ASSERT(validateUtf8(std::string("\xfd\xbf\xbf\xbf\xbf\xbf", 6))); 41 | MORDOR_TEST_ASSERT(!validateUtf8(std::string("\xfc\x80\x80\x80\x80\x80", 6))); 42 | MORDOR_TEST_ASSERT(validateUtf8(std::string("\xfd\xbf\xbf\xbf\xbf\xbf" 43 | "\xfb\xbf\xbf\xbf\xbf" 44 | "\xf0\xa7\xad\xa2" 45 | "\xe8\x80\x80" 46 | "\xd0\xb0" 47 | "\0", 6 + 5 + 4 + 3 + 2 + 1))); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /mordor/tests/temp_stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/streams/temp.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | 8 | MORDOR_UNITTEST(TempStream, SystemTemp) 9 | { 10 | TempStream temp; 11 | MORDOR_ASSERT(temp.supportsRead()); 12 | MORDOR_ASSERT(temp.supportsWrite()); 13 | MORDOR_ASSERT(temp.supportsSeek()); 14 | } 15 | 16 | MORDOR_UNITTEST(TempStream, SystemTempWithPrefix) 17 | { 18 | TempStream temp("mordor"); 19 | MORDOR_ASSERT(temp.supportsRead()); 20 | MORDOR_ASSERT(temp.supportsWrite()); 21 | MORDOR_ASSERT(temp.supportsSeek()); 22 | } 23 | 24 | MORDOR_UNITTEST(TempStream, SystemTempWithPrefix2) 25 | { 26 | TempStream temp("m"); 27 | MORDOR_ASSERT(temp.supportsRead()); 28 | MORDOR_ASSERT(temp.supportsWrite()); 29 | MORDOR_ASSERT(temp.supportsSeek()); 30 | } 31 | -------------------------------------------------------------------------------- /mordor/tests/thread.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "mordor/test/test.h" 6 | #include "mordor/thread.h" 7 | #include "mordor/workerpool.h" 8 | 9 | using namespace Mordor; 10 | 11 | static void threadFunc(tid_t &myTid) 12 | { 13 | myTid = gettid(); 14 | } 15 | 16 | // Tests to make sure the tid as reported by Thread object and inside the 17 | // thread itself are the same (and have a valid value) 18 | MORDOR_UNITTEST(Thread, correctTID) 19 | { 20 | tid_t tid = emptytid(); 21 | Thread t(boost::bind(&threadFunc, boost::ref(tid)), "my thread"); 22 | t.join(); 23 | MORDOR_TEST_ASSERT_NOT_EQUAL(tid, emptytid()); 24 | MORDOR_TEST_ASSERT_EQUAL(tid, t.tid()); 25 | } 26 | 27 | MORDOR_UNITTEST(Thread, bookMark) 28 | { 29 | WorkerPool poolA(1, true), poolB(1, false); 30 | tid_t mainTid = gettid(); 31 | Thread::Bookmark mark; 32 | MORDOR_TEST_ASSERT_EQUAL(mark.tid(), mainTid); 33 | poolB.switchTo(); 34 | tid_t tidB = gettid(); 35 | MORDOR_TEST_ASSERT_NOT_EQUAL(tidB, mainTid); 36 | mark.switchTo(); 37 | tid_t current = gettid(); 38 | MORDOR_TEST_ASSERT_EQUAL(current, mainTid); 39 | } 40 | 41 | namespace { 42 | 43 | struct DummyException : public virtual Mordor::Exception {}; 44 | 45 | static void doSomething(WorkerPool &pool) 46 | { 47 | pool.switchTo(); 48 | } 49 | 50 | static void rethrowException(WorkerPool &poolA, WorkerPool &poolB) 51 | { 52 | tid_t mainTid = 0; 53 | try { 54 | // execute in poolA 55 | poolA.switchTo(); 56 | mainTid = gettid(); 57 | MORDOR_THROW_EXCEPTION(DummyException()); 58 | } catch (...) { 59 | // still in poolA 60 | MORDOR_TEST_ASSERT_EQUAL(gettid(), mainTid); 61 | // do something that might switch or not switch thread 62 | // in this test case, it does switch to a different thread 63 | doSomething(poolB); 64 | MORDOR_TEST_ASSERT_NOT_EQUAL(mainTid, gettid()); 65 | // switch back 66 | // rethrow the exception without any issue 67 | // if we do not handle exception stack, this `throw' can't be caught any 68 | // more, and C++ runtime terminates the program. 69 | throw; 70 | } 71 | } 72 | } 73 | 74 | MORDOR_UNITTEST(Thread, exceptionRethrow) 75 | { 76 | WorkerPool poolA(1, true), poolB(1, false); 77 | MORDOR_TEST_ASSERT_EXCEPTION(rethrowException(poolA, poolB), DummyException); 78 | poolA.switchTo(); 79 | } 80 | -------------------------------------------------------------------------------- /mordor/tests/timeout_stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 - Mozy, Inc. 2 | 3 | #include "mordor/iomanager.h" 4 | #include "mordor/streams/buffer.h" 5 | #include "mordor/streams/delay.h" 6 | #include "mordor/streams/pipe.h" 7 | #include "mordor/streams/timeout.h" 8 | #include "mordor/test/test.h" 9 | 10 | using namespace Mordor; 11 | 12 | MORDOR_UNITTEST(TimeoutStream, readTimeout) 13 | { 14 | IOManager ioManager; 15 | 16 | std::pair streams = pipeStream(); 17 | TimeoutStream::ptr timeout(new TimeoutStream(streams.first, ioManager)); 18 | timeout->readTimeout(0); 19 | 20 | Buffer rb("test"); 21 | MORDOR_TEST_ASSERT_EXCEPTION(timeout->read(rb, 4), TimedOutException); 22 | } 23 | 24 | MORDOR_UNITTEST(TimeoutStream, writeTimeout) 25 | { 26 | IOManager ioManager; 27 | 28 | std::pair streams = pipeStream(1); 29 | DelayStream::ptr delay(new DelayStream(streams.second, &ioManager, 1000)); 30 | TimeoutStream::ptr timeout(new TimeoutStream(delay, ioManager)); 31 | timeout->writeTimeout(0); 32 | 33 | Buffer wb("test"); 34 | size_t len = 4; 35 | try { 36 | while (len > 0) 37 | len -= timeout->write(wb, len); 38 | } catch (TimedOutException &) { 39 | return; 40 | } 41 | MORDOR_NOTREACHED(); 42 | } 43 | 44 | MORDOR_UNITTEST(TimeoutStream, idleTimeout) 45 | { 46 | IOManager ioManager; 47 | 48 | std::pair streams = pipeStream(); 49 | TimeoutStream::ptr timeout(new TimeoutStream(streams.first, ioManager)); 50 | timeout->idleTimeout(0); 51 | 52 | Buffer rb("test"); 53 | MORDOR_TEST_ASSERT_EXCEPTION(timeout->read(rb, 4), TimedOutException); 54 | } 55 | 56 | MORDOR_UNITTEST(TimeoutStream, timeoutSetAfterOpBegan) 57 | { 58 | IOManager ioManager; 59 | 60 | std::pair streams = pipeStream(); 61 | TimeoutStream::ptr timeout(new TimeoutStream(streams.first, ioManager)); 62 | 63 | Buffer rb("test"); 64 | ioManager.schedule(boost::bind(&TimeoutStream::readTimeout, timeout, 0)); 65 | MORDOR_TEST_ASSERT_EXCEPTION(timeout->read(rb, 4), TimedOutException); 66 | } 67 | 68 | MORDOR_UNITTEST(TimeoutStream, timeoutChangedAfterOpBegan) 69 | { 70 | IOManager ioManager; 71 | 72 | std::pair streams = pipeStream(); 73 | TimeoutStream::ptr timeout(new TimeoutStream(streams.first, ioManager)); 74 | 75 | timeout->readTimeout(400000); 76 | Buffer rb("test"); 77 | ioManager.schedule(boost::bind(&TimeoutStream::readTimeout, timeout, 200000)); 78 | unsigned long long now = TimerManager::now(); 79 | MORDOR_TEST_ASSERT_EXCEPTION(timeout->read(rb, 4), TimedOutException); 80 | MORDOR_TEST_ASSERT_ABOUT_EQUAL(TimerManager::now() - now, 200000u, 50000); 81 | } 82 | -------------------------------------------------------------------------------- /mordor/tests/transfer_stream.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/streams/memory.h" 4 | #include "mordor/streams/test.h" 5 | #include "mordor/streams/transfer.h" 6 | #include "mordor/test/test.h" 7 | 8 | using namespace Mordor; 9 | 10 | MORDOR_UNITTEST(TransferStream, exactLengthMultipleReads) 11 | { 12 | Stream::ptr inStream(new MemoryStream()); 13 | TestStream::ptr testStream(new TestStream(inStream)); 14 | testStream->maxReadSize(2); 15 | MemoryStream outStream; 16 | inStream->write("hello", 5); 17 | inStream->write("world", 5); 18 | inStream->seek(0, Stream::BEGIN); 19 | transferStream(testStream, outStream, 7); 20 | MORDOR_TEST_ASSERT_EQUAL(outStream.size(), 7); 21 | MORDOR_TEST_ASSERT_EQUAL(inStream->tell(), 7); 22 | } 23 | 24 | MORDOR_UNITTEST(TransferStream, untilEof) 25 | { 26 | MemoryStream inStream(Buffer("hello")); 27 | MemoryStream outStream; 28 | MORDOR_TEST_ASSERT_EQUAL(transferStream(inStream, outStream, 10, UNTILEOF), 29 | 5ull); 30 | inStream.seek(0); 31 | MORDOR_TEST_ASSERT_EXCEPTION(transferStream(inStream, outStream, 10, 32 | EXACT), UnexpectedEofException); 33 | inStream.seek(0); 34 | MORDOR_TEST_ASSERT_EXCEPTION(transferStream(inStream, outStream, 10), 35 | UnexpectedEofException); 36 | } 37 | 38 | MORDOR_UNITTEST(TransferStream, inferEof) 39 | { 40 | MemoryStream inStream(Buffer("hello")); 41 | MemoryStream outStream; 42 | MORDOR_TEST_ASSERT_EQUAL(transferStream(inStream, outStream), 5ull); 43 | } 44 | -------------------------------------------------------------------------------- /mordor/tests/unicode.cpp: -------------------------------------------------------------------------------- 1 | #include "mordor/pch.h" 2 | 3 | #include "mordor/string.h" 4 | #include "mordor/test/test.h" 5 | 6 | using namespace Mordor; 7 | using namespace Mordor::Test; 8 | 9 | MORDOR_UNITTEST(Unicode, toUtf8) 10 | { 11 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\0'), std::string("\0", 1)); 12 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x1'), "\x1"); 13 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x7f'), "\x7f"); 14 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x80'), "\xc2\x80"); 15 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x7ff'), "\xdf\xbf"); 16 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x800'), "\xe0\xa0\x80"); 17 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\xffff'), "\xef\xbf\xbf"); 18 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf32char)0x10000), "\xf0\x90\x80\x80"); 19 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf32char)0x10ffff), "\xf4\x8f\xbf\xbf"); 20 | 21 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'$'), "$"); 22 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\xa2'), "\xc2\xa2"); 23 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf16char)L'\x20ac'), "\xe2\x82\xac"); 24 | MORDOR_TEST_ASSERT_EQUAL(toUtf8((utf32char)0x024b62), "\xf0\xa4\xad\xa2"); 25 | } 26 | 27 | MORDOR_UNITTEST(Unicode, surrogatePairs) 28 | { 29 | MORDOR_TEST_ASSERT_EQUAL(toUtf32(L'\xd800', L'\xdc00'), 0x10000); 30 | MORDOR_TEST_ASSERT_EQUAL(toUtf32(L'\xdbff', L'\xdffd'), 0x10fffd); 31 | } 32 | 33 | #if defined(WINDOWS) || defined(OSX) || defined(HAVE_ICONV) 34 | 35 | MORDOR_UNITTEST(Unicode, badUtf8Exception) 36 | { 37 | MORDOR_TEST_ASSERT_EXCEPTION(toUtf16("\xc0\xc1"), InvalidUnicodeException); 38 | } 39 | 40 | #endif 41 | 42 | #if defined(OSX) 43 | MORDOR_UNITTEST(Unicode, toUtf8OSX) 44 | { 45 | // Two characters, each requiring 3 bytes for utf8 representation (see rm122624) 46 | unsigned char chinese[] = {0xE4, 0xBD, 0xA0, 0xE5, 0xA5, 0xBD, 0}; 47 | CFStringRef cfStr = CFStringCreateWithCString(kCFAllocatorDefault, (const char *)chinese, kCFStringEncodingUTF8); 48 | std::string converted = toUtf8(cfStr); 49 | MORDOR_TEST_ASSERT_EQUAL(converted, std::string((const char *)chinese)); 50 | CFRelease(cfStr); 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /mordor/tests/util.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include 4 | 5 | #include "mordor/util.h" 6 | #include "mordor/test/test.h" 7 | 8 | using namespace Mordor; 9 | using namespace Mordor::Test; 10 | 11 | 12 | MORDOR_UNITTEST(Util, muldiv64) 13 | { 14 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(0, 1, 1), 0ULL); 15 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(1, 0, 2), 0ULL); 16 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(1, 2, 3), 0ULL); 17 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(3, 2, 1), 6ULL); 18 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(43849324ULL, 11289432, 65463), 7562042093ULL); 19 | 20 | // this computation would overflow without muldiv64() 21 | MORDOR_TEST_ASSERT_EQUAL(muldiv64(0x1111111111111111ULL, 5000000, 1000000), 0x5555555555555555ULL); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /mordor/tests/zip.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "mordor/streams/deflate.h" 4 | #include "mordor/streams/memory.h" 5 | #include "mordor/streams/singleplex.h" 6 | #include "mordor/streams/transfer.h" 7 | #include "mordor/test/test.h" 8 | #include "mordor/zip.h" 9 | 10 | using namespace Mordor; 11 | 12 | MORDOR_UNITTEST(Zip, compressionMethod) 13 | { 14 | { 15 | MemoryStream::ptr stream(new MemoryStream); 16 | Zip zip(stream); 17 | ZipEntry& entry = zip.addFile(); 18 | entry.filename("test"); 19 | entry.compressionMethod(0); 20 | 21 | const std::string data("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY0123456789"); 22 | Buffer buffer(data); 23 | MemoryStream mem(buffer); 24 | transferStream(mem, entry.stream()); 25 | zip.close(); 26 | 27 | stream->seek(0); 28 | MORDOR_TEST_ASSERT_GREATER_THAN(stream->find(data), 0); 29 | Stream::ptr singleEx(new SingleplexStream(stream, SingleplexStream::READ)); 30 | Zip zipEx(singleEx); 31 | const ZipEntry* entryEx = zipEx.getNextEntry(); 32 | MORDOR_TEST_ASSERT(entryEx); 33 | MORDOR_TEST_ASSERT_EQUAL(entryEx->compressionMethod(), 0); 34 | } 35 | 36 | 37 | { 38 | MemoryStream::ptr stream(new MemoryStream); 39 | Stream::ptr single(new SingleplexStream(stream, SingleplexStream::WRITE)); 40 | Zip zip(single); 41 | ZipEntry& entry = zip.addFile(); 42 | entry.filename("test"); 43 | entry.compressionMethod(8); 44 | 45 | const std::string data("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY0123456789"); 46 | Buffer buffer(data); 47 | MemoryStream mem(buffer); 48 | transferStream(mem, entry.stream()); 49 | zip.close(); 50 | 51 | Stream::ptr out(new MemoryStream); 52 | Stream::ptr singleDef(new SingleplexStream(out, SingleplexStream::WRITE)); 53 | DeflateStream deflate(singleDef, false); 54 | deflate.write(buffer, data.length()); 55 | deflate.close(); 56 | out->seek(0); 57 | std::string dest = boost::static_pointer_cast(out)->readBuffer().toString(); 58 | 59 | stream->seek(0); 60 | MORDOR_TEST_ASSERT_GREATER_THAN(stream->find(dest), 0); 61 | Stream::ptr singleEx(new SingleplexStream(stream, SingleplexStream::READ)); 62 | Zip zipEx(singleEx); 63 | const ZipEntry* entryEx = zipEx.getNextEntry(); 64 | MORDOR_TEST_ASSERT(entryEx); 65 | MORDOR_TEST_ASSERT_EQUAL(entryEx->compressionMethod(), 8); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /mordor/thirdPartyPaths-win32-v12.Debug.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | $(winclientlib)\zlib\include;$(winclientlib)\openssl\openssl-1.0.1e\include;$(winclientlib)\boost\boost_1_61_0;$(winclientlib)\lzma\include;$(winclientlib)\protobuf\protobuf-3.0\include;$(IncludePath) 6 | 7 | 8 | $(winclientlib)\openssl\openssl-1.0.1e\openssl-1.0.1e-vc12-x86-debug;$(winclientlib)\zlib\zlib-vc12-x86-debug;$(winclientlib)\boost\boost_1_61_0\lib32-msvc-12.0;$(winclientlib)\protobuf\protobuf-3.0\vc12-x86\lib;$(LibraryPath) 9 | $(winclientlib)\tools;$(ExecutablePath) 10 | 11 | -------------------------------------------------------------------------------- /mordor/thirdPartyPaths-win32-v12.Release.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | $(winclientlib)\zlib\include;$(winclientlib)\openssl\openssl-1.0.1e\include;$(winclientlib)\boost\boost_1_61_0;$(winclientlib)\lzma\include;$(winclientlib)\protobuf\protobuf-3.0\include;$(IncludePath) 6 | 7 | 8 | $(winclientlib)\openssl\openssl-1.0.1e\openssl-1.0.1e-vc12-x86-release;$(winclientlib)\zlib\zlib-vc12-x86-release;$(winclientlib)\boost\boost_1_61_0\lib32-msvc-12.0;$(winclientlib)\protobuf\protobuf-3.0\vc12-x86\lib;$(LibraryPath) 9 | $(winclientlib)\tools;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); 10 | 11 | -------------------------------------------------------------------------------- /mordor/thirdPartyPaths-win64-v12.Debug.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(winclientlib)\zlib\include;$(winclientlib)\openssl\openssl-1.0.1e\include;$(winclientlib)\boost\boost_1_61_0;$(winclientlib)\lzma\include;$(winclientlib)\protobuf\protobuf-3.0\include;$(IncludePath) 5 | 6 | 7 | $(winclientlib)\openssl\openssl-1.0.1e\openssl-1.0.1e-vc12-x64-debug;$(winclientlib)\zlib\zlib-vc12-x64-debug;$(winclientlib)\boost\boost_1_61_0\lib64-msvc-12.0;$(winclientlib)\protobuf\protobuf-3.0\vc12-x64\lib;$(LibraryPath) 8 | $(winclientlib)\tools;$(ExecutablePath) 9 | 10 | -------------------------------------------------------------------------------- /mordor/thirdPartyPaths-win64-v12.Release.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(winclientlib)\zlib\include;$(winclientlib)\openssl\openssl-1.0.1e\include;$(winclientlib)\boost\boost_1_61_0;$(winclientlib)\lzma\include;$(winclientlib)\protobuf\protobuf-3.0\include;$(IncludePath) 5 | 6 | 7 | $(winclientlib)\openssl\openssl-1.0.1e\openssl-1.0.1e-vc12-x64-release;$(winclientlib)\zlib\zlib-vc12-x64-release;$(winclientlib)\boost\boost_1_61_0\lib64-msvc-12.0;$(winclientlib)\protobuf\protobuf-3.0\vc12-x64\lib;$(LibraryPath) 8 | $(winclientlib)\tools;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); 9 | 10 | -------------------------------------------------------------------------------- /mordor/thirdPartyPaths-win64.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(winclientlib)\boost\boost_1_57_0;$(winclientlib)\openssl\openssl-1.0.1e-x64\include;$(winclientlib)\zlib\include;$(IncludePath) 7 | $(winclientlib)\tools;$(ExecutablePath) 8 | $(winclientlib)\boost\boost_1_57_0\lib64-msvc-12.0;$(winclientlib)\openssl\openssl-1.0.1e-x64\lib;$(winclientlib)\zlib\lib64;$(LibraryPath) 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /mordor/thread.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_THREAD_H__ 2 | #define __MORDOR_THREAD_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "version.h" 11 | #ifndef WINDOWS 12 | #include "semaphore.h" 13 | #endif 14 | 15 | namespace Mordor { 16 | 17 | #ifdef WINDOWS 18 | typedef DWORD tid_t; 19 | #elif defined(LINUX) 20 | typedef pid_t tid_t; 21 | #elif defined(OSX) 22 | typedef mach_port_t tid_t; 23 | #else 24 | typedef pthread_t tid_t; 25 | #endif 26 | 27 | inline tid_t emptytid() { return (tid_t)-1; } 28 | tid_t gettid(); 29 | 30 | class Scheduler; 31 | 32 | class Thread : boost::noncopyable 33 | { 34 | public: 35 | /// thread bookmark 36 | /// 37 | /// bookmark current thread id and scheduler, allow to switch back to 38 | /// the same thread id later. 39 | /// @pre The process must be running with available scheduler, otherwise 40 | /// it is not possible to switch execution between threads with bookmark. 41 | /// @note Bookmark was designed to address the issue where we failed to 42 | /// rethrow an exception in catch block, because GCC C++ runtime saves the 43 | /// exception stack in a pthread TLS variable. and swapcontext(3) does not 44 | /// take care of TLS. but developer needs to be more aware of underlying 45 | /// thread using thread bookmark, so we developed another way to fix this 46 | /// problem. thus bookmark only serve as a way which allow user to stick 47 | /// to a native thread. 48 | class Bookmark 49 | { 50 | public: 51 | Bookmark(); 52 | /// switch to bookmark's tid 53 | void switchTo(); 54 | /// bookmark's tid 55 | tid_t tid() const { return m_tid; } 56 | 57 | private: 58 | Scheduler *m_scheduler; 59 | tid_t m_tid; 60 | }; 61 | 62 | public: 63 | Thread(boost::function dg, const char *name = NULL); 64 | ~Thread(); 65 | 66 | tid_t tid() const { return m_tid; } 67 | 68 | void join(); 69 | 70 | private: 71 | static 72 | #ifdef WINDOWS 73 | unsigned WINAPI 74 | #else 75 | void * 76 | #endif 77 | run(void *arg); 78 | 79 | private: 80 | tid_t m_tid; 81 | #ifdef WINDOWS 82 | HANDLE m_hThread; 83 | #else 84 | pthread_t m_thread; 85 | #endif 86 | 87 | #ifdef LINUX 88 | boost::function m_dg; 89 | Semaphore m_semaphore; 90 | const char *m_name; 91 | #endif 92 | }; 93 | 94 | } 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /mordor/thread_local_storage.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_THREAD_LOCAL_STORAGE_H__ 2 | #define __MORDOR_THREAD_LOCAL_STORAGE_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "predef.h" 6 | 7 | #include 8 | 9 | #ifdef WINDOWS 10 | #include 11 | #else 12 | #include 13 | #endif 14 | 15 | #include "exception.h" 16 | 17 | namespace Mordor { 18 | 19 | template 20 | class ThreadLocalStorageBase : boost::noncopyable 21 | { 22 | public: 23 | ThreadLocalStorageBase() 24 | { 25 | #ifdef WINDOWS 26 | m_key = TlsAlloc(); 27 | if (m_key == TLS_OUT_OF_INDEXES) 28 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("TlsAlloc"); 29 | #else 30 | int rc = pthread_key_create(&m_key, NULL); 31 | if (rc) 32 | MORDOR_THROW_EXCEPTION_FROM_ERROR_API(rc, "pthread_create_specific"); 33 | #endif 34 | } 35 | 36 | ~ThreadLocalStorageBase() 37 | { 38 | #ifdef WINDOWS 39 | TlsFree(m_key); 40 | #else 41 | pthread_key_delete(m_key); 42 | #endif 43 | } 44 | 45 | typename boost::enable_if_c::type set(const T &t) 46 | { 47 | #ifdef WINDOWS 48 | if (!TlsSetValue(m_key, (LPVOID)t)) 49 | MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("TlsSetValue"); 50 | #else 51 | int rc = pthread_setspecific(m_key, (const void *)t); 52 | if (rc) 53 | MORDOR_THROW_EXCEPTION_FROM_ERROR_API(rc, "pthread_setspecific"); 54 | #endif 55 | } 56 | 57 | T get() const 58 | { 59 | #ifdef WINDOWS 60 | #pragma warning(push) 61 | #pragma warning(disable: 4800) 62 | DWORD lastError = GetLastError(); 63 | LPVOID result = TlsGetValue(m_key); 64 | SetLastError(lastError); 65 | return (T)result; 66 | #pragma warning(pop) 67 | #else 68 | return (T)pthread_getspecific(m_key); 69 | #endif 70 | } 71 | 72 | operator T() const { return get(); } 73 | 74 | private: 75 | #ifdef WINDOWS 76 | DWORD m_key; 77 | #else 78 | pthread_key_t m_key; 79 | #endif 80 | }; 81 | 82 | template 83 | class ThreadLocalStorage : public ThreadLocalStorageBase 84 | { 85 | public: 86 | T operator =(T t) { ThreadLocalStorageBase::set(t); return t; } 87 | }; 88 | 89 | template 90 | class ThreadLocalStorage : public ThreadLocalStorageBase 91 | { 92 | public: 93 | T * operator =(T *const t) { ThreadLocalStorageBase::set(t); return t; } 94 | T & operator*() { return *ThreadLocalStorageBase::get(); } 95 | T * operator->() { return ThreadLocalStorageBase::get(); } 96 | }; 97 | 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /mordor/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "endian.h" 3 | 4 | namespace Mordor 5 | { 6 | 7 | // muldiv64() was adapted from 8 | // http://www.virtualbox.org/browser/trunk/src/VBox/Devices/muldiv64.c?rev=1 9 | // 10 | // the following copyright notice applies: 11 | /* 12 | * QEMU System Emulator 13 | * 14 | * Copyright (c) 2003-2004 Fabrice Bellard 15 | * 16 | * Permission is hereby granted, free of charge, to any person obtaining a copy 17 | * of this software and associated documentation files (the "Software"), to deal 18 | * in the Software without restriction, including without limitation the rights 19 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | * copies of the Software, and to permit persons to whom the Software is 21 | * furnished to do so, subject to the following conditions: 22 | * 23 | * The above copyright notice and this permission notice shall be included in 24 | * all copies or substantial portions of the Software. 25 | * 26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 32 | * THE SOFTWARE. 33 | */ 34 | 35 | /* compute with 96 bit intermediate result: (a*b)/c */ 36 | uint64_t muldiv64(uint64_t a, uint32_t b, uint64_t c) 37 | { 38 | union { 39 | uint64_t ll; 40 | struct { 41 | #if MORDOR_BYTE_ORDER == MORDOR_BIG_ENDIAN 42 | uint32_t high, low; 43 | #else 44 | uint32_t low, high; 45 | #endif 46 | } l; 47 | } u, res; 48 | uint64_t rl, rh; 49 | 50 | u.ll = a; 51 | rl = (uint64_t)u.l.low * (uint64_t)b; 52 | rh = (uint64_t)u.l.high * (uint64_t)b; 53 | rh += (rl >> 32); 54 | res.l.high = (uint32_t)(rh / c); 55 | res.l.low = (uint32_t)((((rh % c) << 32) + (rl & 0xffffffff)) / c); 56 | return res.ll; 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /mordor/version.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_VERSION_H__ 2 | #define __MORDOR_VERSION_H__ 3 | 4 | // OS 5 | #ifdef _WIN32 6 | # define WINDOWS 7 | #else 8 | # define POSIX 9 | #endif 10 | #ifdef __CYGWIN__ 11 | # define WINDOWS 12 | # define CYGWIN 13 | #endif 14 | 15 | #if defined(linux) || defined(__linux__) 16 | # define LINUX 17 | #endif 18 | 19 | #ifdef __APPLE__ 20 | # define OSX 21 | # ifndef BSD 22 | # define BSD 23 | # endif 24 | #endif 25 | 26 | #ifdef __FreeBSD__ 27 | # define FREEBSD 28 | # define BSD 29 | #endif 30 | 31 | #ifdef WINDOWS 32 | #define MORDOR_NATIVE(win32, posix) win32 33 | #else 34 | #define MORDOR_NATIVE(win32, posix) posix 35 | #endif 36 | 37 | // Architecture 38 | #ifdef _MSC_VER 39 | # define MSVC 40 | # ifdef _M_X64 41 | # define X86_64 42 | # elif defined(_M_IX86) 43 | # define X86 44 | # endif 45 | #endif 46 | 47 | #ifdef __GNUC__ 48 | # define GCC 49 | # ifdef __x86_64 50 | # define X86_64 51 | # elif defined(__i386__) 52 | # define X86 53 | # elif defined(__ppc__) 54 | # define PPC 55 | # elif defined(__arm__) 56 | # define ARM 57 | # endif 58 | #endif 59 | 60 | #ifdef MSVC 61 | # ifndef _DEBUG 62 | # ifndef NDEBUG 63 | # define NDEBUG 64 | # endif 65 | # endif 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /mordor/workerpool.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 - Mozy, Inc. 2 | 3 | #include "workerpool.h" 4 | 5 | #include "fiber.h" 6 | #include "log.h" 7 | 8 | namespace Mordor { 9 | 10 | static Logger::ptr g_log = Log::lookup("mordor:workerpool"); 11 | 12 | WorkerPool::WorkerPool(size_t threads, bool useCaller, size_t batchSize) 13 | : Scheduler(threads, useCaller, batchSize) 14 | { 15 | start(); 16 | } 17 | 18 | void 19 | WorkerPool::idle() 20 | { 21 | while (true) { 22 | if (stopping()) { 23 | return; 24 | } 25 | m_semaphore.wait(); 26 | try { 27 | Fiber::yield(); 28 | } catch (OperationAbortedException &) { 29 | return; 30 | } 31 | } 32 | } 33 | 34 | void 35 | WorkerPool::tickle() 36 | { 37 | MORDOR_LOG_DEBUG(g_log) << this << " tickling"; 38 | m_semaphore.notify(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /mordor/workerpool.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_WORKERPOOL_H__ 2 | #define __MORDOR_WORKERPOOL_H__ 3 | // Copyright (c) 2009 - Mozy, Inc. 4 | 5 | #include "scheduler.h" 6 | #include "semaphore.h" 7 | 8 | namespace Mordor { 9 | 10 | /// Generic Scheduler 11 | 12 | /// A WorkerPool is a generic Scheduler that does nothing when there is no work 13 | /// to be done. 14 | class WorkerPool : public Scheduler 15 | { 16 | public: 17 | WorkerPool(size_t threads = 1, bool useCaller = true, size_t batchSize = 1); 18 | ~WorkerPool() { stop(); } 19 | 20 | protected: 21 | /// The idle Fiber for a WorkerPool simply loops waiting on a Semaphore, 22 | /// and yields whenever that Semaphore is signalled, returning if 23 | /// stopping() is true. 24 | void idle(); 25 | /// Signals the semaphore so that the idle Fiber will yield. 26 | void tickle(); 27 | 28 | private: 29 | Semaphore m_semaphore; 30 | }; 31 | 32 | } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /mordor/xml/.gitignore: -------------------------------------------------------------------------------- 1 | xml_parser.cpp 2 | 3 | -------------------------------------------------------------------------------- /mordor/yaml.h: -------------------------------------------------------------------------------- 1 | #ifndef __MORDOR_YAML_H__ 2 | #define __MORDOR_YAML_H__ 3 | // Copyright (c) 2010 - Mozy, Inc. 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include "exception.h" 10 | #include "json.h" 11 | 12 | namespace Mordor { 13 | class Stream; 14 | 15 | namespace YAML { 16 | 17 | struct Exception : virtual Mordor::Exception 18 | { 19 | public: 20 | Exception(const char *problem, const char *context) 21 | : m_problem(problem), 22 | m_context(context) 23 | {} 24 | 25 | const char *what() const throw() { return m_problem; } 26 | 27 | private: 28 | const char *m_problem; 29 | const char *m_context; 30 | }; 31 | 32 | /// @note YAML parser tags all scalar node as a string if not specified explicitly 33 | /// it could parse scalar node to a particular type if type info is explicitly specified, e.g. 34 | /// @verbatim 35 | /// name: !!str "John" 36 | /// price: !!float "0.278" 37 | /// quantity: !!int "500" 38 | /// @endverbatim 39 | 40 | JSON::Value parse(const std::string &string); 41 | JSON::Value parse(Stream &stream); 42 | JSON::Value parse(boost::shared_ptr stream); 43 | 44 | }} 45 | 46 | #endif 47 | --------------------------------------------------------------------------------