Remove Thread and Socket classes (GH #208, PR #703)

Also see https://groups.google.com/forum/#!topic/cryptopp-users/5btwLoxXXD4.
This commit is contained in:
Jeffrey Walton 2018-08-17 23:55:39 -04:00 committed by GitHub
parent 522da15b13
commit f2171cbe2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 15 additions and 3158 deletions

View File

@ -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

View File

@ -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))

View File

@ -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 -->

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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" />

View File

@ -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
View File

@ -40,7 +40,6 @@
#include "rw.h"
#include "sha.h"
#include "skipjack.h"
#include "trdlocal.h"
#ifdef CRYPTOPP_IMPORTS

View File

@ -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
}

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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