mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2024-11-26 19:30:21 +00:00
Also see https://groups.google.com/forum/#!topic/cryptopp-users/5btwLoxXXD4.
This commit is contained in:
parent
522da15b13
commit
f2171cbe2f
10
Filelist.txt
10
Filelist.txt
@ -202,8 +202,6 @@ naclite.h
|
||||
nbtheory.cpp
|
||||
nbtheory.h
|
||||
neon-simd.cpp
|
||||
network.cpp
|
||||
network.h
|
||||
nr.h
|
||||
oaep.cpp
|
||||
oaep.h
|
||||
@ -311,8 +309,6 @@ sm4.cpp
|
||||
sm4-simd.cpp
|
||||
sm4.h
|
||||
smartptr.h
|
||||
socketft.cpp
|
||||
socketft.h
|
||||
sosemanuk.cpp
|
||||
sosemanuk.h
|
||||
speck.cpp
|
||||
@ -336,8 +332,6 @@ threefish.h
|
||||
tiger.cpp
|
||||
tiger.h
|
||||
tigertab.cpp
|
||||
trdlocal.cpp
|
||||
trdlocal.h
|
||||
trunhash.h
|
||||
ttmac.cpp
|
||||
ttmac.h
|
||||
@ -360,14 +354,10 @@ validate.h
|
||||
vmac.cpp
|
||||
vmac.h
|
||||
vs2005.zip
|
||||
wait.cpp
|
||||
wait.h
|
||||
wake.cpp
|
||||
wake.h
|
||||
whrlpool.cpp
|
||||
whrlpool.h
|
||||
winpipes.cpp
|
||||
winpipes.h
|
||||
words.h
|
||||
x64dll.asm
|
||||
x64masm.asm
|
||||
|
53
config.h
53
config.h
@ -142,15 +142,6 @@
|
||||
// see http://github.com/weidai11/cryptopp/issues/389.
|
||||
// #define CRYPTOPP_NO_ASSIGN_TO_INTEGER
|
||||
|
||||
// choose which style of sockets to wrap (mostly useful for MinGW which has both)
|
||||
#if !defined(NO_BERKELEY_STYLE_SOCKETS) && !defined(PREFER_BERKELEY_STYLE_SOCKETS)
|
||||
# define PREFER_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
// #if !defined(NO_WINDOWS_STYLE_SOCKETS) && !defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
||||
// # define PREFER_WINDOWS_STYLE_SOCKETS
|
||||
// #endif
|
||||
|
||||
// set the name of Rijndael cipher, was "Rijndael" before version 5.3
|
||||
#define CRYPTOPP_RIJNDAEL_NAME "AES"
|
||||
|
||||
@ -219,10 +210,6 @@ namespace CryptoPP { }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
||||
# define __USE_W32_SOCKETS
|
||||
#endif
|
||||
|
||||
// Originally in global namespace to avoid ambiguity with other byte typedefs.
|
||||
// Moved to Crypto++ namespace due to C++17, std::byte and potential compile problems. Also see
|
||||
// http://www.cryptopp.com/wiki/std::byte and http://github.com/weidai11/cryptopp/issues/442
|
||||
@ -912,46 +899,10 @@ NAMESPACE_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
||||
# define HAS_BERKELEY_STYLE_SOCKETS
|
||||
# define SOCKETS_AVAILABLE
|
||||
#endif
|
||||
|
||||
// Sockets are only available under Windows Runtime desktop partition apps (despite the MSDN literature)
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# define HAS_WINDOWS_STYLE_SOCKETS
|
||||
# if !defined(WINAPI_FAMILY)
|
||||
# define SOCKETS_AVAILABLE
|
||||
# elif defined(WINAPI_FAMILY)
|
||||
# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
|
||||
# define SOCKETS_AVAILABLE
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
|
||||
# define USE_WINDOWS_STYLE_SOCKETS
|
||||
#else
|
||||
# define USE_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(SOCKETS_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
|
||||
# define WINDOWS_PIPES_AVAILABLE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define BLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
# define HAS_PTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
// Early IBM XL C on AIX fails to link due to missing pthread gear
|
||||
#if defined(_AIX) && defined(__xlC__)
|
||||
# undef HAS_PTHREADS
|
||||
# undef THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
// Cygwin/Newlib requires _XOPEN_SOURCE=600
|
||||
@ -961,14 +912,10 @@ NAMESPACE_END
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# if !defined(WINAPI_FAMILY)
|
||||
# define HAS_WINTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
# elif defined(WINAPI_FAMILY)
|
||||
# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
|
||||
# define HAS_WINTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
# elif !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP))
|
||||
|
@ -240,7 +240,6 @@
|
||||
<ClCompile Include="skipjack.cpp" />
|
||||
<ClCompile Include="sse-simd.cpp" />
|
||||
<ClCompile Include="strciphr.cpp" />
|
||||
<ClCompile Include="trdlocal.cpp" />
|
||||
</ItemGroup>
|
||||
<!-- Header Files -->
|
||||
<ItemGroup>
|
||||
@ -309,7 +308,6 @@
|
||||
<ClInclude Include="stdcpp.h" />
|
||||
<ClInclude Include="strciphr.h" />
|
||||
<ClInclude Include="trap.h" />
|
||||
<ClInclude Include="trdlocal.h" />
|
||||
<ClInclude Include="words.h" />
|
||||
</ItemGroup>
|
||||
<!-- Back to Visual Studio boilerplate -->
|
||||
|
@ -45,11 +45,9 @@
|
||||
|
||||
###########################################################################################
|
||||
|
||||
# If you use 'make sources' from Linux makefile, then add 'winpipes.cpp' to the list below.
|
||||
LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rabbit.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck-simd.cpp simeck.cpp simon.cpp simon64-simd.cpp simon128-simd.cpp skipjack.cpp sm3.cpp sm4.cpp sm4-simd.cpp sosemanuk.cpp speck.cpp speck64-simd.cpp speck128-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wake.cpp whrlpool.cp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
|
||||
|
||||
LIB_SRCS = cryptlib.cpp cpu.cpp integer.cpp 3way.cpp adler32.cpp algebra.cpp algparam.cpp arc4.cpp aria-simd.cpp aria.cpp ariatab.cpp asn.cpp authenc.cpp base32.cpp base64.cpp basecode.cpp bfinit.cpp blake2-simd.cpp blake2.cpp blowfish.cpp blumshub.cpp camellia.cpp cast.cpp casts.cpp cbcmac.cpp ccm.cpp chacha.cpp cham.cpp cham-simd.cpp channels.cpp cmac.cpp crc-simd.cpp crc.cpp default.cpp des.cpp dessp.cpp dh.cpp dh2.cpp dll.cpp dsa.cpp eax.cpp ec2n.cpp eccrypto.cpp ecp.cpp elgamal.cpp emsa2.cpp eprecomp.cpp esign.cpp files.cpp filters.cpp fips140.cpp fipstest.cpp gcm-simd.cpp gcm.cpp gf256.cpp gf2_32.cpp gf2n.cpp gfpcrypt.cpp gost.cpp gzip.cpp hc128.cpp hc256.cpp hex.cpp hight.cpp hmac.cpp hrtimer.cpp ida.cpp idea.cpp iterhash.cpp kalyna.cpp kalynatab.cpp keccak.cpp lea.cpp lea-simd.cpp luc.cpp mars.cpp marss.cpp md2.cpp md4.cpp md5.cpp misc.cpp modes.cpp mqueue.cpp mqv.cpp nbtheory.cpp neon-simd.cpp network.cpp oaep.cpp osrng.cpp padlkrng.cpp panama.cpp pkcspad.cpp poly1305.cpp polynomi.cpp pssr.cpp pubkey.cpp queue.cpp rabin.cpp randpool.cpp rabbit.cpp rc2.cpp rc5.cpp rc6.cpp rdrand.cpp rdtables.cpp rijndael-simd.cpp rijndael.cpp ripemd.cpp rng.cpp rsa.cpp rw.cpp safer.cpp salsa.cpp scrypt.cpp seal.cpp seed.cpp serpent.cpp sha-simd.cpp sha.cpp sha3.cpp shacal2-simd.cpp shacal2.cpp shark.cpp sharkbox.cpp simeck-simd.cpp simeck.cpp simon.cpp simon64-simd.cpp simon128-simd.cpp skipjack.cpp sm3.cpp sm4.cpp sm4-simd.cpp socketft.cpp sosemanuk.cpp speck.cpp speck64-simd.cpp speck128-simd.cpp square.cpp squaretb.cpp sse-simd.cpp strciphr.cpp tea.cpp tftables.cpp threefish.cpp tiger.cpp tigertab.cpp trdlocal.cpp ttmac.cpp tweetnacl.cpp twofish.cpp vmac.cpp wait.cpp wake.cpp whrlpool.cpp winpipes.cpp xtr.cpp xtrcrypt.cpp zdeflate.cpp zinflate.cpp zlib.cpp
|
||||
|
||||
LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj network.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rabbit.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck-simd.obj simeck.obj simon.obj simon64-simd.obj simon128-simd.obj skipjack.obj sm3.obj sm4.obj sm4-simd.obj socketft.obj sosemanuk.obj speck.obj speck64-simd.obj speck128-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj trdlocal.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wait.obj wake.obj whrlpool.obj winpipes.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
|
||||
LIB_OBJS = cryptlib.obj cpu.obj integer.obj 3way.obj adler32.obj algebra.obj algparam.obj arc4.obj aria-simd.obj aria.obj ariatab.obj asn.obj authenc.obj base32.obj base64.obj basecode.obj bfinit.obj blake2-simd.obj blake2.obj blowfish.obj blumshub.obj camellia.obj cast.obj casts.obj cbcmac.obj ccm.obj chacha.obj cham.obj cham-simd.obj channels.obj cmac.obj crc-simd.obj crc.obj default.obj des.obj dessp.obj dh.obj dh2.obj dll.obj dsa.obj eax.obj ec2n.obj eccrypto.obj ecp.obj elgamal.obj emsa2.obj eprecomp.obj esign.obj files.obj filters.obj fips140.obj fipstest.obj gcm-simd.obj gcm.obj gf256.obj gf2_32.obj gf2n.obj gfpcrypt.obj gost.obj gzip.obj hc128.obj hc256.obj hex.obj hight.obj hmac.obj hrtimer.obj ida.obj idea.obj iterhash.obj kalyna.obj kalynatab.obj keccak.obj lea.obj lea-simd.obj luc.obj mars.obj marss.obj md2.obj md4.obj md5.obj misc.obj modes.obj mqueue.obj mqv.obj nbtheory.obj neon-simd.obj oaep.obj osrng.obj padlkrng.obj panama.obj pkcspad.obj poly1305.obj polynomi.obj pssr.obj pubkey.obj queue.obj rabin.obj randpool.obj rabbit.obj rc2.obj rc5.obj rc6.obj rdrand.obj rdtables.obj rijndael-simd.obj rijndael.obj ripemd.obj rng.obj rsa.obj rw.obj safer.obj salsa.obj scrypt.obj seal.obj seed.obj serpent.obj sha-simd.obj sha.obj sha3.obj shacal2-simd.obj shacal2.obj shark.obj sharkbox.obj simeck-simd.obj simeck.obj simon.obj simon64-simd.obj simon128-simd.obj skipjack.obj sm3.obj sm4.obj sm4-simd.obj sosemanuk.obj speck.obj speck64-simd.obj speck128-simd.obj square.obj squaretb.obj sse-simd.obj strciphr.obj tea.obj tftables.obj threefish.obj tiger.obj tigertab.obj ttmac.obj tweetnacl.obj twofish.obj vmac.obj wake.obj whrlpool.obj xtr.obj xtrcrypt.obj zdeflate.obj zinflate.obj zlib.obj
|
||||
|
||||
TEST_SRCS = bench1.cpp bench2.cpp bench3.cpp test.cpp validat0.cpp validat1.cpp validat2.cpp validat3.cpp validat4.cpp validat5.cpp validat6.cpp validat7.cpp validat8.cpp validat9.cpp validat10.cpp datatest.cpp regtest1.cpp regtest2.cpp regtest3.cpp regtest4.cpp fipsalgt.cpp dlltest.cpp fipstest.cpp
|
||||
|
||||
@ -108,7 +106,7 @@ ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh
|
||||
LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm
|
||||
LIB_OBJS = $(LIB_OBJS) rdrand.obj rdrand-x86.obj
|
||||
LDFLAGS = $(LDFLAGS) /MACHINE:X86
|
||||
LDLIBS = $(LDLIBS) ws2_32.lib kernel32.lib
|
||||
LDLIBS = $(LDLIBS) kernel32.lib
|
||||
!ENDIF
|
||||
|
||||
# May need $(VCINSTALLDIR)\bin\amd64\ml64.exe
|
||||
@ -121,7 +119,7 @@ ASFLAGS = /nologo /D_M_X64 /W3 /Cx /Zi
|
||||
LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm
|
||||
LIB_OBJS = $(LIB_OBJS) rdrand.obj rdrand-x64.obj x64masm.obj x64dll.obj
|
||||
LDFLAGS = $(LDFLAGS) /MACHINE:X64
|
||||
LDLIBS = $(LDLIBS) ws2_32.lib kernel32.lib
|
||||
LDLIBS = $(LDLIBS) kernel32.lib
|
||||
!ENDIF
|
||||
|
||||
# We still don't know what we need for ARM64 on Windows. ARM64 and arm64 may be incorrect
|
||||
@ -131,7 +129,7 @@ CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_PHONE_APP
|
||||
LIB_SRCS = $(LIB_SRCS) neon-simd.cpp
|
||||
LIB_OBJS = $(LIB_OBJS) neon-simd.obj
|
||||
# CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP
|
||||
# LDLIBS = $(LDLIBS) ws2_32.lib
|
||||
# LDLIBS = $(LDLIBS)
|
||||
!ENDIF
|
||||
|
||||
all: cryptest.exe
|
||||
|
@ -22,17 +22,11 @@
|
||||
#include "fips140.h"
|
||||
#include "argnames.h"
|
||||
#include "fltrimpl.h"
|
||||
#include "trdlocal.h"
|
||||
#include "osrng.h"
|
||||
#include "secblock.h"
|
||||
#include "smartptr.h"
|
||||
#include "stdcpp.h"
|
||||
|
||||
// http://www.cygwin.com/faq.html#faq.api.winsock
|
||||
#if (defined(__CYGWIN__) || defined(__CYGWIN32__)) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
||||
# error Cygwin does not support Windows style sockets. See http://www.cygwin.com/faq.html#faq.api.winsock
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
|
||||
|
@ -48,9 +48,9 @@
|
||||
<dt>Compression<dd>
|
||||
Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor
|
||||
<dt>Input Source Classes<dd>
|
||||
StringSource, ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource
|
||||
StringSource, ArraySource, FileSource, RandomNumberSource
|
||||
<dt>Output Sink Classes<dd>
|
||||
StringSinkTemplate, StringSink, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink
|
||||
StringSinkTemplate, StringSink, ArraySink, FileSink, RandomNumberSink
|
||||
<dt>Filter Wrappers<dd>
|
||||
StreamTransformationFilter, AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, HashFilter,
|
||||
HashVerificationFilter, SignerFilter, SignatureVerificationFilter
|
||||
@ -58,7 +58,7 @@
|
||||
HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base64URLEncoder, Base64URLDecoder, Base32Encoder,
|
||||
Base32Decoder
|
||||
<dt>Wrappers for OS features<dd>
|
||||
Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer
|
||||
Timer, ThreadUserTimer
|
||||
|
||||
</dl>
|
||||
|
||||
|
@ -257,7 +257,6 @@
|
||||
<ClCompile Include="mqueue.cpp" />
|
||||
<ClCompile Include="mqv.cpp" />
|
||||
<ClCompile Include="nbtheory.cpp" />
|
||||
<ClCompile Include="network.cpp" />
|
||||
<ClCompile Include="oaep.cpp" />
|
||||
<ClCompile Include="osrng.cpp" />
|
||||
<ClCompile Include="padlkrng.cpp" />
|
||||
@ -308,7 +307,6 @@
|
||||
<ClCompile Include="sm3.cpp" />
|
||||
<ClCompile Include="sm4.cpp" />
|
||||
<ClCompile Include="sm4-simd.cpp" />
|
||||
<ClCompile Include="socketft.cpp" />
|
||||
<ClCompile Include="sosemanuk.cpp" />
|
||||
<ClCompile Include="speck.cpp" />
|
||||
<ClCompile Include="speck64-simd.cpp" />
|
||||
@ -322,15 +320,12 @@
|
||||
<ClCompile Include="threefish.cpp" />
|
||||
<ClCompile Include="tiger.cpp" />
|
||||
<ClCompile Include="tigertab.cpp" />
|
||||
<ClCompile Include="trdlocal.cpp" />
|
||||
<ClCompile Include="ttmac.cpp" />
|
||||
<ClCompile Include="tweetnacl.cpp" />
|
||||
<ClCompile Include="twofish.cpp" />
|
||||
<ClCompile Include="vmac.cpp" />
|
||||
<ClCompile Include="wait.cpp" />
|
||||
<ClCompile Include="wake.cpp" />
|
||||
<ClCompile Include="whrlpool.cpp" />
|
||||
<ClCompile Include="winpipes.cpp" />
|
||||
<ClCompile Include="xtr.cpp" />
|
||||
<ClCompile Include="xtrcrypt.cpp" />
|
||||
<ClCompile Include="zdeflate.cpp" />
|
||||
@ -460,7 +455,6 @@
|
||||
<ClInclude Include="mqv.h" />
|
||||
<ClInclude Include="naclite.h" />
|
||||
<ClInclude Include="nbtheory.h" />
|
||||
<ClInclude Include="network.h" />
|
||||
<ClInclude Include="nr.h" />
|
||||
<ClInclude Include="oaep.h" />
|
||||
<ClInclude Include="oids.h" />
|
||||
@ -507,7 +501,6 @@
|
||||
<ClInclude Include="sm3.h" />
|
||||
<ClInclude Include="sm4.h" />
|
||||
<ClInclude Include="smartptr.h" />
|
||||
<ClInclude Include="socketft.h" />
|
||||
<ClInclude Include="sosemanuk.h" />
|
||||
<ClInclude Include="speck.h" />
|
||||
<ClInclude Include="square.h" />
|
||||
@ -517,16 +510,13 @@
|
||||
<ClInclude Include="threefish.h" />
|
||||
<ClInclude Include="tiger.h" />
|
||||
<ClInclude Include="trap.h" />
|
||||
<ClInclude Include="trdlocal.h" />
|
||||
<ClInclude Include="trunhash.h" />
|
||||
<ClInclude Include="ttmac.h" />
|
||||
<ClInclude Include="tweetnacl.h" />
|
||||
<ClInclude Include="twofish.h" />
|
||||
<ClInclude Include="vmac.h" />
|
||||
<ClInclude Include="wait.h" />
|
||||
<ClInclude Include="wake.h" />
|
||||
<ClInclude Include="whrlpool.h" />
|
||||
<ClInclude Include="winpipes.h" />
|
||||
<ClInclude Include="words.h" />
|
||||
<ClInclude Include="xtr.h" />
|
||||
<ClInclude Include="xtrcrypt.h" />
|
||||
|
@ -269,9 +269,6 @@
|
||||
<ClCompile Include="nbtheory.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="network.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="oaep.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -425,9 +422,6 @@
|
||||
<ClCompile Include="speck128-simd.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="socketft.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sosemanuk.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -458,9 +452,6 @@
|
||||
<ClCompile Include="tigertab.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trdlocal.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ttmac.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -473,18 +464,12 @@
|
||||
<ClCompile Include="vmac.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wait.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wake.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="whrlpool.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="winpipes.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="xtr.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -774,9 +759,6 @@
|
||||
<ClInclude Include="naclite.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="network.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -918,9 +900,6 @@
|
||||
<ClInclude Include="speck.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="socketft.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sosemanuk.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -945,9 +924,6 @@
|
||||
<ClInclude Include="trap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trdlocal.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trunhash.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -963,18 +939,12 @@
|
||||
<ClInclude Include="vmac.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wait.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wake.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="whrlpool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="winpipes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="words.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
1
dll.h
1
dll.h
@ -40,7 +40,6 @@
|
||||
#include "rw.h"
|
||||
#include "sha.h"
|
||||
#include "skipjack.h"
|
||||
#include "trdlocal.h"
|
||||
|
||||
#ifdef CRYPTOPP_IMPORTS
|
||||
|
||||
|
24
fips140.cpp
24
fips140.cpp
@ -6,7 +6,6 @@
|
||||
|
||||
#include "fips140.h"
|
||||
#include "misc.h"
|
||||
#include "trdlocal.h" // needs to be included last for cygwin
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
@ -16,10 +15,6 @@ NAMESPACE_BEGIN(CryptoPP)
|
||||
#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE))
|
||||
#error FIPS 140-2 compliance requires the availability of thread local storage.
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE))
|
||||
#error FIPS 140-2 compliance requires the availability of OS provided RNG.
|
||||
#endif
|
||||
@ -41,29 +36,24 @@ PowerUpSelfTestStatus CRYPTOPP_API GetPowerUpSelfTestStatus()
|
||||
return g_powerUpSelfTestStatus;
|
||||
}
|
||||
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
ThreadLocalStorage & AccessPowerUpSelfTestInProgress()
|
||||
{
|
||||
static ThreadLocalStorage selfTestInProgress;
|
||||
return selfTestInProgress;
|
||||
}
|
||||
#endif
|
||||
// One variable for all threads for compatibility. Previously this
|
||||
// was a ThreadLocalStorage variable, which is per-thread. Also see
|
||||
// https://github.com/weidai11/cryptopp/issues/208
|
||||
static bool s_inProgress = false;
|
||||
|
||||
bool PowerUpSelfTestInProgressOnThisThread()
|
||||
{
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
return AccessPowerUpSelfTestInProgress().GetValue() != NULLPTR;
|
||||
#else
|
||||
CRYPTOPP_ASSERT(false); // should not be called
|
||||
return false;
|
||||
return s_inProgress;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress)
|
||||
{
|
||||
CRYPTOPP_UNUSED(inProgress);
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress);
|
||||
s_inProgress = inProgress;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
554
network.cpp
554
network.cpp
@ -1,554 +0,0 @@
|
||||
// network.cpp - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "network.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
|
||||
|
||||
#include "wait.h"
|
||||
|
||||
#define CRYPTOPP_TRACE_NETWORK 0
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
lword LimitedBandwidth::ComputeCurrentTransceiveLimit()
|
||||
{
|
||||
if (!m_maxBytesPerSecond)
|
||||
return ULONG_MAX;
|
||||
|
||||
const double curTime = GetCurTimeAndCleanUp();
|
||||
CRYPTOPP_UNUSED(curTime);
|
||||
|
||||
lword total = 0;
|
||||
for (OpQueue::size_type i=0; i!=m_ops.size(); ++i)
|
||||
total += m_ops[i].second;
|
||||
return SaturatingSubtract(m_maxBytesPerSecond, total);
|
||||
}
|
||||
|
||||
double LimitedBandwidth::TimeToNextTransceive()
|
||||
{
|
||||
if (!m_maxBytesPerSecond)
|
||||
return 0;
|
||||
|
||||
if (!m_nextTransceiveTime)
|
||||
ComputeNextTransceiveTime();
|
||||
|
||||
return SaturatingSubtract(m_nextTransceiveTime, m_timer.ElapsedTimeAsDouble());
|
||||
}
|
||||
|
||||
void LimitedBandwidth::NoteTransceive(lword size)
|
||||
{
|
||||
if (m_maxBytesPerSecond)
|
||||
{
|
||||
double curTime = GetCurTimeAndCleanUp();
|
||||
m_ops.push_back(std::make_pair(curTime, size));
|
||||
m_nextTransceiveTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LimitedBandwidth::ComputeNextTransceiveTime()
|
||||
{
|
||||
double curTime = GetCurTimeAndCleanUp();
|
||||
lword total = 0;
|
||||
for (unsigned int i=0; i!=m_ops.size(); ++i)
|
||||
total += m_ops[i].second;
|
||||
m_nextTransceiveTime =
|
||||
(total < m_maxBytesPerSecond) ? curTime : m_ops.front().first + 1000;
|
||||
}
|
||||
|
||||
double LimitedBandwidth::GetCurTimeAndCleanUp()
|
||||
{
|
||||
if (!m_maxBytesPerSecond)
|
||||
return 0;
|
||||
|
||||
double curTime = m_timer.ElapsedTimeAsDouble();
|
||||
while (m_ops.size() && (m_ops.front().first + 1000 < curTime))
|
||||
m_ops.pop_front();
|
||||
return curTime;
|
||||
}
|
||||
|
||||
void LimitedBandwidth::GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack)
|
||||
{
|
||||
double nextTransceiveTime = TimeToNextTransceive();
|
||||
if (nextTransceiveTime)
|
||||
container.ScheduleEvent(nextTransceiveTime, CallStack("LimitedBandwidth::GetWaitObjects()", &callStack));
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
size_t NonblockingSource::GeneralPump2(
|
||||
lword& byteCount, bool blockingOutput,
|
||||
unsigned long maxTime, bool checkDelimiter, byte delimiter)
|
||||
{
|
||||
m_blockedBySpeedLimit = false;
|
||||
|
||||
if (!GetMaxBytesPerSecond())
|
||||
{
|
||||
size_t ret = DoPump(byteCount, blockingOutput, maxTime, checkDelimiter, delimiter);
|
||||
m_doPumpBlocked = (ret != 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool forever = (maxTime == INFINITE_TIME);
|
||||
unsigned long timeToGo = maxTime;
|
||||
Timer timer(Timer::MILLISECONDS, forever);
|
||||
lword maxSize = byteCount;
|
||||
byteCount = 0;
|
||||
|
||||
timer.StartTimer();
|
||||
|
||||
while (true)
|
||||
{
|
||||
lword curMaxSize = UnsignedMin(ComputeCurrentTransceiveLimit(), maxSize - byteCount);
|
||||
|
||||
if (curMaxSize || m_doPumpBlocked)
|
||||
{
|
||||
if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
|
||||
size_t ret = DoPump(curMaxSize, blockingOutput, timeToGo, checkDelimiter, delimiter);
|
||||
m_doPumpBlocked = (ret != 0);
|
||||
if (curMaxSize)
|
||||
{
|
||||
NoteTransceive(curMaxSize);
|
||||
byteCount += curMaxSize;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (maxSize != ULONG_MAX && byteCount >= maxSize)
|
||||
break;
|
||||
|
||||
if (!forever)
|
||||
{
|
||||
timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
|
||||
if (!timeToGo)
|
||||
break;
|
||||
}
|
||||
|
||||
double waitTime = TimeToNextTransceive();
|
||||
if (!forever && waitTime > timeToGo)
|
||||
{
|
||||
m_blockedBySpeedLimit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
WaitObjectContainer container;
|
||||
LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSource::GeneralPump2() - speed limit", NULLPTR));
|
||||
container.Wait((unsigned long)waitTime);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t NonblockingSource::PumpMessages2(unsigned int &messageCount, bool blocking)
|
||||
{
|
||||
if (messageCount == 0)
|
||||
return 0;
|
||||
|
||||
messageCount = 0;
|
||||
|
||||
lword byteCount;
|
||||
do {
|
||||
byteCount = LWORD_MAX;
|
||||
RETURN_IF_NONZERO(Pump2(byteCount, blocking));
|
||||
} while(byteCount == LWORD_MAX);
|
||||
|
||||
if (!m_messageEndSent && SourceExhausted())
|
||||
{
|
||||
RETURN_IF_NONZERO(AttachedTransformation()->Put2(NULLPTR, 0, GetAutoSignalPropagation(), true));
|
||||
m_messageEndSent = true;
|
||||
messageCount = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
lword NonblockingSink::TimedFlush(unsigned long maxTime, size_t targetSize)
|
||||
{
|
||||
m_blockedBySpeedLimit = false;
|
||||
|
||||
size_t curBufSize = GetCurrentBufferSize();
|
||||
if (curBufSize <= targetSize && (targetSize || !EofPending()))
|
||||
return 0;
|
||||
|
||||
if (!GetMaxBytesPerSecond())
|
||||
return DoFlush(maxTime, targetSize);
|
||||
|
||||
bool forever = (maxTime == INFINITE_TIME);
|
||||
unsigned long timeToGo = maxTime;
|
||||
Timer timer(Timer::MILLISECONDS, forever);
|
||||
lword totalFlushed = 0;
|
||||
|
||||
timer.StartTimer();
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t flushSize = UnsignedMin(curBufSize - targetSize, ComputeCurrentTransceiveLimit());
|
||||
if (flushSize || EofPending())
|
||||
{
|
||||
if (!forever) timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
|
||||
size_t ret = (size_t)DoFlush(timeToGo, curBufSize - flushSize);
|
||||
if (ret)
|
||||
{
|
||||
NoteTransceive(ret);
|
||||
curBufSize -= ret;
|
||||
totalFlushed += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (curBufSize <= targetSize && (targetSize || !EofPending()))
|
||||
break;
|
||||
|
||||
if (!forever)
|
||||
{
|
||||
timeToGo = SaturatingSubtract(maxTime, timer.ElapsedTime());
|
||||
if (!timeToGo)
|
||||
break;
|
||||
}
|
||||
|
||||
double waitTime = TimeToNextTransceive();
|
||||
if (!forever && waitTime > timeToGo)
|
||||
{
|
||||
m_blockedBySpeedLimit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
WaitObjectContainer container;
|
||||
LimitedBandwidth::GetWaitObjects(container, CallStack("NonblockingSink::TimedFlush() - speed limit", NULLPTR));
|
||||
container.Wait((unsigned long)waitTime);
|
||||
}
|
||||
|
||||
return totalFlushed;
|
||||
}
|
||||
|
||||
bool NonblockingSink::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
TimedFlush(blocking ? INFINITE_TIME : 0);
|
||||
return hardFlush && (!!GetCurrentBufferSize() || EofPending());
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
NetworkSource::NetworkSource(BufferedTransformation *attachment)
|
||||
: NonblockingSource(attachment), m_buf(1024*16)
|
||||
, m_putSize(0), m_dataBegin(0), m_dataEnd(0)
|
||||
, m_waitingForResult(false), m_outputBlocked(false)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int NetworkSource::GetMaxWaitObjectCount() const
|
||||
{
|
||||
return LimitedBandwidth::GetMaxWaitObjectCount()
|
||||
+ GetReceiver().GetMaxWaitObjectCount()
|
||||
+ AttachedTransformation()->GetMaxWaitObjectCount();
|
||||
}
|
||||
|
||||
void NetworkSource::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (BlockedBySpeedLimit())
|
||||
LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - speed limit", &callStack));
|
||||
else if (!m_outputBlocked)
|
||||
{
|
||||
if (m_dataBegin == m_dataEnd)
|
||||
AccessReceiver().GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - no data", &callStack));
|
||||
else
|
||||
container.SetNoWait(CallStack("NetworkSource::GetWaitObjects() - have data", &callStack));
|
||||
}
|
||||
|
||||
AttachedTransformation()->GetWaitObjects(container, CallStack("NetworkSource::GetWaitObjects() - attachment", &callStack));
|
||||
}
|
||||
|
||||
size_t NetworkSource::DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter)
|
||||
{
|
||||
NetworkReceiver &receiver = AccessReceiver();
|
||||
|
||||
lword maxSize = byteCount;
|
||||
byteCount = 0;
|
||||
bool forever = maxTime == INFINITE_TIME;
|
||||
Timer timer(Timer::MILLISECONDS, forever);
|
||||
BufferedTransformation *t = AttachedTransformation();
|
||||
|
||||
if (m_outputBlocked)
|
||||
goto DoOutput;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (m_dataBegin == m_dataEnd)
|
||||
{
|
||||
if (receiver.EofReceived())
|
||||
break;
|
||||
|
||||
if (m_waitingForResult)
|
||||
{
|
||||
if (receiver.MustWaitForResult() &&
|
||||
!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
|
||||
CallStack("NetworkSource::DoPump() - wait receive result", NULLPTR)))
|
||||
break;
|
||||
|
||||
unsigned int recvResult = receiver.GetReceiveResult();
|
||||
#if CRYPTOPP_TRACE_NETWORK
|
||||
OutputDebugStringA((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
|
||||
#endif
|
||||
m_dataEnd += recvResult;
|
||||
m_waitingForResult = false;
|
||||
|
||||
if (!receiver.MustWaitToReceive() && !receiver.EofReceived() && m_dataEnd != m_buf.size())
|
||||
goto ReceiveNoWait;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dataEnd = m_dataBegin = 0;
|
||||
|
||||
if (receiver.MustWaitToReceive())
|
||||
{
|
||||
if (!receiver.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
|
||||
CallStack("NetworkSource::DoPump() - wait receive", NULLPTR)))
|
||||
break;
|
||||
|
||||
receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd);
|
||||
m_waitingForResult = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReceiveNoWait:
|
||||
m_waitingForResult = true;
|
||||
// call Receive repeatedly as long as data is immediately available,
|
||||
// because some receivers tend to return data in small pieces
|
||||
#if CRYPTOPP_TRACE_NETWORK
|
||||
OutputDebugStringA((IntToString((unsigned int)this) + ": Receiving " + IntToString(m_buf.size()-m_dataEnd) + " bytes\n").c_str());
|
||||
#endif
|
||||
while (receiver.Receive(m_buf+m_dataEnd, m_buf.size()-m_dataEnd))
|
||||
{
|
||||
unsigned int recvResult = receiver.GetReceiveResult();
|
||||
#if CRYPTOPP_TRACE_NETWORK
|
||||
OutputDebugStringA((IntToString((unsigned int)this) + ": Received " + IntToString(recvResult) + " bytes\n").c_str());
|
||||
#endif
|
||||
m_dataEnd += recvResult;
|
||||
if (receiver.EofReceived() || m_dataEnd > m_buf.size() /2)
|
||||
{
|
||||
m_waitingForResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_putSize = UnsignedMin(m_dataEnd - m_dataBegin, maxSize - byteCount);
|
||||
|
||||
if (checkDelimiter)
|
||||
m_putSize = std::find(m_buf+m_dataBegin, m_buf+m_dataBegin+m_putSize, delimiter) - (m_buf+m_dataBegin);
|
||||
|
||||
DoOutput:
|
||||
size_t result = t->PutModifiable2(m_buf+m_dataBegin, m_putSize, 0, forever || blockingOutput);
|
||||
if (result)
|
||||
{
|
||||
if (t->Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
|
||||
CallStack("NetworkSource::DoPump() - wait attachment", NULLPTR)))
|
||||
goto DoOutput;
|
||||
else
|
||||
{
|
||||
m_outputBlocked = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
m_outputBlocked = false;
|
||||
|
||||
byteCount += m_putSize;
|
||||
m_dataBegin += m_putSize;
|
||||
if (checkDelimiter && m_dataBegin < m_dataEnd && m_buf[m_dataBegin] == delimiter)
|
||||
break;
|
||||
if (maxSize != ULONG_MAX && byteCount == maxSize)
|
||||
break;
|
||||
// once time limit is reached, return even if there is more data waiting
|
||||
// but make 0 a special case so caller can request a large amount of data to be
|
||||
// pumped as long as it is immediately available
|
||||
if (maxTime > 0 && timer.ElapsedTime() > maxTime)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
NetworkSink::NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound)
|
||||
: m_maxBufferSize(maxBufferSize), m_autoFlushBound(autoFlushBound)
|
||||
, m_needSendResult(false), m_wasBlocked(false), m_eofState(EOF_NONE)
|
||||
, m_buffer(STDMIN(16U*1024U+256, maxBufferSize)), m_skipBytes(0)
|
||||
, m_speedTimer(Timer::MILLISECONDS), m_byteCountSinceLastTimerReset(0)
|
||||
, m_currentSpeed(0), m_maxObservedSpeed(0)
|
||||
{
|
||||
}
|
||||
|
||||
float NetworkSink::ComputeCurrentSpeed()
|
||||
{
|
||||
if (m_speedTimer.ElapsedTime() > 1000)
|
||||
{
|
||||
m_currentSpeed = m_byteCountSinceLastTimerReset * 1000 / m_speedTimer.ElapsedTime();
|
||||
m_maxObservedSpeed = STDMAX(m_currentSpeed, m_maxObservedSpeed * 0.98f);
|
||||
m_byteCountSinceLastTimerReset = 0;
|
||||
m_speedTimer.StartTimer();
|
||||
// OutputDebugStringA(("max speed: " + IntToString((int)m_maxObservedSpeed) + " current speed: " + IntToString((int)m_currentSpeed) + "\n").c_str());
|
||||
}
|
||||
return m_currentSpeed;
|
||||
}
|
||||
|
||||
float NetworkSink::GetMaxObservedSpeed() const
|
||||
{
|
||||
lword m = GetMaxBytesPerSecond();
|
||||
return m ? STDMIN(m_maxObservedSpeed, static_cast<float>(m)) : m_maxObservedSpeed;
|
||||
}
|
||||
|
||||
unsigned int NetworkSink::GetMaxWaitObjectCount() const
|
||||
{
|
||||
return LimitedBandwidth::GetMaxWaitObjectCount() + GetSender().GetMaxWaitObjectCount();
|
||||
}
|
||||
|
||||
void NetworkSink::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (BlockedBySpeedLimit())
|
||||
LimitedBandwidth::GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - speed limit", &callStack));
|
||||
else if (m_wasBlocked)
|
||||
AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - was blocked", &callStack));
|
||||
else if (!m_buffer.IsEmpty())
|
||||
AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - buffer not empty", &callStack));
|
||||
else if (EofPending())
|
||||
AccessSender().GetWaitObjects(container, CallStack("NetworkSink::GetWaitObjects() - EOF pending", &callStack));
|
||||
}
|
||||
|
||||
size_t NetworkSink::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (m_eofState == EOF_DONE)
|
||||
{
|
||||
if (length || messageEnd)
|
||||
throw Exception(Exception::OTHER_ERROR, "NetworkSink::Put2() being called after EOF had been sent");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_eofState > EOF_NONE)
|
||||
goto EofSite;
|
||||
|
||||
{
|
||||
if (m_skipBytes)
|
||||
{
|
||||
CRYPTOPP_ASSERT(length >= m_skipBytes);
|
||||
inString += m_skipBytes;
|
||||
length -= m_skipBytes;
|
||||
}
|
||||
|
||||
m_buffer.Put(inString, length);
|
||||
|
||||
if (!blocking || m_buffer.CurrentSize() > m_autoFlushBound)
|
||||
TimedFlush(0, 0);
|
||||
|
||||
size_t targetSize = messageEnd ? 0 : m_maxBufferSize;
|
||||
if (blocking)
|
||||
TimedFlush(INFINITE_TIME, targetSize);
|
||||
|
||||
if (m_buffer.CurrentSize() > targetSize)
|
||||
{
|
||||
CRYPTOPP_ASSERT(!blocking);
|
||||
m_wasBlocked = true;
|
||||
m_skipBytes += length;
|
||||
size_t blockedBytes = UnsignedMin(length, m_buffer.CurrentSize() - targetSize);
|
||||
return STDMAX<size_t>(blockedBytes, 1);
|
||||
}
|
||||
|
||||
m_wasBlocked = false;
|
||||
m_skipBytes = 0;
|
||||
}
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
m_eofState = EOF_PENDING_SEND;
|
||||
|
||||
EofSite:
|
||||
TimedFlush(blocking ? INFINITE_TIME : 0, 0);
|
||||
if (m_eofState != EOF_DONE)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
lword NetworkSink::DoFlush(unsigned long maxTime, size_t targetSize)
|
||||
{
|
||||
NetworkSender &sender = AccessSender();
|
||||
|
||||
bool forever = maxTime == INFINITE_TIME;
|
||||
Timer timer(Timer::MILLISECONDS, forever);
|
||||
unsigned int totalFlushSize = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (m_buffer.CurrentSize() <= targetSize)
|
||||
break;
|
||||
|
||||
if (m_needSendResult)
|
||||
{
|
||||
if (sender.MustWaitForResult() &&
|
||||
!sender.Wait(SaturatingSubtract(maxTime, timer.ElapsedTime()),
|
||||
CallStack("NetworkSink::DoFlush() - wait send result", NULLPTR)))
|
||||
break;
|
||||
|
||||
unsigned int sendResult = sender.GetSendResult();
|
||||
#if CRYPTOPP_TRACE_NETWORK
|
||||
OutputDebugStringA((IntToString((unsigned int)this) + ": Sent " + IntToString(sendResult) + " bytes\n").c_str());
|
||||
#endif
|
||||
m_buffer.Skip(sendResult);
|
||||
totalFlushSize += sendResult;
|
||||
m_needSendResult = false;
|
||||
|
||||
if (!m_buffer.AnyRetrievable())
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0;
|
||||
if (sender.MustWaitToSend() && !sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait send", NULLPTR)))
|
||||
break;
|
||||
|
||||
size_t contiguousSize = 0;
|
||||
const byte *block = m_buffer.Spy(contiguousSize);
|
||||
|
||||
#if CRYPTOPP_TRACE_NETWORK
|
||||
OutputDebugStringA((IntToString((unsigned int)this) + ": Sending " + IntToString(contiguousSize) + " bytes\n").c_str());
|
||||
#endif
|
||||
sender.Send(block, contiguousSize);
|
||||
m_needSendResult = true;
|
||||
|
||||
if (maxTime > 0 && timeOut == 0)
|
||||
break; // once time limit is reached, return even if there is more data waiting
|
||||
}
|
||||
|
||||
m_byteCountSinceLastTimerReset += totalFlushSize;
|
||||
ComputeCurrentSpeed();
|
||||
|
||||
if (m_buffer.IsEmpty() && !m_needSendResult)
|
||||
{
|
||||
if (m_eofState == EOF_PENDING_SEND)
|
||||
{
|
||||
sender.SendEof();
|
||||
m_eofState = sender.MustWaitForEof() ? EOF_PENDING_DELIVERY : EOF_DONE;
|
||||
}
|
||||
|
||||
while (m_eofState == EOF_PENDING_DELIVERY)
|
||||
{
|
||||
unsigned long timeOut = maxTime ? SaturatingSubtract(maxTime, timer.ElapsedTime()) : 0;
|
||||
if (!sender.Wait(timeOut, CallStack("NetworkSink::DoFlush() - wait EOF", NULLPTR)))
|
||||
break;
|
||||
|
||||
if (sender.EofSent())
|
||||
m_eofState = EOF_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
return totalFlushSize;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // #ifdef SOCKETS_AVAILABLE
|
234
network.h
234
network.h
@ -1,234 +0,0 @@
|
||||
#ifndef CRYPTOPP_NETWORK_H
|
||||
#define CRYPTOPP_NETWORK_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
|
||||
|
||||
#include "filters.h"
|
||||
#include "hrtimer.h"
|
||||
#include "stdcpp.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class LimitedBandwidth
|
||||
{
|
||||
public:
|
||||
LimitedBandwidth(lword maxBytesPerSecond = 0)
|
||||
: m_maxBytesPerSecond(maxBytesPerSecond), m_timer(Timer::MILLISECONDS)
|
||||
, m_nextTransceiveTime(0)
|
||||
{ m_timer.StartTimer(); }
|
||||
|
||||
lword GetMaxBytesPerSecond() const
|
||||
{ return m_maxBytesPerSecond; }
|
||||
|
||||
void SetMaxBytesPerSecond(lword v)
|
||||
{ m_maxBytesPerSecond = v; }
|
||||
|
||||
lword ComputeCurrentTransceiveLimit();
|
||||
|
||||
double TimeToNextTransceive();
|
||||
|
||||
void NoteTransceive(lword size);
|
||||
|
||||
public:
|
||||
/*! GetWaitObjects() must be called despite the 0 return from GetMaxWaitObjectCount();
|
||||
the 0 is because the ScheduleEvent() method is used instead of adding a wait object */
|
||||
unsigned int GetMaxWaitObjectCount() const { return 0; }
|
||||
void GetWaitObjects(WaitObjectContainer &container, const CallStack &callStack);
|
||||
|
||||
private:
|
||||
lword m_maxBytesPerSecond;
|
||||
|
||||
typedef std::deque<std::pair<double, lword> > OpQueue;
|
||||
OpQueue m_ops;
|
||||
|
||||
Timer m_timer;
|
||||
double m_nextTransceiveTime;
|
||||
|
||||
void ComputeNextTransceiveTime();
|
||||
double GetCurTimeAndCleanUp();
|
||||
};
|
||||
|
||||
/// a Source class that can pump from a device for a specified amount of time.
|
||||
class CRYPTOPP_NO_VTABLE NonblockingSource : public AutoSignaling<Source>, public LimitedBandwidth
|
||||
{
|
||||
public:
|
||||
NonblockingSource(BufferedTransformation *attachment)
|
||||
: m_messageEndSent(false) , m_doPumpBlocked(false), m_blockedBySpeedLimit(false) {Detach(attachment);}
|
||||
|
||||
/// \name NONBLOCKING SOURCE
|
||||
//@{
|
||||
|
||||
/// pump up to maxSize bytes using at most maxTime milliseconds
|
||||
/*! If checkDelimiter is true, pump up to delimiter, which itself is not extracted or pumped. */
|
||||
size_t GeneralPump2(lword &byteCount, bool blockingOutput=true, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n');
|
||||
|
||||
lword GeneralPump(lword maxSize=LWORD_MAX, unsigned long maxTime=INFINITE_TIME, bool checkDelimiter=false, byte delimiter='\n')
|
||||
{
|
||||
GeneralPump2(maxSize, true, maxTime, checkDelimiter, delimiter);
|
||||
return maxSize;
|
||||
}
|
||||
lword TimedPump(unsigned long maxTime)
|
||||
{return GeneralPump(LWORD_MAX, maxTime);}
|
||||
lword PumpLine(byte delimiter='\n', lword maxSize=1024)
|
||||
{return GeneralPump(maxSize, INFINITE_TIME, true, delimiter);}
|
||||
|
||||
size_t Pump2(lword &byteCount, bool blocking=true)
|
||||
{return GeneralPump2(byteCount, blocking, blocking ? INFINITE_TIME : 0);}
|
||||
size_t PumpMessages2(unsigned int &messageCount, bool blocking=true);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
virtual size_t DoPump(lword &byteCount, bool blockingOutput,
|
||||
unsigned long maxTime, bool checkDelimiter, byte delimiter) =0;
|
||||
|
||||
bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
|
||||
|
||||
private:
|
||||
bool m_messageEndSent, m_doPumpBlocked, m_blockedBySpeedLimit;
|
||||
};
|
||||
|
||||
/// Network Receiver
|
||||
class CRYPTOPP_NO_VTABLE NetworkReceiver : public Waitable
|
||||
{
|
||||
public:
|
||||
virtual bool MustWaitToReceive() {return false;}
|
||||
virtual bool MustWaitForResult() {return false;}
|
||||
/// receive data from network source, returns whether result is immediately available
|
||||
virtual bool Receive(byte* buf, size_t bufLen) =0;
|
||||
virtual unsigned int GetReceiveResult() =0;
|
||||
virtual bool EofReceived() const =0;
|
||||
};
|
||||
|
||||
class CRYPTOPP_NO_VTABLE NonblockingSinkInfo
|
||||
{
|
||||
public:
|
||||
virtual ~NonblockingSinkInfo() {}
|
||||
virtual size_t GetMaxBufferSize() const =0;
|
||||
virtual size_t GetCurrentBufferSize() const =0;
|
||||
virtual bool EofPending() const =0;
|
||||
/// compute the current speed of this sink in bytes per second
|
||||
virtual float ComputeCurrentSpeed() =0;
|
||||
/// get the maximum observed speed of this sink in bytes per second
|
||||
virtual float GetMaxObservedSpeed() const =0;
|
||||
};
|
||||
|
||||
/// a Sink class that queues input and can flush to a device for a specified amount of time.
|
||||
class CRYPTOPP_NO_VTABLE NonblockingSink : public Sink, public NonblockingSinkInfo, public LimitedBandwidth
|
||||
{
|
||||
public:
|
||||
NonblockingSink() : m_blockedBySpeedLimit(false) {}
|
||||
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
/// flush to device for no more than maxTime milliseconds
|
||||
/*! This function will repeatedly attempt to flush data to some device, until
|
||||
the queue is empty, or a total of maxTime milliseconds have elapsed.
|
||||
If maxTime == 0, at least one attempt will be made to flush some data, but
|
||||
it is likely that not all queued data will be flushed, even if the device
|
||||
is ready to receive more data without waiting. If you want to flush as much data
|
||||
as possible without waiting for the device, call this function in a loop.
|
||||
For example: while (sink.TimedFlush(0) > 0) {}
|
||||
\return number of bytes flushed
|
||||
*/
|
||||
lword TimedFlush(unsigned long maxTime, size_t targetSize = 0);
|
||||
|
||||
virtual void SetMaxBufferSize(size_t maxBufferSize) =0;
|
||||
/// set a bound which will cause sink to flush if exceeded by GetCurrentBufferSize()
|
||||
virtual void SetAutoFlushBound(size_t bound) =0;
|
||||
|
||||
protected:
|
||||
virtual lword DoFlush(unsigned long maxTime, size_t targetSize) = 0;
|
||||
|
||||
bool BlockedBySpeedLimit() const { return m_blockedBySpeedLimit; }
|
||||
|
||||
private:
|
||||
bool m_blockedBySpeedLimit;
|
||||
};
|
||||
|
||||
/// Network Sender
|
||||
class CRYPTOPP_NO_VTABLE NetworkSender : public Waitable
|
||||
{
|
||||
public:
|
||||
virtual bool MustWaitToSend() {return false;}
|
||||
virtual bool MustWaitForResult() {return false;}
|
||||
virtual void Send(const byte* buf, size_t bufLen) =0;
|
||||
virtual unsigned int GetSendResult() =0;
|
||||
virtual bool MustWaitForEof() {return false;}
|
||||
virtual void SendEof() =0;
|
||||
virtual bool EofSent() {return false;} // implement if MustWaitForEof() == true
|
||||
};
|
||||
|
||||
/// Network Source
|
||||
class CRYPTOPP_NO_VTABLE NetworkSource : public NonblockingSource
|
||||
{
|
||||
public:
|
||||
NetworkSource(BufferedTransformation *attachment);
|
||||
|
||||
unsigned int GetMaxWaitObjectCount() const;
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
bool SourceExhausted() const {return m_dataBegin == m_dataEnd && GetReceiver().EofReceived();}
|
||||
|
||||
protected:
|
||||
size_t DoPump(lword &byteCount, bool blockingOutput, unsigned long maxTime, bool checkDelimiter, byte delimiter);
|
||||
|
||||
virtual NetworkReceiver & AccessReceiver() =0;
|
||||
const NetworkReceiver & GetReceiver() const {return const_cast<NetworkSource *>(this)->AccessReceiver();}
|
||||
|
||||
private:
|
||||
SecByteBlock m_buf;
|
||||
size_t m_putSize, m_dataBegin, m_dataEnd;
|
||||
bool m_waitingForResult, m_outputBlocked;
|
||||
};
|
||||
|
||||
/// Network Sink
|
||||
class CRYPTOPP_NO_VTABLE NetworkSink : public NonblockingSink
|
||||
{
|
||||
public:
|
||||
NetworkSink(unsigned int maxBufferSize, unsigned int autoFlushBound);
|
||||
|
||||
unsigned int GetMaxWaitObjectCount() const;
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
|
||||
|
||||
void SetMaxBufferSize(size_t maxBufferSize) {m_maxBufferSize = maxBufferSize; m_buffer.SetNodeSize(UnsignedMin(maxBufferSize, 16U*1024U+256U));}
|
||||
void SetAutoFlushBound(size_t bound) {m_autoFlushBound = bound;}
|
||||
|
||||
size_t GetMaxBufferSize() const {return m_maxBufferSize;}
|
||||
size_t GetCurrentBufferSize() const {return (size_t)m_buffer.CurrentSize();}
|
||||
|
||||
void ClearBuffer() { m_buffer.Clear(); }
|
||||
|
||||
bool EofPending() const { return m_eofState > EOF_NONE && m_eofState < EOF_DONE; }
|
||||
|
||||
/// compute the current speed of this sink in bytes per second
|
||||
float ComputeCurrentSpeed();
|
||||
/// get the maximum observed speed of this sink in bytes per second
|
||||
float GetMaxObservedSpeed() const;
|
||||
|
||||
protected:
|
||||
lword DoFlush(unsigned long maxTime, size_t targetSize);
|
||||
|
||||
virtual NetworkSender & AccessSender() =0;
|
||||
const NetworkSender & GetSender() const {return const_cast<NetworkSink *>(this)->AccessSender();}
|
||||
|
||||
private:
|
||||
enum EofState { EOF_NONE, EOF_PENDING_SEND, EOF_PENDING_DELIVERY, EOF_DONE };
|
||||
|
||||
size_t m_maxBufferSize, m_autoFlushBound;
|
||||
bool m_needSendResult, m_wasBlocked;
|
||||
EofState m_eofState;
|
||||
ByteQueue m_buffer;
|
||||
size_t m_skipBytes;
|
||||
Timer m_speedTimer;
|
||||
float m_byteCountSinceLastTimerReset, m_currentSpeed, m_maxObservedSpeed;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // SOCKETS_AVAILABLE
|
||||
|
||||
#endif // CRYPTOPP_NETWORK_H
|
673
socketft.cpp
673
socketft.cpp
@ -1,673 +0,0 @@
|
||||
// socketft.cpp - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
|
||||
|
||||
#include "socketft.h"
|
||||
#include "wait.h"
|
||||
|
||||
// Windows 8, Windows Server 2012, and Windows Phone 8.1 need <synchapi.h> and <ioapiset.h>
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
|
||||
# include <synchapi.h>
|
||||
# include <ioapiset.h>
|
||||
# define USE_WINDOWS8_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_BERKELEY_STYLE_SOCKETS
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_MSAN)
|
||||
# include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
|
||||
// From http://groups.google.com/d/msg/cryptopp-users/MzvocLrbIpE/TMCa6LFhCgAJ,
|
||||
// <wspiapi.h> is a compatibility header and it needs _WIN32_WINNT >= 0x501.
|
||||
// The work-around should be OK since it won't cross-pollinate into header files.
|
||||
#if defined(__MINGW32__) && (_WIN32_WINNT < 0x501)
|
||||
# undef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x501
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
# pragma comment(lib, "ws2_32.lib")
|
||||
# if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x501)
|
||||
# include <wspiapi.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
const int SOCKET_EINVAL = WSAEINVAL;
|
||||
const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
const int SOCKET_EINVAL = EINVAL;
|
||||
const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
|
||||
#endif
|
||||
|
||||
// Solaris doesn't have INADDR_NONE
|
||||
#ifndef INADDR_NONE
|
||||
# define INADDR_NONE 0xffffffff
|
||||
#endif /* INADDR_NONE */
|
||||
|
||||
// Some Windows SDKs do not have INET6_ADDRSTRLEN
|
||||
#ifndef INET_ADDRSTRLEN
|
||||
# define INET_ADDRSTRLEN (22)
|
||||
#endif
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
# define INET6_ADDRSTRLEN (65)
|
||||
#endif
|
||||
|
||||
#define MAX_ADDRSTRLEN (INET6_ADDRSTRLEN > INET_ADDRSTRLEN ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN)
|
||||
|
||||
// Also see http://stackoverflow.com/a/20816961 and http://github.com/weidai11/cryptopp/issues/322
|
||||
#if defined(USE_WINDOWS_STYLE_SOCKETS)
|
||||
int inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
#if CRYPTOPP_MSC_VERSION
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
// Posix states only src is validated. Avoid a bad dst dereference.
|
||||
if(!src || !dst) return 0;
|
||||
|
||||
struct sockaddr_storage ss;
|
||||
ZeroMemory(&ss, sizeof(ss));
|
||||
|
||||
#if CRYPTOPP_MSC_VERSION >= 1400
|
||||
char temp[MAX_ADDRSTRLEN];
|
||||
strcpy_s(temp, sizeof(temp), src);
|
||||
#else
|
||||
char temp[MAX_ADDRSTRLEN];
|
||||
strncpy(temp, src, sizeof(temp));
|
||||
temp[MAX_ADDRSTRLEN-1] = '\0';
|
||||
#endif
|
||||
|
||||
|
||||
int size = sizeof(ss);
|
||||
if (WSAStringToAddressA(temp, af, NULLPTR, (struct sockaddr *)&ss, &size) == 0) {
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
|
||||
return 1;
|
||||
case AF_INET6:
|
||||
*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
((sockaddr_in *)dst)->sin_addr.s_addr = INADDR_NONE;
|
||||
return 0;
|
||||
|
||||
#if CRYPTOPP_MSC_VERSION
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
Socket::Err::Err(socket_t s, const std::string& operation, int error)
|
||||
: OS_Error(IO_ERROR, "Socket: " + operation + " operation failed with error " + IntToString(error), operation, error)
|
||||
, m_s(s)
|
||||
{
|
||||
}
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
if (m_own)
|
||||
{
|
||||
try
|
||||
{
|
||||
CloseSocket();
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Socket::AttachSocket(socket_t s, bool own)
|
||||
{
|
||||
if (m_own)
|
||||
CloseSocket();
|
||||
|
||||
m_s = s;
|
||||
m_own = own;
|
||||
SocketChanged();
|
||||
}
|
||||
|
||||
socket_t Socket::DetachSocket()
|
||||
{
|
||||
socket_t s = m_s;
|
||||
m_s = INVALID_SOCKET;
|
||||
SocketChanged();
|
||||
return s;
|
||||
}
|
||||
|
||||
void Socket::Create(int nType)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s == INVALID_SOCKET);
|
||||
m_s = socket(AF_INET, nType, 0);
|
||||
CheckAndHandleError("socket", m_s);
|
||||
m_own = true;
|
||||
SocketChanged();
|
||||
}
|
||||
|
||||
void Socket::CloseSocket()
|
||||
{
|
||||
if (m_s != INVALID_SOCKET)
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
# if defined(USE_WINDOWS8_API)
|
||||
BOOL result = CancelIoEx((HANDLE) m_s, NULLPTR);
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CheckAndHandleError_int("closesocket", closesocket(m_s));
|
||||
CRYPTOPP_UNUSED(result); // Used by CRYPTOPP_ASSERT in debug builds
|
||||
# else
|
||||
BOOL result = CancelIo((HANDLE) m_s);
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CheckAndHandleError_int("closesocket", closesocket(m_s));
|
||||
CRYPTOPP_UNUSED(result);
|
||||
# endif
|
||||
#else
|
||||
CheckAndHandleError_int("close", close(m_s));
|
||||
#endif
|
||||
m_s = INVALID_SOCKET;
|
||||
SocketChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Socket::Bind(unsigned int port, const char *addr)
|
||||
{
|
||||
sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
|
||||
if (addr == NULLPTR)
|
||||
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
else
|
||||
{
|
||||
// unsigned long result = inet_addr(addr);
|
||||
unsigned long result;
|
||||
if (inet_pton(AF_INET, addr, &result) < 1 || result == INADDR_NONE)
|
||||
{
|
||||
SetLastError(SOCKET_EINVAL);
|
||||
CheckAndHandleError_int("inet_addr", SOCKET_ERROR);
|
||||
}
|
||||
sa.sin_addr.s_addr = result;
|
||||
}
|
||||
|
||||
sa.sin_port = htons((unsigned short)port);
|
||||
|
||||
Bind((sockaddr *)&sa, sizeof(sa));
|
||||
}
|
||||
|
||||
void Socket::Bind(const sockaddr *psa, socklen_t saLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
// cygwin workaround: needs const_cast
|
||||
CheckAndHandleError_int("bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
|
||||
}
|
||||
|
||||
void Socket::Listen(int backlog)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
CheckAndHandleError_int("listen", listen(m_s, backlog));
|
||||
}
|
||||
|
||||
bool Socket::Connect(const char *addr, unsigned int port)
|
||||
{
|
||||
CRYPTOPP_ASSERT(addr != NULLPTR);
|
||||
|
||||
sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sin_family = AF_INET;
|
||||
|
||||
// Make inet_pton failures non-fatal.
|
||||
if (!addr || inet_pton(AF_INET, addr, &sa.sin_addr.s_addr) < 1)
|
||||
sa.sin_addr.s_addr = INADDR_NONE;
|
||||
|
||||
if (sa.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
addrinfo hints, *result = NULLPTR;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
if (getaddrinfo(addr, NULLPTR, &hints, &result) != 0 || result == NULLPTR)
|
||||
{
|
||||
freeaddrinfo(result);
|
||||
SetLastError(SOCKET_EINVAL);
|
||||
CheckAndHandleError_int("getaddrinfo", SOCKET_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Avoid assignment on due to alignment issues in Apple headers
|
||||
// sa.sin_addr.s_addr = ((struct sockaddr_in *)(result->ai_addr))->sin_addr.s_addr;
|
||||
struct sockaddr_in* sap = (struct sockaddr_in *)result->ai_addr;
|
||||
memcpy(&sa.sin_addr.s_addr, &sap->sin_addr.s_addr, sizeof(sa.sin_addr.s_addr));
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
}
|
||||
|
||||
sa.sin_port = htons((unsigned short)port);
|
||||
|
||||
return Connect((const sockaddr *)&sa, sizeof(sa));
|
||||
}
|
||||
|
||||
bool Socket::Connect(const sockaddr* psa, socklen_t saLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
|
||||
if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
|
||||
return false;
|
||||
CheckAndHandleError_int("connect", result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
socket_t s = accept(m_s, psa, psaLen);
|
||||
if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
|
||||
return false;
|
||||
CheckAndHandleError("accept", s);
|
||||
target.AttachSocket(s, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
CheckAndHandleError_int("getsockname", getsockname(m_s, psa, psaLen));
|
||||
}
|
||||
|
||||
void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
CheckAndHandleError_int("getpeername", getpeername(m_s, psa, psaLen));
|
||||
}
|
||||
|
||||
unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
|
||||
CheckAndHandleError_int("send", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
|
||||
CheckAndHandleError_int("recv", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Socket::ShutDown(int how)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
int result = shutdown(m_s, how);
|
||||
CheckAndHandleError_int("shutdown", result);
|
||||
}
|
||||
|
||||
void Socket::IOCtl(long cmd, unsigned long *argp)
|
||||
{
|
||||
CRYPTOPP_ASSERT(m_s != INVALID_SOCKET);
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
CheckAndHandleError_int("ioctlsocket", ioctlsocket(m_s, cmd, argp));
|
||||
#else
|
||||
CheckAndHandleError_int("ioctl", ioctl(m_s, cmd, argp));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Socket::SendReady(const timeval *timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_s, &fds);
|
||||
#ifdef CRYPTOPP_MSAN
|
||||
__msan_unpoison(&fds, sizeof(fds));
|
||||
#endif
|
||||
|
||||
int ready;
|
||||
if (timeout == NULLPTR)
|
||||
ready = select((int)m_s+1, NULLPTR, &fds, NULLPTR, NULLPTR);
|
||||
else
|
||||
{
|
||||
timeval timeoutCopy = *timeout; // select() modified timeout on Linux
|
||||
ready = select((int)m_s+1, NULLPTR, &fds, NULLPTR, &timeoutCopy);
|
||||
}
|
||||
CheckAndHandleError_int("select", ready);
|
||||
return ready > 0;
|
||||
}
|
||||
|
||||
bool Socket::ReceiveReady(const timeval *timeout)
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_s, &fds);
|
||||
#ifdef CRYPTOPP_MSAN
|
||||
__msan_unpoison(&fds, sizeof(fds));
|
||||
#endif
|
||||
|
||||
int ready;
|
||||
if (timeout == NULLPTR)
|
||||
ready = select((int)m_s+1, &fds, NULLPTR, NULLPTR, NULLPTR);
|
||||
else
|
||||
{
|
||||
timeval timeoutCopy = *timeout; // select() modified timeout on Linux
|
||||
ready = select((int)m_s+1, &fds, NULLPTR, NULLPTR, &timeoutCopy);
|
||||
}
|
||||
CheckAndHandleError_int("select", ready);
|
||||
return ready > 0;
|
||||
}
|
||||
|
||||
unsigned int Socket::PortNameToNumber(const char *name, const char *protocol)
|
||||
{
|
||||
int port = atoi(name);
|
||||
if (IntToString(port) == name)
|
||||
return port;
|
||||
|
||||
servent *se = getservbyname(name, protocol);
|
||||
if (!se)
|
||||
throw Err(INVALID_SOCKET, "getservbyname", SOCKET_EINVAL);
|
||||
return ntohs(se->s_port);
|
||||
}
|
||||
|
||||
void Socket::StartSockets()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
WSADATA wsd;
|
||||
int result = WSAStartup(0x0202, &wsd);
|
||||
if (result != 0)
|
||||
throw Err(INVALID_SOCKET, "WSAStartup", result);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Socket::ShutdownSockets()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
int result = WSACleanup();
|
||||
if (result != 0)
|
||||
throw Err(INVALID_SOCKET, "WSACleanup", result);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Socket::GetLastError()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Socket::SetLastError(int errorCode)
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
WSASetLastError(errorCode);
|
||||
#else
|
||||
errno = errorCode;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Socket::HandleError(const char *operation) const
|
||||
{
|
||||
int err = GetLastError();
|
||||
throw Err(m_s, operation, err);
|
||||
}
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
|
||||
SocketReceiver::SocketReceiver(Socket &s)
|
||||
: m_s(s), m_lastResult(0), m_resultPending(false), m_eofReceived(false)
|
||||
{
|
||||
m_event.AttachHandle(CreateEvent(NULLPTR, true, false, NULLPTR), true);
|
||||
m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
|
||||
memset(&m_overlapped, 0, sizeof(m_overlapped));
|
||||
m_overlapped.hEvent = m_event;
|
||||
}
|
||||
|
||||
SocketReceiver::~SocketReceiver()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
# if defined(USE_WINDOWS8_API)
|
||||
BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULLPTR);
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CRYPTOPP_UNUSED(result); // Used by CRYPTOPP_ASSERT in debug builds
|
||||
# else
|
||||
BOOL result = CancelIo((HANDLE) m_s.GetSocket());
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CRYPTOPP_UNUSED(result);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SocketReceiver::Receive(byte* buf, size_t bufLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(!m_resultPending && !m_eofReceived);
|
||||
|
||||
DWORD flags = 0;
|
||||
// don't queue too much at once, or we might use up non-paged memory
|
||||
WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
|
||||
if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULLPTR) == 0)
|
||||
{
|
||||
if (m_lastResult == 0)
|
||||
m_eofReceived = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
default:
|
||||
m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
|
||||
// Fall through for non-fatal
|
||||
case WSAEDISCON:
|
||||
m_lastResult = 0;
|
||||
m_eofReceived = true;
|
||||
break;
|
||||
case WSA_IO_PENDING:
|
||||
m_resultPending = true;
|
||||
}
|
||||
}
|
||||
return !m_resultPending;
|
||||
}
|
||||
|
||||
void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (m_resultPending)
|
||||
container.AddHandle(m_event, CallStack("SocketReceiver::GetWaitObjects() - result pending", &callStack));
|
||||
else if (!m_eofReceived)
|
||||
container.SetNoWait(CallStack("SocketReceiver::GetWaitObjects() - result ready", &callStack));
|
||||
}
|
||||
|
||||
unsigned int SocketReceiver::GetReceiveResult()
|
||||
{
|
||||
if (m_resultPending)
|
||||
{
|
||||
DWORD flags = 0;
|
||||
if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
|
||||
{
|
||||
if (m_lastResult == 0)
|
||||
m_eofReceived = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (WSAGetLastError())
|
||||
{
|
||||
default:
|
||||
m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
|
||||
// Fall through for non-fatal
|
||||
case WSAEDISCON:
|
||||
m_lastResult = 0;
|
||||
m_eofReceived = true;
|
||||
}
|
||||
}
|
||||
m_resultPending = false;
|
||||
}
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
SocketSender::SocketSender(Socket &s)
|
||||
: m_s(s), m_lastResult(0), m_resultPending(false)
|
||||
{
|
||||
m_event.AttachHandle(CreateEvent(NULLPTR, true, false, NULLPTR), true);
|
||||
m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
|
||||
memset(&m_overlapped, 0, sizeof(m_overlapped));
|
||||
m_overlapped.hEvent = m_event;
|
||||
}
|
||||
|
||||
|
||||
SocketSender::~SocketSender()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
# if defined(USE_WINDOWS8_API)
|
||||
BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULLPTR);
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CRYPTOPP_UNUSED(result); // Used by CRYPTOPP_ASSERT in debug builds
|
||||
# else
|
||||
BOOL result = CancelIo((HANDLE) m_s.GetSocket());
|
||||
CRYPTOPP_ASSERT(result || (!result && GetLastError() == ERROR_NOT_FOUND));
|
||||
CRYPTOPP_UNUSED(result);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketSender::Send(const byte* buf, size_t bufLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(!m_resultPending);
|
||||
DWORD written = 0;
|
||||
// don't queue too much at once, or we might use up non-paged memory
|
||||
WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
|
||||
if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULLPTR) == 0)
|
||||
{
|
||||
m_resultPending = false;
|
||||
m_lastResult = written;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WSAGetLastError() != WSA_IO_PENDING)
|
||||
m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);
|
||||
|
||||
m_resultPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketSender::SendEof()
|
||||
{
|
||||
CRYPTOPP_ASSERT(!m_resultPending);
|
||||
m_s.ShutDown(SD_SEND);
|
||||
m_s.CheckAndHandleError("ResetEvent", ResetEvent(m_event));
|
||||
m_s.CheckAndHandleError_int("WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
|
||||
m_resultPending = true;
|
||||
}
|
||||
|
||||
bool SocketSender::EofSent()
|
||||
{
|
||||
if (m_resultPending)
|
||||
{
|
||||
WSANETWORKEVENTS events;
|
||||
m_s.CheckAndHandleError_int("WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
|
||||
if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
|
||||
throw Socket::Err(m_s, "WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
|
||||
if (events.iErrorCode[FD_CLOSE_BIT] != 0)
|
||||
throw Socket::Err(m_s, "FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
|
||||
m_resultPending = false;
|
||||
}
|
||||
return m_lastResult != 0;
|
||||
}
|
||||
|
||||
void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (m_resultPending)
|
||||
container.AddHandle(m_event, CallStack("SocketSender::GetWaitObjects() - result pending", &callStack));
|
||||
else
|
||||
container.SetNoWait(CallStack("SocketSender::GetWaitObjects() - result ready", &callStack));
|
||||
}
|
||||
|
||||
unsigned int SocketSender::GetSendResult()
|
||||
{
|
||||
if (m_resultPending)
|
||||
{
|
||||
DWORD flags = 0;
|
||||
BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
|
||||
m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
|
||||
m_resultPending = false;
|
||||
}
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_BERKELEY_STYLE_SOCKETS
|
||||
|
||||
SocketReceiver::SocketReceiver(Socket &s)
|
||||
: m_s(s), m_lastResult(0), m_eofReceived(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (!m_eofReceived)
|
||||
container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack));
|
||||
}
|
||||
|
||||
bool SocketReceiver::Receive(byte* buf, size_t bufLen)
|
||||
{
|
||||
m_lastResult = m_s.Receive(buf, bufLen);
|
||||
if (bufLen > 0 && m_lastResult == 0)
|
||||
m_eofReceived = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int SocketReceiver::GetReceiveResult()
|
||||
{
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
SocketSender::SocketSender(Socket &s)
|
||||
: m_s(s), m_lastResult(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SocketSender::Send(const byte* buf, size_t bufLen)
|
||||
{
|
||||
m_lastResult = m_s.Send(buf, bufLen);
|
||||
}
|
||||
|
||||
void SocketSender::SendEof()
|
||||
{
|
||||
m_s.ShutDown(SD_SEND);
|
||||
}
|
||||
|
||||
unsigned int SocketSender::GetSendResult()
|
||||
{
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack));
|
||||
}
|
||||
|
||||
#endif // USE_BERKELEY_STYLE_SOCKETS
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // SOCKETS_AVAILABLE
|
227
socketft.h
227
socketft.h
@ -1,227 +0,0 @@
|
||||
#ifndef CRYPTOPP_SOCKETFT_H
|
||||
#define CRYPTOPP_SOCKETFT_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE)
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "network.h"
|
||||
#include "queue.h"
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
|
||||
# error Winsock 1 is not supported by this library. Please include this file or winsock2.h before windows.h.
|
||||
# endif
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "winpipes.h"
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
typedef ::SOCKET socket_t;
|
||||
#else
|
||||
typedef int socket_t;
|
||||
const socket_t INVALID_SOCKET = -1;
|
||||
// cygwin 1.1.4 doesn't have SHUT_RD
|
||||
const int SD_RECEIVE = 0;
|
||||
const int SD_SEND = 1;
|
||||
const int SD_BOTH = 2;
|
||||
const int SOCKET_ERROR = -1;
|
||||
#endif
|
||||
|
||||
#ifndef socklen_t
|
||||
typedef TYPE_OF_SOCKLEN_T socklen_t; // see config.h
|
||||
#endif
|
||||
|
||||
/// wrapper for Windows or Berkeley Sockets
|
||||
class Socket
|
||||
{
|
||||
public:
|
||||
/// exception thrown by Socket class
|
||||
class Err : public OS_Error
|
||||
{
|
||||
public:
|
||||
Err(socket_t s, const std::string& operation, int error);
|
||||
socket_t GetSocket() const {return m_s;}
|
||||
|
||||
private:
|
||||
socket_t m_s;
|
||||
};
|
||||
|
||||
Socket(socket_t s = INVALID_SOCKET, bool own=false) : m_s(s), m_own(own) {}
|
||||
Socket(const Socket &s) : m_s(s.m_s), m_own(false) {}
|
||||
virtual ~Socket();
|
||||
|
||||
bool GetOwnership() const {return m_own;}
|
||||
void SetOwnership(bool own) {m_own = own;}
|
||||
|
||||
operator socket_t() {return m_s;}
|
||||
socket_t GetSocket() const {return m_s;}
|
||||
void AttachSocket(socket_t s, bool own=false);
|
||||
socket_t DetachSocket();
|
||||
void CloseSocket();
|
||||
|
||||
void Create(int nType = SOCK_STREAM);
|
||||
void Bind(unsigned int port, const char *addr=NULLPTR);
|
||||
void Bind(const sockaddr* psa, socklen_t saLen);
|
||||
void Listen(int backlog = SOMAXCONN);
|
||||
// the next three functions return false if the socket is in nonblocking mode
|
||||
// and the operation cannot be completed immediately
|
||||
bool Connect(const char *addr, unsigned int port);
|
||||
bool Connect(const sockaddr* psa, socklen_t saLen);
|
||||
bool Accept(Socket& s, sockaddr *psa=NULLPTR, socklen_t *psaLen=NULLPTR);
|
||||
void GetSockName(sockaddr *psa, socklen_t *psaLen);
|
||||
void GetPeerName(sockaddr *psa, socklen_t *psaLen);
|
||||
unsigned int Send(const byte* buf, size_t bufLen, int flags=0);
|
||||
unsigned int Receive(byte* buf, size_t bufLen, int flags=0);
|
||||
void ShutDown(int how = SD_SEND);
|
||||
|
||||
void IOCtl(long cmd, unsigned long *argp);
|
||||
bool SendReady(const timeval *timeout);
|
||||
bool ReceiveReady(const timeval *timeout);
|
||||
|
||||
virtual void HandleError(const char *operation) const;
|
||||
void CheckAndHandleError_int(const char *operation, int result) const
|
||||
{if (result == SOCKET_ERROR) HandleError(operation);}
|
||||
void CheckAndHandleError(const char *operation, socket_t result) const
|
||||
{if (result == static_cast<socket_t>(SOCKET_ERROR)) HandleError(operation);}
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
void CheckAndHandleError(const char *operation, BOOL result) const
|
||||
{if (!result) HandleError(operation);}
|
||||
void CheckAndHandleError(const char *operation, bool result) const
|
||||
{if (!result) HandleError(operation);}
|
||||
#endif
|
||||
|
||||
/// look up the port number given its name, returns 0 if not found
|
||||
static unsigned int PortNameToNumber(const char *name, const char *protocol="tcp");
|
||||
/// start Windows Sockets 2
|
||||
static void StartSockets();
|
||||
/// calls WSACleanup for Windows Sockets
|
||||
static void ShutdownSockets();
|
||||
/// returns errno or WSAGetLastError
|
||||
static int GetLastError();
|
||||
/// sets errno or calls WSASetLastError
|
||||
static void SetLastError(int errorCode);
|
||||
|
||||
protected:
|
||||
virtual void SocketChanged() {}
|
||||
|
||||
socket_t m_s;
|
||||
bool m_own;
|
||||
};
|
||||
|
||||
class SocketsInitializer
|
||||
{
|
||||
public:
|
||||
SocketsInitializer() {Socket::StartSockets();}
|
||||
~SocketsInitializer() {try {Socket::ShutdownSockets();} catch (const Exception&) {CRYPTOPP_ASSERT(0);}}
|
||||
};
|
||||
|
||||
class SocketReceiver : public NetworkReceiver
|
||||
{
|
||||
public:
|
||||
SocketReceiver(Socket &s);
|
||||
|
||||
#ifdef USE_BERKELEY_STYLE_SOCKETS
|
||||
bool MustWaitToReceive() {return true;}
|
||||
#else
|
||||
~SocketReceiver();
|
||||
bool MustWaitForResult() {return true;}
|
||||
#endif
|
||||
bool Receive(byte* buf, size_t bufLen);
|
||||
unsigned int GetReceiveResult();
|
||||
bool EofReceived() const {return m_eofReceived;}
|
||||
|
||||
unsigned int GetMaxWaitObjectCount() const {return 1;}
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
private:
|
||||
Socket &m_s;
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
WindowsHandle m_event;
|
||||
OVERLAPPED m_overlapped;
|
||||
DWORD m_lastResult;
|
||||
bool m_resultPending;
|
||||
#else
|
||||
unsigned int m_lastResult;
|
||||
#endif
|
||||
|
||||
bool m_eofReceived;
|
||||
};
|
||||
|
||||
class SocketSender : public NetworkSender
|
||||
{
|
||||
public:
|
||||
SocketSender(Socket &s);
|
||||
|
||||
#ifdef USE_BERKELEY_STYLE_SOCKETS
|
||||
bool MustWaitToSend() {return true;}
|
||||
#else
|
||||
~SocketSender();
|
||||
bool MustWaitForResult() {return true;}
|
||||
bool MustWaitForEof() { return true; }
|
||||
bool EofSent();
|
||||
#endif
|
||||
void Send(const byte* buf, size_t bufLen);
|
||||
unsigned int GetSendResult();
|
||||
void SendEof();
|
||||
|
||||
unsigned int GetMaxWaitObjectCount() const {return 1;}
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
private:
|
||||
Socket &m_s;
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
WindowsHandle m_event;
|
||||
OVERLAPPED m_overlapped;
|
||||
DWORD m_lastResult;
|
||||
bool m_resultPending;
|
||||
#else
|
||||
unsigned int m_lastResult;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// socket-based implementation of NetworkSource
|
||||
class SocketSource : public NetworkSource, public Socket
|
||||
{
|
||||
public:
|
||||
SocketSource(socket_t s = INVALID_SOCKET, bool pumpAll = false, BufferedTransformation *attachment = NULLPTR)
|
||||
: NetworkSource(attachment), Socket(s), m_receiver(*this)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
private:
|
||||
NetworkReceiver & AccessReceiver() {return m_receiver;}
|
||||
SocketReceiver m_receiver;
|
||||
};
|
||||
|
||||
/// socket-based implementation of NetworkSink
|
||||
class SocketSink : public NetworkSink, public Socket
|
||||
{
|
||||
public:
|
||||
SocketSink(socket_t s=INVALID_SOCKET, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
|
||||
: NetworkSink(maxBufferSize, autoFlushBound), Socket(s), m_sender(*this) {}
|
||||
|
||||
void SendEof() {ShutDown(SD_SEND);}
|
||||
|
||||
private:
|
||||
NetworkSender & AccessSender() {return m_sender;}
|
||||
SocketSender m_sender;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // SOCKETS_AVAILABLE
|
||||
|
||||
#endif // CRYPTOPP_SOCKETFT_H
|
83
test.cpp
83
test.cpp
@ -18,8 +18,6 @@
|
||||
#include "randpool.h"
|
||||
#include "ida.h"
|
||||
#include "base64.h"
|
||||
#include "socketft.h"
|
||||
#include "wait.h"
|
||||
#include "factory.h"
|
||||
#include "whrlpool.h"
|
||||
#include "tiger.h"
|
||||
@ -43,11 +41,6 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_BERKELEY_STYLE_SOCKETS) && !defined(macintosh)
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1000)
|
||||
#include <crtdbg.h> // for the debug heap
|
||||
#endif
|
||||
@ -62,7 +55,6 @@
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma comment(lib, "cryptlib_bds.lib")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
|
||||
// Aggressive stack checking with VS2005 SP1 and above.
|
||||
@ -115,8 +107,6 @@ void Base64Decode(const char *infile, const char *outfile);
|
||||
void HexEncode(const char *infile, const char *outfile);
|
||||
void HexDecode(const char *infile, const char *outfile);
|
||||
|
||||
void ForwardTcpPort(const char *sourcePort, const char *destinationHost, const char *destinationPort);
|
||||
|
||||
void FIPS140_GenerateRandomFiles();
|
||||
|
||||
bool Validate(int, bool, const char *);
|
||||
@ -386,8 +376,6 @@ int scoped_main(int argc, char *argv[])
|
||||
FIPS140_SampleApplication();
|
||||
else if (command == "fips-rand")
|
||||
FIPS140_GenerateRandomFiles();
|
||||
else if (command == "ft")
|
||||
ForwardTcpPort(argv[2], argv[3], argv[4]);
|
||||
else if (command == "a")
|
||||
{
|
||||
if (AdhocTest)
|
||||
@ -793,77 +781,6 @@ void HexDecode(const char *in, const char *out)
|
||||
FileSource(in, true, new HexDecoder(new FileSink(out)));
|
||||
}
|
||||
|
||||
void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName)
|
||||
{
|
||||
// Quiet warnings for Windows Phone and Windows Store builds
|
||||
CRYPTOPP_UNUSED(sourcePortName), CRYPTOPP_UNUSED(destinationHost), CRYPTOPP_UNUSED(destinationPortName);
|
||||
|
||||
#ifdef SOCKETS_AVAILABLE
|
||||
SocketsInitializer sockInit;
|
||||
|
||||
Socket sockListen, sockSource, sockDestination;
|
||||
|
||||
int sourcePort = Socket::PortNameToNumber(sourcePortName);
|
||||
int destinationPort = Socket::PortNameToNumber(destinationPortName);
|
||||
|
||||
sockListen.Create();
|
||||
sockListen.Bind(sourcePort);
|
||||
|
||||
const int flag = 1;
|
||||
int err = setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
|
||||
CRYPTOPP_ASSERT(err == 0);
|
||||
if(err != 0)
|
||||
throw Socket::Err(sockListen, "setsockopt", sockListen.GetLastError());
|
||||
|
||||
std::cout << "Listing on port " << sourcePort << ".\n";
|
||||
sockListen.Listen();
|
||||
|
||||
sockListen.Accept(sockSource);
|
||||
std::cout << "Connection accepted on port " << sourcePort << ".\n";
|
||||
sockListen.CloseSocket();
|
||||
|
||||
std::cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
|
||||
sockDestination.Create();
|
||||
sockDestination.Connect(destinationHost, destinationPort);
|
||||
|
||||
std::cout << "Connection made to " << destinationHost << ", starting to forward.\n";
|
||||
|
||||
SocketSource out(sockSource, false, new SocketSink(sockDestination));
|
||||
SocketSource in(sockDestination, false, new SocketSink(sockSource));
|
||||
|
||||
WaitObjectContainer waitObjects;
|
||||
|
||||
while (!(in.SourceExhausted() && out.SourceExhausted()))
|
||||
{
|
||||
waitObjects.Clear();
|
||||
|
||||
out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULLPTR));
|
||||
in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULLPTR));
|
||||
|
||||
waitObjects.Wait(INFINITE_TIME);
|
||||
|
||||
if (!out.SourceExhausted())
|
||||
{
|
||||
std::cout << "o" << std::flush;
|
||||
out.PumpAll2(false);
|
||||
if (out.SourceExhausted())
|
||||
std::cout << "EOF received on source socket.\n";
|
||||
}
|
||||
|
||||
if (!in.SourceExhausted())
|
||||
{
|
||||
std::cout << "i" << std::flush;
|
||||
in.PumpAll2(false);
|
||||
if (in.SourceExhausted())
|
||||
std::cout << "EOF received on destination socket.\n";
|
||||
}
|
||||
}
|
||||
#else
|
||||
std::cout << "Socket support was not enabled at compile time.\n";
|
||||
exit(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Validate(int alg, bool thorough, const char *seedInput)
|
||||
{
|
||||
bool result;
|
||||
|
110
trdlocal.cpp
110
trdlocal.cpp
@ -1,110 +0,0 @@
|
||||
// trdlocal.cpp - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifndef CRYPTOPP_IMPORTS
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(THREADS_AVAILABLE)
|
||||
|
||||
#include "trdlocal.h"
|
||||
#include "stdcpp.h"
|
||||
|
||||
#ifdef HAS_WINTHREADS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
|
||||
# pragma GCC diagnostic ignored "-Wc++11-compat"
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
ThreadLocalStorage::Err::Err(const std::string& operation, int error)
|
||||
: OS_Error(OTHER_ERROR, "ThreadLocalStorage: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
|
||||
{
|
||||
}
|
||||
|
||||
// Windows: "a process may have up to TLS_MINIMUM_AVAILABLE indexes (guaranteed to be greater than
|
||||
// or equal to 64)", https://support.microsoft.com/en-us/help/94804/info-thread-local-storage-overview
|
||||
ThreadLocalStorage::ThreadLocalStorage()
|
||||
{
|
||||
#ifdef HAS_WINTHREADS
|
||||
m_index = TlsAlloc();
|
||||
CRYPTOPP_ASSERT(m_index != TLS_OUT_OF_INDEXES);
|
||||
if (m_index == TLS_OUT_OF_INDEXES)
|
||||
throw Err("TlsAlloc", GetLastError());
|
||||
#else
|
||||
m_index = 0;
|
||||
int error = pthread_key_create(&m_index, NULLPTR);
|
||||
CRYPTOPP_ASSERT(!error);
|
||||
if (error)
|
||||
throw Err("pthread_key_create", error);
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadLocalStorage::~ThreadLocalStorage() CRYPTOPP_THROW
|
||||
{
|
||||
#if defined(CRYPTOPP_CXX17_EXCEPTIONS)
|
||||
if (std::uncaught_exceptions() == 0)
|
||||
#elif defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
|
||||
if (std::uncaught_exception() == false)
|
||||
#else
|
||||
try
|
||||
#endif
|
||||
#ifdef HAS_WINTHREADS
|
||||
{
|
||||
int rc = TlsFree(m_index);
|
||||
CRYPTOPP_ASSERT(rc);
|
||||
if (!rc)
|
||||
throw Err("TlsFree", GetLastError());
|
||||
}
|
||||
#else
|
||||
{
|
||||
int error = pthread_key_delete(m_index);
|
||||
CRYPTOPP_ASSERT(!error);
|
||||
if (error)
|
||||
throw Err("pthread_key_delete", error);
|
||||
}
|
||||
#endif
|
||||
#if !defined(CRYPTOPP_CXX17_EXCEPTIONS) && !defined(CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE)
|
||||
catch(const Exception&)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadLocalStorage::SetValue(void *value)
|
||||
{
|
||||
#ifdef HAS_WINTHREADS
|
||||
if (!TlsSetValue(m_index, value))
|
||||
throw Err("TlsSetValue", GetLastError());
|
||||
#else
|
||||
int error = pthread_setspecific(m_index, value);
|
||||
if (error)
|
||||
throw Err("pthread_key_getspecific", error);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *ThreadLocalStorage::GetValue() const
|
||||
{
|
||||
#ifdef HAS_WINTHREADS
|
||||
void *result = TlsGetValue(m_index);
|
||||
const DWORD dwRet = GetLastError();
|
||||
|
||||
CRYPTOPP_ASSERT(result || (!result && (dwRet == NO_ERROR)));
|
||||
if (!result && dwRet != NO_ERROR)
|
||||
throw Err("TlsGetValue", dwRet);
|
||||
#else
|
||||
// Null is a valid return value. Posix does not provide a way to
|
||||
// check for a "good" Null vs a "bad" Null (errno is not set).
|
||||
void *result = pthread_getspecific(m_index);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // THREADS_AVAILABLE
|
||||
#endif // CRYPTOPP_IMPORTS
|
44
trdlocal.h
44
trdlocal.h
@ -1,44 +0,0 @@
|
||||
#ifndef CRYPTOPP_TRDLOCAL_H
|
||||
#define CRYPTOPP_TRDLOCAL_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(THREADS_AVAILABLE)
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef HAS_WINTHREADS
|
||||
typedef unsigned long ThreadLocalIndexType;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_key_t ThreadLocalIndexType;
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// thread local storage
|
||||
class CRYPTOPP_DLL ThreadLocalStorage : public NotCopyable
|
||||
{
|
||||
public:
|
||||
/// exception thrown by ThreadLocalStorage class
|
||||
class Err : public OS_Error
|
||||
{
|
||||
public:
|
||||
Err(const std::string& operation, int error);
|
||||
};
|
||||
|
||||
ThreadLocalStorage();
|
||||
~ThreadLocalStorage() CRYPTOPP_THROW;
|
||||
|
||||
void SetValue(void *value);
|
||||
void *GetValue() const;
|
||||
|
||||
private:
|
||||
ThreadLocalIndexType m_index;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // THREADS_AVAILABLE
|
||||
|
||||
#endif // CRYPTOPP_TRDLOCAL_H
|
486
wait.cpp
486
wait.cpp
@ -1,486 +0,0 @@
|
||||
// wait.cpp - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "config.h"
|
||||
|
||||
// http://connect.microsoft.com/VisualStudio/feedback/details/1581706
|
||||
// and http://github.com/weidai11/cryptopp/issues/214
|
||||
#if CRYPTOPP_MSC_VERSION
|
||||
# pragma warning(disable: 4189)
|
||||
# pragma warning(disable: 4589)
|
||||
#endif
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && (defined(SOCKETS_AVAILABLE) || defined(WINDOWS_PIPES_AVAILABLE))
|
||||
|
||||
#include "wait.h"
|
||||
#include "misc.h"
|
||||
#include "smartptr.h"
|
||||
|
||||
// Windows 8, Windows Server 2012, and Windows Phone 8.1 need <synchapi.h> and <ioapiset.h>
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
|
||||
# include <synchapi.h>
|
||||
# include <ioapiset.h>
|
||||
# define USE_WINDOWS8_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef USE_BERKELEY_STYLE_SOCKETS
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_MSAN)
|
||||
# include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
unsigned int WaitObjectContainer::MaxWaitObjects()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
return MAXIMUM_WAIT_OBJECTS * (MAXIMUM_WAIT_OBJECTS-1);
|
||||
#else
|
||||
return FD_SETSIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
WaitObjectContainer::WaitObjectContainer(WaitObjectsTracer* tracer)
|
||||
: m_tracer(tracer),
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
m_startWaiting(0), m_stopWaiting(0),
|
||||
#endif
|
||||
m_firstEventTime(0.0f), m_eventTimer(Timer::MILLISECONDS), m_lastResult(0),
|
||||
m_sameResultCount(0), m_noWaitTimer(Timer::MILLISECONDS)
|
||||
{
|
||||
Clear();
|
||||
m_eventTimer.StartTimer();
|
||||
}
|
||||
|
||||
void WaitObjectContainer::Clear()
|
||||
{
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
m_handles.clear();
|
||||
#else
|
||||
m_maxFd = 0;
|
||||
FD_ZERO(&m_readfds);
|
||||
FD_ZERO(&m_writefds);
|
||||
# ifdef CRYPTOPP_MSAN
|
||||
__msan_unpoison(&m_readfds, sizeof(m_readfds));
|
||||
__msan_unpoison(&m_writefds, sizeof(m_writefds));
|
||||
# endif
|
||||
#endif
|
||||
m_noWait = false;
|
||||
m_firstEventTime = 0;
|
||||
}
|
||||
|
||||
inline void WaitObjectContainer::SetLastResult(LastResultType result)
|
||||
{
|
||||
if (result == m_lastResult)
|
||||
m_sameResultCount++;
|
||||
else
|
||||
{
|
||||
m_lastResult = result;
|
||||
m_sameResultCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitObjectContainer::DetectNoWait(LastResultType result, CallStack const& callStack)
|
||||
{
|
||||
if (result == m_lastResult && m_noWaitTimer.ElapsedTime() > 1000)
|
||||
{
|
||||
if (m_sameResultCount > m_noWaitTimer.ElapsedTime())
|
||||
{
|
||||
if (m_tracer)
|
||||
{
|
||||
std::string desc = "No wait loop detected - m_lastResult: ";
|
||||
desc.append(IntToString(m_lastResult)).append(", call stack:");
|
||||
for (CallStack const* cs = &callStack; cs; cs = cs->Prev())
|
||||
desc.append("\n- ").append(cs->Format());
|
||||
m_tracer->TraceNoWaitLoop(desc);
|
||||
}
|
||||
try { throw 0; } catch (...) {} // help debugger break
|
||||
}
|
||||
|
||||
m_noWaitTimer.StartTimer();
|
||||
m_sameResultCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void WaitObjectContainer::SetNoWait(CallStack const& callStack)
|
||||
{
|
||||
DetectNoWait(LastResultType(LASTRESULT_NOWAIT), CallStack("WaitObjectContainer::SetNoWait()", &callStack));
|
||||
m_noWait = true;
|
||||
}
|
||||
|
||||
void WaitObjectContainer::ScheduleEvent(double milliseconds, CallStack const& callStack)
|
||||
{
|
||||
if (milliseconds <= 3)
|
||||
DetectNoWait(LastResultType(LASTRESULT_SCHEDULED), CallStack("WaitObjectContainer::ScheduleEvent()", &callStack));
|
||||
double thisEventTime = m_eventTimer.ElapsedTimeAsDouble() + milliseconds;
|
||||
if (!m_firstEventTime || thisEventTime < m_firstEventTime)
|
||||
m_firstEventTime = thisEventTime;
|
||||
}
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
|
||||
struct WaitingThreadData
|
||||
{
|
||||
bool waitingToWait, terminate;
|
||||
HANDLE startWaiting, stopWaiting;
|
||||
const HANDLE *waitHandles;
|
||||
unsigned int count;
|
||||
HANDLE threadHandle;
|
||||
DWORD threadId;
|
||||
DWORD* error;
|
||||
};
|
||||
|
||||
WaitObjectContainer::~WaitObjectContainer()
|
||||
{
|
||||
try // don't let exceptions escape destructor
|
||||
{
|
||||
if (!m_threads.empty())
|
||||
{
|
||||
HANDLE threadHandles[MAXIMUM_WAIT_OBJECTS] = {0};
|
||||
|
||||
unsigned int i;
|
||||
for (i=0; i<m_threads.size(); i++)
|
||||
{
|
||||
// Enterprise Analysis warning
|
||||
if(!m_threads[i]) continue;
|
||||
|
||||
WaitingThreadData &thread = *m_threads[i];
|
||||
while (!thread.waitingToWait) // spin until thread is in the initial "waiting to wait" state
|
||||
Sleep(0);
|
||||
thread.terminate = true;
|
||||
threadHandles[i] = thread.threadHandle;
|
||||
}
|
||||
|
||||
BOOL bResult = PulseEvent(m_startWaiting);
|
||||
CRYPTOPP_ASSERT(bResult != 0); CRYPTOPP_UNUSED(bResult);
|
||||
|
||||
// Enterprise Analysis warning
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
DWORD dwResult = ::WaitForMultipleObjectsEx((DWORD)m_threads.size(), threadHandles, TRUE, INFINITE, FALSE);
|
||||
CRYPTOPP_ASSERT(dwResult < (DWORD)m_threads.size());
|
||||
#else
|
||||
DWORD dwResult = ::WaitForMultipleObjects((DWORD)m_threads.size(), threadHandles, TRUE, INFINITE);
|
||||
CRYPTOPP_UNUSED(dwResult);
|
||||
CRYPTOPP_ASSERT(dwResult < (DWORD)m_threads.size());
|
||||
#endif
|
||||
|
||||
for (i=0; i<m_threads.size(); i++)
|
||||
{
|
||||
// Enterprise Analysis warning
|
||||
if (!threadHandles[i]) continue;
|
||||
|
||||
bResult = CloseHandle(threadHandles[i]);
|
||||
CRYPTOPP_ASSERT(bResult != 0);
|
||||
}
|
||||
|
||||
bResult = CloseHandle(m_startWaiting);
|
||||
CRYPTOPP_ASSERT(bResult != 0);
|
||||
bResult = CloseHandle(m_stopWaiting);
|
||||
CRYPTOPP_ASSERT(bResult != 0);
|
||||
}
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void WaitObjectContainer::AddHandle(HANDLE handle, CallStack const& callStack)
|
||||
{
|
||||
DetectNoWait(m_handles.size(), CallStack("WaitObjectContainer::AddHandle()", &callStack));
|
||||
m_handles.push_back(handle);
|
||||
}
|
||||
|
||||
DWORD WINAPI WaitingThread(LPVOID lParam)
|
||||
{
|
||||
member_ptr<WaitingThreadData> pThread((WaitingThreadData *)lParam);
|
||||
WaitingThreadData &thread = *pThread;
|
||||
std::vector<HANDLE> handles;
|
||||
|
||||
while (true)
|
||||
{
|
||||
thread.waitingToWait = true;
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
DWORD result = ::WaitForSingleObjectEx(thread.startWaiting, INFINITE, FALSE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#else
|
||||
DWORD result = ::WaitForSingleObject(thread.startWaiting, INFINITE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#endif
|
||||
|
||||
thread.waitingToWait = false;
|
||||
if (thread.terminate)
|
||||
break;
|
||||
if (!thread.count)
|
||||
continue;
|
||||
|
||||
handles.resize(thread.count + 1);
|
||||
handles[0] = thread.stopWaiting;
|
||||
std::copy(thread.waitHandles, thread.waitHandles+thread.count, handles.begin()+1);
|
||||
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
result = ::WaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0], FALSE, INFINITE, FALSE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#else
|
||||
result = ::WaitForMultipleObjects((DWORD)handles.size(), &handles[0], FALSE, INFINITE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#endif
|
||||
|
||||
if (result == WAIT_OBJECT_0)
|
||||
continue; // another thread finished waiting first, so do nothing
|
||||
SetEvent(thread.stopWaiting);
|
||||
if (!(result > WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + handles.size()))
|
||||
{
|
||||
CRYPTOPP_ASSERT(!"error in WaitingThread"); // break here so we can see which thread has an error
|
||||
*thread.error = ::GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK; // return a value here to avoid compiler warning
|
||||
}
|
||||
|
||||
void WaitObjectContainer::CreateThreads(unsigned int count)
|
||||
{
|
||||
size_t currentCount = m_threads.size();
|
||||
if (currentCount == 0)
|
||||
{
|
||||
m_startWaiting = ::CreateEvent(NULLPTR, TRUE, FALSE, NULLPTR);
|
||||
m_stopWaiting = ::CreateEvent(NULLPTR, TRUE, FALSE, NULLPTR);
|
||||
}
|
||||
|
||||
if (currentCount < count)
|
||||
{
|
||||
m_threads.resize(count);
|
||||
for (size_t i=currentCount; i<count; i++)
|
||||
{
|
||||
// Enterprise Analysis warning
|
||||
if(!m_threads[i]) continue;
|
||||
|
||||
m_threads[i] = new WaitingThreadData;
|
||||
WaitingThreadData &thread = *m_threads[i];
|
||||
thread.terminate = false;
|
||||
thread.startWaiting = m_startWaiting;
|
||||
thread.stopWaiting = m_stopWaiting;
|
||||
thread.waitingToWait = false;
|
||||
thread.threadHandle = CreateThread(NULLPTR, 0, &WaitingThread, &thread, 0, &thread.threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WaitObjectContainer::Wait(unsigned long milliseconds)
|
||||
{
|
||||
if (m_noWait || (m_handles.empty() && !m_firstEventTime))
|
||||
{
|
||||
SetLastResult(LastResultType(LASTRESULT_NOWAIT));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool timeoutIsScheduledEvent = false;
|
||||
|
||||
if (m_firstEventTime)
|
||||
{
|
||||
double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble());
|
||||
|
||||
if (timeToFirstEvent <= milliseconds)
|
||||
{
|
||||
milliseconds = (unsigned long)timeToFirstEvent;
|
||||
timeoutIsScheduledEvent = true;
|
||||
}
|
||||
|
||||
if (m_handles.empty() || !milliseconds)
|
||||
{
|
||||
if (milliseconds)
|
||||
Sleep(milliseconds);
|
||||
SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
|
||||
return timeoutIsScheduledEvent;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_handles.size() > MAXIMUM_WAIT_OBJECTS)
|
||||
{
|
||||
// too many wait objects for a single WaitForMultipleObjects call, so use multiple threads
|
||||
static const unsigned int WAIT_OBJECTS_PER_THREAD = MAXIMUM_WAIT_OBJECTS-1;
|
||||
unsigned int nThreads = (unsigned int)((m_handles.size() + WAIT_OBJECTS_PER_THREAD - 1) / WAIT_OBJECTS_PER_THREAD);
|
||||
if (nThreads > MAXIMUM_WAIT_OBJECTS) // still too many wait objects, maybe implement recursive threading later?
|
||||
throw Err("WaitObjectContainer: number of wait objects exceeds limit");
|
||||
CreateThreads(nThreads);
|
||||
DWORD error = S_OK;
|
||||
|
||||
for (unsigned int i=0; i<m_threads.size(); i++)
|
||||
{
|
||||
// Enterprise Analysis warning
|
||||
if(!m_threads[i]) continue;
|
||||
|
||||
WaitingThreadData &thread = *m_threads[i];
|
||||
while (!thread.waitingToWait) // spin until thread is in the initial "waiting to wait" state
|
||||
Sleep(0);
|
||||
if (i<nThreads)
|
||||
{
|
||||
thread.waitHandles = &m_handles[i*WAIT_OBJECTS_PER_THREAD];
|
||||
thread.count = UnsignedMin(WAIT_OBJECTS_PER_THREAD, m_handles.size() - i*WAIT_OBJECTS_PER_THREAD);
|
||||
thread.error = &error;
|
||||
}
|
||||
else
|
||||
thread.count = 0;
|
||||
}
|
||||
|
||||
ResetEvent(m_stopWaiting);
|
||||
PulseEvent(m_startWaiting);
|
||||
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
DWORD result = ::WaitForSingleObjectEx(m_stopWaiting, milliseconds, FALSE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#else
|
||||
DWORD result = ::WaitForSingleObject(m_stopWaiting, milliseconds);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#endif
|
||||
|
||||
if (result == WAIT_OBJECT_0)
|
||||
{
|
||||
if (error == S_OK)
|
||||
return true;
|
||||
else
|
||||
throw Err("WaitObjectContainer: WaitForMultipleObjects in thread failed with error " + IntToString(error));
|
||||
}
|
||||
SetEvent(m_stopWaiting);
|
||||
if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
|
||||
return timeoutIsScheduledEvent;
|
||||
}
|
||||
else
|
||||
throw Err("WaitObjectContainer: WaitForSingleObject failed with error " + IntToString(::GetLastError()));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if TRACE_WAIT
|
||||
static Timer t(Timer::MICROSECONDS);
|
||||
static unsigned long lastTime = 0;
|
||||
unsigned long timeBeforeWait = t.ElapsedTime();
|
||||
#endif
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
DWORD result = ::WaitForMultipleObjectsEx((DWORD)m_handles.size(), &m_handles[0], FALSE, milliseconds, FALSE);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#else
|
||||
DWORD result = ::WaitForMultipleObjects((DWORD)m_handles.size(), &m_handles[0], FALSE, milliseconds);
|
||||
CRYPTOPP_ASSERT(result != WAIT_FAILED);
|
||||
#endif
|
||||
#if TRACE_WAIT
|
||||
if (milliseconds > 0)
|
||||
{
|
||||
unsigned long timeAfterWait = t.ElapsedTime();
|
||||
OutputDebugStringA(("Handles " + IntToString(m_handles.size()) + ", Woke up by " + IntToString(result-WAIT_OBJECT_0) + ", Busied for " + IntToString(timeBeforeWait-lastTime) + " us, Waited for " + IntToString(timeAfterWait-timeBeforeWait) + " us, max " + IntToString(milliseconds) + "ms\n").c_str());
|
||||
lastTime = timeAfterWait;
|
||||
}
|
||||
#endif
|
||||
if (result < WAIT_OBJECT_0 + m_handles.size())
|
||||
{
|
||||
if (result == m_lastResult)
|
||||
m_sameResultCount++;
|
||||
else
|
||||
{
|
||||
m_lastResult = result;
|
||||
m_sameResultCount = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (result == WAIT_TIMEOUT)
|
||||
{
|
||||
SetLastResult(timeoutIsScheduledEvent ? LASTRESULT_SCHEDULED : LASTRESULT_TIMEOUT);
|
||||
return timeoutIsScheduledEvent;
|
||||
}
|
||||
else
|
||||
throw Err("WaitObjectContainer: WaitForMultipleObjects failed with error " + IntToString(::GetLastError()));
|
||||
}
|
||||
}
|
||||
|
||||
#else // #ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
|
||||
void WaitObjectContainer::AddReadFd(int fd, CallStack const& callStack) // TODO: do something with callStack
|
||||
{
|
||||
CRYPTOPP_UNUSED(callStack);
|
||||
FD_SET(fd, &m_readfds);
|
||||
m_maxFd = STDMAX(m_maxFd, fd);
|
||||
}
|
||||
|
||||
void WaitObjectContainer::AddWriteFd(int fd, CallStack const& callStack) // TODO: do something with callStack
|
||||
{
|
||||
CRYPTOPP_UNUSED(callStack);
|
||||
FD_SET(fd, &m_writefds);
|
||||
m_maxFd = STDMAX(m_maxFd, fd);
|
||||
}
|
||||
|
||||
bool WaitObjectContainer::Wait(unsigned long milliseconds)
|
||||
{
|
||||
if (m_noWait || (!m_maxFd && !m_firstEventTime))
|
||||
return true;
|
||||
|
||||
bool timeoutIsScheduledEvent = false;
|
||||
|
||||
if (m_firstEventTime)
|
||||
{
|
||||
double timeToFirstEvent = SaturatingSubtract(m_firstEventTime, m_eventTimer.ElapsedTimeAsDouble());
|
||||
if (timeToFirstEvent <= milliseconds)
|
||||
{
|
||||
milliseconds = (unsigned long)timeToFirstEvent;
|
||||
timeoutIsScheduledEvent = true;
|
||||
}
|
||||
}
|
||||
|
||||
timeval tv, *timeout;
|
||||
|
||||
if (milliseconds == INFINITE_TIME)
|
||||
timeout = NULLPTR;
|
||||
else
|
||||
{
|
||||
tv.tv_sec = milliseconds / 1000;
|
||||
tv.tv_usec = (milliseconds % 1000) * 1000;
|
||||
timeout = &tv;
|
||||
}
|
||||
|
||||
int result = select(m_maxFd+1, &m_readfds, &m_writefds, NULLPTR, timeout);
|
||||
|
||||
if (result > 0)
|
||||
return true;
|
||||
else if (result == 0)
|
||||
return timeoutIsScheduledEvent;
|
||||
else
|
||||
throw Err("WaitObjectContainer: select failed with error " + IntToString(errno));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ********************************************************
|
||||
|
||||
std::string CallStack::Format() const
|
||||
{
|
||||
return m_info;
|
||||
}
|
||||
|
||||
std::string CallStackWithNr::Format() const
|
||||
{
|
||||
return std::string(m_info) + " / nr: " + IntToString(m_nr);
|
||||
}
|
||||
|
||||
std::string CallStackWithStr::Format() const
|
||||
{
|
||||
return std::string(m_info) + " / " + std::string(m_z);
|
||||
}
|
||||
|
||||
bool Waitable::Wait(unsigned long milliseconds, CallStack const& callStack)
|
||||
{
|
||||
WaitObjectContainer container;
|
||||
GetWaitObjects(container, callStack); // reduce clutter by not adding this func to stack
|
||||
return container.Wait(milliseconds);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
235
wait.h
235
wait.h
@ -1,235 +0,0 @@
|
||||
// wait.h - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#ifndef CRYPTOPP_WAIT_H
|
||||
#define CRYPTOPP_WAIT_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && (defined(SOCKETS_AVAILABLE) || defined(WINDOWS_PIPES_AVAILABLE))
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "stdcpp.h"
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
// For definitions of VOID, PVOID, HANDLE, PHANDLE, etc.
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "hrtimer.h"
|
||||
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(memory_sanitizer)
|
||||
# define CRYPTOPP_MSAN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// http://connect.microsoft.com/VisualStudio/feedback/details/1581706
|
||||
// and http://github.com/weidai11/cryptopp/issues/214
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4589)
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class Tracer
|
||||
{
|
||||
public:
|
||||
Tracer(unsigned int level) : m_level(level) {}
|
||||
virtual ~Tracer() {}
|
||||
|
||||
protected:
|
||||
/// Override this in your most-derived tracer to do the actual tracing.
|
||||
virtual void Trace(unsigned int n, std::string const& s) = 0;
|
||||
|
||||
/*! By default, tracers will decide which trace messages to trace according to a trace level
|
||||
mechanism. If your most-derived tracer uses a different mechanism, override this to
|
||||
return false. If this method returns false, the default TraceXxxx(void) methods will all
|
||||
return 0 and must be overridden explicitly by your tracer for trace messages you want. */
|
||||
virtual bool UsingDefaults() const { return true; }
|
||||
|
||||
protected:
|
||||
unsigned int m_level;
|
||||
|
||||
void TraceIf(unsigned int n, std::string const&s)
|
||||
{ if (n) Trace(n, s); }
|
||||
|
||||
/*! Returns nr if, according to the default log settings mechanism (using log levels),
|
||||
the message should be traced. Returns 0 if the default trace level mechanism is not
|
||||
in use, or if it is in use but the event should not be traced. Provided as a utility
|
||||
method for easier and shorter coding of default TraceXxxx(void) implementations. */
|
||||
unsigned int Tracing(unsigned int nr, unsigned int minLevel) const
|
||||
{ return (UsingDefaults() && m_level >= minLevel) ? nr : 0; }
|
||||
};
|
||||
|
||||
// Your Tracer-derived class should inherit as virtual public from Tracer or another
|
||||
// Tracer-derived class, and should pass the log level in its constructor. You can use the
|
||||
// following methods to begin and end your Tracer definition.
|
||||
|
||||
// This constructor macro initializes Tracer directly even if not derived directly from it;
|
||||
// this is intended, virtual base classes are always initialized by the most derived class.
|
||||
#define CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) \
|
||||
public: DERIVED(unsigned int level = 0) : Tracer(level) {}
|
||||
|
||||
#define CRYPTOPP_BEGIN_TRACER_CLASS_1(DERIVED, BASE1) \
|
||||
class DERIVED : virtual public BASE1, public NotCopyable { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
|
||||
|
||||
#define CRYPTOPP_BEGIN_TRACER_CLASS_2(DERIVED, BASE1, BASE2) \
|
||||
class DERIVED : virtual public BASE1, virtual public BASE2, public NotCopyable { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
|
||||
|
||||
#define CRYPTOPP_END_TRACER_CLASS };
|
||||
|
||||
// In your Tracer-derived class, you should define a globally unique event number for each
|
||||
// new event defined. This can be done using the following macros.
|
||||
|
||||
#define CRYPTOPP_BEGIN_TRACER_EVENTS(UNIQUENR) enum { EVENTBASE = UNIQUENR,
|
||||
#define CRYPTOPP_TRACER_EVENT(EVENTNAME) EventNr_##EVENTNAME,
|
||||
#define CRYPTOPP_END_TRACER_EVENTS };
|
||||
|
||||
// In your own Tracer-derived class, you must define two methods per new trace event type:
|
||||
// - unsigned int TraceXxxx() const
|
||||
// Your default implementation of this method should return the event number if according
|
||||
// to the default trace level system the event should be traced, or 0 if it should not.
|
||||
// - void TraceXxxx(string const& s)
|
||||
// This method should call TraceIf(TraceXxxx(), s); to do the tracing.
|
||||
// For your convenience, a macro to define these two types of methods are defined below.
|
||||
// If you use this macro, you should also use the TRACER_EVENTS macros above to associate
|
||||
// event names with numbers.
|
||||
|
||||
#define CRYPTOPP_TRACER_EVENT_METHODS(EVENTNAME, LOGLEVEL) \
|
||||
virtual unsigned int Trace##EVENTNAME() const { return Tracing(EventNr_##EVENTNAME, LOGLEVEL); } \
|
||||
virtual void Trace##EVENTNAME(std::string const& s) { TraceIf(Trace##EVENTNAME(), s); }
|
||||
|
||||
|
||||
/*! A simple unidirectional linked list with m_prev == 0 to indicate the final entry.
|
||||
The aim of this implementation is to provide a very lightweight and practical
|
||||
tracing mechanism with a low performance impact. Functions and methods supporting
|
||||
this call-stack mechanism would take a parameter of the form "CallStack const& callStack",
|
||||
and would pass this parameter to subsequent functions they call using the construct:
|
||||
|
||||
SubFunc(arg1, arg2, CallStack("my func at place such and such", &callStack));
|
||||
|
||||
The advantage of this approach is that it is easy to use and should be very efficient,
|
||||
involving no allocation from the heap, just a linked list of stack objects containing
|
||||
pointers to static ASCIIZ strings (or possibly additional but simple data if derived). */
|
||||
class CallStack
|
||||
{
|
||||
public:
|
||||
CallStack(char const* i, CallStack const* p) : m_info(i), m_prev(p) {}
|
||||
CallStack const* Prev() const { return m_prev; }
|
||||
virtual std::string Format() const;
|
||||
|
||||
protected:
|
||||
char const* m_info;
|
||||
CallStack const* m_prev;
|
||||
};
|
||||
|
||||
/*! An extended CallStack entry type with an additional numeric parameter. */
|
||||
class CallStackWithNr : public CallStack
|
||||
{
|
||||
public:
|
||||
CallStackWithNr(char const* i, word32 n, CallStack const* p) : CallStack(i, p), m_nr(n) {}
|
||||
std::string Format() const;
|
||||
|
||||
protected:
|
||||
word32 m_nr;
|
||||
};
|
||||
|
||||
/*! An extended CallStack entry type with an additional string parameter. */
|
||||
class CallStackWithStr : public CallStack
|
||||
{
|
||||
public:
|
||||
CallStackWithStr(char const* i, char const* z, CallStack const* p) : CallStack(i, p), m_z(z) {}
|
||||
std::string Format() const;
|
||||
|
||||
protected:
|
||||
char const* m_z;
|
||||
};
|
||||
|
||||
// Thanks to Maximilian Zamorsky for help with http://connect.microsoft.com/VisualStudio/feedback/details/1570496/
|
||||
CRYPTOPP_BEGIN_TRACER_CLASS_1(WaitObjectsTracer, Tracer)
|
||||
CRYPTOPP_BEGIN_TRACER_EVENTS(0x48752841)
|
||||
CRYPTOPP_TRACER_EVENT(NoWaitLoop)
|
||||
CRYPTOPP_END_TRACER_EVENTS
|
||||
CRYPTOPP_TRACER_EVENT_METHODS(NoWaitLoop, 1)
|
||||
CRYPTOPP_END_TRACER_CLASS
|
||||
|
||||
struct WaitingThreadData;
|
||||
|
||||
/// container of wait objects
|
||||
class WaitObjectContainer : public NotCopyable
|
||||
{
|
||||
public:
|
||||
/// exception thrown by WaitObjectContainer
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string& s) : Exception(IO_ERROR, s) {}
|
||||
};
|
||||
|
||||
static unsigned int MaxWaitObjects();
|
||||
|
||||
WaitObjectContainer(WaitObjectsTracer* tracer = NULLPTR);
|
||||
|
||||
void Clear();
|
||||
void SetNoWait(CallStack const& callStack);
|
||||
void ScheduleEvent(double milliseconds, CallStack const& callStack);
|
||||
// returns false if timed out
|
||||
bool Wait(unsigned long milliseconds);
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
virtual ~WaitObjectContainer();
|
||||
void AddHandle(HANDLE handle, CallStack const& callStack);
|
||||
#else
|
||||
void AddReadFd(int fd, CallStack const& callStack);
|
||||
void AddWriteFd(int fd, CallStack const& callStack);
|
||||
#endif
|
||||
|
||||
private:
|
||||
WaitObjectsTracer* m_tracer;
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
void CreateThreads(unsigned int count);
|
||||
std::vector<HANDLE> m_handles;
|
||||
std::vector<WaitingThreadData *> m_threads;
|
||||
HANDLE m_startWaiting;
|
||||
HANDLE m_stopWaiting;
|
||||
#else
|
||||
fd_set m_readfds, m_writefds;
|
||||
int m_maxFd;
|
||||
#endif
|
||||
double m_firstEventTime;
|
||||
Timer m_eventTimer;
|
||||
bool m_noWait;
|
||||
|
||||
#ifdef USE_WINDOWS_STYLE_SOCKETS
|
||||
typedef size_t LastResultType;
|
||||
#else
|
||||
typedef int LastResultType;
|
||||
#endif
|
||||
enum { LASTRESULT_NOWAIT = -1, LASTRESULT_SCHEDULED = -2, LASTRESULT_TIMEOUT = -3 };
|
||||
LastResultType m_lastResult;
|
||||
unsigned int m_sameResultCount;
|
||||
Timer m_noWaitTimer;
|
||||
void SetLastResult(LastResultType result);
|
||||
void DetectNoWait(LastResultType result, CallStack const& callStack);
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#if (CRYPTOPP_MSC_VERSION >= 1900)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // NO_OS_DEPENDENCE
|
||||
|
||||
#endif // CRYPTOPP_WAIT_H
|
227
winpipes.cpp
227
winpipes.cpp
@ -1,227 +0,0 @@
|
||||
// winpipes.cpp - originally written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(WINDOWS_PIPES_AVAILABLE)
|
||||
|
||||
#include "winpipes.h"
|
||||
#include "wait.h"
|
||||
|
||||
// Windows 8, Windows Server 2012, and Windows Phone 8.1 need <synchapi.h> and <ioapiset.h>
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
|
||||
# include <synchapi.h>
|
||||
# include <ioapiset.h>
|
||||
# define USE_WINDOWS8_API
|
||||
# endif
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
WindowsHandle::WindowsHandle(HANDLE h, bool own)
|
||||
: m_h(h), m_own(own)
|
||||
{
|
||||
}
|
||||
|
||||
WindowsHandle::~WindowsHandle()
|
||||
{
|
||||
if (m_own)
|
||||
{
|
||||
try
|
||||
{
|
||||
CloseHandle();
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
CRYPTOPP_ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsHandle::HandleValid() const
|
||||
{
|
||||
return m_h && m_h != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
void WindowsHandle::AttachHandle(HANDLE h, bool own)
|
||||
{
|
||||
if (m_own)
|
||||
CloseHandle();
|
||||
|
||||
m_h = h;
|
||||
m_own = own;
|
||||
HandleChanged();
|
||||
}
|
||||
|
||||
HANDLE WindowsHandle::DetachHandle()
|
||||
{
|
||||
HANDLE h = m_h;
|
||||
m_h = INVALID_HANDLE_VALUE;
|
||||
HandleChanged();
|
||||
return h;
|
||||
}
|
||||
|
||||
void WindowsHandle::CloseHandle()
|
||||
{
|
||||
if (m_h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
::CloseHandle(m_h);
|
||||
m_h = INVALID_HANDLE_VALUE;
|
||||
HandleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
void WindowsPipe::HandleError(const char *operation) const
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
throw Err(GetHandle(), operation, err);
|
||||
}
|
||||
|
||||
WindowsPipe::Err::Err(HANDLE s, const std::string& operation, int error)
|
||||
: OS_Error(IO_ERROR, "WindowsPipe: " + operation + " operation failed with error 0x" + IntToString(error, 16), operation, error)
|
||||
, m_h(s)
|
||||
{
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
WindowsPipeReceiver::WindowsPipeReceiver()
|
||||
: m_lastResult(0), m_resultPending(false), m_eofReceived(false)
|
||||
{
|
||||
m_event.AttachHandle(CreateEvent(NULLPTR, true, false, NULLPTR), true);
|
||||
CheckAndHandleError("CreateEvent", m_event.HandleValid());
|
||||
memset(&m_overlapped, 0, sizeof(m_overlapped));
|
||||
m_overlapped.hEvent = m_event;
|
||||
}
|
||||
|
||||
bool WindowsPipeReceiver::Receive(byte* buf, size_t bufLen)
|
||||
{
|
||||
CRYPTOPP_ASSERT(!m_resultPending && !m_eofReceived);
|
||||
|
||||
const HANDLE h = GetHandle();
|
||||
// don't queue too much at once, or we might use up non-paged memory
|
||||
if (ReadFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &m_lastResult, &m_overlapped))
|
||||
{
|
||||
if (m_lastResult == 0)
|
||||
m_eofReceived = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
default:
|
||||
CheckAndHandleError("ReadFile", false);
|
||||
// Fall through for non-fatal
|
||||
case ERROR_BROKEN_PIPE:
|
||||
case ERROR_HANDLE_EOF:
|
||||
m_lastResult = 0;
|
||||
m_eofReceived = true;
|
||||
break;
|
||||
case ERROR_IO_PENDING:
|
||||
m_resultPending = true;
|
||||
}
|
||||
}
|
||||
return !m_resultPending;
|
||||
}
|
||||
|
||||
void WindowsPipeReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (m_resultPending)
|
||||
container.AddHandle(m_event, CallStack("WindowsPipeReceiver::GetWaitObjects() - result pending", &callStack));
|
||||
else if (!m_eofReceived)
|
||||
container.SetNoWait(CallStack("WindowsPipeReceiver::GetWaitObjects() - result ready", &callStack));
|
||||
}
|
||||
|
||||
unsigned int WindowsPipeReceiver::GetReceiveResult()
|
||||
{
|
||||
if (m_resultPending)
|
||||
{
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
BOOL result = GetOverlappedResultEx(GetHandle(), &m_overlapped, &m_lastResult, INFINITE, FALSE);
|
||||
#else
|
||||
BOOL result = GetOverlappedResult(GetHandle(), &m_overlapped, &m_lastResult, FALSE);
|
||||
#endif
|
||||
if (result)
|
||||
{
|
||||
if (m_lastResult == 0)
|
||||
m_eofReceived = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (GetLastError())
|
||||
{
|
||||
default:
|
||||
CheckAndHandleError("GetOverlappedResult", false);
|
||||
// Fall through for non-fatal
|
||||
case ERROR_BROKEN_PIPE:
|
||||
case ERROR_HANDLE_EOF:
|
||||
m_lastResult = 0;
|
||||
m_eofReceived = true;
|
||||
}
|
||||
}
|
||||
m_resultPending = false;
|
||||
}
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
WindowsPipeSender::WindowsPipeSender()
|
||||
: m_lastResult(0), m_resultPending(false)
|
||||
{
|
||||
m_event.AttachHandle(CreateEvent(NULLPTR, true, false, NULLPTR), true);
|
||||
CheckAndHandleError("CreateEvent", m_event.HandleValid());
|
||||
memset(&m_overlapped, 0, sizeof(m_overlapped));
|
||||
m_overlapped.hEvent = m_event;
|
||||
}
|
||||
|
||||
void WindowsPipeSender::Send(const byte* buf, size_t bufLen)
|
||||
{
|
||||
DWORD written = 0;
|
||||
const HANDLE h = GetHandle();
|
||||
// don't queue too much at once, or we might use up non-paged memory
|
||||
if (WriteFile(h, buf, UnsignedMin((DWORD)128*1024, bufLen), &written, &m_overlapped))
|
||||
{
|
||||
m_resultPending = false;
|
||||
m_lastResult = written;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
CheckAndHandleError("WriteFile", false);
|
||||
|
||||
m_resultPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowsPipeSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
|
||||
{
|
||||
if (m_resultPending)
|
||||
container.AddHandle(m_event, CallStack("WindowsPipeSender::GetWaitObjects() - result pending", &callStack));
|
||||
else
|
||||
container.SetNoWait(CallStack("WindowsPipeSender::GetWaitObjects() - result ready", &callStack));
|
||||
}
|
||||
|
||||
unsigned int WindowsPipeSender::GetSendResult()
|
||||
{
|
||||
if (m_resultPending)
|
||||
{
|
||||
const HANDLE h = GetHandle();
|
||||
#if defined(USE_WINDOWS8_API)
|
||||
BOOL result = GetOverlappedResultEx(h, &m_overlapped, &m_lastResult, INFINITE, FALSE);
|
||||
CheckAndHandleError("GetOverlappedResultEx", result);
|
||||
#else
|
||||
BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, FALSE);
|
||||
CheckAndHandleError("GetOverlappedResult", result);
|
||||
#endif
|
||||
m_resultPending = false;
|
||||
}
|
||||
return m_lastResult;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
146
winpipes.h
146
winpipes.h
@ -1,146 +0,0 @@
|
||||
#ifndef CRYPTOPP_WINPIPES_H
|
||||
#define CRYPTOPP_WINPIPES_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(NO_OS_DEPENDENCE) && defined(WINDOWS_PIPES_AVAILABLE)
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "network.h"
|
||||
#include "queue.h"
|
||||
#include <winsock2.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// \brief Windows Handle
|
||||
class WindowsHandle
|
||||
{
|
||||
public:
|
||||
virtual ~WindowsHandle();
|
||||
|
||||
WindowsHandle(HANDLE h = INVALID_HANDLE_VALUE, bool own=false);
|
||||
WindowsHandle(const WindowsHandle &h) : m_h(h.m_h), m_own(false) {}
|
||||
|
||||
bool GetOwnership() const {return m_own;}
|
||||
void SetOwnership(bool own) {m_own = own;}
|
||||
|
||||
operator HANDLE() const {return m_h;}
|
||||
HANDLE GetHandle() const {return m_h;}
|
||||
bool HandleValid() const;
|
||||
void AttachHandle(HANDLE h, bool own=false);
|
||||
HANDLE DetachHandle();
|
||||
void CloseHandle();
|
||||
|
||||
protected:
|
||||
virtual void HandleChanged() {}
|
||||
|
||||
HANDLE m_h;
|
||||
bool m_own;
|
||||
};
|
||||
|
||||
/// \brief Windows Pipe
|
||||
class WindowsPipe
|
||||
{
|
||||
public:
|
||||
class Err : public OS_Error
|
||||
{
|
||||
public:
|
||||
Err(HANDLE h, const std::string& operation, int error);
|
||||
HANDLE GetHandle() const {return m_h;}
|
||||
|
||||
private:
|
||||
HANDLE m_h;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual HANDLE GetHandle() const =0;
|
||||
virtual void HandleError(const char *operation) const;
|
||||
void CheckAndHandleError(const char *operation, BOOL result) const
|
||||
{if (!result) HandleError(operation);}
|
||||
};
|
||||
|
||||
/// \brief Pipe-based implementation of NetworkReceiver
|
||||
class WindowsPipeReceiver : public WindowsPipe, public NetworkReceiver
|
||||
{
|
||||
public:
|
||||
WindowsPipeReceiver();
|
||||
|
||||
bool MustWaitForResult() {return true;}
|
||||
bool Receive(byte* buf, size_t bufLen);
|
||||
unsigned int GetReceiveResult();
|
||||
bool EofReceived() const {return m_eofReceived;}
|
||||
|
||||
HANDLE GetHandle() const {return m_event;}
|
||||
unsigned int GetMaxWaitObjectCount() const {return 1;}
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
private:
|
||||
WindowsHandle m_event;
|
||||
OVERLAPPED m_overlapped;
|
||||
DWORD m_lastResult;
|
||||
bool m_resultPending;
|
||||
bool m_eofReceived;
|
||||
};
|
||||
|
||||
/// \brief Pipe-based implementation of NetworkSender
|
||||
class WindowsPipeSender : public WindowsPipe, public NetworkSender
|
||||
{
|
||||
public:
|
||||
WindowsPipeSender();
|
||||
|
||||
bool MustWaitForResult() {return true;}
|
||||
void Send(const byte* buf, size_t bufLen);
|
||||
unsigned int GetSendResult();
|
||||
bool MustWaitForEof() { return false; }
|
||||
void SendEof() {}
|
||||
|
||||
HANDLE GetHandle() const {return m_event;}
|
||||
unsigned int GetMaxWaitObjectCount() const {return 1;}
|
||||
void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
|
||||
|
||||
private:
|
||||
WindowsHandle m_event;
|
||||
OVERLAPPED m_overlapped;
|
||||
DWORD m_lastResult;
|
||||
bool m_resultPending;
|
||||
};
|
||||
|
||||
/// \brief Windows Pipe Source
|
||||
class WindowsPipeSource : public WindowsHandle, public NetworkSource, public WindowsPipeReceiver
|
||||
{
|
||||
public:
|
||||
WindowsPipeSource(HANDLE h=INVALID_HANDLE_VALUE, bool pumpAll=false, BufferedTransformation *attachment=NULLPTR)
|
||||
: WindowsHandle(h), NetworkSource(attachment)
|
||||
{
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
|
||||
using NetworkSource::GetMaxWaitObjectCount;
|
||||
using NetworkSource::GetWaitObjects;
|
||||
|
||||
private:
|
||||
HANDLE GetHandle() const {return WindowsHandle::GetHandle();}
|
||||
NetworkReceiver & AccessReceiver() {return *this;}
|
||||
};
|
||||
|
||||
/// \brief Windows Pipe Sink
|
||||
class WindowsPipeSink : public WindowsHandle, public NetworkSink, public WindowsPipeSender
|
||||
{
|
||||
public:
|
||||
WindowsPipeSink(HANDLE h=INVALID_HANDLE_VALUE, unsigned int maxBufferSize=0, unsigned int autoFlushBound=16*1024)
|
||||
: WindowsHandle(h), NetworkSink(maxBufferSize, autoFlushBound) {}
|
||||
|
||||
using NetworkSink::GetMaxWaitObjectCount;
|
||||
using NetworkSink::GetWaitObjects;
|
||||
|
||||
private:
|
||||
HANDLE GetHandle() const {return WindowsHandle::GetHandle();}
|
||||
NetworkSender & AccessSender() {return *this;}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // WINDOWS_PIPES_AVAILABLE
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user